|Music skip button based on ESP-Now protocol|
This page is about using the ESP8266/ESP32 ESP-Now protocol in the music skip button.
A music skip button has some tricky requirements:
- you want it to react reasonably quickly, with little latency between pressing the button and skipping to the next song
- the skip button should be mobile, so it is battery powered and has to be conservative with current
The reason to explore the ESP-Now route, is because the existing skip button implementations have some serious disadvantages:
- we used to have a wireless infrastructure based on NRF24L01+ modules, this was never really reliable and it got more complicated with incompatible fakes appearing on the market
- we have a WiFi-based skip button, but it's online continuously, drawing way too much power to make it mobile (so it's tethered to a 5V charger)
The ESP-Now protocol is connection-less, you don't need to set up a session/get an ip-address to communicate between nodes. This saves time and battery power, exactly what we need.
The current ESP-Now skip button prototype needs only about 200 ms after wakeup to send a message and return to deep sleep again.
The hardware is based on ESP8266 (featuring the ESP-Now mode), in particular a Wemos D1 mini board, they are cheap, small and easy to find. A Wemos D1 mini board has an onboard regulator with typically much lower quiescent current than the similar NodeMCU. Another candidate would be an ESP32, it also features the ESP-Now mode and is present on the SHA2017 badge, which is already a kind of mobile platform.
The proposed way of wiring it up, is to make the actual physical button just power up the board. A (super-)cap parallel over the supply wires makes it possible to run the skip program to completion from just a single short press. In case a ESP-Now re-initialisation (which takes a bit more time) is needed, you can just keep the button pressed for a bit longer to complete the initialization process. This way, the SKIP program starts executing as soon as you press the button and there is no quiescent current drain on the battery.
The receiver/master is connected to a raspberry pi or similar, with the EspNowSkip receiving packets from the air and sending them over serial to the raspberry pi. The raspberry pi can then do its magic to make the music skip (e.g. GET/PUT a specific URL of the playback software, send an MQTT message, etc.)
The formula for calculating the required capacitance for the (super)cap over the power supply lines:
C = I . dT / dV
where C = capacity, I = average current, dT = how long the current is drawn, dV = how much voltage drop we can tolerate. Suppose I = 100mA, dT = 0.3 sec, dV = 1V, then the required minimum capacity is approximately 30 mF, or 30,000 uF
Suppose we power the entire circuit with a 18650 battery of 2000mAh capacity.
The deep sleep current of the Wemos D1 mini has been measured at about 0.16 mA. So in deep-sleep, the battery should last > 10000 hours. Battery self discharge current is estimated at 20% per year. For a 2000 mAh battery, that is equivalent to about 400 mAh/8765h = 45 uA, about 1/3rd of the deep sleep current of a wemos d1 mini.
Suppose a skip takes 500 ms consuming a current of 150 mA on average. That's about 0.02 mAh per skip, so the battery should last > 10000 skips.
Regarding the use of a capacitor on the power lines: If we put a (super/ultra-)capacitor parallel over the supply to the wemos d1, we can reasonably assume that all/most of the charge in this capacitor is lost after a skip. Suppose we use a 0.1F supercap charged to 5V, that represents a charge of Q = C.V = 0.5 coulomb, equivalent to about 0.14 mAh. This is already much larger more than calculated earlier. It also scales with the capacitor value, so we should be careful choosing a capacitor value that is not excessively large.
Source code can be found here https://github.com/bertrik/EspNowSkip
It contains the following programs:
- skipbutton.ino: an Arduino program that is the button part of the system (slave) which sends the skip message
- skipreceiver.ino: an Arduino program that is the central part of the system (master) which receives the skip message
- forwardskip.py: a Python script that takes a topic/payload over the serial port from a skipreceiver and forwards it to MQTT
It works like this:
- there are two roles:
- a single central "master" node
- one or more "slave" skip-buttons
- when the skip button is pressed, the ESP8266 resets and starts running, reads the last known ESP-Now channel and MAC address from EEPROM and sends the "SKIP" message
- if the skip button doesn't receive an ACK from the central node, it starts a kind of discovery to re-establish the channel and MAC address of the central node
- the central node is configured as an AP with a specific name (e.g. "espnow-revspace")
- the discovery procedure tries to find the central node by doing an AP scan, the AP name is the only thing that needs to be agreed upon in advance between master and slave code
- in the list of the APs, the slave node finds the SSID belonging to the central node, then it also knows the wifi channel and MAC address of the central node
- the slave node stores both wifi channel and MAC address in (emulated) EEPROM and goes back to sleep
The data we send is an MQTT-like topic + message, for example
The master node can simply parse this into two parts (split on the first space) and bridge this to the Revspace MQTT infrastructure.
- Read-the-docs about the low-level IDF ESP-Now API
- Harringay MakerSpace ESP-Now
- WifiEspNow project on github
- Our current WiFi-based skip button
Future features could be:
- make sure ESP8266 ESP-now implementation is interoperable with ESP32 ESP-now implementation
- use ESP-Now also for other kinds of hacker space infrastructure where low-power consumption is important and/or a power wire is inconvenient.
- add more buttons besides just skipping
- send data back to the skip button, for example we could send a "now playing" message or album art back to a SHA2017 badge and have it shown on its e-ink display.
- investigate whether we can make the central node post directly on the mqtt stream via wifi (at the same time as receiving ESP-Now packets), so we don't need the serial connection.