<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alex Root</title>
    <description>The latest articles on DEV Community by Alex Root (@alex_root_48dfe8afa393367).</description>
    <link>https://dev.to/alex_root_48dfe8afa393367</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3707186%2Fdadafa2f-f9d4-4e10-acab-52898d63fbc1.png</url>
      <title>DEV Community: Alex Root</title>
      <link>https://dev.to/alex_root_48dfe8afa393367</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alex_root_48dfe8afa393367"/>
    <language>en</language>
    <item>
      <title>I Bought a Robot Vacuum, Not a Cloud Spy</title>
      <dc:creator>Alex Root</dc:creator>
      <pubDate>Mon, 12 Jan 2026 19:21:08 +0000</pubDate>
      <link>https://dev.to/alex_root_48dfe8afa393367/i-bought-a-robot-vacuum-not-a-cloud-spy-3978</link>
      <guid>https://dev.to/alex_root_48dfe8afa393367/i-bought-a-robot-vacuum-not-a-cloud-spy-3978</guid>
      <description>&lt;p&gt;Background: Buying a Used Robot&lt;/p&gt;

&lt;p&gt;I didn’t buy this robot vacuum because I urgently needed automated cleaning.&lt;br&gt;
I bought it used — on purpose.&lt;br&gt;
Buying a brand-new device comes with invisible obligations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;warranty&lt;/li&gt;
&lt;li&gt;the mental barrier of “don’t touch it, you might break something”&lt;/li&gt;
&lt;li&gt;the expectation that it must “work off its price” before you can experiment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A new device feels like something you’re borrowing from the manufacturer.&lt;br&gt;
A used device is different.&lt;br&gt;
When hardware is already second-hand, already “imperfect”, you’re free.&lt;br&gt;
You’re not breaking a product — you’re giving it a second life.&lt;br&gt;
This mindset matters a lot for engineering projects.&lt;/p&gt;

&lt;p&gt;Why This Model&lt;/p&gt;

&lt;p&gt;The robot is a Xiaomi Robot Mop Essential.&lt;br&gt;
On the local market inside my country, I paid $25, including delivery.&lt;br&gt;
A new one costs around $125.&lt;br&gt;
For $25 I got:&lt;br&gt;
a fully functional robotic platform&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;motors, sensors, MCU, Wi-Fi&lt;/li&gt;
&lt;li&gt;something i could open without guilt
For $125 I would have gotten the same hardware… plus obligations.
The choice was obvious.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Expectations vs Reality&lt;/p&gt;

&lt;p&gt;To be clear: this robot does its job well.&lt;br&gt;
It drives. It cleans. It creates internal maps and attempts to send them to the cloud.&lt;br&gt;
It does randomly crash into walls — literally.&lt;br&gt;
The robot builds its maps by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bumping into obstacles with its bumper&lt;/li&gt;
&lt;li&gt;calculating position from wheel encoders&lt;/li&gt;
&lt;li&gt;using basic orientation and motion sensors&lt;/li&gt;
&lt;li&gt;No LiDAR. No magic. Just contact, math, and retries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And it works surprisingly well.&lt;br&gt;
The problem was never cleaning quality.&lt;br&gt;
The problem was control.&lt;/p&gt;

&lt;p&gt;Mechanical Issues and Repairs&lt;/p&gt;

&lt;p&gt;This project didn’t start as reverse engineering.&lt;br&gt;
It started with very practical, very physical problems.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Wheel Problem&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The robot was used, and it showed it.&lt;br&gt;
One of the metal bushings had literally destroyed the plastic seat in the wheel.&lt;br&gt;
Instead of a clean fit, the bushing had “eaten” its way through the plastic, leaving a loose, unusable connection.&lt;/p&gt;

&lt;p&gt;My fix was simple but effective:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lubricate the metal bushing.&lt;/li&gt;
&lt;li&gt;Fill the damaged plastic seat with a small tube of cyanoacrylate glue (superglue).&lt;/li&gt;
&lt;li&gt;Wait about 2 hours for full curing.&lt;/li&gt;
&lt;li&gt;Remove the bushing and reinstall.
Result: firm fit, no wobble, wheel restored.
This was my first signal: this thing is repairable.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Wet Surface Traction (Unsolved)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One mechanical issue still remains: traction on wet surfaces.&lt;br&gt;
The robot sometimes slips during mopping.&lt;/p&gt;

&lt;p&gt;Possible reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;insufficient downforce&lt;/li&gt;
&lt;li&gt;poor contact area&lt;/li&gt;
&lt;li&gt;unsuitable wheel tread design&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’m experimenting with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;different TPU filaments&lt;/li&gt;
&lt;li&gt;various 3D-printed tread patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Goal: reliable traction without overloading motors.&lt;br&gt;
This problem is open, and that’s fine — some solutions require iteration.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Wet Cleaning System&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The water nozzles were clogged.&lt;br&gt;
Fix: a thin needle normally used for cleaning 3D-printer nozzles.&lt;/p&gt;

&lt;p&gt;While I was there, I also repaired the small water pump feeding the mop cloth.&lt;br&gt;
No replacement parts, no manuals — just understanding the system.&lt;/p&gt;

&lt;p&gt;From Buttons to Control: Where the Real Problem Started&lt;/p&gt;

&lt;p&gt;After fixing the mechanical issues, the robot worked… almost.&lt;br&gt;
To start cleaning, I still had to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;walk up to it&lt;/li&gt;
&lt;li&gt;press a physical button&lt;/li&gt;
&lt;li&gt;watch it desperately try to connect to Wi-Fi&lt;/li&gt;
&lt;li&gt;and eventually give up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Factory resets didn’t help.&lt;br&gt;
Creating a fresh Mi Home account didn’t help.&lt;br&gt;
Different phones didn’t help.&lt;/p&gt;

&lt;p&gt;The robot wanted Wi-Fi, but it never fully joined.&lt;br&gt;
It built internal maps, sent data to the cloud, and occasionally learned your walls by crashing into them — literally.&lt;br&gt;
At some point, I realized something absurd:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The robot was Wi-Fi enabled, cloud-dependent — and completely unusable without the cloud.&lt;/li&gt;
&lt;li&gt;That was the breaking point.&lt;/li&gt;
&lt;li&gt;I didn’t buy a robot assistant to turn it into a cloud-controlled spy.
I wanted control, not stupid permissions.
So I did what any curious engineer would do: I opened it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inside the Xiaomi Robot Mop Essential&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffi2cwdj4nfctm8rtgvqj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffi2cwdj4nfctm8rtgvqj.png" alt=" " width="550" height="801"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The robot has a very clear internal hierarchy: two brains.&lt;br&gt;
The Main MCU — The Real Robot&lt;br&gt;
The MCU is the heart of the machine. It’s responsible for everything that actually matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Motor control&lt;/li&gt;
&lt;li&gt;Wheel encoders&lt;/li&gt;
&lt;li&gt;Bump sensors&lt;/li&gt;
&lt;li&gt;gyroscope and orientation&lt;/li&gt;
&lt;li&gt;navigation logic&lt;/li&gt;
&lt;li&gt;map building&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwd1jcrvf3qle2xhyxku.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwd1jcrvf3qle2xhyxku.png" alt=" " width="558" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Based on available technical data and analysis of similar Xiaomi robots, this MCU typically features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a 32-bit RISC core for control logic&lt;/li&gt;
&lt;li&gt;a dedicated DSP core for real-time sensor processing&lt;/li&gt;
&lt;li&gt;hardware blocks optimized for navigation and SLAM-like calculations&lt;/li&gt;
&lt;li&gt;external Flash memory for firmware and maps&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The MCU doesn’t care about Wi-Fi. It doesn’t know what a cloud is.&lt;br&gt;
It just wants to clean floors.&lt;br&gt;
The ESP32-WROOM — The Permission Relay&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6mj4r3ng6whxrf4q982e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6mj4r3ng6whxrf4q982e.png" alt=" " width="558" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The ESP32 module’s job is limited but critical:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wi-Fi connectivity&lt;/li&gt;
&lt;li&gt;communication with Xiaomi cloud&lt;/li&gt;
&lt;li&gt;OTA updates&lt;/li&gt;
&lt;li&gt;relaying commands and permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It does not drive motors.&lt;br&gt;
It does not decide where the robot goes.&lt;br&gt;
It mostly acts as a translator and gatekeeper between the cloud and the real robot.&lt;/p&gt;

