Reporting data from a 'sleepy device' #1129
davidg238
started this conversation in
Show and tell
Replies: 2 comments
-
Very nice write-up. Thanks! |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Reporting data from a 'sleepy' device
If you have a sensor which is to be monitored by a battery powered device, power conservation is a primary concern. From the size of battery and device componentry, a power budget can be determined, for how long the battery will last before being discharged. Often the processor has the highest power demand, and manufacturers address this by providing various sleep modes. The ESP32 is no different.
In Toit, when you write
sleep --ms=1_000
, the processor remains active. To actually save power, it is necessary to calldeep_sleep duration/Duration
, part of the esp32 library. This puts the ESP32 into deep sleep mode, saving several orders of magnitude of current consumption, but pausing program execution and severing any open communications links.MQTT is a popular communications protocol for reporting data from device to server, and is thus supported in the Toit library mqtt and by the major cloud vendors. MQTT relies upon a connected transport, so to address sleeping nodes 'MQTT For Sensor Networks' MQTT-SN was developed. MQTT-SN supports non-connected transports and limited channel bandwidth. As the ESP32 in this example uses WiFi, channel bandwidth is not an issue, but being able to run on UDP, allows the device to deep sleep. MQTT-SN relies upon a gateway, to translate the MQTT-SN messges to MQTT.
A useful reference for all things MQTT is Practical MQTT with Steve
In this show and tell, 3 features are demonstrated:
The code is just proof-of-concept and not production ready.
The application
The application looks 'normal', other than the last expression
esp32.deep_sleep (Duration --m=15)
. Rather than the application terminating after the last expression is evaluated, the ESP32 enters deep sleep for (at most) the duration, after which the application is restarted from the beginning. No program state is carried to the next invocation, unless explicitly stashed in say FlashStorage.A very simple MQTT-SN client
Rather than writing a complete MQTT-SN client, I took advantage of Section 6.8 Publish with QoS Level -1 (aka QoS3) of the specification:
This allowed for a tiny client, that could simply report the BME280 temperature, humidity and pressure values. Payloads lengths are restricted by UDP packet size, so if you experiment with this sample, beware. A short sleep is inserted between the last PUBLISH and closing the client, as I noticed the last message was not delivered to the server without it, but I did not spend a lot of time tuning/debugging this.
In development, working with Jaguar and sleepy devices
When the ESP32 enters deep_sleep, it is no longer responsive to the Jaguar CLI. This is a real nuisance, especially if your code executes quickly, you lose CLI access to the target device. (You can recover by re-flashing the device, explicitly nominating the port, like
jag flash --port /dev/ttyUSB0
)Assuming the development target is 'within reach', an alternative is to dedicate a gpio to a wake-on-pin trigger. A test on
esp32.wakeup_cause
is used to determine the reason for the device coming out of deep_sleep, in this case either the deep_sleep duration timer expiring or wake-on-pin trigger. If the latter, simply sleep the device for a period, to give the Jaguar CLI time to connect. I chose one minute as a relaxed window to connect, however 10 seconds is likely the minimum to allow WiFi to start and the Jaguar client on the target be responsive to CLI commands.Finally, as pointed out in a Discord thread, 'Programs that should survive a reboot or deep sleep need to be installed as a container:'
Setup and test
The following was tested on an Ubuntu 20.04 desktop running Jaguar v1.7.1, communicating with an ESP32 Feather, wired to a BME280 and a trigger input on pin 32.
Setup and test MQTT-SN
broker.config
might look like:Open a gateway terminal window and start the rsmb SN gateway with
./broker_mqtts broker.config
Download and make MQTT-SN-Tools
To begin testing your setup, open a subscriber terminal window in the
mqtt-sn-tools
directory, and executewhich subscribes to messages on topic
t_
on the mqtt-sn gateway at localhost:1885Open a publisher terminal window in the
mqtt-sn-tools
directory and executewhich publishes the message
12.4
on topict_
to the gateway on localhost:1885If your setup is working, you should see in the gateway terminal:
showing the broker receiving the PUBLSIH and echoing it to the subscriber
in the subscriber terminal, you should see
12.4
Using known good tooling, you have subscribed to and published a message.
Test sleepy_sensor sending MQTT-SN messages
In the
sleepy_sensor
directory, open a JAG terminal and runjag flash
to install the Jaguar client on the target.Open a monitor terminal, run
jag scan
, thenjag monitor
to monitor the device target.In the JAG terminal, run
jag container install sleeper sleepy_sensor.toit
to install the application container on the target. The response should be like:In the monitor terminal, when the runtime first boots, you should see:
showing the runtime booting, the application running and then entering deep sleep
In the gateway terminal, you should periodically see:
which is the three messages published to the broker, one of which the topic
t_
is echoed to the subscriber.In the subscriber terminal, you should see the actual temperature.
Test working with Jaguar
Then periodically as the device target exits deep_sleep, in the monitor terminal, you should see:
It is essential the WiFi be fully started before attempting the NTP correction or MQTT-SN publish, hence the 10s sleep on line 25 of
sleepy_sensor.toit
Now since the target device is mostly deep_sleeping, if in the JAG terminal you attempt to use the Jaguar CLI
jag container list
, it will fail with an error like:The target device is in deep_sleep and thus un-responsive to network traffic.
The gpio trigger is leveraged to wake the application, by raising pin 32 to rail rather than ground. The test on
esp32.wakeup_cause
on line 34, rather than measuring the BME280, simply sleeps, giving the Jaguar CLI a window to access the target.When you see
Opening window for JAG connect ..
in the monitor terminal, you have a chance to interact with the target in the JAG terminal.If you re-issue the list command now, the containers will be listed:
When you see
.. closing window for JAG connect
, the CLI is unavailable again and program execution has resumed.The gpio trigger thus enables an edit/run development cycle, with deep_sleep code.
Source available at: https://github.com/davidg238/sleepy_sensor
sleepy_demo.mp4
Beta Was this translation helpful? Give feedback.
All reactions