Files
hot-water-control/MQTTClientPump/MQTTClientPump.ino
T
2022-09-24 09:45:20 -07:00

295 lines
7.5 KiB
Arduino

/*
ArduinoMqttClient - WiFi Simple Sender
This example code is in the public domain.
Feather M0
with Timer1 ISR driving events
*/
#define DEBUG false
#include <ArduinoMqttClient.h>
#include <Adafruit_SleepyDog.h>
#include <WiFi101.h>
#include "arduino_secrets.h"
/////// sensitive data in arduino_secrets.h
char ssid[] = SECRET_SSID;
char pass[] = SECRET_PASS;
char user[] = SECRET_USER;
char pw[] = SECRET_PW;
// wifi pins in use:
// WiFi.setPins(8,7,4,2); see setup()
#define LED_PIN 13
#define PUMP_PIN 12 // this is INT3
// PUMP_ON when LOW
#define FLOW_PIN 11 // this is INT0
// == water into the water heater = hot water demand when LOW
#define RATE 10 // Hz == 100mS
#define FLOWING digitalRead(FLOW_PIN)==LOW
#define NOTFLOWING digitalRead(FLOW_PIN)==HIGH
#define PUMPING digitalRead(PUMP_PIN)==LOW
#define NOTPUMPING digitalRead(PUMP_PIN)==HIGH
// Timer1_ISR functions:
void startTimer(int frequencyHz);
void setTimerFrequency(int frequencyHz);
void TC3_Handler();
bool isLEDOn = false;
bool notToggled = true;
// To connect with SSL/TLS:
// 1) Change WiFiClient to WiFiSSLClient.
// 2) Change port value from 1883 to 8883.
// 3) Change broker value to a server with a known SSL/TLS root certificate
// flashed in the WiFi module.
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
const char broker[] = SERVER;
int port = 1883;
const char topic[] = "arduino/simple";
const char subtopic[] = "arduino/state";
volatile boolean intflag1 = false; // external interrupt1
volatile boolean intflag3 = false; // external interrupt3
volatile unsigned long ticktime = 0; // timer interrupt
volatile unsigned int ticknum = 0; // wifi checked when this is > wifiTick
unsigned long flowstarted = 0;
unsigned long flowstopped = 0;
unsigned long pumpstarted = 0;
unsigned long pumpstopped = 0;
const unsigned long interval = 10000; // 10 seconds
const unsigned long timestamp = 300000; // 300,000 ms = 5 min
// 600,000 ms = 10 min resulted in Client KV6KV_F8F005F0BEB9 has exceeded timeout, disconnecting.
unsigned long previousMillis = 0;
unsigned long lasttimestamp = 0;
const unsigned int wifiTick = 100; //(interval/RATE);
// external pin interrupt handlers
void flowchange() {
if (!intflag1) {
intflag1 = true;
}
}
void pumpchange() {
if (!intflag3) {
intflag3 = true;
}
}
// called from TC3 ISR...
void Tick(void) {
ticknum++;
ticktime++;
} // end Tick
void toggleLED(){
digitalWrite(LED_PIN, isLEDOn);
isLEDOn = !isLEDOn;
}
void setup() {
int counddownMS = Watchdog.enable(60000); // 60 seconds
WiFi.setPins(8,7,4,2);
pinMode(LED_PIN, OUTPUT);
pinMode(FLOW_PIN, INPUT_PULLUP);
pinMode(PUMP_PIN, INPUT_PULLUP);
attachInterrupt(FLOW_PIN, flowchange, CHANGE);
attachInterrupt(PUMP_PIN, pumpchange, CHANGE);
startTimer(RATE);
if (DEBUG) {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
}
// attempt to connect to Wifi network:
if (DEBUG) Serial.print("Attempting to connect to WPA SSID: ");
if (DEBUG) Serial.println(ssid);
wifi_connect();
if (DEBUG) Serial.println("You're connected to the network");
if (DEBUG) Serial.println();
// You can provide a unique client ID, if not set the library uses Arduino-millis()
// Each client must have a unique client ID
mqttClient.setId(CLIENTID);
// You can provide a username and password for authentication
mqttClient.setUsernamePassword(SECRET_USER, SECRET_PW);
if (DEBUG) Serial.print("Attempting to connect to the MQTT broker: ");
if (DEBUG) Serial.println(broker);
mqtt_connect(); // first connect
if (DEBUG) Serial.println("You're connected to the MQTT broker!");
if (DEBUG) Serial.println();
mqttClient.subscribe(subtopic);
} // end of setup()
// loop is called repeatedly
void loop() {
unsigned long currentMillis = millis();
// 32bits = 4.295*10^6 seconds = 71.583*10^3 minutes = 1.193*10^3 hours = 49.71 days
/*
int messageSize = mqttClient.parseMessage();
// check incoming message
if (messageSize) {
if (DEBUG) Serial.print(mqttClient.messageTopic());
if (DEBUG) Serial.print(" : ");
while (mqttClient.available()) {
if (DEBUG) Serial.print((char)mqttClient.read());
}
if (DEBUG) Serial.println();
}
*/
// process flow interrupt
if (intflag1) {
mqtt_connect();
if (FLOWING) { // pin is LOW
flowstarted = WiFi.getTime();
mqttClient.beginMessage(topic);
mqttClient.print("start flow event@: ");
if (DEBUG) Serial.print(flowstarted);
if (DEBUG) Serial.println();
mqttClient.print(WiFi.getTime());
mqttClient.endMessage();
intflag1 = false;
} else { // pin is HIGH
flowstopped = WiFi.getTime();
mqttClient.beginMessage(topic);
mqttClient.print("stop flow event@: ");
if (DEBUG) Serial.print(flowstopped);
if (DEBUG) Serial.println();
mqttClient.print(WiFi.getTime());
mqttClient.endMessage();
intflag1 = false;
}
mqttClient.stop();
}
// process pump interrupt
if (intflag3) {
mqtt_connect();
if (PUMPING) { // pin is LOW
pumpstarted = WiFi.getTime();
mqttClient.beginMessage(topic);
mqttClient.print("start pump event@: ");
if (DEBUG) Serial.print(pumpstarted);
if (DEBUG) Serial.println();
mqttClient.print(WiFi.getTime());
mqttClient.endMessage();
intflag3 = false;
} else { // pin is HIGH
pumpstopped = WiFi.getTime();
mqttClient.beginMessage(topic);
mqttClient.print("stop pump event@: ");
if (DEBUG) Serial.print(pumpstopped);
if (DEBUG) Serial.println();
mqttClient.print(WiFi.getTime());
mqttClient.endMessage();
intflag3 = false;
}
mqttClient.stop();
}
// check wifi connection
if (ticknum >= wifiTick) { // every10 sec
ticknum = 0;
// attempt wifi reconnect if needed
// WiFi.status() =
// 3 ok WL_CONNECTED
// 6 disconnected wifi WL_DISCONNECTED
if (WiFi.status() == WL_DISCONNECTED) {
wifi_connect();
}
}
// blink LED @ 1Hz
if ((ticktime % 10) == 0) {
if (notToggled) { // ticks are every 100mS. only toggle ONCE
toggleLED();
notToggled = false;
}
} else {
notToggled = true;
}
// send tick timestamp to indicate operation with no water use
if (currentMillis - lasttimestamp >= timestamp) {
lasttimestamp = currentMillis;
mqtt_connect();
mqttClient.beginMessage(topic);
mqttClient.print("tick@: ");
mqttClient.print(WiFi.getTime());
mqttClient.endMessage();
mqttClient.stop();
if (DEBUG) Serial.println("tick");
}
Watchdog.reset();
} // loop()
void wifi_connect() {
while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
// failed! retry until connected
if (DEBUG) Serial.print("!");
for (int i=0; i<20; i++){ // 2 sec delay with 10hz blink
delay(100);
toggleLED();
}
}
}
void mqtt_connect() {
while (!mqttClient.connected()) {
// not connected! retry until connected
if (DEBUG) Serial.print("+");
if (mqttClient.connect(broker, port)) {
if (DEBUG) Serial.println("connected");
} else {
if (DEBUG) Serial.print("MQTT connection failed! Error code = ");
if (DEBUG) Serial.println(mqttClient.connectError());
for (int i=0; i<10; i++){ // 2 sec delay with 5hz blink
delay(200);
toggleLED();
}
}
}
}