Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

how to write a mikroc code for ultrasonic sensor

Status
Not open for further replies.

Nipuna56

Advanced Member level 4
Joined
Jul 11, 2012
Messages
119
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,296
Activity points
1,993
i'm new guy for electronic field i have very ittle knowledge about this side so i want to know how to write a code for ultrasonic sensor using Mikroc plz help me friends
 

can u please explain this code

Code:
void interrupt();
void main() {
OPTION_REG.INTEDG=0;
INTCON.GIE=1;
INTCON.INTE=1;
TRISA=0x00;
PORTA=0x00;
while(1){
}
}
void interrupt(){
 if(INTCON.INTF==1){
 PORTA=0xFF;
 Delay_ms(1000);
 PORTA=0x00;
 INTCON.INTF=0;
 }   }
 

is this code correct
i want to display distance in lcd display

Code:
char txt[6];
#define TRIG PORTB.F6
#define ECHO PORTB.F7


// LCD module connections
sbit LCD_RS at RA1_bit;
sbit LCD_EN at RA3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;

sbit LCD_RS_Direction at TRISA1_bit;
sbit LCD_EN_Direction at TRISA3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections
        double distance;
void main() {
  INTCON = 0x00;                        //turn off interrupts
  ADRESH = 0x00;
  ADRESL = 0x00;
  ADCON1 = 0x06;                        //all inputs are digital
  ADCON0 = 0x00;
    ADCON1 = 0x06;                        //all inputs are digital
  ADCON0 = 0x00;
  ANSEL  = 0;                        // Configure AN pins as digital I/O
  ANSELH = 0;
  C1ON_bit = 0;                      // Disable comparators
  C2ON_bit = 0;
  TRISD  = 0x00;                        //PORTD is output


  PORTD = 0x00;

  TRISA = 0x00;
  PORTA = 0x00;
  porta.f2=0;
  

  Lcd_Init();                           //Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);                  // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);             // Cursor off



     PORTA.F2=0;






TRISB.F6 = 0;
TRISB.F7 = 1;


OPTION_REG.T0CS = 0;
OPTION_REG.PSA = 0;
OPTION_REG.PS0 = 1;
OPTION_REG.PS1 = 1;
OPTION_REG.PS2 = 1;

  while(1){

  TRIG = 0;
  delay_us(10);
  TRIG = 1;
  delay_us(10);
  TRIG = 0;

 while(ECHO==0);
 TMR0=0;

  while(ECHO==1);
  distance = (double)TMR0 * 4.352;
    wordtostr(distance,txt);
  lcd_out(1,6,txt) ;
  Delay_ms(500);
    Lcd_Cmd(_LCD_CLEAR);                  // Clear display
  

  }






}
 
Last edited:

this is that file
 

Attachments

  • ultra.rar
    13.7 KB · Views: 197

OPTION_REG.INTEDG = 0; means

By default, the INT input will generate an interrupt on the Rising edge of the signal.

The INT input can also be configured to interrupt on the Falling edge by changing the INTEDG bit.

INTEDG: Interrupt Edge Select bit
1 = Interrupt on rising edge of INT pin
0 = Interrupt on falling edge of INT pin

INTCON.GIE = 1; means Interrupt Control Register's Global Interrupt Enable bit is set.

INTCON.INTE = 1; means interrupt is enabled on pin RB0

INTE: RB0/INT Interrupt Enable bit
1 = Enables the RB0/INT interrupt
0 = Disables the RB0/INT interrupt

TRISA = 0x00; means PORTA is configured as output port.

PORTA = 0x00; means A 0 value is written to PORTA or PORTA is cleared.

if(INTCON.INTF==1) means if interrupt flag bit is set do something

INTF: RB0/INT Interrupt Flag bit
1 = The RB0/INT interrupt occurred
0 = The RB0/INT interrupt did not occur

PORTA = 0xFF; means PORTA is made high
Delay_ms(1000); means A 1000ms or 1 sec delay is performed

PORTA = 0x00; means PORTA is made low or PORTA is cleared.

INTCON.INTF = 0; means Interrupt control register's Interrupt Flag is cleared.


You have not connected a button to pin RB0 to cause the interrupt.
 

can u send me the correct code and protues .dsn file.
 

check this schematic. Is it what you want to do. The sensor I think converts distance measured into volts. I think if that is given to adc and calibrated gives the distance. I have to code. Do you want ultrasonic based or infrared based distance measuring? What are you using the sensor for? Robotic application or Automobile?
 

Attachments

  • ultrasound.rar
    12.3 KB · Views: 187
Last edited:

i don't know what is infrared based distance measuring but i want a code to measure the distance by using ultrasonic sensor (hc sr04)
 

