FIFO ADXL362 like in accel_polling with RTIO

 I am trying to use the FIFO from the ADXL362 with in the Thingy:53. As I noticed there is now the Option to use ADXL362_STREAM. I just wanted to use the example from: https://github.com/zephyrproject-rtos/zephyr/tree/main/samples/sensor/accel_polling. I did a bit of changes, because the frequency of the ADXL362 can not be changed over set() in the runtime. Otherwise I thought it should work. I noticed that the FIFO_WATERMARK usage is kind of new implemented. So I just changed the adi,adxl362.yaml so that I can set the fifo-watermark in an overlay file. I do not know if this is even possible, but my build works. 

The problem is that: 

cqe = rtio_cqe_consume_block(&accel_ctx); is blocking. So it seems that the Watermark and fifo are not working. the question is why?
I work with th nrf SDK v3.0.0 and the Toolchain v3.0.0 and the Thingy:53.
I want to use the FIFO because with just polling by 400 Hz ODR I gut just about 377 samples/second. Or would that be not any different with the FIFO usage? 
/*
* Copyright (c) 2022 TOKITA Hiroshi <[email protected]
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <stdio.h>
#include <stdlib.h>

#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/sys/util_macro.h>
#include <zephyr/kernel.h>
#include <zephyr/rtio/rtio.h>
#include <zephyr/drivers/sensor.h>

#define ACCEL_ALIAS(i) DT_ALIAS(_CONCAT(accel, i))
#define ACCELEROMETER_DEVICE(i, _) \
IF_ENABLED(DT_NODE_EXISTS(ACCEL_ALIAS(i)), (DEVICE_DT_GET(ACCEL_ALIAS(i)),))
#define NUM_SENSORS 1

/* support up to 10 accelerometer sensors */
static const struct device *const sensors[] = {LISTIFY(10, ACCELEROMETER_DEVICE, ())};

#ifdef CONFIG_SENSOR_ASYNC_API

#define ACCEL_IODEV_SYM(id) CONCAT(accel_iodev, id)
#define ACCEL_IODEV_PTR(id, _) &ACCEL_IODEV_SYM(id)

#define ACCEL_TRIGGERS \
{SENSOR_TRIG_FIFO_FULL, SENSOR_STREAM_DATA_INCLUDE}, \
{SENSOR_TRIG_FIFO_WATERMARK, SENSOR_STREAM_DATA_DROP}

#define ACCEL_DEFINE_IODEV(id, _) \
SENSOR_DT_STREAM_IODEV( \
ACCEL_IODEV_SYM(id), \
ACCEL_ALIAS(id), \
ACCEL_TRIGGERS);

LISTIFY(NUM_SENSORS, ACCEL_DEFINE_IODEV, (;));

struct rtio_iodev *iodevs[NUM_SENSORS] = { LISTIFY(NUM_SENSORS, ACCEL_IODEV_PTR, (,)) };

RTIO_DEFINE_WITH_MEMPOOL(accel_ctx, NUM_SENSORS, NUM_SENSORS, NUM_SENSORS*20, 256, sizeof(void *));

static int print_accels_stream(const struct device *dev, struct rtio_iodev *iodev)
{
int rc = 0;
struct sensor_three_axis_data accel_data = {0};
const struct sensor_decoder_api *decoder;
struct rtio_cqe *cqe;
uint8_t *buf;
uint32_t buf_len;
struct rtio_sqe *handles[NUM_SENSORS];

/* Start the streams */
for (int i = 0; i < NUM_SENSORS; i++) {
printk("sensor_stream\n");
sensor_stream(iodevs[i], &accel_ctx, NULL, &handles[i]);
}

while (1) {
cqe = rtio_cqe_consume_block(&accel_ctx);

if (cqe->result != 0) {
printk("async read failed %d\n", cqe->result);
return cqe->result;
}

rc = rtio_cqe_get_mempool_buffer(&accel_ctx, cqe, &buf, &buf_len);

if (rc != 0) {
printk("get mempool buffer failed %d\n", rc);
return rc;
}

const struct device *sensor = dev;

rtio_cqe_release(&accel_ctx, cqe);

rc = sensor_get_decoder(sensor, &decoder);

if (rc != 0) {
printk("sensor_get_decoder failed %d\n", rc);
return rc;
}

/* Frame iterator values when data comes from a FIFO */
uint32_t accel_fit = 0;

/* Number of accelerometer data frames */
uint16_t frame_count;

rc = decoder->get_frame_count(buf,
(struct sensor_chan_spec) {SENSOR_CHAN_ACCEL_XYZ, 0}, &frame_count);

if (rc != 0) {
printk("sensor_get_decoder failed %d\n", rc);
return rc;
}

/* If a tap has occurred lets print it out */
if (decoder->has_trigger(buf, SENSOR_TRIG_TAP)) {
printk("Tap! Sensor %s\n", dev->name);
}

/* Decode all available accelerometer sample frames */
for (int i = 0; i < frame_count; i++) {
decoder->decode(buf, (struct sensor_chan_spec) {SENSOR_CHAN_ACCEL_XYZ, 0},
&accel_fit, 1, &accel_data);

printk("Accel data for %s (%" PRIq(6) ", %" PRIq(6)
", %" PRIq(6) ") %lluns\n", dev->name,
PRIq_arg(accel_data.readings[0].x, 6, accel_data.shift),
PRIq_arg(accel_data.readings[0].y, 6, accel_data.shift),
PRIq_arg(accel_data.readings[0].z, 6, accel_data.shift),
(accel_data.header.base_timestamp_ns
+ accel_data.readings[0].timestamp_delta));
}

rtio_release_buffer(&accel_ctx, buf, buf_len);
}

return rc;
}
#else

