Hello,
I am in the process of creating a module (custom PCB, Arduino nano 33 iot as the brains) to control a gasoline powered generator, that now has to be started by manually operating the controls on the control panel of the generator.
The PCB controls: Start motor, ignition, Added electromechanical fuel valve, added servo motor for choke, AC output of generator, ...
The algorithm to start the generator (FSM) is not perfect but works fine for the moment.
Even when freezing outside.
The problem i have is with integrating the arduino IOT cloud library and thus the logic for it.
I am not a seasoned C coder, and i don't fully understand the inner workings of the library.
The Generator can be started via the cloud or via 2 external hardware inputs.
It must start at all times even when there is no connection to the router or cloud.
But this is not always the case, sometimes the generator will be running and the arduino will just restart, this of course interferes with the correct operation of the generator.
The topics i would like to discussion are:
- the watchdog timer: where in the library could i see the time it takes for it to reset the Arduino nano 33 IOT
- the watchdog timer: if i disable it, once the connection is lost to the router (or cloud), it will not automatically try to reconnect in my experience, am i correct in assuming this?
-
General Library question once i call the class "ArduinoCloud.begin(ArduinoIoTPreferredConnection);" can i later change this statement to "ArduinoCloud.begin(ArduinoIoTPreferredConnection, False);" to disable the watchdog timer?
Or is this a one time deal? - if i write a value to the "Thing cloud variables", but i disable all the rest of the
"ArduinoIOTCloud" functions, will this couse a problem? this method compiles, but that does not make it correct.
I will probably add sone questions as i can think of them to solve my problem, but these are the biggest hurdles for now.
Here is the code, Please excuse some of the makeshift parts in this, i will clean all up when i advance with the issues.
/*
RM PR0034-PCB:V0.1B-FIRM:V1.0
This code is writen for an arduino nano 33 iot plugged into the RM INDUSTRIES PR0034 V0.1B Generator autmatisation PCB
Sketch generated by the Arduino IoT Cloud Thing "Untitled 2" https://create.arduino.cc/cloud/things/27f030b6-2699-4a75-aaf6-863a350e076b
Arduino IoT Cloud Variables description
none
The following variables are automatically generated and updated when changes are made to the Thing
String errorState;
String stateName;
int servo;
bool fuelValve;
bool run;
bool startMotor;
Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
which are called when their values are changed from the Dashboard.
These functions are generated with the Thing and added at the end of this sketch.
Servo pos(0) -> choke aan
Servo pos(100) -> choke uit
State Description:
Wait, Check for start input, check for generator state, when start input=1 and generator not running goto: Start1
Start1, While "start inpu=1" Preparation of generator controls (choke, iginition, fuel valve), when ready goto: start2
Start2, start sequence of generator, when running goto: Running
Running, Generator running, waiting for signal to shut off, goto: Shutoff
ShutOff,
Error,
Refferences:
Read and write struct from EEPROM: https://docs.arduino.cc/learn/built-in-libraries/eeprom
*/
//Defines
#define FLASH_DEBUG 0 //Part of FlashStorage_SAMD LIB. Use 0-2. Larger for more debugging messages
//included librairies
#include "thingProperties.h"
#include <Servo.h>
#include <FlashStorage_SAMD.h> // To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include <RTCZero.h>
//Declare IO (Digital pin name)
const int IO_Servo1 = 9; //choke servo position
const int IO_Servo1_en = 12; //choke servo enable
const int IO_CutOffA = 7; //Ignition relay A
const int IO_CutOffB = 6; //Ignition relay B
const int IO_FuelValve = 4; //Fual vale solenoid
const int IO_StartMotor = 5; //Start motor solenoid
const int IO_LED = 13; //Onboard LED pin
const int IO_Ac_Detect = 2; //Generator Ac detect relay
const int IO_Run1 = 10; //Run input from 230Vac contact (active HIGH)
const int IO_Run2 = 11; //Run input from loop contact (active Low)
//Variable Declaration
int Var_ChokePos = 0; //variable to store the servo position
int Var_StartRetry = 0; //Variable to store the star retry index number
const int Var_StartRetryMax = 3; //The maximum amount of times the start sequence is tried before aborting
int Var_AcState = 0; //variable that stored the Generator AC output state
int Var_StartGeneratorState = 0; //variable that stores the generator start state
int Var_Run3 = 0; //Run variable from arduino Cloud
int Var_ErrorMessage = 0; //0:no problem, 1:not able to start 2; lost ac power (unexpected shut off)
const int Var_ChokeEngaged = 5; //Position of servo in active, engaged position
const int Var_ChokeDisengaged = 85; //Position of servo in non active, disengaged
uint8_t FSMgeneral; //variable that stores the Finite state machine current state
const int WRITTEN_SIGNATURE = 0xBEEFDEED; //Part of FlashStorage_SAMD LIB. Signature is the first dataset in the Eeprom emulated flash memory, to check viability
int FlashStorage_SAMD_payload = 0; //for FlashStorage_SAMD LIB. amount of data stored in the flash memory
int FlashStorage_SAMD_Index = 0; //Part of FlashStorage_SAMD LIB. Stores the index of the adres pointer. this will get a value after reading out the flash.
byte ErrorCount; //for FlashStorage_SAMD LIB. the amount of errors in the flash
byte ErrorCountMax = 30; //for FlashStorage_SAMD LIB. The maximum amount of errors that we will save
byte ErrorCountLocation = 4; //for FlashStorage_SAMD LIB. the adres where the variable "ErrorCount" is stored
unsigned long time_now = 0; //Declare Values to use Millis() as delay
bool ArduinoIOTCloudDesired = LOW; //For Arduino IOT Cloud, this variable is set high if we want to use the Cloud, Low if we dont
//Struct declared for error handling
struct ErrorMessage
{
long ErrorMessageUnixtime; //the unix time stamp
byte ErrorMessageValue; //the error value we want to
};
//FSMgeneral state Declaration
enum FSMgeneral
{
Wait, //Wait for an input, when input goto: Start1
Start1, //Preparation of generator controls, when ready goto: start2
Start2, //start sequence of generator, when running goto: Running
Running, //Generator running, waiting for signal to shut off, goto: Shutoff
ShutOff, //Generator is shuting down
EarlyShutOff, //When the gennerator start signals stops before running
Error, //undefined problem
};
//Declare objects
Servo servo1; // create servo object to control a servo
void setup() {
//Declare pinmodes
pinMode(IO_Servo1, OUTPUT);
pinMode(IO_Servo1_en, OUTPUT);
pinMode(IO_CutOffA, OUTPUT);
pinMode(IO_CutOffB, OUTPUT);
pinMode(IO_FuelValve, OUTPUT);
pinMode(IO_StartMotor, OUTPUT);
pinMode(IO_LED, OUTPUT);
pinMode(IO_Ac_Detect, INPUT_PULLUP);
pinMode(IO_Run1, INPUT_PULLUP);
pinMode(IO_Run2, INPUT_PULLUP);
//Set relays to correct output
digitalWrite(IO_Servo1, 0);
digitalWrite(IO_Servo1_en, LOW);
digitalWrite(IO_CutOffA, LOW);
digitalWrite(IO_CutOffB, LOW);
digitalWrite(IO_FuelValve, LOW);
digitalWrite(IO_StartMotor, LOW);
digitalWrite(IO_LED, LOW);
// Initialize serial
Serial.begin(9600); // Initialize serial and wait for port to open:
delay(5000); // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
//Error Handling
FlashStorage_SAMD_Setup();
FlashStorage_SAMD_ReadErrors();
// ---- IOT cloud initialisation ----
if (ArduinoIOTCloudDesired = HIGH){
initProperties(); //include the defined in thingProperties.h
ArduinoCloud.begin(ArduinoIoTPreferredConnection); //Connect to Arduino IoT Cloud (,false: disable the watchdog timer)
ArduinoCloud.addCallback(ArduinoIoTCloudEvent::SYNC, onIoTSync); //Set the Initial values for the cloud variables
setDebugMessageLevel(4); //Debug level from 0:no to 4: everything
ArduinoCloud.printDebugInfo(); //no idea about exact information
}
//Attach phisical pin to object servo
servo1.attach(IO_Servo1); // attaches the servo on pin 9 to the servo object
//Declare startup state in FSMgeneral
FSMgeneral = Wait;
}
void onIoTSync() {
// set your initial values here
run = 0;
Var_Run3 = 0;
stateName = "FSMstate: Boot UP";
}
void loop() {
Serial.println("State: VOID LOOP ");
CustomCloudHandler(); //Update the cloud if we use IOT mode
switch (FSMgeneral)
{
case (Wait):
{
stateName = "FSM State: wait"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode
Var_StartRetry = 0; //reset the index
while (1)
{
CustomCloudHandler(); //Update the cloud if we use IOT mode
if (RunGenerator() && digitalRead(IO_Ac_Detect) == HIGH) //We want to start the generator and it is not running
{
FSMgeneral = Start1;
break; //break out of while loop
}
if (digitalRead(IO_Ac_Detect) == HIGH) //Detect that generator hase been started manualy
{
ErrorHandler(3);
while(digitalRead(IO_Ac_Detect) == HIGH)
{
if ((digitalRead(IO_Run1) == HIGH) || (digitalRead(IO_Run2) == LOW) || (Var_Run3 == HIGH))
{
ErrorHandler(5);
while((digitalRead(IO_Run1) == HIGH) || (digitalRead(IO_Run2) == LOW) || (Var_Run3 == HIGH)){
CustomCloudHandler(); //Update the cloud if we use IOT mode, stay in this loop until generator is off
}
}
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
}
}
}
break;
}
case (Start1):
{
stateName = "FSM State: start1"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
digitalWrite(IO_FuelValve, HIGH); //open the fual valve so fuel hase time to fill carb bowl
fuelValve = HIGH; //Update ITOcloud variable
Ignition(1); //Set Ignition to enable
for (Var_ChokePos = Var_ChokeDisengaged; Var_ChokePos >= Var_ChokeEngaged; Var_ChokePos -= 1) // go from choke position disengaged to engaged in steps of 1
{
servo1.write(Var_ChokePos); // tell servo to go to position in variable 'Var_ChokePos'
delay(15); // waits 15 ms for the servo to reach the position
servo = Var_ChokePos; //write the Var_ChokePos to the IOTcloud variable
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
}
if (RunGenerator() && (digitalRead(IO_Ac_Detect) == LOW)) //Still needed to start generator?
{
FSMgeneral = Start2;
break;
}
else
{
FSMgeneral = EarlyShutOff;
break;
}
break;
}
case (Start2):
{
Serial.write("Start2");
Serial.print('\n');
stateName = "Start2"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
Serial.print(digitalRead(IO_Ac_Detect));
time_now = millis(); //set current millis time to start couting (every 50ms servo reduce, if not started after 2 sec, wait)
while (RunGenerator()) //Continues testing if generator stil needs to be run
{
stateName = "Start2: in while"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
if (Var_StartRetry < Var_StartRetryMax) //tried to start the less than the maximum amount of times
{
if ((millis() - time_now > 5000)) //wait 2sec before starting the motor // && (digitalRead(IO_StartMotor == LOW)
{
stateName = "Start2: Started start motor"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
digitalWrite(IO_StartMotor, HIGH); //Enable start motor
startMotor = HIGH; //write value to IOTcloud variable
}
if (millis() - time_now > 10000) //wait 3.5 sec before desengaging choke
{
stateName = "Start2: Started Servo Desengagment"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
//Close the servo
if ((Var_ChokePos < Var_ChokeDisengaged) && (digitalRead(IO_Ac_Detect) == LOW)) //Servo disengaging and not yet started
{
stateName = "Start2: SubA"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
Var_ChokePos++;
servo1.write(Var_ChokePos);
servo = Var_ChokePos; //write value to IOTcloud variable
delay(50); //50ms delay time between each servo degree
}
else if ((Var_ChokePos < Var_ChokeDisengaged) && (digitalRead(IO_Ac_Detect) == HIGH)) //Servo disengaging and started
{
stateName = "Start2: SubB"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
Var_ChokePos++;
servo1.write(Var_ChokePos);
servo = Var_ChokePos; //write value to IOTcloud variable
delay(100); //100ms delay time between each servo degree
}
else if ((Var_ChokePos >= Var_ChokeDisengaged) && (digitalRead(IO_Ac_Detect) == LOW)) //servo desengaged and not yet started
{
//Some waiting time before stopping start motor
digitalWrite(IO_StartMotor, LOW); //DISABLE start motor
startMotor = LOW; //write value to IOTcloud variable
Var_StartRetry++;
stateName = "Start2: SubC"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
FSMgeneral = Start1;
break;
}
else if ((Var_ChokePos >= Var_ChokeDisengaged) && (digitalRead(IO_Ac_Detect) == HIGH)) //servo desengaged and started
{
stateName = "Start2: SubD"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
FSMgeneral = Running;
delay(700);
digitalWrite(IO_StartMotor, LOW); //DISABLE start motor
startMotor = LOW; //write value to IOTcloud variable
delay(2000); //delay before desengaging
break;
}
}
}
else //tried to start the the maximum amount of times
{
ErrorHandler(1);
FSMgeneral = Error;
break;
}
}
if (!RunGenerator())
{
stateName = "EarlyShutOff///"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
FSMgeneral = EarlyShutOff;
break;
}
break;
}
case (Running):
{
stateName = "Running"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
while ((digitalRead(IO_Ac_Detect) == HIGH) && (RunGenerator()))
{
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
//DID I STUTTER?
}
if ((digitalRead(IO_Ac_Detect) == LOW) && (RunGenerator()))
{
ErrorHandler(2); //errorcode 2: Lost AC power, unexpected cut off
Var_ErrorMessage = 2;
}
FSMgeneral = ShutOff;
break;
}
case (ShutOff):
{
time_now = millis(); //set current millis time to start couting
stateName = "ShutOff"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
digitalWrite(IO_FuelValve, LOW); //Disable fuel suply to carb and leave running to empty bowl
fuelValve = LOW; //write value to IOTcloud variable
digitalWrite(IO_StartMotor, LOW); //DISABLE start motor
startMotor = LOW; //write value to IOTcloud variable
//delay(10000);
while (millis() - time_now <= 10000)
{
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
}
Ignition(2); //Set Ignition to disable
//delay(5000);
while (millis() - time_now <= 15000)
{
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
}
Ignition(0); //Set Ignition to manual operation
servo1.write(100); //Make sure the servo is off
FSMgeneral = Wait;
break;
}
case (EarlyShutOff):
{
time_now = millis(); //set current millis time to start couting
stateName = "EarlyShutOff"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
digitalWrite(IO_FuelValve, LOW);
fuelValve = LOW; //write value to IOTcloud variable
digitalWrite(IO_StartMotor, LOW);
startMotor = LOW; //write value to IOTcloud variable
//Force iginition to off, no manual influence possible
digitalWrite(IO_CutOffA, HIGH); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
digitalWrite(IO_CutOffB, HIGH); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
//delay(3000); //make shure the generator stopped due to inertia of motor
while (millis() - time_now <= 3000)
{
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
}
//Make ignition choise available again for manual use
digitalWrite(IO_CutOffA, LOW); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
digitalWrite(IO_CutOffB, LOW); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
servo1.write(Var_ChokeDisengaged); //Make sure the servo is off
//delay(5000); //chill
while (millis() - time_now <= (3000 + 5000))
{
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
}
FSMgeneral = Wait; //Next state Wait
break;
}
case (Error):
{
stateName = "Error"; //update the cloud variable state to wait
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
digitalWrite(IO_FuelValve, LOW); //Disable fuel to carb
fuelValve = LOW; //write value to IOTcloud variable
delay(4000); //Wait for the fuel to exit carb via engine
//Force iginition to off, no manual influence possible
digitalWrite(IO_CutOffA, HIGH); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
digitalWrite(IO_CutOffB, HIGH); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
delay(3000); //make shure the generator stopped due to inertia of motor
//Make ignition choise available again for manual use
digitalWrite(IO_CutOffA, LOW); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
digitalWrite(IO_CutOffB, LOW); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
servo1.write(100); //Make sure the servo is off
delay(5000); //chill
onIoTSync(); //sych base values for cloud
FSMgeneral = Wait; //Next state Wait
break;
}
}
}
void onStateChange() {
// Add your code here to act upon State change
stateName = FSMgeneral;
}
void onRunChange() {
// Add your code here to act upon Run change
Serial.write("F.C. onRunChange");
Serial.print('\n');
Var_Run3 = run; //Set cloud variable to onboard variable
}
void onfuelValveChange() {
// Add your code here to act upon State change
}
bool RunGenerator() {
if (ArduinoIOTCloudDesired == LOW) {
if (((digitalRead(IO_Run1) == HIGH) || (digitalRead(IO_Run2) == LOW)) && (digitalRead(IO_Ac_Detect) == LOW)) {
return HIGH;
}
else if (!((digitalRead(IO_Run1) == HIGH) || (digitalRead(IO_Run2) == LOW))) {
return LOW;
}
}
else if (ArduinoIOTCloudDesired == HIGH) {
if (((digitalRead(IO_Run1) == HIGH) || (digitalRead(IO_Run2) == LOW) || (Var_Run3 == HIGH)) && (digitalRead(IO_Ac_Detect) == LOW)) {
return HIGH;
}
else if (!((digitalRead(IO_Run1) == HIGH) || (digitalRead(IO_Run2) == LOW) || (Var_Run3 == HIGH))) {
return LOW;
}
}
}
void ErrorHandler(int ErrorCode) {
if (ErrorCode == 0)
{
//no error
}
else if (ErrorCode == 1)
{
//not able to start
FlashStorage_SAMD_WriteError(ErrorCode);
Serial.write("Error Handler Code 1: ");
Serial.write("Not able to start engine");
Serial.print('\n');
errorState = "Error Handler Code 1: Not able to start engine";
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
}
else if (ErrorCode == 2)
{
//loss of AC power, unexpected engine cut-off
FlashStorage_SAMD_WriteError(ErrorCode);
Serial.write("Error Handler Code 2: ");
Serial.write("Loss of AC power, unexpected engine cut-off");
Serial.print('\n');
errorState = "Error Handler Code 2: loss of AC power, unexpected engine cut-off";
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
}
else if (ErrorCode == 3)
{
//Manual generator operation
FlashStorage_SAMD_WriteError(ErrorCode);
Serial.write("Error Handler Code 3: ");
Serial.write("Generator has manualy been opperated");
Serial.print('\n');
errorState = "Generator has manualy been opperated";
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
}
else if (ErrorCode == 4)
{
//unknown input for the ignition function
FlashStorage_SAMD_WriteError(ErrorCode);
Serial.write("Error Handler Code 4: ");
Serial.write("Unknown firmware ignition settings");
Serial.print('\n');
errorState = "Unknown firmware ignition settings";
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
}
else
{
//unknown error
Serial.write("Error Handler Code: ");
Serial.write("unknown");
Serial.print('\n');
errorState = "Unknown error";
CustomCloudHandler(); //Update the cloud if we use IOT mode, Stay in this loop until generator hase been shut off
}
//Reset the error state to nothing
errorState = "";
}
void Ignition(int IgnitionCode) {
if (IgnitionCode == 0){ //Set iginition to manual operation
digitalWrite(IO_CutOffA, LOW); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
digitalWrite(IO_CutOffB, LOW); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
}
else if (IgnitionCode == 1) { //Set iginition to enable
digitalWrite(IO_CutOffA, HIGH); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
digitalWrite(IO_CutOffB, LOW); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
}
else if (IgnitionCode == 2) { //Set iginition to Disable
digitalWrite(IO_CutOffA, HIGH); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
digitalWrite(IO_CutOffB, HIGH); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
}
else { //in case of a fault in the program set ignition to manual
ErrorHandler(4);
digitalWrite(IO_CutOffA, LOW); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
digitalWrite(IO_CutOffB, LOW); //Dual relay setup when A is not equal to B = run, A and B is high = no run, A and B is low = switch operation
}
}
void FlashStorage_SAMD_Setup() {
// Check signature at address 0
int signature;
EEPROM.get(0, signature);
Serial.println(""); //Make some room on serial display
Serial.println("- - - Start of Error Setup informarion - - - "); //Make some room on serial display
// If the EEPROM is empty then no WRITTEN_SIGNATURE
if (signature != WRITTEN_SIGNATURE)
{
Serial.println("EEPROM is empty, writing WRITTEN_SIGNATURE and Setting Error Count to 0");
EEPROM.put(0, WRITTEN_SIGNATURE); //Signature
EEPROM.put(ErrorCountLocation, 0x00); //Error count, until what adres is the flash used to store errors
Serial.print("");
}
//If the eeprom is not empty get the amount of stored errors, the value this gives is the first next free adres for the error
else
{
EEPROM.get(0, signature);
Serial.print("EEPROM has already been written it's Signature is: 0x");
Serial.println(signature, HEX);
EEPROM.get(ErrorCountLocation, ErrorCount);
Serial.print("The Error count is: ");
Serial.println((ErrorCount)); //This gives the amount of errors that are saved in the flash memory
}
Serial.println("- - - End of Error Setup informarion - - - "); //Make some room on serial display
Serial.println(""); //Make some room on serial display
}
void FlashStorage_SAMD_ReadErrors() {
//Print information about the Errors
Serial.println(""); //Make some room on serial display
Serial.println("- - - Start of Error informarion - - - "); //Make some room on serial display
Serial.println("Errors are displayed as two values: [Unix timestamp, Error code]");
Serial.println("Error Codes Decodation:");
Serial.println("Error Code 1 -> Not able to start engine");
Serial.println("Error Code 2 -> Loss of AC power, unexpected engine cut-off");
Serial.println("Error Code 3 -> Generator has manualy been opperated");
Serial.println("Error Code 4 -> Unknown firmware ignition settings");
Serial.println("Error Code 5 -> unknown");
Serial.println("");
Serial.println("Unix timestamp declaration: if value is 0, no time was saved");
Serial.println(" "); //Make some room on serial display
//Print out the saved errors
Serial.print("Error Count: ");
Serial.println(ErrorCount);
for (int i = (ErrorCountLocation + 1); i < (ErrorCountLocation + 1 + (ErrorCount*(sizeof(struct ErrorMessage)))); i = i + (sizeof(struct ErrorMessage))) {
ErrorMessage customVar; //Variable to store custom object read from EEPROM.
EEPROM.get(i, customVar );
Serial.print("Flash (EEPROM) Error Message: ");
Serial.print(customVar.ErrorMessageUnixtime );
Serial.print(", ");
Serial.println(customVar.ErrorMessageValue );
}
Serial.println("- - - End of Error informarion - - - "); //Make some room on serial display
Serial.println(""); //Make some room on serial display
}
void FlashStorage_SAMD_WriteError(byte Value) {
//Fill in the struct
long testvalue = ArduinoCloud.getLocalTime();
ErrorMessage customvar = {
testvalue,
Value
};
int NextOpenEepromAdres = ((ErrorCount*(sizeof(struct ErrorMessage))) + ErrorCountLocation + 1);
//The Time stamp is saved with the most significant byte last, this means, adres9 + adres8 + adres7 + adres6
ErrorCount++; //increment the error count with 1
EEPROM.put(ErrorCountLocation, ErrorCount); //Put the error count value in the flash memory
EEPROM.put(NextOpenEepromAdres, customvar); //put the error code in the next open eeprom adres
}
void CustomCloudHandler() {
if (ArduinoIOTCloudDesired == LOW) {
//Do Nothing
}
else if (ArduinoIOTCloudDesired == HIGH) {
ArduinoCloud.update(); //synch values with the cloud
}
}
Thanks in advance for any input,
Manu