CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to

SRF04 Ultrasonic Ranger - A digital tape measure function

Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
Arizona Chris

Joined: 20 Dec 2014
Posts: 69
Location: Arizona

View user's profile Send private message Visit poster's website

SRF04 Ultrasonic Ranger - A digital tape measure function
PostPosted: Sun Feb 01, 2015 5:08 pm     Reply with quote

There are many ways to read a pulse width in C, Here is one of the easiest to work with. I developed this for use in robotics where you have as many as a dozen sonars all going into one microcontroller, such as the 16F877a chip I am using here. Being able to use any pin is a must for the design. This uses a Scott Edwards 2x16 LCD for display, but you can use what you want of course! And any sonar sold today that puts out a pulse width can use this method. Of course there have been comments on other sonar programs posted here that they can get stuck in a loop forever if the sonar malfunctions or becomes disconnected. Not here - I used a timer overflow interrupt to keep tabs on this so it will jump out of the timing loops if the sonar fails and send you a message. Now we dont want our robots to seize up with ten simultaneous sonars pinging all around when one of them fails do we?

Here is the code. Modify to suit!
//Chris Schur
//(Sonar tests 16F877A)
//Date:  1/31/15

/*Description of this Program:

This version - sends out 10us trig pulse. using timer1 meaures the
return echo in counts.  Converts to uS, then inches. This version limits
the maximum to 116 inches which is the device maximum (18mS pulse).

Also Ive added a timer 1 interrupt so it wont get stuck in a
while loop looking for an edge or pulse and lock up the robot.

Anytime you disconnect either the echo out wire, or trig
input wire the isr kicks in and the message that it failed appears. if you
Reconnect and all is fine.This is in a separate
function format which can be called by the robot per sonar.   */

//I/O Designations ---------------------------------------------------

// RB0:  Status LED output
// RB1:  LCD output
// RB2:  Piezzo Speaker
// RB3:  Sonar Trigger pulse output
// RB4:  Sonar Echo pulse input
// RB5: 
// RB6: 
// RB7: 


//Include Files:
#include <16F877A.h>  //Normally chip, math, etc.  used is here.

//Directives and Defines:

#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 Scott Edwards LCD:
#use rs232(baud=9600, xmit=Pin_B1, bits=8, parity=N, INVERT, stream=SERIAL)
#int_timer1    //internal IF on rollover
   void timer1_isr(void)  {   //interrupt service routine called timer1_isr
      fputc(12,SERIAL);       //clear screen
      fputs("Sonar Fail",SERIAL);  //display if no sonar echo pulses in 210ms
      delay_ms(1000);              //Display time
                 //at the end of this routine, the IF is reset.

//Global Variables:
int16  sonardist = 0;     //distance in inches from internal sonar horns 
//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:

   //Initialize variables and Outputs:  --------------------------------------
   output_low(Pin_B0);  //status LED off
   output_low(Pin_B3);  //sonar trig low
   enable_interrupts (GLOBAL);   //Turn on ALL interrupts in the whole program


while (true)   {

sonardist = sonar1(0,0,0);  //call up sonar1 function, variables start at 0

delay_ms(250);     //space between trig pulses

fputc(12,SERIAL);   //clear screen
fprintf(SERIAL,"%Lu"sonardist);  //NOTE: %Lu in command is int16 only output
fputs(" inches",SERIAL);   //Puts "inches" after the reading on the display


//********* Functions which have prototypes at top of program ****************
int16 sonar1 (int16 sonarpulse, int16 sonartime, int16 d)  {

setup_timer_1( T1_INTERNAL | T1_DIV_BY_8 );//must be inside function!!!!!

output_high(Pin_B3);   //send trig pulse

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_B4) == 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_B4) == 1);  //wait for 1 to 0

//turn off isr:
disable_interrupts (INT_TIMER1);  //turn off TIMER1 interrupt

sonarpulse = get_timer1();
sonartime = sonarpulse * 3.2;

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 d;



When testing dont forget to disconnect either the trigger or echo out lines from the processor to test the interrupts!
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Page 1 of 1

Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

Powered by phpBB © 2001, 2005 phpBB Group