Hello,
I have a technical question about PULSIN, any advice would be welcome.
I'm using a routine to get an IR signal.
The hardware is:
On the sending side: a PIC16F684 where RA5 is used as PWM output at 40KHz with a 30% duty cycle (code below). The pin is connected to a BC182L NPN general purpose transistor with the adequate resistor for the transistor. A TSAL6100 940 nm IR led is powered by 5V (from a 5V voltage regulator) with the appropriate current limiter resistor to have 1.6V at 100 mA.
On the receiving side: a PIC16F684. One input pin is connected to the DATA lead of a TSOP4840 infrared receiver-demodulator at 40KHz carrier.
When a signal is received it triggers an int on the receiver and the signal is decoded.
I'm using PULSIN to check the bits of 14 bits that are sent MSB to LSB
There is a header that is 2400 Us pulse (so it *pulls down* the pin which is default high with internal WPU!).
I use a loop to bypass the header that the pulsin wouldn't read anyway as it is already started when I get to the int handler.
A '1' bit is 1200 Us pulse and a '0' bot is a 600 Us pulse. Each bit is prefixed with a 600 Us pause.
When I read the PULSIN values stores in an array of 14 words I should normaly, for a 8 MHz internal oscillator (a 5Us resolution) have:
For a '0' bit I should have a lenght of 600/5 (=120) and for a '1' bit I should have a length of 1200/5 (=240).
I notice that the values for a '1' range from 221 to 266 while values for a '0' range from 109 to 153. Why is that so??????
Why?
Why??
Why???
I can imagine I may not have exacly either 120 or 240 values but such variation is very difficult to understand. It needs to be more accurate. How can I improve this?
Is this related to PULSIN or is it my hardware? Is this related to the duty cycle?
Snippet for settings for the PWM:
Code:'******************************************************************************* 'PWM (single output mode) related registers for porta.5 T2CON = %00000100 'value:4, 1:1 postscale (unused), Timer2 is ON, Timer 2 Clock prescaler = 1 PR2 = %00110001 'value: 49, PWM Period: 40.0KHz CCP1CON = %00000000 'capture/compare/PWM module OFF, no pwm signal on portc.5 at this time CCPR1L = %00001111 'value: 15, PWM Duty Cycle 8 MSB of 10 bits (2 LSB in bits 5 and 4 of CCP1CON), total: 60d '******************************************************************************* OSCCON = %01110001 CMCON0 = %00000111 'comparators OFF, val = 7 ANSEL = %00000000 'choose digital i/o, val = 0 OPTION_REG = %01111111 'enable porta weak pullups (no weak pull-up available for porta.3), p12
The routine that gets the signal and decodes it:
Code:area = 255 IF (PORTA.0 == 0) THEN FOR i = 0 to 15 'get a sequence of incoming 16 bits (WITHOUT their prefixes which are 600us pause) PULSIN PORTA.0,0,ir_pulse[i] ' Read 16 low-going pulses on RA.4, see pbp manual NEXT i area = 0 ' Loop 16 times, record in 5us resolution pulse duration in the word variables array GOTO decode ENDIF IF (PORTA.1 == 0) THEN FOR i = 0 to 15 'get a sequence of incoming 16 bits (WITHOUT their prefixes which are 600us pause) PULSIN PORTA.1,0,ir_pulse[i] ' Read 16 low-going pulses on RA.4, see pbp manual NEXT i area = 1 ' Loop 16 times, record in 5us resolution pulse duration in the word variables array GOTO decode ENDIF IF (PORTA.2 == 0) THEN FOR i = 0 to 15 'get a sequence of incoming 16 bits (WITHOUT their prefixes which are 600us pause) PULSIN PORTA.2,0,ir_pulse[i] ' Read 16 low-going pulses on RA.4, see pbp manual NEXT i area = 2 ' Loop 16 times, record in 5us resolution pulse duration in the word variables array GOTO decode ENDIF IF (PORTA.3 == 0) THEN FOR i = 0 to 15 'get a sequence of incoming 16 bits (WITHOUT their prefixes which are 600us pause) PULSIN PORTA.3,0,ir_pulse[i] ' Read 16 low-going pulses on RA.4, see pbp manual NEXT i area = 3 ' Loop 16 times, record in 5us resolution pulse duration in the word variables array GOTO decode ENDIF IF (PORTA.4 == 0) THEN FOR i = 0 to 15 'get a sequence of incoming 16 bits (WITHOUT their prefixes which are 600us pause) PULSIN PORTA.4,0,ir_pulse[i] ' Read 16 low-going pulses on RA.4, see pbp manual NEXT i area = 4 ' Loop 16 times, record in 5us resolution pulse duration in the word variables array GOTO decode ENDIF IF (PORTA.5 == 1) THEN area = 5 GOTO bypass ENDIF '--- ELSE --- GOTO bypass 'invalid, area = 255 '------------ decode: 'databyte = $FF ' Start with all 1's and find each 0 'Ranges for LOW bit: 109 to 153 'Ranges for HIGH BIT: 221 to 266 'header length: 118 to 122 'we scan the words array we stored from MSB to LSB databyte = 0 '%0000000000000000 FOR i = 0 TO 13 ' Get 14 "data" bits LCDOUT $fe,1,#i,":",#ir_pulse[i] PAUSE 2000 IF ((ir_pulse[i] < 275) && (ir_pulse[i] > 210)) THEN '240*5us resolution at 8MHz = 1200 us (usual length of a zero is about 127 - 145 and 242 to 266 fore a one) databyte.0(15-i) = 1 'clear the bit goto slip 'bypass ENDIF IF ((ir_pulse[i] < 160) && (ir_pulse[i] > 105)) THEN '240*5us resolution at 8MHz = 1200 us (usual length of a zero is about 127 - 145 and 242 to 266 fore a one) databyte.0(15-i) = 0 'clear the bit GOTO slip 'bypass ENDIF LCDOUT $fe,1,#i,"!",#ir_pulse[i] PAUSE 2000 GOTO bypass 'if any other value, abort slip: NEXT i 'we fill "databyte" from MSB to LSB
The code that sends the IR signal:
Code:'HEADER: 'LCDOUT $fe,1,"header" 'PAUSE 2000 'HIGH PORTC.5 CCP1CON = 12 PAUSEus 2400 'HIGH pulse, 2400 uS on RC5, PWM CCP1CON = 0 'LOW PORTC.5 'DATA: 'LCDOUT $fe,1,"1stByte" 'PAUSE 2000 'first byte, %00000000 (MT2 compatible) firstbyte = %00000000 For i = 0 to 7 'send only 6 MSb pauseus 600 'bit prefix CCP1CON = 12 PAUSEus 600 'min 600 us pause CCP1CON = 0 NEXT i 'second byte, example: %00|1110|-- (56) is for 75% dammages 'LCDOUT $fe,1,"2ndByte" 'PAUSE 2000 For i = 0 to 5 'send only 6 MSb pauseus 600 'bit prefix CCP1CON = 12 IF (dammages.0(7-i) == 1) THEN PAUSEus 1200 ELSE PAUSEUS 600 ENDIF CCP1CON = 0 NEXT i




Bookmarks