Skip to content
  • MySensors
  • OpenHardware.io
  • Categories
  • Recent
  • Tags
  • Popular
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Brand Logo
  1. Home
  2. My Project
  3. Mysensorized Roomba

Mysensorized Roomba

Scheduled Pinned Locked Moved My Project
18 Posts 9 Posters 7.4k Views 10 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • parachutesjP Offline
    parachutesjP Offline
    parachutesj
    wrote on last edited by
    #1

    Hi,
    just wanted to share my POC:
    We're having a cleaning robot since years. It has built in scheduler and cleans based on that no matter if anyone is home or not.
    I wanted to change that; I do have the status of precence in OpenHAB.
    I have just created a simple mySensor node (based on a light switch) which sends 3 different commands to roomba:
    clean
    dock
    stop

    In openHAB it is just defined as a light switch and I can build up a schedule and if someone is home, it delays the start of cleaning until all are gone.

    ToDo:
    See if I can fit the parts inside of the cleaning robot but for POC I am happy

    alt text

    
    // 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
    
    #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
    
    int rxPin = 3;
    int txPin = 4;
    int ledPin = 13;
    
    SoftwareSerial Roomba(rxPin, txPin);
    
    #define bumpright (sensorbytes[0] & 0x01)
    #define bumpleft  (sensorbytes[0] & 0x02)
    
    void setup() {
      pinMode(ledPin, OUTPUT);   // sets the pins as output
      Serial.begin(115200);
      Roomba.begin(115200);
      digitalWrite(ledPin, HIGH); // say we're alive
      Serial.println ("Sending start command...");
      delay (1000);
      // set up ROI to receive commands
      Roomba.write(128);  // START
      delay(150);
      Serial.println ("Sending Safe Mode command...");
      delay (1000);
      Roomba.write(131);  // CONTROL
      delay(150);
      digitalWrite(ledPin, LOW);  // say we've finished setup
      Serial.println ("Ready to go!");
      delay (5000);
    }
    
    void presentation()
    {
      // Send the sketch version information to the gateway and Controller
      sendSketchInfo("Roomba", "1.0");
    
      for (int sensor = 1, pin = RELAY_1; sensor <= NUMBER_OF_RELAYS; sensor++, pin++) {
        // Register all sensors to gw (they will be created as child devices)
        present(sensor, S_BINARY);
      }
    }
    
    void loop() {
    
    }
    
    
    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();
          }
          else {
            Serial.println("Stopp1");
            halt();
          }
        }
    
        if (mySensor == 1) {
          if (myComand == 1) {
            Serial.println("dock");
            dock();
          }
          else {
            Serial.println("Stopp2");
            halt();
          }
        }
    
      }
    }
    
    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);
    }
    
    

    Cheers,
    SJ

    1 Reply Last reply
    4
    • E Offline
      E Offline
      Eoreh
      wrote on last edited by
      #2

      Thanks for sharing this. You inspire me and i also made a similar solution during this weekend.:smiley:

      0_1480952640095_upload-333fe90d-3b5d-4329-9c6d-12edbdcaa6f0

      roomba620_mod

      But I have a problem. Maybe you could answer or someone from the forum.
      I can not wake up my vacuum (roomba 620) from the state of "suspension" to whose passes automatically after 5 minutes. (all diodes off). Complete code is on end of post.

      0_1480953181292_upload-2cb7e05b-938a-4d19-b41e-fcb7f25e6327

      From old documentation "Roomba_SCI_Spec_Manual.pdf" wake up should looks like this

      ser.setRTS (0)
      time.sleep (0.1)
      ser.setRTS (1)
      time.sleep (2)
      

      I can do it "hardware". It means when my yellow cabel from "DD" during insertion into arduino pinMode(D3, OUTPUT) ... roomba weak up all times.

      But when cable is connect to D3 permanently and try send few times signals like this.

      	digitalWrite(D3, LOW); delay(10); 
      	digitalWrite(D3, HIGHT); delay(2);
      

      It didnt work.

      Of course it wake up when i push button "clean" by finger. Did you have similar problem :question:
      My full code is little more complicate and right now looks like this:

      
      #define MY_BAUD_RATE 115200
      
      // 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 MY_RF24_CHANNEL	76   // brama - kuchnia 
      
      #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 <SoftwareSerial.h>
      #include <MySensors.h>
      
      
      #define NUMBER_OF_FUNCTION 7 
      #define NUMBER_OF_SENSORS 6 
      
      int ddPin = 3;
      int rxPin = 6;
      int txPin = 7;
      
      
      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" };
      
      
      
      //for sensorgetting
      
      #define ROOMBA_READ_TIMEOUT 300
      #define ROOMBA_WAKE_COUNT 10
      
      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 = 60000; // 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
      };
      
      // Initialize messages
      
      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);
      
      		if (myComand == 1) {
      			switch (mySensor) {
      			case 0:
      				Serial.println("Stop");
      				rstop();
      				break;
      			case 1:
      				Serial.println("Dock");
      				rcommand(143);
      				break;
      			case 2:
      				Serial.println("Clean");
      				rcommand(135);
      				break;
      			case 3:
      				Serial.println("Spot");
      				rcommand(134);
      				break;
      			case 4:
      				Serial.println("Max");
      				rcommand(136);
      				break;
      			case 5:
      				Serial.println("Power-Off");
      				rcommand(133);
      				break;
      			case 6:
      				Serial.println("Song");
      				rcommand(141);
      				rsong(0);
      				break;
      			}
      		}
      	}
      }
      
      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("wekup: ");
      	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;
      }
      
      1 Reply Last reply
      1
      • emkaE Offline
        emkaE Offline
        emka
        wrote on last edited by
        #3

        Hi Eoreh

        Maybe problem is in this line:
        digitalWrite(D3, HIGHT); delay(2);

        Did you defined HIGHT symbol?

        Actually I did it this way:

        void WakeUp()
        {
          pinMode(DEVICE_DETECT_PIN, OUTPUT);
          digitalWrite(DEVICE_DETECT_PIN, HIGH);
          delay(1000);
          digitalWrite(DEVICE_DETECT_PIN, LOW);
          delay(1000);
          digitalWrite(DEVICE_DETECT_PIN, HIGH);
        }
        

        and it works flawlessly (Ihave other problem with hanging NRF24, but it is another case)

        1 Reply Last reply
        1
        • E Offline
          E Offline
          Eoreh
          wrote on last edited by Eoreh
          #4

          Hi !
          My bad. I type mistake in post on forum. In code is good version. Of course You have right should be "HIGH"

          But You give me some idea on "problem in line D3" . I plugin my logic analizer (Saleae) and bingo!. In my egz. arduino this port was "broken" and dont give any change signal. I plugin into D5 and all works. :heart_eyes:

          I have one small issue / feature. After play song -> (in my code upper this song is Jingle bell for Chrismas) - roomba dont react on buttons. I think i will change this. Also statistic is very bad write. It's also for rewrite.

          Now i have to do more test, and next make looking good case for "node" on roomba. (cos mother-in-law - kill me :) ). But right now im very happy.

          Thank you @emka for your replay.

          1 Reply Last reply
          0
          • EmielAE Offline
            EmielAE Offline
            EmielA
            wrote on last edited by
            #5

            Hello Eoreh,

            I have a older Roomba and had the same idea to control it by my sensors. I only did a other approach.
            I did not mondify the Roomba with a serial interface and a MySensors node on the Roomba. But I did put a MySensors node on the docking station. And control the clean/spot/max command by imitation of the IR commands with a IR Led on the MySensors Node. And I also detect with my nod if the Roomba is in his dock charging or not. With this dock notification I measure the amount of time the Roomba is on its way before it returns to its dock charging (which is also a indication of the quality of the Roomba battery, short time away is a bad battery). I also measure the room temperature and humidity with the same node.
            If you want to know the code let me know I show you.
            With this approach you don't need to put anything on top of the Roomba which wil get broken off (is my experience) when its e.g. working under the bench.
            See the pictures in the link of this setup: alt text

            1 Reply Last reply
            0
            • E Offline
              E Offline
              Eoreh
              wrote on last edited by
              #6

              HI !.
              @EmielA said:

              With this approach you don't need to put anything on top of the Roomba which wil get broken off (is my experience) when its e.g. working under the bench.

              I have only 1 dock station and many rooms :). My roomba dont going "under the bench" so i dont have experience like yours with sensor on top.

              But will be interested looks for code in your approach so please show it.

              Thank You.

              1 Reply Last reply
              0
              • EmielAE Offline
                EmielAE Offline
                EmielA
                wrote on last edited by
                #7

                Eoreh,

                I used different pieces of code from different projects.and combined them to one sketch. I used some from this project : link text
                And the sketch from the MySensors Relay Actuator. I switch the Node/Relay on for about 10 seconds and then off. In the 10 seconds the IR sends the CLEAN command. With a LDR I detect if the Roomba dock led is on or off. So I detect if the Roomba is on its dock. Here under the code I hope it helps you.

                
                
                
                // Example sketch showing how to control physical relays. 
                // This example will remember relay state even after power failure.
                
                #include <MySensor.h>
                #include <SPI.h>
                #include <IRremote.h>
                #include <DHT.h> 
                #include <Bounce2.h>
                
                #define RELAY_1  3  // Arduino Digital I/O pin number for first relay (second on pin+1 etc)
                #define NUMBER_OF_RELAYS 1 // 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 CHILD_ID_HUM 0
                #define CHILD_ID_TEMP 1
                #define CHILD_ID_DOCK 5
                #define HUMIDITY_SENSOR_DIGITAL_PIN 4 // Temperatuur sensor and Humidity op pin 4 input
                #define DOCK_SENSOR_PIN 5 // Light sensor on pin 5 input
                unsigned long WAIT_TIME = 15000; // Wait time between reads (in milliseconds)
                
                
                IRsend irsend; // hardwired to pin 3; use a transistor to drive the IR LED for maximal range
                
                MySensor gw;
                
                Bounce debouncer = Bounce();
                DHT dht;
                int oldValue=-1; //light sensor
                float lastTemp;
                float lastHum;
                boolean metric = true; 
                MyMessage msgHum(CHILD_ID_HUM, V_HUM);
                MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
                
                // Change to V_LIGHT if you use S_LIGHT in presentation below
                MyMessage msgDock(CHILD_ID_DOCK,V_TRIPPED);
                
                void setup()  
                {   
                  // Initialize library and add callback for incoming messages
                  gw.begin(incomingMessage, AUTO, true);
                   
                  // Setup the DOCK_SENSOR to input
                  pinMode(DOCK_SENSOR_PIN,INPUT);
                  
                  // After setting up the button, setup debouncer
                  debouncer.attach(DOCK_SENSOR_PIN);
                  debouncer.interval(5);
                  
                  dht.setup(HUMIDITY_SENSOR_DIGITAL_PIN); 
                  // Send the sketch version information to the gateway and Controller
                  gw.sendSketchInfo("Temp Humidity and Roomba IR", "1.0");
                
                  // Register all sensors to gw (they will be created as child devices)
                  gw.present(CHILD_ID_HUM, S_HUM);
                  gw.present(CHILD_ID_TEMP, S_TEMP);
                  gw.present(CHILD_ID_DOCK, S_DOOR);
                  
                  metric = gw.getConfig().isMetric;
                
                  // Fetch relay status
                  for (int sensor=2, pin=RELAY_1; sensor<=NUMBER_OF_RELAYS;sensor++, pin++) {
                    // Register all sensors to gw (they will be created as child devices)
                    gw.present(sensor, V_LIGHT);
                    // Then set relay pins in output mode
                    pinMode(pin, OUTPUT);   
                    // Set relay to last known state (using eeprom storage) 
                    digitalWrite(pin, gw.loadState(sensor)?RELAY_ON:RELAY_OFF);
                  }
                }
                
                
                void loop() 
                {
                  // Alway process incoming messages whenever possible
                  
                  {  
                  delay(dht.getMinimumSamplingPeriod());
                
                  float temperature = dht.getTemperature();
                  if (isnan(temperature)) {
                      Serial.println("Failed reading temperature from DHT");
                  } else if (temperature != lastTemp) {
                    lastTemp = temperature;
                    if (!metric) {
                      temperature = dht.toFahrenheit(temperature);
                    }
                    gw.send(msgTemp.set(temperature, 1));
                    Serial.print("T: ");
                    Serial.println(temperature);
                  }
                  
                  float humidity = dht.getHumidity();
                  if (isnan(humidity)) {
                      Serial.println("Failed reading humidity from DHT");
                  } else if (humidity != lastHum) {
                      lastHum = humidity;
                      gw.send(msgHum.set(humidity, 1));
                      Serial.print("H: ");
                      Serial.println(humidity);
                  }
                
                  debouncer.update();
                  // Get the update value
                  int value = debouncer.read();
                 
                  if (value != oldValue) {
                     // Send in the new value
                     gw.send(msgDock.set(value==HIGH ? 1 : 0));
                     oldValue = value;
                  }
                  
                  gw.wait(WAIT_TIME); //sleep a bit
                 }
                }
                
                void incomingMessage(const MyMessage &message) {
                  // We only expect one type of message from controller. But we better check anyway.
                  if (message.type==V_LIGHT) {
                     // Change relay state
                //     digitalWrite(message.sensor-1+RELAY_1, message.getBool()?RELAY_ON:RELAY_OFF);
                     roomba_send(136);  // Send "Clean"   
                     // Store state in eeprom
                     gw.saveState(message.sensor, message.getBool());
                     // Write some debug info
                     Serial.print("Incoming change for sensor:");
                     Serial.print(message.sensor);
                     Serial.print(", New status: ");
                     Serial.println(message.getBool());
                   } 
                }
                void roomba_send(int code)
                {
                  Serial.print("Sending Roomba code ");
                  Serial.print(code);
                  int length = 8;
                  unsigned int raw[length*2];
                  unsigned int one_pulse = 3000;
                  unsigned int one_break = 1000;
                  unsigned int zero_pulse = one_break;
                  unsigned int zero_break = one_pulse;
                
                  int arrayposition = 0;
                  // Serial.println("");
                  for (int counter = length-1; counter >= 0; --counter) {
                    if(code & (1<<counter)) {
                      // Serial.print("1");
                      raw[arrayposition] = one_pulse;
                      raw[arrayposition+1] = one_break;
                    }
                    else {
                      // Serial.print("0");
                      raw[arrayposition] = zero_pulse;
                      raw[arrayposition+1] = zero_break;
                    }
                    arrayposition = arrayposition + 2;
                  }
                  for (int i = 0; i < 3; i++) {
                    irsend.sendRaw(raw, 15, 38);
                    delay(50);
                  }
                  Serial.println("");
                
                  Serial.print("Raw timings:");
                   for (int z=0; z<length*2; z++) {
                   Serial.print(" ");
                   Serial.print(raw[z]);
                   }
                   Serial.print("\n\n");
                }
                
                1 Reply Last reply
                0
                • E Offline
                  E Offline
                  Eawo
                  wrote on last edited by
                  #8

                  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

                  parachutesjP 1 Reply Last reply
                  0
                  • E Eawo

                    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

                    parachutesjP Offline
                    parachutesjP Offline
                    parachutesj
                    wrote on last edited by
                    #9

                    @Eawo I do have a 581 and not 100% sure what has been changed on newer models. Maybe you ask in a roomba forum

                    parachutesjP 1 Reply Last reply
                    0
                    • parachutesjP parachutesj

                      @Eawo I do have a 581 and not 100% sure what has been changed on newer models. Maybe you ask in a roomba forum

                      parachutesjP Offline
                      parachutesjP Offline
                      parachutesj
                      wrote on last edited by
                      #10

                      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.

                      1. 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

                      2. finding a spot was easy:
                        alt text
                        There is enough space on the side of the bin. (In picture, the external charging port was already removed)

                      3. 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" ;-)
                        alt text

                      4. all in place and ready to be closed again
                        alt text

                      5. closed without top plate
                        alt text

                      If it stops working or needs a reset, I only need to unplug and replug

                      M 1 Reply Last reply
                      0
                      • parachutesjP parachutesj

                        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.

                        1. 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

                        2. finding a spot was easy:
                          alt text
                          There is enough space on the side of the bin. (In picture, the external charging port was already removed)

                        3. 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" ;-)
                          alt text

                        4. all in place and ready to be closed again
                          alt text

                        5. closed without top plate
                          alt text

                        If it stops working or needs a reset, I only need to unplug and replug

                        M Offline
                        M Offline
                        moskovskiy82
                        wrote on last edited by moskovskiy82
                        #11

                        @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-CHs

                        But publishing to

                        mys-in/15/2/1/0/3
                        mys-in/15/2/1/0/2

                        with payload 1 doesn't do anything

                        parachutesjP 1 Reply Last reply
                        0
                        • M moskovskiy82

                          @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-CHs

                          But publishing to

                          mys-in/15/2/1/0/3
                          mys-in/15/2/1/0/2

                          with payload 1 doesn't do anything

                          parachutesjP Offline
                          parachutesjP Offline
                          parachutesj
                          wrote on last edited by
                          #12

                          @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;
                          }
                          
                          
                          Z 1 Reply Last reply
                          0
                          • gohanG Offline
                            gohanG Offline
                            gohan
                            Mod
                            wrote on last edited by gohan
                            #13

                            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?

                            parachutesjP 1 Reply Last reply
                            0
                            • gohanG gohan

                              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?

                              parachutesjP Offline
                              parachutesjP Offline
                              parachutesj
                              wrote on last edited by
                              #14

                              @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

                              1 Reply Last reply
                              0
                              • M Offline
                                M Offline
                                moskovskiy82
                                wrote on last edited by
                                #15

                                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...

                                1 Reply Last reply
                                0
                                • gohanG Offline
                                  gohanG Offline
                                  gohan
                                  Mod
                                  wrote on last edited by gohan
                                  #16

                                  Oh man, that sucks a lot. Best luck for your disaster recovery

                                  PS if everything you are touching is failing, be careful when you are going to pee 😂

                                  1 Reply Last reply
                                  1
                                  • parachutesjP parachutesj

                                    @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;
                                    }
                                    
                                    
                                    Z Offline
                                    Z Offline
                                    zen85
                                    wrote on last edited by zen85
                                    #17
                                    // 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?

                                    1 Reply Last reply
                                    0
                                    • B Offline
                                      B Offline
                                      banda banda
                                      Banned
                                      wrote on last edited by mfalkvidd
                                      #18

                                      there is plenty of space for a nano or pro mini. wemos mini or nodemcu should also fit
                                      (spam links removed by moderator)

                                      1 Reply Last reply
                                      0
                                      Reply
                                      • Reply as topic
                                      Log in to reply
                                      • Oldest to Newest
                                      • Newest to Oldest
                                      • Most Votes


                                      10

                                      Online

                                      11.7k

                                      Users

                                      11.2k

                                      Topics

                                      113.1k

                                      Posts


                                      Copyright 2025 TBD   |   Forum Guidelines   |   Privacy Policy   |   Terms of Service
                                      • Login

                                      • Don't have an account? Register

                                      • Login or register to search.
                                      • First post
                                        Last post
                                      0
                                      • MySensors
                                      • OpenHardware.io
                                      • Categories
                                      • Recent
                                      • Tags
                                      • Popular