├── scripts ├── roomba_serial.sh ├── fan_ctrl.sh └── roomba_ctrl.sh ├── IRCapture └── IRCapture.ino ├── IRSender └── IRSender.ino ├── RoombaSerial └── RoombaSerial.ino ├── index.html └── README.md /scripts/roomba_serial.sh: -------------------------------------------------------------------------------- 1 | # This is for Roomba 620 with default settings 2 | # 3 | # wiring (mini-din): 4 | # 5 | # + + 6 | # i o 7 | # g g g 8 | # 9 | # 128 - init sequence 10 | # 131 - safe mode (132 - full mode) 11 | # --- 12 | # 135 - clean 13 | # 134 - spot 14 | # 143 - dock 15 | 16 | param=dock 17 | 18 | if [ ! -z "$1" ]; then 19 | param=$1 20 | fi 21 | 22 | case $param in 23 | clean) 24 | raw=128,131,135 25 | ;; 26 | spot) 27 | raw=128,131,134 28 | ;; 29 | dock) 30 | raw=128,131,143 31 | ;; 32 | power) 33 | raw=128,131,133 34 | ;; 35 | esac 36 | 37 | echo $raw 38 | curl -G http://192.168.1.7 --data-urlencode "raw=$raw" 39 | -------------------------------------------------------------------------------- /IRCapture/IRCapture.ino: -------------------------------------------------------------------------------- 1 | //this sketch will capture remote control buttons on the serial monitor of the Arduino Nano 2 | //connect IR receiver from 37 in 1 sensor kit to pin D2 (signal) and 5V/GND accordingly 3 | //if Arduino Nano configuration doesn't work try building as Duemilanove or Diecimila 4 | 5 | #include //load the IRremote library 6 | 7 | int RECV_PIN = 2; //Set the IRreceiver on pin 2 on the Arduino 8 | IRrecv irrecv(RECV_PIN); //Create an instance for irrecv 9 | decode_results results; //Create an instance to store the collected data in 10 | 11 | void setup() { 12 | Serial.begin(9600); //start the serial monitor 13 | Serial.println("Ready."); //print the line between the quotes 14 | irrecv.enableIRIn(); //start the reciever 15 | } 16 | 17 | void loop() { 18 | if (irrecv.decode(&results)) //this line checks if we received a signal from the IR receiver 19 | { 20 | for (int i = 1; i < results.rawlen; i++) { 21 | Serial.print(results.rawbuf[i]*55); 22 | if (i != results.rawlen-1) 23 | Serial.print(","); 24 | } 25 | Serial.println(); 26 | irrecv.resume(); //receive the next value 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /scripts/fan_ctrl.sh: -------------------------------------------------------------------------------- 1 | # these are F12 codes for the Mystery (Airmate) Fan in raw format, grabbed from the IR remote 2 | # originally they were longer but they just repeat 4 times so they're 4 times shorter here 3 | 4 | param=backlit 5 | 6 | if [ ! -z "$1" ]; then 7 | param=$1 8 | fi 9 | 10 | case $param in 11 | speed) 12 | raw=1330,438,1258,440,410,1288,1260,438,1258,440,384,1312,386,1312,412,1286,386,1312,386,1312,1260,440,384,8106 13 | ;; 14 | shutdown) 15 | raw=1266,438,1260,440,412,1284,1260,438,1260,438,408,1288,414,1286,412,1284,410,1288,386,1312,412,1284,1260 16 | ;; 17 | oscillation) 18 | raw=1328,440,1258,440,384,1314,1260,438,1262,436,384,1314,382,1316,1258,440,386,1310,388,1310,384,1314,384,8038 19 | ;; 20 | mode) 21 | raw=1330,438,1260,438,410,1288,1260,440,1258,440,412,1284,414,1284,412,1286,412,1286,1262,436,410,1286,410,8012 22 | ;; 23 | preset) 24 | raw=1328,440,1260,438,412,1284,1260,440,1260,440,1258,438,412,1286,386,1310,410,1288,388,1310,1258,440,1262,7228 25 | ;; 26 | light) 27 | raw=1330,438,1260,440,410,1286,1258,440,1262,436,1258,438,410,1288,410,1288,414,1284,1260,440,1258,438,414,8008 28 | ;; 29 | esac 30 | 31 | curl -G http://192.168.1.9 --data-urlencode "raw=$raw" 32 | 33 | -------------------------------------------------------------------------------- /scripts/roomba_ctrl.sh: -------------------------------------------------------------------------------- 1 | # these are iRobot Roomba codes 2 | # 3 | # 136 Large / Clean 4 | # 132 Spot 5 | # 143 Seek Dock 6 | 7 | # The remote control IR stream consist of 8 bits each 4ms in duration. According to the paper, 8 | # each bit is started by a 1ms low period. If the value is 0, the pulse stays low for 2 more ms. 9 | # If the pulse goes high for 2ms if the value is 1. The bit is ended by sending a 1ms high burst. 10 | 11 | # Grabbed from a working IR remote with IrScrutinizer (see iRoomba at http://rcoid.de/remotefiles.html) 12 | # clean: Freq=38000Hz[+3036,-981,+981,-3036,+981,-3036,+981,-3036,+3036,-981,+981,-3036,+981,-3036,+981,-50100][][] 13 | # spot: Freq=38000Hz[+3036,-981,+981,-3036,+981,-3036,+981,-3036,+981,-3036,+3036,-981,+981,-3036,+981,-50100][][] 14 | # dock: Freq=38000Hz[+2994,-1021,+1021,-2994,+1021,-2994,+1021,-2994,+2994,-1021,+2994,-1021,+2994,-1021,+2994,-50100][][] 15 | 16 | param=dock 17 | 18 | if [ ! -z "$1" ]; then 19 | param=$1 20 | fi 21 | 22 | case $param in 23 | clean) 24 | raw=3036,981,981,3036,981,3036,981,3036,3036,981,981,3036,981,3036,981,50100 25 | ;; 26 | spot) 27 | raw=3036,981,981,3036,981,3036,981,3036,981,3036,3036,981,981,3036,981,50100 28 | ;; 29 | dock) 30 | raw=2994,1021,1021,2994,1021,2994,1021,2994,2994,1021,2994,1021,2994,1021,2994,50100 31 | ;; 32 | esac 33 | 34 | curl -G http://192.168.1.9 --data-urlencode "raw=$raw" 35 | 36 | -------------------------------------------------------------------------------- /IRSender/IRSender.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "config.h" 5 | 6 | const char* ssid = WIFI_SSID; 7 | const char* password = WIFI_PASSWORD; 8 | 9 | WiFiServer server(80); 10 | 11 | const uint16_t kIrLed = D2; // pin 4 12 | IRsend irsend(kIrLed); 13 | 14 | void setup() { 15 | 16 | irsend.begin(); 17 | 18 | Serial.begin(9600, SERIAL_8N1, SERIAL_TX_ONLY); 19 | delay(10); 20 | 21 | pinMode(kIrLed, OUTPUT); 22 | digitalWrite(kIrLed, 0); 23 | 24 | // Connect to WiFi network 25 | WiFi.mode(WIFI_STA); //you can use different modes, also make sure to change the mode in the rewifi() function 26 | WiFi.begin(ssid, password); 27 | delay(5000); //you can change the delay. Incase of electricy cut-off, when power returns, the router takes about 15sec to make the wifi functional. 28 | server.begin(); 29 | 30 | Serial.println("---"); 31 | Serial.println("Connected."); 32 | Serial.println(WiFi.localIP()); 33 | } 34 | 35 | void rewifi(){ 36 | if(WiFi.status() != WL_CONNECTED) { 37 | WiFi.disconnect(); 38 | WiFi.mode(WIFI_STA); 39 | WiFi.begin(ssid, password); 40 | delay(5000); 41 | } 42 | } 43 | 44 | void loop() { 45 | if(WiFi.status() != WL_CONNECTED) { 46 | rewifi(); 47 | return; 48 | } 49 | 50 | delay(100); 51 | 52 | // Check if a client has connected 53 | WiFiClient client = server.available(); 54 | if (!client) { 55 | return; 56 | } 57 | 58 | // Wait until the client sends some data 59 | while(!client.available()){ 60 | delay(1); 61 | } 62 | 63 | // Read the first line of the request 64 | String request = client.readStringUntil('\r'); 65 | client.flush(); 66 | 67 | // Set LED according to the request 68 | client.println("HTTP/1.1 200 OK"); 69 | client.println("Content-Type: text/html"); 70 | client.println(""); // do not forget this one 71 | client.println(""); 72 | client.println(""); 73 | client.println(""); 74 | client.println("IR Sender"); 75 | client.println("

