Skip to content

Watchdogs

Noticing when something stops happening, and forcing a safe state with a strong abort.

Most failures are loud: a sensor reports an error, a limit switch trips. The dangerous ones are quiet. A sensor’s cable breaks and it stops reporting; a controller hangs and stops answering. To catch a silence, a system needs a watchdog: something that expects a regular sign of life, a heartbeat, and raises the alarm when the heartbeat has been missing for too long.

This page builds a watchdog, then uses it to supervise a controller: when the watchdog expires, a strong abort forces the controller into a safe state, whatever it was doing. It builds on counters and timeouts and aborts.

The watchdog waits in Watching. A beat restarts the wait; three ticks without one, and it expires:

WatchdogSimulation

Diagram

Diagram of WatchdogStates: Watching (initial), Expired. Transitions: Watching to Watching: 1: beat; Watching to Expired: 2: 3 true / alarm = true.Watchdoginput boolbeatoutput boolalarmWatchingExpired1: beat2: 3 true/ alarm = true

Code

scchart Watchdog {
input bool beat
output bool alarm
initial state Watching
if beat go to Watching
if 3 true do alarm = true go to Expired
state Expired
}
Tick 0 of 8
Inputs for tick 1 Boolean input: true while on. It keeps its value until you change it.
Timing diagram of Watchdog
Tickinput bool beatoutput bool alarmActive state of the chart
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 8 ticks Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 8 ticks:

  1. beat = falseTick 1: watching. The entry tick does not count.
  2. beat = trueA beat: the self-loop if beat go to Watching re-enters the state, which restarts the count.
  3. beat = falseQuiet: one.
  4. beat = trueA beat: restart.
  5. beat = falseQuiet: one.
  6. beat = falseTwo.
  7. beat = falseThree quiet ticks in a row: the watchdog expires and raises the alarm.
  8. beat = falseExpired.
Warning: KIELER warns about a potential instantaneous loop here, but compiles and runs the chart correctly
  • Warning, line 5, column 17KIELER says: Instantaneous loop detected!KIELER's loop check works on the compiled chart, in which count delays are extra regions and transitions, and warns whenever control could go round a circle there within one tick, without checking whether the triggers prevent it: here the circle runs through Watching. The chart works as written.About this message
Beats in ticks 2 and 4 keep the watchdog happy. After the last one, three quiet ticks (5 to 7), and the alarm goes up in tick 7.

The trick is the self-loop. if beat go to Watching leaves Watching and enters it again, and every entry restarts the count delay if 3 true. So if 3 true can only fire after three ticks in a row without a beat. The beat transition is written first, so a beat in the very tick the count would complete still wins. (KIELER warns Instantaneous loop detected! for this chart, and SCCharts Lab Potential instantaneous loop.: a false alarm, as for the stairwell light on the counters page.)

A counter makes the time since the last beat visible, and lets the limit be anything you like:

Watchdog and WatchdogCounterComparison

Diagrams

Watchdog

Diagram of WatchdogStates: Watching (initial), Expired. Transitions: Watching to Watching: 1: beat; Watching to Expired: 2: 3 true / alarm = true.Watchdoginput boolbeatoutput boolalarmWatchingExpired1: beat2: 3 true/ alarm = true

WatchdogCounter

Diagram of WatchdogCounterStates: Watching (initial), Expired. Transitions: Watching to Watching: 1: beat / quiet = 0; Watching to Expired: 2: quiet == 2 / quiet++; alarm = true; Watching to Watching: 3: / quiet++.WatchdogCounterinput boolbeatoutput boolalarmoutput intquiet = 0WatchingExpired1: beat/ quiet = 02: quiet == 2/ quiet++;alarm = true3: / quiet++

Code

Watchdog

scchart Watchdog {
input bool beat
output bool alarm
initial state Watching
if beat go to Watching
if 3 true do alarm = true go to Expired
state Expired
}