How does it work? the hc sr04?

IR sensor is used for measuring distances. In proteus you have sensor for IR based distance measurement but not for ultrasound sensor.

check this **broken link removed**

can you change this code to mikroC Code

Code:
#include <16F877.h> 
#device adc=8 
#FUSES NOWDT, HS, NOPUT, PROTECT, NOBROWNOUT, NOLVP, NOCPD, NOWRT, NODEBUG 
#use delay(clock=20000000) 

/  Used sonar - HC-SR04  & DYP ME007 
/  If you are using DYP ME 007 or any other 5 pin sonar, Please note that not to take the 
/  pin named 'out'. Take echo instead. 
/  Pin configuration (5 pin)- VCC(+5) TRIG(Trigger pin) ECHO(Output pin) OUT(Not needed) GND (Ground) 
/  Pin configuration (4 pin)- VCC(+5) TRIG(Trigger pin) ECHO(Output pin) GND (Ground) 




#define LCD_TYPE 2 
#include <lcd.c> 

int16 distance, time;          // Defining variables 


// Defining the pins 

#define trig pin_B1     // Change as you wish, can use any pin in the MCU 
#define echo pin_B0     // Change as you wish, can use any pin in the MCU 

void main() 
{ 
   lcd_init();                               // initiating the LCD 

printf(LCD_PUTC, "\f Sonar test \n Code by Bhanu ");// for LCD & MCU restart troubleshooting 

delay_ms(1000);                              // Boot-up delay, for troubleshooting 

setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);     // initiating timer 



while(true) 
{ 

output_high(trig);                         // ping the sonar 
delay_us(20);                            // sending 20us pulse 
output_low(trig); 

while(!input(ECHO))                       // wait for high state of echo pin 
{} 

set_timer1(0);                           // setting timer zero 

while(input(ECHO))                       // Wait for high state of echo pin 
{} 

time=get_timer1();                       // Getting the time 

distance=time*0.028 + 1.093 ;            // Calculating the distance 
                            
                            
printf(LCD_PUTC, "\fTime :%Lu \nDistance = %Lu",time,distance); // Putting the time and 
                                     //distance to the LCD 
delay_ms(1000); 


} 
}
 
Last edited:

no i want only code i can test it in real world
can my code do that measure?
 

can you check this code. It is mikroC code. You have to try it for your pic.

Code:
//////////////////////////////////////////////////////////////////////
//
// File: 16F88_Ultrasonic_ranger.c
//
// 
// Description:
//
//   Range finding by generation and reception of
//   ultrasonic audio at 40kHz.
//
// Compiler : mikroC, mikroElektronika C compiler
//            for Microchip PIC microcontrollers
//            Version: 5.0.0.3
//
// Note Testing:
//
//   Tested on 16F88
//
// Requirements:
//
//   40kHz Ultrasonic amplifier (transistor amp).
//
//   40kHz ultrasonic transducer - for different transducers
//   e.g. for a 32kHz transducer change the software appropriately.
//
//   Target : 16F88
//
// Notes :
//
//  For the CCP module (16F88):
//  Which pin is used is controlled by bit 12 of the configuration
//  word (either RB0 or RB3).  Use the compiler settings to set the
//  configuration word i.e. you can not set this from within the
//  source code
//
//  This software uses RB0 as input to the CCP module.
//
// RB0 : ultrasonic in  (via amplifier, peak hold, level detect).
// RB3 : ultrasonic out (40kHz pulses)

//////////////////////////////////////////////////////////////////////
#include "bit.h"

//////////////////////////////////////////////////////////////////////
// macros

//////////////////////////////////////////////////////////////////////
// globals for interrupt.
//
unsigned int T1_O  = 0; // timer1 overflow updated in interrupt routine.
unsigned short gCapInt = 0; // captured something in interrupt routine.
unsigned short gfCapOn = 1; // control capture only capture 1st value.

unsigned int t_capL = 0; // timer 1 low.
unsigned int t_capH = 0; // timer 1 high.
unsigned int t_capO = 0; // timer 1 overflow.

unsigned int gCapVal = 0; // captured this.

//////////////////////////////////////////////////////////////////////
void init(void) {

   OSCCON  = 0x60; // b6..4 = 110 = 4MHz

   // set CCP to capture mode every rising edge.
   CCP1CON = 0x05;

   ANSEL = 0;     // all ADC pins to digital I/O

   // Timer 1 on
   T1CON = (1<<TMR1ON);
}

//////////////////////////////////////////////////////////////////////
void init_ports(void) {

   PORTA = 0;
   TRISA = 0;     // 0=o/p  - sets analogue pins to digital output.

   PORTB = 0;
   TRISB = 0x01;  // 0=o/p  Receive on RB0.
}

//////////////////////////////////////////////////////////////////////
void enable_interrupts(void) {

   // Timer 1
   PIR1 &= ~(1<<TMR1IF); // Zero T1 overflow register value.

   // Capture
   PIR1 &= ~(1<<CCP1IF); // Zero Capture flag

   // Interrupt enable.
   PIE1 =  (1<<CCP1IE);

   // Global interrupt enable.
   INTCON = (1<<GIE) | (1<<PEIE); // enable global & peripheral
}

//////////////////////////////////////////////////////////////////////
void disable_interrupts(void) {
   INTCON &= ~(1<<GIE); // disable global & peripheral
}

//////////////////////////////////////////////////////////////////////
// RA% can only be input on 16F88
// ret table is for straight through
// PORT 0 1 2 3 4 5 6 7 to a b c d e f g dp
// So map to new outputs:
// 0 a, 1 b, 2 c, 3 d, 4 e, 6 f, 7 g - loosing dp
// i.e. keep 1st 5 and move bits 5,6 to 6,7

int2seg(unsigned short digit) {
unsigned short r;
unsigned short ret[10] = { 0x3F, 0x06, 0x5B, 0x4F, 0x66,
                           0x6D, 0x7D, 0x07, 0x7F, 0x6F };

   if (digit<0 || digit>9) {
      r = 0x7f;
   } else {
      r =(  ret[digit] & 0x1f ) | \
         ( (ret[digit] & 0x60)<< 1);
   }

   return r;
}
//////////////////////////////////////////////////////////////////////
void seg_display_int(unsigned int val) {
char op[7];

    IntToStr(val,op);
    // 6 digits op by above.
    // e.g. for num 1234
    // pos               5 4 3 2 1 0
    // num               x x 1 2 3 4 \0
    // index from left ! 0 1 2 3 4 5

    // Display the lower 4 digits.
    PORTA=int2seg(op[2]-'0');
    setBit(PORTB,5);
    delay_ms(4);
    resBit(PORTB,5);

    PORTA=int2seg(op[3]-'0');
    setBit(PORTB,2);
    delay_ms(4);
    resBit(PORTB,2);

    PORTA=int2seg(op[4]-'0');
    setBit(PORTB,6);
    delay_ms(4);
    resBit(PORTB,6);

    PORTA=int2seg(op[5]-'0');
    setBit(PORTB,7);
    delay_ms(4);
    resBit(PORTB,7);

PORTB &= ~0xe4; // turn off all resBit should do this
PORTB=0;

    PORTA=0x00;
}

//////////////////////////////////////////////////////////////////////
// generate 4 pulses of ultrasonic @ 32kHz  (8 periods of 32kHz).
// Use the simulator to set correct period.
// single ended drive
void gen_ultra(void) {

   setBit(PORTB,3);
   delay_us(12);
   resBit(PORTB,3);
   delay_us(11);

   setBit(PORTB,3);
   delay_us(12);
   resBit(PORTB,3);
   delay_us(11);

   setBit(PORTB,3);
   delay_us(12);
   resBit(PORTB,3);
   delay_us(11);

   setBit(PORTB,3);
   delay_us(12);
   resBit(PORTB,3);
   delay_us(11);
}

//////////////////////////////////////////////////////////////////////
void main() {
unsigned int i,val,s1,s2,tH,tL,tO;
char op[12];
unsigned long calc=0;

   init_ports();
   init();

   gCapInt=0; // Reset capture indicator.

   while(1) {

      gfCapOn = 1; // allow one capture value

      tO = T1_O; // Get the current timer value.
      tH = TMR1H;
      tL = TMR1L;

      t_capL = 0; t_capH = 0; t_capO = 0;  // initialise capture

      gen_ultra();

      enable_interrupts();
      seg_display_int(val);
      disable_interrupts(); // had 20 ish ms of time so stop

      if (! gCapInt) { // no echo from soft output ? try loud

         enable_interrupts();
         seg_display_int(val);
         seg_display_int(val);
         disable_interrupts(); // had 20 ish ms of time so stop
      }

      // Did we get any echo from soft or loud ?
      if (gCapInt) { // captured anything ?
         gCapInt=0;  // reset for next time

         // 4MHz clock so timer 1 returns us
         // gCapVal * 1,000,000 = seconds.
         // speed of sound in air at 20degC = 340m/s
         // (gCapVal*1000000*340)/(2*100) = distance in cm

         s1=(t_capH-tH);
         s2=(t_capL-tL);

         calc = ((s1)<<8)+s2;
         calc *= 34;
         calc /= 2000; // output in cm
         val = (int)calc;
      }
   } // while(1)
}

////////////////////////////////////////////////////////////////////////
void interrupt(void) {

   // Free run Timer 1 get the overflow to extend counter here.
   if (PIR1 & (1<<TMR1IF) ) { // T1 overflowed ?
      PIR1 &= ~(1<<TMR1IF);   // clear timer1 overflow bit.
      T1_O++;
   }

   // Capture
   if (PIR1 & (1<<CCP1IF)) {
      PIR1 &= ~(1<<CCP1IF); // Zero Capture flag.

      if (gfCapOn) { // allow only 1 capture

         gfCapOn = 0;

         t_capL = CCPR1L;
         t_capH = CCPR1H;
         t_capO = T1_O;

         gCapInt = 1; // signal that a capture occured.
      }
   }

   // Interrupts are only enabled at a specific point from program.
   // They are not re-enabled here

   // Note GIE set by RETFIE instruction
}

Can you check this also. This is also mikroC Code.

Code:
/********************
 * MACRO DEFINITIONS
 ********************/
/*
 * ultra sonic pulse length in microseconds
 */
#define PULSELEN        300

/*
 * circular buffer size for samples averaging
 */
#define BUFSIZE 10

/*
 * LCD PORT
 * EasyPic2, EasyPic3 : PORTB
 * EaspyPic4 : PORTD
 */
#define LCDPORT PORTD
#define LCDTRIS TRISD

/*******************
 * GLOBAL VARIABLES
 *******************/
unsigned char   outOfRange ;            // out of range flag : set when no echo is detected

unsigned int    buf[BUFSIZE] ;          // samples buffer
unsigned char   idx = 0 ;               // index of current sample in buffer

/*****************************************
 * INTERRUPT SERVICE ROUTINE
 * This ISR handles TIMER1 overflow only
 *****************************************/
void    interrupt(void)
        {
        if(PIR1.TMR1IF)                                       // timer1 overflow ?
                {
                outOfRange = 1 ;                              // set out of range flag
                PIR1.TMR1IF = 0 ;                             // clear interrupt flag
                }
        }

/************
 * MAIN LOOP
 ************/
void    main()
        {
        ADCON1 = 0 ;            // enables ADC
        
        TRISA = 0xff ;          // PORTA as inputs
        PORTA = 0 ;

        TRISC = 0 ;             // PORTC as outputs
        PORTC = 0 ;

        // TIMER1 settings
        T1CON = 0b00001100 ;    // prescaler 1:1, osc. enabled, not sync, internal clk, stopped
        
#ifdef   LCDPORT
        // init LCD
        Lcd_Init(&LCDPORT) ;            // use EP2/3/4 settings
        Lcd_Cmd(Lcd_CLEAR) ;            // clear display
        Lcd_Cmd(Lcd_CURSOR_OFF) ;       // cursor off

        Lcd_Out(1, 1, "UltraSonicRanger") ;
        Lcd_Out(2, 5, "cm") ;
#endif

        // init PWM Channel : 40 Khz, 50% duty cycle
        PWM1_Init(40000) ;
        PWM1_Change_Duty(128) ;
        
        INTCON.GIE = 1 ;                // enable global interrupts
        INTCON.PEIE = 1 ;               // enable peripheral interrupts
        PIE1.TMR1IE = 0 ;               // disable timer 1 interrupt
        PIR1.TMR1IF = 0 ;               // clear timer 1 interrupt flag

        // forever
        for(;;)
                {
                unsigned char   i ;             // general purpose byte
                unsigned long   cm ;            // distance in centimeters
                unsigned char   str[4] ;        // string for range display

                // prepare timer
                T1CON.TMR1ON = 0 ;              // stop timer
                outOfRange = 0 ;                // reset out of range flag
                TMR1H = 0 ;                     // clear timer1
                TMR1L = 0 ;

                T1CON.TMR1ON = 1 ;              // start timer 1
                PIE1.TMR1IE = 1 ;               // enable timer 1 interrupts on overflow

                // send pulse
                PWM1_Start() ;                  // enable PWM output : transducer is pulsed at ultrasonic frequency
                Delay_us(PULSELEN) ;            // during PULSELEN microseconds
                PWM1_Stop() ;                   // stop PWM

                Delay_us(PULSELEN * 2) ;        // do nothing for twice the pulse length duration to prevent false start

                while(Adc_Read(1) < 1)         // while no pulse detected (no signal on ADC channel 1)
                        {
                        if(outOfRange) break ;  // to late, out of range
                        }

                T1CON.TMR1ON = 0 ;              // stop timer 1
                PIE1.TMR1IE = 0 ;               // disable timer 1 interrupts on overflow

#ifdef LCDPORT
                if(outOfRange)                          // is overrange condtion detected ?
                        {
                        Lcd_Out(2, 8, "OverRange") ;    // display overrange message
                        }
                else if(TMR1H < ((PULSELEN * 6 * Clock_kHz()) / (1000 * 4 * 256)))      // is underrange condition detected ?
                        {
                        Lcd_Out(2, 8, "UnderRnge") ;    // display underrange message
                        }
                else                                    // good reading
                        {
                        buf[idx] = TMR1H ;              // build a 16 bit value from timer1
                        buf[idx] <<= 8 ;                // MSB
                        buf[idx] += TMR1L ;             // LSB

                        // circular buffer
                        idx++ ;                         // next location
                        if(idx == BUFSIZE)              // the end is reached ?
                                {
                                idx = 0 ;               // back to start
                                }

                        cm = 0 ;                        // prepare centimeter averaging
                        for(i = 0 ; i < BUFSIZE ; i++)  // for all samples in buffer
                                {
                                cm += buf[i] ;  // add to sum
                                }
                        cm /= BUFSIZE ;             // average samples

                        /*
                         * cm contains now the number of clock cycles
                         * from the start of the ultrasonic transmission
                         * to the first echo detection
                         * the duration in second is s = cm / (Clock_Khz() * 1000 / 4)
                         * if we admit that sound speed in the air is 340 m/s
                         * the distance in centimeters (forth and back) is d = s * 340 * 100 / 2
                         * or d = 340 * 100 / 2 * cm / Clock_khz() / 1000 * 4
                         * d = 34 * 2 / Clock_Khz()
                         */
                        cm *= 34 * 2 ;                  // now converts to centimeters
                        cm /= Clock_Khz() ;

                        ByteToStr(cm, str) ;            // convert to string
                        Lcd_Out(2, 1, str) ;            // print string
                        Lcd_Out(2, 8, "         ") ;    // clear error message
                        }
#endif

                Delay_ms(10) ;                          // 10 milliseconds delay before next sample
                }
        }
 