&lt;p&gt;Listening Instead of Guessing: UART Sniffing&lt;br&gt;
(No photos of how I connected the UARTs from the Orange Pi in MITM mode — I didn’t think they’d be useful at the time.) &lt;br&gt;
To fully understand the system, I connected an Orange Pi RV2 as a man-in-the-middle.&lt;br&gt;
Wiring scheme:&lt;br&gt;
&lt;code&gt;UART5 RX and UART5 TX → MCU&lt;/code&gt;&lt;br&gt;
&lt;code&gt;UART7 TX and UART7 RX → ESP32&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Why not just an ESP32?&lt;/p&gt;

&lt;p&gt;Because I needed three UART ports simultaneously:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCU → ESP32 communication&lt;/li&gt;
&lt;li&gt;ESP32 → MCU communication&lt;/li&gt;
&lt;li&gt;MCU diagnostic port (which I connected later, after freeing UART5 while keeping UART7 dedicated to command transmission)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Orange Pi quietly sniffed all traffic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no injections&lt;/li&gt;
&lt;li&gt;no modifications&lt;/li&gt;
&lt;li&gt;just observation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I read both the diagnostic UART and the official ESP32 UART simultaneously in a single terminal window.&lt;br&gt;
This let me see exactly what happened when I sent commands, and compare the robot’s reactions to the actual status updates.&lt;/p&gt;

&lt;p&gt;I noticed:&lt;br&gt;
The official UART (ESP32 ↔ MCU) reports only two types of errors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Incorrect command (command doesn’t apply to this MCU)&lt;/li&gt;
&lt;li&gt;Wrong command
The diagnostic UART shows much more: motor currents, encoder values, gyro readings, and internal flags.
Example diagnostic output when starting cleaning:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Oc[3]=410  Ic[3]=-43  k p=101  
Oc[3]=363  Ic[3]=-58  
p offsg 213  
gyrod=10029  
sg 181  
crc=15fb  
STL start clean  
default map enable:1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commands sent to the MCU via official UART produce status codes (ok, error…) numerically.&lt;br&gt;
The diagnostic UART shows the robot’s internal response in real time.&lt;br&gt;
What Actually Happens During Startup&lt;br&gt;
Here’s a simplified version of the handshake:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;MCU -&amp;gt; ESP32 : platform_name&lt;/code&gt;&lt;br&gt;
&lt;code&gt;ESP32 -&amp;gt; MCU : ok&lt;/code&gt;&lt;br&gt;
&lt;code&gt;MCU -&amp;gt; ESP32 : firmware_id&lt;/code&gt;&lt;br&gt;
&lt;code&gt;ESP32 -&amp;gt; MCU : ok&lt;/code&gt;&lt;br&gt;
&lt;code&gt;MCU -&amp;gt; ESP32 : mac_device ?&lt;/code&gt;&lt;br&gt;
&lt;code&gt;ESP32 -&amp;gt; MCU : &amp;lt;device_id&amp;gt;&lt;/code&gt;&lt;br&gt;
(success handshake)&lt;br&gt;
&lt;code&gt;MCU -&amp;gt; ESP32 : “Can I request OTA updates?”&lt;/code&gt;&lt;br&gt;
&lt;code&gt;ESP32 -&amp;gt; MCU : ok&lt;/code&gt;&lt;br&gt;
ESP32 can now send commands and listen to response from MCU.&lt;br&gt;
Normal operation begins.&lt;br&gt;
No cryptography. No authentication at this layer. No magic.&lt;/p&gt;

