SX/B IR remote control
Rsadeika
Posts: 3,837
This is a very basic (no pun intended) program. To be best used with an SX tech board, Parallax remote control (Sony codes), IR detector, and LED.
Problems: sluggish response time between button push and LED turning on; and if somebody tests it, maybe other stuff.
I welcome coding suggestions, and improvements. This uses the latest SX/B compiler.
****code
' =========================================================================
'
'·· File...... Test1.sxb
'·· Purpose... SX/B IR Remote control
'·· Author....·
'·· E-mail....·
'·· Started...
'·· Updated...
'
' =========================================================================
'
' Program Description
'
'
' Device Settings
'
DEVICE········· SX28, OSC4MHZ, TURBO, STACKX, OPTIONX
FREQ··········· 4_000_000
'
' IO Pins
'
'
' Constants
'
'
' Variables
'
·led1 var rb.0
·irpin var rc.0
·irpulse var byte
·temp1 var byte
·idx var byte
remotecode var byte
'
· INTERRUPT
'
ISR_Start:
· ' ISR code here
ISR_Exit:
· RETURNINT ' {cycles}································
' =========================================================================
· PROGRAM Start
' =========================================================================
'
' Subroutine Declarations
'
·ledon sub
·getcode sub
·processcode sub 1
·gofore sub· 'ChUp button
·goback sub· 'ChDn button
·goleft sub··· 'Vol- button
·goright sub··· 'Vol+ button
'
' Program Code
'
Start:
do
·'ledon·· 'Turn on LED
·getcode
·processcode remotecode
·'goto stop
loop
getcode:
'pause 1000· 'Turn on LED, to make sure I got here
·'ledon
remotecode = 0
irpulse = 0
do· ''*******Get start pulse
·pulsin irpin, 0, irpulse
loop while irpulse < 240 'Does not work with 220
''*****Get bits
pulsin irpin, 0, irpulse
if irpulse > 120 then
·remotecode.0 = 1
endif
pulsin irpin, 0, irpulse
if irpulse > 120 then
· remotecode.1 = 1
endif
pulsin irpin, 0, irpulse
if irpulse > 120 then
·remotecode.2 = 1
endif
pulsin irpin, 0, irpulse
if irpulse > 120 then
·remotecode.3 = 1
endif
pulsin irpin, 0, irpulse
if irpulse > 120 then
·remotecode.4 = 1
endif
pulsin irpin, 0, irpulse
if irpulse > 120 then
·remotecode.5 = 1
endif
pulsin irpin, 0, irpulse
if irpulse > 120 then
·remotecode.6 = 1
endif
return remotecode
processcode:
'pause 1000
'ledon
if remotecode = 16 then· ' If ChUp button
gofore· 'Turn on the LED
endif
if remotecode = 17 then·· 'If ChDn button
goback
endif
if remotecode = 18 then
goright
endif
if remotecode = 19 then
goleft
endif
return
ledon:
·tris_b=0
·led1 = 0
·pause 1000
·led1 = 1
return
gofore:
·pause 1000· 'Turn on LED to make sure I got here
ledon
return
goback:
· pause 1000
· ledon
return
goleft:
· pause 1000
· ledon
return
goright:
· pause 1000
· ledon
return
stop:
sleep
Problems: sluggish response time between button push and LED turning on; and if somebody tests it, maybe other stuff.
I welcome coding suggestions, and improvements. This uses the latest SX/B compiler.
****code
' =========================================================================
'
'·· File...... Test1.sxb
'·· Purpose... SX/B IR Remote control
'·· Author....·
'·· E-mail....·
'·· Started...
'·· Updated...
'
' =========================================================================
'
' Program Description
'
'
' Device Settings
'
DEVICE········· SX28, OSC4MHZ, TURBO, STACKX, OPTIONX
FREQ··········· 4_000_000
'
' IO Pins
'
'
' Constants
'
'
' Variables
'
·led1 var rb.0
·irpin var rc.0
·irpulse var byte
·temp1 var byte
·idx var byte
remotecode var byte
'
· INTERRUPT
'
ISR_Start:
· ' ISR code here
ISR_Exit:
· RETURNINT ' {cycles}································
' =========================================================================
· PROGRAM Start
' =========================================================================
'
' Subroutine Declarations
'
·ledon sub
·getcode sub
·processcode sub 1
·gofore sub· 'ChUp button
·goback sub· 'ChDn button
·goleft sub··· 'Vol- button
·goright sub··· 'Vol+ button
'
' Program Code
'
Start:
do
·'ledon·· 'Turn on LED
·getcode
·processcode remotecode
·'goto stop
loop
getcode:
'pause 1000· 'Turn on LED, to make sure I got here
·'ledon
remotecode = 0
irpulse = 0
do· ''*******Get start pulse
·pulsin irpin, 0, irpulse
loop while irpulse < 240 'Does not work with 220
''*****Get bits
pulsin irpin, 0, irpulse
if irpulse > 120 then
·remotecode.0 = 1
endif
pulsin irpin, 0, irpulse
if irpulse > 120 then
· remotecode.1 = 1
endif
pulsin irpin, 0, irpulse
if irpulse > 120 then
·remotecode.2 = 1
endif
pulsin irpin, 0, irpulse
if irpulse > 120 then
·remotecode.3 = 1
endif
pulsin irpin, 0, irpulse
if irpulse > 120 then
·remotecode.4 = 1
endif
pulsin irpin, 0, irpulse
if irpulse > 120 then
·remotecode.5 = 1
endif
pulsin irpin, 0, irpulse
if irpulse > 120 then
·remotecode.6 = 1
endif
return remotecode
processcode:
'pause 1000
'ledon
if remotecode = 16 then· ' If ChUp button
gofore· 'Turn on the LED
endif
if remotecode = 17 then·· 'If ChDn button
goback
endif
if remotecode = 18 then
goright
endif
if remotecode = 19 then
goleft
endif
return
ledon:
·tris_b=0
·led1 = 0
·pause 1000
·led1 = 1
return
gofore:
·pause 1000· 'Turn on LED to make sure I got here
ledon
return
goback:
· pause 1000
· ledon
return
goleft:
· pause 1000
· ledon
return
goright:
· pause 1000
· ledon
return
stop:
sleep
Comments
Since I like to put my money (coding skills) where my [noparse][[/noparse]big]·mouth (theory suggestions) is I've written and tested a simple program that waits for the SIRCS code.· I decided to include the command and device code in the program, and it's written so the device code portion can easily be stripped out, that way you could rewrite the program so you could do this: keyCode = GET_IRCS; right now it uses global vars.· Note that I've created a shell for PULSIN so that it's only expanded once -- this saves a lot of code space.
I've got this program running on my PDB and it's very responsive.·
[noparse][[/noparse]Edit] I've added a scope capture of a Sony IR stream when pressing "0" (zero) on a TV remote. [noparse][[/noparse]/Edit]
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Post Edited (Jon Williams (Parallax)) : 11/25/2005 10:17:51 PM GMT
I'm impressed, I spent the last three days trying to handle the first seven bits, you , in notime come up with a solution for all twelve bits. But, I think that I am getting better.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Post Edited (Jon Williams (Parallax)) : 11/25/2005 6:26:37 PM GMT
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Thanks. After doing a cursory look, first impressions of sircs_isr, SLICK. Looks like a potential article for N&V; needs lots of explanation for the assembly parts. I will have to put on my thinking cap for this one.
?Some where in the asm code resides a pulsin command?
Here's what the ISR does:
· -- data is not already available
····· -- if not already receiving data from IR device
········· -- wait for IR line to go low, then initialize everything
······--·when receiving
········· -- if IR line is low update the bit width counter
········· -- when IR line goes high
··············-- if on start bit (bitCount = 0)
················· -- test for proper width; if okay move to next bit otherwise reset process
··············-- if on data bit (bitCount > 0)
················· -- shift workspace value right
··················-- set workspace.6 if bit was "1" width
············· -- ignore IR line until it goes low again (for next bit)
··········--··when eight bits received
·············· -- move workspace to output var and set flags
The reason this is a little tricky is that SIRCS uses a variable bit width with a fixed idle time this means that the code has to watch for the IR line to go high to know that we're at the end of a bit, measure it, then what for the IR line to go back low to start measuring the next bit -- this is the reason why the rxBit flag is used (it lets us ignore the IR line idle time between bits).
This works, but I'm not saying it's the best way to do it.· Perhaps my friends Guenther, Bean, PeterM or others will chime in and show us where we can do this more efficiently.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
I seem to have confused, ease of use with learning. Ease of use, meaning, the difficulty in typing in somebody elses functioning code, hitting run, and have it work correctly. While learning involves knowing what the commands do or can do. Since, I had my first lesson, with this program, I can say, that SX/B is just as doable as PBASIC. Make sure you know the difference between ease of use and learning.
I had a chance to test both versions of the program you kindly provided. They work as expected, using my LED on/off concept. I have two questions, for now, concerning the ISR version.
1, In the ISR, you use two values, #74, #34. I have looked at these values from a decimal and binary perspective, and it·is not making sense to me. Do these, somehow represent the 2.4, 1.2, 0.6 ms requirements, or am I way off.
2. In the RETURNINT, you place a value of 104 -> 26 us @ 4 MHz. You mention that it will work for a 9600 baud UART. If I change the processor freq value, will both items get messed up. I kind of see maybe the 9600 baud being affected, but the IR portion should be good at any freq change. Am I correct in these assumptions.
Thanks
The ISR you wrote for decoding SIRCS data looks solid and quite compact. I wrote a SIRCS decoder as part of a much bigger project a year ago. In my case, dues to the way the rest of the project worked, I created a software timer that ran at .1 ms. This gave me a way to time incoming pulses with .1 ms resolution. For what it's worth, here is the pertinent part of the comment block for my code:
I'm not sure if this will give you any new ideas, but you never know. In re-reading my comments, I realize I should change my cutoff value from 1 ms to .9 ms to actually be in the middle of .6 ms and 1.2 ms.
hanks, PeterM
Thanks
About those values... the start bit is supposed to be 2400 uS.· 2400 / 26 = 92 -- I use 90% of that (83) since that is still longer than a "1" bit period and gives the code a little flexibility with a remote that might not have perfect timing.· Same for the "1" bit test; in this case I split the difference between the two bit times, use 900.· (INT) 900 / 26 = 34.· The code checks to see if the current bit time is less than this value -- the only time that should ever happen is if the bit is a valid zero.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Jon Williams
Applications Engineer, Parallax
Thanks
Just checking to make sure you're familiar with the difference between programming for debug and programming for standalone running and how to do that in the IDE, right?
Thanks, PeterM
Their is more to it than just making a choice of Run or Program? When I Run it with the SX-key in place the program executes as expected, when I execute it in stand-alone, I run into problems. I am in the midst of trying to narrow down an explanation of why I am getting these two different results. Maybe I need a page number, of some documentation,·that deals with programming for stand-alone applications, if their is indeed a difference. I guess, maybe an explanation in the FAQ may be in helpfull.
When you mention debug, is this a third choice of coding style. Maybe I am getting boged down in syntax, I am not sure at this point. This is getting to be a lot more complicated than doing a simple LED on/off application.
Run->Debug : Compiles or assembles the code and adds additional code which allows the SX key to control the chip. It then programs the chip, and starts the debugger. This is only used to run the code with the SxKey attached and the debugger running. Any external clock source (resonator, crystal, or TTL chip) must be removed from the SX in order for the debugger to work correctly.
Run->Debug Again : Similar to the Run-Debug except that it doesn't program the chip, but merely starts the debugger and assumes that the that the chip has already been programmed via Run->Debug and that the code in the chip is the same as the code in the IDE. This is used to avoid the time spent programming the chip when you haven't made any changes to the code but merely want to run it again.
Run->Program : Compiles or assembles the code and then programs the chip without the extra code used for control by the SxKey. After programming, power to the SX should be removed and an external clock source must be added in order for the chip to be able to run unless the internal 32 Khz, 128 KHz, 1 MHz, or 4 MHz clock is enabled by a DEVICE directive. The SxKey will not generate a clock for the SX chip and it should not be attached except during the programming phase. It is possible to to program the chip with a resonator in place.
Thanks, PeterM
For a begginer like myself, that explanation, does not leave any room for second guessing, very good.
Looking for some SX code to read a Sony remote and, before posting my question, I did a search. Thanks Jon for your code and expert advice. You answered the questions I didn't even think to ask.
John Bond