View previous topic :: View next topic |
Author |
Message |
jahan
Joined: 04 Apr 2005 Posts: 63
|
Sonar - Ultrasonic Range Finder |
Posted: Tue Jun 28, 2005 9:01 am |
|
|
I have a Sonar from Parallax and would like to use it with PIC16F877A.
the specs on Sonar says:
HOST must send a minimum of 2 uS (typical 5 uS) to device.
HOST waits for 750 uS.
Sonar will send a puls back minimum 115 uS to max 18.5 mS
all pulses are from 0 to 5V.
Code: |
|----| |----------------------| 5v
| | | |
----| |-----------| |--------------- 0v
HOST Response from sonar
|
in Basic Stamp (using BS2) word it would look like this:
Code: |
PIN5 = 0
PULSOUT PIN5, 5 // 5 uS
PULSIN PIN5, 1, Dist // dist is a byte
|
now using dist variable they have a simple math to do the distance calculation.
anybody can help me with CCS C code for the sending a PULS and reading back a PULS?
thankx |
|
|
valemike Guest
|
|
Posted: Tue Jun 28, 2005 12:45 pm |
|
|
To send a signal for 5 microseconds:
Say you're using a 4MHz oscillator.
Thus, 4000000 / 4 = 1000000 hz ==> 1 microsecond per instruction.
A "NOOP" is an instruction that will take 1 microsecond. You will want to disable interrupts for a while to get a precise 5 us pulse:
Code: |
disable_interrupts(GLOBAL);
delay_cycles(5); // delay 5 no-ops to get 5 microseconds
enable_interrupts(GLOBAL);
|
Alternatively, you can use the function "delay_us(5)". Then you don't have to worry what oscillator speed you're using.
Now you have to wait approximately 750 microseconds to get a response. You would use the CCP module for that. However, i don't have any code for that. Maybe someone has some code handy that they can cut and paste in for you. |
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
|
Posted: Tue Jun 28, 2005 1:25 pm |
|
|
Here is a cheap way of measuring the pulse. Note that if you do not get a pulse this code will hang. To prevent this, you would need to provide a timeout in the while() loops.
Code: |
int16 getpulsewidth(void)
{
setup_timer1(T1_DISABLED);
set_timer1(0);
// Wait for the signal to go high
while (!input(PIN_RB5);
setup_timer1(T1_INTERNAL|T1_DIV_BY_1);
// Wait for the signal to go low. We are measuring the signal
while (input(PIN_RB5);
setup_timer1(T1_DISABLED);
return(get_timer1());
}
|
|
|
|
jahan
Joined: 04 Apr 2005 Posts: 63
|
Does this work? |
Posted: Tue Jun 28, 2005 2:12 pm |
|
|
Any comment would be great ...
Code: | #include <16F877A.h>
#device adc=8
#fuses NOWDT,RC, NOPUT, NOPROTECT, NODEBUG, BROWNOUT, LVP, NOCPD, NOWRT
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9,stream=DEBUG)
int Sonar(void) {
output_low (PIN_B1); // set current state
output_high(PIN_B1); // bring high
delay_us(5); // wait 5 uS
output_low (PIN_B1); // bring low
while (!input(PIN_B1)); // wait to go high
set_timer1(0); // Start ticking
while(input(PIN_B1)); // wait until it goes low
return get_timer1(); // read timer
}
void main() {
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
while (TRUE) {
fprintf(DEBUG,"%u",Sonar());
}
}
|
|
|
|
Mark
Joined: 07 Sep 2003 Posts: 2838 Location: Atlanta, GA
|
Re: Does this work? |
Posted: Tue Jun 28, 2005 2:19 pm |
|
|
I would start and stop the timer since it is a 16 bit register being accessed via 8 bits and it is changing. Note that I changed the fuses as well. I doubt that you are using LVP which causes most people problems with hang up. I would recommend using the PUT to make sure things are stablized and you probably aren't using an RC as an osc source. Could be wrong though.
Code: | #include <16F877A.h>
#device adc=8
#fuses NOWDT,XT, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=4000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=9,stream=DEBUG)
int Sonar(void) {
setup_timer_1(T1_DISABLED);
set_timer1(0);
output_low (PIN_B1); // set current state
output_high(PIN_B1); // bring high
delay_us(5); // wait 5 uS
output_low (PIN_B1); // bring low
while (!input(PIN_B1)); // wait to go high
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1); // Start ticking
while(input(PIN_B1)); // wait until it goes low
setup_timer_1(T1_DISABLED);
return get_timer1(); // read timer
}
void main() {
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
while (TRUE) {
fprintf(DEBUG,"%u",Sonar());
}
}
|
|
|
|
valemike Guest
|
Re: Does this work? |
Posted: Tue Jun 28, 2005 2:21 pm |
|
|
If microseconds matter in your accuracy, remember to disable interrupts in Mark's code:
disable_interrupts(GLOBAL);
mypulsewidth = getpulsewidth();
enable_interrupts(GLOBAL);
If you don't do that, then you'll get jittery readings especially if you have other interrupts occurring all the time. |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Tue Jun 28, 2005 3:22 pm |
|
|
Quote: |
#fuses NOWDT,RC, NOPUT, NOPROTECT, NODEBUG, BROWNOUT, LVP, NOCPD, NOWRT
#use delay(clock=4000000)
|
Just some comments regarding the selected #fuses options.
1) If microseconds matter in your accuracy, use a crystal in your oscillator instead of an RC.
2) Are you really using LVP ?
3) NOPUT ?
Keep well,
Humberto |
|
|
jahan
Joined: 04 Apr 2005 Posts: 63
|
|
Posted: Tue Jun 28, 2005 3:46 pm |
|
|
the #FUSES are the default from project wizard.
I have to re-eval all of them.
thank you everyone for your input. I'll test this ASAP and anybody is interested, I'll post the result.
Thankx again. |
|
|
MNiCrO-BiT Guest
|
ultrasonic lcd2x16 |
Posted: Thu Mar 06, 2008 9:05 pm |
|
|
Hello friends basket that can help me, I need to visualize the distance but in a lcd 2x16 but themselves not as to do it...
excuse for my badly English one |
|
|
xjackal
Joined: 29 Oct 2005 Posts: 4
|
|
Posted: Sun Mar 15, 2009 10:09 pm |
|
|
are you sure the below codes work? |
|
|
ratheeshbr
Joined: 26 Jan 2011 Posts: 31
|
Distance measuring using Ultrasonic sensor |
Posted: Mon Mar 07, 2011 10:17 pm |
|
|
I too doing the same project to display the distance on an LCD. I tried with timer1 but not getting pulse width. May be a problem with my code. Can any one please guide me? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
|
|