Skip to content

Arduino Firmware

Alejandro Mora edited this page May 8, 2026 · 1 revision

Arduino Firmware

The Arduino Pro Micro firmware turns a cheap microcontroller board into a universal USB IR transceiver. It decodes RC-6 IR signals and forwards them to the host as serial scancodes, and transmits IR signals on command from the host. This makes InfraFi work on any Linux machine regardless of whether it has built-in CIR hardware.


Hardware Required

Component Notes
Arduino Pro Micro (16MHz, 5V) SparkFun or compatible clone
TSOP38238 IR receiver module 38kHz carrier, 5V compatible
IR LED (940nm, e.g. TSAL6200) Any 940nm LED works
NPN transistor (e.g. 2N3904) For driving the IR LED
Resistors 100 ohm (base), 10-33 ohm (LED series)
USB Micro-B cable For power and serial communication

Wiring

Pin Assignments

Arduino Pin Signal Connected To
2 (INT0) PIN_IR_RECV TSOP38238 data output
3 (PWM) PIN_IR_SEND IR LED driver (NPN base via 100 ohm)
4 PIN_TEST_MODE Jumper to GND for test mode
17 (RX LED) PIN_LED_ACT Built-in LED (activity blink)

Receiver Wiring

TSOP38238:
  Pin 1 (OUT) -----> Arduino Pin 2
  Pin 2 (GND) -----> GND
  Pin 3 (VS)  -----> 5V  (add 100 ohm series + 100uF bypass cap to GND)

Transmitter Wiring

Arduino Pin 3 --[100 ohm]--> NPN Base (2N3904)
NPN Collector --[10-33 ohm]--> IR LED Anode (TSAL6200)
IR LED Cathode --> GND
NPN Emitter --> GND

The transistor switches the LED on/off at 36kHz to produce the modulated carrier. SEND_PWM_BY_TIMER is defined in the build flags to enable hardware PWM generation on the ATmega32U4.


Building with PlatformIO

Prerequisites: PlatformIO CLI or PlatformIO IDE extension.

# Install PlatformIO CLI (if not already installed)
pip install platformio

# Build the firmware
cd arduino
pio run

# Upload to connected Pro Micro
pio run -t upload

# Monitor serial output
pio device monitor --baud 115200

The board target is sparkfun_promicro16 (16MHz variant). This is configured in platformio.ini:

[env:promicro]
platform = atmelavr
board = sparkfun_promicro16
framework = arduino
lib_deps = Arduino-IRremote/IRremote@^4.4
monitor_speed = 115200
build_flags = -DSEND_PWM_BY_TIMER

Use the 16MHz variant. The 8MHz variant (sparkfun_promicro8) uses a different bootloader and USB descriptor.


Serial Protocol

The firmware communicates with the host daemon (infrafid) over USB CDC serial at 115200 baud.

Startup

On power-up or USB connection, the Arduino sends one of:

  • WFIR:READY - Normal mode, ready for InfraFi operation
  • TEST:READY - Test mode active (pin 4 pulled to GND)

Text Mode (initial)

Before binary mode negotiation, communication is human-readable.

Host -> Arduino:

WFIR          -> Initiate binary mode handshake
TX:A0:05      -> Transmit IR scancode (address=0xA0, command=0x05)

Arduino -> Host:

WFIR:OK:1     -> Binary mode accepted
SC:A0:05      -> Received IR scancode (address=0xA0, command=0x05)
TX:OK         -> IR transmission complete

Binary Mode (negotiated)

After handshake, the protocol switches to compact binary frames for efficiency.

Arduino -> Host (received scancode):

[0xA5] [address] [command]

Host -> Arduino (transmit request):

[0xA6] [address] [command]

Arduino -> Host (TX complete):

[0xA7] [0x00] [0x00]

Sync bytes:

Byte Constant Direction Meaning
0xA5 SYNC_RX_SC Arduino -> Host Received scancode follows
0xA6 SYNC_TX_REQ Host -> Arduino Transmit request follows
0xA7 SYNC_TX_DONE Arduino -> Host TX complete

Test Mode

Bridge pin 4 to GND before powering on to enter test mode. In test mode:

  • All received IR protocols are printed (not just RC-6)
  • Output format: IR:<protocol>:A=0x<addr>:C=0x<cmd>:R=0x<raw>
  • No scancode forwarding to binary protocol

This is useful for verifying IR reception and diagnosing protocol issues with arbitrary remotes.

# Watch test mode output
pio device monitor --baud 115200

Example output:

TEST:READY
IR:RC6:A=0xA0:C=0x05:R=0xA05
IR:RC6:A=0xA4:C=0x48:R=0xA448

Watchdog

The firmware enables the AVR watchdog timer with a 4-second timeout (WDTO_4S). If the main loop hangs for any reason, the board resets automatically. The watchdog is reset at the top of each loop() call.


Activity LED

Pin 17 (the built-in RX LED on the Pro Micro) blinks briefly on every received or transmitted IR event. Since the LED is active-low on the Pro Micro, LOW = on and HIGH = off.


Source Files

arduino/
  platformio.ini    # Board config, dependencies
  src/
    main.cpp        # Firmware: IR receive, serial protocol, IR TX
    config.h        # Pin definitions, baud rate, sync bytes, protocol constants

Clone this wiki locally