Last active
June 13, 2024 05:46
-
-
Save Tech500/149a9c0c123a99e220232b195ae296c8 to your computer and use it in GitHub Desktop.
E220 remote switch operated by on demand web GET request.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//E220_Remote_Switch_Sender.ino | |
// 6/12/2024 @ 20:119 EST | |
// See library downloads for each library license. | |
// With FIXED SENDER configuration | |
#define DESTINATION_ADDL 3 | |
#include <Arduino.h> | |
#include "WiFi.h" | |
#include <WiFiUdp.h> | |
#include <HTTPClient.h> | |
#include <time.h> | |
#include "LoRa_E220.h" | |
#include <AsyncTCP.h> | |
#include "ESPAsyncWebServer.h" | |
#include <Ticker.h> | |
#import "index7.h" //Video feed HTML; do not remove | |
#define FREQENCY_915 | |
WiFiClient client; | |
///Are we currently connected? | |
boolean connected = false; | |
WiFiUDP udp; | |
// local port to listen for UDP packets | |
const int udpPort = 1337; | |
char incomingPacket[255]; | |
char replyPacket[] = "Hi there! Got the message :-)"; | |
//NTP Time Servers | |
const char * udpAddress1 = "pool.ntp.org"; | |
const char * udpAddress2 = "time.nist.gov"; | |
#define TZ "EST+5EDT,M3.2.0/2,M11.1.0/2" | |
int DOW, MONTH, DATE, YEAR, HOUR, MINUTE, SECOND; | |
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; | |
char strftime_buf[64]; | |
// ---------- esp32 pins -------------- | |
LoRa_E220 e220ttl(&Serial2, 15, 21, 19); // RX AUX M0 M1 | |
//LoRa_E220 e220ttl(&Serial2, 22, 4, 33, 21, 19, UART_BPS_RATE_9600); // esp32 RX <-- e220 TX, esp32 TX --> e220 RX AUX_PIN M0 M1 | |
// ------------------------------------- | |
#define AUX_PIN GPIO_NUM_15 | |
#define RXD1 16 | |
#define TXD1 17 | |
// Replace with your network details | |
const char *ssid = "R2D2"; | |
const char *password = "sissy4357"; | |
AsyncWebServer server(80); | |
int data = 2; | |
// Struct to hold date and time components | |
struct DateTime { | |
int year; | |
int month; | |
int day; | |
int hour; | |
int minute; | |
int second; | |
}; | |
// Define the maximum length for the timestamp | |
const int MAX_TIMESTAMP_LENGTH = 30; | |
int switchState; | |
struct Message { | |
int switchState; | |
char timestamp[MAX_TIMESTAMP_LENGTH]; | |
}message; | |
char dtStamp[MAX_TIMESTAMP_LENGTH]; | |
Ticker oneTick; | |
Ticker onceTick; | |
String linkAddress = "xxx.xxx.xxx.xxx:80"; | |
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; | |
volatile int watchdogCounter; | |
int totalwatchdogCounter; | |
int cameraPowerOff = 0; | |
int watchDog; | |
void ISRwatchdog() { | |
portENTER_CRITICAL_ISR(&mux); | |
watchdogCounter++; | |
if (watchdogCounter >= 75) { | |
watchDog = 1; | |
} | |
portEXIT_CRITICAL_ISR(&mux); | |
} | |
int cameraFlag; | |
int needAnotherCountdown = 0; | |
void ISRcamera() { | |
batteryOff(); | |
} | |
bool got_interrupt = false; | |
void interruptHandler() { | |
got_interrupt = true; | |
} | |
void setup() { | |
Serial.begin(9600); | |
delay(500); | |
Serial1.begin(9600, SERIAL_8N1, RXD1, TXD1); | |
Serial1.println("Hello, world?"); | |
wifi_Start(); | |
pinMode(AUX_PIN, INPUT); | |
attachInterrupt(GPIO_NUM_15, interruptHandler, FALLING); | |
// Startup all pins and UART | |
e220ttl.begin(); | |
e220ttl.setMode(MODE_1_WOR_TRANSMITTER); | |
delay(1000); | |
Serial.println("\nHi, I'm going to send WOR message!"); | |
// Send message | |
ResponseStatus rs = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 66, "\nHello, world? WOR!"); | |
// Check If there is some problem of succesfully send | |
Serial.println(rs.getResponseDescription()); | |
e220ttl.setMode(MODE_0_NORMAL); | |
delay(1000); | |
Serial.println("\n\n\nWebserver and"); | |
Serial.println("E220-900T30D Remote Switch\n"); | |
configTime(0, 0, "pool.ntp.org", "time.nist.gov"); | |
// See https://github.com/nayarsystems/posix_tz_db/blob/master/zones.csv for Timezone codes for your region | |
setenv("TZ", "EST+5EDT,M3.2.0/2,M11.1.0/2", 3); // this sets TZ to Indianapolis, Indiana | |
server.on("/relay", HTTP_GET, [](AsyncWebServerRequest *request) { | |
request->send_P(200, PSTR("text/html"), HTML7, processor7); | |
data = 1; | |
needAnotherCountdown = 1; | |
countdownTrigger(); | |
}); | |
server.begin(); | |
oneTick.attach(1.0, ISRwatchdog); //watchdog ISR triggers every 1 second | |
} | |
void loop() { | |
DateTime currentDateTime = getCurrentDateTime(); | |
if((currentDateTime.minute % 15 == 0) && (currentDateTime.second == 0)){ | |
//webInterface(); //Sends URL Get request to wake up Radio and ESP32 at 1 minute interval | |
// URL = http://10.0.0.27/relay | |
//delay(1000); | |
} | |
//udp only send data when connected | |
if (connected) | |
{ | |
//Send a packet | |
udp.beginPacket(udpAddress1, udpPort); | |
udp.printf("Seconds since boot: %u", millis() / 1000); | |
udp.endPacket(); | |
} | |
// If something available | |
if (e220ttl.available() > 1) { | |
// read the String message | |
ResponseContainer rc = e220ttl.receiveMessage(); | |
// Is something goes wrong print error | |
if (rc.status.code != 1) { | |
Serial.println(rc.status.getResponseDescription()); | |
} else { | |
// Print the data received | |
Serial.println(rc.status.getResponseDescription()); | |
Serial.println(rc.data); | |
} | |
} | |
if (Serial1.available()) { | |
Message message; | |
// Read switch state (assuming data is a single byte) | |
message.switchState = Serial1.read(); | |
// Get timestamp (assuming a string format) | |
String timestamp = get_time(); // Replace with your timestamp function | |
timestamp.toCharArray(message.timestamp, MAX_TIMESTAMP_LENGTH); | |
message.timestamp[0] = Serial1.read(); | |
// Send message | |
ResponseStatus rs = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 66, &message, sizeof(Message)); | |
// Check for successful send | |
Serial.println(rs.getResponseDescription()); | |
} | |
} | |
String processor7(const String &var) { | |
//index7.h | |
if (var == F("LINK")) | |
return linkAddress; | |
return String(); | |
} | |
void batteryOff() { | |
int data = 2; | |
switchOne(data); | |
oneTick.detach(); | |
} | |
void configTime() | |
{ | |
configTime(0, 0, udpAddress1, udpAddress2); | |
setenv("TZ", "EST+5EDT,M3.2.0/2,M11.1.0/2", 3); // this sets TZ to Indianapolis, Indiana | |
tzset(); | |
//udp only send data when connected | |
if (connected) | |
{ | |
//Send a packet | |
udp.beginPacket(udpAddress1, udpPort); | |
udp.printf("Seconds since boot: %u", millis() / 1000); | |
udp.endPacket(); | |
} | |
Serial.print("wait for first valid timestamp"); | |
while (time(nullptr) < 100000ul) | |
{ | |
Serial.print("."); | |
delay(5000); | |
} | |
Serial.println("\nSystem Time set\n"); | |
get_time(); | |
Serial.println(message.timestamp); | |
} | |
void countdownTrigger() { | |
// Perform countdown actions here | |
Serial.println("\nCountdown timer triggered!\n"); | |
//getDateTime(); | |
// Schedule the next countdown if needed | |
if (needAnotherCountdown == 1) { | |
onceTick.once(60, ISRcamera); | |
int data = 1; | |
switchOne(data); | |
needAnotherCountdown = 0; | |
} | |
} | |
// Function to get current date and time | |
DateTime getCurrentDateTime() { | |
DateTime currentDateTime; | |
time_t now = time(nullptr); | |
struct tm *ti = localtime(&now); | |
// Extract individual components | |
currentDateTime.year = ti->tm_year + 1900; | |
currentDateTime.month = ti->tm_mon + 1; | |
currentDateTime.day = ti->tm_mday; | |
currentDateTime.hour = ti->tm_hour; | |
currentDateTime.minute = ti->tm_min; | |
currentDateTime.second = ti->tm_sec; | |
return currentDateTime; | |
} | |
// Function to get the timestamp | |
String get_time() { | |
time_t now; | |
time(&now); | |
char time_output[MAX_TIMESTAMP_LENGTH]; | |
strftime(time_output, MAX_TIMESTAMP_LENGTH, "%a %m/%d/%y %T", localtime(&now)); | |
return String(time_output); // returns timestamp in the specified format | |
} | |
void switchOne(int data) { | |
if (data == 1) { | |
int data = 1; | |
Serial.println("\nBattery Switch is ON"); | |
Serial.println("ESP32 waking from Deep Sleep\n"); | |
} | |
if (data == 2) { | |
int data = 2; | |
Serial.println("\nBattery power switched OFF"); | |
Serial.println("ESP32 going to Deep Sleep\n"); | |
} | |
Serial.println("Hi, I'm going to send message!"); | |
get_time(); | |
Message message; | |
//initialize struct members | |
message.switchState = data; | |
// Initialize the timestamp | |
String timestamp = get_time(); | |
timestamp.toCharArray(message.timestamp, MAX_TIMESTAMP_LENGTH); | |
Serial.print("TimeStamp: "); Serial.println(message.timestamp); | |
// Send message | |
ResponseStatus rs = e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 66, &message, sizeof(Message)); | |
// Check If there is some problem of succesfully send | |
Serial.println(rs.getResponseDescription()); | |
} | |
void webInterface() { | |
//getTimeDate(); | |
String data = "http://10.0.0.27/relay"; | |
if (WiFi.status() == WL_CONNECTED) { | |
HTTPClient http; // Declare object of class HTTPClient | |
http.begin(data); // Specify request destination | |
// No need to add content-type header for a simple GET request | |
int httpCode = http.GET(); // Send the GET request | |
if (httpCode == HTTP_CODE_OK) { | |
String payload = http.getString(); // Get the response payload | |
Serial.print("HttpCode: "); | |
Serial.print(httpCode); // Print HTTP return code | |
Serial.println("\n"); | |
//Serial.print(" Data echoed back from Hosted website: "); | |
//Serial.println(payload); // Print payload response | |
http.end(); // Close HTTPClient | |
} else { | |
Serial.print("HttpCode: "); | |
Serial.print(httpCode); // Print HTTP return code | |
Serial.println(" URL Request failed."); | |
http.end(); // Close HTTPClient | |
} | |
} else { | |
Serial.println("Error in WiFi connection"); | |
} | |
} | |
void wifi_Start() { | |
//Server settings | |
#define ip { 10, 0, 0, 27} | |
#define subnet \ | |
{ 255, 255, 255, 0 } | |
#define gateway \ | |
{ 10, 0, 0, 1 } | |
#define dns \ | |
{ 10, 0, 0, 1 } | |
WiFi.mode(WIFI_AP_STA); | |
Serial.println(); | |
Serial.print("MAC: "); | |
Serial.println(WiFi.macAddress()); | |
// We start by connecting to WiFi Station | |
Serial.print("Connecting to "); | |
Serial.println(ssid); | |
WiFi.begin(ssid, password); | |
delay(1000); | |
//setting the static addresses in function "wifi_Start | |
IPAddress ip; | |
IPAddress gateway; | |
IPAddress subnet; | |
IPAddress dns; | |
WiFi.config(ip, gateway, subnet, dns); | |
Serial.println("Web server running. Waiting for the ESP32 IP..."); | |
// Printing the ESP IP address | |
Serial.print("Server IP: "); | |
Serial.println(WiFi.localIP()); | |
Serial.print("Port: "); | |
Serial.println("80"); | |
Serial.print("MAC: "); | |
Serial.println(WiFi.macAddress()); | |
Serial.print("Wi-Fi Channel: "); | |
Serial.println(WiFi.channel()); | |
Serial.println("\n"); | |
delay(500); | |
WiFi.waitForConnectResult(); | |
Serial.printf("Connection result: %d\n", WiFi.waitForConnectResult()); | |
server.begin(); | |
if (WiFi.waitForConnectResult() != 3) { | |
delay(3000); | |
wifi_Start(); | |
} | |
} | |
void printParameters(struct Configuration configuration) { | |
DEBUG_PRINTLN("----------------------------------------"); | |
DEBUG_PRINT(F("HEAD : ")); DEBUG_PRINT(configuration.COMMAND, HEX);DEBUG_PRINT(" ");DEBUG_PRINT(configuration.STARTING_ADDRESS, HEX);DEBUG_PRINT(" ");DEBUG_PRINTLN(configuration.LENGHT, HEX); | |
DEBUG_PRINTLN(F(" ")); | |
DEBUG_PRINT(F("AddH : ")); DEBUG_PRINTLN(configuration.ADDH, HEX); | |
DEBUG_PRINT(F("AddL : ")); DEBUG_PRINTLN(configuration.ADDL, HEX); | |
DEBUG_PRINTLN(F(" ")); | |
DEBUG_PRINT(F("Chan : ")); DEBUG_PRINT(configuration.CHAN, DEC); DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.getChannelDescription()); | |
DEBUG_PRINTLN(F(" ")); | |
DEBUG_PRINT(F("SpeedParityBit : ")); DEBUG_PRINT(configuration.SPED.uartParity, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.SPED.getUARTParityDescription()); | |
DEBUG_PRINT(F("SpeedUARTDatte : ")); DEBUG_PRINT(configuration.SPED.uartBaudRate, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.SPED.getUARTBaudRateDescription()); | |
DEBUG_PRINT(F("SpeedAirDataRate : ")); DEBUG_PRINT(configuration.SPED.airDataRate, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.SPED.getAirDataRateDescription()); | |
DEBUG_PRINTLN(F(" ")); | |
DEBUG_PRINT(F("OptionSubPacketSett: ")); DEBUG_PRINT(configuration.OPTION.subPacketSetting, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.OPTION.getSubPacketSetting()); | |
DEBUG_PRINT(F("OptionTranPower : ")); DEBUG_PRINT(configuration.OPTION.transmissionPower, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.OPTION.getTransmissionPowerDescription()); | |
DEBUG_PRINT(F("OptionRSSIAmbientNo: ")); DEBUG_PRINT(configuration.OPTION.RSSIAmbientNoise, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.OPTION.getRSSIAmbientNoiseEnable()); | |
DEBUG_PRINTLN(F(" ")); | |
DEBUG_PRINT(F("TransModeWORPeriod : ")); DEBUG_PRINT(configuration.TRANSMISSION_MODE.WORPeriod, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.TRANSMISSION_MODE.getWORPeriodByParamsDescription()); | |
DEBUG_PRINT(F("TransModeEnableLBT : ")); DEBUG_PRINT(configuration.TRANSMISSION_MODE.enableLBT, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.TRANSMISSION_MODE.getLBTEnableByteDescription()); | |
DEBUG_PRINT(F("TransModeEnableRSSI: ")); DEBUG_PRINT(configuration.TRANSMISSION_MODE.enableRSSI, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.TRANSMISSION_MODE.getRSSIEnableByteDescription()); | |
DEBUG_PRINT(F("TransModeFixedTrans: ")); DEBUG_PRINT(configuration.TRANSMISSION_MODE.fixedTransmission, BIN);DEBUG_PRINT(" -> "); DEBUG_PRINTLN(configuration.TRANSMISSION_MODE.getFixedTransmissionDescription()); | |
DEBUG_PRINTLN("----------------------------------------"); | |
} | |
void printModuleInformation(struct ModuleInformation moduleInformation) { | |
Serial.println("----------------------------------------"); | |
DEBUG_PRINT(F("HEAD: ")); DEBUG_PRINT(moduleInformation.COMMAND, HEX);DEBUG_PRINT(" ");DEBUG_PRINT(moduleInformation.STARTING_ADDRESS, HEX);DEBUG_PRINT(" ");DEBUG_PRINTLN(moduleInformation.LENGHT, DEC); | |
Serial.print(F("Model no.: ")); Serial.println(moduleInformation.model, HEX); | |
Serial.print(F("Version : ")); Serial.println(moduleInformation.version, HEX); | |
Serial.print(F("Features : ")); Serial.println(moduleInformation.features, HEX); | |
Serial.println("----------------------------------------"); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//E220_Remote_Switch_Receiver.ino | |
// 6/12/2024 @ 2011 EST | |
// See library downloads for each library license. | |
//Project uses Ebyte E220-900T30D, KY002S Bi-stable MOSFET Switch, and INA226 Battery Monitor module. | |
/* | |
* EBYTE LoRa E220 | |
* Stay in sleep mode and wait a wake up WOR message | |
* | |
* You must configure the address with 0 3 66 with WOR receiver enable | |
* and pay attention that WOR period must be the same of sender | |
* | |
* | |
* https://mischianti.org | |
* | |
* E220 ----- esp32 | |
* M0 ----- 19 (or 3.3v) | |
* M1 ----- 21 (or GND) | |
* RX ----- TX2 (PullUP) | |
* TX ----- RX2 (PullUP) | |
* AUX ----- 15 (PullUP) | |
* VCC ----- 3.3v/5v | |
* GND ----- GND | |
* | |
*/ | |
// with this DESTINATION_ADDL 2 you must set | |
// WOR SENDER configuration to the other device and | |
// WOR RECEIVER to this device | |
#define DESTINATION_ADDL 2 | |
// If you want use RSSI uncomment //#define ENABLE_RSSI true | |
// and use relative configuration with RSSI enabled | |
//#define ENABLE_RSSI true | |
#include "Arduino.h" | |
#include "LoRa_E220.h" | |
#include <WiFi.h> | |
#include <time.h> | |
#include <FS.h> | |
#include <LittleFS.h> | |
#include "esp_sleep.h" | |
#include "driver/gpio.h" | |
#include "esp_system.h" | |
#include <rom/rtc.h> | |
#include "soc/rtc_cntl_reg.h" | |
#include "soc/rtc.h" | |
#include "driver/rtc_io.h" | |
#include <INA226_WE.h> | |
#include <Wire.h> | |
// Persisted RTC variable | |
RTC_DATA_ATTR bool isPowerUp = false; | |
RTC_DATA_ATTR int bootCount = 0; | |
RTC_DATA_ATTR bool switch_State = false; // Initially switch is off | |
const int pulseDuration = 100; // 100 milliseconds (adjust as needed) | |
#define FREQUENCY_915 | |
#define AUX_PIN GPIO_NUM_15 | |
#define TRIGGER 23 //KY002S MOSFET Bi-Stable Switch | |
#define ALERT 4 //INA226 Battery Monitor | |
#define SDA 13 | |
#define SCL 22 | |
#define RXD1 16 | |
#define TXD1 17 | |
#define I2C_ADDRESS 0x40 | |
/* There are several ways to create your INA226 object: | |
* INA226_WE ina226 = INA226_WE(); -> uses I2C Address = 0x40 / Wire | |
* INA226_WE ina226 = INA226_WE(I2C_ADDRESS); | |
* INA226_WE ina226 = INA226_WE(&Wire); -> uses I2C_ADDRESS = 0x40, pass any Wire Object | |
* INA226_WE ina226 = INA226_WE(&Wire, I2C_ADDRESS); | |
*/ | |
INA226_WE ina226 = INA226_WE(I2C_ADDRESS); | |
volatile bool event = false; | |
void alert() { | |
event = true; | |
detachInterrupt(ALERT); | |
} | |
// Struct to hold date and time components | |
struct DateTime { | |
int year; | |
int month; | |
int day; | |
int hour; | |
int minute; | |
int second; | |
}; | |
// Define the maximum length for the timestamp | |
const int MAX_TIMESTAMP_LENGTH = 30; | |
struct Message { | |
int switchState; | |
char timestamp[MAX_TIMESTAMP_LENGTH]; | |
}; | |
Message message; | |
volatile int data = message.switchState; | |
char dtStamp[MAX_TIMESTAMP_LENGTH]; | |
#define FPM_SLEEP_MAX_TIME 0xFFFFFFF | |
void callback() { | |
Serial.println("Callback"); | |
Serial.flush(); | |
} | |
bool interruptExecuted = false; // Ensure interruptExecuted is volatile | |
void IRAM_ATTR wakeUp() { | |
// Do not use Serial on interrupt callback | |
interruptExecuted = true; | |
//detachInterrupt(AUX_PIN); | |
} | |
void printParameters(struct Configuration configuration); | |
// ---------- esp8266 pins -------------- | |
//LoRa_E32 e220ttl(RX, TX, AUX, M0, M1); // Arduino RX <-- e22 TX, Arduino TX --> e22 RX | |
//LoRa_E32 e220ttl(D3, D4, D5, D7, D6); // Arduino RX <-- e22 TX, Arduino TX --> e22 RX AUX M0 M1 | |
//LoRa_E32 e220ttl(D2, D3); // Config without connect AUX and M0 M1 | |
//#include <SoftwareSerial.h> | |
//SoftwareSerial mySerial(D2, D3); // Arduino RX <-- e22 TX, Arduino TX --> e22 RX | |
//LoRa_E32 e220ttl(&mySerial, D5, D7, D6); // AUX M0 M1 | |
// ------------------------------------- | |
// ---------- Arduino pins -------------- | |
//LoRa_E32 e220ttl(4, 5, 3, 7, 6); // Arduino RX <-- e22 TX, Arduino TX --> e22 RX AUX M0 M1 | |
//LoRa_E32 e220ttl(4, 5); // Config without connect AUX and M0 M1 | |
//#include <SoftwareSerial.h> | |
//SoftwareSerial mySerial(4, 5); // Arduino RX <-- e22 TX, Arduino TX --> e22 RX | |
//LoRa_E32 e220ttl(&mySerial, 3, 7, 6); // AUX M0 M1 | |
// ------------------------------------- | |
// ---------- esp32 pins ---------------- | |
LoRa_E220 e220ttl(&Serial2, 15, 21, 19); // RX AUX M0 M1 | |
//LoRa_E220 e220(&Serial2, 16, 17); // TX, RX pins// esp32 RX <-- e22 TX, esp32 TX --> e22 RX AUX M0 M1 | |
// ------------------------------------- | |
void handleWakeupReason() { | |
esp_sleep_wakeup_cause_t 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 enterDeepSleep() { | |
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_SLOW_MEM, ESP_PD_OPTION_ON); | |
gpio_hold_en(GPIO_NUM_19); | |
gpio_hold_en(GPIO_NUM_21); | |
gpio_deep_sleep_hold_en(); | |
Serial.println("Going to sleep now"); | |
esp_deep_sleep_start(); | |
Serial.println("This will never be printed"); | |
} | |
void setup() { | |
Serial.begin(9600); | |
delay(1000); | |
Serial.println("\n\nE220 Remote Switch Receiver\n"); | |
attachInterrupt(GPIO_NUM_15, wakeUp, FALLING); | |
// Call the refactored function to handle the wakeup reason | |
handleWakeupReason(); | |
pinMode(AUX_PIN, INPUT); | |
esp_sleep_enable_ext0_wakeup(GPIO_NUM_15, 0); | |
bool fsok = LittleFS.begin(true); | |
Serial.printf_P(PSTR("\nFS init: %s\n"), fsok ? PSTR("ok") : PSTR("fail!")); | |
Wire.begin(SDA, SCL); | |
pinMode(TRIGGER, OUTPUT); //ESP32, GPIO23 | |
pinMode(ALERT, OUTPUT); //ESP32, GPIO4 | |
if (!ina226.init()) { | |
Serial.println("\nFailed to init INA226. Check your wiring."); | |
//while(1){} | |
} | |
// INA226 configuration | |
ina226.enableAlertLatch(); | |
ina226.setAlertType(BUS_UNDER, 5.0); | |
attachInterrupt(digitalPinToInterrupt(ALERT), alert, FALLING); | |
e220ttl.begin(); | |
e220ttl.setMode(MODE_2_WOR_RECEIVER); | |
esp_sleep_wakeup_cause_t wakeup_reason; | |
wakeup_reason = esp_sleep_get_wakeup_cause(); | |
if (ESP_SLEEP_WAKEUP_EXT0 == wakeup_reason) { | |
Serial.println("Waked up from external GPIO!"); | |
gpio_hold_dis(GPIO_NUM_21); | |
gpio_hold_dis(GPIO_NUM_19); | |
gpio_deep_sleep_hold_dis(); | |
e220ttl.setMode(MODE_0_NORMAL); | |
delay(1000); | |
e220ttl.sendFixedMessage(0, DESTINATION_ADDL, 23, "We have waked up from message, but we can't read It!"); | |
} else { | |
e220ttl.setMode(MODE_2_POWER_SAVING); | |
delay(1000); | |
Serial.println(); | |
Serial.println("Start sleep!"); | |
delay(100); | |
if (ESP_OK == gpio_hold_en(GPIO_NUM_21)) { | |
Serial.println("HOLD 21"); | |
} else { | |
Serial.println("NO HOLD 21"); | |
} | |
if (ESP_OK == gpio_hold_en(GPIO_NUM_19)) { | |
Serial.println("HOLD 19"); | |
} else { | |
Serial.println("NO HOLD 19"); | |
} | |
gpio_deep_sleep_hold_en(); | |
//Go to sleep now | |
Serial.println("Going to sleep now"); | |
//esp_deep_sleep_start(); | |
delay(1); | |
} | |
// e220ttl.setMode(MODE_0_NORMAL); | |
// delay(1000); | |
Serial.println(); | |
Serial.println("Wake and start listening!"); | |
} | |
// The loop function is called in an endless loop | |
void loop() { | |
if (e220ttl.available() > 1) { | |
Serial.println("\nMessage arrived!"); | |
ResponseStructContainer rsc = e220ttl.receiveMessage(sizeof(Message)); | |
// Is something goes wrong print error | |
if (rsc.status.code != 1) { | |
Serial.println(rsc.status.getResponseDescription()); | |
} else { | |
// Print the data received | |
Serial.println(rsc.status.getResponseDescription()); | |
struct Message message = *(Message*)rsc.data; | |
Serial.println(message.switchState); //This prints to monitor | |
Serial.println(message.timestamp); //This prints to monitor | |
data = message.switchState; | |
rsc.close(); | |
Serial.print("data: "); | |
Serial.println(data); | |
; | |
} | |
e220ttl.setMode(MODE_0_NORMAL); | |
delay(1000); | |
ResponseStatus rsSend = e220ttl.sendFixedMessage(0, 3, 66, "We have received the message!"); | |
// Check If there is some problem of succesfully send | |
Serial.println(rsSend.getResponseDescription()); | |
delay(10); | |
Serial.println("Gets here 2"); | |
Serial.print("data before interrupt: "); | |
Serial.println(data); | |
} | |
if (interruptExecuted) { | |
interruptExecuted = false; | |
//detachInterrupt(AUX_PIN); | |
Serial.println("WakeUp Callback, AUX pin go LOW and start receive message!\n"); | |
Serial.print("After Interrupt: "); | |
Serial.println(data); | |
//------------------------- Task execution ------------------------------ | |
if (data != 1 || 2) { | |
enterDeepSleep(); | |
} | |
if (data == 1) { | |
digitalWrite(TRIGGER, HIGH); | |
delay(pulseDuration); | |
digitalWrite(TRIGGER, LOW); | |
switch_State = digitalRead(TRIGGER); // Read current switch state | |
Serial.println("\nBattery power switched ON"); | |
Serial.println("ESP32 wake from Deep Sleep\n"); | |
getINA226(dtStamp); | |
char dtStamp[MAX_TIMESTAMP_LENGTH]; | |
strncpy(dtStamp, message.timestamp, MAX_TIMESTAMP_LENGTH); // Copy timestamp | |
//logBattery(dtStamp); // Pass temporary copy | |
enterDeepSleep(); | |
} | |
if (data == 2) { | |
digitalWrite(TRIGGER, HIGH); | |
delay(pulseDuration); | |
digitalWrite(TRIGGER, LOW); | |
switch_State = digitalRead(TRIGGER); // Read current switch state | |
Serial.println("\nBattery power switched OFF"); | |
Serial.println("ESP32 going to Deep Sleep\n"); | |
delay(1000); | |
enterDeepSleep(); | |
} | |
if (event) { | |
digitalWrite(TRIGGER, HIGH); | |
delay(pulseDuration); | |
digitalWrite(TRIGGER, LOW); | |
ina226.readAndClearFlags(); // reads interrupt and overflow flags and deletes them | |
//getINA226(dtStamp); //displayResults(); | |
attachInterrupt(digitalPinToInterrupt(ALERT), alert, FALLING); | |
event = false; | |
digitalWrite(TRIGGER, LOW); | |
ina226.readAndClearFlags(); | |
enterDeepSleep(); | |
} | |
//----------------------End Task Execution ------------------------ | |
data = 0; | |
} | |
} | |
int main() { | |
// Create an instance of the Message struct | |
Message message; | |
// Get the timestamp using the get_time function and assign it to the struct member | |
String timestamp = get_time(); | |
timestamp.toCharArray(message.timestamp, MAX_TIMESTAMP_LENGTH); | |
// Now you can use message.timestamp as needed... | |
return 0; | |
} | |
// Function to get the timestamp | |
String get_time() { | |
time_t now; | |
time(&now); | |
char time_output[MAX_TIMESTAMP_LENGTH]; | |
strftime(time_output, MAX_TIMESTAMP_LENGTH, "%a %d-%m-%y %T", localtime(&now)); | |
return String(time_output); // returns timestamp in the specified format | |
} | |
void getINA226(const char* dtStamp) { | |
float shuntVoltage_mV = 0.0; | |
float loadVoltage_V = 0.0; | |
float busVoltage_V = 0.0; | |
float current_mA = 0.0; | |
float power_mW = 0.0; | |
ina226.startSingleMeasurement(); | |
ina226.readAndClearFlags(); | |
shuntVoltage_mV = ina226.getShuntVoltage_mV(); | |
busVoltage_V = ina226.getBusVoltage_V(); | |
current_mA = ina226.getCurrent_mA(); | |
power_mW = ina226.getBusPower(); | |
loadVoltage_V = busVoltage_V + (shuntVoltage_mV / 1000); | |
checkForI2cErrors(); | |
Serial.println(dtStamp); | |
Serial.print("Shunt Voltage [mV]: "); | |
Serial.println(shuntVoltage_mV); | |
Serial.print("Bus Voltage [V]: "); | |
Serial.println(busVoltage_V); | |
Serial.print("Load Voltage [V]: "); | |
Serial.println(loadVoltage_V); | |
Serial.print("Current[mA]: "); | |
Serial.println(current_mA); | |
Serial.print("Bus Power [mW]: "); | |
Serial.println(power_mW); | |
if (!ina226.overflow) { | |
Serial.println("Values OK - no overflow"); | |
} else { | |
Serial.println("Overflow! Choose higher current range"); | |
} | |
Serial.println(); | |
// Open a "log.txt" for appended writing | |
File log = LittleFS.open("/log.txt", "a"); | |
if (!log) { | |
Serial.println("file 'log.txt' open failed"); | |
} | |
log.print(dtStamp); | |
log.print(" , "); | |
log.print(shuntVoltage_mV, 3); | |
log.print(" , "); | |
log.print(busVoltage_V, 3); | |
log.print(" , "); | |
log.print(loadVoltage_V, 3); | |
log.print(" , "); | |
log.print(current_mA, 3); | |
log.print(" , "); | |
log.print(power_mW, 3); | |
log.println(""); | |
log.close(); | |
} | |
void checkForI2cErrors() { | |
byte errorCode = ina226.getI2cErrorCode(); | |
if (errorCode) { | |
Serial.print("I2C error: "); | |
Serial.println(errorCode); | |
switch (errorCode) { | |
case 1: | |
Serial.println("Data too long to fit in transmit buffer"); | |
break; | |
case 2: | |
Serial.println("Received NACK on transmit of address"); | |
break; | |
case 3: | |
Serial.println("Received NACK on transmit of data"); | |
break; | |
case 4: | |
Serial.println("Other error"); | |
break; | |
case 5: | |
Serial.println("Timeout"); | |
break; | |
default: | |
Serial.println("Can't identify the error"); | |
} | |
if (errorCode) { | |
while (1) {} | |
} | |
} | |
} | |
void printParameters(struct Configuration configuration) { | |
Serial.println("----------------------------------------"); | |
Serial.print(F("HEAD : ")); | |
Serial.print(configuration.COMMAND, HEX); | |
Serial.print(" "); | |
Serial.print(configuration.STARTING_ADDRESS, HEX); | |
Serial.print(" "); | |
Serial.println(configuration.LENGHT, HEX); | |
Serial.println(F(" ")); | |
Serial.print(F("AddH : ")); | |
Serial.println(configuration.ADDH, HEX); | |
Serial.print(F("AddL : ")); | |
Serial.println(configuration.ADDL, HEX); | |
Serial.println(F(" ")); | |
Serial.print(F("Chan : ")); | |
Serial.print(configuration.CHAN, DEC); | |
Serial.print(" -> "); | |
Serial.println(configuration.getChannelDescription()); | |
Serial.println(F(" ")); | |
Serial.print(F("SpeedParityBit : ")); | |
Serial.print(configuration.SPED.uartParity, BIN); | |
Serial.print(" -> "); | |
Serial.println(configuration.SPED.getUARTParityDescription()); | |
Serial.print(F("SpeedUARTDatte : ")); | |
Serial.print(configuration.SPED.uartBaudRate, BIN); | |
Serial.print(" -> "); | |
Serial.println(configuration.SPED.getUARTBaudRateDescription()); | |
Serial.print(F("SpeedAirDataRate : ")); | |
Serial.print(configuration.SPED.airDataRate, BIN); | |
Serial.print(" -> "); | |
Serial.println(configuration.SPED.getAirDataRateDescription()); | |
Serial.println(F(" ")); | |
Serial.print(F("OptionSubPacketSett: ")); | |
Serial.print(configuration.OPTION.subPacketSetting, BIN); | |
Serial.print(" -> "); | |
Serial.println(configuration.OPTION.getSubPacketSetting()); | |
Serial.print(F("OptionTranPower : ")); | |
Serial.print(configuration.OPTION.transmissionPower, BIN); | |
Serial.print(" -> "); | |
Serial.println(configuration.OPTION.getTransmissionPowerDescription()); | |
Serial.print(F("OptionRSSIAmbientNo: ")); | |
Serial.print(configuration.OPTION.RSSIAmbientNoise, BIN); | |
Serial.print(" -> "); | |
Serial.println(configuration.OPTION.getRSSIAmbientNoiseEnable()); | |
Serial.println(F(" ")); | |
Serial.print(F("TransModeWORPeriod : ")); | |
Serial.print(configuration.TRANSMISSION_MODE.WORPeriod, BIN); | |
Serial.print(" -> "); | |
Serial.println(configuration.TRANSMISSION_MODE.getWORPeriodByParamsDescription()); | |
Serial.print(F("TransModeEnableLBT : ")); | |
Serial.print(configuration.TRANSMISSION_MODE.enableLBT, BIN); | |
Serial.print(" -> "); | |
Serial.println(configuration.TRANSMISSION_MODE.getLBTEnableByteDescription()); | |
Serial.print(F("TransModeEnableRSSI: ")); | |
Serial.print(configuration.TRANSMISSION_MODE.enableRSSI, BIN); | |
Serial.print(" -> "); | |
Serial.println(configuration.TRANSMISSION_MODE.getRSSIEnableByteDescription()); | |
Serial.print(F("TransModeFixedTrans: ")); | |
Serial.print(configuration.TRANSMISSION_MODE.fixedTransmission, BIN); | |
Serial.print(" -> "); | |
Serial.println(configuration.TRANSMISSION_MODE.getFixedTransmissionDescription()); | |
Serial.println("----------------------------------------"); | |
} | |
void printModuleInformation(struct ModuleInformation moduleInformation) { | |
Serial.println("----------------------------------------"); | |
Serial.print(F("HEAD: ")); | |
Serial.print(moduleInformation.COMMAND, HEX); | |
Serial.print(" "); | |
Serial.print(moduleInformation.STARTING_ADDRESS, HEX); | |
Serial.print(" "); | |
Serial.println(moduleInformation.LENGHT, DEC); | |
Serial.print(F("Model no.: ")); | |
Serial.println(moduleInformation.model, HEX); | |
Serial.print(F("Version : ")); | |
Serial.println(moduleInformation.version, HEX); | |
Serial.print(F("Features : ")); | |
Serial.println(moduleInformation.features, HEX); | |
Serial.println("----------------------------------------"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment