Example Code for Firebeetle 2 ESP32-E-Timed Sleep and Wake-up

Last revision 2026/03/05

This tutorial on Firebeetle 2 ESP32-E covers implementing timed sleep and wake-up using a gesture sensor. It includes hardware setup, Arduino IDE software installation, and step-by-step code execution for seamless project integration.

Hardware Preparation

Software Preparation

Wiring Diagram

SEN0670-Wakeup wiring diagram

Pin Connection Description:

  • Sensor: + Pin --- (Connects to) --- Main Controller: 3V3
  • Sensor: - Pin --- (Connects to) --- Main Controller: GND
  • Sensor: SCL Pin --- (Connects to) --- Main Controller: 22/SCL
  • Sensor: SDA Pin --- (Connects to) --- Main Controller: 21/SDA
  • Sensor: WAKEUP --- (Connects to) --- Main Controller: 12/D13

Sample Code

Function: Upon first power-up, the sensor works for 10 seconds then automatically sleeps; afterward, pressing the button wakes it up, and it will continuously detect gestures and output data without auto-sleeping.

#include <Arduino.h>
#include <Wire.h>
#include <DFRobot_HumanPose.h>

// -------------------------- Hardware Configuration --------------------------
#define HUMANPOSE_COMM_I2C
const int WAKEUP_PIN = 26;        // GPIO to control sensor power (LOW=OFF, HIGH=ON)
#define BUTTON_PIN     27          // Onboard button for wakeup (INPUT_PULLUP)
#define I2C_SDA        21         // ESP32 I2C SDA pin
#define I2C_SCL        22         // ESP32 I2C SCL pin
const uint8_t I2C_ADDR = 0x3A;    // Sensor I2C address (match sample)

// -------------------------- Time Configuration --------------------------
const unsigned long POWER_ON_DELAY = 500;      // Sensor power-up stabilization delay (ms)
const unsigned long AUTO_OFF_DELAY = 10000;    // Auto power-off after 10s (ms)
const unsigned long DEBOUNCE_DELAY = 20;       // Button debounce delay (ms)

// -------------------------- Global Variables --------------------------
DFRobot_HumanPose_I2C humanPose(&Wire, I2C_ADDR); // Match sample definition
bool sensorPowered = false;                       // Sensor power state (true=ON, false=OFF)
unsigned long powerOnTime = 0;                    // Timestamp of sensor power-on
unsigned long lastButtonTime = 0;                 // Last button check timestamp

// -------------------------- Sensor Power Control --------------------------
/**
 * @brief Power off sensor (pull WAKEUP_PIN LOW, release I2C bus)
 */
void sensorPowerOff() {
  digitalWrite(WAKEUP_PIN, LOW);
  Wire.end();
  sensorPowered = false;
  Serial.println("[INFO] Sensor powered OFF (press button to wakeup)");
}

/**
 * @brief Power on sensor and re-initialize (align with sample init logic)
 * @return true=success, false=failed
 */
bool sensorPowerOn() {
  // Hardware power-on
  digitalWrite(WAKEUP_PIN, HIGH);
  delay(POWER_ON_DELAY);
  Serial.println("[INFO] Sensor powering ON...");

  // Re-initialize I2C (match sample)
  Wire.begin(I2C_SDA, I2C_SCL);
  Wire.setClock(400000);
  delay(100);

  // Sample-style sensor initialization
  if (!humanPose.begin()) {
    sensorPowerOff(); // Power off on failure
    Serial.println("[ERROR] Sensor init fail!");
    return false;
  }
  Serial.println("[INFO] Sensor init success!");
  
  // Critical: Set model type to hand (match sample)
  humanPose.setModelType(DFRobot_HumanPose::eHand);
  
  sensorPowered = true;
  powerOnTime = millis(); // Record power-on time for 10s auto-off
  return true;
}

// -------------------------- Button Wakeup (Debounced) --------------------------
/**
 * @brief Check button state (debounced) for wakeup (only when sensor is OFF)
 */
void checkButtonWakeup() {
  if (sensorPowered) return; // Skip if sensor is already ON

  unsigned long now = millis();
  if (now - lastButtonTime < DEBOUNCE_DELAY) return; // Debounce

  lastButtonTime = now;
  if (digitalRead(BUTTON_PIN) == LOW) { // Button pressed (INPUT_PULLUP)
    sensorPowerOn(); // Wake up sensor
  }
}

// -------------------------- Gesture Read (Exact Sample Logic) --------------------------
/**
 * @brief Read & print gesture data (1:1 match with sample code)
 */
