Automating power measurements using C#
Automating power measurements using C#
Introduction
Using the free software that comes with Otii is a great way to get an understanding of the energy consumption of your device, and an easy way to get direct feedback on how changes in the hardware and/or software will affect the power efficiency.
But as every developer knows, the real power of a developer tool is the ability to automate repetitive tasks. With the Otii Automation Toolbox, you can achieve automation of power measurements by integrating it with the tools you normally use in your development stack.
Otii Automation Toolbox includes a TCP-server using a Json-based API to control the Otii application from any software supporting TCP-connections. To make it even easier, we have created TCP clients you can add to your code for a few popular languages – Python, C#, Java & Matlab. You can find them on the Qoitech GitHub page.
In this article, we will show you how to get started with automation of power measurements using C#, and show you a few useful patterns to automatically compute the energy consumption for a specific part of the measurement of the energy consumption of your device.
Setting up Otii for power automation
To automatize Otii, you’ll need an Otii Automation Toolbox license. You can get it on the Qoitech website. If you register your device, you automatically get a two-week trial of the Otii All Pack that includes the Otii Automation Toolbox.
When you have your license, follow the steps in our documentation to set up and start the TCP-Server.
C# setup
To connect your C# program to the Otii Software you need the Otii TCP Client. It is available as source code from our GitHub page. It is also available as a NuGet package from nuget.org.
To get started, create a new C# project in Microsoft Visual Studio, and use the Nuget manager to install the OtiiTcpClient. You can read more about how to get started with C# in the Otii documentation.
In the main program file, add the following code to connect to the TCP-server:
using Otii; namespace Test { class Program { static void Main(string [] args) { var client = new OtiiClient(); client.Connect(); var otii = client.Otii; } } }
The default parameters of the Connect method of OtiiClient connects to an Otii software running on the same computer. If you want to run the Otii software on another computer, just add the IP-address of which as an argument to Connect:
... client.Connect("192.168.1.5"); ...
Connecting your device
In this example, we will measure the energy consumption of a Particle Argon connected to a DHT-11 temperature sensor.
Fig 1: Otii Arc connected to the device under test
In this setup we have:
- replaced the battery with a connector to the Otii Arc main output,
- connected the TX of the device to the RX of the Otii Arc to capture logs
- connected an additional digital output of the device to the GPI1 input of the Arc.
Overview of automation test set-up
In this setup, we will power the device from the Otii Arc, and at the same time measure the total energy consumed over time. If you are programming your device using USB, remember to disconnect the USB cable when doing measurements. By the way, if you find yourself connecting and disconnecting the USB cable all the time, there is a way to automate that, too. Read about it here.
To be able to compare two recordings made with different firmware, hardware and/or setups, we want to have a way to mark the start and end of the period we want to look at. Typically this would be one duty cycle – including a period of activity, and then a (much longer) period of sleep mode.
We will show you two ways of doing this. Either by the use of the digital output of the device, or by messages sent through the UART of the device.
Setting up the project
To record data, we need an open project. Here we will use a common pattern:
- if there already is an open project, use that,
- and if that fails, create a new project
... var project = otii.GetActiveProject(); if (project == null) { project = otii.CreateProject(); }
Configure the Arc
In this test we want exactly one Arc to be connected to the computer. If we have more Arcs connected, we need to name them uniquely to be able to address them separately.
The device in this test is normally powered by a rechargeable Li-Po battery, so we set the device power to 3.7 V. It is always recommended to set the over-current protection to a value that is 10-20% above the max current drawn by the device.
The expansion port is connected to the digital pins and the UART of the device, and those are set to 3.3 V.
We also enabled the UART and set the UART baud rate to 115 200 to match the firmware setting of the Argon.
var devices = otii.GetDevices(); if (devices.Length != 1) { throw new Exception($"Expected exactly one Arc to be connected, found {devices.Length}"); } var arc = devices[0]; arc.SetMainVoltage(3.7); arc.SetMaxCurrent(0.5); arc.SetExpVoltage(3.3); arc.SetUartBaudrate(115200); arc.EnableUart(true);
And last, we want to enable the channels we want to record. Here we want to measure the main current, main energy, the GPI1 and the UART RX:
arc.EnableChannel("mc", true); arc.EnableChannel("me", true); arc.EnableChannel("i1", true); arc.EnableChannel("rx", true);
Recording data
For this device we want to measure for at least 80 seconds to be able to capture at least one complete duty cycle including one period of activity and one period of sleep mode.
const int RecordingTime = 80_000; ... project.StartRecording(); arc.SetMain(true); Thread.Sleep(RecordingTime); arc.SetMain(false); project.StopRecording(); var recording = project.GetLastRecording();
And if we now run the program this is the output of the recording in Otii:
Fig 3: Otii real-time current recording
Analyze energy consumption
The main energy channel we enabled above is not plotted in Otii. It is used to compute the energy for the complete recording, as well as the energy of a selected part. It stores the accumulated energy over time at the same rate as the main current channel. This makes it simple to calculate the energy for a duty cycle. Just subtract the value at the beginning of the selection from the value at the end of the selection.
To find the start and end of one duty cycle we will present two alternative ways; either by using the RX input, or by using a digital input.
Analyze using the RX input
The firmware in this example outputs the text “Waking up” as the first thing when waking up from sleep. This before getting a value from the temperature sensor and sending the result to a server using Wi-Fi.
So all we need to do is to find two consecutive log entries containing the text “Waking up”, and use the timestamps for those entries to get the accumulated energy for each one. With the device in this example, the first activity period is always a bit longer than the following activity periods. Thus, we will use the second period to calculate the energy using the second and third log entry containing “Waking up”.
We can then compare this result with some threshold, or the energy computed from an earlier recording.
var count = recording.GetChannelDataCount(arc.DeviceId, "rx"); var rxData = recording.GetLogChannelData(arc.DeviceId, "rx", 0, count); var timestamps = rxData.Where(log => log.Value == "Waking up").Select(log => log.Timestamp).ToArray(); if (timestamps.Length < 3) { throw new Exception("Need at last three \"Waking up\" log entries to be able to calulate the energy consumption for a period"); } var timeFrom = timestamps[1]; var timeTo = timestamps[2]; var indexFrom = recording.GetChannelDataIndex(arc.DeviceId, "me", timeFrom); var indexTo = recording.GetChannelDataIndex(arc.DeviceId, "me", timeTo); var energyFrom = recording.GetAnalogChannelData(arc.DeviceId, "me", indexFrom, 1); var energyTo = recording.GetAnalogChannelData(arc.DeviceId, "me", indexTo, 1); var energy = energyTo.Values[0] - energyFrom.Values[0];
Analyze using the digital input
If you don’t have an UART log to sync with, or you don’t want to use it because the UART uses too much energy, you can use a digital output of your device instead.
The device in this example will set the digital output to high when waking up, and to low before going to sleep. Because of the first period being longer, we will calculate the energy between the second and third time the digital output goes high.
var count = recording.GetChannelDataCount(arc.DeviceId, "i1"); var data = recording.GetDigitalChannelData(arc.DeviceId, "i1", 0, count); var timestamps = data.Where(log => log.Value).Select(log => log.Timestamp).ToArray(); if (timestamps.Length < 3) { throw new Exception("Need at last three positive flank timestamps to be able to calulate the energy consumption for a period"); } var timeFrom = timestamps[0]; var timeTo = timestamps[1]; var indexFrom = recording.GetChannelDataIndex(arc.DeviceId, "me", timeFrom); var indexTo = recording.GetChannelDataIndex(arc.DeviceId, "me", timeTo); var energyFrom = recording.GetAnalogChannelData(arc.DeviceId, "me", indexFrom, 1); var energyTo = recording.GetAnalogChannelData(arc.DeviceId, "me", indexTo, 1); var energy = energyTo.Values[0] - energyFrom.Values[0];
Links to code
- C# example code for one duty measurement cycle
- Otii TCP client for Python
- Otii TCP client for Java
- Otii TCP client for Matlab
Conclusion
Automating repetitive tasks is the real strength of developer tools and can make our lives a lot easier. Using the Otii Automation Toolbox you can automate using C#, and automatically compute the energy consumption for specific parts of the measurement.
Become a member of our community
Gain access to exclusive resources, educational materials, and expert advice to enhance your knowledge and understanding of powering IoT devices and battery testing.