PDA

View Full Version : IR Counter



partime
- 24th May 2009, 07:28
I want to use infrared communication to increase/decrease the score on a scoreboard. So, if I press one button on a remote, then the score will increase by one. And, if another button is pressed, then the score gets decreased by one. The score is output to a dual 7-segment LED display. This is what I have done so far.

First, I setup a PIC627 to increase the count by one everytime I pressed a button which was hardwired to the PIC. Next, I removed the button and added a PIC628a to act as the button. I bought the Infrared Communications kit from Rentron.com (http://www.rentron.com/remote_control/infrared-serial.htm) and used the PNA4602M detector to be the input to the PIC628a. I programmed it so the output would go high when an infrared signal was detected. This worked. I could use any remote I had and the count would increase everytime I pressed any button. Lastly, I assembled the transmitting part of the kit I got from Rentron. I used a simple SEROUT command to be transmitted. And again, the count would increase when the signal was detected. So, I think I sort of have the up count figured out. I am new to most of this and I took small steps to get where I am now. I started with the simple counter and just added to it.

Here is some of the programming I have used:

PIC627 - gets input from portb.7 and increase cnt by 1 when button is pressed

BUTTON Pbutton, 1, 255,0, i, 0, LOOP 'pbutton = portb.7
pause 100
Cnt = Cnt + 1
GOTO LOOP

The count would increase very rapidly when the remote button was press just montentarly, so I added the pause. This helped slow things down. I'm not sure if this best command to use to increase the count or not. It was okay when I just used this chip hardwired to a button. But, now since I want the increase to be triggered by an IR signal, I'm not sure it is the best choice to use.


PIC628a - gets input from the PNA4602M detector and outputs to the 627 as a button

loop:
IF PORTB.0 = 0 Then
high PORTB.1
else
low PORTB.1
endif
goto loop

So, if an infrared signal is detected, then a high signal is output to portb.7 on the PIC627.


PIC84 - used to produce the data to be transmitted

TRISB = 0
ADDRESS VAR BYTE
DAT VAR BYTE
ID VAR BYTE
ADDRESS = 10
ID = 25

BEGIN:
FOR DAT = 0 TO 255
SEROUT PORTB.0,4,[ID,ADDRESS,DAT]
PAUSE 100
NEXT
GOTO BEGIN

This is just the code I got off the Rentron website, just to test that things were working. The output is NANDed with 38 kHz carrier frequency. Having this setup, the diplay will count up very fast because of the constant signal that is being generated.


My next task is to add a way to decrease the count. This is were I think I am going to need some guidance. Ideally, I would like to be able use an old TV remote and just use one button on the remote to increase the count and another to decrease it. Otherwise, I believe that I will need to add pushbuttons which produce different SEROUT data. Or something like that.

I can probably reduce the number of PICs that I am using. I just used each PIC to accomplish a given task and simplify things.

Hopefully this isn't too much information, but I wanted to give a good idea of what I have setup. Do I look like I am going in the right direction with things? Any input would be appreciated. Thanks.

dhouston
- 24th May 2009, 11:20
You need to take this step-by-step.

The first step is to choose the remote and then capture the signal from the keys you want to use. See http://davehouston.org/learn.htm for a simple way to do this.

partime
- 28th May 2009, 06:49
Thanks for the response dhouston. I looked over the information. I think that is were I eventually want to get to. However, I don't think I am ready to take that big of jump yet.

I have been working on trying to do simple IR communications between 2 PICs. I basically used the codes from http://www.rentron.com/Infrared_Communication.htm.

I used a PIC627 with this code for the PWM and SEROUT.


DEFINE OSC 4
TRISB.3 = 0 ' CCP1 (PortB.3 = Output)
PR2 = 25 ' Set PWM Period for approximately 38KHz
CCPR1L = 13 ' Set PWM Duty-Cycle to 50%
CCP1CON = %00001100 ' Select PWM Mode
T2CON = %00000100 ' Timer2 = ON + 1:1 prescale
TRISB.0 = 0

ADDRESS VAR BYTE
DAT VAR BYTE
ID VAR BYTE
ADDRESS = 10
ID = 25

BEGIN:
FOR DAT = 0 TO 255
SEROUT PORTB.0,4,[ID,ADDRESS,DAT]
PAUSE 100
NEXT
GOTO BEGIN
END

And I used a PIC628A with this code for SERIN. The code Rentron had listed was BS2 code. I did my best to convert it to picbasic. I used SERIN2 instead of SERIN.



DEFINE OSC 4
CMCON = 7
VRCON = 0
TRISA = 0
TRISB = 1

SYNCH CON 25 'Establish synchronization byte
BAUD CON 396 'NON INVERTED 2400 baud (MAX)
DAT VAR byte 'Data storage variable
ADDRESS VAR BYTE

START:

SERIN2 PORTB.0,BAUD,[WAIT(SYNCH),ADDRESS,DAT]
PORTA = DAT

GOTO START
END

Was it okay to use SERIN2 with SEROUT?

I connected 4 LEDs to porta.0 thru porta.3. I am getting a response from the LEDs. I am just not sure if it representing the correct data. When I try something like:


ADDRESS VAR BYTE
DAT VAR BYTE
ID VAR BYTE
ADDRESS = 10
ID = 25
DAT = 10
BEGIN:
SEROUT PORTB.0,4,[ID,ADDRESS,DAT]
PAUSE 100
GOTO BEGIN
END

I get the correct LEDs to light up initially for about a second. Then, the other LEDs start flashing.

I will continue to experiment and hopefully I will get the communications figured out.

I do have a question about the schematic Rentron uses for the IR Transmitter. Is there a reason why 2 Infrared LEDs are used to transmit the signal?

dhouston
- 28th May 2009, 11:18
Was it okay to use SERIN2 with SEROUT?If you eventually want to use a remote, then all of this is just a waste of effort as 99.99% of remotes do not use RS232 communications.
I do have a question about the schematic Rentron uses for the IR Transmitter. Is there a reason why 2 Infrared LEDs are used to transmit the signal?
You get twice the IR signal strength for the same current.

picster
- 31st May 2009, 21:21
If your "carrier true" signal is incrementing because of looping, then you can simply count one, then sit and loop (no more counting) until the carrier detection returns a FALSE state, after which you drop out of the loop and wait for the next "button press". Kind of like switch debouncing, but different.

picster

flotulopex
- 31st May 2009, 22:51
Hello Partime,

I made a self-learning IR remote (with lots of help from people in this forum).

Maybe you can help some helpfull stuff in the code (especially LEARN and SEND routines).

Have a look here http://home.citycable.ch/flotulopex/REMI/REMI_Frames_e.htm

Archangel
- 1st June 2009, 03:26
Hello Partime,

I made a self-learning IR remote (with lots of help from people in this forum).

Maybe you can help some helpfull stuff in the code (especially LEARN and SEND routines).

Have a look here http://home.citycable.ch/flotulopex/REMI/REMI_Frames_e.htm
Roger, Nice ! I like your website ! Interested in that self learning remote too.

partime
- 1st June 2009, 06:00
Thank you picster and Roger for the information you presented.

I finally captured the signal from my remote as dhouston suggested. I couldn't get Loop Recorder to capture the signal, but I did get it with a different program (http://www.passmark.com/products/soundcheck.htm). I attached a copy of the signal I captured. It is from a Hitachi CLU-5722TSI remote's channel up button. The bottom one is the full signal. The top ones are of the signal divided into two segments.

The signal seems to follow this protocol that I found for Hitachi.
Code length: 32 bits
Carrier: 39.2kHz

The code is only transmitted once, and after that a stop code is transmitted.



+--------------------------------+
Header: | |
+ +----------------+..
16T 8T
8.8ms 4.4ms

+--+
1 is coded: | |
..+ +------+..
T 3T

+--+
0 is coded: | |
..+ +--+..
T T
+--+
| |
After the last bit a ( ..+ + ) is transmitted to terminate the last bit.
T

+--------------------------------+ +--+
Stop code: | | | |
+ +--------+ +
16T 4T T
8.8ms 2.2ms

T = 550us


What should the next step be? Should I try to write some code using PULSIN to read the incoming IR signal?

dhouston
- 1st June 2009, 11:19
That's the NEC protocol. It's one of the oldest and is used by more manufacturers than any other. It's very reliable as it has error detection built in (although some implementations do not use that). I have shown how to send/receive it (as RF) in this thread http://www.picbasic.co.uk/forum/showthread.php?t=6261. You just have to account for the fact that the IR receiver is active low while the RF receiver is active high. There is a link within that post to a NEC datasheet that explains it completely. I've decoded the third image and attached it. Hitachi is using error detection - the first two bytes sum to FF as do the third and fourth bytes.

dhouston
- 1st June 2009, 15:50
I just looked at your diagram. That's not a Stop Code - it's a Repeat Code. That reduces battery drain compared to repeating the full code.

partime
- 3rd June 2009, 07:12
Thanks again for your help Dave. I pretty much used your RF receiver code and modified it for use with the IR signal. Here is the code I used on an 16F84A with a 4 MHz crystal. I used it to test if the channel up button was pressed on the remote.


define PULSIN_MAX 968

IRPIN var PORTB.0
LED var PORTB.1
LED2 var PORTB.2
RF var byte[4]
Header var word
PULSE_LENGTH var byte
i var byte

INIT: RF[0]=0
RF[1]=0
RF[2]=0
RF[3]=0
i=0
Pulsin IRPIN, 0, Header
if (Header < 792) then INIT
while irpin = 0:wend
repeat
pulsin IRPIN, 1, PULSE_LENGTH
if (PULSE_LENGTH < 40) or (PULSE_LENGTH > 175) then INIT
if (PULSE_LENGTH > 90) then
RF.0(i) = 1
else
rf.0(i) = 0
endif
i=i+1
until (i>31)
if (RF[3]=230) then
high LED
pause 500
low LED
else
high LED2
pause 500
low LED2
endif
goto INIT
end

I get LED to go high when I press the channel up button.

It took me awhile to figure out how the data was arranged in the array. I started out using RF[0]=10 to light LED, but kept getting LED2 to light up. So, I thought there was something screwed up with the values pulsin was generating. Finally, I read through the FAQ on arrays and figured out my problem. I used RF[0]=80 and got LED to light up. However, LED would light up with any button I pushed since all the buttons used the same starting code. So, I ended up using RF[3] to test if channel up was pressed.

Is testing RF[3] going to be the best way to determine which button is pushed? I plan to use channel up/channel down for one team and volume up/volume down for the other team.

dhouston
- 3rd June 2009, 11:09
Is testing RF[3] going to be the best way to determine which button is pushed? I plan to use channel up/channel down for one team and volume up/volume down for the other team.The way most use this protocol, RF[0] indicates a device (e.g. TV, CD player) and RF[2] indicates a button (e.g. number, Vol+). RF[1] is the bitwise complement of RF[0] and RF[3] is the bitwise complement of RF[2]. So, you are probably safe using either RF[2] or RF[3].

I would suggest a change...
while irpin = 1:wendThat merely waits until the initial space part of the header passes. With RF I found that was necessary.

dhouston
- 3rd June 2009, 12:34
Also, since the array elements are reset to zero at the top of the loop, you can simplify this...
if (PULSE_LENGTH > 90) then
RF.0(i) = 1
else
rf.0(i) = 0
endif
to this...
if (PULSE_LENGTH > 90) then
RF.0(i) = 1
endif
And, while errors are less likely with IR, you can detect them buy adding RF[2] and RF[3]. They should always sum to 255 or $FF.