Hi everybody,
today I wrote my first own class.
If the class-declaration is above the instantiation the code compiles
class MonoFlop {
byte triggerInputPin;
byte PinToSwitch;
unsigned long InitialWaitTime = 1000; // set to zero if you don't want an initial wait
unsigned long ActiveTime = 5000;
unsigned long LockedTime = 3000; // set to zero if you don't want a lock-time
byte triggerIsActive = LOW; // LOW o HIGH
byte OutPutOn = HIGH;
// the attention-mark ! is the not-operator which inverts the value
// !true = false !false = true !HIGH = LOW !LOW = HIGH
byte OutPutOff = !OutPutOn;
// set InitialWaitTime to 0 if you don't want a delay between triggering and switching output
unsigned long MonoFlopTimer; // variable used for non-blocking timing
// constants of the state-machine
#define sm_Idling 0
#define sm_InitialWait 1
#define sm_Activated 2
#define sm_Locked 3
#define sm_stopped 4
byte MonoFlopState = sm_Idling; // state-variable of the state-machine
// constructor
public:
MonoFlop(byte cp_triggerPin, byte cp_outputPin) {
triggerInputPin = cp_triggerPin;
PinToSwitch = cp_outputPin;
MonoFlopState = sm_stopped;
pinMode(triggerInputPin, INPUT_PULLUP);
pinMode(PinToSwitch, OUTPUT);
digitalWrite(PinToSwitch, OutPutOff);
}
void deactivate() {
digitalWrite(PinToSwitch, OutPutOff);
MonoFlopState = sm_stopped;;
}
void activate() {
MonoFlopState = sm_Idling;
}
void run() {
MonoFlopStateMachine();
}
void setOutputDelay(unsigned long p_outputDelay) {
InitialWaitTime = p_outputDelay;
}
void setHighTime(unsigned long p_HighTime) {
ActiveTime = p_HighTime;
}
void setLockTime(unsigned long p_LockTime) {
LockedTime = p_LockTime;
}
void setTriggerLevel(byte p_TriggerLevel) {
triggerIsActive = p_TriggerLevel;
}
void setOutputOnLevel(byte p_OnLevel) {
OutPutOn = p_OnLevel;
OutPutOff = !OutPutOn;
}
boolean TPiO(unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void MonoFlopStateMachine() {
switch (MonoFlopState) {
case sm_stopped:
// do absolutely nothing
break;
case sm_Idling:
// check if trigger-input reads triggering signal
if (digitalRead(triggerInputPin) == triggerIsActive) {
MonoFlopTimer = millis(); // make snapshot of time
MonoFlopState = sm_InitialWait; // set next state of state-machine
Serial.println( F("trigger-signal detected start inital wait") );
}
break; // IMMIDIATELY jump down to END OF SWITCH
case sm_InitialWait:
// wait until initial waittime has passed by
if ( TPiO(MonoFlopTimer, InitialWaitTime) ) {
// if waittime HAS passed by
MonoFlopTimer = millis(); // make new snapshot of time
digitalWrite(PinToSwitch, OutPutOn); // switch IO-Pin to activated state
MonoFlopState = sm_Activated; // set next state of state-machine
Serial.println( F("InitialWaitTime is over switching output to ACTIVE") );
}
break; // IMMIDIATELY jump down to END OF SWITCH
case sm_Activated:
// check if time the IO-pin shall be active is over
if ( TPiO(MonoFlopTimer, ActiveTime) ) {
// if activetime of IO-pin IS over
MonoFlopTimer = millis(); // make new snapshot of time
digitalWrite(PinToSwitch, OutPutOff); // switch IO-pin to DE-activated state
MonoFlopState = sm_Locked; // set next state of state-machine
Serial.println( F("Activetime is over switching output to IN-active") );
Serial.println( F("and starting locktime") );
}
break; // IMMIDIATELY jump down to END OF SWITCH
case sm_Locked:
// check if time the logic shall be locked against too early re-triggering is over
if ( TPiO(MonoFlopTimer, LockedTime) ) {
// if locked time IS over
Serial.println( F("locktime is over change state to idling") );
MonoFlopState = sm_Idling; // set state-machine to idle-mode
}
break; // IMMIDIATELY jump down to END OF SWITCH
} // END OF SWITCH
}
}; // end of class MonoFlop
const byte myTriggerPin = 2;
const byte myOutputPin = 3;
MonoFlop myMonoflop1(myTriggerPin, myOutputPin);
void PrintFileNameDateTime() {
Serial.println( F("Code running comes from file ") );
Serial.println( F(__FILE__) );
Serial.print( F(" compiled ") );
Serial.print( F(__DATE__) );
Serial.print( F(" ") );
Serial.println( F(__TIME__) );
}
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
unsigned long MyTestTimer = 0; // Timer-variables MUST be of type unsigned long
const byte OnBoard_LED = 13;
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
}
}
void setup() {
Serial.begin(115200);
Serial.println("Setup-Start");
PrintFileNameDateTime();
}
void loop() {
BlinkHeartBeatLED(OnBoard_LED, 250);
myMonoflop1.run();
}
For readabilty reasons I want to put the class-declartion at the bottom of the code
If I simply move the class-declaration to the bottom of the *.ino-file I get an
MonoFlop-006-Demo:54:3: error: 'myMonoflop1' was not declared in this scope
error.
Sure if the compiler knows nothing about the class the compiler complains.
So I tried to use a forward-declaration like with functions
class MonoFlop(byte cp_triggerPin, byte cp_outputPin);
const byte myTriggerPin = 2;
const byte myOutputPin = 3;
MonoFlop myMonoflop1(myTriggerPin, myOutputPin);
but then I get an compiler-error
MonoFlop-006-Demo:2:21: error: expected ')' before 'cp_triggerPin'
class MonoFlop(byte cp_triggerPin, byte cp_outputPin);
I have googled some time if I could find something about forward-declaration of a class but did'nt find anything useful.
So my question is: is it possible to have a forward-declartion of a class?
And if yes how does it look like?
complete code that does not compile
class MonoFlop(byte cp_triggerPin, byte cp_outputPin);
const byte myTriggerPin = 2;
const byte myOutputPin = 3;
MonoFlop myMonoflop1(myTriggerPin, myOutputPin);
void PrintFileNameDateTime() {
Serial.println( F("Code running comes from file ") );
Serial.println( F(__FILE__) );
Serial.print( F(" compiled ") );
Serial.print( F(__DATE__) );
Serial.print( F(" ") );
Serial.println( F(__TIME__) );
}
// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
unsigned long MyTestTimer = 0; // Timer-variables MUST be of type unsigned long
const byte OnBoard_LED = 13;
void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
static unsigned long MyBlinkTimer;
pinMode(IO_Pin, OUTPUT);
if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
}
}
void setup() {
Serial.begin(115200);
Serial.println("Setup-Start");
PrintFileNameDateTime();
}
void loop() {
BlinkHeartBeatLED(OnBoard_LED, 250);
myMonoflop1.run();
}
class MonoFlop {
byte triggerInputPin;
byte PinToSwitch;
unsigned long InitialWaitTime = 1000; // set to zero if you don't want an initial wait
unsigned long ActiveTime = 5000;
unsigned long LockedTime = 3000; // set to zero if you don't want a lock-time
byte triggerIsActive = LOW; // LOW o HIGH
byte OutPutOn = HIGH;
// the attention-mark ! is the not-operator which inverts the value
// !true = false !false = true !HIGH = LOW !LOW = HIGH
byte OutPutOff = !OutPutOn;
// set InitialWaitTime to 0 if you don't want a delay between triggering and switching output
unsigned long MonoFlopTimer; // variable used for non-blocking timing
// constants of the state-machine
#define sm_Idling 0
#define sm_InitialWait 1
#define sm_Activated 2
#define sm_Locked 3
#define sm_stopped 4
byte MonoFlopState = sm_Idling; // state-variable of the state-machine
// constructor
public:
MonoFlop(byte cp_triggerPin, byte cp_outputPin) {
triggerInputPin = cp_triggerPin;
PinToSwitch = cp_outputPin;
MonoFlopState = sm_stopped;
pinMode(triggerInputPin, INPUT_PULLUP);
pinMode(PinToSwitch, OUTPUT);
digitalWrite(PinToSwitch, OutPutOff);
}
void deactivate() {
digitalWrite(PinToSwitch, OutPutOff);
MonoFlopState = sm_stopped;;
}
void activate() {
MonoFlopState = sm_Idling;
}
void run() {
MonoFlopStateMachine();
}
void setOutputDelay(unsigned long p_outputDelay) {
InitialWaitTime = p_outputDelay;
}
void setHighTime(unsigned long p_HighTime) {
ActiveTime = p_HighTime;
}
void setLockTime(unsigned long p_LockTime) {
LockedTime = p_LockTime;
}
void setTriggerLevel(byte p_TriggerLevel) {
triggerIsActive = p_TriggerLevel;
}
void setOutputOnLevel(byte p_OnLevel) {
OutPutOn = p_OnLevel;
OutPutOff = !OutPutOn;
}
boolean TPiO(unsigned long &startOfPeriod, unsigned long TimePeriod) {
unsigned long currentMillis = millis();
if ( currentMillis - startOfPeriod >= TimePeriod ) {
// more time than TimePeriod has elapsed since last time if-condition was true
startOfPeriod = currentMillis; // a new period starts right here so set new starttime
return true;
}
else return false; // actual TimePeriod is NOT yet over
}
void MonoFlopStateMachine() {
switch (MonoFlopState) {
case sm_stopped:
// do absolutely nothing
break;
case sm_Idling:
// check if trigger-input reads triggering signal
if (digitalRead(triggerInputPin) == triggerIsActive) {
MonoFlopTimer = millis(); // make snapshot of time
MonoFlopState = sm_InitialWait; // set next state of state-machine
Serial.println( F("trigger-signal detected start inital wait") );
}
break; // IMMIDIATELY jump down to END OF SWITCH
case sm_InitialWait:
// wait until initial waittime has passed by
if ( TPiO(MonoFlopTimer, InitialWaitTime) ) {
// if waittime HAS passed by
MonoFlopTimer = millis(); // make new snapshot of time
digitalWrite(PinToSwitch, OutPutOn); // switch IO-Pin to activated state
MonoFlopState = sm_Activated; // set next state of state-machine
Serial.println( F("InitialWaitTime is over switching output to ACTIVE") );
}
break; // IMMIDIATELY jump down to END OF SWITCH
case sm_Activated:
// check if time the IO-pin shall be active is over
if ( TPiO(MonoFlopTimer, ActiveTime) ) {
// if activetime of IO-pin IS over
MonoFlopTimer = millis(); // make new snapshot of time
digitalWrite(PinToSwitch, OutPutOff); // switch IO-pin to DE-activated state
MonoFlopState = sm_Locked; // set next state of state-machine
Serial.println( F("Activetime is over switching output to IN-active") );
Serial.println( F("and starting locktime") );
}
break; // IMMIDIATELY jump down to END OF SWITCH
case sm_Locked:
// check if time the logic shall be locked against too early re-triggering is over
if ( TPiO(MonoFlopTimer, LockedTime) ) {
// if locked time IS over
Serial.println( F("locktime is over change state to idling") );
MonoFlopState = sm_Idling; // set state-machine to idle-mode
}
break; // IMMIDIATELY jump down to END OF SWITCH
} // END OF SWITCH
}
}; // end of class MonoFlop
best regards Stefan