WatchdogCounter

scchart WatchdogCounter {
input bool beat
output bool alarm
output int quiet = 0 // ticks since the last beat
initial state Watching
if beat do quiet = 0 go to Watching
if quiet == 2 do quiet++; alarm = true go to Expired
do quiet++ go to Watching
state Expired
}
Tick 0 of 8
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it.
Timing diagram of Watchdog and WatchdogCounter, no ticks yet
Tickinput bool beatWatchdog: output bool alarmWatchdog: Active state of the chartWatchdogCounter: output bool alarmWatchdogCounter: output int quietWatchdogCounter: Active state of the chart
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 8 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 8 ticks, the same inputs for both charts:

  1. beat = falseTick 1: both watch. The count delay does not count the entry tick, and quiet is 0.
  2. beat = trueA beat. Watchdog’s self-loop re-enters Watching, which restarts its count; WatchdogCounter sets quiet to 0.
  3. beat = falseA tick without a beat: quiet is 1.
  4. beat = trueA beat: both start again, quiet is 0.
  5. beat = falseQuiet: 1.
  6. beat = falseQuiet: 2.
  7. beat = falseThe third quiet tick in a row: both expire and raise the alarm. (quiet shows 3.)
  8. beat = falseExpired.
Warning: KIELER warns about a potential instantaneous loop here, but compiles and runs the chart correctly (Watchdog)
  • Warning in Watchdog, line 5, column 17KIELER says: Instantaneous loop detected!KIELER's loop check works on the compiled chart, in which count delays are extra regions and transitions, and warns whenever control could go round a circle there within one tick, without checking whether the triggers prevent it: here the circle runs through Watching. The chart works as written.About this message
Both raise the alarm in tick 7. quiet shows how long the silence has lasted.

quiet is reset by a beat and counted up otherwise; when it is 2 and the third quiet tick arrives, the watchdog expires. The two versions agree tick for tick. A real watchdog’s limit comes from the sensor: if it is specified to report every 50 ms and the chart ticks every 10 ms, a limit of a few more than 5 ticks tolerates a little jitter without waiting dangerously long.

Supervision: a strong abort into a safe state

Section titled “Supervision: a strong abort into a safe state”

Now a controller to supervise. Running drives a motor on demand and counts its starts. A watchdog in a concurrent region listens for the heartbeat of the sensor the controller depends on, and when it expires it emits expired. Running has a strong abort on that signal into Safe, which raises the alarm. restart brings both back.

SupervisorSimulation

Diagram

Diagram of SupervisorStates: Watching (initial), Expired, Running (initial, superstate), Stopped (initial), Started, Safe (superstate). Transitions: Watching to Watching: 1: beat; Watching to Expired: 2: 3 true / expired; Expired to Watching: restart; Stopped to Started: demand / motor = true; starts++; Started to Stopped: !demand / motor = false; Running to Safe: expired; Safe to Running: restart.Supervisorinput boolbeat, demand, restartoutput boolmotor, alarmoutput intstarts = 0signalexpiredWatchdogWatchingExpired1: beat2: 3 true/ expiredrestartControlRunningexit/ motor = falseStoppedStarteddemand/ motor = true;starts++!demand/ motor = falseSafeentry/ alarm = trueexit/ alarm = falseexpiredrestart

Code

