This page contains basic documentation for the BayLibre Power-Cape software suite.
Please note, that the project itself is still work-in-progress and the software suite should be treated as a Proof-of-Concept.
Power-Cape software suite has been written with Linux in mind and has not been tested on different systems yet. Besides glibc6 it's linked against the following external libraries: libwebsockets, libconfig, Qt5 and Qwt6 (the last two are required only for the Qt UI).
You can find the exact instructions on how to build provided programs in the README.building file in the project's main directory.
The main component of the software suite is the daemon which runs on the same platform on which the probes are installed and talks to the drivers via sysfs. It exports the data via websocket protocol so that it's suitable both for native UIs as well as for web-browsers.
The daemon can also receive data and instruct probes to cut or restore power to they connected devices.
After having built the daemon, the executable (together with libwebsocket and libconfig) should be installed on the measurement board. The whole /pages directory of the project should be copied to the board as well if you want to provide the Web UI.
The default path to the config file is /etc/pwcd/config.cfg. You can override this by passing the -c option to the daemon.
The default path to the web directory (where the contents of /pages are installed) is /var/pwcd/www. You can override this setting by passing the -w option to the daemon. The specified path has to be an absolute path for security reasons.
The daemon can be ordered to daemonize itself when passed the -d option.
The daemon uses a simple structured configuration file as specified by libconfig. See this link for an example. In general please refer to libconfig documentation.
The basic structure of the configuration file is as follows:
# Top level of the configuration. application: { # Array of capes. power_capes = ( { # Name of the power cape. name = "example_cape_0"; # Array of all the probes of the single cape. probes = ( { # Name of the probe name = "probe_0"; # Defines a path to the power-switch GPIO. # If not present, then the probe is not equipped # with a power-switch. power_switch = "/sys/class/gpio/gpio123"; # Array of the measurements available for this probe. measurements = ( { # Arbitrary name of this measurement. name = "Power"; # Type of the measurement - can be: # P - power, # C - current, # V - voltage, # T - temperature. type = "P"; # Path to the sysfs file from which the values # should be read. path = "/sys/class/hwmon/hwmon0/power1_input"; # Units for the presentation layer. Can be: # W - Watt, # V - Volts, # A - Amper, # C - Celsius. unit = "W"; }, { # Second example measurement. name = "Voltage"; type = "V"; path = "/sys/class/hwmon/hwmon0/in1_input"; unit = "V"; }); }, { # Second example probe. name = "probe_1"; measurements = ( { name = "Temperature"; type = "T"; path = "/sys/class/hwmon/hwmon1/temp1_input"; unit = "C"; }); }); }); }
The Web UI is accessible via web browsers (by default on port 12351, but this can be overriden by -p option in the daemon). It's a simple page, which connects to the daemon via a websocket and starts to draw the plots as soon as it starts receiving the data from the server.
Each chart can be hidden and each separate plot curve can be disabled. Power-switch buttons are displayed for these probes which are equipped with one.
Building the Qt UI is described in detail in README.building.
Upon starting the program displays an empty chart and some text fields allowing to connect to the server at given address and port. Clicking the 'connect' button causes the program to connect to the server via websocket procotol. From this point it works exactly like the browser UI except that all the plots are displayed in a single chart.
Each probe can be hidden and restored with the checkboxes below and clicking separate measurements on the right can hide single plots as well. Power buttons are available for probes equipped with one.
There's a slider in the lower left corner of the UI which allows to dynamically change the width of the plot lines. It's useful when the plot lines are not distinct enough.
The LCD display code is not finished as of yet.
Idem.
The protocol used now is not the final version. During the implementation several issues have been found and it will be redesigned. That's why it's not described here in detail.
For information on the websocket protocol please refer to RFC.
In general:
As can be seen this protocol is not very flexible (adding extensions is impossible) and needs a rework.
This is an example JSON message sent in the handshake:
{ "max_sps": 100, "probes": [ { "name": "probe_0_0", "power_switch": "1", "measurements": [ { "name": "Power", "unit": "A" }, { "name": "Voltage", "unit": "V" }, { "name": "Current", "unit": "W" }] }, { "name": "probe_0_1", "measurements": [ { "name": "Temperature 1", "unit":"C" }, { "name": "Temperature 2", "unit": "C" }] }] }
The main difference from the config file structure is that we don't split the probes among capes. This information is irrelevant for the client.
The sensor chip used with the Power Probe is currently a ina226 Power Monitor from Texas Instruments. It is supported in the Linux kernel through two frameworks: hwmon (current use) and industrial-io (work in progress).
Hwmon is specialized in system status monitoring devices like temperature and voltage monitoring, and fan control. It is meant for low-speed measurement and controlling.
Typical client applications for hwmon are:
Industrial IO is focused on industrial controlling and measuring, including high-speed data transfers, for instance from/to ADCs & DACs, accelerometers & gyroscopes etc… IIO allows for a streaming scheme, using software or hardware buffers, real-time capture triggers, events like value thresholds or timeouts. The Capture device may run a deamon (IIOD) , so that the processing or GUI front-end can be on a remote client, typically a PC.
Typical clients for IIO are:
The kernel module source is located under driver/hwmon/ina2xx.c
Up to kernel 4.3: it performs a bulk-read of all 8 I2C registers, resulting in an acquisition time of mean 0.8ms x 8 = 6.4ms. The actual achievable sampling rate is roughly 1/6.4ms = 156 Hz. The driver will issue delayed values for read-rates faster than 156 Hz.
From kernel 4.4 and later on: the driver performs a more optimized read-out of selected values. Reading Power/VBus/Current will result in an acquisition time of mean 0.8ms x 3 = 2.4 ms, i.e. a sampling rate of 416 Hz (312Hz when monitoring VShunt as well). Reading a single value can be done at a rate of 1/0.8ms = 1250 Hz in theory, however, the driver will allow for capture rates up to 500Hz only (averaging value set to 1:1).
The device features as seen through the driver can be visualized with the iio_info tool.
IIO context has 1 devices: iio:device0: ina226 5 channels found: voltage0: (input) 6 channel-specific attributes found: attr 0: scale value: 2.500000000 attr 1: raw value: 799 attr 2: integration_time value: 0.001100 attr 3: index value: 0 attr 4: en value: 1 attr 5: type value: le:u16/16>>0 voltage1: (input) 6 channel-specific attributes found: attr 0: integration_time value: 0.001100 attr 1: raw value: 4149 attr 2: scale value: 1.250000000 attr 3: en value: 1 attr 4: index value: 1 attr 5: type value: le:u16/16>>0 power2: (input) 5 channel-specific attributes found: attr 0: raw value: 42 attr 1: scale value: 25.000000000 attr 2: index value: 2 attr 3: type value: le:u16/16>>0 attr 4: en value: 1 current3: (input) 5 channel-specific attributes found: attr 0: scale value: 1 attr 1: raw value: 200 attr 2: type value: le:u16/16>>0 attr 3: index value: 3 attr 4: en value: 1 timestamp: (input) 3 channel-specific attributes found: attr 0: type value: le:s64/64>>0 attr 1: index value: 4 attr 2: en value: 1 5 device-specific attributes found: attr 0: in_oversampling_ratio value: 4 attr 1: in_shunt_resistor value: 10000 attr 2: in_allow_async_readout value: 0 attr 3: integration_time_available value: 0.000140 0.000204 0.000332 0.000588 0.001100 0.002116 0.004156 0.008244 attr 4: in_sampling_frequency value: 114
This driver supports both
The client application can set an active_channel mask, this is used by the driver to optimize to type of i2c tranfers: bulk read is used when possible. The capture to a kfifo buffer is done by a kernel thread, that will compute the remaining time after the i2c transfer until the next due capture event, and do an active waiting. This insures near-to-realtime timestamps and a clean sampling clock for sampling periods longer than the i2c transaction time, like in the example below:
With Freq=454Hz, averaging is 4-times, the sampling period is 8.8ms, the i2c transfer for all four channels takes ~700us. The sampling is very regular.
It is possible to sample faster, when less channels are wanted.
For instance, for one channel only (POWER) with Freq=850Hz, averaging is 1-times, the sampling period is 1176us, the i2c transfer for channel POWER takes ~450us. The sampling is very regular, but sampling clock jitter can be observed due to the i2c layer.
The kernel module source is located under driver/iio/adc/ina2xx-adc.c
Patches: As of today it is not upstreamed, it must be retrieved from the baylibre git, using branch the acme-iio http://git.baylibre.com/pub/acme/linux/log/?h=acme-iio.
kernel config: this will reauire the following switches
CONFIG_IIO=y CONFIG_INA2XX_ADC=m (selects IIO_BUFFER)
Also, to generate the whole ACME software with IIO support, please refer to https://github.com/BayLibre/ACME
Insert driver with modprobe ina2xx-iio using the gpio extender and device-tree config as described in the acme wiki.
for debug purpose, you may setup the channels and buffer through sysfs:
echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage0_en echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_voltage1_en echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_current3_en echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_power2_en echo 1 > /sys/bus/iio/devices/iio:device0/scan_elements/in_timestamp_en echo 2 > /sys/bus/iio/devices/iio:device0/in_mean_raw echo 100 > /sys/bus/iio/devices/iio:device0/buffer/length
Enable the buffer, and stream the data through the character device
echo 1 > /sys/bus/iio/devices/iio:device0/buffer/enable dd if=/dev/iio\:device0 of=/root/result echo 0 > /sys/bus/iio/devices/iio:device0/buffer/enable
Typically, the resulting data file will hold the four measurement channel values as int16 (4), and a int64 (1) timestamp.
Plotting with gnuplot can be done with
set term png set output "iio-test.png" plot "result" binary format="%4int16%int64" u 5:1 w l, \ "result" binary format="%4int16%int64" u 5:2 w l, \ "result" binary format="%4int16%int64" u 5:3 w l, \ "result" binary format="%4int16%int64" u 5:4 w l set term x11
Example of a USB remove/insert capture (units not shown).
The driver registers a debugfs direct register access interface, under /sys/kernel/debug/iio.
These are some of the known bugs, limitations and future features: