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

External wake up ext1 problem #9809

Closed
1 task done
CobaProgram opened this issue Jun 8, 2024 · 8 comments · Fixed by #9904
Closed
1 task done

External wake up ext1 problem #9809

CobaProgram opened this issue Jun 8, 2024 · 8 comments · Fixed by #9904
Assignees
Labels
3.0 migration issue relates to migration from 2.X to 3.X version Status: In Progress Issue is in progress
Milestone

Comments

@CobaProgram
Copy link

Board

ESP32 Dev Module and Doit ESP32 devkit v1

Device Description

Devkit v1

Hardware Configuration

GPIO 34, 36 and 39 connect to push button active high (pulldown resistor 10k)

Version

v3.0.0

IDE Name

Arduino IDE

Operating System

Windows 10

Flash frequency

80 MHz

PSRAM enabled

no

Upload speed

921600

Description

This code does not work after update to version 3.0.0 and always awake

Sketch

/*
Deep Sleep with External Wake Up
=====================================
This code displays how to use deep sleep with
an external trigger as a wake up source and how
to store data in RTC memory to use it over reboots

This code is under Public Domain License.

Hardware Connections
======================
Push Button to GPIO 33 pulled down with a 10K Ohm
resistor

NOTE:
======
Only RTC IO can be used as a source for external wake
source. They are pins: 0,2,4,12-15,25-27,32-39.

Author:
Pranav Cherukupalli <cherukupallip@gmail.com>
*/
#define BUTTON_PIN_BITMASK 0x400000000  // 2^34 in hex //0x9400000000

RTC_DATA_ATTR int bootCount = 0;

/*
Method to print the reason by which ESP32
has been awaken from sleep
*/
void print_wakeup_reason() {
  esp_sleep_wakeup_cause_t wakeup_reason;

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch (wakeup_reason) {
    case ESP_SLEEP_WAKEUP_EXT0: Serial.println("Wakeup caused by external signal using RTC_IO"); break;
    case ESP_SLEEP_WAKEUP_EXT1: Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
    case ESP_SLEEP_WAKEUP_TIMER: Serial.println("Wakeup caused by timer"); break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD: Serial.println("Wakeup caused by touchpad"); break;
    case ESP_SLEEP_WAKEUP_ULP: Serial.println("Wakeup caused by ULP program"); break;
    default: Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason); break;
  }
}

void setup() {
  Serial.begin(115200);
  delay(1000);  //Take some time to open up the Serial Monitor

  //Increment boot number and print it every reboot
  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));
  
  //Print the wakeup reason for ESP32
  print_wakeup_reason();

  /*
  First we configure the wake up source
  We set our ESP32 to wake up for an external trigger.
  There are two types for ESP32, ext0 and ext1 .
  ext0 uses RTC_IO to wakeup thus requires RTC peripherals
  to be on while ext1 uses RTC Controller so does not need
  peripherals to be powered on.
  Note that using internal pullups/pulldowns also requires
  RTC peripherals to be turned on.
  */
  //esp_sleep_enable_ext0_wakeup(GPIO_NUM_33, 1);  //1 = High, 0 = Low

  //If you were to use ext1, you would use it like
  esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK, ESP_EXT1_WAKEUP_ANY_HIGH);

  //Go to sleep now
  Serial.println("Going to sleep now");

  esp_deep_sleep_start();
  Serial.println("This will never be printed");
}

void loop() {
  //This is not going to be called
}

Debug Message

nothing error but always awake after sleep mode active

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.
@CobaProgram CobaProgram added the Status: Awaiting triage Issue is waiting for triage label Jun 8, 2024
@CobaProgram
Copy link
Author

I found the command ESP_EXT1_WAKEUP_ALL_LOW is the same as ESP_EXT1_WAKEUP_ANY_HIGH in 3.0.0 version

so that's the cause of the problem in 3.0.0 and 3.0.1 but in version 2.x.x there is no problem

@Pr77Pr77
Copy link

I have the same problem. It seems like @CobaProgram is right. ESP_EXT1_WAKEUP_ANY_HIGH behaves like ESP_EXT1_WAKEUP_ALL_LOW should. But how can I get it to wake up on a high pin?
I haven't tried to replace ESP_EXT1_WAKEUP_ANY_HIGH with ESP_EXT1_WAKEUP_ALL_LOW, because the behaviours could be exchanged.
Does anyone have an idea?

@bfeldman-threadb
Copy link

I'm having the same issue on an ESP32-S2. The code for waking up on high pins worked in Core 2.0.x but triggers immediately on Core 3.0.1 when the pins are low.

I looked through the code for both cores (ESP-IDF versions 4.4 and 5.1) and tried manually setting the following registers to no avail:

REG_WRITE(RTC_CNTL_PAD_HOLD_REG,0x4000);
REG_SET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL, 0x4000);
SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1,1, RTC_CNTL_EXT_WAKEUP1_LV_S);
REG_WRITE(IO_MUX_GPIO14_REG, 0b0001101000000000);

Setting those registers alone had no effect. If I put this line before them:

esp_sleep_enable_ext1_wakeup(0x4000, ESP_EXT1_WAKEUP_ANY_HIGH);

