The latest Circuit Playground board, the Adafruit Circuit Playground Express comes equipped with an onboard IR transmitter and receiver! This can be used to communicate with TVs and other household devices. You can also use infrared remote controls to control your Circuit Playground Express. You can use another Circuit Playground Express as a remote to control your CPX, and you can even send simple messages between Circuit Playgrounds. By measuring the raw reflected IR light bouncing off of nearby objects you can make a simple proximity sensor!
Hi, Steven here from Core Electronics, today we're going to talk about how to use the Infrared Transmitter and Receiver on the Adafruit Circuit Playground Express and we're going to program it using Circuit Python.
So on the top of your Circuit Playground Express, there's a built-in infrared transmitter and receiver, the transmits marked with TX and that's a small diode here and then the receiver is marked with RX and it's the black one and then this little chip down here is our decoder and we needed a decoder because when we send an infrared signal we're not just turning the infrared light on and off, we actually send a series of pulses of on and off and we measure the time that passes between each pulse, so each of those is a duration and it can be anywhere. The most IR remotes will be under 200 durations and all this happens in just a fraction of a second, so there's a lot of fun things that you can do with an infrared transmitter and receiver on the Circuit Playground Express, I mean obviously you can use it as an infrared remote, so you can make your Circuit Playground control your TV or other devices in your house that receive infrared, maybe a radio and you can also receive signals from any device, so we can learn the pulse of any IR remote and make that control your Circuit Playground Express. So, say you have a spare IR remote from an LED strip laying around you can change all those buttons to influence the code that you're running on your Circuit Playground Express. For this we're going to make a sketch that turns your Circuit Playground Express into both the transmitter and receiver, so we'll send a unique pulse with each button press and always be waiting for one of those pulses on your Circuit Playground.
So, I've loaded the same sketch on to two separate Circuit Playground Expresses. When I press the A button on one, it will have a sparkle effect and when I press the B button, it'll make a rainbow effect and then it would work both ways on each board, so they're both capable of transmitting and receiving always. You can make you can make them do anything really I've just chosen some simple animations so we can see that it is, in fact, receiving our signals and the infrared transmitter and receiver should work pretty accurately up to about three meters and it will need more or less direct line-of-sight there's a lot of error within the pulse detection and in these signals, so although it is possible to bounce them off hard surfaces and things it's just not as reliable as direct line-of-sight.
So if we take a look at our code that we've made to make this program run I'll run us through it, first of all, we should we should all be familiar with importing libraries by now and for this code we need the Circuit Playground Express library, we need our board library, we need neopixels because we're using the onboard neopixels, Random which we use for our sparkle animation, Time to induce some pauses and our new one here, is our pulseIO and this is the critical one for transmitting pulses and receiving pulses with our infrared and we also need Array.
So, the getting the "meat" of the code here the first our first important part is to initialize our infrared receiver, so I named it pulseIn and we use the pulseio.PulseIn and there are three parts to this. First, we need to identify where it is the receiver is and we use board.IR_RX for the Circuit Playground Express but if you were using an external infrared receiver then you'd use this location to say "D3" or wherever it was connected. The next part is the max length of the durations that the pulse we're looking for, so I know that mine is going to be exactly 59 because I know the pulse that I'm sending, so I set it to 59, so then any longer pulses are going to just be ignored right away they'll be thrown out because it'll hit the maximum and stop if you're not sure what your pulse lengths are you have varying pulse lengths, then I would set this to 100 basically every infrared transmitter uses under 200 pulses, so if you're really not sure set it to 200 but beware on some devices if you're not using a Circuit Playground Express this does eat up a lot of memory and you may run into memory problems if that numbers too big. Then our last part is idle_state=True and this just confirms that the normal state for an infrared receiver is logic "HIGH" and this just confirms that that's the condition that we are starting out. Then we clear any artifacts within our pulseIn and then resume our detection.
The next part we're going to initialize our pulse out. So, our transmitter for first we need the pulse width modulation out and we need the pulse out command. So, first we set up our PWM and again we say where our transmitter is. For this, we need to set our frequency and infrared (this is important) infrared signals are always going to be 38 kilohertz. So, we've set that frequency to 38 kilohertz and the duty cycle is just the time on vs. time off and we've set this to 50 percent, which will work for most devices and then we confirm our pulse out using the variable pulse. So moving on we have our first pulse array here and as you can see these are actually the time that passes between each pulse so these are the duration times and there's 59 of them in this particular one but you could set them to any length you want and it's good to start and end each pulse, with a pretty long duration gap, So your receiver has maybe has a little extra time to realize it's receiving a pulse and it can make it a little cleaner, so you don't have overlapping pulse durations. Something important to mention about our pulses is, in order for them to send and receive properly through IR, we can't use regular arrays we need to make them an array.array data type 'H', which is for unsigned half-word and we do this because this ensures that the entire array will be sent whenever we command it to be sent and then the signal will stop when it's completed, so that way we don't start sending part of the array our code continues and it gets cut off. So, this makes sure that whenever it's sent, it's set in a whole single-unit.
Our next part of the code is our comparison, and this compares our received pulses against our stored pulses. So that's what determines if say we've received a pulse that's what determines if the pulse we received matches our stored pulses, an important thing to point out with this is it is a fuzzy compare. There's a lot of error like I said earlier within infrared, so we can't be looking for a perfect match every time we need to have a percentage margin of error that's acceptable to still be a match. so, the fuzziness is the margin percent of error set up in this code and I've said it to 0.5 which is 50%, since I'm only looking for 2 commands or two different pulses, 50% is still a very acceptable margin of error between the two and there are no false positives between buttons still. if you had a lot of if you were looking for a lot of different commands there are a lot of different pulse inputs then you might need to set that down to about 20% but for this sketch it works just fine at 50% and it's a little bit nicer user experience because it's much more likely to read as a match then not. if you set the fuzziness to low then you might find that you're pressing your button on your remote four or five times before I realize it realizes that it's a match.
We then initialize our neopixels and we set up our animations for sparkles and rainbow cycles and I won't get into that too much here, there's a lot of documentation available for neopixels. In our main loop, we have first our button press button, press logic so, when we press a button it sends the signal out because the transmitter and receiver are so close together, we need to be sure that before we transmit it we turn our receiver off, so it doesn't just read the transmitted pulse that's coming out right next to it as a unique pulse. So, first we pause the infrared detection we send our pulse we pause for a second, so our if we if the buttons held down it doesn't run the pulses together which might be read as one long pulse instead of unique multiple pulses. Then we clear any artifacts that might have been read halfway if by some chance the device was halfway through reading a pulse when you push the button this would clear any artifacts and then we resume our detection of new pulses once that's over.
For as far as receiving pulses, this is our next part of code we have our while length pulse in is greater than or equal to 59 and 59 is the max, so this will only really read when it's at 59 which is the length we want. We'll pause our detection and then we'll convert our input, we'll convert our detected pulse into the variable detected, as an array.array with the with the data type 'H' and it will be the pulse in data in an array the length of the pulse is detected and then we'll compare that against our stored pulses and if it's a match, we'll print that we received a good button press and then play the relevant animation for two seconds and then we'll clear our pulses and we'll resume. So, it's important the clear and resume because whenever you receive you receive an IR pulse it stores it in the pulse in until it's cleared, so if you don't clear it's just going to it's just going to stay at that reading that it had the first time and it won't overwrite.
So, let's see it in action with our serial monitor, we have our IR activated print and then when we hit it with an IR signal, we see that it's received a correct button A, correct button B press. Now if you want to use a different remote to control this same sketch, you can do that, you just need to you just need to record the signal that it's sending out first and then plug that into your code. So, I'll show you how to do that now.
So, let's go into a new document will open the 'repl' and this is kind of a live coding tool, so we can enter in our code as we go, and it will execute right on the board. So, when we have the 'repl' open, we're not actually using the computer at all what we're running directly from the board right now and we just have our display on the computer. So first we need to import the libraries that we'll use so we'll import the board, import pulse, I'll import array and then we need to initialize our infrared reader. So, I'm just going to copy and paste this in to save time, it's all available on the tutorial page for you to see. So, we do IR read equals the pulse in, we identify the board location the max length and I've set it to 100 because maybe we don't know how long the pulse durations are going to be, 'idle_state=true' and we'll hit enter and then we'll enter length IR read, so length IR read is zero, so we've received no pulse durations. So now we take our infrared remote for this I'll just use our already set up transmitting Circuit Playground Express. I'll hit the button once, so it's received A button press from my infrared remote, will do the IR read again and now you see that we've got fifty-nine pulses detected. So now we want to pause our detection because if we have any stray infrared in the room or something it might throw off our results or if there's another button press then they'll throw off our results. So, we'll pause that while we do our next step, which is to convert our detected pulses into an array and again I'll just copy that, but it's available toward the bottom of the tutorial page. So, we've stored in as on command equals array. array and it's going to be data type H and we'll say it's IR read for X in range, which is the length IR read which would be 59 and then we can just type in on command to see the array that we just stored and here it is our array. So that's our pulse durations for the IR remote that we just pointed at it. So now we can just copy this and paste it straight into our code and save it as a pulse option if you want and that allows you to use any infrared remote to control your Circuit Playground or just save the pulse code that it's outputting, so rather than maybe trying to look up somewhere and a datasheet what the actual pulse info is, you can just read it and stick it straight into your code and away you go.
So that wraps up our tutorial on using the infrared transmitter and receiver for that Adafruit Circuit Playground Express, if you want to learn more head over to our tutorials page all the code and some step-by-step info on how to read infrared pulses is available there and if you're interested in learning how to do the same project and MakeCode check out our other videos I've got a tutorial that I've just put up on how to do the same thing in MakeCode and it has great results. So, see you there.
SKU: ADA3333 https://core-electronics.com.au/circuit-playground-express-developer-edition.html
CAT: https://core-electronics.com.au/adafruit-circuit-playground.html
Makers love reviews as much as you do, please follow this link to review the products you have purchased.