View previous topic :: View next topic |
Author |
Message |
RAzorex
Joined: 07 Nov 2011 Posts: 13
|
Ultrasonic distance measuring |
Posted: Mon Nov 07, 2011 2:39 pm |
|
|
Hi everyone
Let me start by saying that I'm a starter at pic programming yet I've made a mistake by choosing to build a robot for my school project (its a long story:))
I am using a 16f877 and 4mhz osc.
Here is my receiver
I connected my transmitter directly to pic (one pin to ground other to a port in pic).
My problem is when I use this code there is no output at pinb7. Therefore receiving end is always high and I can't get a reading in cm on the serial output screen. I know this is not a beginner project to do but any help would be great. Thanks
I tried many codes over weeks but this is the recent one;
(there was a while(true) there in my main function I must have deleted accidently in recent chances to my code).
Code: |
#include <16F877.h>
#device adc=16
#FUSES NOWDT //No Watch Dog Timer
#FUSES XT //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES PUT //Power Up Timer
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#use delay(clock=4000000)
#use rs232(baud=9600 , XMIT = PIN_C6)
#define Echo PIN_B1
long time;
int16 dist;
int16 k;
void transducer(void){
#pragma use fast_io(B)
output_bit(PIN_B7, 1);
delay_us(13);
output_bit(PIN_B7, 0);
delay_us(12);
#pragma use standard_io(B)
}
void main()
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
set_tris_b(0x1f);
while(true){
for(k=0; k<8; k++)
{
transducer();
}
while(!input(Echo))
{}
set_timer1(0); // setting timer zero
while(input(Echo)) // Wait for high state of echo pin
{}
time=get_timer1(); // Getting the time
dist=time/58 ;
printf("%lu cm \n\r", dist);
delay_ms(250);
}
}
|
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Nov 07, 2011 3:04 pm |
|
|
Quote: |
My problem is when I use this code there is no output at pinb7.
void transducer(void){
#pragma use fast_io(B)
output_bit(PIN_B7, 1);
delay_us(13);
output_bit(PIN_B7, 0);
delay_us(12);
#pragma use standard_io(B)
}
void main()
{
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
set_tris_b(0x1f);
while(true){
for(k=0; k<8; k++)
{
transducer();
}
|
My advice is to make a simple program that only toggles Pin B7. Get rid
of the Timer1 setup line. Get rid of the #use fast_io lines and get rid of
the TRIS line. Let the compiler set the TRIS. Don't use output_bit().
Use output_high() and output_low().
Debug the program and the hardware until you can successfully toggle the pin.
Also, if you have an ICD or Pickit or anything programmer or debugger
connected to the board, it will be connected to pins B6 and B7. These
are not the best pins to use for external circuits, for that reason. It's
best to choose some other pins. |
|
![](templates/subSilver/images/spacer.gif) |
RAzorex
Joined: 07 Nov 2011 Posts: 13
|
|
Posted: Mon Nov 07, 2011 3:14 pm |
|
|
I'm using a simple JDM programmer I got from a friend so all my programming is done outside the board (btw I'm currently using a breadboard if thats somehow relevant)
When I first encountered output problems I did test for led blinker and it was running ok. Sorry I forgot to mention that.
I setup Pwm (Ccp1) once to get 40khz square wave(%50 duty cycle) and output was 2.6v ( I don't have an oscilloscope I'm planning on using the one at school )
(sorry if my english is a bit off) |
|
![](templates/subSilver/images/spacer.gif) |
RAzorex
Joined: 07 Nov 2011 Posts: 13
|
|
Posted: Mon Nov 07, 2011 7:09 pm |
|
|
I tried this code and got 2.2v output on multimeter. My first code persistent on not working though. any help would be great, thanks
Code: |
output_high(pin_b2);
delay_us(12)
output_low(pin_b2);
delay_us(12);
|
|
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Nov 07, 2011 9:37 pm |
|
|
Since you don't have an oscilloscope, you should test low speed blinking
of an LED. Example:
Code: |
#include <16F877.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 20M)
//==================================
void main()
{
while(1)
{
output_high(PIN_B0); // Blink LED on pin B0
delay_ms(500);
output_low(PIN_B0);
delay_ms(500);
}
}
|
Try this test on various pins to make sure that they work. |
|
![](templates/subSilver/images/spacer.gif) |
RAzorex
Joined: 07 Nov 2011 Posts: 13
|
|
Posted: Tue Nov 08, 2011 4:03 am |
|
|
PCM programmer wrote: | Since you don't have an oscilloscope, you should test low speed blinking
of an LED. Example:
Code: |
#include <16F877.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 20M)
//==================================
void main()
{
while(1)
{
output_high(PIN_B0); // Blink LED on pin B0
delay_ms(500);
output_low(PIN_B0);
delay_ms(500);
}
}
|
Try this test on various pins to make sure that they work. |
I tested this code it seems to be working as intended.What should try/test next? btw thanks for the help Im stuck at this this one for weeks |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Tue Nov 08, 2011 5:53 am |
|
|
Some comments:
You say the transducer is directly wired to B7. Have you any details of the TX transducer?. While some can be driven off a 5v output like this, many need a lot higher drive voltage. Devices like the Polaroid transducers for example need nearly 70v!.... Also, the transducers behave as resonant devices at their drive frequency, and could quite easily destroy a PIC output pin if connected without some protection. This may well be what has happened to your B7.
So, give some details of your transducer...
Now, also the transducer will have a very specific operating frequency - typically close to 40KHz. The timings of your code, won't be right unless your clock rate in the clock command, matches what your system is actually running at. So start with the test program, and verify that the LED flash interval really is _1 second_. If it is not, then your crystal is not 20MHz. this needs to be got 'right'.
Then, don't fiddle around using #pragma. This is not going to do anything worthwhile in your code. Pragma, is a command to force pre-processing code to be executed first. It does nothing in your code, and just makes the code look messy. Seriously, if you are using fast_io for speed, then select this, and leave it selected. Given the need for speed, use:
Code: |
#use fast_io(b)
#inline
void transducer(void){
output_highPIN_B7); //This is faster than output_bit
delay_us(13);
output_low(PIN_B7);
delay_us(12);
}
|
The compiler will probably make the routine 'inline' anyway, but force it, to be sure.
Then lay things out logically so you (and us), can see what
Code: |
void main(void) {
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
set_tris_b(0x1f);
do {
for (k=0; k<8; k++) {
transducer(); //8 pulses on the transducer
}
while (input(Echo)==0) ; //You seem to be waiting for a low....
time=get_timer1(); // Getting the time
dist=time/58 ;
printf("%lu cm \n\r", dist);
delay_ms(250);
} while(TRUE);
}
|
Now you are waiting after sending the pulse , 'while' the input is high. However according to your comments you want to wait _till_ the pin goes high....
There is though a potential problem. On most ultrasonic rangefinders the 'receive' input _will_ trigger while the pulse is being sent. You actually have to wait for the signal to drop, and then go high _again_. You may need to rethink what you are doing here....
Best Wishes
Last edited by Ttelmah on Tue Nov 08, 2011 7:44 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
RAzorex
Joined: 07 Nov 2011 Posts: 13
|
|
Posted: Tue Nov 08, 2011 6:20 am |
|
|
Sorry I forgot the tranducer specs
here they are :
1.Model:TCT40-16R/T (Diameter 16mm)
2.Nominal frequency:40KHz
3.Emission sound pressure (at 10V):≥117dB
4.Reception sensitivity (at 40KHz):≥-65dB
5.Capacitance:2000PF ±30%
6.Maximum input voltage:60Vp-p
7.Operating temperature:-20℃--+70℃
8.Storage temperature:-40℃--+85℃
I did test the crystal time to time It seemed ok. and the original curcuit
(I got the receiver from) was based on 16f628 using 4mhz. so I assumed 4mhz is way to go to get timing right. also orginal code was in Picbasic I can post it if you want to. about my code part ; my goal was to send 40khz pulse and when receiver detect the echo signal( output should go low when pulse is detected). store that time and calculate the distance by dividing time with 58( 58 part is calculated from speed of sound , wave traveling same distance twice etc.) I did test for many codes over time but this one is from this forum I thought I should give it a try. I hope I explained myself. Thanks |
|
![](templates/subSilver/images/spacer.gif) |
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Tue Nov 08, 2011 7:30 am |
|
|
There are many ways to drive a 40kHz transmitter. Simply connecting it to an IO pin is not one of them.
Taka a look at http://www.ti.com/lit/an/slaa136a/slaa136a.pdf Its an application note from Ti. Its based on their MSP430 processor, which is their equivalent of the PIC. They generate the 40kHz in the processor and use simple circuitry to generate a decent drive voltage for the transducer. It also describes the timing and even gives code, which is useless to us.
This is the sort of thing you need to build.
RF Developer |
|
![](templates/subSilver/images/spacer.gif) |
RAzorex
Joined: 07 Nov 2011 Posts: 13
|
|
Posted: Tue Nov 08, 2011 7:45 am |
|
|
My first curcuit was this ;
[img]
In my code I triggered the 4th in on 555 with
[/code]
output_high(pin_b7);
delay_us(250);
output_low(pin_b7);
[code]
after getting no reading from 555's output pin , first I assumed 555 was broken , and I switched it with another one but that didnt give out reading either so I decided to connect the TX diretly to pic( I've read it somewhere that it was posible , I dont know though.) Then I should re wire this Tx circuit? Im lost ![Smile](images/smiles/icon_smile.gif) |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Tue Nov 08, 2011 8:23 am |
|
|
OK.
With those sensors, you probably can drive the TX from a PIC pin without damage, _but_ the range will be tiny. I'd guess possibly about 1foot max.
Driving from the 555, will be better, especially if you use a higher supply voltage for this chip.
Other choices:
Push-pull drive as suggested in the example from RF_Developer.
Drive from a PIC pin, with a transistor, and an inductor across the TX transducer (and a trap resistor). This way you can get a higher effective drive voltage from a 5v supply, by using the 'flyback' energy in the inductor. Something in the order of 1mH.
If you are running at 4MHz, then hopefully the LED flash example from PCM_Programmer, will actually flash at 5 second from start to start of the light pulse. Does it?.
Don't worry for now about the receive code. Just do a dead basic 40KHz pulse code, sending for rather longer, and see if you get the LED to light on the receive circuit.
It is the old 'get one part working first'.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
RAzorex
Joined: 07 Nov 2011 Posts: 13
|
|
Posted: Tue Nov 08, 2011 8:56 am |
|
|
I tried PCM_Programmer's code for led. It was on for half second and off for half second. considering delay_ms(500) it should be right?. I also tried my
555 circuit again pin3 is always 0v with my code ( the one that uses delay_us(250))
I currently have 330uH inductor would it work?
Thanks |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah
Joined: 11 Mar 2010 Posts: 19359
|
|
Posted: Tue Nov 08, 2011 9:45 am |
|
|
RAzorex wrote: | I tried PCM_Programmer's code for led. It was on for half second and off for half second. considering delay_ms(500) it should be right?. I also tried my
555 circuit again pin3 is always 0v with my code ( the one that uses delay_us(250))
I currently have 330uH inductor would it work?
Thanks |
No.
If you look at PCM_Programmers example, it is setup for a _20MHz_ oscillator. Clock=20M
and HS fuse
If this is running at the right speed, then your circuit _does not_ have a 4MHz oscillator.
Would you actually 'see' the pulse on pin3?.
You talk about using a multimeter, and if the oscillator is actually running 5* faster than you think, then the pulse would only be 50uSec. Most multimeters take perhaps 1/4 second to acquire a reading.....
Yes, but remember if using an inductor in flyback like this, the transistor that is driving it would need something like perhaps a 60V rating. Not a PIC output pin, or even a 555, and you _must_ have a trap resistor to limit just how large the voltage spike is, or you risk everything else in your circuit.
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
RAzorex
Joined: 07 Nov 2011 Posts: 13
|
|
Posted: Tue Nov 08, 2011 10:23 am |
|
|
I will take another look at my setup to confirm my oscillator issue I will post the results. Btw
I tried this circuit once code was in mikroC ,it was very problematic also it was said to be very unstable for robot use so gave up on it. my question is the tx part of this circuit should give about 20v (with a pwm code 40khz %50 duty cyle) would you recommend this?
thanks
edit : I think resistor in image "3k3" should be 33k |
|
![](templates/subSilver/images/spacer.gif) |
RAzorex
Joined: 07 Nov 2011 Posts: 13
|
|
Posted: Tue Nov 08, 2011 11:03 am |
|
|
I forgot to put HS to config earlier so when tested again (#use delay(clock=20M) with 4mhz on circuit led flashed about 4 second from start to start it seems a bit off still |
|
![](templates/subSilver/images/spacer.gif) |
|