Circuit Playground Express TV Remote

Updated 28 May 2019

Have you ever lost or broken a TV remote before it's time? Have you ever wanted to spice up the way you change channels or inputs on your TV? Have you got a greedy housemate who always steals the remote off you? If any of these are the case, you can learn to program your own TV remote using an Adafruit Circuit Playground Express! The onboard IR receiver (RX) and transmitter (TX) will be used to save and emulate the signals from the original remote to your TV or IR enabled device. If you haven't played with an Adafruit board before the CPX is a great place to start.

Recording Signals for your TV

Before we can start sending signals to your TV we need to know what data they should contain. The program we will upload to the CPX requires the pulseio, board, adafruit_circuitplayground libraries that are available from our CircuitPython on Circuit Playground Express tutorial however we will also require an additional library to make the IR encoding/decoding easier. This library is called adafruit_irremote and can be obtained from the Adafruit IR Remote GitHub Repository. After downloading and unzipping this file, navigate to the \lib folder and then copy the 'adafruit_irremote.mpy' file to the Circuit Playground Express' \lib directory. The board will now have access to the adafruit_irremote library which can be tested by typing 'import adafruit_irremote' in the REPL when the board is connected.

Now that we have the necessary libraries, we need to record some control signals! To record this data, we'll be setting up the IR receiver on your Circuit Playground Express and using your TV remote or remote emulator to send some signals. The code below simply reads any incoming IR signals and prints them to the REPL so you can copy and paste them into a text document for later use.

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

# Create a 'pulseio' input, to listen to infrared signals on the IR receiver
pulsein = pulseio.PulseIn(board.IR_RX, maxlen=120, idle_state=True)
# Create a decoder that will take pulses and turn them into numbers
decoder = adafruit_irremote.GenericDecode()

while True:
    pulses = decoder.read_pulses(pulsein)
    try:
        # Attempt to convert received pulses into 4 bytes
        received_code = decoder.decode_bits(pulses, debug=False)
    except adafruit_irremote.IRNECRepeatException:
        # We got an unusual short code, probably a 'repeat' signal
        print("NEC repeat!")
        continue
    except adafruit_irremote.IRDecodeException as e:
        # Something got distorted or maybe its not an NEC-type remote?
        print("Failed to decode: ", e.args)
        continue

    # Print the received code to the REPL
    print("NEC Infrared code received: ", received_code)

The format of these signals should be four bytes separated by commas in square brackets, e.g. [250, 0, 124, 30].


Sending Signals to your TV

