Mysensorized Roomba
-
Maybe this is off topic but I'm going to buy a roomba but it is so many versions. Will roomba 615 or 616 do the job or is the newer versions smarter cleaner? I have around 80kvd
@Eawo I do have a 581 and not 100% sure what has been changed on newer models. Maybe you ask in a roomba forum
-
@Eawo I do have a 581 and not 100% sure what has been changed on newer models. Maybe you ask in a roomba forum
All,
I did some updates also thanks to @Eoreh I updated my code a bit. Anyhow, no really news on software side but was able to fit it more or less completely inside of the Roomba.-
I wanted to fit all inside and I think there is enough space but wanted to be able to disable it and thought about a dip-switch somewhere but then decided to have it connected via DIN as before. Means also no soldering on Roomba
-
finding a spot was easy:

There is enough space on the side of the bin. (In picture, the external charging port was already removed) -
I soldered all together and decided to opt for a Nano instead of a Pro Mini due to the lack of 3.3V on board. I know radio might be better powered with a voltage regulator but the reception and reliability is not too important here. Anyhow not experienced any issues so far. I also used the SMD radio to save some extra space.
The voltage regulator has a heat sink mounted which is pointing where the charing port was and is getting some "fresh air" ;-)

-
all in place and ready to be closed again

-
closed without top plate

If it stops working or needs a reset, I only need to unplug and replug
-
-
All,
I did some updates also thanks to @Eoreh I updated my code a bit. Anyhow, no really news on software side but was able to fit it more or less completely inside of the Roomba.-
I wanted to fit all inside and I think there is enough space but wanted to be able to disable it and thought about a dip-switch somewhere but then decided to have it connected via DIN as before. Means also no soldering on Roomba
-
finding a spot was easy:

There is enough space on the side of the bin. (In picture, the external charging port was already removed) -
I soldered all together and decided to opt for a Nano instead of a Pro Mini due to the lack of 3.3V on board. I know radio might be better powered with a voltage regulator but the reception and reliability is not too important here. Anyhow not experienced any issues so far. I also used the SMD radio to save some extra space.
The voltage regulator has a heat sink mounted which is pointing where the charing port was and is getting some "fresh air" ;-)

-
all in place and ready to be closed again

-
closed without top plate

