Unable to wake the XIAO ESP32C3 up from deep sleep with a PIR sensor

I’ve made further progress on my solution and discovered that using GPIO_FLOATING might not be the best approach for detecting the VOUT signal from the PIR sensor. This option can be unreliable for detection purposes. When I tested how the signal travels from the PIR sensor’s VOUT wire to GPIO2, I had the positive test probe of my multimeter connected to GPIO2. Surprisingly, the wakeup from the PIR worked reliably without floating (I changed GPIO_FLOATING to GPIO_PULLUP_PULLDOWN). It appears that the inner resistance of the multimeter had an impact on the reliability of the pulldown.

As a solution, I added a 22 kΩ resistor to the connection leading to GPIO2 and connected its other end to the 3.3V output of the ESP32-C3. That did the trick! Now GPIO2 operates reliably.

Here’s the setup:

Additional points of interest:

  • Some PIR sensors have excellent standby current consumption: for example, the AM312 (8 uA) and the Panasonic EKMB1303111K (6 uA). The AM312 costs only about £2 in the UK while Panasonic’s sensor can cost over £20. I am using the AM312.
  • I was able to connect the surface-mountable ESP32C3 to a breadboard using just jumper cable pins, which meant no soldering was needed for this quick test.
  • I found it impossible to upload newly compiled firmware to the ESP32-C3 when either the resistor or the data wire of the PIR sensor (or both) was connected to GPIO2. This pin is also involved in the boot process.
  • Below is the latest test code I used:
#define LED 10
#define INTERRUPT_PIN 2
RTC_DATA_ATTR int bootCount = 0;

void setup() {
  Serial.begin(115200);
  delay(1000);

  pinMode(LED, OUTPUT);
  digitalWrite(LED, LOW);

  ++bootCount;
  Serial.println("Boot number: " + String(bootCount));

  print_wakeup_reason();

  Serial.println("Going to blink the LED 3 times");
  blink(3);
  Serial.println("Going to sleep now");
  delay (1000);
  gpio_sleep_set_pull_mode(GPIO_NUM_2, GPIO_PULLUP_PULLDOWN);
  esp_deep_sleep_enable_gpio_wakeup(1 << INTERRUPT_PIN, ESP_GPIO_WAKEUP_GPIO_HIGH);
  delay (1000);
  esp_deep_sleep_start();
}

void loop() { }

void blink(int times) {
  for (int i = 0; i < times; i++) {
    digitalWrite(LED, HIGH);
    delay(1000);

    digitalWrite(LED, LOW);
    delay(1000);
    Serial.print("Blink ");
    Serial.println(i + 1);
  }
}

void print_wakeup_reason() {
  esp_sleep_wakeup_cause_t wakeup_reason;
  char reason_description[100];

  wakeup_reason = esp_sleep_get_wakeup_cause();

  switch (wakeup_reason) {
    case ESP_SLEEP_WAKEUP_GPIO:
      strcpy(reason_description, "Wakeup caused by GPIO");
      break;
    case ESP_SLEEP_WAKEUP_EXT0:
      strcpy(reason_description, "Wakeup caused by external signal using RTC_IO");
      break;
    case ESP_SLEEP_WAKEUP_EXT1:
      strcpy(reason_description, "Wakeup caused by external signal using RTC_CNTL");
      break;
    case ESP_SLEEP_WAKEUP_TIMER:
      strcpy(reason_description, "Wakeup caused by timer");
      break;
    case ESP_SLEEP_WAKEUP_TOUCHPAD:
      strcpy(reason_description, "Wakeup caused by touchpad");
      break;
    case ESP_SLEEP_WAKEUP_ULP:
      strcpy(reason_description, "Wakeup caused by ULP program");
      break;
    default:
      snprintf(reason_description, sizeof(reason_description), "Wakeup was not caused by deep sleep: %d", wakeup_reason);
  }

  Serial.println(reason_description);
}
1 Like