Christians Webseite        << zurueck        vor >>

Eigene Software auf dem Shelly

Die Shellys sind eine gute Alternative wenn man "mal eben" irgendwas mit WiFi oder BLE aufbauen möchte. Sie haben direkt ihr eigenes Netzteil und ein Relais dabei und sind dadurch unschlagbar kompakt.

UART und Programmieren

Achtung:

Bei den folgenden Arbeiten darf der Shelly NICHT mit dem Stromnetz verbunden sein. Die Klemme/Phase "L" ist direkt mit der Elektronik-Masse verbunden und würde alle angeschlossenen Geräte direkt unter Netzspannung setzen. Die Elektronik mus deshalb aus einen 3.3V oder 12V Labornetzteil versorgt werden.

Das Programmieren überschreibt die Shelly-Software. Dieser Vorgang ist (fast) nicht reversibel. Das Gerät verliert die Shelly-Software und den Zugang zum Shelly-Netzwerk.


Die Kontaktpunkte für die Programmierschnittstelle sind freundlicherweise leicht erreichbar angelegt. Als Programmieradapter ist bereits ein simpler USB-UART mit 2 Tastern ausreichend. Der Betrieb ist halbautomatisch. Zum Starten des ESP-Bootloaders den Taster FLASH gedrückt halten und kurz RESET drücken.

Das Target /die Shelly-Platine darf nur aus genau einer Quelle mit Strom versorgt werden! Entweder aus den 3.3V des UART-Adapters oder über ein externes 3.3V Netzteil oder über den 12V -> 3.3V Wandler des Shelly.
shelly

Auf einigen "etwas besseren" UART-Boards ist auch das RTS-Signal herausgeführt. Mit 2 zusätzlichen Transistoren kann man die auf den üblichen Eval-Boards vorhandene Programmierbeschaltung nachbilden. Die beiden Taster werden dann nicht mehr benötigt:
shelly

Abgesehen von der Möglichkeit zur Programmierung kann man mit angeschlossenem USB-UART-Adapter auch die Monitor-Daten auf der seriellen Schnittstelle (115200,8,1,N) mitlesen. Nach einem normalen Reset meldet sich der Shelly mit den folgenden Daten (gekürzt):

ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x1 (POWERON),boot:0xd (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fcd5820,len:0x11a8
load:0x403cc710,len:0x148c
load:0x403ce710,len:0x28c0
entry 0x403cc71a
boot: Shelly OS loader 1.0.0 (Oct 11 2024 11:45:33 IDF 5.2.1-s2)
boot: chip revision: v0.4
boot.esp32c3: SPI Speed      : 80MHz
boot.esp32c3: SPI Mode       : DIO
boot.esp32c3: SPI Flash Size : 8MB
boot: Enabling RNG early entropy source...
...

Das Bild ändert sich wenn GPIO9/[15]/"FLASH" während des Reset auf Masse liegt. Der Bootloader wird aktiviert und der Programmiermodus gestartet. Das Gerät wartet auf neue Firmware:
ESP-ROM:esp32c3-api1-20210207
Build:Feb  7 2021
rst:0x1 (POWERON),boot:0x5 (DOWNLOAD(USB/UART0/1))
waiting for download

PlatformIO

PlatformIO ist eine der aktuell gängigsten Programmierungebungen. Üblicherweise beginnt man dort mit der Angabe des verwendeten Board-Typs. Dadurch werden alle für die SW-Erstellung wesentlichen Details (z.B. Port-Belegungen und Speichergrössen) gesetzt. Leider sind "die Shellys" dort unbekannt. Eine schnelle und einfache Lösung ist es ein primitives/generisches Board mit dem gleichen Prozessor als Basis zu nehmen und die Abweichungen händisch in der platformio.ini aufzulisten. Für den ESP32-C38F ist das insbesondere die Speicherkonfiguration:

[env:esp32-c3-devkitc-02]
platform = espressif32
board = esp32-c3-devkitc-02
board_upload.flash_size = "8MB"
board_upload.maximum_size = 8388608
board_upload.maximum_ram_size = 512000
board_build.partitions = default_8MB.csv
framework = arduino
monitor_speed = 115200


OTA Update

Wenn man in seinem Programm die WiFi-Funktionen des ESP nutzt dann hat man auch die Option offen die Programmierung darüber zu machen (OverTheAir). Das ist sehr schnell und benötigt keinen zusätzlichen Adapter (abgesehen von der initialen Programmierung).

Eine beispielhafte Anleitung liegt hier:
https://randomnerdtutorials.com/esp8266-ota-updates-with-arduino-ide-over-the-air/

In der platformio.ini müssen das gewünschte Protokoll und die IP-Adresse des ESP-WiFi bekannt gemacht werden:

[env:esp32-c3-devkitc-02]
...
upload_protocol = espota
upload_port = 192.168.178.42
...

Im Hauptprogramm im Shelly muss das passende Include eingebunden und im Setup-Bereich initiiert werden.

main.cpp
...
#include <ArduinoOTA.h>            // Enable SW-Update over WiFi 

uint16_t OTA_Port = 8266;                       
const char* OTA_Hostname ="myesp8266";
...


void setup() {
  ArduinoOTA.setPort(OTA_Port);
  ArduinoOTA.setHostname(OTA_Hostname);

  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH) {
      type = "sketch";
    } else {  // U_FS
      type = "filesystem";
    }
    // NOTE: if updating FS this would be the place to unmount FS using FS.end()
    if (SendSerialDebugActive == 1)      Serial.println("Start updating " + type);
  });
  
  ArduinoOTA.onEnd([]() { if (SendSerialDebugActive == 1)  Serial.println("\nEnd");});
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) 
    { if (SendSerialDebugActive == 1) Serial.printf("Progress: %u%%\r", (progress/(total/100)));}
  );
  ArduinoOTA.onError([](ota_error_t error) 
  {
    if (SendSerialDebugActive == 1) {     
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) {
      Serial.println("Auth Failed");
    } else if (error == OTA_BEGIN_ERROR) {
      Serial.println("Begin Failed");
    } else if (error == OTA_CONNECT_ERROR) {
      Serial.println("Connect Failed");
    } else if (error == OTA_RECEIVE_ERROR) {
      Serial.println("Receive Failed");
    } else if (error == OTA_END_ERROR) {
      Serial.println("End Failed");
    }
  }    
  });

  ArduinoOTA.begin();
...
}

Im "Loop-Bereich" wird regelmässig überprüft ob eine Update-Anforderung anliegt. Der Rest läuft danach vollautomatisch.
	

void loop() {
  ArduinoOTA.handle();  
...