Closed Funky185540 closed 3 years ago
Hey. Yeah, Rust is a great way to do this! This library is still fairly young, but I'm already using it in production and want to make sure it's bug-free. But here's a few things to keep in mind:
Anyway, riio_tsbuf
is claiming that it can't set the sampling rate: "Can't set sampling rate to 100Hz..."
Let's see if we can figure that out.
First step: Can you post a dump of iio_info
so we can see what hardware you have on your board?
Hello again,
sorry for the late reply! Had to reinstall the whole system due to other reasons, but now it's back alive.
Thanks for the heads up! Here's the file: iio_info_dump.txt
Another thing to note, which you can also read from the output in the file: The very first sensor (iio:device0
on my system) doesn't have a name in the sysfs directory. Do you think it might be an option to read the name from the OF node in that case, or is this out of scope for this crate?
Dumping here for easier reading:
Library version: 0.21 (git tag: v0.21)
Compiled with backends: local xml ip usb serial
IIO context created with local backend.
Backend version: 0.21 (git tag: v0.21)
Backend description string: Linux toolbox 5.12.0 #34 SMP Sat May 1 14:14:27 CEST 2021 aarch64
IIO context has 2 attributes:
local,kernel: 5.12.0
uri: local:
IIO context has 6 devices:
iio:device0:
5 channels found:
voltage2: (input)
2 channel-specific attributes found:
attr 0: raw value: 3485
attr 1: scale value: 1.100000
current1: (input)
2 channel-specific attributes found:
attr 0: raw value: 0
attr 1: scale value: 1
voltage1: (input)
2 channel-specific attributes found:
attr 0: raw value: 0
attr 1: scale value: 0.800000
current2: (input)
2 channel-specific attributes found:
attr 0: raw value: 320
attr 1: scale value: 1
temp: (input)
3 channel-specific attributes found:
attr 0: offset value: -2667
attr 1: raw value: 2834
attr 2: scale value: 100
No trigger on this device
iio:device1: stk3310
2 channels found:
proximity: (input)
5 channel-specific attributes found:
attr 0: integration_time value: 0.000370
attr 1: integration_time_available value: 0.000185 0.000370 0.000741 0.001480 0.002960 0.005920 0.011840 0.023680 0.047360 0.094720 0.189440 0.378880 0.757760 1.515520 3.031040 6.062080
attr 2: raw value: 11
attr 3: scale value: 0.100000
attr 4: scale_available value: 6.4 1.6 0.4 0.1
illuminance: (input)
5 channel-specific attributes found:
attr 0: integration_time value: 0.094720
attr 1: integration_time_available value: 0.000185 0.000370 0.000741 0.001480 0.002960 0.005920 0.011840 0.023680 0.047360 0.094720 0.189440 0.378880 0.757760 1.515520 3.031040 6.062080
attr 2: raw value: 344
attr 3: scale value: 0.100000
attr 4: scale_available value: 6.4 1.6 0.4 0.1
No trigger on this device
iio:device2: mpu6050 (buffer capable)
9 channels found:
accel_x: (input, index: 0, format: be:S16/16>>0)
6 channel-specific attributes found:
attr 0: calibbias value: -32
attr 1: matrix value: 0, 0, 0; 0, 0, 0; 0, 0, 0
attr 2: mount_matrix value: 0, 1, 0; -1, 0, 0; 0, 0, -1
attr 3: raw value: 738
attr 4: scale value: 0.000598
attr 5: scale_available value: 0.000598 0.001196 0.002392 0.004785
accel_y: (input, index: 1, format: be:S16/16>>0)
6 channel-specific attributes found:
attr 0: calibbias value: 765
attr 1: matrix value: 0, 0, 0; 0, 0, 0; 0, 0, 0
attr 2: mount_matrix value: 0, 1, 0; -1, 0, 0; 0, 0, -1
attr 3: raw value: -14
attr 4: scale value: 0.000598
attr 5: scale_available value: 0.000598 0.001196 0.002392 0.004785
accel_z: (input, index: 2, format: be:S16/16>>0)
6 channel-specific attributes found:
attr 0: calibbias value: 972
attr 1: matrix value: 0, 0, 0; 0, 0, 0; 0, 0, 0
attr 2: mount_matrix value: 0, 1, 0; -1, 0, 0; 0, 0, -1
attr 3: raw value: 14980
attr 4: scale value: 0.000598
attr 5: scale_available value: 0.000598 0.001196 0.002392 0.004785
temp: (input)
3 channel-specific attributes found:
attr 0: offset value: 12420
attr 1: raw value: 1557
attr 2: scale value: 2.941176
anglvel_x: (input, index: 4, format: be:S16/16>>0)
5 channel-specific attributes found:
attr 0: calibbias value: 0
attr 1: mount_matrix value: 0, 1, 0; -1, 0, 0; 0, 0, -1
attr 2: raw value: -18
attr 3: scale value: 0.001064724
attr 4: scale_available value: 0.000133090 0.000266181 0.000532362 0.001064724
anglvel_y: (input, index: 5, format: be:S16/16>>0)
5 channel-specific attributes found:
attr 0: calibbias value: 0
attr 1: mount_matrix value: 0, 1, 0; -1, 0, 0; 0, 0, -1
attr 2: raw value: -15
attr 3: scale value: 0.001064724
attr 4: scale_available value: 0.000133090 0.000266181 0.000532362 0.001064724
anglvel_z: (input, index: 6, format: be:S16/16>>0)
5 channel-specific attributes found:
attr 0: calibbias value: 0
attr 1: mount_matrix value: 0, 1, 0; -1, 0, 0; 0, 0, -1
attr 2: raw value: -30
attr 3: scale value: 0.001064724
attr 4: scale_available value: 0.000133090 0.000266181 0.000532362 0.001064724
timestamp: (input, index: 7, format: le:S64/64>>0)
gyro: (input, WARN:iio_channel_get_type()=UNKNOWN)
1 channel-specific attributes found:
attr 0: matrix value: 0, 0, 0; 0, 0, 0; 0, 0, 0
3 device-specific attributes found:
attr 0: current_timestamp_clock value: realtime
attr 1: sampling_frequency value: 50
attr 2: sampling_frequency_available value: 10 20 50 100 200 500
2 buffer-specific attributes found:
attr 0: data_available value: 0
attr 1: watermark value: 1
Current trigger: trigger1(mpu6050-dev2)
iio:device3: lis3mdl (buffer capable)
4 channels found:
magn_x: (input, index: 0, format: le:S16/16>>0)
3 channel-specific attributes found:
attr 0: raw value: 6454
attr 1: scale value: 0.000146
attr 2: scale_available value: 0.000146 0.000292 0.000438 0.000584
magn_y: (input, index: 1, format: le:S16/16>>0)
3 channel-specific attributes found:
attr 0: raw value: -1626
attr 1: scale value: 0.000146
attr 2: scale_available value: 0.000146 0.000292 0.000438 0.000584
magn_z: (input, index: 2, format: le:S16/16>>0)
3 channel-specific attributes found:
attr 0: raw value: 5611
attr 1: scale value: 0.000146
attr 2: scale_available value: 0.000146 0.000292 0.000438 0.000584
timestamp: (input, index: 3, format: le:S64/64>>0)
3 device-specific attributes found:
attr 0: current_timestamp_clock value: realtime
attr 1: sampling_frequency value: 1
attr 2: sampling_frequency_available value: 1 2 3 5 10 20 40 80
2 buffer-specific attributes found:
attr 0: data_available value: 0
attr 1: watermark value: 1
Current trigger: trigger0(lis3mdl-trigger)
trigger0: lis3mdl-trigger
0 channels found:
No trigger on this device
trigger1: mpu6050-dev2
0 channels found:
No trigger on this device
Oh... I think I see it...
We have the device, iio:device2: mpu6050
, and we have the separate trigger, trigger1: mpu6050-dev2
. Normally, when you set the sampling frequency, you set the attribute on the trigger, and not on the device. After all, that supposed to be the function of the trigger; to pace the sampling.
But in your case, the sampling frequency attribute is on the device itself, iio:device2
, and not on the trigger, trigger1
.
It's not totally uncommon to see a device that has a sampling_frequency
attribute, but I have never seen one that also exports an external trigger that doesn't have the attribute!
So, this particular hardware configuration isn't currently supported by the example app. But you can probably hack it pretty easily to get it to work. Don't bother with the trigger device; just set the attribute on the main device.
So remove (comment out) the trigger section:
let trig = ctx.find_device(trig_name).unwrap_or_else(|| {
eprintln!("Couldn't find requested trigger: {}", trig_name);
process::exit(1);
});
let freq = matches
.value_of("frequency")
.and_then(|s| s.parse::<i64>().ok())
.unwrap_or(DFLT_FREQ);
// Set the sampling rate
if let Err(err) = trig.attr_write_int("sampling_frequency", freq) {
println!("Can't set sampling rate to {}Hz: {}", freq, err);
}
dev.set_trigger(&trig).unwrap_or_else(|err| {
println!("Error setting the trigger in the device: {}", err);
process::exit(2);
});
and replace it with code to set the attribute on the device:
let freq = matches
.value_of("frequency")
.and_then(|s| s.parse::<i64>().ok())
.unwrap_or(DFLT_FREQ);
// Set the sampling rate
if let Err(err) = dev.attr_write_int("sampling_frequency", freq) {
println!("Can't set sampling rate to {}Hz: {}", freq, err);
}
Note that it's now writing the attribute to dev
and not trig
.
I haven't actually tried this, so you may have to hack at it a bit. Let us know if you get it to work.
You're right, the patch did the trick! I can now set the sampling frequency on the device.
I have some more questions about that though: I know that the MPU6050 can't run with arbitrary sampling frequencies, however the example allows me to make it run at arbitrary sampling frequencies. How does this work? Is the MPU6050 oversampled and the library runs with the requested sample rate?
Also: Is this weirdness (Trigger doesn't have sampling_frequency attr) something that needs fixing in the device tree, or is it part of the kernel driver instead?
Thank you very much!
Okay, I assume it's not the DT, I can't find any info related to the trigger configuration there... If you don't do it first, I'd like to extend the example to make it work for cases such as mine (probably using has_attr
on the trigger). Cool stuff!
Another question (Sorry for asking so many questions!): How would I sample multiple channels simultaneously? Are they guaranteed to be synchronized?
How does this work?
I don't know.
Is the MPU6050 oversampled and the library runs with the requested sample rate?
I have no idea.
Is this weirdness ... something that needs fixing in the device tree, or is it part of the kernel driver instead?
I've never seen that before, so I have no idea.
I'm ind of joking, but I think the basic point of IIO is that if you have a (possibly high-speed) data collection device that doesn't conform to any other device class, then you can write a driver for it to pull data out using the IIO API. But then it's totally up to the driver writer to map the capabilities of the hardware to the IIO calls.
So far, from what I've seen, every piece of hardware is slightly different, but often if you look at what the capabilities are (as reported by _iioinfo), you can tend to figure it out. If not, a look at the specific device driver might help, or even the datasheet for the chip can be helpful.
And, also, I've never used this specific chip, but with similar ones, I've seen a lot of jitter on the sampling rate, especially if you try and push it faster, possibly from calculations that are non-deterministic. So weirdness could come from anywhere.
Yeah, I was thinking for the example app, if the user supplies a sampling rate but no trigger device on the command line, then the app should attempt to set the sampling frequency on the device itself. If it doesn't have that attribute, then exit with an error.
I have a couple ADS1115 boards wired up to a BeagleBone Green. I believe they support internal triggering; so I can try this out. It would be good to have a solution that isn't specific to any particular hardware.
I also ordered a couple MPU6050 boards this week to try out; they may already be here. I will see if I can find a few minutes this week to wire them up and see how they work.
BTW, what is your hardware setup?
As for the multi-channel acquisition, yes, you can acquire from multiple channels in a device so long as they can be triggered by the same trigger device. They should be synchronized, but as to whether they are truly sampled in parallel, or sampled serially one after the other, that depends on the hardware capabilities and device driver.
Thanks for sharing all that knowledge!
Yeah, I was thinking for the example app, if the user supplies a sampling rate but no trigger device on the command line, then the app should attempt to set the sampling frequency on the device itself. If it doesn't have that attribute, then exit with an error.
That sounds reasonable, indeed.
BTW, what is your hardware setup?
It's a PinePhone, I need the sensor data for a course at university this semester. All my fellow students own Android devices and use PhyPhox for data acquisition, but as I have a PinePhone and like to teach myself cool new tricks I thought I'll just do it the hard way. Or maybe that's because im masochistic, I can't tell for sure.... :-)
Fixed in #10.
So I just connected an Adafruit MPU-6050 breakout board to a RaspberryPi https://www.adafruit.com/product/3886
With this setup, I'm seeing the same basic configuration for the IMU chip. So I can test the examples with the same chip.
fmp@raspberrypi:~ $ iio_info
Library version: 0.21 (git tag: e1f6a84)
Compiled with backends: local xml ip usb
IIO context created with local backend.
Backend version: 0.21 (git tag: e1f6a84)
Backend description string: Linux raspberrypi 5.10.17-v7l+ #1403 SMP Mon Feb 22 11:33:35 GMT 2021 armv7l
IIO context has 2 attributes:
local,kernel: 5.10.17-v7l+
uri: local:
IIO context has 2 devices:
iio:device0: mpu6050 (buffer capable)
9 channels found:
accel_x: (input, index: 0, format: be:S16/16>>0)
6 channel-specific attributes found:
attr 0: calibbias value: -2360
attr 1: matrix value: 0, 0, 0; 0, 0, 0; 0, 0, 0
attr 2: mount_matrix value: 1, 0, 0; 0, 1, 0; 0, 0, 1
attr 3: raw value: 220
attr 4: scale value: 0.000598
attr 5: scale_available value: 0.000598 0.001196 0.002392 0.004785
accel_y: (input, index: 1, format: be:S16/16>>0)
6 channel-specific attributes found:
attr 0: calibbias value: -887
attr 1: matrix value: 0, 0, 0; 0, 0, 0; 0, 0, 0
attr 2: mount_matrix value: 1, 0, 0; 0, 1, 0; 0, 0, 1
attr 3: raw value: 2970
attr 4: scale value: 0.000598
attr 5: scale_available value: 0.000598 0.001196 0.002392 0.004785
accel_z: (input, index: 2, format: be:S16/16>>0)
6 channel-specific attributes found:
attr 0: calibbias value: 1830
attr 1: matrix value: 0, 0, 0; 0, 0, 0; 0, 0, 0
attr 2: mount_matrix value: 1, 0, 0; 0, 1, 0; 0, 0, 1
attr 3: raw value: 13172
attr 4: scale value: 0.000598
attr 5: scale_available value: 0.000598 0.001196 0.002392 0.004785
temp: (input)
3 channel-specific attributes found:
attr 0: offset value: 12420
attr 1: raw value: -1593
attr 2: scale value: 2.941176
anglvel_x: (input, index: 4, format: be:S16/16>>0)
5 channel-specific attributes found:
attr 0: calibbias value: 0
attr 1: mount_matrix value: 1, 0, 0; 0, 1, 0; 0, 0, 1
attr 2: raw value: -21
attr 3: scale value: 0.001064724
attr 4: scale_available value: 0.000133090 0.000266181 0.000532362 0.001064724
anglvel_y: (input, index: 5, format: be:S16/16>>0)
5 channel-specific attributes found:
attr 0: calibbias value: 0
attr 1: mount_matrix value: 1, 0, 0; 0, 1, 0; 0, 0, 1
attr 2: raw value: -41
attr 3: scale value: 0.001064724
attr 4: scale_available value: 0.000133090 0.000266181 0.000532362 0.001064724
anglvel_z: (input, index: 6, format: be:S16/16>>0)
5 channel-specific attributes found:
attr 0: calibbias value: 0
attr 1: mount_matrix value: 1, 0, 0; 0, 1, 0; 0, 0, 1
attr 2: raw value: -46
attr 3: scale value: 0.001064724
attr 4: scale_available value: 0.000133090 0.000266181 0.000532362 0.001064724
timestamp: (input, index: 7, format: le:S64/64>>0)
gyro: (input, WARN:iio_channel_get_type()=UNKNOWN)
1 channel-specific attributes found:
attr 0: matrix value: 0, 0, 0; 0, 0, 0; 0, 0, 0
3 device-specific attributes found:
attr 0: current_timestamp_clock value: realtime
attr 1: sampling_frequency value: 50
attr 2: sampling_frequency_available value: 10 20 50 100 200 500
2 buffer-specific attributes found:
attr 0: data_available value: 0
attr 1: watermark value: 1
Current trigger: trigger0(mpu6050-dev0)
trigger0: mpu6050-dev0
0 channels found:
No trigger on this device
Hi,
I'm currently teaching myself how to program in Rust, and as I have a university project that requires me to read sensors from an embedded system I though why not do it in Rust and learn something along the way (Besides I personally find that the C-interface to libiio is extremely awkward to use). So first up: Thanks for making the effort!
I decided to start with the examples to see how everything works out. And unfortunately I can't seem to properly access the sensors on my system. See below:
As can be estimated from the timestamps, the sample rate is set to 50Hz. However, when I attempt to update the samplerate via CLI, it works:
Is this somehow related to libiio, or is my installation to blame?
And as a sidenote: Do the weird sensor readings originate from the sensor/driver acting up, or could this be related to the way that the samples are collected? The device was resting on the table while performing the measurements, and the measurements are rather inconsistent imo... :(
Thanks in advance!