Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- This sketch configures an ESP32 module to monitor motion using an ADXL345 accelerometer,
- sends boot count information via Telegram, and manages power consumption through deep sleep modes.
- Key functionalities:
- - Monitors activity on the Y-axis using the ADXL345 accelerometer, with configurable thresholds.
- - Connects to WiFi and sends updates via Telegram on each boot, including the boot count.
- - If no significant activity is detected within a few seconds after ADXL345 setup begins, the ESP32 enters deep sleep mode.
- - Deep sleep is managed based on the boot count:
- - Boots 1-2: The ESP32 can wake up on external activity (GPIO14).
- - Boot 3: The ESP32 sleeps for an extended period (2 minutes), then resets the boot count.
- - Includes brownout protection and visual feedback (LED) on boot and before entering deep sleep.
- Libraries used:
- - ADXL345_WE: For controlling and configuring the ADXL345 accelerometer.
- https://wolles-elektronikkiste.de/en/adxl345-the-universal-accelerometer-part-1 (English)
- https://github.com/wollewald/ADXL345_WE
- - AsyncTelegram2: For sending messages through Telegram.
- https://github.com/cotestatnt/AsyncTelegram2
- Configure WiFi and Telegram token parameters.
- This project is being used to detect rain events. The bottom of a plastic container was cut and the opening, now facing up, covered with cellophane;
- the adxl345 was glued to the cellophane, which bounces with the drops of rain, triggering the interrupt.
- */
- #include "driver/rtc_io.h"
- #include<Wire.h>
- #include<ADXL345_WE.h>
- #define ADXL345_I2CADDR 0x53 // 0x1D if SDO = HIGH
- const int int2Pin = 14;
- volatile bool in_activity = false; // in_activity: either activity or inactivity interrupt occured
- #include "soc/soc.h" // Brownout error fix
- #include "soc/rtc_cntl_reg.h" // Brownout error fix
- #include <WiFiClientSecure.h>
- WiFiClientSecure client;
- #include <AsyncTelegram2.h> // https://github.com/cotestatnt/AsyncTelegram2
- AsyncTelegram2 myBot(client);
- const char * network = "696969"; // SSID WiFi network
- const char * pass = "696969"; // Password WiFi network
- const char * token = "696969"; // () Telegram token
- int64_t userid = 696969;
- //int64_t userid = -696969; //
- #define MYTZ "WET0WEST,M3.5.0/1,M10.5.0/2" // POSIX timezone string for Lisbon
- /* There are several ways to create your ADXL345 object:
- * ADXL345_WE myAcc = ADXL345_WE() -> uses Wire / I2C Address = 0x53
- * ADXL345_WE myAcc = ADXL345_WE(ADXL345_I2CADDR) -> uses Wire / ADXL345_I2CADDR
- * ADXL345_WE myAcc = ADXL345_WE(&wire2) -> uses the TwoWire object wire2 / ADXL345_I2CADDR
- * ADXL345_WE myAcc = ADXL345_WE(&wire2, ADXL345_I2CADDR) -> all together
- */
- ADXL345_WE myAcc = ADXL345_WE(ADXL345_I2CADDR);
- int activity_counter = 0;
- bool goToSleep = false;
- #define uS_TO_S_FACTOR 1000000ULL /* Conversion factor for micro seconds to seconds */
- #define LONG_SLEEP_TIME 10 * 60 /* Time ESP32 will sleep (in seconds) if bootCount = 4 */
- #define WAKEUP_GPIO GPIO_NUM_14 /* GPIO pin used for external wakeup */
- RTC_DATA_ATTR int bootCount = 0;
- byte ledPin = 13; // ESP32-room-32
- portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
- void IRAM_ATTR in_activityISR() {
- portENTER_CRITICAL(&mux);
- in_activity = true;
- portEXIT_CRITICAL(&mux);
- }
- 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) {
- //enterDeepSleep();
- break;
- }
- delay(1000);
- }
- Serial.println("");
- Serial.println("WiFi connected!");
- // 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 blinkLED(int numBlinks, int blinkInterval) {
- for (int i = 0; i < numBlinks; i++) {
- digitalWrite(ledPin, HIGH); // Turn on the LED
- delay(blinkInterval);
- digitalWrite(ledPin, LOW); // Turn off the LED
- delay(blinkInterval);
- }
- }
- void setup() {
- WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); // disable brownout detector
- Wire.begin(33, 32);
- Serial.begin(9600); Serial.println();
- pinMode(int2Pin, INPUT);
- pinMode(ledPin, OUTPUT);
- blinkLED(3, 200); // Blink the LED 3 times with a 200ms interval to indicate wake up
- Serial.println("ADXL345_Sketch - Activity and Inactivity Interrupts");
- Serial.println();
- //Increment boot number and print it every reboot
- ++bootCount;
- Serial.println("Boot number: " + String(bootCount));
- Serial.println();
- sendToTelegram();
- if (!myAcc.init()) {
- Serial.println("ADXL345 not connected!");
- }
- /* Choose the data rate Hz
- ADXL345_DATA_RATE_3200 3200
- ADXL345_DATA_RATE_1600 1600
- ADXL345_DATA_RATE_800 800
- ADXL345_DATA_RATE_400 400
- ADXL345_DATA_RATE_200 200
- ADXL345_DATA_RATE_100 100
- ADXL345_DATA_RATE_50 50
- ADXL345_DATA_RATE_25 25
- ADXL345_DATA_RATE_12_5 12.5
- ADXL345_DATA_RATE_6_25 6.25
- ADXL345_DATA_RATE_3_13 3.13
- ADXL345_DATA_RATE_1_56 1.56
- ADXL345_DATA_RATE_0_78 0.78
- ADXL345_DATA_RATE_0_39 0.39
- ADXL345_DATA_RATE_0_20 0.20
- ADXL345_DATA_RATE_0_10 0.10
- */
- myAcc.setDataRate(ADXL345_DATA_RATE_200);
- Serial.print("Data rate: ");
- Serial.print(myAcc.getDataRateAsString());
- /* Choose the measurement range
- ADXL345_RANGE_16G 16g
- ADXL345_RANGE_8G 8g
- ADXL345_RANGE_4G 4g
- ADXL345_RANGE_2G 2g
- */
- myAcc.setRange(ADXL345_RANGE_2G);
- Serial.print(" / g-Range: ");
- Serial.println(myAcc.getRangeAsString());
- Serial.println();
- attachInterrupt(digitalPinToInterrupt(int2Pin), in_activityISR, RISING);
- /* Three parameters have to be set for activity:
- 1. DC / AC Mode:
- ADXL345_DC_MODE - Threshold is the defined one (parameter 3)
- ADXL345_AC_MODE - Threshold = starting acceleration + defined threshold
- 2. Axes, that are considered:
- ADXL345_000 - no axis (which makes no sense)
- ADXL345_00Z - z
- ADXL345_0Y0 - y
- ADXL345_0YZ - y,z
- ADXL345_X00 - x
- ADXL345_X0Z - x,z
- ADXL345_XY0 - x,y
- ADXL345_XYZ - all axes
- 3. Threshold in g
- */
- myAcc.setActivityParameters(ADXL345_AC_MODE, ADXL345_0Y0, 0.1);
- /* You can choose the following interrupts:
- Variable name: Triggered, if:
- ADXL345_OVERRUN - new data replaces unread data
- ADXL345_WATERMARK - the number of samples in FIFO equals the number defined in FIFO_CTL
- ADXL345_FREEFALL - acceleration values of all axes are below the threshold defined in THRESH_FF
- ADXL345_INACTIVITY - acc. value of all included axes are < THRESH_INACT for period > TIME_INACT
- ADXL345_ACTIVITY - acc. value of included axes are > THRESH_ACT
- ADXL345_DOUBLE_TAP - double tap detected on one incl. axis and various defined conditions are met
- ADXL345_SINGLE_TAP - single tap detected on one incl. axis and various defined conditions are met
- ADXL345_DATA_READY - new data available
- Assign the interrupts to INT1 (INT_PIN_1) or INT2 (INT_PIN_2). Data ready, watermark and overrun are
- always enabled. You can only change the assignment of these which is INT1 by default.
- You can delete interrupts with deleteInterrupt(type);
- */
- myAcc.setInterrupt(ADXL345_ACTIVITY, INT_PIN_2);
- myAcc.readAndClearInterrupts();
- }
- /* In the main loop some checks are done:
- getActTapStatus() returns which axes are responsible for activity interrupt as byte (code in library)
- getActTapStatusAsString() returns the axes that caused the interrupt as string
- readAndClearInterrupts(); returns the interrupt type as byte (code in library)
- checkInterrupt(intSource, type) returns if intSource is type as bool
- */
- void loop() {
- if ((millis() % 1000) == 1) {
- xyzFloat g = myAcc.getGValues();
- Serial.print("g-x = ");
- Serial.print(g.x);
- Serial.print(" | g-y = ");
- Serial.print(g.y);
- Serial.print(" | g-z = ");
- Serial.print(g.z);
- Serial.print(" | act-cnt = ");
- ++activity_counter;
- Serial.println(activity_counter);
- }
- if(in_activity == true) {
- ++activity_counter;
- //byte actTapSource = myAcc.getActTapStatus();
- //Serial.println(actTapSource, BIN);
- String axes = myAcc.getActTapStatusAsString();
- byte intSource = myAcc.readAndClearInterrupts();
- if(myAcc.checkInterrupt(intSource, ADXL345_ACTIVITY)){
- Serial.print("Activity at: ");
- Serial.println(axes);
- }
- delay(1000);
- myAcc.readAndClearInterrupts();
- in_activity = false;
- }
- if(activity_counter >= 20) goToSleep = true;
- if(goToSleep == true) {
- Serial.println("goToSleep == true");
- Serial.println();
- if (bootCount >= 1 && bootCount <= 2) {
- // Configure external wakeup on GPIO14
- esp_sleep_enable_ext0_wakeup(WAKEUP_GPIO, 1); // 1 = High, 0 = Low
- rtc_gpio_pullup_dis(WAKEUP_GPIO);
- rtc_gpio_pulldown_en(WAKEUP_GPIO);
- Serial.println("Setup ESP32 to wake up on GPIO14 trigger");
- } else if (bootCount == 3) {
- // Sleep for 10 minutes instead of sending more than 3 consecutive notifications
- 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 3 times with a 200ms interval to indicate wake up
- Serial.println("Going to sleep now");
- Serial.flush();
- esp_deep_sleep_start();
- Serial.println("This will never be printed");
- Serial.println();
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement