Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using ESPIDF to program on ESP32-C6 for receiving data with SPI (IDFGH-12704) #13691

Closed
3 tasks done
Rickxiaoxin opened this issue Apr 25, 2024 · 9 comments
Closed
3 tasks done
Labels
Status: Opened Issue is new Type: Bug bugs in IDF

Comments

@Rickxiaoxin
Copy link

Rickxiaoxin commented Apr 25, 2024

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

IDF version.

5.2.1

Espressif SoC revision.

ESP32-C6

Operating System used.

Windows

How did you build your project?

VS Code IDE

If you are using Windows, please specify command line type.

PowerShell

Development Kit.

ESP32-C6-DevKitC-1

Power Supply used.

USB

What is the expected behavior?

can obtain stable data like this
image

What is the actual behavior?

can't obtain stable data
image

Steps to reproduce.

this is my code.

static void IRAM_ATTR gpio_isr_handler(void *arg)
{
    uint32_t gpio_num = (uint32_t)arg;
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}

static void gpio_task(void *arg)
{
    uint32_t io_num;
    uint8_t val[9] = {0};
    for (;;)
    {
        if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY))
        {

            for (int i = 0; i < 9; i++)
            {
                val[i] = ads1292r_receive_data(spi_handle);
            }
            printf("%x %x %x %x %x %x %x %x %x \n", val[0], val[1], val[2],
                   val[3], val[4], val[5],
                   val[6], val[7], val[8]);
            usleep(3000);
        }
    }
}

void app_main(void)
{
    // gpio config
    gpio_config_t io_conf;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
    io_conf.pull_down_en = 0;
    io_conf.pull_up_en = 0;
    gpio_config(&io_conf);
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pin_bit_mask = BIT64(GPIO_DRDY);
    io_conf.pull_down_en = 0;
    io_conf.pull_up_en = 1;
    io_conf.intr_type = GPIO_INTR_NEGEDGE;
    gpio_config(&io_conf);

    // gpio isr
    gpio_evt_queue = xQueueCreate(100, sizeof(uint32_t));
    xTaskCreate(gpio_task, "gpio_task", 4096, NULL, 15, NULL);
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    gpio_isr_handler_add(GPIO_DRDY, gpio_isr_handler, (void *)GPIO_DRDY);

    // uart config
    uart_config_t uart_config = {
        .baud_rate = 115200,
        .data_bits = UART_DATA_8_BITS,
        .parity = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk = UART_SCLK_DEFAULT,
    };
    uart_driver_install(UART_NUM_0, 512 * 2, 0, 0, NULL, 0);
    uart_param_config(UART_NUM_0, &uart_config);
    uart_set_pin(UART_NUM_0, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);

    // spi config
    spi_bus_config_t spi_bus_cfg = {
        .mosi_io_num = GPIO_MOSI,
        .miso_io_num = GPIO_MISO,
        .sclk_io_num = GPIO_SCLK,
        .quadhd_io_num = -1,
        .quadwp_io_num = -1,
    };
    spi_bus_initialize(SPI2_HOST, &spi_bus_cfg, SPI_DMA_CH_AUTO);
    spi_device_interface_config_t dev_cfg = {
        .clock_speed_hz = 1 * 1000 * 1000,
        .mode = 1,
        .spics_io_num = -1,
        .queue_size = 1,
    };
    spi_bus_add_device(SPI2_HOST, &dev_cfg, &spi_handle);

    ads1292r_init(spi_handle);
}

Debug Logs.

no error was reported

More Information.

I'm using esp32-c6 and ads1292r to acquire ECG data. I have successfully established communication with the ADS1292R through SPI and am able to write to and read from the ADS1292R registers. I also use gpio interrupt to send queue, and create task to receive queue, then receive data from ads1292r. When I set sample rate to 125Hz, I can receive stable data from ads1292r without connecting to body. However, I can't obtain stable data when I set sample rate to 250Hz, and the received data is misaligned and wrong.
I think this might be due to issues with FreeRTOS task scheduling,but I'm not certain and don't know how to address this problem.I want to achieve to obtain right data .I would appreciate it if someone could give me some help!

@Rickxiaoxin Rickxiaoxin added the Type: Bug bugs in IDF label Apr 25, 2024
@espressif-bot espressif-bot added the Status: Opened Issue is new label Apr 25, 2024
@github-actions github-actions bot changed the title Using ESPIDF to program on ESP32-C6 for receiving data with SPI Using ESPIDF to program on ESP32-C6 for receiving data with SPI (IDFGH-12704) Apr 25, 2024
@nopnop2002
Copy link

nopnop2002 commented Apr 26, 2024

It's most likely a printf issue.
What happens if you change printf to ESP_LOGx?

            printf("%x %x %x %x %x %x %x %x %x \n", val[0], val[1], val[2],
                   val[3], val[4], val[5],
                   val[6], val[7], val[8]);

@wanckl
Copy link
Contributor

wanckl commented Apr 28, 2024

