MQ7-esp/esp8266-RM370-interrupt/esp8266-RM370-interrupt.ino

257 lines
7.0 KiB
Arduino
Raw Permalink Normal View History

2020-11-14 18:18:36 +00:00
//#define LOG(fmt, ...)
#define LOG(fmt, ...) (Serial.printf("%09llu: " fmt "\n", GetTimestamp(), ##__VA_ARGS__)); Serial.flush();
//#define DEBUGLOG(fmt, ...)
2020-11-19 09:13:55 +00:00
#define DEBUGLOG(fmt, ...) (Serial.printf("%09llu: [DEBUG] " fmt "\n", GetTimestamp(), ##__VA_ARGS__));
2020-11-14 18:18:36 +00:00
#define GLOBAL_VERBOSE 1//activate if the 'GREEN' status should be globally available
2020-11-19 09:13:55 +00:00
#define debounceDelay 1000 //LED shining duration
#define globalDelay 20000
2020-11-14 18:18:36 +00:00
#define alarmDelay 50
2021-01-22 17:13:55 +00:00
#define adcDelay 600000UL //10 minutes
2020-11-14 18:18:36 +00:00
#define warningDelay 333
2020-11-19 09:13:55 +00:00
const int MAX_PEERS = 20; //Limited due espNOW
2021-01-22 17:13:55 +00:00
//static const int WIFIESPNOW_KEYLEN = 16; //Limited due espNOW
const uint8_t key[16] = { 0 };
2020-11-14 18:18:36 +00:00
#if defined(ESP8266)
#include <ESP8266WiFi.h>
2021-01-22 17:13:55 +00:00
#include <Hash.h>
2020-11-14 18:18:36 +00:00
#elif defined(ESP32)
#include <WiFi.h>
#endif
2021-01-13 14:25:56 +00:00
#include <WifiEspNowBroadcast.h> //https://github.com/yoursunny/WifiEspNow
#include <Ticker.h> //Ticker Library
2020-11-14 18:18:36 +00:00
//version 1.1 - added originMAC
2020-11-19 09:13:55 +00:00
typedef struct {
2020-11-14 18:18:36 +00:00
char PREAMBLE1 = 'R';
char PREAMBLE2 = 'M';
uint8_t messageID[20];
char code = 'g'; // [g, y, r, X]
2020-11-14 18:18:36 +00:00
bool batteryWarning = false; //ToDo not implemented yet
uint8_t originMAC[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
2020-11-14 18:18:36 +00:00
} rm370;
2020-11-19 09:13:55 +00:00
rm370 receiveBuffer[MAX_PEERS];
2020-11-14 18:18:36 +00:00
rm370 transmitBuffer;
2020-11-19 09:13:55 +00:00
rm370 ownState;
2020-11-14 18:18:36 +00:00
//Remember VIL == 0.25×VIO ==> ~0,8275V
//Lowest voltage on LED 2,5V ==> 1,6V with level shifter
const uint8_t GREEN_Pin = D5; //CAUTION Vext is NOT 3.3V !!!
const uint8_t YELLOW_Pin = D6; //CAUTION Vext is NOT 3.3V !!!
const uint8_t RED_Pin = D7; //CAUTION Vext is NOT 3.3V !!!
const uint8_t BUZZER_Pin = D2; //CAUTION Vext is NOT 3.3V !!!
2021-01-22 17:13:55 +00:00
const uint8_t BAT_Pin = A0; //CAUTION Vext is NOT 1.1V !!!
Ticker alarmGenerator;
2020-11-14 18:18:36 +00:00
Ticker warningGenerator;
2020-11-19 09:13:55 +00:00
volatile bool alarmTrigger = false; //global
volatile bool warningTrigger = false; //global
volatile bool debounceTrigger = false;
2021-01-22 17:13:55 +00:00
//real physics workaround
2020-11-19 09:13:55 +00:00
volatile unsigned long globalStart = 0; //real physics workaround
volatile unsigned long debounceStart = 0; //real physics workaround
2021-01-23 15:54:54 +00:00
volatile unsigned long nowMillis = millis(); //real physics workaround
2021-01-22 17:13:55 +00:00
volatile unsigned long lastADCRead = 0;
volatile byte rxCounter = 0; //marker for the receive interrupt callback
volatile byte rxHandlePointer = 0; //marker for internal processing
2020-11-14 18:18:36 +00:00
int64_t GetTimestamp() {
struct timeval tv;
gettimeofday(&tv, NULL);
return (tv.tv_sec * 1000LL + (tv.tv_usec / 1000LL));
}
2020-11-14 18:18:36 +00:00
void buzzerTone() {
2020-11-19 09:13:55 +00:00
//just trigger if externel trigger received
if (ownState.code == 'g') {
digitalWrite(BUZZER_Pin, !(digitalRead(BUZZER_Pin)));
}
2020-11-14 18:18:36 +00:00
}
2021-01-22 17:13:55 +00:00
void batteryCheck() {
int sensorValue = analogRead(BAT_Pin);
DEBUGLOG("AnalogRead: %i", sensorValue);
lastADCRead = millis();
int voltage = map(sensorValue, 0, 1023, 0, 5000);
DEBUGLOG("VoltageMap: %i mV", voltage);
if (voltage < 3000) {
ownState.batteryWarning = true;
}
else {
ownState.batteryWarning = false;
}
2021-01-22 17:13:55 +00:00
}
2020-11-14 18:18:36 +00:00
void buzzerTest() {
LOG("Test alarm buzzer");
2020-11-19 09:13:55 +00:00
debounceTrigger = true;
2020-11-14 18:18:36 +00:00
alarmTrigger = true;
for (int i = 0; i < (3000 / alarmDelay); i++) {
buzzerTone();
delay(alarmDelay);
}
alarmTrigger = false;
2020-11-19 09:13:55 +00:00
2020-11-14 18:18:36 +00:00
LOG("Test warning buzzer");
warningTrigger = true;
for (int i = 0; i < (3000 / warningDelay); i++) {
buzzerTone();
delay(warningDelay);
}
warningTrigger = false;
2020-11-19 09:13:55 +00:00
//Failsafe
2021-01-25 12:38:49 +00:00
digitalWrite(BUZZER_Pin, HIGH);
2020-11-19 09:13:55 +00:00
debounceTrigger = false;
}
void globalStatus() {
if (globalStart != 0) {
//reset global
2021-01-23 15:54:54 +00:00
if ( (nowMillis - globalStart) > globalDelay ) {
if (alarmGenerator.active()) {
2020-11-19 09:13:55 +00:00
alarmGenerator.detach();
alarmTrigger = false;
}
2021-01-23 15:54:54 +00:00
if (warningGenerator.active()) {
2020-11-19 09:13:55 +00:00
warningGenerator.detach();
warningTrigger = false;
}
globalStart = 0;
//Failsafe
2021-01-25 12:38:49 +00:00
digitalWrite(BUZZER_Pin, HIGH);
2020-11-19 09:13:55 +00:00
LOG("Global ended");
}
if (alarmTrigger && !alarmGenerator.active()) {
LOG("Global started");
alarmGenerator.attach(float(alarmDelay / 1000.0), buzzerTone);
}
//attach ticker
if (warningTrigger && !warningGenerator.active()) {
LOG("Global started");
warningGenerator.attach(float(warningDelay / 1000.0), buzzerTone);
}
}
}
void setup() {
pinMode(RED_Pin, INPUT_PULLUP);
2021-01-24 15:17:17 +00:00
pinMode(YELLOW_Pin, INPUT_PULLUP);
pinMode(GREEN_Pin, INPUT_PULLUP);
pinMode(BUZZER_Pin, OUTPUT);
2021-01-25 12:38:49 +00:00
digitalWrite(BUZZER_Pin, HIGH);
2020-11-14 18:18:36 +00:00
attachInterrupt(digitalPinToInterrupt(RED_Pin), IntREDCallback, FALLING);
attachInterrupt(digitalPinToInterrupt(YELLOW_Pin), IntYELLOWCallback, FALLING);
attachInterrupt(digitalPinToInterrupt(GREEN_Pin), IntGREENCallback, FALLING);
2020-11-19 09:13:55 +00:00
Serial.begin(115200);
2020-11-14 18:18:36 +00:00
Serial.flush();
delay(1000);
LOG("\n\nInterrupt D7,D6,D5 with Serial.print");
#if defined(GLOBAL_VERBOSE)
LOG("\nGlobal verbose ACTIVE");
#endif
2020-11-14 18:18:36 +00:00
if (!initCommunication()) {
ESP.restart();
}
2021-01-22 17:13:55 +00:00
batteryCheck();
2020-11-14 18:18:36 +00:00
buzzerTest();
LOG("Setup completed.\n");
}
void loop() {
2020-11-19 09:13:55 +00:00
//loop things
2021-01-23 15:54:54 +00:00
nowMillis = millis();
2020-11-19 09:13:55 +00:00
WifiEspNowBroadcast.loop();
globalStatus();
2021-01-23 15:54:54 +00:00
if ((nowMillis - lastADCRead) > adcDelay) {
2021-01-22 17:13:55 +00:00
batteryCheck();
}
2020-11-19 09:13:55 +00:00
//reset debounce, as the LEDs shine a period of time
2021-01-23 15:54:54 +00:00
if (debounceTrigger && ((nowMillis - debounceStart) > debounceDelay)) {
2020-11-19 09:13:55 +00:00
debounceTrigger = false;
if (ownState.code == 'r') {
DEBUGLOG("RED LED");
}
if (ownState.code == 'y') {
DEBUGLOG("YELLOW LED");
}
//Todo check for code 'g'
2020-11-19 09:13:55 +00:00
if (!(ownState.code == 'r' || ownState.code == 'y')) {
DEBUGLOG("GREEN LED");
}
//send own status
#if defined(GLOBAL_VERBOSE)
if (ownState.code == 'r' || ownState.code == 'y' || ownState.code == 'g') {
#else
2020-11-19 09:13:55 +00:00
if (ownState.code == 'r' || ownState.code == 'y') {
#endif
2020-11-19 09:13:55 +00:00
//generate unique identifier
char messageIDString[65];
itoa(millis(), messageIDString, 10);
sha1(messageIDString, ownState.messageID);
transmitBuffer = ownState;
sendMessage();
}
}
2020-11-14 18:18:36 +00:00
2020-11-19 09:13:55 +00:00
//process remaining rxBuffer
while (rxHandlePointer != rxCounter)
{
checkMessage();
//shift ring buffer working pointer
2021-01-23 15:54:54 +00:00
if (rxHandlePointer + 1 < MAX_PEERS) {
2020-11-19 09:13:55 +00:00
rxHandlePointer++;
}
else {
rxHandlePointer = 0;
}
//forward received messages
#if defined(GLOBAL_VERBOSE)
if (transmitBuffer.code == 'r' || transmitBuffer.code == 'y' || transmitBuffer.code == 'g') {
#else
2020-11-19 09:13:55 +00:00
if (transmitBuffer.code == 'r' || transmitBuffer.code == 'y') {
#endif
2020-11-19 09:13:55 +00:00
sendMessage();
}
2020-11-14 18:18:36 +00:00
}
}
ICACHE_RAM_ATTR void IntREDCallback() {
2020-11-19 09:13:55 +00:00
if (!debounceTrigger) {
alarmTrigger = true;
warningTrigger = false;
ownState.code = 'r';
//real physics workaround
debounceTrigger = true;
debounceStart = millis();
}
}
ICACHE_RAM_ATTR void IntYELLOWCallback() {
2020-11-19 09:13:55 +00:00
if (!debounceTrigger) {
if (!alarmTrigger) {
warningTrigger = true;
}
ownState.code = 'y';
//real physics workaround
debounceTrigger = true;
debounceStart = millis();
}
}
ICACHE_RAM_ATTR void IntGREENCallback() {
2020-11-19 09:13:55 +00:00
if (!debounceTrigger) {
ownState.code = 'g';
//real physics workaround
debounceTrigger = true;
debounceStart = millis();
}
}