Last edited:

how can change this line
Code:
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);     // initiating timer
 

Check the other code I posted. It is also mikroC Code. It is easier to read.

- - - Updated - - -

setup_timer_1(T1_INTERNAL|T1_DIV_BY_8); means value of T1_INTERNAL or T1 divided by 8 is passed to the setup_timer_1() function. T1_INTERNAL and T!_DIV_BY_8 must be defined somewhere.

Check this also

Code:
#include<pic.h> 
#define trig RB0 
#define echo RB1 
#define sound_speed 33000 
  
void  init_ports(void); 
unsigned int  read_distance(void); 
void  compare_react(unsigned int); 

void init_ports(void) 
{ 
 TRISB = 0xfe;       // RB0 (trig) is output (Burst) 
 PORTB = 0xfe;       // and starts low 
 T1CON = 0x00;  
 CCP1CON = 0x00; 
 TMR1H  = 0x00;   
 TMR1L  = 0x00; 
 CCPR1H  = 0x00; 
 CCPR1L  = 0x00; 
 PEIE = 1; 
 T0IE = 1; 
 TMR1IE = 1; 
 CCP1IE = 1; 
} 
unsigned int read_distance(void) 
{ 
 int i; 
 for(i=0;i<=10;i++)        //**THIS GENERATES 10 PULSE  BURST AT 40 khz**// 
 { 
  TMR1H  = 0xff;       // prepare timer for 12.5 uS pulse 
  TMR1L  = -1f; 
  T1CON  = 0x11;       // 1:2 prescale and running 
  TMR1IF = 0;  
  trig   = 1;        // start trigger pulse 
  while(!TMR1IF);       // wait for 12.5 us 
  trig= 0 ;       
  TMR1ON = 0;        // stop timer 
  TMR1H  = 0xff;       // prepare timer for 12.5 uS pulse 
  TMR1L  = -1f; 
  T1CON  = 0x11;       // 1:2 prescale and running 
  TMR1IF = 0;  
  trig   = 0;        // start trigger pulse 
  while(!TMR1IF);       // wait for 12.5 us 
  trig= 1 ;       
  TMR1ON = 0;        // stop timer 
 } 
        
 TMR1H = 0x00;        // prepare timer to measure flight time of echo 
 TMR1L = 0x00; 
 T1CON = 0x11;        // 1:2 prescale and  running 
 TMR1IF=0; 
 while(!TMR1IF);        // detect rising edge 
 TMR1ON = 0;         // stop timer 
 return (TMR1H<<8)+TMR1L;     // TMR1H:TMR1L contains flight time of the pulse in 0.4 uS units 
   
} 
void compare_react(unsigned int time ) 
{  
 int dist_cm = time * sound_speed /2000000; // gets the distance in CM unit 
  
 if(dist_cm >= 0 && dist_cm <= 375) 
 { 
  // Action 
 } 
 else if(dist_cm >375 && dist_cm <= 750) 
 { 
  //Action 
 } 
 else if(dist_cm >750 && dist_cm <= 1125) 
 { 
  //Action 
 } 
 else if(dist_cm >1125 && dist_cm <= 1500) 
 { 
  //Action 
 } 
 else 
 { 
  //something wrong??? 
 }  
}  
void main() 
{ 
 unsigned int flight_time; 
 init_ports(); 
 while(1) 
 { 
  flight_time = read_distance();     // Trigger Transmiiter, Reads the echo, Calculates and returns the distance  
  compare_react(flight_time);     // Displays Messages, Buzzes the beeper 
  TMR1H = 0x00;        // delay between two trigers  
  TMR1L = 0x00;         
  T1CON = 0x21;        // 1:4 prescale and running 
  TMR1IF = 0; 
  while(!TMR1IF);        // wait for delay time 
  TMR1ON = 0;         // stop timer  
   
 } 
}


Distance is calculated as: L = C × T/2 , where L is the length, C is the speed of sound in air, T is the time difference from the transmission from the transmitter to the receiver. This is divided by 2 for the two-directions the sound travels. Speed of sound is about: C = 344m / s (20 degrees C room temperature).
 
Last edited:

this is a very simple module indeed.
this code might not be perfect, but for testing, it kinda OK :-?
Code:
char txt[6];
unsigned int timex;
#define TRIG PORTB.F6
#define ECHO PORTB.F7


// LCD module connections
sbit LCD_RS at RA1_bit;
sbit LCD_EN at RA3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;

sbit LCD_RS_Direction at TRISA1_bit;
sbit LCD_EN_Direction at TRISA3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections
        double distance;
void main() {
  INTCON = 0x00;                        //turn off interrupts
  ADRESH = 0x00;
  ADRESL = 0x00;
  ADCON1 = 0x06;                        //all inputs are digital
  ADCON0 = 0x00;
  ADCON1 = 0x06;                        //all inputs are digital
  ADCON0 = 0x00;
  ANSEL  = 0;                        // Configure AN pins as digital I/O
  ANSELH = 0;
  C1ON_bit = 0;                      // Disable comparators
  C2ON_bit = 0;
  TRISD  = 0x00;                        //PORTD is output
  PORTD = 0x00;
  TRISA = 0x00;
  PORTA = 0x00;
  porta.f2=0;
  Lcd_Init();                           //Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);                  // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);             // Cursor off
  PORTA.F2=0;
TRISB.F6 = 0;
TRISB.F7 = 1;
OPTION_REG.T0CS = 0;
OPTION_REG.PSA = 0;
OPTION_REG.PS0 = 1;
OPTION_REG.PS1 = 1;
OPTION_REG.PS2 = 1;


  while(1)
  {
  TRIG = 0;
  delay_us(10);
  TRIG = 1;
  delay_us(10);
  TRIG = 0;

 while(ECHO==0);
{
     timex = timex +1;
     Delay_us(1);
}

 timex  = timex/116;
  Inttostr(timex,txt);
  lcd_out(1,1,txt) ;
  lcd_out(1,7,"cm") ;
  Delay_ms(100);



  }
}
 
Check this. This is written for PIC18F4410 and serial LCD. Change it to PIC16F887. Remove the serial lcd code.

Code:
#include <p18cxxx.h>
#include "stdio.h"
#include "stdlib.h"


// Configuration Bit Values
/** CONFIGURATION **************************************************/
        #pragma config OSC      = INTIO67
        #pragma config FCMEN    = OFF
        #pragma config IESO     = OFF
        #pragma config PWRT     = ON
        #pragma config BOREN    = OFF
        #pragma config WDT      = OFF
        #pragma config WDTPS    = 32768
        #pragma config MCLRE    = OFF
        #pragma config LPT1OSC  = OFF
        #pragma config PBADEN   = OFF
        #pragma config STVREN   = ON
        #pragma config LVP      = OFF
        #pragma config XINST    = OFF       			// Extended Instruction Set
        #pragma config CP0      = OFF
        #pragma config CP1      = OFF
        #pragma config CPB      = OFF
        #pragma config WRT0     = OFF
        #pragma config WRT1     = OFF
        #pragma config WRTB     = OFF       			// Boot Block Write Protection
        #pragma config WRTC     = OFF
        #pragma config EBTR0    = OFF
        #pragma config EBTR1    = OFF
        #pragma config EBTRB    = OFF

