espressif / arduino-esp32

Arduino core for the ESP32
GNU Lesser General Public License v2.1
13.36k stars 7.37k forks source link

ESP32C3 : not able to wake up HIGH level on GPIO 0 or 1 #8447

Closed spilz87 closed 1 week ago

spilz87 commented 1 year ago

Board

ESP32-C3

Device Description

custom board with ESP32-C3

Hardware Configuration

rotary encoder connected to GPIO 0 and 1 with 100k PULLUP resistor connected to 3.3v

Version

latest master (checkout manually)

IDE Name

Arduino IDE

Operating System

Windows 10

Flash frequency

80MHz

PSRAM enabled

yes

Upload speed

921600

Description

I'm building a low power remote. I use a rotary encoder connected to GPIO 0 and 1. I would like to use it to wake up the ESP32C3, sending data and going back to deep sleep. the goal is to be able to use a small battery and not having to charge it for one month (or more)

I'm able to wake up from deep sleep by LOW level, but I'm not able to wake up by HIGH level.

An other information, if I put 1k PULLUP resistor, it works well but consume too much energy in deep sleep (close to 1mA)

I guess there is something I shoud disable or set to be able to use this wake up by high level.

thanks for your help in advance.

PS. : I already checked the issue #6656 but it's not the same issue and it didn't solve mine.

Sketch

void setup() {
  pinMode(0, INPUT);
  pinMode(1, INPUT);

  delay(1000);
  gpio_deep_sleep_hold_dis();
  esp_sleep_config_gpio_isolate();
  esp_deep_sleep_enable_gpio_wakeup(1<<0, ESP_GPIO_WAKEUP_GPIO_HIGH);
  esp_deep_sleep_enable_gpio_wakeup(1<<1, ESP_GPIO_WAKEUP_GPIO_HIGH);
  gpio_set_direction(GPIO_NUM_0, GPIO_MODE_INPUT);
  gpio_set_direction(GPIO_NUM_1, GPIO_MODE_INPUT);
  delay(500);
  esp_deep_sleep_start();
}

void loop() {
  // put your main code here, to run repeatedly:

}

Debug Message

no debug message, I use power consumation analyser to detect if it wakes up

Other Steps to Reproduce

No response

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

mcenderdragon commented 1 year ago

why not use a 100k pull up instead ?

spilz87 commented 1 year ago

why not use a 100k pull up instead ?

I put a 100k and it doesn't work With a 1k it works but consumes too much

SuGlider commented 1 year ago

I have tested this sketch with an ESP32-C3 using just a wire to shortcut GPIO 0 or 1 to the 3.3v pin. I used Arduino Core 2.0.11 and it worked fine. It waked up whenever I touched the wire with the 3.3v pin.

SuGlider commented 1 year ago

rotary encoder connected to GPIO 0 and 1 with 100k PULLUP resistor connected to 3.3v

ESP32-C3 wakeup works by LEVEL 3.3, not by edge. Maybe you could try it by removing any resistor. When it is floating or on GND, it won't wakeup. The GPIO must go to 3.3v directly.

spilz87 commented 1 year ago

@SuGlider thanks for your reply

with a shortcut or a low resistor it works fine.

my problem is that I use a rotary encoder, which I want to use to wake up the ESP32C3.

The goal is to reduce a lot the consuption. As I can not know in which state the rotary encoder will stop, I have to be avare about the fact both pins can be HIGH or LOW when it enter in deep sleep mode. if one of the pin is connected to commun (GND) the value of the resistor as an impact on the deep sleep consuption. that's why I need 100k, not a short cut.

the weird part is the first deep sleep is inpacted, not the others

spilz87 commented 1 year ago

rotary encoder connected to GPIO 0 and 1 with 100k PULLUP resistor connected to 3.3v

ESP32-C3 wakeup works by LEVEL 3.3, not by edge. Maybe you could try it by removing any resistor. When it is floating or on GND, it won't wakeup. The GPIO must go to 3.3v directly.

Do you mean using the rotary encoder in the opposite way : commun connected to 3.3V ? I need to be able to use the rotary encoder when the esp32C3 is awake too

lbernstone commented 1 year ago

The internal resistors in an esp32 are about 50-60K. I suspect you need to overcome that resistance to toggle the interrupt. Try smaller resistors until you get it to wake.

SuGlider commented 1 year ago

@spilz87 - I'm sorry but I'm not following you, please send me some diagram or hand drawing of how it is all connected. Thanks.

spilz87 commented 1 year ago

I think the issue is directly related to #8449

SuGlider commented 1 year ago

@spilz87 - The C3 RTC GPIO wake up needs no pullup. Please try it with no resistors. https://github.com/espressif/arduino-esp32/issues/8449#issuecomment-1664706413

VojtechBartoska commented 1 year ago

any updates on this @spilz87?

spilz87 commented 1 year ago

any updates on this @spilz87?

I wait to be home to test again

do you have the same issue ?

VojtechBartoska commented 1 year ago

No, I didn't test, just asking about the status. :) We will appreciate if you can retest this, ideally on 2.0.11 version. Thanks

spilz87 commented 1 year ago

I did the tests and give more informations in this issue #8449

spilz87 commented 1 year ago

rotary encoder doesn't work properly without pullup nor pulldown resistor. on 2.0.10 and 2.0.11 it become even worth.

my hypotesis : it is linked to internal pulldown resistor which seems enabled when enter in deep sleep mode.

spilz87 commented 1 year ago

@spilz87 - I'm sorry but I'm not following you, please send me some diagram or hand drawing of how it is all connected. Thanks.

Here is the diagram used : Schema Rotary encoder

thanks for your support

VojtechBartoska commented 1 year ago

thanks for more info @spilz87, Can you please take a look @SuGlider?

spilz87 commented 1 year ago

Hi @SuGlider Did you have time to have a look ? Thanks in advance Have a good day

SuGlider commented 1 year ago

Hi, not yet, I don't have a rotary in order to test it better. I just have a few dupont cables.

SuGlider commented 1 year ago

@spilz87 - I'm sorry but I'm not following you, please send me some diagram or hand drawing of how it is all connected. Thanks.

Here is the diagram used : Schema Rotary encoder

thanks for your support

I understand that, based on the circuit, even if the ESP32-C3 is not present, it will consume current because of the rotary pullup resistors. The ROTSW_A or ROTSW_B pins are always connected to GND (one or the other). This makes a permanent circuit from VCC to GND through the resistors.

SuGlider commented 1 year ago

Not sure why would this part of the code be necessary:

  gpio_deep_sleep_hold_dis();
  esp_sleep_config_gpio_isolate();

@spilz87 - is it an attempt to reduce the electrical current consumption?

spilz87 commented 1 year ago

@spilz87 - I'm sorry but I'm not following you, please send me some diagram or hand drawing of how it is all connected. Thanks.

Here is the diagram used : Schema Rotary encoder

thanks for your support

I understand that, based on the circuit, even if the ESP32-C3 is not present, it will consume current because of the rotary pullup resistors.

The ROTSW_A or ROTSW_B pins are always connected to GND (one or the other). This makes a permanent circuit from VCC to GND through the resistors.

Hi, the basic rotary encoder act like switchs between A and COM, and B and COM. In my schematic COM is GROUND. In stable position : A and B are low (switchs closed) Or A and B are high (switchs opened)

In mouvement : Depends the direction, A or B changes then the other one follows.

So yes, in some position (switchs closed) there is a permanent consumption, that's why it is necessary to increase the resistor.

As it seems the internal pull down resistors are activated at deep sleep mode, only small resistor connected to rotary encoder can compensate and so big consumption for nothing.

Tell me if it's not clear :)

SuGlider commented 1 year ago

The problem that I see is that the Encoder KY-040 (mechanical Arduino Rotary Encoder) causes bouncing signals, like a mechanical push button.

Most probably, what you call "too fast" is the noise.

spilz87 commented 1 year ago

Yes, in use, the encoder causes this kind of bouncing signals, that's why the external pull-up resistors are needed.

But I'm talking about enter and waking up from deep sleep. I just need to wake up properly, all the rest of the code is working well.

The issue seems it occures when enter in deep sleep mode, so when encoder is not moving any more for few secondes

SuGlider commented 1 year ago

I'm a bit lost already. What is exactly the issue you want to solve?

spilz87 commented 1 year ago

I'm a bit lost already. What is exactly the issue you want to solve?

When I enter in deep sleep mode and GPIO (0 or 1) are LOW level (rotary encoder "closed"), I'm not able to wake up when I turn the encoder (rotary encoder "opened").

spilz87 commented 1 year ago

Experiment :

On version 2.0.9 it reacted like this only on the first enter in deep sleep mode, so I found a turn arround On version 2.0.10 and 2.0.11 it reacts always like this.

according to this different reactions depends on the version, it clearly indicates a driver issue for me

SuGlider commented 1 year ago

@spilz87 - I don't have a Rotary Encoder here to test it, but I have used a push button. In this case I just used 3.3v connected to one end of the push button and the other end going to the GPIO 0. The same for a second push button connected to GPIO 1. Whenever necessary, I switch the wires to GND.

No external pullup, not set to input mode, no isolation mode, no hold GPIO disabled. GPIO ---> BUTTON --> 3.3V | GND

It works fine. Why wouldn't it work with a Rotary Encoder? I'm using Arduino 2.0.11

The sketch used is this:

RTC_DATA_ATTR int bootCount = 0;
#define GPIO_A 0
#define GPIO_B 0

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;
    case ESP_SLEEP_WAKEUP_GPIO : Serial.println("Wakeup caused by RISC V GPIO"); break;
    default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  }
}

