IR from CPX to CPX

Your Circuit Playground Express can both transmit and receive IR signals! There is an example where each button on the CPX sends a different signal. We've emulated the volume up and volume down buttons on the Adafruit NEC remote since the receive code is already looking for those signals. So, the program be sending four bytes of data with each button press for the other CPX to receive and decode.

Why send four bytes instead of one? IR communication is messy, and often gets mixed up with flickering lights in the room, or maybe something blocking the photons. If you send only one byte, you run the risk of a signal being mis-interpreted as some other signal. By requiring and checking for four digits, your chance of getting a mistaken message is less likely. Why not more than four? If the message is too long, it would take a long time to send, and use more power. Four bytes are defined for the NEC standard - it's a nice trade-off between too-short and too-long.

You'll need two Circuit Playground Expresses for this example.

You should still have the code from the previous example on the first CPX.

Copy the following code into your code.py on the second CPX:

import time
from adafruit_circuitplayground.express import cpx
import adafruit_irremote
import pulseio
import board

# Create a 'pulseio' output, to send infrared signals on the IR transmitter @ 38KHz
pwm = pulseio.PWMOut(board.IR_TX, frequency=38000, duty_cycle=2 ** 15)
pulseout = pulseio.PulseOut(pwm)
# Create an encoder that will take numbers and turn them into NEC IR pulses
encoder = adafruit_irremote.GenericTransmit(header=[9500, 4500], one=[550, 550],
                                            zero=[550, 1700], trail=0)

while True:
    if cpx.button_a:
        print("Button A pressed! \n")
        cpx.red_led = True
        encoder.transmit(pulseout, [255, 2, 255, 0])
        cpx.red_led = False
        # wait so the receiver can get the full message
        time.sleep(0.2)
    if cpx.button_b:
        print("Button B pressed! \n")
        cpx.red_led = True
        encoder.transmit(pulseout, [255, 2, 191, 64])
        cpx.red_led = False
        time.sleep(0.2)

We create a pulseio output to send infrared signals from the IR transmitter at 38KHz. Then we create an encoder that will take the numbers we're sending and turn them into NEC IR pulses.

The arguments we pass into the adafruit_irremote.GenericTransmit line is what lets the irremote library know how to encode the 4 bytes into NEC remote data. There's a 9.5ms pulse high followed by a 4.5ms pulse low to let the receiver know data is coming. Then 550us+550us pulse pairs for a '1' value and 550us+1700us pulse pair for a '0' value.

header=[9500, 4500], one=[550, 550], zero=[550, 1700], trail=0

Inside our loop, we check to see if each button is pressed. When a button is pressed, we print a message to the serial console. Then, we turn on the red LED, send our 4 byte data signal, and turn the red LED off. Then we wait 0.2 seconds to give the receiver a chance to receive the full message.

Connect both Circuit Playground Expresses to the serial console to see the associated serial output. We've overlapped the windows side-by-side to show the serial output from both boards next to each other. You can see exactly what happens on the left when you press a button on the transmitting board, and on the right after the signal is received by the receiving board.

If you'd like to emulate your own remote, simply change the IR codes in the code.py above to match the changes you made in the last example. It works as long as you're transmitting the same code that the receiving board is expecting!

This guide was first published on Jul 24, 2018. It was last updated on Jul 24, 2018. This page (IR from CPX to CPX) was last updated on Jul 21, 2019.