On-Chip Software Development Kit
has been customized to ensure low-power operation. While the customization does not affect the way your application interacts with it, it does ensure that theLTC5800
chip is automatically put into low-power state when no task is executing.You application is not aware of these optimizations. In particular, your application does not have to do anything for the chip to go into low-power state, since this is handled entirely by the uC/OS-II library.
Your application has access to all devices and peripherals on the
LTC5800
chip, and controls theSmartMesh network stack
. This means that it has a major influence on the energy consumed by the device.What follows are some "best practice" tips for keeping that consumption as low as possible.
Packets Size and Frequency
Very often, your application will collect small samples from sensors, possibly only a handful of bytes for each sample.
Recommendation
We recommend that you group several sensor readings into a large packet (which you send infrequently), rather than frequently sending a small packet.
For example, if your application collects a 2-byte reading from a flow sensor every second, we recommend you cache those readings, and send a packet with 80 bytes of application payload every 40 seconds, rather than sending one packet with 2 bytes of application payload every second.
The reason is that wireless communication accounts for most of the energy budget of your device. Sending large packets infrequently has the following advantages over sending small packets frequently:
- Apart from your application payload, all packets contain header bytes to ensure correct and secure delivery of your data. The overhead associated with sending and receiving those bytes is the same whether you send a small or large number of payload bytes. If therefore makes sense to send as small a number of packets as possible.
- Similarly, sending a packet involves starting up the radio's RF chain on both the transmitter and the receiver, and exchanging an acknowledgment packet for the receiver to indicate successful reception.
- This overhead is all the more important that your device can be located multiple hops from its destination. No data aggregation is done in the network, so if you send 5 packets, 5 separate packets will be traveling along the multi-hop route between your device and the destination. This means that the overhead associated with sending many small packets is accounted for at each wireless hop.
Services and Actual Data Rate
After joining, your application requests a service, which can be seen as a data "pipe" your device can send data through. When requesting the service, your application indicates the value of the service. For a service of type "bandwidth", this corresponds to the number of milliseconds between any two consecutive packets. If a
SmartMesh mote
requests a service with value 10000ms, it is indicating to theSmartMesh manager
that it plans on sending one data packet every 10 seconds. In the analogy above, the value of the service is equivalent to the thickness of the data pipe.Once your application requests this service, the
SmartMesh manager
installs and maintains enough resources to satisfy this request, along the multi-hop route between your device and the destination. These resources are links in the communication schedule. TheSmartMesh manager
will not monitor how much data traffic your application actually sends through this data pipe. If your application requests a service of value 10000ms, and only sends one packet every 30s, this will result in energy being wasted. The reason is that, even if your application does not send a packet, the devices along this packet will listen for possible data.Recommendation
We recommend that your application requests services which match the interval that data will actually be sent.
Busy-waiting/Polling
When your application is waiting for an event to happen, it is possible to implement a busy wait. In addition to being energy-inefficient, this approach prevents lower priority tasks from executing and may result in erroneous operation.
For example, if your application is waiting for a pin to go high, you could, in one of your application's tasks, read the value of that pin in a loop, and exit the loop when the value read indicates that the pin is high. This is called busy-waiting since the micro-controller is continuously busy (in this case reading a GPIO pin), while waiting.
A better way for waiting for a pin to transition is to enable the pin's notifications at the driver level. Your application can then sleep while waiting for a callback function to be called by the GPIO driver.
Another example is synchronization between tasks in your application. If task A is waiting for task B to do some operation, you could have both tasks share some variable, and have task A continuously read the value of that variable while waiting for task B to set it. Apart from obvious concurrency issues, this also results in wasted energy.
A more optimal way to synchronize between different tasks in your application is to use a uC/OS-II synchronization primitive such as a semaphore. In this case, your task A can pend on a shared semaphore, which task B posts whenever ready. The uC/OS-II scheduler then handles the synchronization in a way that does not involve busy-waiting.
Use driver notifications and uC/OS-II task synchronization primitives instead of busy-waiting.
Battery Load Resistors
To assess the depletion level of your battery, your application can enable internal battery load resistors before measuring the supply voltage. This is detailed in the
SmartMesh On-Chip API html documentation
. When enabled, current flows through those resistors. While this is needed for evaluating the depletion level of some batteries (by measuring their internal resistance), your application should disable those load resistors directly after the measurement is done.Enable the battery load resistors only strictly when needed.