Fast IO pin toggle with WiFi seems to cause issues

brebisson
Posts: 32
Joined: Fri Dec 22, 2023 9:44 am

Fast IO pin toggle with WiFi seems to cause issues

Postby brebisson » Sun Jan 26, 2025 2:29 pm

Hello,

In my project, I need to toggle an IO pin at speeds up to 20khz, while the wifi is running...

I have setup a 50µs clock using a GP timer (see code bellow), and in the IRQ routine, I will set/clear the pin as needed...

However, adding this in my code make the Wifi unreliable....
The IRQ code is short, it will compare time with a reference time and, if needed, issue a pulse and increment some counters...
I tried moving this code out of an IRQ, but it did not work as my motor movements became not-smooth...
Any advices on how to fix this?
Thanks,
Cyrille

Code: Select all


    void IRAM_ATTR next(uint32_t now)
    {
        if (currentSpd==0) return;
        if (int32_t(now-nextStepmus)<0) return;    // nothing to do. we wait
        nextStepmus+= deltaBetweenSteps;           // program allarm
        if (stpVal==0) { CGPIO::set(stp); stpVal= 1; } else { CGPIO::clear(stp); stpVal= 0; }
        if (currentSpd>=0) pos+= 1; else pos-= 1;      // increase pos
        if (pos==dst) { pos= dst; currentSpd= requestedSpd=0; return; } // destination reached!
    }
static bool IRAM_ATTR stepperTick(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_data)
{
    uint32_t now= micros(); next(now);
    return pdFALSE;
}
void initSteppers()
{
    gptimer_handle_t gptimer;
    gptimer_config_t timer_config = {
        .clk_src = GPTIMER_CLK_SRC_DEFAULT,
        .direction = GPTIMER_COUNT_UP,
        .resolution_hz = 1000000, // 1MHz, 1 tick=1us
    };
    ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
    gptimer_event_callbacks_t cbs = { .on_alarm = stepperTick, };
    ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, nullptr));
    gptimer_alarm_config_t alarm_config1; memset(&alarm_config1, 0, sizeof(alarm_config1));
    alarm_config1.reload_count = 0;
    alarm_config1.alarm_count = 50; // period = 50us or 20k spets/s!
    alarm_config1.flags.auto_reload_on_alarm = true;
    ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config1));
    ESP_ERROR_CHECK(gptimer_enable(gptimer));
    ESP_ERROR_CHECK(gptimer_start(gptimer));
}

MicroController
Posts: 2046
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Fast IO pin toggle with WiFi seems to cause issues

Postby MicroController » Sun Jan 26, 2025 6:43 pm

You may want to stop the timer/alarm when&while pos==dst, which may significantly reduce system load.
Allocating the timer+interrupt on the APP CPU may also reduce interference with WiFi.
Then you may want to look into ways to create the pulses you need by hardware, e.g. via the SPI or RMT peripheral.

brebisson
Posts: 32
Joined: Fri Dec 22, 2023 9:44 am

Re: Fast IO pin toggle with WiFi seems to cause issues

Postby brebisson » Sun Jan 26, 2025 9:01 pm

Hello,

> You may want to stop the timer/alarm when&while pos==dst, which may significantly reduce system load.
ok, easy, can do....

> Allocating the timer+interrupt on the APP CPU may also reduce interference with WiFi.
Can you help me understand this? How would I do that? How do I know what is running on which core?

> Then you may want to look into ways to create the pulses you need by hardware, e.g. via the SPI or RMT peripheral
What tricks would/could I use to do this?
Basically, I can calculate, every 10 to 100 milliseconds, how many, and when the pulses need to go out...
I could, assuming that I know the frequency of my output, create a bitmap of 0 and 1 bits...
How do I translate this into a "Hey, HW, can you please output this stream at this speed through this pin?" command?

Thanks,
Cyrille

MicroController
Posts: 2046
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Fast IO pin toggle with WiFi seems to cause issues

Postby MicroController » Mon Jan 27, 2025 8:12 am

brebisson wrote:
Sun Jan 26, 2025 9:01 pm
> Allocating the timer+interrupt on the APP CPU may also reduce interference with WiFi.
Can you help me understand this? How would I do that? How do I know what is running on which core?
For most IDF drivers, the interrupts are allocated on the core where the driver is initialized. So running the driver initialization from a task pinned to core 1 (APP CPU) usually does the trick.
Basically, I can calculate, every 10 to 100 milliseconds, how many, and when the pulses need to go out...
I could, assuming that I know the frequency of my output, create a bitmap of 0 and 1 bits...
How do I translate this into a "Hey, HW, can you please output this stream at this speed through this pin?" command?
With SPI you could send out a 1010101... pattern (0xAA) of desired length, the RMT is designed to output pulses.
Another, possibly easiest, way could be using a UART. At 100kBit/s you just let it send one byte (0xF0) for every pulse to get the 10kHz output (sending (part of) a predefined array of 0xF0 bytes in one go for efficiency when more than a single pulse is needed).

