EspNowSkip: Difference between revisions

From RevSpace
Jump to navigation Jump to search
No edit summary
 
(99 intermediate revisions by 2 users not shown)
Line 1: Line 1:
   {{Project
   {{Project
   |Name=EspNowSkip
   |Name=EspNowSkip
   |Picture=plaatje dat je geupload hebt op de wiki
   |Picture=EspNowSkip.png
   |Omschrijving=Muziekskipknop op basis van ESP-Now protocol
   |Omschrijving=Music skip button based on ESP-Now protocol
   |Status=Initializing
   |Status=Completed
   |Contact=bertrik
   |Contact=bertrik
   |Contact2=jelly
   |Contact2=jelly
   }}
   }}


{{Skipknoppenlijstje}}


== Introduction ==
== Introduction ==
Line 14: Line 15:
A music skip button has some tricky requirements:
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
* 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 conserve power
* the skip button should be mobile, so it is battery powered and has to be conservative with current


The ESP-Now protocol is connectionless, you don't need to set up a session/get an ip-address to communicate between nodes.
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.


== Hardware ==
== Hardware ==
The hardware is based on ESP8266, they are cheap and ubiquitous.
[[File:espnowskip_schema.png|thumb|right|schematic]]
 
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 way it's wired 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 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.
 
=== Capacitor calculation ===
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
 
=== Battery life ===
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.


The sender/slave/skip button is wired such that the actual physical button just wakes up the ESP8266.
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.


The receiver/master is connected to a raspberry pi or similar, receiving packets over ESP-Now, sending received data over serial to the raspberry pi.
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 the charge in this capacitor is lost after a skip.
Suppose we use a 0.1F supercap charged to 4V, that represents a charge of Q = C.V = 0.4 coulomb, equivalent to about 0.11 mAh.
This is already much larger more than the 0.02 mAh calculated earlier, though still allowing over 9000 skips from a 1000 mAh SHA badge battery.
It also scales with the capacitor value, so we should be careful choosing a capacitor value that is not excessively large.


== Software ==
== Software ==
<span style="padding: 5px; border: 2px solid darkred; background-color: orange; font-size: large; font-weight: bold;">The protocol detailed here is outdated and has been replaced by the system described on [[ESP-Now]].</span>


=== Source code ===
=== Source code ===
I plan to store source code here:
Source code can be found here https://github.com/bertrik/EspNowSkip
* https://github.com/bertrik/EspNowSkip
 
It contains the following programs:
* <b>skipbutton.ino</b>: an Arduino program running on the button part (on an ESP8266) which sends the skip message
* <b>skipreceiver.ino</b>: an Arduino program running on the receiver part (on an ESP32) which receives the skip message


=== Proposed EspNowSkip protocol ===
=== EspNowSkip protocol ===
It could work something like this:
It works like this:
* there are two roles:
* there are two roles:
** a single central "master" node
** a single central node
** one or more "slave" skip-buttons
** one or more skip-buttons
* when the skip button is pressed, it wakes up from deep sleep and sends an ESP-Now "SKIP" message to the last known channel and MAC address of the central node
* 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
** 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 sets up an AP by name (e.g. "espnow-revspace")
* 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 name, this AP name is the only thing that needs to be agreed upon in advance between master and slave code
* 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 central receiver and button
** from the AP name, the slave node can do a scan to determine the wifi channel and MAC address to use
** in the list of the APs, the button 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 keeps both wifi channel and MAC address in (emulated) EEPROM and goes back to sleep
** the button 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
  revspace/button/skip jump_fwd
 
The "jump_fwd" command is the literal command as used in the Squeezeplayer JSON-RPC protocol.
 
The master node simply parses this into two parts (split on the first space) and bridges this to the Revspace MQTT infrastructure.
 
=== Skip protocol ===
 
There are apparently several ways to send a command to our music playback systems.
Two of these are briefly described below, we currently use the second method.
 
==== Classic HTTP GET ====
Our audio system skips to the next song in the playlist using an HTTP GET with the following path:
  /Classic/status_header.html?p0=...&p1=...&p2=...&player=...
where
  p0 is "playlist"
  p1 is "jump"
  p2 is "%2B1", or "+1" escaped
  player is "d8%3Ad3%3A85%3A17%3A30%3A9c", or "d8:d3:85:17:30:9c" escaped, which is the unique id of the particular player instance
 
Example:
  http://jukebox:9000/Classic/status_header.html?p0=playlist&p1=jump&p2=%2B1&player=b8%3A27%3Aeb%3Aba%3Abc%3Ad5
 
==== JSON Protocol ====
To skip, send a HTTP POST to:
  http://jukebox.space.revspace.nl:9000/jsonrpc.js
with content
  {"id":1,"method":"slim.request","params":["be:e0:e6:04:46:38",["button","jump_fwd"]]}
 
Expect a result like:
  {"result":{},"params":["be:e0:e6:04:46:38",["button","jump_fwd"]],"method":"slim.request","id":1}
 
== More buttons modification ==
[[File:espnowskip_volbuttons.png|thumb|right|adding volume buttons]]
 
In its current form, the skip button can only skip.
 
To get more functionality (e.g. volume up/down) the following could be done:
* add two more buttons, volume up and volume down
* when a volume button is pressed, it connects the positive battery terminal to a ESP8266 input pin
* also it powers up the ESP8266 by connecting the positive battery terminal to the ESP8266 Vcc (through a low-drop schottky diode, e.g. BAT43)
* the software is modified to check the input pin upon startup, if the pin is active, it performs the action for volume up/down, instead of the action for skip
* problem (?): the ESP8266 does not have a built-in pull-down, so the pin level is undefined when the button is not pressed -> perhaps add an external pull-down?
** alternatively, the pins do have a built-in pull-up, so we could perhaps wire it up so we switch the ground pin instead of the Vcc pin


