Your first key code
Three wires and one library, and every button on the remote prints its protocol, its address and its command. Keep this sketch: nothing you build with the sender works until it has told you what your remote sends.
Three wires
GND to GND, VCC to your board's logic supply, SIGNAL to a digital pin, NC to nothing. The receive pin is the same in every sketch in this book: D2 on an Uno, GPIO 23 on an ESP32, GPIO 9 on an ESP32-S3, GP16 on a Pico. Any other input pin works too.
The sketch
Three library calls do the work.
IrReceiver.begin(pin, DISABLE_LED_FEEDBACK) starts a timer that samples the
pin every 50 microseconds and records how long it stays low and high.
IrReceiver.decode() returns true once a whole frame has arrived and been
matched against every decoder the library has. It never waits.
IrReceiver.resume() hands the buffer back. Until you call it the library
looks at nothing else, and nothing says so: forget it and the sketch decodes
one press and then looks dead.
What you should see
Open the Serial Monitor at 115200 and press every button in turn:
NEC address=0x4 command=0x16 first time, 1 so far
NEC address=0x4 command=0x17 first time, 2 so far
NEC address=0x4 command=0x17
[repeat]
[repeat]Your numbers will differ; that is the point of the next chapter but one. The
address is the same for every button on one remote. The command
changes per button, and it is the number your project will act on. Holding a
button gives [repeat] every 110 ms instead of another code.
Write them down
Press all seventeen buttons and copy the address and command of the ones you care about into a comment. Be the remote and one button, one job need them, and they exist nowhere except in the remote in your hand.
The code
Prints one line per button press and counts how many different codes it has seen. Change IR_RX_PIN to the pin SIGNAL is on and nothing else. The remote in the kit has seventeen buttons, so a full pass ends at 17.
/*
IR Receiver - key codes TK15 / /p/tk15
Wiring. Count from the square pad on the TinkerBlock board, parts
up, header at the bottom:
GND -> GND
VCC -> 5V on an Uno; 3V3 on an ESP32, ESP32-S3 or Pico
(SIGNAL idles at VCC, so match your board)
NC -> nothing (unconnected on the board)
SIGNAL -> D2 on an Uno, GPIO 23 on an ESP32, GPIO 9 on an
ESP32-S3, GP16 on a Raspberry Pi Pico
Arduino IDE
Tools > Board your board, e.g. Arduino Uno
Tools > Port the one that appears when you plug in
Tools > USB CDC On Boot Enabled (ESP32-S3 only)
Tools > Manage Libraries IRremote by shirriff, z3t0 and
ArminJo, version 4 or later
Serial Monitor 115200
*/
#include <IRremote.hpp>
// The pin SIGNAL is wired to.
// Uno: 2. ESP32: 23. ESP32-S3: 9. Pico: 16.
const int IR_RX_PIN = 2;
// Every address-and-command pair seen so far.
const int MAX_KEYS = 32;
uint32_t seen[MAX_KEYS];
int keys = 0;
bool firstTime(uint32_t key) {
for (int i = 0; i < keys; i++) {
if (seen[i] == key) return false;
}
if (keys < MAX_KEYS) seen[keys++] = key;
return true;
}
void setup() {
Serial.begin(115200);
// DISABLE_LED_FEEDBACK: leave your board's own LED alone.
IrReceiver.begin(IR_RX_PIN, DISABLE_LED_FEEDBACK);
Serial.println("Press every button on the remote.");
}
void loop() {
if (!IrReceiver.decode()) return; // no whole frame yet
IRData &d = IrReceiver.decodedIRData;
if (d.flags & IRDATA_FLAGS_IS_REPEAT) {
Serial.println("[repeat]"); // a held button
} else if (d.protocol == UNKNOWN) {
Serial.println("UNKNOWN: no decoder matched this frame");
} else {
Serial.print(getProtocolString(d.protocol));
Serial.print(" address=0x");
Serial.print(d.address, HEX);
Serial.print(" command=0x");
Serial.print(d.command, HEX);
uint32_t key = ((uint32_t)d.address << 16) | d.command;
if (firstTime(key)) {
Serial.print(" first time, ");
Serial.print(keys);
Serial.print(" so far");
}
Serial.println();
}
IrReceiver.resume(); // nothing else decodes until this runs
}Holding a button prints [repeat], which is NEC working, not a fault. If every press prints UNKNOWN, the remote is not one of the protocols the library knows; codes belong to remotes explains what to do with it.
The same key dump in MicroPython, for an ESP32, an ESP32-S3 or a Pico, with Peter Hinch's micropython_ir. The library calls got() for every frame it decodes; the loop at the bottom only keeps the program alive.
"""
IR Receiver - key codes, MicroPython TK15 / /p/tk15
Wiring. Count from the square pad on the TinkerBlock board, parts
up, header at the bottom:
GND -> GND
VCC -> 3V3 (SIGNAL idles at VCC)
NC -> nothing (unconnected on the board)
SIGNAL -> GPIO 23 on an ESP32, GPIO 9 on an ESP32-S3,
GP16 on a Raspberry Pi Pico
Install once, from a computer:
mpremote mip install "github:peterhinch/micropython_ir/ir_rx"
Thonny
Run > Configure interpreter MicroPython (ESP32) or
MicroPython (Raspberry Pi Pico)
Save it to the board as main.py to run it on every power-up.
"""
import time
from machine import Pin
from ir_rx.nec import NEC_8 # NEC, 8-bit address and its check
# The GPIO number SIGNAL is wired to. ESP32: 23. ESP32-S3: 9. Pico: 16.
IR_RX_PIN = 9
seen = set()
def got(command, address, ctrl):
if command < 0: # a repeat frame carries no data
print("[repeat]")
return
key = (address, command)
first = key not in seen
seen.add(key)
line = "address=0x%02x command=0x%02x" % (address, command)
if first:
line += " first time, %d so far" % len(seen)
print(line)
ir = NEC_8(Pin(IR_RX_PIN, Pin.IN), got)
print("Press every button on the remote.")
while True:
time.sleep_ms(500)Install ir_rx once from a computer with mpremote, as the comment says; Thonny then runs the file. NEC_8 checks each byte against its complement, so a frame that fails the check is dropped rather than printed. Stop it with Ctrl-C.
When it does not work
Watch the TK15's red LED. If it flickers when you press a button, the board and the remote are fine and the fault is the SIGNAL wire or the pin number. If it does not, check GND and VCC, and that the remote has batteries: none come in the kit.
A frame arrived that no decoder recognised. Air-conditioner remotes are the usual cause: they send a hundred bits or more. On an Uno the library's buffer holds 200 entries; define a larger, even RAW_BUFFER_LENGTH on the line before the #include, as far as the Uno's 2 KB of memory allows. An ESP32 or a Pico already holds 750.
You are holding the button. NEC sends the code once, then a short repeat frame every 110 ms while the key is down, and the sketch prints [repeat] for each. One press, one action means skipping repeats, as the sketch does.
IrReceiver.resume() is missing, or sits in a branch that did not run. The library holds the frame until you release it, so without that call it never looks at another, and nothing reports an error.
On an Uno the library receives with Timer2, and Timer2 drives PWM on pins 3 and 11. Move that output to pin 5, 6, 9 or 10. It is receiving that costs those pins, not sending.
Set Tools > USB CDC On Boot to Enabled and upload again. Without it the S3's USB port brings up no serial port at boot, so the sketch runs with nowhere to print.
What those two numbers are made of, and why half of every frame is a copy of the other half.
Thirty-two bits of NEC →Edit this page — content/books/ir-receiver/your-first-key-code.mdx
Questions about this product
See what other owners have asked, and read their solutions.
This page covers several products. Choose yours to see the right discussions.
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.