scchart Supervisor {
input bool beat, demand, restart
output bool motor, alarm
output int starts = 0
signal expired
region Watchdog {
initial state Watching
if beat go to Watching
if 3 true do expired go to Expired
state Expired
if restart go to Watching
}
region Control {
initial state Running {
exit do motor = false
initial state Stopped
if demand do motor = true; starts++ go to Started
state Started
if !demand do motor = false go to Stopped
}
if expired abort to Safe
state Safe {
entry do alarm = true
exit do alarm = false
}
if restart go to Running
}
}
Tick 0 of 12
Inputs for tick 1 Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it.
Timing diagram of Supervisor
Tickinput bool beatinput bool demandinput bool restartoutput bool motoroutput bool alarmoutput int startsActive state of region WatchdogActive state of region ControlActive state of the region of Running
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 12 ticks Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 12 ticks:

  1. beat = false, demand = false, restart = falseTick 1: watching and running, motor stopped.
  2. beat = trueA beat.
  3. beat = false, demand = trueDemand: the motor starts (starts is 1).
  4. beat = trueA beat.
  5. beat = false, demand = falseNo demand: the motor stops. From now on no more beats arrive.
  6. Second quiet tick.
  7. demand = trueThird quiet tick: the watchdog emits expired. In the same tick demand rises again, but the strong abort if expired abort to Safe is decided before Running reacts: the motor is not started, starts stays 1. Running’s exit action makes sure the motor is off, and Safe raises the alarm.
  8. demand = falseSafe: the alarm stays on, whatever the inputs.
  9. restart = true, beat = truerestart, with the beats back: the watchdog watches again and the controller returns to Running.
  10. restart = falseRunning.
  11. beat = falseQuiet.
  12. Quiet.
Warning: KIELER warns about a potential instantaneous loop here, but compiles and runs the chart correctly
  • Warning, line 8, column 19KIELER says: Instantaneous loop detected!KIELER's loop check works on the compiled chart, in which count delays are extra regions and transitions, and warns whenever control could go round a circle there within one tick, without checking whether the triggers prevent it: here the circle runs through Watching. The chart works as written.About this message
Tick 7: the watchdog expires in the same tick as a demand. The motor is not started; the controller goes to Safe.

Look at tick 7. The watchdog expires, and in the same tick demand rises. Two things happen in that tick:

  • The watchdog region emits expired, and Running’s abort, which reads expired after the emission (every emission of a signal comes before every test of it in another region), fires.
  • Because the abort is strong, it is decided before anything inside Running reacts. Stopped never sees the demand: no start, starts stays 1.

Running’s exit action, exit do motor = false, runs although Running is left by a strong abort: exit actions run on every kind of exit, as mode switching explains. Put “switch everything off” into the exit action of the supervised state, and every way out of it, normal or forced, ends with the outputs safe.

With a weak abort, if expired go to Safe, the inside of Running would finish its tick first:

Supervisor and SupervisorWeakComparison

Diagrams

Supervisor

Diagram of SupervisorStates: Watching (initial), Expired, Running (initial, superstate), Stopped (initial), Started, Safe (superstate). Transitions: Watching to Watching: 1: beat; Watching to Expired: 2: 3 true / expired; Expired to Watching: restart; Stopped to Started: demand / motor = true; starts++; Started to Stopped: !demand / motor = false; Running to Safe: expired; Safe to Running: restart.Supervisorinput boolbeat, demand, restartoutput boolmotor, alarmoutput intstarts = 0signalexpiredWatchdogWatchingExpired1: beat2: 3 true/ expiredrestartControlRunningexit/ motor = falseStoppedStarteddemand/ motor = true;starts++!demand/ motor = falseSafeentry/ alarm = trueexit/ alarm = falseexpiredrestart

SupervisorWeak

Diagram of SupervisorWeakStates: Watching (initial), Expired, Running (initial, superstate), Stopped (initial), Started, Safe (superstate). Transitions: Watching to Watching: 1: beat; Watching to Expired: 2: 3 true / expired; Expired to Watching: restart; Stopped to Started: demand / motor = true; starts++; Started to Stopped: !demand / motor = false; Running to Safe: expired; Safe to Running: restart.SupervisorWeakinput boolbeat, demand, restartoutput boolmotor, alarmoutput intstarts = 0signalexpiredWatchdogWatchingExpired1: beat2: 3 true/ expiredrestartControlRunningexit/ motor = falseStoppedStarteddemand/ motor = true;starts++!demand/ motor = falseSafeentry/ alarm = trueexit/ alarm = falseexpiredrestart

Code

Supervisor

scchart Supervisor {
input bool beat, demand, restart
output bool motor, alarm
output int starts = 0
signal expired
region Watchdog {
initial state Watching
if beat go to Watching
if 3 true do expired go to Expired
state Expired
if restart go to Watching
}
region Control {
initial state Running {
exit do motor = false
initial state Stopped
if demand do motor = true; starts++ go to Started
state Started
if !demand do motor = false go to Stopped
}
if expired abort to Safe
state Safe {
entry do alarm = true
exit do alarm = false
}
if restart go to Running
}
}

SupervisorWeak

scchart SupervisorWeak {
input bool beat, demand, restart
output bool motor, alarm
output int starts = 0
signal expired
region Watchdog {
initial state Watching
if beat go to Watching
if 3 true do expired go to Expired
state Expired
if restart go to Watching
}
region Control {
initial state Running {
exit do motor = false
initial state Stopped
if demand do motor = true; starts++ go to Started
state Started
if !demand do motor = false go to Stopped
}
if expired go to Safe
state Safe {
entry do alarm = true
exit do alarm = false
}
if restart go to Running
}
}
Tick 0 of 12
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it.
Timing diagram of Supervisor and SupervisorWeak, no ticks yet
Tickinput bool beatinput bool demandinput bool restartSupervisor: output bool motorSupervisor: output bool alarmSupervisor: output int startsSupervisor: Active state of region WatchdogSupervisor: Active state of region ControlSupervisor: Active state of the region of RunningSupervisorWeak: output bool motorSupervisorWeak: output bool alarmSupervisorWeak: output int startsSupervisorWeak: Active state of region WatchdogSupervisorWeak: Active state of region ControlSupervisorWeak: Active state of the region of Running
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 12 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 12 ticks, the same inputs for both charts:

  1. beat = false, demand = false, restart = falseTick 1: both charts watch and run; the motors are stopped.
  2. beat = trueA beat.
  3. beat = false, demand = trueDemand: both motors start, and starts is 1.
  4. beat = trueA beat.
  5. beat = false, demand = falseNo demand: the motors stop. From now on no more beats arrive.
  6. The second tick without a beat.
  7. demand = trueThe third quiet tick: both watchdogs emit expired, in the very tick in which demand rises again. Supervisor’s strong abort is decided before Running reacts: no start, starts stays 1. SupervisorWeak’s weak abort lets Running finish its tick first: the motor is started and counted (starts is 2), and only then is Running left, its exit action switching the motor off again. Both end the tick in Safe, alarm on.
  8. demand = falseSafe: both alarms stay on.
  9. restart = true, beat = truerestart, with the beats back: both watch again and return to Running.
  10. restart = falseRunning.
  11. beat = falseQuiet.
  12. Quiet.
Warning: KIELER warns about a potential instantaneous loop here, but compiles and runs the chart correctly (Supervisor and SupervisorWeak)
  • Warning in Supervisor and SupervisorWeak, line 8, column 19KIELER says: Instantaneous loop detected!KIELER's loop check works on the compiled chart, in which count delays are extra regions and transitions, and warns whenever control could go round a circle there within one tick, without checking whether the triggers prevent it: here the circle runs through Watching. The chart works as written.About this message
Tick 7: with the weak abort, the motor is started (starts becomes 2) before the controller goes to Safe.

Strong and Weak are starts in Supervisor and in SupervisorWeak. Both raise the alarm in tick 7:

Tick Inputs Strong Weak
3 demand 1 1
6 none 1 1
7 demand 1 2
8 none 1 2

In SupervisorWeak, the motor is started in tick 7 and switched off again by Running’s exit action in the same tick. motor ends the tick off in both charts, but in SupervisorWeak a start command was issued and counted (starts is 2), and in a real system perhaps sent to hardware, by a controller that was already known to be blind. For supervision, use a strong abort: once the watchdog has spoken, nothing inside gets another move.

It is tempting to put the watchdog inside the state it supervises, as one more region of Running. KIELER rejects this version:

WatchdogInsideSimulation

Diagram

Diagram of WatchdogInsideStates: Running (initial, superstate), Watching (initial), Expired, Stopped (initial), Started, Safe (superstate). Transitions: Watching to Watching: 1: beat; Watching to Expired: 2: 3 true / expired; Stopped to Started: demand / motor = true; starts++; Started to Stopped: !demand / motor = false; Running to Safe: expired.WatchdogInsideinput boolbeat, demandoutput boolmotor, alarmoutput intstarts = 0signalexpiredRunningexit/ motor = falseWatchdogWatchingExpired1: beat2: 3 true/ expiredWorkStoppedStarteddemand/ motor = true;starts++!demand/ motor = falseSafeentry/ alarm = trueexpired

Code

scchart WatchdogInside {
input bool beat, demand
output bool motor, alarm
output int starts = 0
signal expired
initial state Running {
exit do motor = false
region Watchdog {
initial state Watching
if beat go to Watching
if 3 true do expired go to Expired
state Expired
}
region Work {
initial state Stopped
if demand do motor = true; starts++ go to Started
state Started
if !demand do motor = false go to Stopped
}
}
if expired abort to Safe
state Safe {
entry do alarm = true
}
}

KIELER rejects this chart

  • Line 26, column 6The strong abort from Running to Safe reads expired, which is emitted inside Running in the same tick, and KIELER cannot put the two in an orderKIELER says: The SCG is NOT asc-schedulable!In each tick KIELER has to check this abort and run the inside of Running in some order, and here each waits for the other. (KIELER accepts some charts whose transitions out of a superstate read a value written inside it, but not this one.) What always works: emit expired in a region next to Running, outside it, or read last tick's value with pre(expired).About this message
The watchdog is a region of Running itself. KIELER rejects the chart.

The messages are Can't schedule from … and The SCG is NOT asc-schedulable!; SCCharts Lab adds:

Circular dependency prevents scheduling this tick.

The abort out of Running reads expired, and now the watchdog emits expired inside Running, on the transition with the count delay. KIELER has to check the abort and run the inside of Running in some order, and with that count delay it cannot find one. It is not a matter of the abort being strong: KIELER rejects the weak version, if expired go to Safe, in the same way.

Without a count delay, KIELER does accept a watchdog inside the state it aborts. Here is the counter watchdog as a region of Running, with beats in ticks 2 and 4 as for Supervisor:

WatchdogInsideCounterSimulation

Diagram

Diagram of WatchdogInsideCounterStates: Running (initial, superstate), Watching (initial), Expired, Stopped (initial), Started, Safe (superstate). Transitions: Watching to Watching: 1: beat / quiet = 0; Watching to Expired: 2: quiet == 2 / quiet++; expired; Watching to Watching: 3: / quiet++; Stopped to Started: demand / motor = true; starts++; Started to Stopped: !demand / motor = false; Running to Safe: expired.WatchdogInsideCounterinput boolbeat, demandoutput boolmotor, alarmoutput intstarts = 0, quiet = 0signalexpiredRunningexit/ motor = falseWatchdogWatchingExpired1: beat/ quiet = 02: quiet == 2/ quiet++;expired3: / quiet++WorkStoppedStarteddemand/ motor = true;starts++!demand/ motor = falseSafeentry/ alarm = trueexpired

Code

scchart WatchdogInsideCounter {
input bool beat, demand
output bool motor, alarm
output int starts = 0, quiet = 0
signal expired
initial state Running {
exit do motor = false
region Watchdog {
initial state Watching
if beat do quiet = 0 go to Watching
if quiet == 2 do quiet++; expired go to Expired
do quiet++ go to Watching
state Expired
}
region Work {
initial state Stopped
if demand do motor = true; starts++ go to Started
state Started
if !demand do motor = false go to Stopped
}
}
if expired abort to Safe
state Safe {
entry do alarm = true
}
}
Tick 0 of 10
Inputs for tick 1 Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it.
Timing diagram of WatchdogInsideCounter
Tickinput bool beatinput bool demandoutput bool motoroutput bool alarmoutput int startsoutput int quietActive state of the chartActive state of region Watchdog (in Running)Active state of region Work (in Running)
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 10 ticks Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 10 ticks:

  1. beat = false, demand = falseTick 1: watching and running, motor stopped.
  2. beat = trueA beat.
  3. beat = false, demand = trueDemand: the motor starts (starts is 1). quiet counts the first tick without a beat.
  4. beat = trueA beat: quiet is 0 again. From now on no more beats arrive.
  5. beat = falseFirst quiet tick.
  6. Second quiet tick.
  7. Third quiet tick: the watchdog emits expired. Work checks the abort after that emission and stops at once, in Started, with the motor on. Watchdog checked it before its own emission, so it carries on into Expired, and Running is not left.
  8. expired was a signal, and it is gone. Watchdog sits in Expired, which never stops, so Running is never left: no Safe, no alarm.
  9. demand = falseThe demand ends, but Work has stopped in Started, so nothing switches the motor off. Running’s exit action would, but Running is never left.
  10. beat = trueA beat changes nothing: the motor runs, and the alarm never comes.
Note: This strong abort reads expired, which the inside of Running writes: in a tick in which expired changes, some inner regions can be aborted while others still react
  • Note, line 27, column 3KIELER checks a strong abort separately in each inner region, before that region reacts, so a region that writes expired has already read the old value. Use a weak abort (go to) or a termination (join to) for conditions computed inside Running.
Tick 7: the watchdog expires and Work stops, with the motor on. Running is never left: no Safe, no alarm, and the motor runs on.

That is worse than a rejection. KIELER checks a strong abort separately in each region inside the state, as that region runs. The Work region checks it after the watchdog has emitted expired, and stops at once, in Started. The Watchdog region checks it before its own emission, sees nothing, and moves on to Expired. Running is left only once every region inside it has stopped, and from tick 8 on expired, a signal, is absent again. So Running is never left, its exit action never runs, and nothing switches the motor off.

The rule is simple: the watchdog and the thing it supervises are siblings, never parent and child. As a sibling region, the watchdog emits expired before Running’s abort reads it, and the abort stops Running in one piece.

An early warning

Extend the counter watchdog with an output late that is true in the second tick in a row without a beat, one tick before the alarm, and false otherwise (also once the alarm is up). To test it: a beat in tick 2 and none in ticks 3 and 4 make late true in tick 4; a beat in tick 5 clears it; after that, silence makes it true in tick 7, and in tick 8 the alarm goes up and late is false again.

Show the starter chart
scchart EarlyWarning {
input bool beat
output bool alarm, late
output int quiet = 0 // ticks since the last beat
initial state Watching
if beat do quiet = 0 go to Watching
if quiet == 2 do quiet++; alarm = true go to Expired
do quiet++ go to Watching
state Expired
}
Show a solution
scchart EarlyWarning {
input bool beat
output bool alarm, late
output int quiet = 0 // ticks since the last beat
initial state Watching
if beat do quiet = 0; late = false go to Watching
if quiet == 2 do quiet++; late = false; alarm = true go to Expired
do quiet++; late = quiet == 2 go to Watching
state Expired
}

Two sensors

The starter watches sensor A. Add a second watchdog for sensor B (beatB), so that the alarm goes up when either sensor falls silent. Both watchdogs may emit the same signal. To test it: both sensors beat in tick 2, then only A (ticks 4 and 6). The starter never raises the alarm; yours should raise it in tick 5, the third tick without a beat from B, and restart with both beating (tick 8) should clear it.