for (int i = 0; i < 9; i++)
    {
        val[i] = ads1292r_receive_data(spi_handle);
    }

Seems you using SPI read only 1 byte for 1 transaction, ,,there may some order issue, this chip should support read 1 pack(9 bytes) in one transaction, that should more stable.

And then, what the convention resolution you set for 250Hz, different resolution need different time to finish convention.

And SPI transaction also need time, refer to your datasheet bellow, you can also increase your SPI bus frequency.
image

@Rickxiaoxin
Copy link
Author

It's most likely a printf issue. What happens if you change printf to ESP_LOGx?

            printf("%x %x %x %x %x %x %x %x %x \n", val[0], val[1], val[2],
                   val[3], val[4], val[5],
                   val[6], val[7], val[8]);

@nopnop2002 I'm very sorry for the late response. I feel that the issue may lie in SPI communication. Currently, I'm using polling instead of interrupts for SPI communication and have lowered the sampling rate to ensure receiving correct information.I will try the method you mentioned and will reply later with the results.

@Rickxiaoxin
Copy link
Author

for (int i = 0; i < 9; i++)
    {
        val[i] = ads1292r_receive_data(spi_handle);
    }

Seems you using SPI read only 1 byte for 1 transaction, ,,there may some order issue, this chip should support read 1 pack(9 bytes) in one transaction, that should more stable.

And then, what the convention resolution you set for 250Hz, different resolution need different time to finish convention.

And SPI transaction also need time, refer to your datasheet bellow, you can also increase your SPI bus frequency. image

@wanckl I'm very sorry for the late response.I previously used the same settings in STM32, and I could receive correct information. Initially, I was communicating by receiving 9 bytes at once, which also encountered the aforementioned issue. Later, I changed it to receive one byte at a time. The problem was resolved after I disabled the task watchdog and interrupt watchdog, and set FreeRTOS config tick=100 to 1000. However, I'm not sure why this resolved the issue.

@nopnop2002
Copy link

nopnop2002 commented Apr 29, 2024

I disabled the task watchdog and interrupt watchdog

usleep(10000) and vTaskDelay(1) both wait 10ms, but using usleep will cause a TaskWatchDog alert regardless of the wait time.

// TaskWatchDog alerts are not fired.
while(1) {
  vTaskDelay(1); // wait for 10mSec
}
// TaskWatchDog alerts are fired.
while(1) {
  usleep(10000); // wait for 10mSec
}

If you use usleep, you must disable task watchdog.
If you disable TaskWatchDog, there is no need to wait at all.

static void gpio_task(void *arg)
{
    uint32_t io_num;
    uint8_t val[9] = {0};
    for (;;)
    {
        if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY))
        {

            for (int i = 0; i < 9; i++)
            {
                val[i] = ads1292r_receive_data(spi_handle);
            }
            printf("%x %x %x %x %x %x %x %x %x \n", val[0], val[1], val[2],
                   val[3], val[4], val[5],
                   val[6], val[7], val[8]);
            //usleep(3000);
        }
    }
}

@Rickxiaoxin
Copy link
Author

I disabled the task watchdog and interrupt watchdog

usleep(10000) and vTaskDelay(1) both wait 10ms, but using usleep will cause a TaskWatchDog alert regardless of the wait time.

// TaskWatchDog alerts are not fired.
while(1) {
  vTaskDelay(1); // wait for 10mSec
}
// TaskWatchDog alerts are fired.
while(1) {
  usleep(10000); // wait for 10mSec
}

If you use usleep, you must disable task watchdog. If you disable TaskWatchDog, there is no need to wait at all.

static void gpio_task(void *arg)
{
    uint32_t io_num;
    uint8_t val[9] = {0};
    for (;;)
    {
        if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY))
        {

            for (int i = 0; i < 9; i++)
            {
                val[i] = ads1292r_receive_data(spi_handle);
            }
            printf("%x %x %x %x %x %x %x %x %x \n", val[0], val[1], val[2],
                   val[3], val[4], val[5],
                   val[6], val[7], val[8]);
            //usleep(3000);
        }
    }
}

@nopnop2002 Thank you very much. Now I know function usleep will trigger the task watchdog, I will try it!

@nopnop2002
Copy link

Now I know function usleep will trigger the task watchdog

To be precise, usleep() cannot avoid TaskWatchDog alerts.

@Rickxiaoxin
Copy link
Author

Now I know function usleep will trigger the task watchdog

To be precise, usleep() cannot avoid TaskWatchDog alerts.

So only the vTaskDelay() function can avoid TaskWatchDog alerts?

@nopnop2002
Copy link

nopnop2002 commented Apr 29, 2024

So only the vTaskDelay() function can avoid TaskWatchDog alerts?

Yes. You are right.

I think esp_task_wdt_reset() can also avoid TaskWatchDog alerts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Opened Issue is new Type: Bug bugs in IDF
Projects
None yet
Development

No branches or pull requests

4 participants