If it stops working or needs a reset, I only need to unplug and replug
@parachutesj Mind posting your finished code?
Also wonder what is the correct MQTT payload to start for example cleaning?
Upon start i see the following
mys-out/15/255/3/0/11 MYS Roomba
mys-out/15/255/3/0/12 2.1
mys-out/15/0/0/0/3 Roomba-Stop
mys-out/15/1/0/0/3 Roomba-Dock
mys-out/15/2/0/0/3 Roomba-Clean
mys-out/15/3/0/0/3 Roomba-Spot
mys-out/15/4/0/0/3 Roomba-Max
mys-out/15/5/0/0/3 Roomba-Power
mys-out/15/6/0/0/3 Roomba-Play
mys-out/15/100/0/0/6 Roomba-Batt-Temp
mys-out/15/101/0/0/39 Roomba-Batt-Proc
mys-out/15/102/0/0/30 Roomba-Batt-Volt
mys-out/15/103/0/0/30 Roomba-Batt-mAH
mys-out/15/104/0/0/36 Roomba-Batt-CHt
mys-out/15/105/0/0/36 Roomba-Batt-CHsBut publishing to
mys-in/15/2/1/0/3
mys-in/15/2/1/0/2with payload 1 doesn't do anything
-
-
@parachutesj Mind posting your finished code?
Also wonder what is the correct MQTT payload to start for example cleaning?
Upon start i see the following
mys-out/15/255/3/0/11 MYS Roomba
mys-out/15/255/3/0/12 2.1
mys-out/15/0/0/0/3 Roomba-Stop
mys-out/15/1/0/0/3 Roomba-Dock
mys-out/15/2/0/0/3 Roomba-Clean
mys-out/15/3/0/0/3 Roomba-Spot
mys-out/15/4/0/0/3 Roomba-Max
mys-out/15/5/0/0/3 Roomba-Power
mys-out/15/6/0/0/3 Roomba-Play
mys-out/15/100/0/0/6 Roomba-Batt-Temp
mys-out/15/101/0/0/39 Roomba-Batt-Proc
mys-out/15/102/0/0/30 Roomba-Batt-Volt
mys-out/15/103/0/0/30 Roomba-Batt-mAH
mys-out/15/104/0/0/36 Roomba-Batt-CHt
mys-out/15/105/0/0/36 Roomba-Batt-CHsBut publishing to
mys-in/15/2/1/0/3
mys-in/15/2/1/0/2with payload 1 doesn't do anything
@moskovskiy82 I did not change too much compared to @EmielA on the code. worked pretty good until I bought a new roomba recently. Haven't tried it on the 980 yet:
// Enable debug prints to serial monitor #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 // Enable repeater functionality for this node #define MY_REPEATER_FEATURE #define CHILD_ID_BATT_TEMP 100 // Id of the 2nd msg1_3 #define CHILD_ID_BATT_PROC 101 // Id of the 2nd msg1_4 #define CHILD_ID_BATT_VOLT 102 // Id of the 2nd msg1_2 #define CHILD_ID_BATT_AH 103 // Id of the 2nd msg2_5 #define CHILD_ID_BATT_CHARGE_TYPE 104 // Id of the 2nd msg1_1 #define CHILD_ID_BATT_CHARGE_SOURCE 105 // Id of the 2nd msg2_2 #include <MySensors.h> #include <SoftwareSerial.h> //#define RELAY_1 5 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) //#define NUMBER_OF_RELAYS 2 // Total number of attached relays //#define RELAY_ON 1 // GPIO value to write to turn on attached relay //#define RELAY_OFF 0 // GPIO value to write to turn off attached relay #define NUMBER_OF_FUNCTION 7 #define NUMBER_OF_SENSORS 6 #define ROOMBA_READ_TIMEOUT 300 #define ROOMBA_WAKE_COUNT 10 int ddPin = 6; int rxPin = 3; int txPin = 4; int ledPin = 13; SoftwareSerial roomba(rxPin, txPin); const char SWITCH_NAMES[NUMBER_OF_FUNCTION][14] = { "Roomba-Stop","Roomba-Dock","Roomba-Clean","Roomba-Spot","Roomba-Max","Roomba-Power","Roomba-Play" }; const char SENSORS_NAMES[NUMBER_OF_SENSORS][24] = { "Roomba-Batt-Temp","Roomba-Batt-Proc","Roomba-Batt-Volt", "Roomba-Batt-mAH" , "Roomba-Batt-CHt" , "Roomba-Batt-CHs" }; uint8_t buf[52]; boolean lowBattery = true; // Acts as a debounce long battery_Current_mAh = 0; long battery_Total_mAh = 0; long battery_percent = 0; boolean DeadBattery = false; boolean FullBattery = true; unsigned long chargingState = 0; long voltage = 0; long temp = 0; long OiMode = 0; long ChargeSource = 0; long sensorfrequency = 300000; // 300000 = 5 min - frequency the sensors are read long lastsensorread = 0; // when were the sensors read the last time unsigned long lastsensorssend = 0; const char ChargeTypes[6][34] = { "Not charging","Reconditioning Charging","Full Charging","Trickle Charging","Waiting","Charging Fault Condition" }; const char OiTypes[4][14] = { "Off","Passive","Safe","Full" }; int packetSizes[58] = { 0,0,0,0,0,0, //1-6 1,1,1,1,1,1,1,1,1,1,1,1, //7-18 2,2, //19-20 1, //21 2,2, //22-23 1, //24 2,2,2,2,2,2,2, //25-31 1, //32 2, //33 1,1,1,1,1, //34-38 2,2,2,2,2,2, //39-44 1, //45 2,2,2,2,2,2, //46-51 1,1, //52-53 2,2,2,2, //54-57 1 //58 }; #define bumpright (sensorbytes[0] & 0x01) #define bumpleft (sensorbytes[0] & 0x02) MyMessage msg1_3(CHILD_ID_BATT_TEMP, V_TEMP); //status of Temperature MyMessage msg1_4(CHILD_ID_BATT_PROC, V_PH); //status of Charge [%] MyMessage msg1_2(CHILD_ID_BATT_VOLT, V_VOLTAGE); //status of Voltage MyMessage msg2_5(CHILD_ID_BATT_AH, V_CURRENT); //status of mAH MyMessage msg1_1(CHILD_ID_BATT_CHARGE_TYPE, V_TEXT); //status of charget type MyMessage msg2_2(CHILD_ID_BATT_CHARGE_SOURCE, V_TEXT); //status of charger source void setup() { pinMode(ddPin, OUTPUT); digitalWrite(ddPin, LOW); Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } roomba.begin(115200); //Serial.println("Sending start command..."); //delay(1000); //// set up ROI to receive commands defsongs(); delay(500); rstop(); Serial.println("Ready to go!"); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Roomba", "1.2"); for (int sensor = 0; sensor < NUMBER_OF_FUNCTION; sensor++) { // Register all sensors to gw (they will be created as child devices) present(sensor, S_BINARY, SWITCH_NAMES[sensor]); delay(100); } present(CHILD_ID_BATT_TEMP, S_TEMP, SENSORS_NAMES[0]); delay(100); present(CHILD_ID_BATT_PROC, S_WATER_QUALITY, SENSORS_NAMES[1]); delay(100); present(CHILD_ID_BATT_VOLT, S_MULTIMETER, SENSORS_NAMES[2]); delay(100); present(CHILD_ID_BATT_AH, S_MULTIMETER, SENSORS_NAMES[3]); delay(100); present(CHILD_ID_BATT_CHARGE_TYPE, S_INFO, SENSORS_NAMES[4]); delay(100); present(CHILD_ID_BATT_CHARGE_SOURCE, S_INFO, SENSORS_NAMES[5]); delay(100); } void loop() { unsigned long now = millis(); if (now > lastsensorssend + sensorfrequency) { readsensors(); lastsensorssend = now; } } void receive(const MyMessage &message) { // We only expect one type of message from controller. But we better check anyway. if (message.type == V_LIGHT) { int mySensor = message.sensor; int myComand = message.getBool(); //Serial.print(message.sensor-1+RELAY_1); if (mySensor == 0) { if (myComand == 1) { Serial.println("Clean"); //clean(); rcommand(135); } else { Serial.println("Stopp1"); //halt(); rstop(); } } if (mySensor == 1) { if (myComand == 1) { Serial.println("dock"); //dock(); rcommand(143); } else { Serial.println("Stopp2"); //halt(); rstop(); } } if (mySensor == 2) { if (myComand == 1) { Serial.println("song"); //dock(); rcommand(141); rsong(0); } else { Serial.println("Stopp2"); //halt(); rstop(); } } } } void halt() { ; roomba.write(131); // SAFE byte j = 0x00; roomba.write(137); roomba.write(j); roomba.write(j); roomba.write(j); roomba.write(j); } void dock() { delay(1000); roomba.write(143); } void clean() { delay(1000); roomba.write(135); } void rstop() { if (rwakeup()) { roomba.write(128); delay(100); roomba.write(131); delay(100); roomba.write(137); delay(100); byte j = 0x00; roomba.write(j); delay(100); roomba.write(j); delay(100); roomba.write(j); delay(100); roomba.write(j); delay(100); roomba.write(128); } } void rsong(int b) { roomba.write(b); delay(100); } void rcommand(int command) { if (rwakeup()) { roomba.write(128); delay(100); roomba.write(131); delay(100); roomba.write(command); } } void play(char note, int rlong) { roomba.write(rnote(note)); delay(10); roomba.write(64 / rlong); delay(10); } bool rwakeup() { bool ret = getSensors(6, buf, 52); Serial.print("wakeup: "); Serial.print(ret); if (!ret) { for (int ii = 1; ii < ROOMBA_WAKE_COUNT; ii++) { for (int jj = 0; jj < 3; jj++) { digitalWrite(ddPin, HIGH); delay(10); digitalWrite(ddPin, LOW); delay(2); } delay(100); roomba.write(128); if (getSensors(6, buf, 52)) { ret = true; break; } Serial.print("-"); } } Serial.println(ret); return ret; } bool getSensors(uint8_t packetID, uint8_t* dest, uint8_t len) { roomba.write(142); delay(100); roomba.write(packetID); delay(100); return getData(dest, len); } bool getData(uint8_t* dest, uint8_t len) { while (len-- > 0) { unsigned long startTime = millis(); while (!roomba.available()) { // Look for a timeout if (millis() > startTime + ROOMBA_READ_TIMEOUT) return false; // Timed out } *dest++ = roomba.read(); } return true; } //for sensorgetting int getPacketSize(int p) { return packetSizes[p - 1]; } int getPacketOffset(int p) { int i = 0; for (int s = 1; s < p; s++) { i += getPacketSize(s); } return i; } //read sensors void readsensors() { if (getSensors(6, buf, 52)) { int off = 0; // Battery Checks off = getPacketOffset(21); chargingState = buf[off + 0]; voltage = buf[off + 2] + 256 * buf[off + 1]; temp = buf[off + 5]; battery_Current_mAh = buf[off + 7] + 256 * buf[off + 6]; battery_Total_mAh = buf[off + 9] + 256 * buf[off + 8]; if (battery_Total_mAh == 0) battery_Total_mAh = 1; int nBatPcent = battery_Current_mAh * 100 / battery_Total_mAh; battery_percent = nBatPcent; //Oi Mode off = getPacketOffset(35); OiMode = buf[off + 0]; //ChargeSource off = getPacketOffset(34); ChargeSource = buf[off + 0]; send(msg1_3.set(temp)); delay(100); send(msg1_4.set(battery_percent)); delay(100); send(msg1_2.set(round(voltage / 10), 1)); delay(100); send(msg2_5.set(battery_Current_mAh)); delay(100); send(msg1_1.set(ChargeTypes[chargingState])); delay(100); send(msg2_2.set(ChargeSource)); delay(100); //send(msg2_5.set(chargingState)); // Send info value to gw //send(msg2_5.set("charging state")); // Send info value to gw //send(msg2_5.set(battery_Total_mAh)); // Send info value to gw //send(msg2_1.set(OiTypes[OiMode])); // Send info value to gw lastsensorread = millis(); } else { send(msg1_1.set("roomba is off")); } // Send info value to gw } void defsongs() { uint8_t zero = 0; roomba.write(128); delay(100); roomba.write(131); delay(100); //[128 131](Start the command stream and change roomba mode to "Safe" mode) roomba.write(140); delay(100); roomba.write(zero); delay(100); //[140 0](Start song definition and define the first song, song number 0) roomba.write(25); //[16](16 notes will be sent for song number 0) play('E', 4); //[76 16](play Mi sound for 1 / 4 seconds) // E play('E', 4); play('E', 2); play('E', 4); play('E', 4); play('E', 2); //[76 32](play Mi sound for 1 / 2 seconds) play('E', 4); play('G', 4); play('C', 4); play('D', 4); play('E', 1); play('F', 4); play('F', 4); play('F', 2); play('F', 4); play('E', 4); play('E', 2); play('E', 4); play('D', 4); play('D', 4); play('E', 4); play('D', 1); delay(100); roomba.write(128); } int rnote(char note) { int command = 31; switch (note) { case 'C': command = 72; break; case 'D': command = 74; break; case 'E': command = 76; break; case 'F': command = 77; break; case 'G': command = 79; break; } return command; } -
Just a question, but wouldn't it be an esp8266 a more compact solution? (Not to mention the quick ota programming) Or the roomba is running 5v serial output?
@gohan ESP is probably a good alternative. but then again you could also buy an after market wireless module for your roomba.
I am not sure about the serial output, but I think it is 5v.but there is plenty of space for a nano or pro mini. wemos mini or nodemcu should also fit
-
ESP is the best solution although couldn't find the code with sensors (only clean/dock commands). I recently made a post on HomeAssistant forum - how wemos D1 fits nicely inside. You only need a buck converter and 4 cat5 wires soldered. And 5V serial output is not such a big problem as you need a voltage divider only on rx pin (didn't put it)
P.S. But then one of those "machine revolt weeks happened" so my esproomba didn't respond and then i burned it down. Next day my RPi3 went down with HA and lots of goodies. And today ESXi...
-
@moskovskiy82 I did not change too much compared to @EmielA on the code. worked pretty good until I bought a new roomba recently. Haven't tried it on the 980 yet:
// Enable debug prints to serial monitor #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 // Enable repeater functionality for this node #define MY_REPEATER_FEATURE #define CHILD_ID_BATT_TEMP 100 // Id of the 2nd msg1_3 #define CHILD_ID_BATT_PROC 101 // Id of the 2nd msg1_4 #define CHILD_ID_BATT_VOLT 102 // Id of the 2nd msg1_2 #define CHILD_ID_BATT_AH 103 // Id of the 2nd msg2_5 #define CHILD_ID_BATT_CHARGE_TYPE 104 // Id of the 2nd msg1_1 #define CHILD_ID_BATT_CHARGE_SOURCE 105 // Id of the 2nd msg2_2 #include <MySensors.h> #include <SoftwareSerial.h> //#define RELAY_1 5 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) //#define NUMBER_OF_RELAYS 2 // Total number of attached relays //#define RELAY_ON 1 // GPIO value to write to turn on attached relay //#define RELAY_OFF 0 // GPIO value to write to turn off attached relay #define NUMBER_OF_FUNCTION 7 #define NUMBER_OF_SENSORS 6 #define ROOMBA_READ_TIMEOUT 300 #define ROOMBA_WAKE_COUNT 10 int ddPin = 6; int rxPin = 3; int txPin = 4; int ledPin = 13; SoftwareSerial roomba(rxPin, txPin); const char SWITCH_NAMES[NUMBER_OF_FUNCTION][14] = { "Roomba-Stop","Roomba-Dock","Roomba-Clean","Roomba-Spot","Roomba-Max","Roomba-Power","Roomba-Play" }; const char SENSORS_NAMES[NUMBER_OF_SENSORS][24] = { "Roomba-Batt-Temp","Roomba-Batt-Proc","Roomba-Batt-Volt", "Roomba-Batt-mAH" , "Roomba-Batt-CHt" , "Roomba-Batt-CHs" }; uint8_t buf[52]; boolean lowBattery = true; // Acts as a debounce long battery_Current_mAh = 0; long battery_Total_mAh = 0; long battery_percent = 0; boolean DeadBattery = false; boolean FullBattery = true; unsigned long chargingState = 0; long voltage = 0; long temp = 0; long OiMode = 0; long ChargeSource = 0; long sensorfrequency = 300000; // 300000 = 5 min - frequency the sensors are read long lastsensorread = 0; // when were the sensors read the last time unsigned long lastsensorssend = 0; const char ChargeTypes[6][34] = { "Not charging","Reconditioning Charging","Full Charging","Trickle Charging","Waiting","Charging Fault Condition" }; const char OiTypes[4][14] = { "Off","Passive","Safe","Full" }; int packetSizes[58] = { 0,0,0,0,0,0, //1-6 1,1,1,1,1,1,1,1,1,1,1,1, //7-18 2,2, //19-20 1, //21 2,2, //22-23 1, //24 2,2,2,2,2,2,2, //25-31 1, //32 2, //33 1,1,1,1,1, //34-38 2,2,2,2,2,2, //39-44 1, //45 2,2,2,2,2,2, //46-51 1,1, //52-53 2,2,2,2, //54-57 1 //58 }; #define bumpright (sensorbytes[0] & 0x01) #define bumpleft (sensorbytes[0] & 0x02) MyMessage msg1_3(CHILD_ID_BATT_TEMP, V_TEMP); //status of Temperature MyMessage msg1_4(CHILD_ID_BATT_PROC, V_PH); //status of Charge [%] MyMessage msg1_2(CHILD_ID_BATT_VOLT, V_VOLTAGE); //status of Voltage MyMessage msg2_5(CHILD_ID_BATT_AH, V_CURRENT); //status of mAH MyMessage msg1_1(CHILD_ID_BATT_CHARGE_TYPE, V_TEXT); //status of charget type MyMessage msg2_2(CHILD_ID_BATT_CHARGE_SOURCE, V_TEXT); //status of charger source void setup() { pinMode(ddPin, OUTPUT); digitalWrite(ddPin, LOW); Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } roomba.begin(115200); //Serial.println("Sending start command..."); //delay(1000); //// set up ROI to receive commands defsongs(); delay(500); rstop(); Serial.println("Ready to go!"); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Roomba", "1.2"); for (int sensor = 0; sensor < NUMBER_OF_FUNCTION; sensor++) { // Register all sensors to gw (they will be created as child devices) present(sensor, S_BINARY, SWITCH_NAMES[sensor]); delay(100); } present(CHILD_ID_BATT_TEMP, S_TEMP, SENSORS_NAMES[0]); delay(100); present(CHILD_ID_BATT_PROC, S_WATER_QUALITY, SENSORS_NAMES[1]); delay(100); present(CHILD_ID_BATT_VOLT, S_MULTIMETER, SENSORS_NAMES[2]); delay(100); present(CHILD_ID_BATT_AH, S_MULTIMETER, SENSORS_NAMES[3]); delay(100); present(CHILD_ID_BATT_CHARGE_TYPE, S_INFO, SENSORS_NAMES[4]); delay(100); present(CHILD_ID_BATT_CHARGE_SOURCE, S_INFO, SENSORS_NAMES[5]); delay(100); } void loop() { unsigned long now = millis(); if (now > lastsensorssend + sensorfrequency) { readsensors(); lastsensorssend = now; } } void receive(const MyMessage &message) { // We only expect one type of message from controller. But we better check anyway. if (message.type == V_LIGHT) { int mySensor = message.sensor; int myComand = message.getBool(); //Serial.print(message.sensor-1+RELAY_1); if (mySensor == 0) { if (myComand == 1) { Serial.println("Clean"); //clean(); rcommand(135); } else { Serial.println("Stopp1"); //halt(); rstop(); } } if (mySensor == 1) { if (myComand == 1) { Serial.println("dock"); //dock(); rcommand(143); } else { Serial.println("Stopp2"); //halt(); rstop(); } } if (mySensor == 2) { if (myComand == 1) { Serial.println("song"); //dock(); rcommand(141); rsong(0); } else { Serial.println("Stopp2"); //halt(); rstop(); } } } } void halt() { ; roomba.write(131); // SAFE byte j = 0x00; roomba.write(137); roomba.write(j); roomba.write(j); roomba.write(j); roomba.write(j); } void dock() { delay(1000); roomba.write(143); } void clean() { delay(1000); roomba.write(135); } void rstop() { if (rwakeup()) { roomba.write(128); delay(100); roomba.write(131); delay(100); roomba.write(137); delay(100); byte j = 0x00; roomba.write(j); delay(100); roomba.write(j); delay(100); roomba.write(j); delay(100); roomba.write(j); delay(100); roomba.write(128); } } void rsong(int b) { roomba.write(b); delay(100); } void rcommand(int command) { if (rwakeup()) { roomba.write(128); delay(100); roomba.write(131); delay(100); roomba.write(command); } } void play(char note, int rlong) { roomba.write(rnote(note)); delay(10); roomba.write(64 / rlong); delay(10); } bool rwakeup() { bool ret = getSensors(6, buf, 52); Serial.print("wakeup: "); Serial.print(ret); if (!ret) { for (int ii = 1; ii < ROOMBA_WAKE_COUNT; ii++) { for (int jj = 0; jj < 3; jj++) { digitalWrite(ddPin, HIGH); delay(10); digitalWrite(ddPin, LOW); delay(2); } delay(100); roomba.write(128); if (getSensors(6, buf, 52)) { ret = true; break; } Serial.print("-"); } } Serial.println(ret); return ret; } bool getSensors(uint8_t packetID, uint8_t* dest, uint8_t len) { roomba.write(142); delay(100); roomba.write(packetID); delay(100); return getData(dest, len); } bool getData(uint8_t* dest, uint8_t len) { while (len-- > 0) { unsigned long startTime = millis(); while (!roomba.available()) { // Look for a timeout if (millis() > startTime + ROOMBA_READ_TIMEOUT) return false; // Timed out } *dest++ = roomba.read(); } return true; } //for sensorgetting int getPacketSize(int p) { return packetSizes[p - 1]; } int getPacketOffset(int p) { int i = 0; for (int s = 1; s < p; s++) { i += getPacketSize(s); } return i; } //read sensors void readsensors() { if (getSensors(6, buf, 52)) { int off = 0; // Battery Checks off = getPacketOffset(21); chargingState = buf[off + 0]; voltage = buf[off + 2] + 256 * buf[off + 1]; temp = buf[off + 5]; battery_Current_mAh = buf[off + 7] + 256 * buf[off + 6]; battery_Total_mAh = buf[off + 9] + 256 * buf[off + 8]; if (battery_Total_mAh == 0) battery_Total_mAh = 1; int nBatPcent = battery_Current_mAh * 100 / battery_Total_mAh; battery_percent = nBatPcent; //Oi Mode off = getPacketOffset(35); OiMode = buf[off + 0]; //ChargeSource off = getPacketOffset(34); ChargeSource = buf[off + 0]; send(msg1_3.set(temp)); delay(100); send(msg1_4.set(battery_percent)); delay(100); send(msg1_2.set(round(voltage / 10), 1)); delay(100); send(msg2_5.set(battery_Current_mAh)); delay(100); send(msg1_1.set(ChargeTypes[chargingState])); delay(100); send(msg2_2.set(ChargeSource)); delay(100); //send(msg2_5.set(chargingState)); // Send info value to gw //send(msg2_5.set("charging state")); // Send info value to gw //send(msg2_5.set(battery_Total_mAh)); // Send info value to gw //send(msg2_1.set(OiTypes[OiMode])); // Send info value to gw lastsensorread = millis(); } else { send(msg1_1.set("roomba is off")); } // Send info value to gw } void defsongs() { uint8_t zero = 0; roomba.write(128); delay(100); roomba.write(131); delay(100); //[128 131](Start the command stream and change roomba mode to "Safe" mode) roomba.write(140); delay(100); roomba.write(zero); delay(100); //[140 0](Start song definition and define the first song, song number 0) roomba.write(25); //[16](16 notes will be sent for song number 0) play('E', 4); //[76 16](play Mi sound for 1 / 4 seconds) // E play('E', 4); play('E', 2); play('E', 4); play('E', 4); play('E', 2); //[76 32](play Mi sound for 1 / 2 seconds) play('E', 4); play('G', 4); play('C', 4); play('D', 4); play('E', 1); play('F', 4); play('F', 4); play('F', 2); play('F', 4); play('E', 4); play('E', 2); play('E', 4); play('D', 4); play('D', 4); play('E', 4); play('D', 1); delay(100); roomba.write(128); } int rnote(char note) { int command = 31; switch (note) { case 'C': command = 72; break; case 'D': command = 74; break; case 'E': command = 76; break; case 'F': command = 77; break; case 'G': command = 79; break; } return command; }// Enable debug prints to serial monitor #define MY_DEBUG // Enable and select radio type attached #define MY_RADIO_NRF24 //#define MY_RADIO_RFM69 // Enable repeater functionality for this node #define MY_REPEATER_FEATURE #define CHILD_ID_BATT_TEMP 100 // Id of the 2nd msg1_3 #define CHILD_ID_BATT_PROC 101 // Id of the 2nd msg1_4 #define CHILD_ID_BATT_VOLT 102 // Id of the 2nd msg1_2 #define CHILD_ID_BATT_AH 103 // Id of the 2nd msg2_5 #define CHILD_ID_BATT_CHARGE_TYPE 104 // Id of the 2nd msg1_1 #define CHILD_ID_BATT_CHARGE_SOURCE 105 // Id of the 2nd msg2_2 #include <MySensors.h> #include <SoftwareSerial.h> //#define RELAY_1 5 // Arduino Digital I/O pin number for first relay (second on pin+1 etc) //#define NUMBER_OF_RELAYS 2 // Total number of attached relays //#define RELAY_ON 1 // GPIO value to write to turn on attached relay //#define RELAY_OFF 0 // GPIO value to write to turn off attached relay #define NUMBER_OF_FUNCTION 7 #define NUMBER_OF_SENSORS 6 #define ROOMBA_READ_TIMEOUT 300 #define ROOMBA_WAKE_COUNT 10 int ddPin = 6; int rxPin = 3; int txPin = 4; int ledPin = 13; SoftwareSerial roomba(rxPin, txPin); const char SWITCH_NAMES[NUMBER_OF_FUNCTION][14] = { "Roomba-Stop","Roomba-Dock","Roomba-Clean","Roomba-Spot","Roomba-Max","Roomba-Power","Roomba-Play" }; const char SENSORS_NAMES[NUMBER_OF_SENSORS][24] = { "Roomba-Batt-Temp","Roomba-Batt-Proc","Roomba-Batt-Volt", "Roomba-Batt-mAH" , "Roomba-Batt-CHt" , "Roomba-Batt-CHs" }; uint8_t buf[52]; boolean lowBattery = true; // Acts as a debounce long battery_Current_mAh = 0; long battery_Total_mAh = 0; long battery_percent = 0; boolean DeadBattery = false; boolean FullBattery = true; unsigned long chargingState = 0; long voltage = 0; long temp = 0; long OiMode = 0; long ChargeSource = 0; long sensorfrequency = 300000; // 300000 = 5 min - frequency the sensors are read long lastsensorread = 0; // when were the sensors read the last time unsigned long lastsensorssend = 0; const char ChargeTypes[6][34] = { "Not charging","Reconditioning Charging","Full Charging","Trickle Charging","Waiting","Charging Fault Condition" }; const char OiTypes[4][14] = { "Off","Passive","Safe","Full" }; int packetSizes[58] = { 0,0,0,0,0,0, //1-6 1,1,1,1,1,1,1,1,1,1,1,1, //7-18 2,2, //19-20 1, //21 2,2, //22-23 1, //24 2,2,2,2,2,2,2, //25-31 1, //32 2, //33 1,1,1,1,1, //34-38 2,2,2,2,2,2, //39-44 1, //45 2,2,2,2,2,2, //46-51 1,1, //52-53 2,2,2,2, //54-57 1 //58 }; #define bumpright (sensorbytes[0] & 0x01) #define bumpleft (sensorbytes[0] & 0x02) MyMessage msg1_3(CHILD_ID_BATT_TEMP, V_TEMP); //status of Temperature MyMessage msg1_4(CHILD_ID_BATT_PROC, V_PH); //status of Charge [%] MyMessage msg1_2(CHILD_ID_BATT_VOLT, V_VOLTAGE); //status of Voltage MyMessage msg2_5(CHILD_ID_BATT_AH, V_CURRENT); //status of mAH MyMessage msg1_1(CHILD_ID_BATT_CHARGE_TYPE, V_TEXT); //status of charget type MyMessage msg2_2(CHILD_ID_BATT_CHARGE_SOURCE, V_TEXT); //status of charger source void setup() { pinMode(ddPin, OUTPUT); digitalWrite(ddPin, LOW); Serial.begin(115200); while (!Serial) { ; // wait for serial port to connect. Needed for native USB port only } roomba.begin(115200); //Serial.println("Sending start command..."); //delay(1000); //// set up ROI to receive commands defsongs(); delay(500); rstop(); Serial.println("Ready to go!"); } void presentation() { // Send the sketch version information to the gateway and Controller sendSketchInfo("Roomba", "1.2"); for (int sensor = 0; sensor < NUMBER_OF_FUNCTION; sensor++) { // Register all sensors to gw (they will be created as child devices) present(sensor, S_BINARY, SWITCH_NAMES[sensor]); delay(100); } present(CHILD_ID_BATT_TEMP, S_TEMP, SENSORS_NAMES[0]); delay(100); present(CHILD_ID_BATT_PROC, S_WATER_QUALITY, SENSORS_NAMES[1]); delay(100); present(CHILD_ID_BATT_VOLT, S_MULTIMETER, SENSORS_NAMES[2]); delay(100); present(CHILD_ID_BATT_AH, S_MULTIMETER, SENSORS_NAMES[3]); delay(100); present(CHILD_ID_BATT_CHARGE_TYPE, S_INFO, SENSORS_NAMES[4]); delay(100); present(CHILD_ID_BATT_CHARGE_SOURCE, S_INFO, SENSORS_NAMES[5]); delay(100); } void loop() { unsigned long now = millis(); if (now > lastsensorssend + sensorfrequency) { readsensors(); lastsensorssend = now; } } void receive(const MyMessage &message) { // We only expect one type of message from controller. But we better check anyway. if (message.type == V_LIGHT) { int mySensor = message.sensor; int myComand = message.getBool(); //Serial.print(message.sensor-1+RELAY_1); if (mySensor == 0) { if (myComand == 1) { Serial.println("Clean"); //clean(); rcommand(135); } else { Serial.println("Stopp1"); //halt(); rstop(); } } if (mySensor == 1) { if (myComand == 1) { Serial.println("dock"); //dock(); rcommand(143); } else { Serial.println("Stopp2"); //halt(); rstop(); } } if (mySensor == 2) { if (myComand == 1) { Serial.println("song"); //dock(); rcommand(141); rsong(0); } else { Serial.println("Stopp2"); //halt(); rstop(); } } } } void halt() { ; roomba.write(131); // SAFE byte j = 0x00; roomba.write(137); roomba.write(j); roomba.write(j); roomba.write(j); roomba.write(j); } void dock() { delay(1000); roomba.write(143); } void clean() { delay(1000); roomba.write(135); } void rstop() { if (rwakeup()) { roomba.write(128); delay(100); roomba.write(131); delay(100); roomba.write(137); delay(100); byte j = 0x00; roomba.write(j); delay(100); roomba.write(j); delay(100); roomba.write(j); delay(100); roomba.write(j); delay(100); roomba.write(128); } } void rsong(int b) { roomba.write(b); delay(100); } void rcommand(int command) { if (rwakeup()) { roomba.write(128); delay(100); roomba.write(131); delay(100); roomba.write(command); } } void play(char note, int rlong) { roomba.write(rnote(note)); delay(10); roomba.write(64 / rlong); delay(10); } bool rwakeup() { bool ret = getSensors(6, buf, 52); Serial.print("wakeup: "); Serial.print(ret); if (!ret) { for (int ii = 1; ii < ROOMBA_WAKE_COUNT; ii++) { for (int jj = 0; jj < 3; jj++) { digitalWrite(ddPin, HIGH); delay(10); digitalWrite(ddPin, LOW); delay(2); } delay(100); roomba.write(128); if (getSensors(6, buf, 52)) { ret = true; break; } Serial.print("-"); } } Serial.println(ret); return ret; } bool getSensors(uint8_t packetID, uint8_t* dest, uint8_t len) { roomba.write(142); delay(100); roomba.write(packetID); delay(100); return getData(dest, len); } bool getData(uint8_t* dest, uint8_t len) { while (len-- > 0) { unsigned long startTime = millis(); while (!roomba.available()) { // Look for a timeout if (millis() > startTime + ROOMBA_READ_TIMEOUT) return false; // Timed out } *dest++ = roomba.read(); } return true; } //for sensorgetting int getPacketSize(int p) { return packetSizes[p - 1]; } int getPacketOffset(int p) { int i = 0; for (int s = 1; s < p; s++) { i += getPacketSize(s); } return i; } //read sensors void readsensors() { if (getSensors(6, buf, 52)) { int off = 0; // Battery Checks off = getPacketOffset(21); chargingState = buf[off + 0]; voltage = buf[off + 2] + 256 * buf[off + 1]; temp = buf[off + 5]; battery_Current_mAh = buf[off + 7] + 256 * buf[off + 6]; battery_Total_mAh = buf[off + 9] + 256 * buf[off + 8]; if (battery_Total_mAh == 0) battery_Total_mAh = 1; int nBatPcent = battery_Current_mAh * 100 / battery_Total_mAh; battery_percent = nBatPcent; //Oi Mode off = getPacketOffset(35); OiMode = buf[off + 0]; //ChargeSource off = getPacketOffset(34); ChargeSource = buf[off + 0]; send(msg1_3.set(temp)); delay(100); send(msg1_4.set(battery_percent)); delay(100); send(msg1_2.set(round(voltage / 10), 1)); delay(100); send(msg2_5.set(battery_Current_mAh)); delay(100); send(msg1_1.set(ChargeTypes[chargingState])); delay(100); send(msg2_2.set(ChargeSource)); delay(100); //send(msg2_5.set(chargingState)); // Send info value to gw //send(msg2_5.set("charging state")); // Send info value to gw //send(msg2_5.set(battery_Total_mAh)); // Send info value to gw //send(msg2_1.set(OiTypes[OiMode])); // Send info value to gw lastsensorread = millis(); } else { send(msg1_1.set("roomba is off")); } // Send info value to gw } void defsongs() { uint8_t zero = 0; roomba.write(128); delay(100); roomba.write(131); delay(100); //[128 131](Start the command stream and change roomba mode to "Safe" mode) roomba.write(140); delay(100); roomba.write(zero); delay(100); //[140 0](Start song definition and define the first song, song number 0) roomba.write(25); //[16](16 notes will be sent for song number 0) play('E', 4); //[76 16](play Mi sound for 1 / 4 seconds) // E play('E', 4); play('E', 2); play('E', 4); play('E', 4); play('E', 2); //[76 32](play Mi sound for 1 / 2 seconds) play('E', 4); play('G', 4); play('C', 4); play('D', 4); play('E', 1); play('F', 4); play('F', 4); play('F', 2); play('F', 4); play('E', 4); play('E', 2); play('E', 4); play('D', 4); play('D', 4); play('E', 4); play('D', 1); delay(100); roomba.write(128); } int rnote(char note) { int command = 31; switch (note) { case 'C': command = 72; break; case 'D': command = 74; break; case 'E': command = 76; break; case 'F': command = 77; break; case 'G': command = 79; break; } return command; }i love this project. i am the owner of a roomba 620 and hooked it up to a arduino-mega. putting "clean()" in the code does what it should and the radiomodules are working fine. but it seems that i dont get values from the sensors and so nothing is showing up in homeassistant... :(
i checked the wiring about 5 times already and since starting for example "clean()" works i think it is a different issue...
did anyone else try this and ran into the same problem?
-
there is plenty of space for a nano or pro mini. wemos mini or nodemcu should also fit
(spam links removed by moderator)