I am currently working on configuring SPI for the ADIS16460 using the following setup:
- Raspberry Pi 4B+ running Analog Devices Kuiper Linux.
- libiio v1.0, compiled from the source in the main branch.
- Two ADIS16460 devices connected to SPI, and their information can be accessed and displayed using iio_info.
iio_info iio_info version: 1.0 (git tag:7b973b58) Libiio version: 1.0 (git tag: 7b973b58) backends: local ip usb xml IIO context created with local backend. Backend version: 1.0 (git tag: 7b973b58) Backend description string: Linux analog 5.10.63-v7l+ #1 SMP Fri Mar 10 16:35:58 UTC 2023 armv7l IIO context has 4 attributes: attr 0: hw_carrier value: Raspberry Pi 4 Model B Rev 1.5 attr 1: dtoverlay value: vc4-kms-v3d,adis16460 attr 2: local,kernel value: 5.10.63-v7l+ attr 3: uri value: local: IIO context has 7 devices: hwmon0: cpu_thermal 1 channels found: temp1: (input) 1 channel-specific attributes found: attr 0: input (temp1_input) value: 46251 No trigger on this device hwmon1: rpi_volt 1 channels found: in0: (input) 1 channel-specific attributes found: attr 0: lcrit_alarm (in0_lcrit_alarm) value: 0 No trigger on this device iio:device0: adis16460 (buffer capable) 8 channels found: anglvel_x: (input, index: 0, format: be:S32/32>>0) 2 channel-specific attributes found: attr 0: raw (in_anglvel_x_raw) value: 984392 attr 1: scale (in_anglvel_scale) value: 0.000000001 anglvel_y: (input, index: 1, format: be:S32/32>>0) 2 channel-specific attributes found: attr 0: raw (in_anglvel_y_raw) value: 5555135 attr 1: scale (in_anglvel_scale) value: 0.000000001 anglvel_z: (input, index: 2, format: be:S32/32>>0) 2 channel-specific attributes found: attr 0: raw (in_anglvel_z_raw) value: -851792 attr 1: scale (in_anglvel_scale) value: 0.000000001 accel_x: (input, index: 3, format: be:S32/32>>0) 2 channel-specific attributes found: attr 0: raw (in_accel_x_raw) value: 9895935 attr 1: scale (in_accel_scale) value: 0.000000037 accel_y: (input, index: 4, format: be:S32/32>>0) 2 channel-specific attributes found: attr 0: raw (in_accel_y_raw) value: 131071 attr 1: scale (in_accel_scale) value: 0.000000037 accel_z: (input, index: 5, format: be:S32/32>>0) 2 channel-specific attributes found: attr 0: raw (in_accel_z_raw) value: -261816320 attr 1: scale (in_accel_scale) value: 0.000000037 temp0: (input, index: 6, format: be:S16/16>>0) 3 channel-specific attributes found: attr 0: offset (in_temp0_offset) value: 500 attr 1: raw (in_temp0_raw) value: 42 attr 2: scale (in_temp0_scale) value: 50 timestamp: (input, index: 7, format: le:S64/64>>0) 2 device-specific attributes found: attr 0: current_timestamp_clock value: realtime attr 1: sampling_frequency value: 2048.000000 Current trigger: trigger0(adis16460-dev0) iio:device1: adis16460 (buffer capable) 8 channels found: anglvel_x: (input, index: 0, format: be:S32/32>>0) 2 channel-specific attributes found: attr 0: raw (in_anglvel_x_raw) value: 823395 attr 1: scale (in_anglvel_scale) value: 0.000000001 anglvel_y: (input, index: 1, format: be:S32/32>>0) 2 channel-specific attributes found: attr 0: raw (in_anglvel_y_raw) value: 4403151 attr 1: scale (in_anglvel_scale) value: 0.000000001 anglvel_z: (input, index: 2, format: be:S32/32>>0) 2 channel-specific attributes found: attr 0: raw (in_anglvel_z_raw) value: 1639127 attr 1: scale (in_anglvel_scale) value: 0.000000001 accel_x: (input, index: 3, format: be:S32/32>>0) 2 channel-specific attributes found: attr 0: raw (in_accel_x_raw) value: -10027008 attr 1: scale (in_accel_scale) value: 0.000000037 accel_y: (input, index: 4, format: be:S32/32>>0) 2 channel-specific attributes found: attr 0: raw (in_accel_y_raw) value: 6946815 attr 1: scale (in_accel_scale) value: 0.000000037 accel_z: (input, index: 5, format: be:S32/32>>0) 2 channel-specific attributes found: attr 0: raw (in_accel_z_raw) value: 263716863 attr 1: scale (in_accel_scale) value: 0.000000037 temp0: (input, index: 6, format: be:S16/16>>0) 3 channel-specific attributes found: attr 0: offset (in_temp0_offset) value: 500 attr 1: raw (in_temp0_raw) value: 4 attr 2: scale (in_temp0_scale) value: 50 timestamp: (input, index: 7, format: le:S64/64>>0) 2 device-specific attributes found: attr 0: current_timestamp_clock value: realtime attr 1: sampling_frequency value: 2048.000000 No trigger assigned to device iio_sysfs_trigger: 0 channels found: 2 device-specific attributes found: attr 0: add_trigger value: ERROR: Permission denied (-13) attr 1: remove_trigger value: ERROR: Permission denied (-13) No trigger on this device trigger0: adis16460-dev0 0 channels found: No trigger on this device trigger1: adis16460-dev1 0 channels found: No trigger on this device
The SPI speed is configured in the Device Tree to a maximum of 2MHz. Given the 2048SPS conversion rate of the sensor, this setup enables sampling data from it at a frequency of 2kHz.
#include <iio/iio.h>
#include <iio/iio-debug.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
// Context
struct iio_context *ctx;
// Channel name
const char *chn_name = "accel_z";
// Streaming devices
struct iio_device *dev0;
struct iio_device *trigger0;
// Channels
struct iio_channel *dev0_chn;
// Masks
struct iio_channels_mask *dev0_mask;
// Buffers
struct iio_buffer *dev0_buff;
// Streams
struct iio_stream *dev0_stream;
// Sample Size
size_t dev0_sample_sz;
// Error
int err;
printf("* Acquiring IIO context *\n");
ctx = iio_create_context(NULL, "local:");
printf("* Acquiring ADI14640 streaming device *\n");
dev0 = iio_context_find_device(ctx, "iio:device0");
printf("* Acquiring trigger0 streaming device *\n");
trigger0 = iio_context_find_device(ctx, "trigger0");
iio_device_set_trigger(dev0, trigger0);
printf("Check if trigger0 is a trigger: %d\n", iio_device_is_trigger(iio_device_get_trigger(dev0)));
printf("* Acquiring IIO channels *\n");
dev0_chn = iio_device_find_channel(dev0, chn_name, false);
printf("* Channelname: %s *\n", iio_channel_get_id(dev0_chn));
printf("* Acquiring IIO channel mask *\n");
dev0_mask = iio_create_channels_mask(iio_device_get_channels_count(dev0));
printf("* Enabling IIO channel mask *\n");
iio_channel_enable(dev0_chn, dev0_mask);
printf("* Creating IIO buffers *\n");
dev0_buff = iio_device_create_buffer(dev0, 0, dev0_mask);
size_t sample = iio_device_get_sample_size(dev0, dev0_mask);
printf("Error: %d\n", iio_err(dev0_buff));
printf("* Creating IIO streams *\n");
dev0_stream = iio_buffer_create_stream(dev0_buff, 4, 4);
printf("Error: %d\n", iio_err(dev0_stream));
printf("* Reading IIO streams *\n");
const struct iio_block* block = iio_stream_get_next_block(dev0_stream);
return 0;
}
I've configured a C file to interface with an ADIS16460 sensor, connecting the trigger to it. Initially, my focus is on reading a single channel, with plans to expand to all channels later. I've created a buffer and initiated the buffer stream. According to the Libiio v1.0 documentation, the recommended method for reading sensor data is through iio_stream_get_next_block. However, I encounter an error: "ERROR: iio:device0: Unable to enable buffer: Invalid argument (22)." If I successfully obtain iio_stream_get_next_block, I'm unsure how to extract the channel data into a float value. Any guidance on this would be greatly appreciated.
Full C Log:
sudo ./main * Acquiring IIO context * * Acquiring ADI14640 streaming device * * Acquiring trigger0 streaming device * Check if trigger0 is a trigger: 1 * Acquiring IIO channels * * Channelname: accel_z * * Acquiring IIO channel mask * * Enabling IIO channel mask * * Creating IIO buffers * Error: 0 * Creating IIO streams * Error: 0 * Reading IIO streams * ERROR: iio:device0: Unable to enable buffer: Invalid argument (22)
I have an additional inquiry: why is it necessary to initiate the program using sudo? Without it, the program fails to create a buffer, encountering a permission error.