Show the starter chart
scchart TwoSensors {
input bool beatA, beatB, restart
output bool alarm
signal expired
region WatchA {
initial state Watching
if beatA go to Watching
if 3 true do expired go to Expired
state Expired
if restart go to Watching
}
region Alarm {
initial state Normal
if expired go to Raised
state Raised {
entry do alarm = true
exit do alarm = false
}
if restart go to Normal
}
}
Show a solution
scchart TwoSensors {
input bool beatA, beatB, restart
output bool alarm
signal expired
region WatchA {
initial state Watching
if beatA go to Watching
if 3 true do expired go to Expired
state Expired
if restart go to Watching
}
region WatchB {
initial state Watching
if beatB go to Watching
if 3 true do expired go to Expired
state Expired
if restart go to Watching
}
region Alarm {
initial state Normal
if expired go to Raised
state Raised {
entry do alarm = true
exit do alarm = false
}
if restart go to Normal
}
}
WatchdogPrediction

Diagram

Diagram of WatchdogStates: Watching (initial), Expired. Transitions: Watching to Watching: 1: beat; Watching to Expired: 2: 3 true / alarm = true.Watchdoginput boolbeatoutput boolalarmWatchingExpired1: beat2: 3 true/ alarm = true

Code

scchart Watchdog {
input bool beat
output bool alarm
initial state Watching
if beat go to Watching
if 3 true do alarm = true go to Expired
state Expired
}

The count-delay watchdog, with beats in ticks 2, 5 and 9. What is alarm after ticks 5, 7, 8 and 9?

Inputs per tick. A value in grey was not set in that tick: it holds from an earlier one.

Tickbeat
1false
2true
3false
4false
5true
6false
7false
8false
9true
Plays the scenario on the diagram, then marks each answer.
Explanation

alarm is false after ticks 5 and 7 and true after ticks 8 and 9. The beat in tick 5 comes after two quiet ticks, just in time, and restarts the count. Ticks 6, 7 and 8 are quiet, so the watchdog expires in tick 8. The beat in tick 9 is too late: Expired has no transitions, so the alarm stays up.

In WatchdogInsideCounter the watchdog emits expired in tick 7, but Running is never left. Why?
Show the answer

Answer B: Watchdog checks the abort before emitting expired, and by tick 8 it is gone

KIELER checks a strong abort separately in each region inside the state. Work checks it after the emission and stops, which also shows that a signal from inside can trigger the abort. Watchdog checks it before, so it is not stopped, and from tick 8 on expired is absent. Running is left only once all its regions have stopped, so it never is. With the watchdog as a sibling region, expired is emitted before Running’s abort reads it, and the abort stops Running in one piece.

Why does the watchdog restart its count with a self-loop if beat go to Watching instead of using if 3 !beat go to Expired?
Show the answer

Answer C: if 3 !beat counts quiet ticks, not quiet ticks in a row

A count delay counts the ticks in which its trigger holds, consecutive or not. if 3 !beat would expire after any three quiet ticks since Watching was entered, even if beats came in between: with a beat in every other tick (ticks 2, 4 and 6), it expires in tick 7. KIELER accepts it without a word. The self-loop re-enters Watching on every beat, and re-entering restarts the count.

Key ideas

  • A watchdog expects a heartbeat and expires when it has been missing for N ticks: a count delay restarted by a self-loop, or a counter reset by each beat.
  • Give beats as single ticks when you test: inputs keep their value in the simulator.
  • Supervise with a strong abort on the watchdog’s signal: in the expiry tick nothing inside the supervised state moves.
  • Exit actions run on strong aborts too; use them to switch outputs off.
  • Keep the watchdog in a sibling region, never inside the state it aborts.

Next, Sharing a resource: two clients, one device, and an arbiter that decides who goes first.

Report a mistake on this page