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
 
      }
 
}   
 
 
 | 	 
  | 
			 
		  |