使用 ESP32-C3 进行深度睡眠唤醒

问题描述 投票:0回答:1

buttonPin 最初从按下状态开始。因此,当在开始时按下按钮上传代码时,esp32-c3 会进入睡眠状态。当 GPIO 变高时,另一个按钮 (buttonPin2) 将 esp 从深度睡眠中唤醒。唤醒后,esp 运行 BLE 脚本并连接到手机(使用 ble 扫描仪进行测试)。一旦成功连接(经过一段延迟),deviceConnected 回调将使 esp 重新进入睡眠状态。现在,当设备返回睡眠状态时,应通过第一个按钮 (buttonPin) 唤醒。该代码包含用于在 GPIO 变低时唤醒 esp 的行。但是,一旦释放按钮,esp 就会重置(需要再按一次按钮才能打印唤醒原因并切换 LED)。为什么ESP复位了,没有被按钮唤醒?我怎样才能解决这个问题?我希望buttonPin2最初唤醒esp以通过蓝牙将其配对,然后希望buttonPin在它再次返回睡眠状态后将其唤醒(并在唤醒时切换LED)。

#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>
#include <Wire.h>
#include <Preferences.h>
#include <WiFi.h>
#include <WiFiMulti.h>


const int buttonPin = 3;  // # for button pin for States/Interrupt
const int buttonPin2 = 2; // # for button pin for BLE
const int ledPin =  5;   // # for the Green LED pin
const int ledPin2 = 6;   // # for the Red LED pin
const int ledPin3 = 7;    // # for the Blue LED pin


// variables will change:
int buttonState = 0;    
int lastButtonState = 0;
int buttonState2 = 0;
int lastButtonState2 = 0;  
int ledState = 0;
int state = 0;
//int BLEcounter = 0;
RTC_DATA_ATTR int counter = 0;


#define SERVICE_UUID        "f0e279fc-a979-4ffd-924c-59ced5392948"
#define CHARACTERISTIC_UUID "7f98738e-382d-43d9-b256-3cf8bd3120b7"


BLEServer *pServer = NULL;
BLEService *pService = NULL;
BLECharacteristic *pCharacteristic = NULL;


Preferences preferences;
WiFiMulti wifimulti;


bool deviceConnected = false;
class MyServerCallbacks: public BLEServerCallbacks {
    void onConnect(BLEServer* pServer) {
      deviceConnected = true;
      Serial.println("True");
      state = preferences.getInt("state", 0);
      Serial.print("State: ");
      Serial.println(counter);
      delay(5000);
      Serial.println("Going to Sleep");
      digitalWrite(ledPin3, LOW);  // Turn off LED
      esp_deep_sleep_start();  // Enter deep sleep mode
    };


    void onDisconnect(BLEServer* pServer) {
      deviceConnected = false;
      Serial.println("Disconnected!");
      Serial.println("Advertising...");
      pServer->getAdvertising()->start();
    }
};


class MyCallbacks: public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pCharacteristic)
  {
    std::string value = pCharacteristic->getValue();


    if (value.length() > 0)
    {
      Serial.println("*********");
      Serial.print("New value: ");
      for (int i = 0; i < value.length(); i++)
      {
        Serial.print(value[i]);
      }


      Serial.println();
      Serial.println("*********");
    }
  }
};


void setupBLEServer(void) {


  Serial.println("Starting BLE Server!");
  BLEDevice::init("Pirouette-IoT-Device");
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());


  pService = pServer->createService(SERVICE_UUID);


  pCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_WRITE | BLECharacteristic::PROPERTY_NOTIFY);


  pCharacteristic->setCallbacks(new MyCallbacks());


  pCharacteristic->setValue("device_state_0_stored");
  pService->start();
  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->addServiceUUID(SERVICE_UUID);
  pAdvertising->setScanResponse(true);
  pAdvertising->setMinPreferred(0x06);  // functions that help with iPhone connections issue
  pAdvertising->setMinPreferred(0x12);
  pAdvertising->start();
}


void pairing(){


  digitalWrite(ledPin3, HIGH);
  setupBLEServer();
}


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: //New wakeup reason <--
      Serial.println("Wakeup caused by a GPIO");
      if(lastButtonState == HIGH && buttonState == LOW){
        counter++;
        Serial.print("Counter: ");
        Serial.println(counter);
      }
     
      if(counter == 1){
        digitalWrite(ledPin, HIGH);
      }


      //digitalWrite(ledPin, HIGH);
      //Serial.println("Advertising...");
      //pServer->startAdvertising();
      if(deviceConnected){
        if(pCharacteristic != NULL){
          pCharacteristic->setValue("device_state_1_ready"); //add code for device state 1 ready once buttonPin1 is pushed/released
          pCharacteristic->notify();
        }
      }
      break;
    default:
      Serial.printf("Wakeup was not caused by deep sleep: %d\n", wakeup_reason);
      break;
  }
}


void setup() {
 
  Serial.begin(115200);
 
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  pinMode(ledPin2, OUTPUT);
  pinMode(ledPin3, OUTPUT);
 
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
  pinMode(buttonPin2, INPUT_PULLUP);


  //Enable GPIO Wakeup from buttonPin
  esp_deep_sleep_enable_gpio_wakeup(1 << buttonPin, ESP_GPIO_WAKEUP_GPIO_LOW);
  esp_deep_sleep_enable_gpio_wakeup(1 << buttonPin2, ESP_GPIO_WAKEUP_GPIO_HIGH);
  gpio_set_direction((gpio_num_t)buttonPin, GPIO_MODE_INPUT);  // <<<=== Add this line
  gpio_set_direction((gpio_num_t)buttonPin2, GPIO_MODE_INPUT);  // <<<=== Add this line




  preferences.begin("dev-states", false);


  state = preferences.getInt("state", 0);
  Serial.print("State: ");
  Serial.println(counter);


  buttonState2 = digitalRead(buttonPin2);
  if(buttonState2 == HIGH && lastButtonState2 == LOW){
    print_wakeup_reason();
    pairing();
  }


  buttonState = digitalRead(buttonPin);
  buttonState2 = digitalRead(buttonPin2);
  if(buttonState == HIGH && buttonState2 == LOW){
    Serial.println("Going to Sleep");
    esp_deep_sleep_start();
  }


}


void loop() {


  // read the state of the BLE pushbutton
  buttonState2 = digitalRead(buttonPin2);
  if (lastButtonState2 == HIGH && buttonState2 == LOW) {
    print_wakeup_reason();
    Serial.println("The button is pressed");
    pairing();
  }
  lastButtonState2 = buttonState2;
 
  // read the state of the internal pushbutton:
  buttonState = digitalRead(buttonPin);


  // compare the buttonState to its previous state
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    if (lastButtonState == HIGH && buttonState == LOW) {
      print_wakeup_reason();
      //counter++;
      Serial.print("Number of button pushes:  ");
      Serial.println(counter);
      // if the current state is HIGH then the button went from off to on:
      ledState = !ledState;
    }
    if(counter == 2){
      buttonState = lastButtonState;
    }
  }
  // save the current state as the last state, for next time through the loop
  lastButtonState = buttonState;


  // sets the LED to the button's state
  if(counter == 1){
    digitalWrite(ledPin, HIGH);
    digitalWrite(ledPin2, LOW);
   
    if(pCharacteristic != NULL){
      pCharacteristic->setValue("device_state_3_locked"); //add code for device state 1 ready once buttonPin1 is pushed/released
      pCharacteristic->notify();
    }
  }


  if(counter == 3){
    digitalWrite(ledPin2, HIGH);
    digitalWrite(ledPin, LOW);
   
    if(pCharacteristic != NULL){
      pCharacteristic->setValue("device_state_3_locked"); //add code for device state 3 used once buttonPin1 is pushed/released
      pCharacteristic->notify();
    }
  }


  if(counter >= 4){
    digitalWrite(ledPin, LOW);
    digitalWrite(ledPin2, LOW);
  }


  delay(50);


}
arduino microcontroller esp32 arduino-ide arduino-c++
1个回答
0
投票

愚蠢的建议,但根据您的描述,我想到的一个可能的原因是您可能无意中触发了实际上是 ESP 上的重置引脚的引脚。

如果您查看主板的引脚图,它会显示哪个引脚标记为“RST”,具体取决于您的接线,如果您向该引脚供电,它将重置芯片。

问题是有些主板只会打印数字 1,2,3...但只有当您查看实际的引脚图时,它才会告诉您哪个引脚做什么。

我一直这样做,但是是故意的,如果我没有物理开关而是使用按钮,我会让 ESP 进入睡眠状态,当需要使用设备时,用户按下按钮按钮向 RST 发送脉冲,有效地重新启动设备,就像刚刚插入电源一样。

正如一些人评论的那样,您发布了太多的代码,最好的办法是隔离问题,放弃代码中除睡眠/唤醒部分之外的所有内容,并对其进行测试,直到该部分机制起作用,或者如果它不只发布该代码。如果内容切中要点,则更有机会获得优质帮助(否则您只会收到脾气暴躁的评论:-)

© www.soinside.com 2019 - 2024. All rights reserved.