View previous topic :: View next topic |
Author |
Message |
DavdQrs
Joined: 25 Apr 2008 Posts: 5
|
IR Tx/Rx problems. |
Posted: Fri Apr 25, 2008 10:17 pm |
|
|
Hello.
I have been trying to make a simple object detection circuit. As an object gets closer (within a predetermined distance) the LED turns on and when the object moves away the LED turns off. Simple. The IR reviever passes through a 2.2uF cap to an AI1 input of the PIC.
The problem is as the object gets gradually closer the LED starts to flicker and progressively flickers faster until it finally stays on. The same thing happens as the object moves away where the LEDs flickers less until completely off. I have implemented a HUGE amount of hysteresis around 4 volts to avoid flickering but obviously that does not work. I have tried this using another compiler with no problems what so ever with very similar PWM specs but would like to use CCS because of it features as the project will be expanded.
My code is as follows:
Code: | int val;
void main(){
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1, 25, 1); // 38Khz output (4Meg clock)
set_pwm1_duty(24); // around 96% duty
setup_adc_ports(sAN1|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(1);
setup_comparator( NC_NC_NC_NC );
setup_vref(FALSE);
while(1){
val=read_adc();
if(val<20)
output_high(PIN_A0);
if(val>245)
output_low(PIN_A0);
}
} |
Please help. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Apr 25, 2008 10:22 pm |
|
|
Your program is not complete, the #fuses, device include and #delay are missing.
Which processor are you using?
What is the version number of your compiler? |
|
|
DavdQrs
Joined: 25 Apr 2008 Posts: 5
|
|
Posted: Fri Apr 25, 2008 10:26 pm |
|
|
Sorry:
Code: | #include <12F683.h>
#device adc=10
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOCPD //No EE protection
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOPUT //No Power Up Timer
#FUSES BROWNOUT //Reset when brownout detected
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#use delay(clock=4000000)
|
compiler 4.057
Thanks. |
|
|
RLScott
Joined: 10 Jul 2007 Posts: 465
|
Re: IR Tx/Rx problems. |
Posted: Sat Apr 26, 2008 5:17 am |
|
|
DavdQrs wrote: | ...The problem is as the object gets gradually closer the LED starts to flicker and progressively flickers faster until it finally stays on. The same thing happens as the object moves away where the LEDs flickers less until completely off. I have implemented a HUGE amount of hysteresis around 4 volts to avoid flickering but obviously that does not work.... |
Your problem may not have anything to do with software. Have you looked at the analog signal from the IR sensor on a scope to see if it has variations bigger than the hysteresis?
Robert Scott
Real-Time Specialties |
|
|
DavdQrs
Joined: 25 Apr 2008 Posts: 5
|
|
Posted: Sat Apr 26, 2008 6:46 am |
|
|
The variations of the sensor are from 0-5V and look fairly linear as an object gets closer, even with the flicker.
I had no problem with this on mikroc compiler. |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
Re: IR Tx/Rx problems. |
Posted: Sat Apr 26, 2008 8:00 am |
|
|
Code: | setup_adc(ADC_CLOCK_INTERNAL); |
From the PIC12F683 datasheet Table9-1: Quote: | 4: When the device frequency is greater than 1 MHz, the FRC clock source is only recommended if the conversion will be performed during Sleep. | You are not meeting these criteria, so change to ADC_CLOCK_DIV_16 instead.
You are reading the A/D converter very soon again after the last conversion. This might create problems depending on your hardware connected to the A/D input. During conversion the internal hold capacitor is disconnected from the input and it will need little time to adjust to the external voltage before the next conversion is started. Make sure the impedance as seen by this input is smaller than 10k Ohm.
Just for testing you could add a small delay between conversions.
Code: | set_pwm1_duty(24); // around 96% duty
| 24/(25+1) gives around 92% duty cycle.
Last edited by ckielstra on Sat Apr 26, 2008 8:05 am; edited 1 time in total |
|
|
Guest
|
|
Posted: Sat Apr 26, 2008 8:03 am |
|
|
What sensor are you using? Is this simply a IR LED and IR receive module or is it one of the sharp IR distance sensors (or similar) ? |
|
|
DavdQrs
Joined: 25 Apr 2008 Posts: 5
|
|
Posted: Sat Apr 26, 2008 8:37 am |
|
|
Ok, i tried:
setup_adc(ADC_CLOCK_DIV_16);
and various delays between cycles but still no luck.
Im using a PNA4602 ir reciever module from solarbotics.
I have tried tried quite a few variotions but still not getting the desired result. Is there a simpler way i could implement the code? |
|
|
Gerhard L Guest
|
|
Posted: Sat Apr 26, 2008 10:34 am |
|
|
Check your ADC is setup to read values between 0 and 1024. A selection of <25 and 245 is a small change in actual value that the IR sends into the analog port. Change that adc = 10 to 8 or remove that statement completely and try that. Also just insert a small delay in your program as to just give your adc achange to charge the cap of internal adc measurement. delay_us(20) should be enough |
|
|
Gerhard
Joined: 30 Aug 2007 Posts: 144 Location: South Africa
|
|
Posted: Sat Apr 26, 2008 10:40 am |
|
|
Code: | #include <12F683.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC_IO //Internal RC Osc, no CLKOUT
#FUSES NOCPD //No EE protection
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOPUT //No Power Up Timer
#FUSES BROWNOUT //Reset when brownout detected
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES FCMEN //Fail-safe clock monitor enabled
#use delay(clock=4000000)
int val;
void main(){
setup_ccp1(CCP_PWM);
setup_timer_2(T2_DIV_BY_1, 25, 1); // 38Khz output (4Meg clock)
set_pwm1_duty(24); // around 96% duty
setup_adc_ports(sAN1|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(1);
setup_comparator( NC_NC_NC_NC );
setup_vref(FALSE);
while(1){
delay_us(20);
val=read_adc();
if(val<20)
output_high(PIN_A0);
if(val>245)
output_low(PIN_A0);
}
} |
Didnt log in before.
Just try it like this |
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Sat Apr 26, 2008 10:53 am |
|
|
Stupid of me, because the code is split over two posts I overlooked the 'adc=10'. Most likely this is his problem as he is reading the adc-value into an int8, loosing the two most significant bits. For voltages up to 1.25V the program works as expected, above that you get strange behaviour.
I'm always surprised to see how other people spot different bugs. I like code reviews. |
|
|
DavdQrs
Joined: 25 Apr 2008 Posts: 5
|
|
Posted: Sat Apr 26, 2008 7:37 pm |
|
|
Thanks guys its working your right the adc=10 was suppose to adc=8 unless val is to be set as long int for adc=10.
Thanks again. |
|
|
|