Add wifi to an older roomba

Maybe the issue is related to the dynamic behaviour of the battery, i.e. under load the voltage is not stable as when you measured it., leading the romba logic (a FSM) to an inconsistent state?

Unfortunately, I think I’m gonna have to give up on this project :cry:.
For now I’ll keep my Roomba dumb and probably will buy a new one when I get frustrated with the dumb device.

Trying to get it working on my friend’s Roomba didn’t result in anything either.
So it’s not the battery, it’s not the motherboard. I tried my prototype on breadboard as well, to verify it is not my custom pcb, but no dice.
Maybe one of these combinations already fried my new motherboard :man_shrugging:.

If I really want to try again, I can try with an oscilloscope, which I don’t own now.
Eventually when I take this hobby of pcb design further, I’ll probably get one, but not right now to debug this. (I also need a hot air station and a solder hot plate :sweat_smile:).

Wish you guys all the best of luck to take this topic further.

What about this?

Never give up!

I just updated a 630, 615 and 652 with the UART component moving from MQTT from many, many years ago. My 560 will have to wait for me to print some new brush gears before it gets the same treatment. Many thanks to you @wburgers and @davidecavestro as well as @bremby for the nice controls.

My kids I love the drive control. I’m going to set up some obstacle courses for my kids to race each other through :smile:

2 Likes

Unfortunately that doesn’t work anymore either.
It was weird that it worked the first time and not after I tried the newer battery again.
Also it straight away didn’t work in the Roomba of my friend.
(Maybe I killed his Roomba 602’s OI port now :sweat_smile:, but he doesn’t use that anyway…)

So yeah, I am completely back to square one again on the debugging part and without a scope it’s going to be impossible probably.

I agree with @sreknob’s Never give up! mood
You could also try with any way you find to just send commands and see if the device someway reacts.

@sreknob have you tried using an FTDI on the port to see if the boot message shows up? I was with the same thought about my Roomba, but with the FTDI I figured out that the port was fine

Hello @davidecavestro and @bremby.
Thank you for your work on this so far but i’m confused.
I’m trying to get ESPHome to talk to my Roomba 780.
You two seem to have to most complete setups in this topic but all the bit i’ve put together do not work.

The schema on @davidecavestro’s GitHub repo contains no pin numbers, the schema used by @bremby in this topic has the PNP transistor pins mirrored from the official Roomba docks.

Can either of you provide me with the ESP code as well as the schema used so I have a working set together instead of pieced together parts the I don’t fully understand :smiley:

The pin numbers in the docs match the top view of the Roomba, as stated in the docs.
image

What may be confusing is that if you look at your Roomba from above, you probably have the dust collection bin towards you. This diagram has the front of the Roomba towards you.
The Base of the PNP is connected with pin 4 of the Roomba.
The collector is connected to ground and the emitter is connected to your ESP.
You can find my full schema here.

1 Like

Also got my ESP working again.
Have no clue what changed :thinking:.
Maybe it had something to do with not sending the start command at every startup or with every command from the ESP or something weird.
I don’t know why, but that was never before needed.
I still shorted it though, because the battery was drained that one time and everything got very hot.

4 Likes

and which of the forked codes is running on yours?
Because this is how mine is connected but all i see is NA

HI @PHiAX

here you can find the schema

here the code

substitutions:
  device_name: roomba-control
  friendly_name: "Roomba Control"
  device_platform: ESP8266
  device_board: d1_mini
  device_ip: X.X.X.X
  # BRC pin, RX pin, TX pin, polling interval in milliseconds
  # Pin 3 is labeled rx on the wemos d1 mini, 1 is labeled TX We don't use the hardware UART but we're using its pins!
  init: 'RoombaComponent::instance(D4, id(uart_bus), 10000, true);'
  
esphome:
  includes:
    - ./src/ESPHomeRoombaComponentUARTnew.h

