When we tried the same approach for the Roomba, irrecord failed to read the Roomba's remote codes — with no clear reason why.
So we switched to controlling the Roomba from Arduino instead of Raspberry Pi.
The logic is simple: both Raspberry Pi and Arduino can send IR signals, so either works.
With Arduino in the picture, the first problem is getting commands from the hub's Node-RED to the Arduino.
Since all we need to transmit is a few bits, there are plenty of options — ESP-WROOM-02, Bluetooth, and so on.
For this build I used an old FlashAir (W-02) that was lying around.
- Gather parts.
- Set up Node-RED on the main Raspberry Pi and register it with Amazon Echo Dot
- Headless WiFi setup for Raspberry Pi Zero W
- Copy IR remote codes with Raspberry Pi
- Call IR functions from Node-RED to control the TV
- Control Arduino via HTTP API using FlashAir GPIO mode [This article]
- (Bonus) Control Roomba from Arduino via ROI serial interface
- Control Roomba from Arduino via IR
- Control Roomba from Node-RED via FlashAir/Arduino
FlashAir GPIO Mode
FlashAir's GPIO mode lets you use five of the SD card's terminals as GPIO pins, controllable via HTTP.FlashAir Developers has a detailed explanation.
In other words, connect FlashAir's terminals to Arduino pins and you can toggle those pins High/Low over HTTP.
The trade-off: FlashAir can no longer be used as storage.
To change FlashAir's behavior, edit the /SD_WLAN/CONFIG file.
It's normally a hidden folder, but on Linux or Mac you can mount the card and edit the file via shell.
On Windows, enabling hidden folder visibility should work.
Open the file and add IFMODE=1 at the end to enable GPIO mode.
Setting FlashAir to Station (Client) Mode
By default, FlashAir acts as a WiFi access point.That means it can't receive HTTP requests from Node-RED inside your home LAN.
The fix is to put FlashAir into station mode so it connects to your WiFi router as a client.
This is also covered on FlashAir Developers:
"Using Station Mode"
The final CONFIG file looks like this:
APPMODE=5
APPNAME={FlashAir device name}
APPSSID={WiFi SSID}
APPNETWORKKEY={WiFi password}
CIPATH=/DCIM/100__TSB/FA000001.JPG
VERSION=F19BAW3AW2.00.00
CID=02544d535730384708c00b7d7800d201
PRODUCT=FlashAir
VENDOR=TOSHIBA
MASTERCODE=18002d4ff0a2
IFMODE=1
Connecting FlashAir to Arduino
Use an SD card slot like this one (Amazon) to connect FlashAir to the Arduino.Since all we need is to trigger the Roomba, one bit is enough.
So we only connect three pins: one signal pin, 3.3V, and GND.
FlashAir's SDI was connected to Arduino pin 11.
3.3V and GND connected as appropriate.
Writing FlashAir GPIO State via HTTP
The HTTP API for GPIO is documented on FlashAir Developers under "SD Interface Terminal I/O (op=190)".We're using the SDO pin (CMD) as GPIO, so we just need to toggle 0x01 between HIGH and LOW.
The URL parameters for each state are:
- SDO=HIGH → op=190&CTRL=0x1f&DATA=0x01
- SDO=LOW → op=190&CTRL=0x1f&DATA=0x00
Reading FlashAir GPIO from Arduino
Reading a pin state from Arduino is just a plaindigitalRead call — no library needed.One thing to watch: all pins are HIGH when FlashAir starts up.
If you trigger the Roomba on a HIGH signal, it will start immediately when FlashAir powers on.
You could invert the HIGH/LOW logic in hardware, but that adds parts.
Instead, I worked around it in Node-RED: send a LOW reset first, then send HIGH to trigger.
It might also be possible to set the Arduino pin to OUTPUT and pull it LOW initially, but I haven't tested that.
The Arduino code looks like this:
#define PIN_SD_CLEAN 11
void setup() {
Serial.begin(9600);
pinMode(PIN_SD_CLEAN, INPUT);
}
// Ignore the initial HIGH state right after Arduino boots.
// Cleaning starts only after a LOW-to-HIGH transition.
volatile bool clean_flag = HIGH;
void loop() {
if ( clean_flag == LOW && digitalRead(PIN_SD_CLEAN) == HIGH ){
Serial.println("Run Roomba with clean mode");
}
clean_flag = digitalRead(PIN_SD_CLEAN);
delay(1000);
}
Sending HTTP Requests from Node-RED to Arduino
A bit rough, but here's the flow:Saying "Alexa, ルンバで掃除して" triggers the leftmost "ルンバ" (Roomba) node.
The middle flow fires first, calling "Roomba reset".
"Roomba reset" is an HTTP request node that sends op=190&CTRL=0x1f&DATA=0x00 to FlashAir, resetting all pins to zero.
For the second and subsequent "Roomba, clean" commands after FlashAir boots, the pins are already zero-reset from the previous call, so this step is effectively a no-op.
To ensure Roomba reset runs first, the upper flow has a 2-second delay.
Ideally, the flow would set a flag after Roomba reset completes and lock execution — but this is the lazy version.
The downside: there's a 2-second gap between saying "Roomba, clean" and it actually starting, which feels slightly off.
After 2 seconds, "Roomba clean" is called.
This sends op=190&CTRL=0x1f&DATA=0x01 to set the SDO pin HIGH.
At this point, the Arduino side enters Roomba control.
Then a 5-second delay fires another zero-reset.
The 5 seconds gives the Arduino enough time to reliably detect the HIGH signal.
For the first delay: if the Arduino misses it, only the very first invocation after boot fails — tolerable.
Keep it short to minimize the lag between the voice command and Roomba starting.
For the second delay: too short and it fails every time; too long has no usability impact, so err on the long side.
At this point, Node-RED can send a 1-bit signal to Arduino via HTTP.
Next up: controlling the Roomba from Arduino.

No comments:
Post a Comment