brebisson
Posts: 32
Joined: Fri Dec 22, 2023 9:44 am

Re: Fast IO pin toggle with WiFi seems to cause issues

Postby brebisson » Mon Jan 27, 2025 2:06 pm

Hello,

With regard to creating tasks pined to core... This is something that I know prety much nothing about. Could you help me, give me some pointers?

As far as I understand the usual way to work on the esp32 is for core 0 to handle the "system stuff", which includes the wifi handling while core 1 handles the application level stuff...

In my case, app_main will:
- start wifi (will tasks created there be on core 0 or 1?)
- setup my timer (Assuming that app_main is on core 0, this would be pinned on core 0, so not good)...
- Setup A TCP listener task which will create client handlers (never more than 1 or 2 at the same time)
- it will then handle UI by reading from serial and updating the LCD (so, this would run on core 0 I guess)?

But this is not really what I need to do apparently.
I can continue to have app_main init wifi
the setup of the TCP server is OK, but I should start the task on core 1
I should then start another task on core 1 which will setup my timer AND be the UI task.
app_main can then return (and will be deleted)..

Is this correct?

Thanks,
Cyrille

brebisson
Posts: 32
Joined: Fri Dec 22, 2023 9:44 am

Re: Fast IO pin toggle with WiFi seems to cause issues

Postby brebisson » Mon Jan 27, 2025 2:32 pm

Hello,

ok, I have tried to pin my task to core 1... But this does not seem to work! I get a crash with the following error:
xTaskCreatePinnedToCore(HWTask, "HWTask", 2048, nullptr, 2, nullptr, 1); << DOES NOT WORK
xTaskCreatePinnedToCore(HWTask, "HWTask", 2048, nullptr, 2, nullptr, 0); << WORK!!!

I am using an ESP32C3....
Using core 1 leads to this crash...

assert failed: xTaskCreatePinnedToCore freertos_tasks_c_additions.h:163 (( ( ( ( BaseType_t ) xCoreID ) >= 0 && ( ( BaseType_t ) xCoreID ) < 1 ) ? ( ( BaseType_t ) 1 ) : ( ( BaseType_t ) 0 ) ) == ( (
Core 0 register dump:
MEPC : 0x40380880 RA : 0x4038665a SP : 0x3fc9d7e0 GP : 0x3fc94200
--- 0x40380880: panic_abort at C:/Users/cydeb/esp/v5.4/esp-idf/components/esp_system/panic.c:468
0x4038665a: __ubsan_include at C:/Users/cydeb/esp/v5.4/esp-idf/components/esp_system/ubsan.c:311

What am I doing wrong?

Thanks,
Cyrille

MicroController
Posts: 2046
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Fast IO pin toggle with WiFi seems to cause issues

Postby MicroController » Mon Jan 27, 2025 2:40 pm

brebisson wrote:
Mon Jan 27, 2025 2:32 pm
I am using an ESP32C3....
Oh, ok. The -C3 only has a single core :) So nothing to be achieved on this end.

User avatar
ok-home
Posts: 116
Joined: Sun May 02, 2021 7:23 pm
Location: Russia Novosibirsk
Contact:

Re: Fast IO pin toggle with WiFi seems to cause issues

Postby ok-home » Mon Jan 27, 2025 3:02 pm

for c3
I think it's best to use RMT in continue mode, with a loop counter
it's guaranteed not to take up the CPU, it will give up control when it counts everything up
There is a limit on the number of pulses, you need to understand how many pulses are needed in a single transaction.

MicroController
Posts: 2046
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Fast IO pin toggle with WiFi seems to cause issues

Postby MicroController » Mon Jan 27, 2025 3:29 pm

ok-home wrote:
Mon Jan 27, 2025 3:02 pm
I think it's best to use RMT in continue mode, with a loop counter
:+1:

brebisson
Posts: 32
Joined: Fri Dec 22, 2023 9:44 am

Re: Fast IO pin toggle with WiFi seems to cause issues

Postby brebisson » Mon Jan 27, 2025 4:14 pm

Hello,

I'll be darned! I was certain that it was a dual core :-(

Ok, back to planning.

What is wrong with using the SPI to send a pulse which can be of variable size?
They are 3 phases to any movements.
Acceleration phase, regular speed and deceleration...
With a SPI speed equal to 4 times my max speed (i.e, 1 fast pulse is 4 bit set to true in the data), I can generate pulses of any longer length with 20% accuracy.
Speed = 20Khz, so at max speed, this is 80Khz SPI, and 10KBytes/s. Should be no problems...
Furthermore, since the acceleration to full speed happends in 1/5th of a second (2Kbytes), I could prepare 3 buffers
1 accelerate
1 run full speed for 1/5 of a second
1 decelerate
For a total of 6Kbytes.
I can then send n transactions request with the full speed buffer being used again and again (with a last use potentially using only part of it)...

Does that sound like a plan?

What does RMT do that would be better than that?

Cyrille

Who is online

Users browsing this forum: Bing [Bot], petterk and 90 guests