IR Sender

"); 76 | 77 | client.println("
"); 78 | 79 | client.println(""); 81 | 82 | if (request.indexOf("/?raw=") != -1) { 83 | const int buf_size = 1024; 84 | uint16_t raw[buf_size]; 85 | 86 | int p1 = request.indexOf("=") + 1; 87 | int size = 0; 88 | while (size"); 101 | client.println(""); 102 | client.println(""); 103 | 104 | delay(1); 105 | } 106 | -------------------------------------------------------------------------------- /RoombaSerial/RoombaSerial.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "config.h" 4 | 5 | const char *ssid = WIFI_SSID; 6 | const char *password = WIFI_PASSWORD; 7 | 8 | WiFiServer server(80); 9 | 10 | void setup() { 11 | // The starting baud rate can be changed to 19200 by holding down the Clean button 12 | // while powering on Roomba until you hear a sequence of descending tones 13 | // but you have to disconnect the battery to set it back to 115200 14 | // Using this you can set default 115200 for compatibility (note the 50ms delay) 15 | Serial.begin(115200); 16 | Serial.write(129); // 129 - Baud command 17 | delay(50); 18 | Serial.write(11); // 11 - 115200 19 | delay(50); 20 | 21 | // Connect to WiFi network 22 | WiFi.mode(WIFI_STA); // you can use different modes, also make sure to change 23 | // the mode in the rewifi() function 24 | WiFi.begin(ssid, password); 25 | delay(5000); // you can change the delay. Incase of electricy cut-off, when 26 | // power returns, the router takes about 15sec to make the wifi 27 | // functional. 28 | server.begin(); 29 | } 30 | 31 | void rewifi() { 32 | if (WiFi.status() != WL_CONNECTED) { 33 | WiFi.disconnect(); 34 | WiFi.mode(WIFI_STA); 35 | WiFi.begin(ssid, password); 36 | delay(5000); 37 | } 38 | } 39 | 40 | void loop() { 41 | if (WiFi.status() != WL_CONNECTED) { 42 | rewifi(); 43 | return; 44 | } 45 | 46 | delay(100); 47 | 48 | // Check if a client has connected 49 | WiFiClient client = server.available(); 50 | if (!client) { 51 | return; 52 | } 53 | 54 | // Wait until the client sends some data 55 | while (!client.available()) { 56 | delay(1); 57 | } 58 | 59 | // Read the first line of the request 60 | String request = client.readStringUntil('\r'); 61 | client.flush(); 62 | 63 | client.println("HTTP/1.1 200 OK"); 64 | client.println("Content-Type: text/html"); 65 | client.println(""); // do not forget this one 66 | client.println(""); 67 | client.println(""); 68 | client.println(""); 70 | client.println("Roomba"); 71 | client.println("

Roomba

"); 72 | 73 | client.println("
"); 74 | 75 | client.println( 76 | ""); 79 | 80 | if (request.indexOf("/?raw=") != -1) { 81 | const int buf_size = 1024; 82 | uint8_t raw[buf_size]; 83 | 84 | int p1 = request.indexOf("=") + 1; 85 | int size = 0; 86 | while (size < buf_size) { 87 | int p2 = request.indexOf("%", p1); 88 | int value = 89 | request.substring(p1, p2 == -1 ? request.length() : p2).toInt(); 90 | raw[size++] = value; 91 | if (p2 == -1) 92 | break; 93 | p1 = p2 + 3; // + %2C 94 | } 95 | 96 | for (int i = 0; i < size; i++) { 97 | Serial.write(raw[i]); 98 | delay(50); 99 | } 100 | } 101 | 102 | client.println("
"); 103 | client.println("
"); 104 | client.println(""); 105 | 106 | delay(1); 107 | } 108 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | IR Codes 14 | 15 | 58 | 59 | 60 | 69 |
70 |
71 |
72 |
73 |
76 |
77 |
78 |
79 |
80 | 81 |
82 |
83 |
84 | 85 |
86 |
87 | 274 | 275 | 276 | 277 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Airmate 2 | 3 | A small ESP-12F (ESP8266)-based DIY IR controller originally written for the Airmate Mystery MSF-2414 fan. 4 | 5 | Related IRDB PR: https://github.com/probonopd/irdb/pull/30 6 | 7 | ## Video 8 | 9 | [![](http://img.youtube.com/vi/UZf-yPra764/maxresdefault.jpg)](https://youtu.be/UZf-yPra764) 10 | 11 | ## Hardware 12 | 13 | Solder as on the picture (GPIO15 pulled down to GND, EN pulled up to VCC). 14 | IR LED to GPIO4 (doesn't need a resistor). 15 | Hook up UART (RX to TXD0, TX to RXD0). 16 | To enable flash mode, short GPIO0 to GND during startup. 17 | Build and flash [IRSender.ino](https://github.com/joric/airmate/blob/master/IRSender/IRSender.ino) 18 | (use Arduino IDE setup from [ESP8266-HTTP-IR-Blaster](https://github.com/mdhiggins/ESP8266-HTTP-IR-Blaster)). 19 | Check for the IR Sender address in your Wi-Fi router settings. 20 | 21 | ESP12-F dies from 5V in about a week, so 3.3V regulator (e.g. AMS1117-based) is a must. 22 | You can also use NodeMCU boards, they are a little bit better (have built in UART and 3.3V regulator), but a few times more expensive. 23 | Mind that cheap fans use 15-20 mA condenser PSU's and Wi-Fi modules need 70-300 mA, so 24 | you probably would also need a separate [power supply](https://www.aliexpress.com/wholesale?catId=0&SearchText=3.3v%20transformer%20power%20supply). 25 | 26 | ![](https://i.imgur.com/9JLIY99.jpg) 27 | 28 | ![](https://i.imgur.com/Z3OM5Vm.jpg) 29 | 30 | More pictures: 31 | 32 | * https://imgur.com/a/qzOVUFb 33 | 34 | ## Capturing and sending IR codes 35 | 36 | Use [IRCapture.ino](https://github.com/joric/airmate/blob/master/IRCapture/IRCapture.ino) 37 | and Arduino Nano with VS1838 IR receiver (from 37 in 1 set) hooked up to pin D2 to capture IR codes. 38 | You can also capture and convert IR codes with [IrScrutinizer](https://github.com/bengtmartensson/IrScrutinizer/releases) and Arduino Nano 39 | with [GirsLite 1.0.2](https://github.com/bengtmartensson/AGirs/releases) firmware (hook up IR receiver module to pins D5, GND and 5V, check "Use receive for capture" 40 | in capture settings, export as Arduino RAW). 41 | After you captured and saved the codes you can send them in a comma-separated RAW format via the IR Sender's HTTP interface. 42 | 43 | * https://github.com/bengtmartensson/AGirs/releases (GirsLite 1.0.2 firmwware) 44 | * https://github.com/bengtmartensson/IrScrutinizer/releases (IrScrutinizer) 45 | 46 | ![](https://i.imgur.com/4w0tTFJ.jpg) 47 | 48 | ## IR Protocol 49 | 50 | There are a lot of formats, autodetection and generation of those formats is pretty complicated. 51 | You could try looking into [IrpTransmogrifier](https://github.com/bengtmartensson/IrpTransmogrifier) code 52 | (used in [IrScrutinizer](https://github.com/bengtmartensson/IrScrutinizer)). 53 | This is probably the best detector and generator that reads IRP format notation from the XML definition file 54 | ([IrpProtocols.xml](https://github.com/bengtmartensson/IrpTransmogrifier/blob/master/src/main/resources/IrpProtocols.xml)), 55 | so it's data-driven and not hardcoded as in [decodeir](https://github.com/probonopd/decodeir). 56 | 57 | ### Raw format 58 | 59 | RAW format is pretty simple, it's just a comma-separated sequence of microsecond timings: 60 | 61 | `1330,438,1258,440,410,1288,1260,438,1258,440,384,1312,386,1312,412,1286,386,1312,386,1312,1260,440,384,8106` 62 | 63 | Sequence starts with light on and alternates. Timings also could be explicitly written with alternating signs, where '+' means light on, '-' means light off (order is always the same): 64 | 65 | `+1330 -438 +1258 -440 +410 -1288 +1260 -438 +1258 -440 +384 -1312 +386 -1312 +412 -1286 +386 -1312 +386 -1312 +1260 -440 +384 -8106` 66 | 67 | Bits are usually encoded in value pairs, For F12 bit specification (<1,-3|3,-1>) that means [+1x,-3x]=0, [+3x,-1x]=1. 68 | 69 | `[+1330,-438],[+1258,-440],[+410,-1288],[+1260,-438],[+1258,-440],[+384,-1312],... = [1],[1],[0],[1],[1],[0],...` 70 | 71 | Examples above encode the same 12 bits, 110110000010. For F12 bitfield (D:3,S:1,F:8) that would mean 72 | D=3, S=1, F=65 (110,1,10000010 = 011b,1b,01000001b in LSB notation). 73 | 74 | Carrier frequency (usually 38 Khz) doesn't really affect microsecond timings, every timing consists of many (dozens) 75 | bursts of light at the carrier frequency. It's just a pulse width modulation (PWM) thing, that controls signal brightness and intensity. 76 | 77 | Pronto hex format takes carrier frequency into account, so every value is adjusted as 1000000*value/carrierFrequency. 78 | 79 | ### IRP format notation 80 | 81 | Example (F12 format): **{37.9k,422}<1,-3|3,-1>(D:3,S:1,F:8,-80)*** 82 | 83 | * **{37.9k,422}** General: {carrier frequency, time unit, sequencing rule} 84 | * Carrier Frequency: Hz; e.g. 38.3k; default is 0k (no modulation) 85 | * Time Unit: Integer that can represent durations. Suffix u (default) is microseconds, p is pulses of the carrier. 86 | * Sequencing Rule: lsb|msb; lsb (default) means the least significant bit of a binary form is sent first. 87 | 88 | 89 | * **<1,-3|3,-1>** BitSpec: Rule for the translating bit sequences to duration 90 | * Most IR protocols use only , and the sequence is simply OnDuration,OffDuration. 91 | * Example: NEC uses <1,-1|1,-3>. Durations are given in Time Units specified above. 92 | 93 | 94 | * **(D:3,S:1,F:8,-80)*** Bitfield: B:NumberOfBits:StartingBit (StartingBit is optional. B:6 is equivalent to B:6:0) 95 | * if B=47=01000111, B:2:5 means x10xxxxx. B:2:5=10b=2. ~ is the bitwise complement operator, ~B=10111000. 96 | * A trailing + means send one or more times, a trailing * means send zero or more times. 97 | * No prefix means a flash, a preceeding "-" (minus) means a gap, which trails a signal. 98 | * D means device code, S is subdevice code, F is function 99 | 100 | See http://www.hifi-remote.com/johnsfine/DecodeIR.html for details. 101 | 102 | ## Airmate 103 | 104 | Actual Airmate fan codes in F12 format (see https://github.com/probonopd/irdb/pull/30): 105 | 106 | function name|protocol|device|subdevice|function 107 | --|--|--|--|-- 108 | Oscillation | F12|3|1|9 109 | Timer | F12|3|1|17 110 | Fan mode | F12|3|1|33 111 | Speed | F12|3|1|65 112 | Light | F12|3|1|99 113 | Shutdown | F12|3|1|129 114 | Presets | F12|3|1|195 115 | 116 | For example, "Speed" (protocol=F12, D=3, S=1, F=65) encodes into bits=110110000010 117 | because D=3 (0x011), S=1 (0x01), F=65 (0x01000001) is `[110][1][10000010]` in MSB notation. 118 | 119 | F12 protocol pulse spec is `<1,-3|3,-1>` (ZeroPulseSeq=1,-3; OnePulseSeq=3,-1) means 3x duration followed by 1x duration is bit 1; 1x duration followed by 3x duration is bit 0. 120 | 121 | `[+1330,-438],[+1258,-440],[+410,-1288],[+1260,-438],[+1258,-440],[+384,-1312],... = [1],[1],[0],[1],[1],[0],` 122 | 123 | (Durations are not exact, they were captured from the actual IR remote and decoded backwards but they work.) 124 | 125 | I.e. [+1330,-438] is `<+3,-1>` ("One") because it's about 1320 (3x 440) time units followed by 440 (1x 440) time units. 126 | 127 | LED on/off durations start from on and alternate to the end. All durations are in microseconds. 128 | So the resulting sequence for the "Speed" command is 24 values including stop duration at the end: 129 | 130 | `1330,438,1258,440,410,1288,1260,438,1258,440,384,1312,386,1312,412,1286,386,1312,386,1312,1260,440,384,8106` 131 | 132 | An example online converter to decode captured frequencies into the IRP format: https://joric.github.io/airmate/ 133 | 134 | ## Roomba 135 | 136 | There's also a small project for Roomba 620 (in progress). I tried to utilize IR sender but it 137 | didn't work for some reason, so I just used roomba serial port to send commands (you need it for power anyway). 138 | The serial port is located under the top cover (it can be lifted with bare hands), some kind of 139 | mini-DIN connector (sadly mouse/keyboard PS/2 adapters can't be donors for that, they [won't fit](https://i.imgur.com/9b3O1Kg.jpg)). 140 | I've used 3.3V regulator and the unshielded ESP-12F module, so it fits under the top cover. 141 | 142 | * [RoombaSerial.ino](https://github.com/joric/airmate/blob/master/RoombaSerial/RoombaSerial.ino) (RoombaSerial sketch, mostly works fine, occasionally hangs, probably regulator is overheating) 143 | * [roomba_serial.sh](https://github.com/joric/airmate/blob/master/scripts/roomba_serial.sh) (RoombaSerial control script) 144 | * [roomba_ctrl.sh](https://github.com/joric/airmate/blob/master/scripts/roomba_ctrl.sh) (IRSender script, doesn't work yet) 145 | 146 | IR timings grabbed with IrScrutinizer from a working [RCoid](http://rcoid.de/remotefiles.html) remote. Don't work yet (maybe need mode change). 147 | 148 | Code | Action | Comment / IR sequence 149 | ---|---|--- 150 | 129|baud| (serial only) switch baud rate, 7 for 19200 or 11 for 115200 151 | 128|start|(serial only) switch mode, 131 - safe, 132 - full control over actuators 152 | 134|spot|3036,981,981,3036,981,3036,981,3036,981,3036,3036,981,981,3036,981 153 | 135|clean|3036,981,981,3036,981,3036,981,3036,3036,981,981,3036,981,3036,981 154 | 143|dock|2994,1021,1021,2994,1021,2994,1021,2994,2994,1021,2994,1021,2994,1021,2994 155 | 156 | As for the serial you just send 3 bytes (with 50 ms delay), e.g. 128,131,135 to clean. See [Roomba OI documentation](https://www.irobot.lv/uploaded_files/File/iRobot_Roomba_500_Open_Interface_Spec.pdf). 157 | 158 | ![cover removal](https://i.imgur.com/KYULdfd.png) 159 | 160 | **WARNING! Measured voltage on Roomba 620 serial adapter is 15V on battery, 20V while charging (!) so don't use AMS1117, it's up to 15V max, it will burn and kill your ESP module. Use DC-DC adapter or MC33269.** 161 | 162 | ![esp-12f on roomba](https://i.imgur.com/D0KXeZr.jpg) 163 | 164 | ![esp-01 on roomba](https://i.imgur.com/brmV5nT.jpg) 165 | 166 | There's a very useful video about disassembling and adding WiFi to Roomba: 167 | 168 | * https://youtu.be/t2NgA8qYcFI (shows how to remove the top cover and send commands for roomba) 169 | 170 | Same as a blog post: 171 | 172 | * https://www.crc.id.au/hacking-the-roomba-600 173 | 174 | While the 400 & 500 series are wakeable on the dock, the 600 series is not less you request [firmware upgrade from iRobot](https://robotics.stackexchange.com/questions/15433/create-2-losing-serial-communication-after-toggling-full-to-passive-while-chargi). 175 | It's possible to wake up the 600 series with a different version of sketch that pulses the BRC pin to prevent sleep, but that seems like a better solution. 176 | 177 | * https://github.com/thehookup/MQTT-Roomba-ESP01/blob/master/RoombaESP01_CONFIGURE.ino (500x) 178 | * https://github.com/thehookup/MQTT-Roomba-ESP01/blob/master/Roomba_600_ESP01_CONFIGURE.ino (600x) 179 | 180 | To disable sleep, pulse the BRC pin low periodically before these five minutes expire. Each pulse resets this five minute counter. 181 | Careful! BRC pin is high voltage pin (+5V most of the time), direct connection kills your ESP. 182 | 183 | ![esp pinout](https://i.imgur.com/cO1b62K.jpg) 184 | 185 | ![din pinout](https://i.imgur.com/erDHbxD.png) 186 | 187 | ## References 188 | 189 | * https://github.com/mdhiggins/ESP8266-HTTP-IR-Blaster (ESP8266-based universal learning remote) 190 | * http://www.hifi-remote.com/johnsfine/DecodeIR.html (IRP format whitepaper) 191 | * https://www.techdesign.be/projects/011/011_waves.htm (different IR waveforms) 192 | * https://clearwater.com.au/code/rc5 (Philips RC5 format description) 193 | * https://github.com/probonopd/irdb (large IR codes database, uses original IR formats) 194 | * https://github.com/bengtmartensson/IrScrutinizer (Desktop IR capturing and decoding tool) 195 | * https://github.com/bengtmartensson/AGirs (IrScrutinizer firmware for microcontrollers) 196 | * https://github.com/probonopd/decodeir (command line IR decoding tool, supports pronto and raw) 197 | * https://github.com/johnboiles/esp-roomba-mqtt (esp roomba firmware, uses Roomba library) 198 | * https://www.reddit.com/r/esp8266/comments/flrqjf/roomba_620_esp/ (a Reddit post about roomba) 199 | --------------------------------------------------------------------------------