Sending modulated IR data with a BS2 and NO external hardware ...
Phil Pilgrim (PhiPi)
Posts: 23,514
... except an IRED and a resistor, of course!
A couple recent posts, notably here and here, discuss sending infrared messages from a BASIC Stamp for the purpose of remote control. Each required external circuitry in the form of a 555 timer or a coprocessor in order to modulate the infrared at 38.5KHz, so the receiver could detect it.
For transmitting a small finite number of possible characters, though, this external circuitry is unnecessary; and the BASIC Stamp can do the modulation on its own. The trick is to employ a combinaiton of FREQOUTs and PULSOUTs to form the modulated bitstream. The FREQOUTs, with a frequency of 38.5KHz (as used for obstacle detection) encode the zeroes of the bitstream and are applied to a pin which drives the anode of an IRED through a 220-ohm resistor. The PULSOUTs encode the ones of the bitstream and are applied to a dummy pin to which nothing is connected.
Since FREQOUT encodes bursts in multiples of 1ms (in the BS2, to which this discussion applies), the fastest baudrate that can be accommodated by this technique is 1kbaud, and this is the rate we'll be using here. Since the BS2 isn't fast enough to send bitstreams on the fly by shifting and "banging" the bits out one-by-one, we have to resort to a different technique. In this method, the modulated zeroes and unmodulated ones are generated by inline code that groups like consecutive bits together. For example, to send the letter "C", which equals 43 in hex, or 01000011 in binary, we must first add a zero start bit to the end and a one stop bit to the beginning, thus: 1010000110. Then, since serial I/O occurs least-significant-bit first, we have to reverse the bit order: 0100000101. Finally, we can group like bits together: 0 11 0000 1 0 1. So to send a "C", we send 1ms of modulation, followd by 2ms of nothing, followed by 4ms of modulation, then 1ms of nothing, 1ms of modulation, and finally 1ms of nothing. The code to do that looks like this:
Here, so is the pin connected to the IRED, and dummy is the empty pin. Between FREQOUTs, there is a net 670µs of interpreter overhead, which can be compensated for in the PULSOUTs. Since pulses are encoded in increments of 2µs, a 1ms silent interval would normally be transmitted with a pulse length of 500. But after subtracting the 670µs overhead (pulse width of 335), we're left with a pulse width of 165 instead. This is only for single one bits, though. For each additional one bit in a group, add 500 to the pulsewidth. Hence, the 665 in the code above.
To make creation of these sequences easier, I've posted a subroutine generator at: www.phipi.com/ir_xmt. To use the generator, just type in the characters/hex values/decimal values you want to be able to send, and a send subroutine will be created for you that you can copy and paste into your BS2 code. Given the following input data ...
... here's a typical example of its output:
Here are complete programs for transmitting and receiving data using a pair of BS2s — one with the IRED and resistor, the other with an infrared receiver:
It should be noted that this method of communication is unsuitable for sending messages containing arbitrary ASCII characters. To do so would require a SendChr routine with CASEs for the entire ASCII alphabet! But for limited data and remote control sequences, the method should be entirely adequate.
-Phil
A couple recent posts, notably here and here, discuss sending infrared messages from a BASIC Stamp for the purpose of remote control. Each required external circuitry in the form of a 555 timer or a coprocessor in order to modulate the infrared at 38.5KHz, so the receiver could detect it.
For transmitting a small finite number of possible characters, though, this external circuitry is unnecessary; and the BASIC Stamp can do the modulation on its own. The trick is to employ a combinaiton of FREQOUTs and PULSOUTs to form the modulated bitstream. The FREQOUTs, with a frequency of 38.5KHz (as used for obstacle detection) encode the zeroes of the bitstream and are applied to a pin which drives the anode of an IRED through a 220-ohm resistor. The PULSOUTs encode the ones of the bitstream and are applied to a dummy pin to which nothing is connected.
Since FREQOUT encodes bursts in multiples of 1ms (in the BS2, to which this discussion applies), the fastest baudrate that can be accommodated by this technique is 1kbaud, and this is the rate we'll be using here. Since the BS2 isn't fast enough to send bitstreams on the fly by shifting and "banging" the bits out one-by-one, we have to resort to a different technique. In this method, the modulated zeroes and unmodulated ones are generated by inline code that groups like consecutive bits together. For example, to send the letter "C", which equals 43 in hex, or 01000011 in binary, we must first add a zero start bit to the end and a one stop bit to the beginning, thus: 1010000110. Then, since serial I/O occurs least-significant-bit first, we have to reverse the bit order: 0100000101. Finally, we can group like bits together: 0 11 0000 1 0 1. So to send a "C", we send 1ms of modulation, followd by 2ms of nothing, followed by 4ms of modulation, then 1ms of nothing, 1ms of modulation, and finally 1ms of nothing. The code to do that looks like this:
FREQOUT so, 1, 38500 ' Send start bit 0 (modulate 1ms). PULSOUT dummy, 665 ' Send 11 (silence 2ms). FREQOUT so, 4, 38500 ' Send 0000 (modulate 4ms). PULSOUT dummy, 165 ' Send 1 (silence 1ms). FREQOUT so, 1, 38500 ' Send 0 (modulate 1ms). PULSOUT dummy, 165 ' Send stop bit 0 (silence 1ms).
Here, so is the pin connected to the IRED, and dummy is the empty pin. Between FREQOUTs, there is a net 670µs of interpreter overhead, which can be compensated for in the PULSOUTs. Since pulses are encoded in increments of 2µs, a 1ms silent interval would normally be transmitted with a pulse length of 500. But after subtracting the 670µs overhead (pulse width of 335), we're left with a pulse width of 165 instead. This is only for single one bits, though. For each additional one bit in a group, add 500 to the pulsewidth. Hence, the 665 in the code above.
To make creation of these sequences easier, I've posted a subroutine generator at: www.phipi.com/ir_xmt. To use the generator, just type in the characters/hex values/decimal values you want to be able to send, and a send subroutine will be created for you that you can copy and paste into your BS2 code. Given the following input data ...
"A", "B", $10, 5
... here's a typical example of its output:
SendChr: SELECT chr CASE "A": FREQOUT so, 1, 38500 PULSOUT dummy, 165 FREQOUT so, 5, 38500 PULSOUT dummy, 165 FREQOUT so, 1, 38500 CASE "B": FREQOUT so, 2, 38500 PULSOUT dummy, 165 FREQOUT so, 4, 38500 PULSOUT dummy, 165 FREQOUT so, 1, 38500 CASE $10: FREQOUT so, 5, 38500 PULSOUT dummy, 165 FREQOUT so, 3, 38500 CASE 5: FREQOUT so, 1, 38500 PULSOUT dummy, 165 FREQOUT so, 1, 38500 PULSOUT dummy, 165 FREQOUT so, 5, 38500 ENDSELECT PULSOUT dummy, 165 RETURN
Here are complete programs for transmitting and receiving data using a pair of BS2s — one with the IRED and resistor, the other with an infrared receiver:
' {$STAMP BS2} ' {$PBASIC 2.5} ' Program to test sending data via modulated IR. so PIN 0 ' Pin to which IRED is connected. dummy PIN 1 ' Unconnected pin. chr VAR Byte ' Variable that holds character to send. StrAddr VAR Word ' Pointer to EEPROM string. StringA DATA "!ABC", CR, 0 ' Strings in EEPROM. StringB DATA "!xyz", CR, 0 DO StrAddr = StringA ' Point to StringA. GOSUB SendStr ' Send it. PAUSE 100 StrAddr = StringB ' Point to StringB. GOSUB SendStr ' Send it. PAUSE 1000 ' Wait a sec. LOOP SendStr: DO READ StrAddr, chr ' Read next character. StrAddr = StrAddr + 1 ' Increment string address. IF (chr = 0) THEN EXIT ' End of string? Exit loop if so. GOSUB SendChr ' Send character if not. LOOP ' Again. RETURN ' Return to caller. SendChr: ' SendChr routine from http://www.phipi.com/ir_xmt SELECT chr CASE "!": FREQOUT so, 1, 38500 PULSOUT dummy, 165 FREQOUT so, 4, 38500 PULSOUT dummy, 165 FREQOUT so, 2, 38500 CASE "A": FREQOUT so, 1, 38500 PULSOUT dummy, 165 FREQOUT so, 5, 38500 PULSOUT dummy, 165 FREQOUT so, 1, 38500 CASE "B": FREQOUT so, 2, 38500 PULSOUT dummy, 165 FREQOUT so, 4, 38500 PULSOUT dummy, 165 FREQOUT so, 1, 38500 CASE "C": FREQOUT so, 1, 38500 PULSOUT dummy, 665 FREQOUT so, 4, 38500 PULSOUT dummy, 165 FREQOUT so, 1, 38500 CASE "x": FREQOUT so, 4, 38500 PULSOUT dummy, 1665 FREQOUT so, 1, 38500 CASE "y": FREQOUT so, 1, 38500 PULSOUT dummy, 165 FREQOUT so, 2, 38500 PULSOUT dummy, 1665 FREQOUT so, 1, 38500 CASE "z": FREQOUT so, 2, 38500 PULSOUT dummy, 165 FREQOUT so, 1, 38500 PULSOUT dummy, 1665 FREQOUT so, 1, 38500 CASE 13: FREQOUT so, 1, 38500 PULSOUT dummy, 165 FREQOUT so, 1, 38500 PULSOUT dummy, 665 FREQOUT so, 4, 38500 ENDSELECT PULSOUT dummy, 165 RETURN
' {$STAMP BS2} ' {$PBASIC 2.5} ' Program to receive IR test data. BAUD1000 CON 980 ' Constant for 1000 baud. ir_input PIN 15 ' Pin to which IR receiver is connected. string VAR Byte(4) ' Array containing received string. DO SERIN ir_input, BAUD1000, [noparse][[/noparse]WAIT("!"), STR string\4] DEBUG STR string\4 LOOP
It should be noted that this method of communication is unsuitable for sending messages containing arbitrary ASCII characters. To do so would require a SendChr routine with CASEs for the entire ASCII alphabet! But for limited data and remote control sequences, the method should be entirely adequate.
-Phil
Comments
I'm also a big fan of getting the most IR "bang for the buck", and I experiment a lot to that end. I just posted a circuit on a cheap IR navigation beacon at http://forums.parallax.com/showthread.php?p=722919 that lets my Scribbler navigate around the house easily.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
·"If you build it, they will come."
Back then I was working in the Field Service Division of Siemens Electrocom, constantly flying out to distant cities for weeks at a time to service or install automation systems inside USPS postal facilities. The boredom of being away from home all the time was killing me, living out of a suitcase and praying the crappy telephone lines at any particular hotel would work with mt 56k dialup modem to get on the net. (broadband didnt hardly exist yet!)
I ended up buying a BS-1 starter, (one of the best things I ever did, seriously) and started doing the experiments in the spiral-bound manual that came with it. One experiment in particular I became interested in was the IR transmitter and receiver. The Pbasic language was rather sparse, but attractive in simplicity. I was soon controlling a remote device (on/off) with this circuit, but noticed limitations in range or direction of detector.(orientation)
The TX was driven from my laptop RS-232 serial port, and the RX was the BS-1 tied to a radioshack IR detector module. (with the little sheet metal enclosure -10mm 10mm 10mm)
One thing I noticed almost accidentally, and havent said anything publicly about it all this time until now, was something I did in the setup programming by accidentally omitting a zero, was something that made this same exact circuit able to transmit 10x as far (even farther actually) and most notably, around corners, not even in direct view!
All this time I was like thinking I would somehow monopolize on this discovery and somehow make profit by offering a lame improvement to IR interfaces...as we all know the pains and troubles conventional IR remotes for TVs etc. can be when trying to even change channels in direct sight. Never did anything about it, as of course this wasnt patentable or anything...but I didnt really say anything about it either...all this time.
Now, because of my endeavors building autopilot systems for drones using Arduinos, and catching the electronics bug again, Ive found my ancient assemblies of this circuit with the BS-1s still plugged in.
What I did before putting it all away in storage for 12 years, was take the BS-1 circuit described, and built a second clone of it, to create two separate transceivers utilizing this "discovery" I made.
The programming differed slightly between the two, in the device ID assigned, and the starting sequence. One was a "starter" that sent out the packet 1st when powered up. and the other was the "responder" that was listening quietly when powered up. When both were on, they would "toss a ball" proverbially between them, blinking an LED when each received its packet and re-sent.
So you could visually see them alternating blinks while "tossing the ball", like a game of catch.
If a packet was lost, the unit that lost it didnt resend, and they both stopped.
It was really interesting to me at the time, and I ran them a lot, tried to show friends and coworkers the concept...
No one really thought much of it, as I guess it was over their heads or something...so I think that had damped my enthusiasm, and it was no longer fun for me...that precipitated the packing them away for all this time, and losing interest in MCs in general.. until now.
I dont know if anyone ever managed to get IR transceivers or even a TX/RX pair to transmit ASCII around corners by just wall reflection (thats all I can attribute this to) but now that Ive found my little contraptions, Im about ready to clean em up, re-solder a wire or two on the "responder" unit, and film them playing "catch" for a youtube video.
In this, I will show them talking back and forth in sight of each other, then I will move the responder around the corner, down the hall, to demonstrate this phenomenon...and show they are still playing catch. Then I will cover the IR opening on one to "kill" the cycle.
When I get this made in a few days I will post back here with the link to show you, if interested in this.
I didnt do anything exceedingly brilliant or genius to create this, just a simple error as I said, and recognizing the discovery of why it did this.
I could have easily missed the error, corrected my code without ever even running the BS-1 with the error to begin with, and thus never made this astonishing discovery in IR comms.
When I divulge the exact code that enabled this thing, you will laugh. But honestly, its so stupid and unexpected that no wonder its probably unknown to anyone still.
Man, Im so glad things have happened the way they have and Im right back into this stuff again...had
I not looked for some parts when I did recently, these Stamps and everything related to this would have been thrown away or lost forever.