Now that we have our signals in a text file (hopefully labelled), we can send this data using the same libraries as before! The code for this (set to my TV's codes) is below.

# Import the relevant libraries
import time                 # For sleep between transmitting data
import board                # For accessing the boards pins
import pulseio              # For creating the IR pulse object
import adafruit_irremote    # For easily transmitting NEC codes
from adafruit_circuitplayground.express import cpx
                            # For accessing the boards functionality

# Define the TV's NEC codes
Power_Button    = [177, 68, 143, 112]
Mute_Button     = [177, 68, 167, 88]
Menu_Button     = [177, 68, 63, 192]
Source_Button   = [177, 68, 135, 120]
Up_Button       = [177, 68, 221, 34]
Left_Button     = [177, 68, 199, 56]
Okay_Button     = [177, 68, 197, 58]
Right_Button    = [177, 68, 237, 18]
Down_Button     = [177, 68, 71, 184]
Exit_Button     = [177, 68, 69, 186]
EPG_Button      = [177, 68, 7, 248]
Volume_Up       = [177, 68, 109, 146]
Channel_Up      = [177, 68, 117, 138]
Volume_Down     = [177, 68, 61, 194]
Channel_Down    = [177, 68, 77, 178]

# Create the relavent instances
PWM = pulseio.PWMOut(board.IR_TX, frequency = 38000, duty_cycle = 2 ** 15)
                            # Defines the IR signal pwm for communication with 50% duty cycle
Pulse_Out = pulseio.PulseOut(PWM)
                            # Creates the output pulse instance
Signal_Encoder = adafruit_irremote.GenericTransmit(header=[9500, 4500],
                            one=[550, 550], zero=[550, 1700], trail=0)
                            # Defines NEC signals to be sent

# Define the capacitive touch sensitivity
cpx.adjust_touch_threshold(adjustment = 750)

# This is the main loop for the code
while True:
    # If the switch is to the left
    if cpx.switch:
        # If A1 is touched send Okay_Button
        if cpx.touch_A1:
            cpx.red_led = True
            Signal_Encoder.transmit(Pulse_Out, Up_Button)
            cpx.red_led = False
            time.sleep(0.2)
        # If A2 is touched send Source_Button
        if cpx.touch_A2:
            cpx.red_led = True
            Signal_Encoder.transmit(Pulse_Out, Down_Button)
            cpx.red_led = False
            time.sleep(0.2)
        # If A3 is touched send Power_Button
        if cpx.touch_A3:
            cpx.red_led = True
            Signal_Encoder.transmit(Pulse_Out, Okay_Button)
            cpx.red_led = False
            time.sleep(0.2)
        # If A4 is touched send Volume_Up
        if cpx.touch_A4:
            cpx.red_led = True
            Signal_Encoder.transmit(Pulse_Out, Volume_Up)
            cpx.red_led = False
            time.sleep(0.1)
        # If A5 is touched send Volume_Down
        if cpx.touch_A5:
            cpx.red_led = True
            Signal_Encoder.transmit(Pulse_Out, Volume_Down)
            cpx.red_led = False
            time.sleep(0.1)
        # If A6 is touched send Channel_Up
        if cpx.touch_A6:
            cpx.red_led = True
            Signal_Encoder.transmit(Pulse_Out, Channel_Up)
            cpx.red_led = False
            time.sleep(0.2)
        # If A7 is touched send Channel_Down
        if cpx.touch_A7:
            cpx.red_led = True
            Signal_Encoder.transmit(Pulse_Out, Channel_Down)
            cpx.red_led = False
            time.sleep(0.2)
        # If Button a is pressed, send Up_Button
        if cpx.button_a:
            cpx.red_led = True
            Signal_Encoder.transmit(Pulse_Out, Source_Button)
            cpx.red_led = False
            time.sleep(0.2)
        # If Button b is pressed, send Down_Button
        if cpx.button_b:
            cpx.red_led = True
            Signal_Encoder.transmit(Pulse_Out, Power_Button)
            cpx.red_led = False
            time.sleep(0.2)

As you can see, I have only used 9 signals for this program but have the capacity to add more if I want to implement the slide switch. Once loaded, feel free to test this program on your TV and see if you can change the channel with A6/A7 or change volume with A4/A5. If you can't see a red light from the D13 led your program has either halted which you can debug with the REPL or you need to change the capacitance-sensing value by altering the line

 cpx.adjust_touch_threshold(adjustment = 750)

With the switch in the 'True' position, the board will now send an IR signal and the onboard red LED will light up!

cpx-ir-test


Freeforming the Remote

Now we come to the really fun part. If you visit your local hobbyist store you can often find thin, brass rod which is a great conductor. For this project, I used a 1.5mm diameter rod and soldered the 3 ground connections on the board to a copper base plate. I then soldered the capacitive touch ports to a capacitive touch keyboard build for the Circuit Playground Express. Rubber feet on the bottom of the base plate lets the board stand on its own and rubber feet on top of the base plate allow me to place a battery on it for power when a Micro USB connection isn't an option. 

cpx-ir-final

There you have it, a functioning TV remote that you've programmed yourself! If you have any troubles or questions don't hesitate to consult our forum and we'll do our best to help you out. If you're interested in learning more, visit our Online Circuit Playground Express Workshop or our other Circuit Playground Express Tutorials.

Have a question? Ask the Author of this guide today!

Please enter minimum 20 characters

Your comment will be posted (automatically) on our Support Forum which is publicly accessible. Don't enter private information, such as your phone number.

Expect a quick reply during business hours, many of us check-in over the weekend as well.

Feedback

Please continue if you would like to leave feedback for any of these topics:

  • Website features/issues
  • Content errors/improvements
  • Missing products/categories
  • Product assignments to categories
  • Search results relevance

For all other inquiries (orders status, stock levels, etc), please contact our support team for quick assistance.

Note: click continue and a draft email will be opened to edit. If you don't have an email client on your device, then send a message via the chat icon on the bottom left of our website.

Makers love reviews as much as you do, please follow this link to review the products you have purchased.