-
That a very subjective subject.
-
Style is a personal thing unless your boss says do it this way.
-
Here is a style I’ve adopted.
//
//
// WEB link
//
//
// Version YY/MM/DD Comments
// ======= ======== ====================================================================
// 1.00 --/--/-- Running code
//
//
//
//********************************************^************************************************
//For diagnostics on an UNO, ProMini or Nano
//
//PINB5 = 13, PINB4 = 12, PINB3 = 11, PINB2 = 10, PINB1 = 9, PINB0 = 8
//
//Macro definition for generating a 63ns pulse on UNO pin 13 i.e. PINB5
//
//add this line to setup()
//pinMode(13,OUTPUT);
#define PULSE62_13 cli(); PINB = bit(PINB5); PINB = bit(PINB5); sei()
//********************************************^************************************************
// S e r i a l O R P a r a l l e l L C D ?
//********************************************^************************************************
//uncomment the next line if you have a serial LCD <-----<<<<<
#define serialLCDisBeingUsed
#ifdef serialLCDisBeingUsed
#include <Wire.h>
//Use I2C library: https://github.com/duinoWitchery/hd44780
//LCD Reference: https://www.arduino.cc/en/Reference/LiquidCrystal
#include <hd44780.h> //main hd44780 header
//NOTE:
//hd44780_I2Cexp control LCD using I2C I/O expander backpack (PCF8574 or MCP23008)
//hd44780_I2Clcd control LCD with native I2C interface (PCF2116, PCF2119x, etc...)
#include <hd44780ioClass/hd44780_I2Cexp.h> //I2C expander i/o class header
//If you do not know what your I2C address is, first run the 'I2C_Scanner' sketch
//OR
//run the "I2CexpDiag" sketch that comes with the hd44780 library
//hd44780_I2Cexp lcd(0x3F);
hd44780_I2Cexp lcd(0x27);
//********************************************^************************************************
#else
#include <LiquidCrystal.h>
// LCD pin 4 6 11 12 13 14
// RS EN D4 D5 D6 D7
LiquidCrystal lcd( 4, 5, 6, 7, 8, 9);
#endif
// M a c r o s
//********************************************^************************************************
#define RESET 0
#define VALID true
#define INVALID false
#define EXPIRED true
#define stillTIMING false
#define ENABLED true
#define DISABLED false
#define LEDon HIGH //+5V---[220R]---[LED]---PIN
#define LEDoff LOW
#define OPENED HIGH //+5V---[Internal 50k]---PIN---[switch]---GND
#define CLOSED LOW
//#define OPENED LOW //+5V---[switch]---PIN---[10k]---GND
//#define CLOSED HIGH
#define PRESSED HIGH //+5V---[Internal 50k]---PIN---[switch]---GND
#define RELEASED LOW
// S w i t c h s t u f f
//********************************************^************************************************
//a Structure that creates "switch" objects.
//if we read 3 same level changes in a row, we have a valid switch operation.
//if we sample the switches every 5ms, we can catch input changes ~15ms and longer in duration
struct defineSwitch
{
#define VALID true
#define INVALID false
const byte switchPin;
byte switchState;
byte debounceFlag;
unsigned long timeClosed;
//****************************************
//Function to check if there is a valid "switch" operation (OPENED or CLOSED)
bool checkSwitch()
{
byte currentState = digitalRead(switchPin);
//****************************************
//was there a change in state ?
if (switchState != currentState)
{
//**************************
//have we seen this change 3 times in a row ?
if (debounceFlag++ >= 3)
{
//get ready for the next 3 readings
debounceFlag = 0;
//update to the new state
switchState = currentState;
//has the switch closed ?
if (switchState == CLOSED)
{
//save the time the switch closed
timeClosed = millis();
}
//the switch has opened
else
{
//calculate how long was the switch closed
timeClosed = millis() - timeClosed;
}
return VALID;
}
}
//****************************************
//there was no change in state detected
else
{
debounceFlag = 0;
}
return INVALID;
}
}; //END of struct defineSwitch
//********************************************^************************************************
//create you switch objects
//****************************************
defineSwitch userSwitch =
{
//switchPin, switchState (at power up time)
2, OPENED
};
// T I M E R s t u f f
//********************************************^************************************************
//a Structure that creates TIMER objects
struct makeTimer
{
#define MILLIS 1
#define MICROS 1000 //we can use this value to divide into a variable to get milliseconds
#define ENABLED true
#define DISABLED false
#define YES true
#define NO false
//timerType = what kind of TIMER is this, MILLIS or MICROS
//enableFlag = tells us if this TIMER is ENABLED or DISABLED
//restart = do we start this TIMER again and again, YES or NO
//interval = delay time (ms/us) which we are looking for
//intervalDefault = if used, this is the powerup default value for "interval"
//intervalNew = if used, this is the value we want to change "interval" to
//
//****************************************
//You need a minimum number of member values to create TIMER object.
//Example:
//give this TIMER a name "myTimer"
// makeTimer myTimer =
// {
//assign values to the members that make up this TIMER
//timerType (MILLIS or MICROS), enableFlag, restart, interval, intervalDefault, intervalNew
// MICROS, ENABLED, YES, 200ul, 200UL, 200ul
// };
//
// You have access to:
// Variables: myTimer.timerType, myTimer.enableFlag, myTimer.restart, myTimer.interval,
// myTimer.intervalDefault, myTimer.intervalNew
//
// Functions: myTimer.checkTime(), myTimer.enableTimer(), myTimer.disableTimer(),
// myTimer.expireTimer(), myTimer.restartTimer()
//****************************************
//these are the bare minimum "members" needed when defining a TIMER
int timerType;
bool enableFlag;
bool restart;
unsigned long interval;
//when you do not define the following members,
//these will get initialized to 0 when a TIMER is instantiated
unsigned long intervalDefault;
unsigned long intervalNew;
unsigned long previousTime;
unsigned long currentTime;
//****************************************
//Function to check if this TIMER has expired ex: myTimer.checkTime();
bool checkTime()
{
currentTime = getTime();
//has this TIMER expired ?
if (currentTime - previousTime >= interval)
//Note: with delays of < 2 millis, use micros() and adjust "interval" as needed
{
//should this TIMER start again?
if (restart == ENABLED)
{
//get ready for the next iteration
previousTime = currentTime;
}
//this TIMER has expired
return true;
}
//this TIMER has not expired
return false;
} //END of checkTime()
//****************************************
//Function to enable and reset this TIMER, ex: myTimer.enableTimer();
void enableTimer()
{
enableFlag = ENABLED;
//initialize previousTime to current millis() or micros()
previousTime = getTime();
} //END of enableTimer()
//****************************************
//Function to disable this TIMER, ex: myTimer.disableTimer();
void disableTimer()
{
enableFlag = DISABLED;
} //END of disableTimer()
//****************************************
//Function to force this TIMER to expire ex: myTimer.expireTimer();
void expireTimer()
{
//force this TIMER to expire
previousTime = getTime() - interval;
} //END of expireTimer()
//****************************************
//Function to restart this TIMER ex: myTimer.restartTimer();
void restartTimer()
{
//reset this TIMER
previousTime = getTime();
} //END of restartTimer()
//****************************************
//Function to return the current time
unsigned long getTime()
{
//return the time i.e. millis() or micros()
if (timerType == MILLIS)
{
return millis();
}
else
{
return micros();
}
}; //END of getTime()
}; //END of structure “makeTimer”
//********************************************^************************************************
//example:
//
//create and initialize a "test" TIMER object
//****************************************
//makeTimer test =
//{
//timerType (MILLIS or MICROS), enableFlag, restart, interval, intervalDefault, intervalNew
// MILLIS, DISABLED, NO, 2000ul, 2000ul, 0ul
//this is a millis() based TIMER, it is disabled, it does not restart,
//its interval is 2 seconds, its default is 2 seconds, new value is 0ul
//};
//****************************************
makeTimer heartbeat =
{
//timerType (MILLIS or MICROS), enableFlag, restart, interval, intervalDefault, intervalNew
MILLIS, ENABLED, YES, 500ul
};
//****************************************
makeTimer switches =
{
//timerType (MILLIS or MICROS), enableFlag, restart, interval, intervalDefault, intervalNew
MILLIS, ENABLED, YES, 5ul
};
//****************************************
makeTimer stateMachine =
{
//timerType (MILLIS or MICROS), enableFlag, restart, interval, intervalDefault, intervalNew
MILLIS, ENABLED, YES, 50ul
};
//****************************************
makeTimer common =
{
//timerType (MILLIS or MICROS), enableFlag, restart, interval, intervalDefault, intervalNew
MILLIS, DISABLED, YES, 1000ul
};
// S t a t e M a c h i n e St u f f
//********************************************^************************************************
enum SM {Startup, State1, State2, State3};
SM machineState = Startup;
// G P I O P i n s
//********************************************^************************************************
//userSwitch 2
const byte testLED = 3;
//used for a parallel LCD 4, 5, 6, 7, 8, 9
const byte heartbeatLED = 13;
// s e t u p ( )
//********************************************^************************************************
void setup()
{
Serial.begin(115200);
pinMode(userSwitch.switchPin, INPUT_PULLUP);
pinMode(testLED, OUTPUT);
pinMode(heartbeatLED, OUTPUT);
//used for diagnostics <-------<<<<<
//pinMode(13, OUTPUT); //in this case pin 13 is the heartbeat LED
//****************************************
//LCD stuff
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0, 0);
// 111111
// 0123456789012345
// Skeleton
lcd.print(" Skeleton ");
lcd.setCursor(0, 1);
// 111111
// 0123456789012345
// Sketch
lcd.print(" Sketch ");
} //END of setup()
// l o o p ( )
//********************************************^************************************************
void loop()
{
//PULSE62_13;
//**************************************** h e a r t b e a t T I M E R
//is it time to toggle the heartbeatLED ?
if (heartbeat.checkTime() == EXPIRED)
{
//Toggle the heartbeatLED
digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
}
//**************************************** s w i t c h e s T I M E R
//is it time to check the switches ?
if (switches.checkTime() == EXPIRED)
{
checkSwitches();
}
//**************************************** s t a t e M a c h i n e T I M E R
//is it time to check the the State Machine ?
if (stateMachine.checkTime() == EXPIRED)
{
checkMachine();
}
//========================================
//Other non blocking code goes here
//========================================
} //END of loop()
// c h e c k S w i t c h e s ( )
//********************************************^************************************************
void checkSwitches()
{
//**************************************** u s e r S w i t c h
//is there a valid change in switch state ?
if (userSwitch.checkSwitch() == VALID)
{
//************ CLOSED
//did the switch closed ?
if (userSwitch.switchState == CLOSED)
{
//do something
//toggle the testLED
digitalWrite(testLED, !digitalRead(testLED));
}
//************ OPENED
//the switch opened
else
{
//do something
Serial.println(userSwitch.timeClosed);
}
} //END of if (userSwitch.checkSwitch() == VALID)
//**************************************** end of this switch
//========================================
//next switch code
//========================================
} //END of checkSwitches()
// c h e c k M a c h i n e ( )
//********************************************^************************************************
//service the State Machine
void checkMachine()
{
switch (machineState)
{
//****************************************
case Startup:
{
//do startup stuff
//set the common TIMER interval to 500ms
common.interval = 500ul;
common.enableTimer();
//next state
machineState = State1;
}
break; //END of case:
//****************************************
case State1:
{
//has the common TIMER expired ?
if (common.checkTime() == EXPIRED)
{
//do something
//as needed
//common.disableTimer();
}
}
break; //END of case:
//****************************************
case State2:
{
//do something
}
break; //END of case:
//****************************************
case State3:
{
//do something
}
break; //END of case:
} //END of switch/case
} //END of checkMachine()
//********************************************^************************************************
// E N D O f S k e t c h
//********************************************^************************************************