I've cut the sketch down to give an idea of how it's set up. It's on a mega. The sketch continues to run, as it's still turning things on and off that are hardwired to it and the LCD screen still changes, it's just the MQQT.
#include <Arduino.h>
#include <FreqMeasure.h>
#include <elapsedMillis.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>
// Update these with values suitable for your hardware/network.
byte mac[] = { 0xDE, 0xED, 0xAB, 0xEF, 0xFE, 0xDE };
IPAddress ip(192, 168, 3, 183);
IPAddress server(192, 168, 3, 196);
EthernetClient ethClient;
PubSubClient client(ethClient);
long lastReconnectAttempt = 0;
// Set the pins on the I2C chip used for LCD connections:
// addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x3F, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address
//LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
const byte noOfTriacs = 15; // <-- total number of ssr's inc pwm
const byte noOfPWMTriacs = 6; // <-- total number of pwm triacs
float frequencyHigh = 50.35; // frequency at which next SSR will turn on. Note PWM starts 0.15 Hz below this.
float frequencyLow = 50.02; // frequency at which next SSR will turn off
float interTriacDelayOn = 1.5; // additional seconds before next higher SSR can come on (0.1 sec already in sketch)
float interTriacDelayOff = 2; // additional seconds before next lower SSR can go off (0.1 sec already in sketch)
//float freqCal = 0.045; // calibration value Hz Desk spare
float freqCal = 0.005; // calibration value Hz Utility
const byte pinForTrigger[noOfTriacs] = {40, 26, 27, 28, 29, 40, 40, 40, 30, 31, 40, 32, 33, 34, 35}; // none PWM SSR's (pin 40 is just to allocate a pin and not used)
const byte pwmPin[noOfPWMTriacs] = {12, 8, 44, 11, 7, 40}; // PWM SSR's (last one not used)
const byte outputModePoolSelectorPin = 22; // digital
const byte outputModeGridSelectorPin = 23; // digital
int pwmglobalPin = 24; //global on/off for pwm SSR's
String temp_str;
bool temp_strb;
char temp[50];
// Timers for timed loads
const long delayOn[noOfTriacs] = {0, 0, 60, 90, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // delay (seconds) for turning on loads 0,1,2,3 etc remember inc. all ssr's
const long delayOff[noOfTriacs] = {0, 0, 1800, 1800, 30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // delay (seconds) for turning off loads 0,1,2,3 etc remember inc. all ssr's
enum outputGridModes {CONNECTED, DISCONNECTED};
//
boolean runTimeSelectionOfGridstatusIsEnabled = true;
enum outputGridModes outputGridMode = DISCONNECTED;
//
double sum = 0;
int count = 0;
enum outputPoolModes {OFF, ON};
//
boolean runTimeSelectionOfPoolstatusIsEnabled = true;
enum outputPoolModes outputPoolMode = ON;
//
boolean GridMQQT = false;
//
boolean DHW = true; // For selection by MQQT of Domestic hot water
boolean DHWBoost = false; // For selection by MQQT of Domestic hot water boost
boolean DHWPriority = false;
boolean airCon = true; // For selection by MQQT of Air Con
boolean poolOn1 = true; // For selection by MQQT of Pool
boolean poolOn2 = true; // For selection by MQQT of Pool
boolean poolOn3 = true; // For selection by MQQT of Pool
boolean delayPool1 = false; // for pool1 timer run out increase load
boolean delayPool2 = false; // for pool2 timer run out increase load
boolean utility = true; // For selection by MQQT of Utility heater
boolean study = true; // For selection by MQQT of study heater
boolean DHW2 = true; // For selection by MQQT of domestic hot water bottom
boolean landing = true; // For selection by MQQT of landing heater
boolean kitchen = true; // For selection by MQQT of kitchen heater
boolean living = true; // For selection by MQQT of living room
boolean office = true; // For selection by MQQT of office heater
boolean extra = true; // For selection by MQQT of extra heater
boolean workshop = true; // For selection by MQQT of workshop heater
boolean extra2 = true; // For selection by MQQT of extra2 heater
boolean resetArduino = false;
//
byte received_payload[128];
//
//
//
elapsedMillis timer0;
elapsedMillis timer1;
elapsedMillis timer2; // start delay reset
#define interval0 150 // the interval 0 in mS for Frequency measurement time period
#define interval1 1000 // the interval 1 in mS for SSR delays
#define interval2 30000 // start delay for reset 30 seconds
//
int delayAirConMqqt = 0; // for resending aircon MQQT every 10 minutes (600 seconds)
//
enum triacStates {TRIAC_OFF, TRIAC_ON}; // the external trigger device is active high.
enum pwmStates {PWM_OFF, PWM_ON}; // the external trigger device is active high.
//
int x = 0; // to ignore first results
int y = 0; // for PWM (used for next PWM ssr to come on)
int yold = -1;
int z = 0; // to reduce display fequency of PWM and frequency
int v = 0; // to reduce mqqt postings when grid on
int PWMValue = 0;
int PWMValueOld = 0;
int w = 0; // for reset
int r = 0; // check for increase load of 3 cycles
int s = 0; // for MQQT sending frequency
//
enum triacStates triacState[noOfTriacs];
enum pwmStates pwmState[noOfTriacs];
//
long cycleCountTimerOn[noOfTriacs]; // for timed on and off of loads
long cycleCountTimerOff[noOfTriacs];
long cycleCount = 0;
long cycleCountAtLastTransition = 0;
//
static byte countpool = 0;
static byte countgrid = 0;
float frequency;
boolean reconnect()
{
if (!client.connected())
{
Serial.print("MQQT connect failed, error code = ");
Serial.println (client.state());
Serial.println("Attempting MQTT connection...");
}
if (client.connect("ArduinoFrequencyWired"))
{
// Once connected, publish an announcement...
client.publish("frequency", "ArduinoFrequencyWired");
Serial.println("MQTT Connected");
// ... and resubscribe
client.subscribe("frequency/+");
}
return client.connected();
}
void(* resetFunc) (void) = 0; //declare reset function at address 0
void callback(char* topic, byte* payload, unsigned int length)
{
memcpy(received_payload, payload, length);
Serial.println();
Serial.print("Message arrived ["); // handle message arrived
Serial.print(topic);
Serial.println("] ");
String string;
for (int i = 0; i < length; i++)
{
string += ((char)payload[i]);
}
int detail = string.toInt(); // convert payload as an Integer
if ( strcmp(topic, "frequency/reset") == 0 )
{
Serial.print("Resetting ");
Serial.println(string);
if (string == "true")
{
resetArduino = true;
client.publish("frequencywired/reset", "Resetting", true);
client.publish("Pylontech/reset", "true", true);
delay(2000);
resetFunc(); //call reset
}
}
}
void setup()
{
lcd.begin(20, 4);
lcd.clear();
Serial.begin(115600);
FreqMeasure.begin();
client.setServer(server, 1883);
client.setCallback(callback);
Ethernet.begin(mac, ip);
//delay(1500);
lastReconnectAttempt = 0;
void loop()
{
if (!client.connected())
{
long now = millis();
if (now - lastReconnectAttempt > 5000)
{
lastReconnectAttempt = now;
// Attempt to reconnect
if (reconnect())
{
lastReconnectAttempt = 0;
}
}
}
else
{
// Client connected
client.loop();
}
}
// end of loop()
void checkMQQT()
{
if (DHWBoost == true && triacState[0] == TRIAC_OFF)
{
triacState[0] = TRIAC_ON;
analogWrite(pwmPin[0], 255);
cycleCountTimerOff[0] = 0;
cycleCountTimerOn[0] = 0;
Serial.print ("SSR on ");
Serial.println (0);
char buffer[30];
sprintf(buffer, "frequencywired/%d", 0);
client.publish(buffer, "ON", true);
}
}