SENT protocol based sensor configuration with nrf boards

hey there, i have a project which uses  nrf9151 with a pressures sensor from BOSCH which uses SENT protocol to transfer data, my question is

1. Is it possible to configure the SENT protocol on the nrf9151
2. if yes, how am i gonna configure what should i use?

  • Hello,

    We don't have any SENT peripheral on the nRF91 series (or any of the other device that we have). 

    I have not heard about it before, but is it a 1 wire protocol, where they just have a longer pulse for higher value? Or how does it work?

    And how is the flow? Do you need to request the data? Or will it continuously send data using the SENT protocol? How about the voltage level of the signal? What does it look like?

    Best regards,

    Edvin

  • Hi,

    I have not heard about it before, but is it a 1 wire protocol, where they just have a longer pulse for higher value? Or how does it work?

    SENT protocol is (SINGLE EDGE NIBBLE TRANSFER) which transfer data encoded in the falling to falling edge period of the signal, it works according to the (SAE J2716 JAN 2010 standard).


    And how is the flow? Do you need to request the data? Or will it continuously send data using the SENT protocol? How about the voltage level of the signal? What does it look like?


    No ,it continuously send data we don't need to request it. the voltage level is it operates on 5v.

    https://devzone.nordicsemi.com/f/nordic-q-a/78001/sent-protocol-driver-using-nrf-timer-captures

    i have tried the approach this dude shared but i am unable to get any capture period, also i can not use ADC as its an digital signal.

  • #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <nrfx_gpiote.h>
    #include <nrfx_timer.h>
    #include <nrfx_ppi.h>
    #include <zephyr/sys/printk.h>

    #define SENT_GPIO_PIN 11 // Replace with your actual GPIO pin number

    nrfx_timer_t timer = NRFX_TIMER_INSTANCE(0);
    static uint32_t pulse_buffer[64];
    static uint8_t pulse_index = 0;
    static uint32_t last_capture = 0;
    static uint8_t last_printed_index = 0;

    void gpio_handler(nrfx_gpiote_pin_t pin, nrfx_gpiote_trigger_t trigger, void *p_context)
    {
    uint32_t capture_value = nrf_timer_cc_get(timer.p_reg, NRF_TIMER_CC_CHANNEL0);
    uint32_t pulse_width = capture_value - last_capture;
    last_capture = capture_value;
    pulse_buffer[pulse_index] = pulse_width;
    pulse_index = (pulse_index + 1) % 64;
    }

    void timer_handler(nrf_timer_event_t event_type, void *p_context)
    {
    }

    int main()
    {
    printk("Starting pressure sensor example\n\r");
    int err_code;
    if (!nrfx_gpiote_is_init())
    {
    err_code = nrfx_gpiote_init(0);
    }
    uint8_t gpiote_channel_index;
    err_code = nrfx_gpiote_channel_alloc(&gpiote_channel_index);
    if (err_code != NRFX_SUCCESS)
    {
    printk("Failed to allocate GPIOTE channel. Error code: %d\n", err_code);
    return -1;
    }

    nrfx_gpiote_input_config_t input_config = {
    .pull = NRF_GPIO_PIN_PULLUP};

    nrfx_gpiote_trigger_config_t trigger_config = {
    .trigger = NRFX_GPIOTE_TRIGGER_HITOLO,
    .p_in_channel = &gpiote_channel_index};

    nrfx_gpiote_handler_config_t handler_config = {
    .handler = gpio_handler,
    .p_context = NULL};

    err_code = nrfx_gpiote_input_configure(SENT_GPIO_PIN, &input_config, &trigger_config, &handler_config);
    if (err_code != NRFX_SUCCESS)
    {
    printk("GPIOTE input configuration failed with error code: %d\n", err_code);
    return -1;
    }
    printk("GPIOTE configured for pin %d, channel %d\n", SENT_GPIO_PIN, gpiote_channel_index);
    uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(timer.p_reg);
    printk("Frequency is %d\n\r", base_frequency);
    nrfx_timer_config_t config = NRFX_TIMER_DEFAULT_CONFIG(base_frequency);
    config.mode = NRF_TIMER_MODE_TIMER;
    config.bit_width = NRF_TIMER_BIT_WIDTH_32;
    config.p_context = &timer;
    err_code = nrfx_timer_init(&timer, &config, timer_handler);
    if (err_code != NRFX_SUCCESS)
    {
    printk("Timer initialization failed. Error code: %d\n", err_code);
    return -1;
    }

    // Configure timer to clear on every 3µs (assuming 16MHz timer frequency)
    // nrf_timer_cc_set(timer.p_reg, NRF_TIMER_CC_CHANNEL1, 16 * 3);
    // nrf_timer_shorts_enable(timer.p_reg, NRF_TIMER_SHORT_COMPARE1_CLEAR_MASK);

    // Enable Timer
    nrfx_timer_enable(&timer);

    // nrf_timer_cc_set(timer.p_reg, NRF_TIMER_CC_CHANNEL0, 16000000); // 1 second interval
    // nrf_timer_shorts_enable(timer.p_reg, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK);
    nrf_timer_int_enable(timer.p_reg, NRF_TIMER_INT_COMPARE0_MASK);
    nrfx_gpiote_trigger_enable(SENT_GPIO_PIN, true);

    // Configure PPI
    nrf_ppi_channel_t ppi_channel;
    err_code = nrfx_ppi_channel_alloc(&ppi_channel);
    if (err_code != NRFX_SUCCESS)
    {
    printk("PPI channel allocation failed with error code: %d\n", err_code);
    return -1;
    }

    printk("PPI channel allocated\n\r");

    // Set up the event endpoint
    nrf_gpiote_event_t gpiote_event = nrf_gpiote_event_pin_get(NRF_GPIOTE, gpiote_channel_index);
    uint32_t gpiote_event_addr = nrf_gpiote_event_address_get(NRF_GPIOTE, gpiote_event);

    // Set up the task endpoint
    nrf_timer_task_t timer_task = NRF_TIMER_TASK_CAPTURE0;
    uint32_t timer_task_addr = nrf_timer_task_address_get(timer.p_reg, timer_task);

    // Connect the event and task using PPI
    err_code = nrfx_ppi_channel_assign(ppi_channel, gpiote_event_addr, timer_task_addr);
    if (err_code != NRFX_SUCCESS)
    {
    printk("PPI channel assignment failed with error code: %d\n", err_code);
    return -1;
    }

    printk("PPI channel assigned\n\r");

    // Enable the PPI channel
    err_code = nrfx_ppi_channel_enable(ppi_channel);
    if (err_code != NRFX_SUCCESS)
    {
    printk("PPI channel enable failed with error code: %d\n", err_code);
    return -1;
    }

    printk("PPI channel enabled\n\r");

    // Enable GPIOTE interrupt

    printk("GPIOTE Event Address: 0x%08X\n\r", gpiote_event_addr);
    printk("Timer Task Address: 0x%08X\n\r", timer_task_addr);

    while (1)
    {
    printk("Pulse %d: %u ticks\n\r", last_printed_index, pulse_buffer[last_printed_index]);
    last_printed_index = (last_printed_index + 1) % 64;
    k_sleep(K_MSEC(1000));
    }
    }
  • The above is my implementation according to this

    SENT protocol driver using nRF Timer captures

    can someone please guide me where am i going wrong because i am unable to read any capture falling to falling edge period.

    thank you

  • Something like this may work. What will happen is that it will automatically capture the TIMER value when the GPIO event triggers, that you can then read out in the gpio_handler, as you do. The issue is that you are dependent of the CPU to store away the buffer using the gpio_handler(). If the CPU is busy handling something else, only for a short time, that is fine, because the gpio_handler() will be called when that initial task is done. But if the CPU is busy for a bit longer, or two of the pulses are really close to eachother, then you risk not being able to handle the first interrupt before the second one occurs, and you risk that your application interprets two pulses as one that is the sum of the two (because the PPI task will trigger everytime. It doesn't know whether you have had time to update the last_capture parameter yet or not).

    I don't know at what rates these pulses come. What is the shortest possible pulse? If you want to try this, I suggest that you set the gpio_handler priority very high. 

    Best regards,

    Edvin

Related