&lt;p&gt;This alone tells you everything:&lt;br&gt;
The MCU asks for permission.&lt;br&gt;
The ESP32 simply relays answers from the cloud.&lt;br&gt;
The robot doesn’t talk to the internet - it asks if it’s allowed to. &lt;br&gt;
Replacing the Cloud with My Own ESP32&lt;/p&gt;

&lt;p&gt;Once it became clear that the MCU was merely asking for permission from the ESP32, the solution was obvious:&lt;br&gt;
If the original ESP32 only replies “ok” to the MCU… then I can reply “ok” too.&lt;br&gt;
Instead of the original chain:&lt;br&gt;
MCU &amp;lt;-&amp;gt; Xiaomi Cloud &amp;lt;-&amp;gt; App&lt;br&gt;
I wanted:&lt;br&gt;
MCU &amp;lt;-&amp;gt; My ESP32 &amp;lt;-&amp;gt; Optional UI / Terminal / Custom Features&lt;br&gt;
Same expectations. Same protocol.&lt;br&gt;
No cloud. No spying.&lt;br&gt;
The factory ESP32 was removed.&lt;br&gt;
My own ESP32 took its place.&lt;br&gt;
Not to fully emulate the cloud — but to get it out of the way.&lt;br&gt;
Now, the MCU can clean floors, build maps, and respond to commands without ever contacting the internet.&lt;/p&gt;

&lt;p&gt;Minimal ESP32 Firmware Architecture.&lt;br&gt;
The firmware I built is modular, with clear responsibilities:&lt;br&gt;
Core system (critical for multitasking and reliability):&lt;br&gt;
dispatcher — task manager&lt;br&gt;
scheduler — time and event scheduling&lt;br&gt;
multicore — leveraging both cores of the ESP32&lt;br&gt;
Hardware &amp;amp; peripherals:&lt;br&gt;
uart — read both diagnostic and official MCU ports simultaneously&lt;br&gt;
ext_flash — work with external SPI flash&lt;br&gt;
display — optional screen for status&lt;br&gt;
buttons &amp;amp; leds — physical interface&lt;br&gt;
Communication &amp;amp; protocols:&lt;br&gt;
miio_miot — simplified implementation of Xiaomi MIOT protocol, enough to relay commands and monitor state&lt;br&gt;
http — web interface for control&lt;br&gt;
auth — authentication for local UI&lt;br&gt;
wifi_mgr — optional Wi-Fi management&lt;br&gt;
Utility &amp;amp; support:&lt;/p&gt;

&lt;p&gt;terminal — serial terminal for debugging&lt;/p&gt;

&lt;p&gt;logger — log all UART traffic and events&lt;br&gt;
sysinfo — system diagnostics&lt;br&gt;
time_sync — keep time in sync&lt;br&gt;
storage — configuration and map persistence&lt;br&gt;
ota — optional firmware updates(ESP32)&lt;/p&gt;

&lt;p&gt;Dual UART Monitoring&lt;br&gt;
One of the key features: reading two UARTs simultaneously.&lt;br&gt;
Official MCU &amp;lt;-&amp;gt; ESP32 UART: status, commands, simple errors&lt;br&gt;
Diagnostic UART: detailed motor currents, encoder readings, gyro data, internal flags&lt;br&gt;
This allowed me to:&lt;br&gt;
verify that commands were correctly interpreted&lt;br&gt;
see detailed internal responses&lt;br&gt;
log all activity for debugging and development&lt;br&gt;
The result is a full local control system, where nothing is hidden behind the cloud.&lt;/p&gt;

&lt;p&gt;Current Status&lt;/p&gt;

&lt;p&gt;At the moment, the ESP32 firmware is still under development. Most of the core system is functional — about 80% complete.&lt;/p&gt;

&lt;p&gt;The modules are in place, dual UART monitoring works, and the dispatcher, scheduler, and multicore systems are running. Basic MIOT-like protocol handling (JSON API) is already implemented.&lt;/p&gt;

&lt;p&gt;Some modules, like OTA, are already integrated, which will make future modifications — including connecting the display and enhancing the interface — much easier to implement.&lt;/p&gt;

&lt;p&gt;Once finished, the robot will have full local control, reliable telemetry, and optional display feedback — all without ever needing the cloud.&lt;/p&gt;

&lt;p&gt;Physical Mods: Replacing Buttons with a “Head”&lt;br&gt;
Original Button Modul&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgn9oi3jo73g9vsd5207y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgn9oi3jo73g9vsd5207y.png" alt="Original button modul" width="720" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My parallel connection to button / uart to esp32 and diagnostic port&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuafzgh4fe5mwghj751v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuafzgh4fe5mwghj751v.png" alt=" " width="540" height="730"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjuf8k6hwua16iedmbvib.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjuf8k6hwua16iedmbvib.png" alt=" " width="720" height="1280"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Temporary installation of buttons and LEDs&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foj6akershtnlfm25bce9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foj6akershtnlfm25bce9.png" alt=" " width="540" height="730"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zmhlho0yuhe1fj77u1k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7zmhlho0yuhe1fj77u1k.png" alt=" " width="540" height="658"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the software and UART control were in place, the next step was physical accessibility.&lt;br&gt;
My NodeMCU board and button cluster couldn’t fit comfortably in the original housing if I wanted to add a display and retain easy access to the interface.&lt;br&gt;
The solution: create a small “tower” or “head” on top of the robot.&lt;br&gt;
What I did&lt;br&gt;
-Relocated the original button block to the new head&lt;br&gt;
-Kept parallel functionality: the robot still responds to factory buttons&lt;br&gt;
-Replaced the original 8 factory LEDs with 2 custom RGB LEDs for clear status indication&lt;br&gt;
Integrated a small display for additional information ( planned for future update)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzi1pwm22iz7dvjozytns.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzi1pwm22iz7dvjozytns.png" alt=" " width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This physical modification achieves several goals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Makes interacting with the robot intuitive even without an app&lt;/li&gt;
&lt;li&gt;Keeps visual status indicators simple and visible&lt;/li&gt;
&lt;li&gt;Allows me to retain full MCU control while optionally using the original buttons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Think of it as a “command tower” — a small cockpit for my robot that gives it a personality and a clear interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vnbnrogy2q1vzba7at9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vnbnrogy2q1vzba7at9.png" alt=" " width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjg3t1u427vb3j9u0r9sh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjg3t1u427vb3j9u0r9sh.png" alt=" " width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What I’d Change if Designing This Robot&lt;/p&gt;

&lt;p&gt;If I were designing the Xiaomi Robot Mop Essential from scratch, here’s what I would do:&lt;br&gt;
-Provide full local control out of the box, without requiring cloud connection&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make cloud telemetry optional and clearly permission-based&lt;/li&gt;
&lt;li&gt;Expose an official UART or API for advanced users&lt;/li&gt;
&lt;li&gt;Allow easy replacement or expansion of LEDs and buttons for custom interfaces&lt;/li&gt;
&lt;li&gt;Include a modular design for attaching displays or additional sensors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This would let engineers and hobbyists:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand what the robot is doing&lt;/li&gt;
&lt;li&gt;Customize behavior safely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid turning a simple cleaning robot into an unintended cloud spy.😁&lt;/p&gt;

</description>
      <category>hardware</category>
      <category>iot</category>
      <category>embedded</category>
      <category>diy</category>
    </item>
  </channel>
</rss>
