PDA

View Full Version : Funny PULSIN values: what is going on???



xnihilo
- 27th April 2008, 21:10
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:






'************************************************* ******************************
'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:




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:






'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

xnihilo
- 28th April 2008, 11:37
Can someone please help me?

b1arrk5
- 29th April 2008, 01:20
I don't know if this will help or not, but Bruce put together a nice little program here;
http://www.picbasic.co.uk/forum/showthread.php?p=23401
I'm not familiar with the PIC you're using, but if you have a CCP module I would give Bruce's program a shot, it looks like it should be very accurate.
Hope this helps.
Jerry.

xnihilo
- 29th April 2008, 07:29
"I need to time an incoming pulse that can be anywhere from 35 to 1000 mS long"...

My pulses are 600 or 1200 us long... There is a problem with PULSIN or with the hardware, I can't understanf why I have such fluctuation...

Darrel Taylor
- 29th April 2008, 08:40
I think there's several sources of the variances.
But a large portion is probably because TMR2 is left running when you turn off the CCP module.

When you put it back in PWM mode again, TMR2 is at an unknown value, and if it's over 49 (PR2) then it could take up to 100us for it to roll-over to 0 again.

When you turn off the PWM, you should Stop TMR2 and reset it to 0.

added: Or maybe just zeroing TMR2 before starting the PWM will work.
<br>

xnihilo
- 30th April 2008, 08:02
I will give it a try.
Thanks.