Checking GPIO level in ULP on the ESP32S2

DylanWork
Posts: 32
Joined: Wed Jun 02, 2021 4:27 am

Checking GPIO level in ULP on the ESP32S2

Postby DylanWork » Tue Nov 23, 2021 2:13 pm

Hi all,

I am currently stuck trying to understand what is happening with my code in ULP.

I am using an IRLED and phototransistor combo to detect entry events using the ULP.

I originally used this example:
https://github.com/espressif/esp-idf/tr ... riscv/gpio

Which puts the ULP processor into an infinite while loop until the wakeup function is called.

I have now begun utilising the ULP without the infinite while loop like this new example:
https://github.com/espressif/esp-idf/tr ... 20_onewire

However, now that I turn the ULP off and on every 300ms, it appears that the pin config is incorrect after the first reset (assumption, unlikely true, the real change is explained below).

Example:
  1. [code]
  2.     for(int i = 13; i < 17; ++i){                                    //cycle through GPIO's 13 to 16
  3.         wait(2000);                                                     //Keep LED's off for 1000 cycles
  4.         example_ulp_gpio_init(i);                                //Init LED Pin
  5.         example_ulp_gpio_output_enable(i);                //Set LED pin as input/drain
  6.         example_ulp_gpio_set_output_mode(i, 1);        //Set LED output to high
  7.         wait(2000);                                                     //Keep LED on for 2000 cycles
  8.  
  9.         gpio_level = (bool)example_ulp_gpio_get_level(GPIO_NUM_21);     //Check level of Phototransistor
  10.         if((bool)example_ulp_gpio_get_level(GPIO_NUM_21))
  11.         {                                                                                                  //If phototransistor level is 1 - an LED is being blocked
  12.           yellow_heartbeat();
  13.         }
  14.         wait(6000);                                                     //Keep LED on for 6000 cycles
  15.         example_ulp_gpio_output_disable(i);
  16.         example_ulp_gpio_deinit(i);
  17.  
  18.     }
  19. [/code]
This code while in the infinite while loop works everytime.

However without the infinite while loop it works the first time the gpio_level is changed and then never again.

It seems as though I need setup the GPIO lines at the beginning of the main loop, I have tried this:

Code: Select all

[Codebox=c file=Untitled.c]
   example_ulp_gpio_init(GPIO_NUM_21);
    example_ulp_gpio_input_enable(GPIO_NUM_21);
    example_ulp_gpio_pulldown_disable(GPIO_NUM_21);
    example_ulp_gpio_pullup_disable(GPIO_NUM_21);
[/Codebox]
But no progress as of yet.

I hope I've explained this issue well enough.

I have searched the forums and the datasheet to understand how to configure the pins in ULP but I'm falling short of a solution.

Using the get_level function in ULP seems like a pretty straight forward process, so I'm not understanding where I could be going wrong, hopefully it's something simple that I've missed...

Any help is greatly appreciated,
Cheers

DylanWork
Posts: 32
Joined: Wed Jun 02, 2021 4:27 am

Re: Checking GPIO level in ULP on the ESP32S2

Postby DylanWork » Wed Nov 24, 2021 1:33 pm

Hi all,

To give a clear example of the issue occurring here.

This code does not work:

Code: Select all

int main (void)
{
    for(int i = 13; i < 17; ++i){                                    //Cycle through IRLED GPIO's
        wait(2000);                                                     //Keep LED's off for 2000 cycles
        example_ulp_gpio_init(i);                                       //Init LED Pin
        example_ulp_gpio_output_enable(i);                              //Set LED pin as input/drain
        example_ulp_gpio_set_output_mode(i, 1);                         //Set LED output to high
        wait(2000);                                                     //Keep LED on for 2000 cycles

        while((bool)example_ulp_gpio_get_level(Phototransistor)) 
        {                                                   //If phototransistor level is 1 - an LED is being blocked
            yellow_heartbeat(); //The Yellow LED should blink when the path between the IRLED and the Phototransistor is blocked
        }
        wait(6000);                                                     //Keep LED on for 6000 cycles

        // wait(1000); 
        example_ulp_gpio_output_disable(i);
        example_ulp_gpio_deinit(i);

    }
 }
This code does work:

Code: Select all

int main (void)
{
while(1){
    for(int i = 13; i < 17; ++i){                                    //Cycle through IRLED GPIO's
        wait(2000);                                                     //Keep LED's off for 2000 cycles
        example_ulp_gpio_init(i);                                       //Init LED Pin
        example_ulp_gpio_output_enable(i);                              //Set LED pin as input/drain
        example_ulp_gpio_set_output_mode(i, 1);                         //Set LED output to high
        wait(2000);                                                     //Keep LED on for 2000 cycles

        while((bool)example_ulp_gpio_get_level(Phototransistor)) 
        {                                                   //If phototransistor level is 1 - an LED is being blocked
            yellow_heartbeat(); //The Yellow LED should blink when the path between the IRLED and the Phototransistor is blocked
        }
        wait(6000);                                                     //Keep LED on for 6000 cycles

        // wait(1000); 
        example_ulp_gpio_output_disable(i);
        example_ulp_gpio_deinit(i);

    }
 }
 }
The setup between these two functions are exactly the same, I just wrap the for loop with the while(1) loop.

This is how I have come to the conclusion that something happens to the GPIO setup when the ULP goes to sleep for 300ms as setup here:

Code: Select all

static void init_ulp_program(void)
{
    esp_err_t err = ulp_riscv_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start));
    ESP_ERROR_CHECK(err);

    /* The first argument is the period index, which is not used by the ULP-RISC-V timer
     * The second argument is the period in microseconds, which gives a wakeup time period of: 20ms
     */
    ulp_set_wakeup_period(0, 300000);

    /* Start the program */
    err = ulp_riscv_run();
    ESP_ERROR_CHECK(err);
}
I hope this gives more clarity to the issue.

How do I continue to check the status of a GPIO in ULP mode?

deandob
Posts: 22
Joined: Sun Dec 02, 2018 5:21 am

Re: Checking GPIO level in ULP on the ESP32S2

Postby deandob » Thu Nov 25, 2021 7:45 am

Dylan,

If I understand you correctly, you are looking for confirmation that with the ESP32-S2:
1) When the ULP wakes up from sleep, it has to re-initialize all the pin settings?
2) Re-initializing the pin settings after ULP wake-up works the first time but not for subsequent wake-ups (the pins are back to the default state).

I don't think both 1 and 2 are expected behaviors, maybe someone from the Espressif team can confirm? And if not, its likely a logic error in your software.

Who is online

Users browsing this forum: No registered users and 121 guests