== References ==
== References ==
* [https://esp-idf.readthedocs.io/en/latest/api-reference/wifi/esp_now.html Read-the-docs] about the low-level IDF ESP-Now API
* [https://esp-idf.readthedocs.io/en/latest/api-reference/wifi/esp_now.html Read-the-docs] about the low-level IDF ESP-Now API
* [https://github.com/HarringayMakerSpace/ESP-Now Harringay MakerSpace ESP-Now]
* [https://github.com/yoursunny/WifiEspNow WifiEspNow project on github]
* [https://github.com/yoursunny/WifiEspNow WifiEspNow project on github]
* Our current [https://revspace.nl/Wifiskip WiFi-based skip button]
== Future ==
To do in the immediate future:
* put it in a nicer case (ceiling cavia watches you skip)
* add more buttons besides just skipping!
More distant future:
* use ESP-Now also for other kinds of hacker space infrastructure where low-power consumption is important and/or a power wire is inconvenient: spark shack temperature for example.
* 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. Complication: there is no easy-to-use Arduino implementation of the e-ink display.
* <strike>add a supercap to the skip button, to allow a short press (e.g. 100 ms) to also be registered -> I have various types in my Samla (e.g. 0.1F 5.5V).</strike>.Not needed.

Latest revision as of 13:36, 3 December 2022

Project EspNowSkip
EspNowSkip.png
Music skip button based on ESP-Now protocol
Status Completed
Contact bertrik, jelly
Last Update 2022-12-03
Zie ook:
Uitvoering Skip Wifiskip EspNowSkip Skipknop
Gemaakt 2013 2015 2018/2019 2020
Status Verouderd Onbekend In gebruik In gebruik

Introduction

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.

Hardware

schematic

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 way it's wired 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 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.

Capacitor calculation

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

Battery life

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 the charge in this capacitor is lost after a skip. Suppose we use a 0.1F supercap charged to 4V, that represents a charge of Q = C.V = 0.4 coulomb, equivalent to about 0.11 mAh. This is already much larger more than the 0.02 mAh calculated earlier, though still allowing over 9000 skips from a 1000 mAh SHA badge battery. It also scales with the capacitor value, so we should be careful choosing a capacitor value that is not excessively large.

Software

The protocol detailed here is outdated and has been replaced by the system described on ESP-Now.

Source code

Source code can be found here https://github.com/bertrik/EspNowSkip

It contains the following programs:

  • skipbutton.ino: an Arduino program running on the button part (on an ESP8266) which sends the skip message
  • skipreceiver.ino: an Arduino program running on the receiver part (on an ESP32) which receives the skip message

EspNowSkip protocol

It works like this:

  • there are two roles:
    • a single central node
    • one or more 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 central receiver and button
    • in the list of the APs, the button node finds the SSID belonging to the central node, then it also knows the wifi channel and MAC address of the central node
    • the button 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

 revspace/button/skip jump_fwd

The "jump_fwd" command is the literal command as used in the Squeezeplayer JSON-RPC protocol.

The master node simply parses this into two parts (split on the first space) and bridges this to the Revspace MQTT infrastructure.

Skip protocol

There are apparently several ways to send a command to our music playback systems. Two of these are briefly described below, we currently use the second method.

Classic HTTP GET

Our audio system skips to the next song in the playlist using an HTTP GET with the following path:

 /Classic/status_header.html?p0=...&p1=...&p2=...&player=...

where

 p0 is "playlist"
 p1 is "jump"
 p2 is "%2B1", or "+1" escaped
 player is "d8%3Ad3%3A85%3A17%3A30%3A9c", or "d8:d3:85:17:30:9c" escaped, which is the unique id of the particular player instance

Example:

 http://jukebox:9000/Classic/status_header.html?p0=playlist&p1=jump&p2=%2B1&player=b8%3A27%3Aeb%3Aba%3Abc%3Ad5

JSON Protocol

To skip, send a HTTP POST to:

 http://jukebox.space.revspace.nl:9000/jsonrpc.js

with content

 {"id":1,"method":"slim.request","params":["be:e0:e6:04:46:38",["button","jump_fwd"]]}

Expect a result like:

 {"result":{},"params":["be:e0:e6:04:46:38",["button","jump_fwd"]],"method":"slim.request","id":1}

More buttons modification

adding volume buttons

In its current form, the skip button can only skip.

To get more functionality (e.g. volume up/down) the following could be done:

  • add two more buttons, volume up and volume down
  • when a volume button is pressed, it connects the positive battery terminal to a ESP8266 input pin
  • also it powers up the ESP8266 by connecting the positive battery terminal to the ESP8266 Vcc (through a low-drop schottky diode, e.g. BAT43)
  • the software is modified to check the input pin upon startup, if the pin is active, it performs the action for volume up/down, instead of the action for skip
  • problem (?): the ESP8266 does not have a built-in pull-down, so the pin level is undefined when the button is not pressed -> perhaps add an external pull-down?
    • alternatively, the pins do have a built-in pull-up, so we could perhaps wire it up so we switch the ground pin instead of the Vcc pin

References

Future

To do in the immediate future:

  • put it in a nicer case (ceiling cavia watches you skip)
  • add more buttons besides just skipping!

More distant future:

  • use ESP-Now also for other kinds of hacker space infrastructure where low-power consumption is important and/or a power wire is inconvenient: spark shack temperature for example.
  • 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. Complication: there is no easy-to-use Arduino implementation of the e-ink display.
  • add a supercap to the skip button, to allow a short press (e.g. 100 ms) to also be registered -> I have various types in my Samla (e.g. 0.1F 5.5V)..Not needed.