Advertisement
kodilivetv

esp32_mpu6050_deepsleep_interrupt_c3SUPERMINI

Jul 4th, 2025
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.06 KB | Software | 0 0
  1. /*
  2.  * ESP32-C3 Supermini Motion Detection with Deep Sleep and Telegram Notifications
  3.  *
  4.  * DESCRIPTION:
  5.  * This sketch implements a battery-efficient motion detection system using an ESP32-C3 Supermini
  6.  * and MPU6050 accelerometer/gyroscope sensor. The system uses deep sleep to conserve power and
  7.  * wakes up on motion detection or timer events.
  8.  *
  9.  * FUNCTIONALITY:
  10.  * - Detects motion using MPU6050's Wake-on-Motion (WoM) interrupt feature
  11.  * - Wakes from deep sleep when motion is detected on GPIO pin 4
  12.  * - Sends boot count notifications to Telegram bot
  13.  * - Implements power-saving sleep cycle:
  14.  *   * First 2 wake-ups: Motion detection mode (wake on GPIO interrupt)
  15.  *   * 3rd wake-up: Extended sleep mode (5 minutes timer-based sleep)
  16.  *   * Cycle repeats indefinitely
  17.  *
  18.  * HARDWARE REQUIREMENTS:
  19.  * - ESP32-C3 Supermini board
  20.  * - MPU6050 sensor module
  21.  * - LED connected to GPIO 8 (for status indication)
  22.  * - I2C connections: SDA=GPIO6, SCL=GPIO7
  23.  * - Interrupt connection: MPU6050 INT pin to GPIO4
  24.  *
  25.  * POWER OPTIMIZATION:
  26.  * - Disables gyroscopes to reduce current consumption (~600µA)
  27.  * - Uses deep sleep between motion events
  28.  * - Brownout detector disabled for stable operation
  29.  * - GPIO wakeup configured for ESP32-C3 (differs from ESP32-WROOM/WROVER)
  30.  *
  31.  * NETWORK FEATURES:
  32.  * - Connects to WiFi network on wake-up
  33.  * - Sends notifications via Telegram bot
  34.  * - Includes timeout protection for WiFi connection attempts
  35.  * - Synchronizes time with NTP servers
  36.  *
  37.  * CONFIGURATION:
  38.  * - Motion sensitivity: Adjustable via setInterrupt() threshold (1-255)
  39.  * - Sleep duration: 5 minutes (LONG_SLEEP_TIME constant)
  40.  * - WiFi credentials and Telegram token need to be configured
  41.  * - Timezone set for Lisbon, Portugal (MYTZ constant)
  42.  *
  43.  * OPERATION CYCLE:
  44.  * 1. Boot and increment boot counter
  45.  * 2. Send status to Telegram
  46.  * 3. Configure motion detection (boots 1-2) or timer sleep (boot 3)
  47.  * 4. Enter deep sleep
  48.  * 5. Wake on motion or timer, repeat cycle
  49.  *
  50.  * AUTHOR: [Your name/organization]
  51.  * VERSION: 1.0
  52.  * DATE: [Current date]
  53.  *
  54.  * DEPENDENCIES:
  55.  * - AsyncTelegram2 library
  56.  * - WiFiClientSecure library
  57.  * - Wire library (I2C)
  58.  *
  59.  * NOTE: This code is specifically configured for ESP32-C3 Supermini.
  60.  * GPIO wakeup configuration differs from ESP32-WROOM/WROVER modules.
  61.  */
  62.  
  63.  /*
  64. * https://www.jarzebski.pl/arduino/czujniki-i-sensory/3-osiowy-zyroskop-i-akcelerometr-mpu6050.html
  65. * https://wolles-elektronikkiste.de/mpu6050-beschleunigungssensor-und-gyroskop
  66. * https://arduino.stackexchange.com/questions/48424/how-to-generate-hardware-interrupt-in-mpu6050-to-wakeup-arduino-from-sleep-mode/48430#48430
  67. * https://github.com/chris-ault/MotionDetector
  68. * https://os.mbed.com/teams/Unina_corse/code/Nucleo_rtos_basic_copyProva_Quirino/docs/tip/MPU6050_8h_source.html
  69. */
  70.  
  71. //#include <WiFi.h>
  72.  
  73. #include "soc/soc.h"           // Brownout error fix
  74. #include "soc/rtc_cntl_reg.h"  // Brownout error fix
  75.  
  76. #include "driver/rtc_io.h"
  77.  
  78. #include <WiFiClientSecure.h>
  79. WiFiClientSecure client;
  80. #include <AsyncTelegram2.h> // https://github.com/cotestatnt/AsyncTelegram2
  81. AsyncTelegram2 myBot(client);
  82. const char * network = "xxxxxxxx"; // SSID WiFi network
  83. const char * pass = "xxxxxxxx"; // Password  WiFi network
  84. const char * token = "xxxxxxxx"; // (superC3mpu6050) Telegram token
  85. int64_t userid = xxxxxxxx;
  86. //int64_t userid = -1001336045228; // Canal Oeste
  87. #define MYTZ "WET0WEST,M3.5.0/1,M10.5.0/2" // POSIX timezone string for Lisbon
  88.  
  89. #include "Wire.h"
  90.  
  91. #define MPU6050_ADDR              0x68 // Alternatively set AD0 to HIGH  --> Address = 0x69
  92. #define MPU6050_ACCEL_CONFIG      0x1C // Accelerometer Configuration Register
  93. #define MPU6050_PWR_MGT_1         0x6B // Power Management 1 Register
  94. #define MPU6050_INT_PIN_CFG       0x37 // Interrupt Pin / Bypass Enable Configuration Register
  95. #define MPU6050_INT_ENABLE        0x38 // Interrupt Enable Register
  96. #define MPU6050_LATCH_INT_EN      0x05 // Latch Enable Bit for Interrupt
  97. #define MPU6050_ACTL              0x07 // Active-Low Enable Bit
  98. #define MPU6050_WOM_EN            0x06 // Wake on Motion Enable bit
  99. #define MPU6050_WOM_THR           0x1F // Wake on Motion Threshold Register
  100. #define MPU6050_MOT_DUR           0x20 // Motion Detection Duration Register
  101. #define MPU6050_ACCEL_INTEL_CTRL  0x69 // Accelaration Interrupt Control Register
  102. #define MPU6050_SIGNAL_PATH_RESET 0x68 // Signal Path Reset Register
  103.  
  104. //byte interruptPin = 4;
  105. byte ledPin = 8; // ESP32-C3 Supermini
  106. volatile bool accEvent = false;
  107.  
  108. #define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */
  109. #define LONG_SLEEP_TIME  5 * 60       /* Time ESP32 will sleep (in seconds) if bootCount = 4 */
  110. #define WAKEUP_PIN 4   /* GPIO pin used for external wakeup */
  111.  
  112. RTC_DATA_ATTR int bootCount = 0;
  113.  
  114. /*
  115. Method to print the reason by which ESP32
  116. has been awaken from sleep
  117. */
  118. void print_wakeup_reason(){
  119.   esp_sleep_wakeup_cause_t wakeup_reason;
  120.  
  121.   wakeup_reason = esp_sleep_get_wakeup_cause();
  122.  
  123.   switch(wakeup_reason)
  124.   {
  125.     case ESP_SLEEP_WAKEUP_EXT0 : Serial.println("Wakeup caused by external signal using RTC_IO"); break;
  126.     case ESP_SLEEP_WAKEUP_EXT1 : Serial.println("Wakeup caused by external signal using RTC_CNTL"); break;
  127.     case ESP_SLEEP_WAKEUP_TIMER : Serial.println("Wakeup caused by timer"); break;
  128.     case ESP_SLEEP_WAKEUP_TOUCHPAD : Serial.println("Wakeup caused by touchpad"); break;
  129.     case ESP_SLEEP_WAKEUP_ULP : Serial.println("Wakeup caused by ULP program"); break;
  130.     default : Serial.printf("Wakeup was not caused by deep sleep: %d\n",wakeup_reason); break;
  131.   }
  132. }
  133.  
  134. void blinkLED(int numBlinks, int blinkInterval) {
  135.    for (int i = 0; i < numBlinks; i++) {
  136.     digitalWrite(ledPin, LOW); // Turn on the LED // LOW for ESP32C3
  137.     delay(blinkInterval);
  138.     digitalWrite(ledPin, HIGH); // Turn off the LED
  139.     delay(blinkInterval);
  140.   }  
  141. }
  142.  
  143. void sendToTelegram() {  
  144.   Serial.print("Connecting to ");
  145.   Serial.println(network);
  146.  
  147.   WiFi.begin(network, pass);
  148.  
  149.   int wifi_start_counter = 0;
  150.   while (WiFi.status() != WL_CONNECTED) {
  151.     Serial.print(".");
  152.     wifi_start_counter++;
  153.     if (wifi_start_counter >= 10) {
  154.       return; // exit sendToTelegram() completely
  155.     }
  156.     delay(1000);
  157.   }
  158.  
  159.   Serial.println("");
  160.   Serial.println("WiFi connected! Sending message to Telegram...");
  161.  
  162.   // Sync time with NTP
  163.   configTzTime(MYTZ, "time.google.com", "time.windows.com", "pool.ntp.org");
  164.   client.setCACert(telegram_cert);
  165.   // Set the Telegram bot properies
  166.   myBot.setUpdateTime(2000);
  167.   myBot.setTelegramToken(token);
  168.  
  169.   // Check if all things are ok
  170.   Serial.print("\nTest Telegram connection... ");
  171.   myBot.begin() ? Serial.println("OK") : Serial.println("NOK");
  172.  
  173.   //// Send a welcome message to user when ready
  174.   //char welcome_msg[64];
  175.   //snprintf(welcome_msg, 64, "BOT @%s online.\nTry with /takePhoto command.", myBot.getBotName());
  176.   //myBot.sendTo(userid, welcome_msg);
  177.  
  178.     char bootCountMsg[64];
  179.     snprintf(bootCountMsg, 64, "Boot count is: %d", bootCount);
  180.     myBot.sendTo(userid, bootCountMsg);
  181.  
  182.   //const char* message = "/clip";
  183.   //// Send the message to the Telegram channel
  184.   //bool sent = myBot.sendTo(userid, message);
  185. }
  186.  
  187. void setup() {  
  188.   WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0);       // disable brownout detector
  189.  
  190.   Wire.begin(6, 7);
  191.    
  192.   Serial.begin(115200);Serial.println("");
  193.  
  194.   pinMode(ledPin, OUTPUT);
  195.   blinkLED(3, 100); // Blink the LED 3 times with a 100ms interval
  196.  
  197.   //Print the wakeup reason for ESP32
  198.   //print_wakeup_reason();
  199.  
  200.   //Increment boot number and print it every reboot
  201.   ++bootCount;
  202.   Serial.println("Boot number: " + String(bootCount));Serial.println("");
  203.  
  204.    sendToTelegram();
  205.  
  206.    // Sleep for an amount of time after more than 3 external interrupts
  207.   if (bootCount >= 1 && bootCount <= 2) {
  208.  
  209.     writeRegister(MPU6050_PWR_MGT_1, 0);
  210.     setInterrupt(1); // set Wake on Motion Interrupt / Sensitivity; 1(highest sensitivity) - 255
  211.     delay(100);
  212.    
  213.     // Configure external wakeup on WAKEUP_PIN when bootCount is between 1 and 3
  214.     // For ESP32 C3 Supermini
  215.     esp_deep_sleep_enable_gpio_wakeup(1 << WAKEUP_PIN, ESP_GPIO_WAKEUP_GPIO_HIGH);
  216.  
  217.     /*// For ESP32-WROOM and ESP32-WROVER
  218.     esp_sleep_enable_ext0_wakeup(WAKEUP_PIN, 1); // 1 = High, 0 = Low
  219.     rtc_gpio_pullup_dis(WAKEUP_PIN);
  220.     rtc_gpio_pulldown_en(WAKEUP_PIN);*/
  221.  
  222.     Serial.println("Setup ESP32 to wake up on WAKEUP_PIN trigger");
  223.    
  224.   } else if (bootCount == 3) {
  225.    
  226.     // Reset bootCount and set timer wakeup for 2*30 seconds
  227.     bootCount = 0;
  228.     esp_sleep_enable_timer_wakeup(LONG_SLEEP_TIME * uS_TO_S_FACTOR);
  229.     Serial.println("Setup ESP32 to sleep for 10*60 seconds and reset bootCount");
  230.    
  231.   }
  232.  
  233.   // Go to sleep now
  234.   blinkLED(2, 1000); // Blink the LED 2 times with a 100ms interval
  235.   Serial.println("");
  236.   Serial.println("Going to sleep now");
  237.   Serial.flush();
  238.   esp_deep_sleep_start();
  239.   Serial.println("This will never be printed");
  240.  
  241. }
  242.  
  243. void loop() {
  244.  
  245. //   if(accEvent){
  246. //    digitalWrite(ledPin, HIGH);
  247. //    delay(1000);
  248. //    digitalWrite(ledPin, LOW);
  249. //    accEvent = false;
  250. //    attachInterrupt(digitalPinToInterrupt(interruptPin), motion, RISING);  
  251. //  }
  252.  
  253. }
  254.  
  255. void setInterrupt(byte threshold){
  256. //writeRegister(MPU6050_SIGNAL_PATH_RESET, 0b00000111);  // not(?) needed
  257. //writeRegister(MPU6050_INT_PIN_CFG, 1<<MPU6050_ACTL); // 1<<MPU6050_LATCH_INT_EN
  258.   writeRegister(MPU6050_ACCEL_CONFIG, 0b00000001);
  259.   writeRegister(MPU6050_WOM_THR, threshold);
  260.   writeRegister(MPU6050_MOT_DUR, 0b00000001);  // set duration (LSB = 1 ms)
  261. //writeRegister(MPU6050_ACCEL_INTEL_CTRL, 0x15);  // not needed (?)
  262.   writeRegister(MPU6050_INT_ENABLE, 1<<MPU6050_WOM_EN);
  263.  
  264.  writeRegister(0x6C, 7); // Disable Gyros to lower quiescent current to close to 600uA
  265.  //writeRegister(0x6C, 0); // Re-enable Gyros
  266. }
  267.  
  268. void writeRegister(uint16_t reg, byte value){
  269.   Wire.beginTransmission(MPU6050_ADDR);
  270.   Wire.write(reg);
  271.   Wire.write(value);
  272.   Wire.endTransmission();
  273. }
  274.  
  275. //void motion(){
  276. //  accEvent = true;
  277. //  detachInterrupt(digitalPinToInterrupt(interruptPin));
  278. //}
  279.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement