How to support the MySensors smartSleep function?
FYI my development board looks like this. Parts include Arduino Pro Mini, MCP1703 (+v.e to 3.3v), 8 channel relay board, nRF24L01+ radio module.

I want to be able to reliably send commands to this MySensors node but I want the node to be sleeping most of the time when the relays are not activated.
When you code up a MySensors node you can save power by sleeping. This works fine until you want to send the node a command. The node won’t receive the command because it is asleep. I initially thought that I could get around this by simply sending the command with a qos status of 1. This doesn’t work!
Recall that a MySensors NODE communicates with a MySensors GATEWAY. The gateway is responsible for sending and receiving messages to an MQTT BROKER.
If you send a command with a qos status of 1 this guarantees delivery to the GATEWAY but it does not guarantee delivery to the node if the node is sleeping. The gateway isn’t clever enough to buffer messages for nodes.
The MySensors library has a built in function called smartSleep. When you call this function the following happens:
- The Node sends a message (I_PRE_SLEEP_NOTIFICATION) to the server with a payload containing the number of milliseconds before it sleeps
- The Node waits for this amount of time
- The Node sleeps
Sending a command to a sleeping node then becomes a lot easier.
The following algorithm can be used when a command is received.
- MqttCogs receives a set command
- Check whether node is sleeping
- If sleeping buffer message to new table
- If not sleeping or it doesn’t look like a MySensor packet then issue the set command
The following algorithm can be used when a incoming I_PRE_SLEEP_NOTIFICATION message is received by MqttCogs
- Check buffer for messages for this node (extract in datetime order)
- Send messages to Node
I’ve had an alpha stab at implementing this. The following will submit a set command to node 10, sensor 6. This is a relay, the value is the number of minutes the relay should open.
[ mqttcogs_set topic='mysensors_in/10/6/1/0/2' text='Add' label_text='Enter a new value here:' input_type='number' input_min='0' input_max='6' input_title='Please enter a number between 0 and 6' qos='1'/ ]
And heres a history of what happened. When you set the value the graph won’t change. The node is only not sleeping for 500ms every minute unless the relay is activated….
For reference, my arduino loop looks something like the code below. I added in a couple of useful safety features.
- A relay can only be activated for a fixed time only.
- When the arduino restarts the relays are set to OFF
void loop()
{
if (sensor_active) {
//check if sensor should still be on
if ((millis() - sensor_start)> sensor_ms) {
digitalWrite(sensor_active-1 + RELAY_PIN, RELAY_OFF);
saveState(sensor_active, false);
send(msg.setSensor(sensor_active).set(false));
sensor_active = 0;
sensor_start = 0;
sensor_ms = 0;
}
//don't sleep while relay is on
return;
}
smartSleep(60000);
}
So, power saving?
It’s good. While sleeping the board (without modifications) consumes 1.5mA (mainly due to the led). I removed the on LED and the board now consumes 60uA when sleeping (should be less so need to look at why).
When relay is on it uses *a lot* because the relay has to be energised.
I’ve coded things so that only one relay can be on at once. This reduces the suck through the MCP1703. The MCP1703 only supports 250mA current draw. More than 2 relays on at once would break it!
No Comments
You can leave the first : )