The TCP Server requires an Automation Toolbox license.
If you have a valid license for the automation toolbox you can enable a TCP server in Otii, making it possible to control Otii from another application. Using this feature you could e.g. use Otii in a continuous integration environment to automatically keep track of how firmware changes affects the energy consumption.
The following example shows how to add a test job that uses Otii in combination with Jenkins to make sure that a firmware change doesn't affect the energy consumption in a negative way.
Our test system
In this example we are using a ST32 Cortex M4 programmed with a ST-Link debugger. The board is powered by the Otii, and is connected to the ST-Link using the SWD interface to make it possible to flash the device with new firmware. To get a realistic measurement of the energy consumed, the ST-Link needs to be disconnected during the actual measurement.
For this reason we have developed a simple switch board that is connected to the expansion port of the Otii Arc, and is controlled by the GPO of the Arc. This makes it possible to connect the SWD when flashing the device, and then disconnect it when doing the energy measurements.
The device connects to the RX and the GPI1 of the Otii Arc. These are used in this example to mark the start and stop of parts of the measurements we want to verify.
The Python Otii Client
You need to install the Otii python client first, read more about it in the section Scripting with Python.
A first start
Create a test python script named otii_test.py. We will use the built in python unit test framework unittest to run our tests. Add the following code to otii_test.py:
./otii_test.py
Running tests...
----------------------------------------------------------------------
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Configure the Otii TCP Server
See the TCP Server for information about how to configure and start the TCP server, either using the Otii desktop client, or using the Otii command line tool.
If you want to automatically start the server from your test script, read more in the section Scripting with Python.
Connecting to the Otii TCP Server
The next step is to connect to the Otii TCP server from the test script:
Now we query Otii for all the available devices, and try to find the correct Arc to use.
By giving each Arc a unique name, you will be sure that you are using the correct one.
...PORT =1905ARC_NAME ="TestArc1"...classOtiiTest(unittest.TestCase):deftest_energy_consumption(self): ... devices = otii.get_devices()iflen(devices)==0:print("No Arc connected!") sys.exit() devices = [device for device in devices if device.name == ARC_NAME]iflen(devices)!=1:print("Expected to find exactly 1 device named {0}, found {1} devices".format(ARC_NAME, len(devices))) sys.exit() arc = devices[0] arc.set_main_voltage(3.3) arc.set_exp_voltage(3.3) arc.set_max_current(0.5) arc.set_uart_baudrate(115200) arc.enable_uart(True) arc.enable_exp_port(True) arc.enable_5v(True)# The switch board is powerd by the Otii +5V pin.
We configure the main out and the expansion port to 3.3 V, we set the max current to 500 mA and configure the UART to a baudrate of 115000, and then enable the UART and expansion port.
The demo system using the UART to send out a start and stop indicator for a part where the system does a temperature measurements and it using the digital input to mark the interval of each temperature measurement.
Using RX to analyze data
In this system, the DUT sends the log message "Getting temperature" when starting a temperature measurement. We use two of these messages to extract the energy consumed for a complete cycle.
...classOtiiTest(unittest.TestCase): ... recording = project.get_last_recording() index =0 count = recording.get_channel_data_count(arc.id, "rx") data = recording.get_channel_data(arc.id, "rx", index, count) values = data["values"] timestamps = [value["timestamp"]for value in values if value["value"]=="Getting temperature"] self.assertGreaterEqual(len(timestamps), 2, "Need at least two \"Getting temperature\" timestamps") statistics = recording.get_channel_statistics(arc.id, 'mc', timestamps[0], timestamps[1]) self.assertLess(statistics["energy"], 0.0004, "One interval consumes to much energy") self.assertGreater(statistics["energy"], 0.0002, "One interval consumes to little energy, is everything up and running?")
Using GPI1 to analyze data
In this system, the DUT sends a small pulse when it wakes up to start a temperature measurement. We try to find the first two pulses, and extracts the energy consumed for this interval.
...classOtiiTest(unittest.TestCase): ... index =0 count = recording.get_channel_data_count(arc.id, "i1") gpi1_data = recording.get_channel_data(arc.id, "i1", index, count)["values"] timestamps = [gpi1_value["timestamp"]for gpi1_value in gpi1_data] self.assertGreaterEqual(len(timestamps), 4, "Need at least four GPI1 pulses") statistics = recording.get_channel_statistics(arc.id, 'mc', timestamps[0], timestamps[2]) self.assertLess(statistics["energy"], 0.0004, "One interval consumes to much energy") self.assertGreater(statistics["energy"], 0.0002, "One interval consumes to little energy, is everything up and running?")
Building and uploading the firmware
This Jenkins job is going to be triggered when new firmware is merged to the master branch of the code repository. The first thing we need to do is to build the firmware, and then upload the new firmware to the device. We only need to do this once, so we add the class method setUpClass to the OtiiTest class, this will be called once before running the unit tests.
Since we have a switch board that is used to enable the debugger that is controlled by the Otii Arc, we have to move the connection and setup part from the test to this method. We make otii and arc class atrributes, making them accessible by all tests in this class.
...classOtiiTest(unittest.TestCase): otii =None arc =None@classmethoddefsetUpClass(cls):# Connecting to Otii and setup Arc connection = otii_connection.OtiiConnection(HOSTNAME, PORT) ... arc.enable_5v(True)# The switch board is powered by the Otii +5V pin.# Turn on the main power, and give the DUT time to startup. arc.set_main(True) time.sleep(1.0)# Enable the USB, and give the ST-lINK time to startup arc.set_gpo(1, True) time.sleep(3.0)# Upload new firmware result = subprocess.call("cd ../firmware; make; make upload", shell=True)if result !=0:print("Failed to upload new firmware") sys.exit() time.sleep(3.0)# Disable the USB, and turn off the main power arc.set_gpo(1, False) time.sleep(1.0) arc.set_main(False);def test_energy_consumption ...