rasProject_01 / weSweetHome
R. 240
process control / RasPi software by weinert-automation
|
States and state machine support. More...
Functions | |
uint8_t | fiveBandDoEnter (state_t *const me, float analogueVal) |
Five band checker turn / force ON. More... | |
uint8_t | fiveBandDoLeave (state_t *const me, float analogueVal) |
Five band checker turn / force OFF. More... | |
uint8_t | fiveBandTick (state_t *const me, float controlV) |
Five band checker trigger. More... | |
uint8_t | floatHystDoEnter (state_t *const me, float analogueVal) |
Float value hysteresis turn / force ON. More... | |
uint8_t | floatHystDoLeave (state_t *const me, float analogueVal) |
Float value hysteresis turn / force OFF. More... | |
uint8_t | floatHystTick (state_t *const me, float const controlV) |
Float value hysteresis trigger. More... | |
void | genStateText (char *stateText, state_t const *const me, char const *stamp) |
Generate text for state machine status. More... | |
void | logStateReason (state_t const *const me, char const *stamp, char const *cause) |
Log status text with cause and info. More... | |
void | logStateText (state_t const *const me, char const *stamp) |
Log status text. More... | |
uint8_t | seqContDoEnter (state_t *const me, char const *startCommand) |
Sequential control entry. More... | |
uint8_t | seqContDoLeave (state_t *const me, char const *const stopCommand) |
Sequential control leave. More... | |
uint8_t | seqContTick (state_t *const me) |
Sequential control tick or check. More... | |
void | setGenStateText (state_t *const me, genStateText_t const fun) |
Set the function to generate text for state machine status. More... | |
void | startStateText (char *stateText, state_t const *const me, char const *stamp) |
Generate status text standard start. More... | |
uint8_t | switchDebDoEnter (state_t *const me, uint32_t controlV) |
Switch de-bounce turn / force ON. More... | |
uint8_t | switchDebDoLeave (state_t *const me, uint32_t controlV) |
Switch de-bounce turn / force OFF. More... | |
uint8_t | switchDebTick (state_t *const me, uint32_t controlV) |
Switch de-bounce trigger. More... | |
uint8_t | switchDebTickAC (state_t *const me, uint32_t controlV) |
Switch de-bounce trigger AC. More... | |
uint8_t | timerDoEnter (state_t *const me, uint32_t secFromNow) |
Timer entry. More... | |
uint8_t | timerDoLeave (state_t *const me, uint32_t ignored) |
Timer leave, that is stop timer. More... | |
uint8_t | timerDoStart (state_t *const me, uint32_t secFromNow) |
Timer unconditional entry and set. More... | |
uint8_t | timerDoStart4ever (state_t *const me) |
Timer unconditional entry and set forever or stop it. More... | |
uint8_t | timerDoTrigger (state_t *const me, uint32_t secFromNow) |
Timer entry or (pro-longing) re-trigger. More... | |
uint8_t | timerEndTrigger (state_t *const me, uint32_t const secUTCend) |
Timer entry or (pro-longing) re-trigger to absolute UTC end. More... | |
uint8_t | timerTickCheck (state_t *const me, uint32_t controlV) |
Timer trigger. More... | |
States and state machine support.
Revision history
State machines are implemented in an object oriented way although C is in no way supporting objects. We do this by defining the state in a structure and the behaviour in a set of functions, regarding a defined structure variable plus the functions as an object modelling the state machine in question.
Of course, in C we don't have the object orientation principles, especially no encapsulation. There is no binding of behaviour (functions) to the state (structure variable), which leads to a structure pointer as first parameter of every related function. The only substitute is discipline.
As of Revision 193 there are five types of state machines:
sequential Control in Sequential Function Chart (SFC) mannor (0xFC)
cross-compile by: arm-linux-gnueabihf-gcc -DMCU=BCM2837 -I./include -c -o weRasp/weStateM.o weRasp/weStateM.c
void startStateText | ( | char * | stateText, |
state_t const *const | me, | ||
char const * | stamp | ||
) |
Generate status text standard start.
This sets the common standard start of a status text in state text, like:
It ends with a blank at [40] after the colon at [39]. State machine type or instance specific text may be added from [40] or [41] up to (recommended) [76] followed by a terminating 0.
Hint: This function sets a 0 at [41] for robustness, i.e. having stateText always as string.
stateText | a character array supplied to hold the state text to be generated; minimal length 80. |
me | pointer to own state; never null |
stamp | (time) stamp to be prepended (max. length 23); default " - " |
void genStateText | ( | char * | stateText, |
state_t const *const | me, | ||
char const * | stamp | ||
) |
Generate text for state machine status.
This is the minimal common standard for all status machines.
stateText | a character array supplied to hold the state text to be generated; minimal length 80. |
me | pointer to own state; never null! |
stamp | (time) stamp to be prepended (max. length 23); default " - " |
void logStateText | ( | state_t const *const | me, |
char const * | stamp | ||
) |
void logStateReason | ( | state_t const *const | me, |
char const * | stamp, | ||
char const * | cause | ||
) |
Log status text with cause and info.
The status as text will be generated and then be output to outLog. outLog will be flushed.
The text will be:
stamp # state machine name: cause me->infoTxt
me->infoTxt has to be set/ provided by application software and will be output to a maximum / recommended length of 29. A standard format is one field of 7 and two fields of ten characters separated by spaces.
me | pointer to own state; not null |
stamp | (time) stamp to be prepended (max. length 23); default " - " |
cause | the cause of the state change (max. length 6); default me->controlVS |
void setGenStateText | ( | state_t *const | me, |
genStateText_t const | fun | ||
) |
Set the function to generate text for state machine status.
me | pointer to own state machine |
fun | the new text generator function |
uint8_t timerTickCheck | ( | state_t *const | me, |
uint32_t | controlV | ||
) |
Timer trigger.
me | pointer to own state; not null |
controlV | current time stamp; mostly cycTaskEventData_t.realSec resp. getAbsS() |
uint8_t timerDoEnter | ( | state_t *const | me, |
uint32_t | secFromNow | ||
) |
Timer entry.
This function starts an inactive timer to end secFromNow s. It does nothing on a timer already active resp. running, especially, it does not re-trigger / prolong the timer's time.
This is the function set as (default) state_t.doEnter and not timerDoStart.
me | pointer to own state; not null |
secFromNow | time to run on from now (s) |
uint8_t timerDoStart | ( | state_t *const | me, |
uint32_t | secFromNow | ||
) |
Timer unconditional entry and set.
This function starts an inactive timer. The timer's end time will be set to (now + secFromNow s) no matter the timers previous state. This unconditional changing the end time of a timer already running is the difference to timerDoEnter.
This is not the function set as (default) state_t.doEnter; it is timerDoEnter.
me | pointer to own state; not null |
secFromNow | time to run on from now (s) |
uint8_t timerDoStart4ever | ( | state_t *const | me | ) |
Timer unconditional entry and set forever or stop it.
This function starts an inactive timer. The timer's end time will be set to 2.2.2106 no matter the timers previous state. This date is considered as for ever in our 21st century. This does effectively stop the timer.
This function is intended to start or keep running a timer not to end before its time is to be set (by timerDoStart) to a sensible end time.
One use case is: A timer running forever is in error state.
This function is, of course, faster than timerDoEnter and timerDoStart.
me | pointer to own state; not null |
uint8_t timerDoTrigger | ( | state_t *const | me, |
uint32_t | secFromNow | ||
) |
Timer entry or (pro-longing) re-trigger.
This function starts an inactive timer to end secFromNow s. IF the timer is active and if (now + secFromNow) is later than the current end, the timer me's runtime will be prolonged accordingly (timer re-trigger).
me | pointer to own state; not null |
secFromNow | time to run on from now (s) |
uint8_t timerEndTrigger | ( | state_t *const | me, |
uint32_t const | secUTCend | ||
) |
Timer entry or (pro-longing) re-trigger to absolute UTC end.
If secUTCend is now or in the past or if it is equal the the end of the already active timer, nothing will be done (returns 1).
This function starts an inactive timer to end at secUTCend. If the timer is active already secUTCend will be taken as new end time.
me | pointer to own state; not null |
secUTCend | end time |
uint8_t timerDoLeave | ( | state_t *const | me, |
uint32_t | ignored | ||
) |
Timer leave, that is stop timer.
Note: This function is usable for other state machine types, too, if appropriate.
me | pointer to own state; not null |
ignored | as the name says |
uint8_t switchDebTick | ( | state_t *const | me, |
uint32_t | controlV | ||
) |
Switch de-bounce trigger.
me | pointer to own state; not null |
controlV | 0: input OFF else: input ON |
uint8_t switchDebTickAC | ( | state_t *const | me, |
uint32_t | controlV | ||
) |
Switch de-bounce trigger AC.
This function does essentially the same as switchDebTick, except for On ticks being counted twice. This is meant for half wave rectified AC signals sampled at multiples of their frequency. Obviously, half or 1/2 + 1 of the samples will always be Off. And, of course, the state machine has to be made with a on chain length being by the number of samples per period higher than the normal switch de-bounce filter time, to avoid spiky ON results.
me | pointer to own state; not null |
controlV | 0: input OFF else: input ON |
uint8_t switchDebDoEnter | ( | state_t *const | me, |
uint32_t | controlV | ||
) |
Switch de-bounce turn / force ON.
me | pointer to own state; not null |
controlV | irrelevant but recorded ob state change |
uint8_t switchDebDoLeave | ( | state_t *const | me, |
uint32_t | controlV | ||
) |
Switch de-bounce turn / force OFF.
Note: this function is usable for other non timer stati, too;
me | pointer to own state; not null |
controlV | irrelevant but recorded ob state change |
uint8_t floatHystTick | ( | state_t *const | me, |
float | controlV | ||
) |
Float value hysteresis trigger.
me | pointer to own state; not null |
controlV | the sampled analogue value |
uint8_t floatHystDoEnter | ( | state_t *const | me, |
float | analogueVal | ||
) |
Float value hysteresis turn / force ON.
me | pointer to own state; not null |
analogueVal | irrelevant, but recorded |
uint8_t floatHystDoLeave | ( | state_t *const | me, |
float | analogueVal | ||
) |
Float value hysteresis turn / force OFF.
Note: this function is usable for other non timer stati, too;
me | pointer to own state; not null |
analogueVal | irrelevant, but recorded; may take an (uint32_t) cast float |
uint8_t fiveBandTick | ( | state_t *const | me, |
float | controlV | ||
) |
Five band checker trigger.
me | pointer to own state; not null |
controlV | the sampled analogue value |
uint8_t fiveBandDoEnter | ( | state_t *const | me, |
float | analogueVal | ||
) |
Five band checker turn / force ON.
This function puts the checker in state bad Hi (2) no matter the parameter value.
me | pointer to own state; not null |
analogueVal | irrelevant, but recorded on state change |
uint8_t fiveBandDoLeave | ( | state_t *const | me, |
float | analogueVal | ||
) |
Five band checker turn / force OFF.
This function puts the checker in state OK (0) no matter the parameter value.
me | pointer to own state; not null |
analogueVal | irrelevant, but recorded on state change |
uint8_t seqContDoEnter | ( | state_t *const | me, |
char const * | startCommand | ||
) |
Sequential control entry.
This function starts the sequence from OFF to ON.
me | pointer to own state; not null |
startCommand | the cause of the state change; 6 characters (max.) to be recorded and else irrelevant for his function |
uint8_t seqContDoLeave | ( | state_t *const | me, |
char const * | stopCommand | ||
) |
Sequential control leave.
This function starts the sequence from ON to OFF.
me | pointer to own state; not null |
stopCommand | It is recorded on state changes and else irrelevant for this function; see description on seqContTick |
uint8_t seqContTick | ( | state_t *const | me | ) |
Sequential control tick or check.
If this sequential control (me) is not in a stable OFF or ON state, that is state_t.status is 0 or 1 and state_t.subStatus is 0, this function should be called at regular intervals or on relevant conditions state changes.
The function must keep or advance the state.
It must react on interrupts by seqContDoEnter or seqContDoLeave recognisable by state_t.status == 5 respectively 4. Note: This is just for the case, that individual the call back function state_t.onStateChange does not handle this "interrupts" — what it really should.
This (basic) implementation advances the sub state from 1 to n-1 respectively m-1. Interrupts by seqContDoEnter or seqContDoLeave are handled by changing to sub state 1 of the opposite leg.
When this basic implementation is not sufficient for a concrete SFC, the application may provide an own tick/check function. However, in most cases seemingly complicated cases — nonlinear chains, wait conditions etc. — the specialised behaviour can most often be implemented by an individual state_t.onStateChange call back function.
me | pointer to own state; not null |