#define TRIG			LATDbits.LATD3			// used to trigger the srf04
#define ECHO			PORTDbits.RD2			// Used to read the echo pulse back from  SRF04

// Prototypes
void setup(void);
void setup_lcd(void);
void print_buff(void);
void set_cursor(unsigned char pos);
void SetTimer(unsigned int time);
void Wait4Timer(void);
void send_pulse(void);
void measure_pulse(void);

unsigned char s[21]; 						// used to print data to the LCD03

void main(void)
{
unsigned int range;

	setup();
	setup_lcd();							// Clear LCD03 screen and hide cursor
	set_cursor(1);
	sprintf(s, "SRF04 Example");
	print_buff();

	while(1)
	{
		SetTimer(6500);						// Start a 50mS timer running with timer 0
		send_pulse();						// Send a 10uS pulse to trigger the SRF04			
		while(!ECHO);						// Wait for echo line to go high
		measure_pulse();					// Measure the length of the incoming pulse using timer 1
		range = (TMR1H << 8) + TMR1L;		// Get timer 1 values high byte and low byte into range
		range /= 58;						// Range is a reading in uS dividing this by 58 will give us the range
		sprintf(s, "Range: %i  ", range);
		set_cursor(21);
		print_buff();
		Wait4Timer();						// Wait for the 50mS timer to finish before triggering the SRF04 again
	}
}

/*****************
* SRF04 routines *
*****************/

void send_pulse(void)
{
	TMR1H = 255;					// Set the clock to only need 2 counts to roll over				
	TMR1L = 253;					// This will give us 10uS before it rolls over

	TRIG = 1; 						// Pin high to trigger ping from SRF04;
	PIR1bits.TMR1IF = 0;			// Clear timer 1 interupt flag
	T1CONbits.TMR1ON = 1;			// Start timer 1 running for 10us
	while(PIR1bits.TMR1IF == 0);	// Wait for interupt to be set
	T1CONbits.TMR1ON = 0;
	TRIG = 0; 						// Pin output for SRF04 low
	TMR1H = 0;						// Clear timer
	TMR1L = 0;					
}

void measure_pulse(void)
{
	T1CONbits.TMR1ON = 1;			// Start timer 1 counting
	while(ECHO);					// Wait for echo line to go low
	T1CONbits.TMR1ON = 0;
}

/*****************
* Timer Routines *
*****************/
void SetTimer(unsigned int time)
{
	TMR0H = 0-(time/256);
	TMR0L = 0-(time&0xff);
	INTCONbits.TMR0IF = 0;
}

void Wait4Timer(void)
{
	while(INTCONbits.TMR0IF==0);
}

/*************
* Chip setup *
*************/

void setup(void)
{	
	OSCCON = 0x70;				// set 8MHz

	TRISDbits.TRISD2 = 1;		// pin Input for SRF04 
	TRISDbits.TRISD3 = 0;		// pin output for SRF04 
	LATDbits.LATD3 = 0;			

	T0CON = 0x83;				// 16bit, 64:1 prescaler
	T1CON = 0x10;				// Timer 1 16bit: 2:1 prescaler

	ADCON1 = 0x0f;				// all ports to digital
	TRISC = 0x1F;
	SSPSTAT = 0x80;				// slew diabled
	SSPCON1 = 0x38;				// master mode enabled
	SSPADD = 0x11;				// 100khz
}

/**********************
* Functions for LCD03 *
**********************/

void setup_lcd(void)
{
	SSPCON2bits.SEN = 1;	// innitiate a start bit
	while(SSPCON2bits.SEN);	// Wait for start bit to end
	PIR1bits.SSPIF = 0;		// Clear the i2c interupt flag
	SSPBUF = 0xC6;			// Address of LCD03
	while(!PIR1bits.SSPIF);	// Wait for interupt flag to be set indicating and of a transmission
	PIR1bits.SSPIF = 0;		
	SSPBUF = 0x00;			// Command register of LCD03
	while(!PIR1bits.SSPIF);		
	PIR1bits.SSPIF = 0;		
	SSPBUF = 0x04;			// command to hide cursor
	while(!PIR1bits.SSPIF);	
	PIR1bits.SSPIF = 0;		
	SSPBUF = 0x0C;			// command to clear screen
	while(!PIR1bits.SSPIF);	
	SSPCON2bits.PEN = 1;	// Send stop bit
	while(SSPCON2bits.PEN);	// Wait for stop bit to finish
}

