2024-02-10 02:36 PM
I am trying to get the raw data (with timestamp included) from a few IIO devices (hardware sensors, such as accelerometer, gyroscope, magnetometer and barometer) mounted on a linux platform and with the ST drivers. I was able to get the data for the accelerometer and for the gyroscope using the libiio library within a C++ code or using sysfs commands (enabling the buffer). However, for the magnetometer and for the barometer it seems (I'm not expert in this field) this procedure doesn't work. In particular, with the magnetometer (device2), I am able to get the data but not the timestamp (that remains 0).
root@dab:/sys/devices/platform/soc@0/soc@0:bus@30800000/30a50000.i2c/i2c-3/3-001e/iio:device2/buffer# hexdump -C /dev/iio:\device2
00000000 85 01 20 00 34 fe 00 00 00 00 00 00 00 00 00 00 |.. .4...........|
00000010 87 01 24 00 31 fe 00 00 00 00 00 00 00 00 00 00 |..$.1...........|
I've noticed, from the iio_info commands that there is a trigger set-up for the magnetometer, however it seems to me (I am not expert in this field) it isn't really working (as we're able to get the data but not the timestamp), so the problem might be elsewhere. I thought there might be a problem in the location (some REGs maybe?) where the timestamp is written, but I am not sure, as this is the first time I work with sensors.
Is there anything I could check to see why am I getting this problem and how to solve it?
This is the output of the "iio_info" command:
Library version: 0.19 (git tag: v0.19) Compiled with backends: local xml ip usb serial IIO context created with local backend. Backend version: 0.19 (git tag: v0.19) Backend description string: Linux dab 5.4.193-toradex #1 SMP PREEMPT Fri Oct 6 13:55:59 CEST 2023 aarch64 IIO context has 1 attributes: local,kernel: 5.4.193-toradex IIO context has 6 devices: .... iio:device2: iis2mdc (buffer capable) 4 channels found: magn_x: (input, index: 0, format: le:S16/16>>0) 3 channel-specific attributes found: attr 0: raw ERROR: Device or resource busy (-16) attr 1: scale value: 0.001500 attr 2: scale_available value: 0.001500 magn_y: (input, index: 1, format: le:S16/16>>0) 3 channel-specific attributes found: attr 0: raw ERROR: Device or resource busy (-16) attr 1: scale value: 0.001500 attr 2: scale_available value: 0.001500 magn_z: (input, index: 2, format: le:S16/16>>0) 3 channel-specific attributes found: attr 0: raw ERROR: Device or resource busy (-16) attr 1: scale value: 0.001500 attr 2: scale_available value: 0.001500 timestamp: (input, index: 3, format: le:S64/64>>0) 5 device-specific attributes found: attr 0: consumers ERROR: Input/output error (-5) attr 1: current_timestamp_clock value: realtime attr 2: sampling_frequency value: 10 attr 3: sampling_frequency_available value: 10 20 50 100 attr 4: suppliers ERROR: Input/output error (-5) 2 buffer-specific attributes found: attr 0: data_available value: 16 attr 1: watermark value: 1 Current trigger: trigger0(iis2mdc-trigger) ... attr 1: watermark value: 1 trigger0: iis2mdc-trigger 0 channels found: 2 device-specific attributes found: attr 0: consumers ERROR: Input/output error (-5) attr 1: suppliers ERROR: Input/output error (-5)
2024-02-13 07:20 AM
Hi @Ginkgo ,
Are you using the sensor interrupt pin or are you using an external software trigger?
What libiio shell command do you use to read the sensor data?
2024-02-13 09:42 AM
Hi @Federica Bossi,
The shell commands I am using are the following ones:
echo 1 > scan_elements/elements/in_magn_x_en (for the three components of the magnetic field)
echo 1 > scan_elements/in_timestamp_en
echo 16 > buffer/length
echo 1 > buffer/enable
And then the hexdump command.
However, I've also written a script in C++ using libiio-dev v. 0.19 (attached).
Through the iio_info command (in my previous message) you can see there is a "iis2mdc-trigger" trigger is already set by default (so not set by me) appearing among the devices. However I do not know if this might have an influence on this problem, and if so, if I should set it up somehow or disable it.
In the attached code I also tried to set this trigger by associating it with the magnetometer through the command iio_device_set_trigger(). I am able to get the data (with or without setting the trigger) but it seems the timestamp is not available.
#include <iostream>
#include <iio.h>
#include <sys/time.h>
#include <cstring>
#include <thread>
int main() {
struct iio_context *ctx;
struct iio_device *magn_device, *magn_trigger;
struct iio_channel *magn_x, *magn_y, *magn_z, *timestamp_magn;
struct iio_buffer *magn_buffer;
int64_t time_out;
// Create a local context for interacting with Industrial I/O devices
ctx = iio_create_local_context();
if (!ctx) {
std::cerr << "Error creating IIO context" << std::endl;
return -1;
}
// Find the magnetometer device and trigger device by their names
magn_device = iio_context_find_device(ctx,"iis2mdc");
magn_trigger = iio_context_find_device(ctx,"iis2mdc-trigger");
// Get a reference to the specific device using its description
if (magn_trigger) {
// Check if the device is a trigger
if (iio_device_is_trigger(magn_trigger)) {
printf("The device is a trigger.\n");
} else {
printf("The device is not a trigger.\n");
}
} else {
printf("Device not found.\n");
}
if (!magn_device || !magn_trigger) {
std::cerr << "Devices not found" << std::endl;
iio_context_destroy(ctx);
return -1;
}
// Set the number of kernel buffers for the magnetometer device
iio_device_set_kernel_buffers_count(magn_device, 1);
// Find magnetometer channels and timestamp channel
magn_x = iio_device_find_channel(magn_device, "magn_x", false);
magn_y = iio_device_find_channel(magn_device, "magn_y", false);
magn_z = iio_device_find_channel(magn_device, "magn_z", false);
timestamp_magn = iio_device_find_channel(magn_device, "timestamp", false);
if (!magn_x || !magn_y || !magn_z || !timestamp_magn) {
std::cerr << "Channels not found" << std::endl;
iio_context_destroy(ctx);
return -1;
}
// Enable magnetometer channels and timestamp channel
iio_channel_enable(timestamp_magn);
iio_channel_enable(magn_x);
iio_channel_enable(magn_y);
iio_channel_enable(magn_z);
// Set the trigger for the magnetometer device
if (iio_device_set_trigger(magn_device, magn_trigger) < 0) {
std::cerr << "Error setting trigger" << " " << iio_device_set_trigger(magn_device, magn_trigger) << std::endl;
iio_context_destroy(ctx);
return -1;
}
// Create a buffer for reading magnetometer data
magn_buffer = iio_device_create_buffer(magn_device, 1, false);
if (!magn_buffer) {
std::cerr << "Error creating buffer" << std::endl;
iio_context_destroy(ctx);
return -1;
}
// Set the timeout for the context
time_out = iio_context_set_timeout(ctx, 0);
if (time_out < 0){
std::cerr << "Error setting timeout" << std::endl;
iio_context_destroy(ctx);
return -1;
}
// Continuously read data from the buffer
while (true) {
// Refill the buffer with data
ssize_t magn_bytes = iio_buffer_refill(magn_buffer);
std::cout << "Data filled in the magnetometer buffer: " << magn_bytes << " bytes" << std::endl;
if (magn_bytes < 0) {
std::cerr << "Error refilling buffer" << std::endl;
break;
}
// Read magnetometer data from the buffer and print
for (void *ptr = iio_buffer_first(magn_buffer, magn_x); ptr < iio_buffer_end(magn_buffer); ptr += iio_buffer_step(magn_buffer)) {
int16_t Magn_x = *(uint16_t*)(ptr);
std::cout << "Magn_x = " << Magn_x << std::endl;
}
for (void *ptr = iio_buffer_first(magn_buffer, magn_y); ptr < iio_buffer_end(magn_buffer); ptr += iio_buffer_step(magn_buffer)) {
int16_t Magn_y = *(uint16_t*)(ptr);
std::cout << "Magn_y = " << Magn_y << std::endl;
}
for (void *ptr = iio_buffer_first(magn_buffer, magn_z); ptr < iio_buffer_end(magn_buffer); ptr += iio_buffer_step(magn_buffer)) {
int16_t Magn_z = *(uint16_t*)(ptr);
std::cout << "Magn_z = " << Magn_z << std::endl;
}
for (void *ptr = iio_buffer_first(magn_buffer, timestamp_magn); ptr < iio_buffer_end(magn_buffer); ptr += iio_buffer_step(magn_buffer)) {
int64_t Timestamp_magn = *(uint64_t*)(ptr);
std::cout << "Timestamp_magn = " << Timestamp_magn << std::endl;
}
}
// Destroy the buffer and context before exiting
iio_buffer_destroy(magn_buffer);
iio_context_destroy(ctx);
return 0;
}
2024-02-15 02:55 AM
Hi @Ginkgo ,
Thanks for your answer. To better understand what could be the issue I need to know if you are using the sensor interrupt pin or an external software trigger.
Let me know 🙂
2024-02-29 02:05 AM
Hi @Ginkgo ,
A patch has been made and is currently in the CI test phase, soon it will be public on the github.
I will let you know when it will be released.