OctoPrint / OctoPrint-FirmwareUpdater

OctoPrint plugin for flashing pre-compiled firmware images to a 3D printer.
https://plugins.octoprint.org/plugins/firmwareupdater/
GNU Affero General Public License v3.0
351 stars 76 forks source link

FEATURE REQUEST: add ESP32 support #329

Closed ghost closed 1 year ago

ghost commented 1 year ago

As there are some boards out there which use the ESP32, it would be nice to add functionality for updating the firmware on that chip.

Of course it is possible to flash the ESP32 OTA, but the WiFi implementation on it is, well, flaky. It would be nice to have a second option for flashing it over the air.

benlye commented 1 year ago

Can you give an example of a specific ESP32 board you want supported? Can you provide a board for development and testing?

ghost commented 1 year ago

Currently I am using a MKS Tinybee with a ESP32-WROOM-32U with following specs: Flash: 8192K, RAM: 520K, Frequency: 240MHz.

I have a few ESP32-WROOM-32 dev modules laying around. As the flashing would be the exact same process as with a printer controller (esptool over USB serial), I could provide one of them.

Here you can find the documentation for the espressif equivalent of avrdude: https://nodemcu.readthedocs.io/en/latest/flash/

A typical command for the ESP32 would look as following:

esptool.py --port /dev/ttyUSB0 write_flash -fm dio 0x00000 <firmware>.bin
benlye commented 1 year ago

I'll take a look. I have some NodeMCU ESP32 devices so I can start with those. Should be pretty easy.

ghost commented 1 year ago

Thanks a lot!

benlye commented 1 year ago

Can you give v1.14.0b1 a try?

You need to switch the plugin to the Development release channel to try the build. You will also need to make sure that esptool.py is installed and working on your host. If you have OctoPrint running in a virtual environment, you need to make sure you install it in that venv.

ghost commented 1 year ago

Currently it bricks the board. I've also tried to set -fm qui in the command line options, with no success.

As flashing from PlatformIO works fine, I'm investigating further

benlye commented 1 year ago

Perhaps it needs a different flash address? Does PlatformIO use esptool.py? If so, can you get (and try) the complete command line that it uses?

benlye commented 1 year ago

I did all my testing with an ESP8266. I've ordered an ESP32 WROOM-32 but I wouldn't have thought it would make much difference as the tool seems to work the same no matter what type of chip it's flashing. I was able to flash different sketches to my ESP8266 without any problems.

ghost commented 1 year ago

I'm on it, I've already tried if strace would give me something, but it is of course quiet as soon as esptool is called. Note: Same behavior occurs from the command line when invoked via esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash -z 0x0 firmware.bin.

The output of pio run suggests that different stuff gets written to various adresses.

ghost commented 1 year ago

Got it. It also writes bootloader, etc:

AVAILABLE: esp-prog, espota, esptool, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa
CURRENT: upload_protocol = esptool
MethodWrapper(["upload"], [".pio/build/mks_tinybee/firmware.bin"])
Auto-detected: /dev/ttyUSB0
"/usr/bin/python" "/home/mashuptwice/.platformio/packages/tool-esptoolpy@1.30000.201119/esptool.py" --chip esp32 --port "/dev/ttyUSB0" --baud 921600 --before default_reset --after hard_reset write_flash -z --flash_mode dio --flash_freq 40m --flash_size detect 0x1000 /home/mashuptwice/.platformio/packages/framework-arduinoespressif32/tools/sdk/bin/bootloader_dio_40m.bin 0x8000 /home/mashuptwice/3DPrint/mks_firmware/.pio/build/mks_tinybee/partitions.bin 0xe000 /home/mashuptwice/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin 0x10000 .pio/build/mks_tinybee/firmware.bin
esptool.py v3.0
Serial port /dev/ttyUSB0
Connecting.......
ghost commented 1 year ago

Tested setting the address for writing to 0x10000 in command line and it works!

benlye commented 1 year ago

Tested setting the address for writing to 0x10000 in command line and it works!

Did you need to specify a flash mode as well? I can easily change the default address to 0x10000, and add the flash mode switch if needed.

ghost commented 1 year ago

I've used esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash -z 0x10000 firmware.bin

I couldn't test it in the plugin, as there is some overflow happening when entering the flash address: Screenshot_20221110_233046

Did you need to specify a flash mode as well?

Usually the flash mode should be detected automatically, so I think adding a switch for cases when it is not, should also include an "AUTO" setting. esptool.py --chip esp32 --port /dev/ttyUSB0 write_flash -z 0x10000 firmware.bin

benlye commented 1 year ago

I'll figure out how to stop the GUI munging the flash address, but the doc does say it can be either hex or decimal, so 65536 should work (same as 0x10000) so it may just work as-is.

We can make the default command line whatever you like and add parameters for anything that might commonly need to be changed.

ghost commented 1 year ago

I'll test it tomorrow, the beeping that occurs on a bad flash is waking the whole house.

A few thougts:

Nothing more to add yet, except for a big thanks for implementing the changes that fast! This was definitely the fastest on any OSS project I've ever seen! Any way to support this project further?

benlye commented 1 year ago

I've fixed the hex conversion thing - it was a bug in the settings handler. I'll add a baudrate dropdown option and will do another beta release tomorrow for you to test.

It looks like it should be good if we make this the default command line: {esptool} -p {port} -c {chip} -b {baud} --before default_reset --after hard_reset -fm dio write_flash -z {address} {firmware}

With {chip} defaulting to esp32 and {baud} defaulting to 921600.

benlye commented 1 year ago

Give v1.14.0b2 a try when you have a chance.

ghost commented 1 year ago

First it exited with status 2, so I've removed the chip definition and firmware write mode from the command line:

{esptool} -p {port} write_flash {address} {firmware}

That did the trick. It is now flashing successfully! After having a look into the plugin settings afterwards, it seems that I had set the chip type to capitalized ESP32 from the last version. It needed to be lowercase to work correctly.

Maybe it would be best to ditch the chip selection and flash mode flags by default, and add a footnote to set them if experiencing problems. It could help with compatibility of other boards, and esptool should be able to auto detect the chip by itself just fine.

benlye commented 1 year ago

I got an ESP32 dev board yesterday and have been able to flash it many times using the default command and settings but I'll force the chip string to lower case and change it back to auto as the default.

I probably should have mentioned that it would be a good idea to reset your settings before testing the new version.

ghost commented 1 year ago

Well, that should be fine i think.

With the wrong board set, I've only got esptools exit status shown, it might make sense for less tech iterate users to include more of the error message, as esptool usually also reports 'unknown board' or something.

benlye commented 1 year ago

With the wrong board set, I've only got esptools exit status shown, it might make sense for less tech iterate users to include more of the error message, as esptool usually also reports 'unknown board' or something.

Did you have an actual wrong board or was it when you had the board set in upper case? I am handling the actual wrong board with a more specific error message.

ghost commented 1 year ago

Thanks for implementing this so fast!

github-actions[bot] commented 1 year ago

This issue has been automatically locked because there was no further activity after it was closed. Please open a new issue for any related problems.