Context
Many years ago I bought a “bargain” bluetooth scale.
I wanted a way to automatically log my weight, and the Xiaomi equivalent was more than twice as expensive at the time.
The problem is that it came with a very basic and somewhat sketchy software that required signing up, and none of the typical apps (openscale, gadgetbridge…) supported it.
I looked at how to reverse engineer it, but I did not have much time back then, and I wrote it off as a “future project”.
Luckily, it had a screen, so I’ve been using it as a regular scale.
I did not even bother to check the body composition metrics, because I got a very depressing reading of 35% body fat.
Flash forward to today, when I decided to finally work on it.
In addition to trying nrfConnect, I installed the app to see the actual values..
It turns out the composition data was completely off!!
When a reading starts, the app needs to tell the scale some basic data about you (age, height, sex).
Unfortunately, there is no way (that I know of) to set a default user, so when the phone is not connected, it goes back to the wildly inaccurate reading.
So, I decided to connect one of my idle ESP32 boards to it, to interface with the scale through bluetooth (sending the right user data) and logging the results somewhere through WiFi.
The problem
Installing the firmware was not too difficult, after I got the board to properly register.
1
2
3
4
5
6
| โฏ uv tool run esptool.py --port /dev/ttyACM4 erase-flash
...
Chip type: ESP32-S3 (QFN56) (revision v0.2)
Features: Wi-Fi, BT 5 (LE), Dual Core + LP Core, 240MHz, Embedded Flash 4MB (XMC), Embedded PSRAM 2MB (AP_3v3)
...
โฏ uv tool run esptool.py --port /dev/ttyACM4 --baud 460800 write_flash 0 ESP32_GENERIC_S3-20250415-v1.25.0.bin
|
But then, I kept getting this error on boot: OSError: (-24579, 'ESP_ERR_FLASH_NOT_INITIALISED')
.
And I could not copy any files or install any packages.
After some research, I narrowed the possibilities to:
- A wrong partition table, most likely due to the fact that my board only has 4MB of flash.
- Using an unsupported type of PSRAM (less likely)
The solution
At this point, I could either try to compile the firmware with a custom partition (kind of tedious), or I could use the wonderful mp-image-tool-esp32 tool to check existing firmwares and modify partition sizes.
I confirmed my suspicion:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| โฏ uv tool run mp-image-tool-esp32 ~/Downloads/ESP32_GENERIC_S3-20250415-v1.25.0.bin
Running mp-image-tool-esp32 v0.1.1 (Python 3.12.11).
Opening /home/j/Downloads/ESP32_GENERIC_S3-20250415-v1.25.0.bin...
Found esp32s3 firmware file (8MB flash).
Partition table (flash size: 8MB):
โญโโโโโโโโโโโฌโโโโโโโฌโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโฌโโโโโโโโโโโโฎ
โ Name โ Type โ SubType โ Offset โ Size โ End โ Flags โ โ
โโโโโโโโโโโโผโโโโโโโผโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโผโโโโโโโโโโโโค
โ nvs โ data โ nvs โ 0x9000 โ 0x6000 โ 0xf000 โ 0x0 โ (24.0 kB) โ
โ phy_init โ data โ phy โ 0xf000 โ 0x1000 โ 0x10000 โ 0x0 โ (4.0 kB) โ
โ factory โ app โ factory โ 0x10000 โ 0x1f0000 โ 0x200000 โ 0x0 โ (1.9 MB) โ
โ vfs โ data โ fat โ 0x200000 โ 0x600000 โ 0x800000 โ 0x0 โ (6.0 MB) โ
โฐโโโโโโโโโโโดโโโโโโโดโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโดโโโโโโโโโโโโฏ
Micropython app fills 79.3% of factory partition (410 kB free)
|
1
2
| โฏ uv tool run mp-image-tool-esp32 -f 4MB --resize vfs=2MB ESP32_GENERIC_S3-20250415-v1.25.0.bin
โฏ uv tool run esptool.py --port /dev/ttyACM4 --baud 460800 write_flash 0 ESP32_GENERIC_S3-20250415-v1.25.0-4MB-resize=vfs=2097152.bin
|
After that, I was able to install new packages with mpremote
and mip
:
1
| uv tool run mpremote mip install aioble
|
We can check that we are fully utilizing the 2MB of PSRAM:
1
2
| โฏ uv tool run mpremote exec 'import gc;print(gc.mem_free(), "bytes")'
2061456 bytes
|
If you see much less than that, you are probably using the wrong variant (try SPIRAM_OCT
).