void print_buff(void)
{
unsigned char index = 0;
	SSPCON2bits.SEN = 1;				// innitiate a start bit
	while(SSPCON2bits.SEN);				// Wait for start bit to end
	PIR1bits.SSPIF = 0;					// Clear the i2c interupt flag
	SSPBUF = 0xC6;						// Address of LCD03
	while(!PIR1bits.SSPIF);				// Wait for interupt flag to be set indicating and of a transmission
	PIR1bits.SSPIF = 0;		
	SSPBUF = 0x00;						// Command register of LCD03
	while(!PIR1bits.SSPIF);	
	while(s[index])						// Send ascii string to LCD03 untill a null reached
	{
		PIR1bits.SSPIF = 0;		
		SSPBUF = s[index++];			// Command register of LCD03
		while(!PIR1bits.SSPIF);	
	}
	SSPCON2bits.PEN = 1;				// Send stop bit
	while(SSPCON2bits.PEN);
}	

void set_cursor(unsigned char pos)
{
	SSPCON2bits.SEN = 1;	// innitiate a start bit
	while(SSPCON2bits.SEN);	// Wait for start bit to end
	PIR1bits.SSPIF = 0;		// Clear the i2c interupt flag
	SSPBUF = 0xC6;			// Address of LCD03
	while(!PIR1bits.SSPIF);	// Wait for interupt flag to be set indicating and of a transmission
	PIR1bits.SSPIF = 0;		
	SSPBUF = 0x00;			// Command register of LCD03
	while(!PIR1bits.SSPIF);	// Wait for interupt flag to be set indicating and of a transmission
	PIR1bits.SSPIF = 0;		
	SSPBUF = 0x02;			// Command to set cursor possition
	while(!PIR1bits.SSPIF);	// Wait for interupt flag to be set indicating and of a transmission
	PIR1bits.SSPIF = 0;		
	SSPBUF = pos;			// where to set cursor to
	while(!PIR1bits.SSPIF);

	SSPCON2bits.PEN = 1;	// Send stop bit
	while(SSPCON2bits.PEN);	// Wait for stop bit to finish
}
 

Code:
char txt[6];
#define TRIG PORTB.F6
#define ECHO PORTB.F7


// LCD module connections
sbit LCD_RS at RA1_bit;
sbit LCD_EN at RA3_bit;
sbit LCD_D4 at RD4_bit;
sbit LCD_D5 at RD5_bit;
sbit LCD_D6 at RD6_bit;
sbit LCD_D7 at RD7_bit;

sbit LCD_RS_Direction at TRISA1_bit;
sbit LCD_EN_Direction at TRISA3_bit;
sbit LCD_D4_Direction at TRISD4_bit;
sbit LCD_D5_Direction at TRISD5_bit;
sbit LCD_D6_Direction at TRISD6_bit;
sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections
        double distance;
void main() {
  INTCON = 0x00;                        //turn off interrupts
  ADRESH = 0x00;
  ADRESL = 0x00;
  ADCON1 = 0x06;                        //all inputs are digital
  ADCON0 = 0x00;
    ADCON1 = 0x06;                        //all inputs are digital
  ADCON0 = 0x00;
  ANSEL  = 0;                        // Configure AN pins as digital I/O
  ANSELH = 0;
  C1ON_bit = 0;                      // Disable comparators
  C2ON_bit = 0;
  TRISD  = 0x00;                        //PORTD is output


  PORTD = 0x00;

  TRISA = 0x00;
  PORTA = 0x00;
  porta.f2=0;
  

  Lcd_Init();                           //Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);                  // Clear display
  Lcd_Cmd(_LCD_CURSOR_OFF);             // Cursor off



     PORTA.F2=0;






TRISB.F6 = 0;
TRISB.F7 = 1;


OPTION_REG.T0CS = 0;
OPTION_REG.PSA = 0;
OPTION_REG.PS0 = 1;
OPTION_REG.PS1 = 1;
OPTION_REG.PS2 = 1;

  while(1){

  TRIG = 0;
  delay_us(10);
  TRIG = 1;
  delay_us(10);
  TRIG = 0;

 while(ECHO==0);
 TMR0=0;

  while(ECHO==1);
  distance = (double)TMR0 * 4.352;
    wordtostr(distance,txt);
  lcd_out(1,6,txt) ;
  Delay_ms(500);
    Lcd_Cmd(_LCD_CLEAR);                  // Clear display
  

  }






}

what is this TMR0 ?
what is the use of it?
i read the manual but i hard to understand it
 

its an 8 bit timer / counter module of pic. when it is configured as a timer, it will count for 0 to 255 and then set a falg. TMR0 can be used in your project 'cse of it has got better resolution than other methods.
 
this is not a my code
i think according to this code it measure the time between send signal(trig) and received signal(echo)
is that correct?
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top