Arizona Chris
Joined: 20 Dec 2014 Posts: 69 Location: Arizona
|
High accuracy SRF04 Sonar distance chip for remote RS232 |
Posted: Fri Sep 04, 2015 7:47 pm |
|
|
Greetings all,
Been doing a lot of work with remote sensors that take the computational loading off the main processor to keep my ROM space in check. This one uses a PIC16F628 for the sensor chip, and here I am using as an example to send it to a 16F887 chip. I can use this PIC now that I have my wonderful Mach X programmer! ;)
The key here is to account for what happens when a sensors 232 data stops transmitting due to a fault. the getc command will of course wait forever for a 232 input, and your main processor locks up. But by using the function khbit we can prevent this. I set a half second delay in if no 232 input is recieved. I purposly used a non UART input to show that you can have many sensors on one master chip and do it with a software 232. Thanks for looking.
You can see schematics, photos of the setup, and layouts on my web page here:
http://www.schursastrophotography.com/PICprojects/SonarChip090315.html
First the sonar chip code
Code: |
//****************************************************************************
//Chris Schur
//(Sonar Chip 16F628)
//Date: 8/23/15
//****************************************************************************
/*Description of this Program:
This program sends raw serial data at 9600kb out to be reciveved by the main
processor every 100ms. */
//I/O Designations ---------------------------------------------------
// RA0: sonar TRIG Output
// RA1: sonar Pulse Input
// RA2:
// RA3:
// RA4: (Open Collector output)
// RA5: (MCLR)
// RA6: Xtal Output
// RA7: Xtal Input
// RB0: rs232 output to main uC
// RB1: GREEN LED output
// RB2: BLUE LED output
// RB3:
// RB4:
// RB5:
// RB6:
// RB7:
//--------------------------------------------------------------------
//Include Files:
#include <16F628.h> //Normally chip, math, etc. used is here.
//Directives and Defines:
//#device ADC=10 //Set ADC when used to 10 bit = 0 - 1023
#fuses NOPROTECT,HS,NOWDT //xtal is used
#use delay(crystal=10MHz) //xtal speed
#use fast_io(ALL) //must define tris below in main when using this
//for LCD:
//#use rs232(baud=9600, xmit=Pin_B3, bits=8, parity=N,stream=SERIALNH)
//for data out to main processor:
#use rs232(baud=9600, xmit=Pin_B0, bits=8, parity=N,STREAM=SONAR)
//****************************************************************************
//Global Variables:
int16 sonarmeas = 0; //distance in inches from internal horns
float sonardist = 0;
int highbyte,lowbyte; //high byte and low byte for serial data
//****************************************************************************
//Functions/Subroutines, Prototypes:
int16 sonar1 (int16 sonarpulse, int16 sonartime, int16 d); //get sonar dist.
//****************************************************************************
//-- Main Program
//****************************************************************************
void main(void) {
// Set TRIS I/O directions, define analog inputs, compartors:
set_tris_A(0b01111110);
set_tris_B(0b11110000);
//(analog inputs digital by default)
//Initialize variables and Outputs: --------------------------------------
output_low(Pin_B0); //status off
output_low(Pin_B1);
output_low(Pin_B2);
output_low(Pin_B3);
//Setup for timers, PWM, and other peripherals:
//----------------------------------------------------------------
//MAIN LOOP:
while (true) {
//get sonar current dist:
sonarmeas = sonar1(0,0,0); //call up sonar1 function, variables start at 0
//sonardist = (float) sonarmeas / 155; //convert to inches-change typedef
//Next send the raw measurement data out serially:
//Convert to two 8 bit integers to send:
lowbyte = MAKE8(sonarmeas,0);
highbyte = MAKE8(sonarmeas,1);
delay_ms(100); //space between trig pulses
//trig pip for oscilloscope to see data clearly
output_high(Pin_B2);
delay_us(10);
output_low(Pin_B2);
//send data serially:
fputc(lowbyte,SONAR);
//delay_ms(5);
fputc(highbyte,SONAR);
//delay_ms(10);
}
}
//********* Functions which have prototypes at top of program ****************
int16 sonar1 (int16 sonarpulse, int16 sonartime, int16 d) {
setup_timer_1( T1_INTERNAL | T1_DIV_BY_2 );//must be inside function!!!!!
//max 52.6ms = 65000 x .8uS res per count
output_high(Pin_A0); //send trig pulse
delay_us(10);
output_low(Pin_A0);
delay_us(200); //this delay is added to end 70uS before the rising edge of echo
//start isr to time out if no echo:
SET_TIMER1(0); //reset to zero on timer counter.
//clear_interrupt (INT_TIMER1); //you must do this or it will have int allready.
//enable_interrupts (INT_TIMER1); //turn on TIMER1 interrupt
//now look for L to H transition:
while (input(Pin_A1) == 0); //wait for 0 to 1
//reset timer:
SET_TIMER1(0); //reset to zero on timer counter.
//now look for H to L transition:
while (input(Pin_A1) == 1); //wait for 1 to 0
//turn off isr:
//disable_interrupts (INT_TIMER1); //turn off TIMER1 interrupt
sonarpulse = get_timer1();
sonartime = sonarpulse * .8; //actual uS pulse width
if (sonartime > 18000) //max range is 18ms = 116" = 9.7 feet.
sonartime = 18000; //set to max if beyond range.
//d = sonartime / 155; //18000/155= 116;
return sonartime;
}
|
Next here is the reciver code on an 887 chip
Code: |
//****************************************************************************
//Chris Schur
//(sonar recieve 16F887)
//Date: 8/28/15
//****************************************************************************
/*Description of this Program:
This short program recieves the 9600 kb serial data from the sonar chip and converts
it to a distance in inches with two decimal places, then sends it to the serial LCD.*/
//I/O Designations ---------------------------------------------------
// RA0: (AN0) Sonar serial data input
// RA1: (AN1)
// RA2: (AN2)
// RA3: (AN3)
// RA4: (Open Collector output)
// RA5: (AN4)
// RA6: OSC OUT
// RA7: OSC IN
// RB0: (AN12,EXT INT) Status LED output
// RB1: (AN10) LCD output
// RB2: (AN8)
// RB3: (AN9)
// RB4: (AN11)
// RB5: (AN13)
// RB6:
// RB7:
// RC0:
// RC1:
// RC2:
// RC3: (SCLK)
// RC4: (SDA)
// RC5:
// RC6:
// RC7:
// RD0:
// RD1:
// RD2:
// RD3:
// RD4:
// RD5:
// RD6:
// RD7:
// RE0: (AN5)
// RE1: (AN6)
// RE2: (AN7)
// RE3: (MCLR INPUT - Pull High)
//--------------------------------------------------------------------
//Include Files:
#include <16F887.h> //Normally chip, math, etc. used is here.
//Directives and Defines:
#device ADC=10 //Set ADC when used to 10 bit = 0 - 1023
#fuses NOPROTECT,HS,NOWDT //xtal is used
#use delay(crystal=10MHz) //xtal speed
#use fast_io(ALL) //must define tris below in main when using this
//for LCD:
#use rs232(baud=9600, xmit=Pin_B1, bits=8, parity=N,stream=SERIALNH)
//For reciving sonar data on pin A0:
#use rs232(baud=9600, rcv=Pin_A0, bits=8, parity=N, DISABLE_INTS,stream=SONAR)
//Note: the "disable_ints is critical, turns off constant barrage of interrupts
//during the aquisition of data in the get command so timing is not affected.
//NO_ANALOGS is default in device file...(All I/Os are digital)
//***Global Variables:********************************************************
int16 sonarmeas = 0; //distance in inches from internal horns
float sonardist = 0;
int highbyte,lowbyte; //high byte and low byte for serial data
int1 sonarbit; //incoming data verification bit
int16 sonartimeout; //counts of kbit delay increrments
//***Functions/Subroutines, Prototypes:***************************************
//Clears LCD Display:
void LCDCLR() {
fputc(0xFE,SERIALNH); //Command Prefix
fputc(0x51,SERIALNH); //Clear screen
}
//Sets LCD to line 2 start point
void LCDLN2() {
fputc(0xFE,SERIALNH); //Command Prefix
fputc(0x45,SERIALNH); //set cursor command
fputc(0x40,SERIALNH); //Set cursor to next line, pos 40 = start line 2
}
void GETSONAR(void);
//****************************************************************************
//***-- Main Program*********************************************************
void main(void) {
// Set TRIS I/O directions, define analog inputs, compartors:
set_tris_A(0b10111111);
set_tris_B(0b11111100);
set_tris_C(0b11111111);
set_tris_D(0b11111111);
set_tris_E(0b1111);
//Initialize variables and Outputs: --------------------------------------
//Setup for timers, PWM, and other peripherals:
//----------------------------------------------------------------
//Main Program
while (true) {
GETSONAR(); //go get sonar data serially
LCDCLR(); //clear screen
delay_ms(10);
fprintf(SERIALNH,"%f"sonardist); //NOTE: %Lu in command is int16 only output
delay_ms(250);
output_high(Pin_B0);
delay_ms(25);
output_low(Pin_B0);
delay_ms(25);
} //while
} //main
//********* Functions which have prototypes at top of program ****************
void GETSONAR(void) {
//test loop to see if data has come in lasting maximum of 1/2 second:
sonartimeout = 0; //reset timeout
while (!kbhit(SONAR) && (++sonartimeout < 50000)) //half second wait IF NO SIGNAL
delay_us(10);
if (kbhit(SONAR)) { //We have a signal
lowbyte = fgetc(SONAR);
highbyte = fgetc(SONAR);
sonarmeas = MAKE16(highbyte,lowbyte); //RAW
sonardist = (float) sonarmeas / 155; //inches with 2 decimals
}
}
|
|
|