static const enum sensor_channel channels[] = {
SENSOR_CHAN_ACCEL_X,
SENSOR_CHAN_ACCEL_Y,
SENSOR_CHAN_ACCEL_Z,
};

static int print_accels(const struct device *dev)
{
int ret;
struct sensor_value accel[3];

ret = sensor_sample_fetch(dev);
if (ret < 0) {
printk("%s: sensor_sample_fetch() failed: %d\n", dev->name, ret);
return ret;
}

for (size_t i = 0; i < ARRAY_SIZE(channels); i++) {
ret = sensor_channel_get(dev, channels[i], &accel[i]);
if (ret < 0) {
printk("%s: sensor_channel_get(%c) failed: %d\n", dev->name, 'X' + i, ret);
return ret;
}
}

printk("%16s [m/s^2]: (%12.6f, %12.6f, %12.6f)\n", dev->name,
sensor_value_to_double(&accel[0]), sensor_value_to_double(&accel[1]),
sensor_value_to_double(&accel[2]));

return 0;
}
#endif /*CONFIG_SENSOR_ASYNC_API*/



int main(void)
{
int ret;

for (size_t i = 0; i < ARRAY_SIZE(sensors); i++) {
if (!device_is_ready(sensors[i])) {
printk("sensor: device %s not ready.\n", sensors[i]->name);
return 0;
}
}

#ifndef CONFIG_COVERAGE
while (1) {
#else
for (int i = 0; i < 5; i++) {
#endif
for (size_t i = 0; i < ARRAY_SIZE(sensors); i++) {
#ifdef CONFIG_SENSOR_ASYNC_API
ret = print_accels_stream(sensors[i], iodevs[i]);
#else
ret = print_accels(sensors[i]);
#endif /*CONFIG_SENSOR_ASYNC_API*/
if (ret < 0) {
return 0;
}
}
k_msleep(1000);
}
return 0;
}
(sorry I had Problems attaching the main() but its all from: https://github.com/zephyrproject-rtos/zephyr/tree/main/samples/sensor/accel_polling.)
Parents
  • Hi Pauline, 

    This is an external sensor usage with a sample in Zephyr. For best results, you should post this in the Zephyr forums.

    Just trying to think loud here.

    I would check the overlay for the FIFO mode and watermark value, googling about it shows different kind of watermark values (8) but I might be reading this wrong as I am not an expert on this sensor.

    Also make sure that the INT1 and INT2 of that sensor is connected to valid GPIOs of the NRF chip.

    I want to use the FIFO because with just polling by 400 Hz ODR I gut just about 377 samples/second. Or would that be not any different with the FIFO usage? 

    Polling is not power friendly and using FIFO with interrupts is better for both throughput and power efficiency. If you do not worry too much about the power, then polling is simpler.

Reply
  • Hi Pauline, 

    This is an external sensor usage with a sample in Zephyr. For best results, you should post this in the Zephyr forums.

    Just trying to think loud here.

    I would check the overlay for the FIFO mode and watermark value, googling about it shows different kind of watermark values (8) but I might be reading this wrong as I am not an expert on this sensor.

    Also make sure that the INT1 and INT2 of that sensor is connected to valid GPIOs of the NRF chip.

    I want to use the FIFO because with just polling by 400 Hz ODR I gut just about 377 samples/second. Or would that be not any different with the FIFO usage? 

    Polling is not power friendly and using FIFO with interrupts is better for both throughput and power efficiency. If you do not worry too much about the power, then polling is simpler.

Children
No Data
Related