packages:
  wifi: !include common/device_wifi.yaml
  device_base: !include common/device_base_ESP8266.yaml
  home_assistant_api: !include common/device_api.yaml
  sensor_wifi_ip_address: !include common/sensor_wifi_ip_address.yaml  

uart:
  id: uart_bus
  tx_pin: TX
  rx_pin: RX
  baud_rate: 115200
  
# Enable logging
logger:
  hardware_uart: UART1

#Status LED on the built in LED in the wemos d1 mini
#status_led:
#  pin:
#      number: D4
#      inverted: true

#status_led:
#  pin:
#    number: GPIO2
#    inverted: True

custom_component:
  - lambda: |-
      auto r = ${init}
      return {r};

sensor:
#  - platform: adc
#    pin: VCC
#    name: "${friendly_name} VCC Voltage"
  - platform: custom
    lambda: |-
      auto r = ${init}
      return {r->voltageSensor, r->currentSensor, r->batteryChargeSensor, r->batteryCapacitySensor, r->batteryPercentSensor, r->batteryTemperatureSensor, r->driveSpeedSensor};

    sensors:
      - name: "${friendly_name} voltage"
        unit_of_measurement: "V"
        icon: mdi:sine-wave
        accuracy_decimals: 2
        filters:
        - quantile:
            window_size: 7
            send_every: 4
            send_first_at: 3
            quantile: .9
        - multiply: 0.001

      - name: "${friendly_name} current"
        unit_of_measurement: "A"
        icon: mdi:lightning-bolt
        accuracy_decimals: 3
        filters:
        - quantile:
            window_size: 7
            send_every: 4
            send_first_at: 3
            quantile: .9
        - multiply: 0.001

      - name: "${friendly_name} charge"
        unit_of_measurement: "Ah"
        icon: mdi:battery-charging
        accuracy_decimals: 2
        filters:
        - quantile:
            window_size: 7
            send_every: 4
            send_first_at: 3
            quantile: .9
        - multiply: 0.001

      - name: "${friendly_name} capacity"
        unit_of_measurement: "Ah"
        icon: mdi:battery
        accuracy_decimals: 2
        filters:
        - quantile:
            window_size: 7
            send_every: 4
            send_first_at: 3
            quantile: .9
        - multiply: 0.001

      - name: "${friendly_name} battery"
        unit_of_measurement: "%"
        state_class: "measurement"
        device_class: battery
        icon: mdi:battery-outline
        accuracy_decimals: 0
        filters:
        - quantile:
            window_size: 7
            send_every: 4
            send_first_at: 3
            quantile: .9

      - name: "${friendly_name} temperature"
        unit_of_measurement: "°C"
        icon: mdi:thermometer
        accuracy_decimals: 0
        filters:
        - quantile:
            window_size: 7
            send_every: 4
            send_first_at: 3
            quantile: .9

      - name: "${friendly_name} drive speed"
        unit_of_measurement: "mm/s"
        icon: mdi:speedometer
        accuracy_decimals: 0

text_sensor:
  - platform: custom
    lambda: |-
      auto r = ${init}
      return {r->chargingSensor, r->activitySensor, r->oiModeSensor};
    text_sensors:
        - name: "${friendly_name} charging state"
          icon: mdi:battery-charging-high 
        - name: "${friendly_name} activity"
          icon: mdi:robot-vacuum-variant
        - name: "${friendly_name} OI mode"
          icon: mdi:steering

please check the RX and TX, because that is most of the time the issue

this is the code from @davidecavestro that I’m using

davidecavestro/ESPHomeRoombaComponent at uart (github.com)

2 Likes

@wburgers, I’m happy to see that you are back to the game :smiley:

3 Likes

Thank you very much, this combination got things working! Turns out I soldered correctly but my yaml was wrong and the ESPHomeRoombaComponent was also mismatched.
The touch buttons on my unit no longer worked so i was afraid my roomba was e-waste, but now I can just start en stop it with HA :smiley: nice!

1 Like

Hi All -
I was missing my vacuum entities that I used to have with the MQTT vacuum version, so I just created a template vacuum and thought I’d share it back. See below to convert the UART custom component version into a vacuum entity to use in HA.