void setup() {
  Serial.begin(115200);
  pinMode(GPIO_A, INPUT);
  pinMode(GPIO_B, INPUT);
  Serial.println("\nSTARTING...\n");

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

  esp_deepsleep_gpio_wake_up_mode_t GPIO_A_mode = ESP_GPIO_WAKEUP_GPIO_HIGH;
  esp_deepsleep_gpio_wake_up_mode_t GPIO_B_mode = ESP_GPIO_WAKEUP_GPIO_HIGH;
  if (digitalRead(GPIO_A)) {
     GPIO_A_mode = ESP_GPIO_WAKEUP_GPIO_LOW;
  }
  if (digitalRead(GPIO_B)) {
     GPIO_B_mode = ESP_GPIO_WAKEUP_GPIO_LOW;
  }

  esp_deep_sleep_enable_gpio_wakeup(1<<GPIO_A, GPIO_A_mode);
  esp_deep_sleep_enable_gpio_wakeup(1<<GPIO_B, GPIO_B_mode);

  delay(500);
  Serial.println("Sleep Begining.");
  esp_deep_sleep_start();
}

void loop() {}
SuGlider commented 1 year ago

This is the breadboard circuit:

image

SuGlider commented 1 year ago

If I keep pressed the Yellow Button, the S3 wakes up and returns to sleep, not waking up again (meaning that the state changed to HIGH making it wake up and then the sketch only wakes up again on LOW). Then I relese the button and move the red wire to GND pin from the C3 board. When I press it again, the C3 wakes up (on LOW).

Therefore, it reads the GPIO, sets the correct state to start sleeping and wakes up when the State of the GPIO changes from what has been read to the inverse.

spilz87 commented 1 year ago

did you put the 100ko resistor ?

SuGlider commented 1 year ago

No

SuGlider commented 1 year ago

I understant that the Rotary Encoder pins A and B are always on GND or on VCC (3.3). Never floating. Right?

spilz87 commented 1 year ago

so you can not be impacted by internal pulldown resistor

SuGlider commented 1 year ago

No, but it works.... This is what matters, isn't it?

spilz87 commented 1 year ago

I understant that the Rotary Encoder pins A and B are always on GND or on VCC (3.3). Never floating. Right?

no, it acts like a switch with ground, so you need pullup resistor otherwile you would have a short cut

SuGlider commented 1 year ago

I understant that the Rotary Encoder pins A and B are always on GND or on VCC (3.3). Never floating. Right?

no, it acts like a switch with ground, so you need pullup resistor otherwile you would have a short cut

I don't think so.... the GPIO is in INPUT mode, no pull up/down. It is reading, not outputing any level.

SuGlider commented 1 year ago

Anyway, the C3 doesn't reset or anything. With a short cut, it must reset.

spilz87 commented 1 year ago

I understant that the Rotary Encoder pins A and B are always on GND or on VCC (3.3). Never floating. Right?

no, it acts like a switch with ground, so you need pullup resistor otherwile you would have a short cut

I don't think so.... the GPIO is in INPUT mode, no pull up/down. It is reading, not outputing any level.

actually I tell you

spilz87 commented 1 year ago

Anyway, the C3 doesn't reset or anything. With a short cut, it must reset.

because you are not in the same configuration

put a 100ko pullup resistor between your switch and 3.3v and when you press connect to the ground

SuGlider commented 1 year ago

I understant that you want the Rotary Encoder to wake up the C3. Is it correct?

spilz87 commented 1 year ago

switch

In this configuration, I want the ESP wakes up when switch open

SuGlider commented 1 year ago

OK, I'll set my circuit to use the resistor. Hold on.

spilz87 commented 1 year ago

thanks :)

SuGlider commented 1 year ago

Using the resistor, the sketch doesn't work because it reads 2.75v and doesn't wake up the C3. It only wakes up on 3.3v.

The Rotary Circuit is not the same of the button:

VCC -----+
         |---- GPIO (it goes to VCC or to GND, but VCC never connects to GND (no short cut).
 GND---- + 

image

Output A is in the grey or orange area, never in both. Each area is connected to GND or VCC.

SuGlider commented 1 year ago

I can't understand why you need a 100K resistor.... there is no short cut.

spilz87 commented 1 year ago

rot a rotary encoder works like this

https://www.youtube.com/watch?app=desktop&v=ns1iqNInzG8

spilz87 commented 1 year ago

Using the resistor, the sketch doesn't work because it reads 2.75v and doesn't wake up the C3. It only wakes up on 3.3v.

The Rotary Circuit is not the same of the button:

VCC -----+
         |---- GPIO (it goes to VCC or to GND, but VCC never connects to GND (no short cut).
 GND---- + 

image

Output A is in the grey or orange area, never in both. Each area is connected to GND or VCC.

in your picture, it explains :

SuGlider commented 1 year ago

Yes, in the Orange/Grey picture, there is no pull up. It is directly connected to VCC or GND. Output A will be directly connected to VCC or to GND.

If the device works in this direct way, the C3 will wake up. If the deveice has internally a resistor, it won't.

spilz87 commented 1 year ago

A and B are connected to GPIO 0 and GPIO 1 Common is connected to GND We need pullup resistor to put GPIO 0 and GPIO1 to HIGH level when common (so GND) is not touching A or B