Skip to content

TIT8/shelly_esp32_button_espidf

Repository files navigation

Native ESP code for Shelly's toggle button

ESP-IDF version of the Arduino repo: https://github.com/TIT8/shelly_button_esp32_arduino

Description

A push button is connected to the ESP32 microcontroller. When its state changes, it will trigger an MQTT publish which will toggle the light controlled by a Shelly plus 1 relay.

❗Keep in mind that you should either use a capacitor (better) or providing some delay in the code to debounce the push button and filter out spurious changes. Pull down the push button via a 10k resistor, if you don't set the pull-up mode on the input pin.


Schematich


❗ The software and the hardware (watchdog timer) can already handle reconnections if something goes wrong.

Prerequisities

  1. Look at the PlatformIO documentation to start.
  2. If you already have the ESP-IDF installed (via Platformio or not), all the dependencies come with it, so you won't import anything. Simply build and upload 💪.
  3. An ESP32 board (with IDF, also other versions like S2/S3/C3).
  4. Remember to add the CP2102 driver to connect old ESP32 development board (with CP2102 as USB-UART bridge).
  5. How to setup a local broker in a Docker container.

ESP-IDF vs Arduino

Features ESP-IDF Arduino
Dependencies All included in the official SDK
  • ArduinoJson
  • Pubsubclient
  • ArduinoOta
Clear advantage Extreme control on execution contexts Portability of code to other Arduino compatible board
JSON response Handled via cJSON (well maintained) Handled via ArduinoJson (wrapper of cJSON)
MQTT features
  • Well maintained library
  • QoS 0,1,2 on publish and subscribe
  • Ability to have multiple client
  • MQTT over Websocket and SSL/TLS
  • MQTT 5 also available
  • Unmaintained library 1
  • QoS 0 on publish and QoS 0, 1 on subscribe
  • MQTT 3 only
  • MQTT over Websocket and SSL/TLS not available
  • Work on board of different manufacturers
GPIO pin handling Same as Arduino, but more control on interrupt ISR and FreeRTOS queue Easieast to start, you know... ❤️
OTA updates Great flexibility, but difficult to start without strong motivation Less flexibility, but easy to get the job done
Memory footprint
  • RAM 27.1 KB
  • Flash 701.4 KB 2
  • RAM 34.6 KB
  • Flash 637.8 KB
RTOS Yes, you see clearly how it works 3 Yes, but hidden
Hardware configurations Easy via the menu config (like STM32CubeMX, less graphic though) You have to explicitly write the code to configure the peripherals/timers you need
Feelings Faster 🚀 Just works ⭐

Difference with branch V2?

On the master branch, I'm using task notifications from FreeRTOS to unblock a high-priority (relative to core 1) task responsible for debouncing in the software, despite the use of interrupts (which are disabled and enabled within that task). Therefore, when the button is not in use, the task remains blocked on a type of semaphore, conserving CPU resources. This allows the idle task to run uninterrupted until the button is pressed, ensuring the watchdog timer is consistently reset.

The main thread is more efficient than the one in the V2 branch (which employs busy wait for monitoring button status instead of being notified by interrupts).
In the main task, interrupts are enabled and disabled only on the GPIO pin used and on the core where the task is pinned, akin to a critical section, as outlined in the official documentation. 4

The code handles the scenario where the button is continuously pressed; after a while, the main thread will enter a blocked state. You can refer to the relevant part of the firmware for more details. In this way, I can add other tasks in the future to the same board. Meanwhile, with busy waiting, the time consumed by the main task could be critical for other tasks to execute.

Obviously, putting the ESP32 to sleep until it's awakened by the GPIO would be much more efficient. However, the latency from button press to waking the CPU, connecting to WiFi and MQTT, and sending commands will decrease the responsiveness of the application (on the ESP32, you cannot put the CPU into deep sleep without turning off the radio).

Shelly options

Screenshot (31)

Why don't you use Bluetooth?

Yea, it will be far less power consuming (two devices that talk via BLE, instead of two + broker + router via WiFi). But Shelly cannot receive command via Bluetooth, it sends only informations.

Adventure with speech recognition

You can make it with I2S MIC + ESP-EYE on Edge Impulse for example. I tried with different boards, take a look here for offline recognition and here for online.


Footnotes

  1. Still relevant in performance and reliability for general use cases.

  2. I know that can be less than Arduino, but I'm still a beginner with the official IDF. Forgive me.

  3. This Youtube channel can be your starting point in RTOS (you'll never come back then).

  4. Also a useful topic.