vacuum:
  - platform: template
    vacuums:
      roomba:
		# Name for your Roomba
        friendly_name: "My WiFi Roomba"
        # Any unique identifier, eg, MAC address (optional)
		unique_id: "ESP-MAC-ADDRESS"
		# Vacuum state template
		# NOTE: need to convert to lower case for template to work and "Lost" is not a valid state.
		# Either change the custom component to use lower case and "idle" for state "lost" or 
		# change the template here to convert case and convert "lost" state to another valid state 
		# (see https://www.home-assistant.io/integrations/vacuum.template/#value_template for possible states)
		# and use one of the below value_templates. FYI, second one is NOT tested!
        value_template: "{{ states('sensor.roomba_activity')|lower }}"
		#value_template: >
		#  {% if is_state('sensor.roomba_activity', 'Cleaning') %}
		#    cleaning
		#  {% elif is_state('sensor.roomba_activity', 'Docked') %}
		#    docked
		#  {% elif is_state('sensor.roomba_activity', 'Lost') %}
		#    idle
		#  {% else %}
		#    error
		#  {% endif %}
        battery_level_template: "{{ states('sensor.roomba_battery')|int }}"
        # Use ESP module availability for vacuum availability, if defined in your ESPHome yaml
        availability_template: "{{ states('binary_sensor.roomba_status') }}"
		# Provide vacuum attributes based on exposed ESPHome sensors
		attribute_templates:
          activity: "{{ states('sensor.roomba_activity') }}"
          oi_mode: "{{ states('sensor.roomba_oi_mode')|title }}"
          charging_state: "{{ states('sensor.roomba_charging_state') }}"
          temperature: "{{ states('sensor.roomba_temperature')|int }} °C"
          voltage: "{{ states('sensor.roomba_voltage')|int }} V"
		# Provide commands for each action to send to ESP
        start:
          service: esphome.roomba_command
          data:
            command: start
        pause:
          service: esphome.roomba_command
          data:
            command: sleep
        stop:
          service: esphome.roomba_command
          data:
            command: stop
        return_to_base:
          service: esphome.roomba_command
          data:
            command: dock
        clean_spot:
          service: esphome.roomba_command
          data:
            command: spot
        locate:
          service: esphome.roomba_command
          data:
            command: locate

Also, I was wondering - anyone else having trouble with a vacuum returning to “passive”? I have one that is continually reporting “safe” mode. I figure I have a serial communication error that is contributing to the problem and need to turn debug mode back on to track it down, but wondering if anyone else has experienced the same issue.

Additionally, is there any easy way to add the serial setup with the Roomba to negotiate the baud rate in the custom UART component? I’m just wondering if my terrible soldering or cheap transistors might be happier at 57600, which could be related to my OI mode problem, but maybe not :slight_smile:

3 Likes

Hi @sreknob,

can you please share your full yaml config?

@bremby in case you have issues with the vacuum config from @sreknob the issue is related to a mix of tab and spaces in indentations

1 Like

Hi,

I have an old Roomba 651 that I tried to smartify as my first attempt at an ESPHome project (and my first soldering attempt in 15 years). I followed this schema:

Now I have it partly working as I can control the Roomba from HA. But there are two issues that I hope somebody can help me with:

  1. The sensors in HA are always reporting ‘Unknown’, this corresponds to the error message constantly thrown in ESPHome logs:

[D][custom:079]: Could not get sensor values from serial

Am I correct to assume I probably messed something up when connecting the transistor? I did solder its ground wire and D1 Mini’s ground wire to different DC-DC converters OUT- holes - I assumed it wouldn’t change the logical schema?

  1. I enabled the lazy wakeup hack in RoombaComponent’s constructor, but the commands only work for a minute or so after pushing the physical Clean button. Is there something I may be missing or should I assume the 651 just acts differently and I should start looking at using a relay to mimic the clean button press?

For people trying to add their ESP inside the Roomba and need solder points instead of using the DIN connector: (used on a Roomba 560; don’t trust me, always measure continuity with a multimeter !)

connections

I dropped the 5V with a HT7833 and a couple of caps and connected it to an ESP-01S inside the barrel connector cavity. Don’t do like me and route the cables next to the mainboard (see photo) as the plastic cover will go inside there. I had to re-route them to the left later on…

As a side note, if you don’t want to buy C batteries, you can use another HT7833 (or a similar voltage regulator) to get a lighthouse on USB. In my case I had an old PCB from some cheap earbuds connected to a Lithium battery (300mAh) and added a ON/OFF switch, but it could obviously be a lot simpler.

lighthouse1

As far as code goes, it seems everybody is going straight for the full-on custom ESPHome component, but if you want to test the connections, you don’t need much if you use UART:

uart:
  id: uart_bus
  baud_rate: 115200
  tx_pin: TX
  rx_pin: RX
  debug:

# BRC pin (power default off)
output:
  - platform: gpio
    id: brc
    pin:
      number: GPIO0
      mode:
        output: true
      inverted: true

# Wakeup script (toggle BRC pin)
script:
  - id: wakeup
    then:
      - output.turn_on: brc
      - delay: 100ms
      - output.turn_off: brc
      - delay: 100ms

api:
  # Insert your default API configuration like password, encryption etc.
  services:
    - service: command
      variables:
        cmd: string
      then:
        - logger.log:
            format: "Command received: %s"
            args: [ 'cmd.c_str()' ]
            level: INFO
            tag: roomba

        - if: # Toggle BRC pin (wake up from sleep)
            condition:
              lambda: 'return cmd == "wakeup";'
            then:
              - script.execute: wakeup
              - script.wait: wakeup
              - uart.write: [128, 131]

        - if: # POWER (sleep)
            condition:
              lambda: 'return cmd == "sleep";'
            then:
              - uart.write: [133]
        - if: # SPOT
            condition:
              lambda: 'return cmd == "spot";'
            then:
              - uart.write: [134]
        - if: # CLEAN
            condition:
              lambda: 'return cmd == "clean";'
            then:
              - uart.write: [135]
        - if: # MAX
            condition:
              lambda: 'return cmd == "max";'
            then:
              - uart.write: [136]
        - if: # SEEK DOCK
            condition:
              lambda: 'return cmd == "dock";'
            then:
              - uart.write: [143]

        - if: # Sensors (get individual/group/all sensor data)
            condition:
              lambda: 'return cmd == "sensors_all";'
            then:
              - uart.write: [142,100]
        - if: # Query list (get data from specified sensors/groups)
            condition:
              lambda: 'return cmd == "sensors_battery";'
            then:
              - uart.write: [149, 6, 21,22,23,24,25,26]

        - if: # Song (record), Play (a recorded song number | only SAFE or FULL mode)
            condition:
              lambda: 'return cmd == "locate";'
            then:
              - uart.write: [140,1, 4, 62,12, 66,12, 69,12, 74,36]
              - uart.write: [131, 141,1]

        - if: # Digit LEDs ASCII (write to clock display | only SAFE or FULL mode)
            condition:
              lambda: 'return cmd == "display";'
            then:
              - uart.write: [131, 164, 72,69,76,80] # Writes HELP

I decided I didn’t really need the sensors and kept just the code to command it on a schedule with HA (with some exceptions built in obviously, it’s never “really” simple ;-)).

Edit: with my code you can test the sensors to see if the Roomba responds, but if you want (all) the sensors in HA you need a custom component…
(Oh, and substitute the GPIO pin you actually use for the BRC connection, unless you use GPIO0 obviously)

Hi,

regarding your first point

  1. The sensors in HA are always reporting ‘Unknown’, this corresponds to the error message constantly thrown in ESPHome logs:

mine is taking some seconds after a reboot or re-initialization before pass from Unknown to some data, can you try to keep the Roomba on the charging station and see if you start to get info?