The processor would wake up immediately when pin 14 was low. Wakeup reason is shows as EXT1, pin 14.

I did a comparison of all RTC_CNTL registers (and a few others) between Core 2.0.6 and Core 3.0.1 and didn't find any significant differences that I believe would explain the problem. Not sure whether this is fixable with modifying registers alone or the ESP-IDF code needs to be modified.

@VojtechBartoska
Copy link
Collaborator

@SuGlider Can you please help with triage of this issue? Thanks a lot

@SuGlider
Copy link
Collaborator

This issue seems to be related to a change in IDF code. Not directly Arduino related.
The example from IDF Github is now a bit different for EXT1 Wakeup from deepsleep.

IDF 4: esp-idf/examples/system/deep_sleep/main/deep_sleep_example_main.c at release/v4.4 · espressif/esp-idf (github.com)

This is how it was and how the issue describes it:

    const int ext_wakeup_pin_1 = 2;
    const uint64_t ext_wakeup_pin_1_mask = 1ULL << ext_wakeup_pin_1;
    const int ext_wakeup_pin_2 = 4;
    const uint64_t ext_wakeup_pin_2_mask = 1ULL << ext_wakeup_pin_2;

    printf("Enabling EXT1 wakeup on pins GPIO%d, GPIO%d\n", ext_wakeup_pin_1, ext_wakeup_pin_2);
    ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup(ext_wakeup_pin_1_mask | ext_wakeup_pin_2_mask, ESP_EXT1_WAKEUP_ANY_HIGH));

IDF 5.1: esp-idf/examples/system/deep_sleep/main/deep_sleep_example_main.c at release/v5.1 · espressif/esp-idf (github.com)

This is the way how IDF 5.x does it:

    const int ext_wakeup_pin_1 = CONFIG_EXAMPLE_EXT1_WAKEUP_PIN_1;
    const int ext_wakeup_pin_2 = CONFIG_EXAMPLE_EXT1_WAKEUP_PIN_2;
    const uint64_t ext_wakeup_pin_1_mask = 1ULL << ext_wakeup_pin_1;
    const uint64_t ext_wakeup_pin_2_mask = 1ULL << ext_wakeup_pin_2;
    printf("Enabling EXT1 wakeup on pins GPIO%d, GPIO%d\n", ext_wakeup_pin_1, ext_wakeup_pin_2);

#if SOC_PM_SUPPORT_EXT1_WAKEUP_MODE_PER_PIN
    ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup_io(ext_wakeup_pin_1_mask, CONFIG_EXAMPLE_EXT1_WAKEUP_MODE_PIN_1));
    ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup_io(ext_wakeup_pin_2_mask, CONFIG_EXAMPLE_EXT1_WAKEUP_MODE_PIN_2));
#else
    ESP_ERROR_CHECK(esp_sleep_enable_ext1_wakeup_io(ext_wakeup_pin_1_mask | ext_wakeup_pin_2_mask, CONFIG_EXAMPLE_EXT1_WAKEUP_MODE));
#endif

The IDF Calls are different.
IDF 4.x uses esp_sleep_enable_ext1_wakeup(MASK, MODE); + necessary disabling PULL_UP/DOWN.
IDF 5.x uses esp_sleep_enable_ext1_wakeup_io(MASK, MODE); + necessary disabling PULL_UP/DOWN.

My suggestion is about reading the manual and checking those examples.
https://docs.espressif.com/projects/esp-idf/en/v5.1/esp32/api-reference/system/sleep_modes.html#external-wakeup-ext1

@SuGlider
Copy link
Collaborator

The solution for this issue is:

  esp_sleep_enable_ext1_wakeup_io(BUTTON_PIN_BITMASK(WAKEUP_GPIO), ESP_EXT1_WAKEUP_ANY_HIGH);
  /*
    If there are no external pull-up/downs, tie wakeup pins to inactive level with internal pull-up/downs via RTC IO
         during deepsleep. However, RTC IO relies on the RTC_PERIPH power domain. Keeping this power domain on will
         increase some power comsumption. However, if we turn off the RTC_PERIPH domain or if certain chips lack the RTC_PERIPH
         domain, we will use the HOLD feature to maintain the pull-up and pull-down on the pins during sleep.
  */
  rtc_gpio_pulldown_en(WAKEUP_GPIO);  // GPIO33 is tie to GND in order to wake up in HIGH
  rtc_gpio_pullup_dis(WAKEUP_GPIO);   // Disable PULL_UP in order to allow it to wakeup on HIGH

The example from Arduino has been fixed as well.
Please check the cnahges in #9904

@SuGlider
Copy link
Collaborator

@CobaProgram - No pull down resistor is necessary because it is done internally to the chip using rtc_gpio_pulldown_en(GPIO_NUM);

@SuGlider
Copy link
Collaborator

Note: it is necessary to include a new file in order to use rtc_gpio_pulldown_en() etc.

#include "driver/rtc_io.h"

@SuGlider SuGlider added 3.0 migration issue relates to migration from 2.X to 3.X version and removed Status: Awaiting triage Issue is waiting for triage labels Jun 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3.0 migration issue relates to migration from 2.X to 3.X version Status: In Progress Issue is in progress
Projects
Development

Successfully merging a pull request may close this issue.

5 participants