void readAndPrintGesture() {
  if (humanPose.getResult() == DFRobot_HumanPose::eOK) {
    while (humanPose.availableResult()) {
      HandResult *result = static_cast<HandResult *>(humanPose.popResult());
      
      // Exact print logic from your sample
      Serial.print("Gesture ID: "); Serial.println(result->id);
      Serial.print("Gesture: "); Serial.println(result->name);
      Serial.print("Score: "); Serial.println(result->score);
      
      Serial.println("score: " + String(result->score));
      Serial.println("xLeft: " + String(result->xLeft));
      Serial.println("yTop: " + String(result->yTop));
      Serial.println("width: " + String(result->width));
      Serial.println("height: " + String(result->height));
      Serial.println("wrist: " + String(result->wrist.x) + ", " + String(result->wrist.y));
      Serial.println("thumbCmc: " + String(result->thumbCmc.x) + ", " + String(result->thumbCmc.y));
      Serial.println("thumbMcp: " + String(result->thumbMcp.x) + ", " + String(result->thumbMcp.y));
      Serial.println("thumbIp: " + String(result->thumbIp.x) + ", " + String(result->thumbIp.y));
      Serial.println("thumbTip: " + String(result->thumbTip.x) + ", " + String(result->thumbTip.y));
      Serial.println("indexFingerMcp: " + String(result->indexFingerMcp.x) + ", " + String(result->indexFingerMcp.y));
      Serial.println("indexFingerPip: " + String(result->indexFingerPip.x) + ", " + String(result->indexFingerPip.y));
      Serial.println("indexFingerDip: " + String(result->indexFingerDip.x) + ", " + String(result->indexFingerDip.y));
      Serial.println("indexFingerTip: " + String(result->indexFingerTip.x) + ", " + String(result->indexFingerTip.y));
      Serial.println("middleFingerMcp: " + String(result->middleFingerMcp.x) + ", " + String(result->middleFingerMcp.y));
      Serial.println("middleFingerPip: " + String(result->middleFingerPip.x) + ", " + String(result->middleFingerPip.y));
      Serial.println("middleFingerDip: " + String(result->middleFingerDip.x) + ", " + String(result->middleFingerDip.y));
      Serial.println("middleFingerTip: " + String(result->middleFingerTip.x) + ", " + String(result->middleFingerTip.y));
      Serial.println("ringFingerMcp: " + String(result->ringFingerMcp.x) + ", " + String(result->ringFingerMcp.y));
      Serial.println("ringFingerPip: " + String(result->ringFingerPip.x) + ", " + String(result->ringFingerPip.y));
      Serial.println("ringFingerDip: " + String(result->ringFingerDip.x) + ", " + String(result->ringFingerDip.y));
      Serial.println("ringFingerTip: " + String(result->ringFingerTip.x) + ", " + String(result->ringFingerTip.y));
      Serial.println("pinkyFingerMcp: " + String(result->pinkyFingerMcp.x) + ", " + String(result->pinkyFingerMcp.y));
      Serial.println("pinkyFingerPip: " + String(result->pinkyFingerPip.x) + ", " + String(result->pinkyFingerPip.y));
      Serial.println("pinkyFingerDip: " + String(result->pinkyFingerDip.x) + ", " + String(result->pinkyFingerDip.y));
      Serial.println("pinkyFingerTip: " + String(result->pinkyFingerTip.x) + ", " + String(result->pinkyFingerTip.y));
      
      Serial.println("--------------------------------");
    }
  }
}

// -------------------------- Setup & Loop --------------------------
void setup() {
  // Initialize serial (match sample baud rate)
  Serial.begin(115200);
  while (!Serial) delay(10);
  Serial.println("[INFO] ESP32 + HumanPose Sensor (Correct Execution Order)");

  // Initialize pins
  pinMode(WAKEUP_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);

  // ✅ Critical Fix: Power on sensor immediately (no initial off delay)
  sensorPowerOn();
}

void loop() {
  // Case 1: Sensor is OFF → only check button for wakeup
  if (!sensorPowered) {
    checkButtonWakeup();
    delay(50);
    return;
  }

  // Case 2: Sensor is ON → execute core logic
  // Step 1: Check auto power-off (10s after power-on)
  unsigned long now = millis();
  if (now - powerOnTime >= AUTO_OFF_DELAY) {
    sensorPowerOff(); // Sleep after 10s of working
    return;
  }

  // Step 2: Read & print gesture data (match sample)
  readAndPrintGesture();

  // Step 3: Low CPU load delay (match sample)
  delay(50);
}

Result

As shown in the serial port output information, the sensor initialization is successful. After 10 seconds, it enters sleep mode (power off) and needs to be awakened by pressing the button.

SEN0670-sleep

At this point, pressing the onboard button of the ESP32-E controller will display the following serial port information.

SEN0670-botton

SEN0670-WAKEUP

Was this article helpful?

TOP