Hi I'm trying to wake my esp32 up from deep sleep with the IRQ pin from nRF24L01.
I'm basically making a wireless door lock that has a keypad on one side, and a servo motor on the other side.
Both have nRF24L01 and are used for communication.
Since I use 4 AA batteries for each, power saving is crucial so I decided to use deep sleep mode when there is no external input to both.
The keypad module wakes up well whenever I press a key, but the problem is the servo module.
I want to wake the servo module whenever it receives a signal from nRF module by monitoring the IRQ pin, but it seems like it's not reading the IRQ pin when the esp32 is in deep sleep.
The following are the codes for each module.
[Keypad Module Code (Tx)]
#include "driver/rtc_io.h"
#include <Keypad.h>
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RTC_DATA_ATTR int bootCount = 0;
RF24 radio(4, 5);
// long long address = 0x1234ABCDEFLL;
const byte address[][6] = {"00001", "00002"};
const byte ROWS = 4;
const byte COLS = 3;
const uint8_t soundpin = 22;
char hexaKeys[ROWS][COLS] = {
{'1','2','3'},
{'4','5','6'},
{'7','8','9'},
{'*','0','#'}
};
byte rowPins[ROWS] = {32, 33, 25, 26}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {27, 14, 12}; //connect to the column pinouts of the keypad
RTC_DATA_ATTR char inputPassword[100] = {};
RTC_DATA_ATTR int idx = 0;
// char presetPassword[100] = {};
char presetPassword[100] = {'1', '2', '3', '4'};
int passwordLength = 4;
Keypad customKeypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS);
enum doorLockState{
DOOR_LOCKED,
DOOR_UNLOCKING,
DOOR_UNLOCKED
};
RTC_DATA_ATTR doorLockState lockState = DOOR_LOCKED;
const int lowPowerModeDelay = 10000;
long int prevMillis;
void setup(){
Serial.begin(115200);
++bootCount;
Serial.println("Boot number: " + String(bootCount));
print_wakeup_reason();
if(bootCount == 1){
resetArray(inputPassword, passwordLength);
idx = 0;
}
ledcAttachChannel(soundpin, NOTE_A, 7, 2);
radio.begin();
radio.openWritingPipe(address[1]);
radio.setDataRate(RF24_2MBPS);
radio.setPALevel(RF24_PA_MIN);
radio.setChannel(0x4C);
radio.stopListening();
delay(1000);
prevMillis = millis();
}
void loop(){
char customKey = customKeypad.getKey();
if(customKey){
prevMillis = millis();
}
if(!customKey && (millis() - prevMillis > lowPowerModeDelay)){
Serial.println("Going to sleep");
ledcWriteNote(soundpin,NOTE_G, 7);
delay(100);
ledcWrite(soundpin,0);
rtc_gpio_pullup_en(GPIO_NUM_26);
esp_sleep_enable_ext0_wakeup(GPIO_NUM_26,0);
esp_deep_sleep_start();
}
switch(lockState){
case DOOR_LOCKED:
if(customKey == '#'){
ledcWriteNote(soundpin,NOTE_G, 7);
delay(100);
ledcWrite(soundpin,0);
lockState = DOOR_UNLOCKING;
bool sendSuccess = radio.write(&lockState, sizeof(lockState));
while(!sendSuccess){
Serial.println("Transmition error. Sending again.");
sendSuccess = radio.write(&lockState, sizeof(lockState));
}
prevMillis = millis();
}
break;
case DOOR_UNLOCKING:
if(customKey){
ledcWriteNote(soundpin,NOTE_G, 7);
delay(100);
ledcWrite(soundpin,0);
delay(100);
if(customKey == '*'){
if(compareArrays(inputPassword, presetPassword, passwordLength)){
lockState = DOOR_UNLOCKED;
bool sendSuccess = radio.write(&lockState, sizeof(lockState));
while(!sendSuccess){
Serial.println("Transmition error. Sending again.");
sendSuccess = radio.write(&lockState, sizeof(lockState));
}
prevMillis = millis();
Serial.println("PASSWORD MATCH. DOOR OPENED!");
ledcWriteNote(soundpin,NOTE_C, 7);
delay(300);
ledcWriteNote(soundpin,NOTE_E, 7);
delay(300);
ledcWriteNote(soundpin,NOTE_G, 7);
delay(300);
ledcWrite(soundpin,0);
}
else{
lockState = DOOR_LOCKED;
bool sendSuccess = radio.write(&lockState, sizeof(lockState));
while(!sendSuccess){
Serial.println("Transmition error. Sending again.");
sendSuccess = radio.write(&lockState, sizeof(lockState));
}
prevMillis = millis();
Serial.println("PASSWORD NOT MATCHING. DOOR CLOSED!");
for(int i = 0; i < 3; i++){
ledcWriteNote(soundpin,NOTE_B, 7);
delay(100);
ledcWrite(soundpin,0);
delay(30);
}
}
resetArray(inputPassword, passwordLength);
idx = 0;
}
else{
Serial.println(customKey);
inputPassword[idx++] = customKey;
}
}
break;
case DOOR_UNLOCKED:
if(customKey == '#'){
lockState = DOOR_LOCKED;
Serial.println("DOOR LOCKING!");
bool sendSuccess = radio.write(&lockState, sizeof(lockState));
while(!sendSuccess){
Serial.println("Transmition error. Sending again.");
sendSuccess = radio.write(&lockState, sizeof(lockState));
}
prevMillis = millis();
ledcWriteNote(soundpin,NOTE_G, 7);
delay(300);
ledcWriteNote(soundpin,NOTE_E, 7);
delay(300);
ledcWriteNote(soundpin,NOTE_C, 7);
delay(300);
ledcWrite(soundpin,0);
}
break;
}
}
bool compareArrays(char arr1[], char arr2[], int size) {
for(int i = 0; i < size; i++){
Serial.print(arr1[i]);
}
Serial.println();
for (int i = 0; i < size; i++) {
if (arr1[i] != arr2[i]) {
return false; // If any element is different, return false
}
}
return true; // All elements are identical
}
void resetArray(char arr[], int size) {
for (int i = 0; i < size; i++) {
arr[i] = '$';
}
}
void print_wakeup_reason(){
esp_sleep_wakeup_cause_t wakeup_reason;
wakeup_reason = esp_sleep_get_wakeup_cause();
switch(wakeup_reason)
{
case 2 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
case 3 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
case 4 : Serial.println("Wakeup caused by timer"); break;
case 5 : Serial.println("Wakeup caused by touchpad"); break;
case 6 : Serial.println("Wakeup caused by ULP program"); break;
default : Serial.println("Wakeup was not caused by deep sleep"); break;
}
}
[Servo Module Code(Rx)]
#include "ESP32Servo.h"
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <esp_sleep.h>
#include <EEPROM.h>
#include "driver/rtc_io.h"
RF24 radio(4, 5);
// long long address = 0x1234ABCDEFLL;
const byte address[][6] = {"00001", "00002"};
#define SERVO_PIN 13
#define NRF_IRQ_PIN 14 // Pin connected to nRF24L01+ IRQ pin
Servo myservo;
bool isServoRotated = false;
bool isLocked = true;
enum doorLockState {
DOOR_LOCKED,
DOOR_UNLOCKING,
DOOR_UNLOCKED
};
doorLockState lockState = DOOR_LOCKED;
unsigned long lastRadioSignalTime = 0;
const unsigned long sleepDelay = 5000; // 5 seconds
volatile bool radioSignalReceived = false;
void IRAM_ATTR onRadioSignal() {
radioSignalReceived = true;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
myservo.setPeriodHertz(50);
myservo.attach(SERVO_PIN, 500, 2400);
myservo.write(10);
radio.begin();
radio.openReadingPipe(1, address[1]);
radio.setDataRate(RF24_2MBPS);
radio.setPALevel(RF24_PA_MIN);
radio.setChannel(0x4C);
radio.startListening();
delay(1000);
// Set up the interrupt for the nRF24L01+ IRQ pin
pinMode(NRF_IRQ_PIN, INPUT);
attachInterrupt(digitalPinToInterrupt(NRF_IRQ_PIN), onRadioSignal, FALLING);
// Initialize EEPROM
EEPROM.begin(512);
// Check if EEPROM is initialized
if (EEPROM.read(0) != 0xAA) {
// EEPROM is not initialized, set default values
lockState = DOOR_LOCKED;
isServoRotated = false;
isLocked = true;
// Write default values to EEPROM
EEPROM.write(0, 0xAA); // Mark EEPROM as initialized
EEPROM.write(1, lockState);
EEPROM.write(2, isServoRotated);
EEPROM.write(3, isLocked);
EEPROM.commit();
} else {
// EEPROM is initialized, read stored values
lockState = (doorLockState)EEPROM.read(1);
isServoRotated = EEPROM.read(2);
isLocked = EEPROM.read(3);
}
}
void loop() {
// put your main code here, to run repeatedly:
if (radioSignalReceived) {
radioSignalReceived = false;
if (radio.available()) {
radio.read(&lockState, sizeof(lockState));
Serial.println(lockState);
lastRadioSignalTime = millis();
}
}
if (millis() - lastRadioSignalTime >= sleepDelay) {
// No signal for 5 seconds, go to sleep
Serial.println("No signal, going to sleep...");
Serial.flush();
enterDeepSleep();
}
switch (lockState) {
case DOOR_LOCKED:
if (!isServoRotated || !isLocked) {
Serial.println("Servo rotating for door locking!");
myservo.write(0);
delay(1000);
isServoRotated = true;
isLocked = true;
}
break;
case DOOR_UNLOCKING:
isServoRotated = false;
break;
case DOOR_UNLOCKED:
if (!isServoRotated) {
Serial.println("Servo rotating for door unlocking!");
myservo.write(100);
delay(1000);
isServoRotated = true;
}
isLocked = false;
break;
}
}
void enterDeepSleep() {
// Store state in EEPROM
EEPROM.write(1, lockState);
EEPROM.write(2, isServoRotated);
EEPROM.write(3, isLocked);
EEPROM.commit();
// Prepare for deep sleep
esp_sleep_enable_ext0_wakeup((gpio_num_t)NRF_IRQ_PIN, 0); // Wake up on falling edge (LOW signal)
Serial.println("Going to deep sleep...");
Serial.flush();
gpio_pullup_en((gpio_num_t)NRF_IRQ_PIN);
esp_deep_sleep_start();
}
I'm suffering from this problem for the whole day... Please I need your help guys
Thanks.