Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * ESP32-C3 Supermini Motion Detection with Deep Sleep and Telegram Notifications
- *
- * DESCRIPTION:
- * This sketch implements a battery-efficient motion detection system using an ESP32-C3 Supermini
- * and MPU6050 accelerometer/gyroscope sensor. The system uses deep sleep to conserve power and
- * wakes up on motion detection or timer events.
- *
- * FUNCTIONALITY:
- * - Detects motion using MPU6050's Wake-on-Motion (WoM) interrupt feature
- * - Wakes from deep sleep when motion is detected on GPIO pin 4
- * - Sends boot count notifications to Telegram bot
- * - Implements power-saving sleep cycle:
- * * First 2 wake-ups: Motion detection mode (wake on GPIO interrupt)
- * * 3rd wake-up: Extended sleep mode (5 minutes timer-based sleep)
- * * Cycle repeats indefinitely
- *
- * HARDWARE REQUIREMENTS:
- * - ESP32-C3 Supermini board
- * - MPU6050 sensor module
- * - LED connected to GPIO 8 (for status indication)
- * - I2C connections: SDA=GPIO6, SCL=GPIO7
- * - Interrupt connection: MPU6050 INT pin to GPIO4
- *
- * POWER OPTIMIZATION:
- * - Disables gyroscopes to reduce current consumption (~600µA)
- * - Uses deep sleep between motion events
- * - Brownout detector disabled for stable operation
- * - GPIO wakeup configured for ESP32-C3 (differs from ESP32-WROOM/WROVER)
- *
- * NETWORK FEATURES:
- * - Connects to WiFi network on wake-up
- * - Sends notifications via Telegram bot
- * - Includes timeout protection for WiFi connection attempts
- * - Synchronizes time with NTP servers
- *
- * CONFIGURATION:
- * - Motion sensitivity: Adjustable via setInterrupt() threshold (1-255)
- * - Sleep duration: 5 minutes (LONG_SLEEP_TIME constant)
- * - WiFi credentials and Telegram token need to be configured
- * - Timezone set for Lisbon, Portugal (MYTZ constant)
- *
- * OPERATION CYCLE:
- * 1. Boot and increment boot counter
- * 2. Send status to Telegram
- * 3. Configure motion detection (boots 1-2) or timer sleep (boot 3)
- * 4. Enter deep sleep
- * 5. Wake on motion or timer, repeat cycle
- *
- * AUTHOR: [Your name/organization]
- * VERSION: 1.0
- * DATE: [Current date]
- *
- * DEPENDENCIES:
- * - AsyncTelegram2 library
- * - WiFiClientSecure library
- * - Wire library (I2C)
- *
- * NOTE: This code is specifically configured for ESP32-C3 Supermini.
- * GPIO wakeup configuration differs from ESP32-WROOM/WROVER modules.
- */
- /*
- * https://www.jarzebski.pl/arduino/czujniki-i-sensory/3-osiowy-zyroskop-i-akcelerometr-mpu6050.html
- * https://wolles-elektronikkiste.de/mpu6050-beschleunigungssensor-und-gyroskop
- * https://arduino.stackexchange.com/questions/48424/how-to-generate-hardware-interrupt-in-mpu6050-to-wakeup-arduino-from-sleep-mode/48430#48430
- * https://github.com/chris-ault/MotionDetector
- * https://os.mbed.com/teams/Unina_corse/code/Nucleo_rtos_basic_copyProva_Quirino/docs/tip/MPU6050_8h_source.html
- */
- //#include <WiFi.h>
- #include "soc/soc.h" // Brownout error fix
- #include "soc/rtc_cntl_reg.h" // Brownout error fix
- #include "driver/rtc_io.h"
- #include <WiFiClientSecure.h>
- WiFiClientSecure client;
- #include <AsyncTelegram2.h> // https://github.com/cotestatnt/AsyncTelegram2
- AsyncTelegram2 myBot(client);
- const char * network = "xxxxxxxx"; // SSID WiFi network
- const char * pass = "xxxxxxxx"; // Password WiFi network
- const char * token = "xxxxxxxx"; // (superC3mpu6050) Telegram token
- int64_t userid = xxxxxxxx;
- //int64_t userid = -1001336045228; // Canal Oeste
- #define MYTZ "WET0WEST,M3.5.0/1,M10.5.0/2" // POSIX timezone string for Lisbon
- #include "Wire.h"
- #define MPU6050_ADDR 0x68 // Alternatively set AD0 to HIGH --> Address = 0x69
- #define MPU6050_ACCEL_CONFIG 0x1C // Accelerometer Configuration Register
- #define MPU6050_PWR_MGT_1 0x6B // Power Management 1 Register
- #define MPU6050_INT_PIN_CFG 0x37 // Interrupt Pin / Bypass Enable Configuration Register
- #define MPU6050_INT_ENABLE 0x38 // Interrupt Enable Register
- #define MPU6050_LATCH_INT_EN 0x05 // Latch Enable Bit for Interrupt
- #define MPU6050_ACTL 0x07 // Active-Low Enable Bit
- #define MPU6050_WOM_EN 0x06 // Wake on Motion Enable bit
- #define MPU6050_WOM_THR 0x1F // Wake on Motion Threshold Register
- #define MPU6050_MOT_DUR 0x20 // Motion Detection Duration Register
- #define MPU6050_ACCEL_INTEL_CTRL 0x69 // Accelaration Interrupt Control Register
- #define MPU6050_SIGNAL_PATH_RESET 0x68 // Signal Path Reset Register
- //byte interruptPin = 4;
- byte ledPin = 8; // ESP32-C3 Supermini
- volatile bool accEvent = false;
- #define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */
- #define LONG_SLEEP_TIME 5 * 60 /* Time ESP32 will sleep (in seconds) if bootCount = 4 */
- #define WAKEUP_PIN 4 /* GPIO pin used for external wakeup */
- RTC_DATA_ATTR int bootCount = 0;
- /*
- Method to print the reason by which ESP32
- has been awaken from sleep
- */
- 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;
- default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
- }
- }
- void blinkLED(int numBlinks, int blinkInterval) {
- for (int i = 0; i < numBlinks; i++) {
- digitalWrite(ledPin, LOW); // Turn on the LED // LOW for ESP32C3
- delay(blinkInterval);
- digitalWrite(ledPin, HIGH); // Turn off the LED
- delay(blinkInterval);
- }
- }
- void sendToTelegram() {
- Serial.print("Connecting to ");
- Serial.println(network);
- WiFi.begin(network, pass);
- int wifi_start_counter = 0;
- while (WiFi.status() != WL_CONNECTED) {
- Serial.print(".");
- wifi_start_counter++;
- if (wifi_start_counter >= 10) {
- return; // exit sendToTelegram() completely
- }
- delay(1000);
- }
- Serial.println("");
- Serial.println("WiFi connected! Sending message to Telegram...");
- // Sync time with NTP
- configTzTime(MYTZ, "time.google.com", "time.windows.com", "pool.ntp.org");
- client.setCACert(telegram_cert);
- // Set the Telegram bot properies
- myBot.setUpdateTime(2000);
- myBot.setTelegramToken(token);
- // Check if all things are ok
- Serial.print("\nTest Telegram connection... ");
- myBot.begin() ? Serial.println("OK") : Serial.println("NOK");
- //// Send a welcome message to user when ready
- //char welcome_msg[64];
- //snprintf(welcome_msg, 64, "BOT @%s online.\nTry with /takePhoto command.", myBot.getBotName());
- //myBot.sendTo(userid, welcome_msg);
- char bootCountMsg[64];
- snprintf(bootCountMsg, 64, "Boot count is: %d", bootCount);
- myBot.sendTo(userid, bootCountMsg);
- //const char* message = "/clip";
- //// Send the message to the Telegram channel
- //bool sent = myBot.sendTo(userid, message);
- }
- void setup() {
- WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector
- Wire.begin(6, 7);
- Serial.begin(115200);Serial.println("");
- pinMode(ledPin, OUTPUT);
- blinkLED(3, 100); // Blink the LED 3 times with a 100ms interval
- //Print the wakeup reason for ESP32
- //print_wakeup_reason();
- //Increment boot number and print it every reboot
- ++bootCount;
- Serial.println("Boot number: " + String(bootCount));Serial.println("");
- sendToTelegram();
- // Sleep for an amount of time after more than 3 external interrupts
- if (bootCount >= 1 && bootCount <= 2) {
- writeRegister(MPU6050_PWR_MGT_1, 0);
- setInterrupt(1); // set Wake on Motion Interrupt / Sensitivity; 1(highest sensitivity) - 255
- delay(100);
- // Configure external wakeup on WAKEUP_PIN when bootCount is between 1 and 3
- // For ESP32 C3 Supermini
- esp_deep_sleep_enable_gpio_wakeup(1 << WAKEUP_PIN, ESP_GPIO_WAKEUP_GPIO_HIGH);
- /*// For ESP32-WROOM and ESP32-WROVER
- esp_sleep_enable_ext0_wakeup(WAKEUP_PIN, 1); // 1 = High, 0 = Low
- rtc_gpio_pullup_dis(WAKEUP_PIN);
- rtc_gpio_pulldown_en(WAKEUP_PIN);*/
- Serial.println("Setup ESP32 to wake up on WAKEUP_PIN trigger");
- } else if (bootCount == 3) {
- // Reset bootCount and set timer wakeup for 2*30 seconds
- bootCount = 0;
- esp_sleep_enable_timer_wakeup(LONG_SLEEP_TIME * uS_TO_S_FACTOR);
- Serial.println("Setup ESP32 to sleep for 10*60 seconds and reset bootCount");
- }
- // Go to sleep now
- blinkLED(2, 1000); // Blink the LED 2 times with a 100ms interval
- Serial.println("");
- Serial.println("Going to sleep now");
- Serial.flush();
- esp_deep_sleep_start();
- Serial.println("This will never be printed");
- }
- void loop() {
- // if(accEvent){
- // digitalWrite(ledPin, HIGH);
- // delay(1000);
- // digitalWrite(ledPin, LOW);
- // accEvent = false;
- // attachInterrupt(digitalPinToInterrupt(interruptPin), motion, RISING);
- // }
- }
- void setInterrupt(byte threshold){
- //writeRegister(MPU6050_SIGNAL_PATH_RESET, 0b00000111); // not(?) needed
- //writeRegister(MPU6050_INT_PIN_CFG, 1<<MPU6050_ACTL); // 1<<MPU6050_LATCH_INT_EN
- writeRegister(MPU6050_ACCEL_CONFIG, 0b00000001);
- writeRegister(MPU6050_WOM_THR, threshold);
- writeRegister(MPU6050_MOT_DUR, 0b00000001); // set duration (LSB = 1 ms)
- //writeRegister(MPU6050_ACCEL_INTEL_CTRL, 0x15); // not needed (?)
- writeRegister(MPU6050_INT_ENABLE, 1<<MPU6050_WOM_EN);
- writeRegister(0x6C, 7); // Disable Gyros to lower quiescent current to close to 600uA
- //writeRegister(0x6C, 0); // Re-enable Gyros
- }
- void writeRegister(uint16_t reg, byte value){
- Wire.beginTransmission(MPU6050_ADDR);
- Wire.write(reg);
- Wire.write(value);
- Wire.endTransmission();
- }
- //void motion(){
- // accEvent = true;
- // detachInterrupt(digitalPinToInterrupt(interruptPin));
- //}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement