Zähl- und Zeitfunktionen
Signalformung
Dirac-Impuls "dirac"
Die Funktion gibt mit der globalen diskreten Abtastzeit discreteSampleTimeMs einen 0-1-0 Impuls der Länge 1 ns aus. Der Rückgabetyp ist <bool>
.
p = dirac();
Da diese Funktion in der Regel für logische Funktionen verwendet wird, ist der Rückgabe Wert als <bool>
direkt false oder true. Damit für einen "echten" Dirac-Impuls die Integralbedingung
stimmt, müsste dirac()
mit multipliziert werden.
Um ein Signal mit der diskreten Abtastzeit discreteSampleTimeMs abzutasten, ist die Funktion sample(x)
zu verwenden.
Timer "timer"
Die folgende Formel liefert periodisch zu den definierten Zeitpunkten einen Impuls oder den zugehörenden Zeitstempel.
pulse = timer({ interval: <dbl> // verpflichtend, sofern nicht midestens ein (*) definiert ist
, grid: <bool>
, readTime: <bool>
, minute: <str> // (*)
, hour: <str> // (*)
, day: <str> // (*)
, month: <str> // (*)
, weekday: <str> // (*)
});
// Das Konfigurationsobjekt ist verpflichtend, um darin
// eine eindeutige Konfiguration aus interval oder einem
// (*) - Element, um die Ereigniszeitpunkte zu definieren.
Eigenschaft | Wert | Beschreibung |
---|---|---|
interval | <dbl> | Zeitintervall, in dem ein Ereignis ausgelöst wird. |
grid | <bool> | Ist diese Option gesetzt, wird Intervall unabhängig von der Startzeit der Berechnung auf 00:00:00 des Tages bezogen. |
readTime | <bool> | Ist diese Option gesetzt, wird statt eines 1 Nano-Sekunde Impulses zur Ereigniszeit der Zeitstempel ausgegeben, uin64 in UTC-Nano-Sekunden seit 1.1.1970. |
minute | <str> | crontab-Syntax zur Definition der Ereigniszeitpunkte |
hour | <str> | crontab-Syntax zur Definition der Ereigniszeitpunkte |
day | <str> | crontab-Syntax zur Definition der Ereigniszeitpunkte |
month | <str> | crontab-Syntax zur Definition der Ereigniszeitpunkte |
weekday | <str> | crontab-Syntax zur Definition der Ereigniszeitpunkte |
Werden statt interval die Parameter hour, minute, day, month und/oder weekday verwendet, können explizite Triggerzeitpunkte (UTC) festgelegt werden.
Für jeden Eintrag in der Reihenfolge minute, hour, day, month, weekday ist folgende Angabe möglich (angelehnt an die crontab-Syntax):
Angabe | Bedeutung |
---|---|
keine Angabe | ist '*', wenn alle folgenden Elemente nicht definiert sind, sonst '0' |
'*' | immer / zu jeder |
'*/n' | im Interval von n |
'a-e' | im Bereich von a bis einschließlich e |
'a,b,c' | Komma-getrennte Liste von beliebigen Einzelwerten Ausführung um/am a, b und c |
Für Wochentage und Monate können statt Zahlen auch Kurznamen verwendet werden, die den ersten drei Buchstaben der englischen Bezeichnung entsprechen: z.B. “mon”, “thu”, “apr”, “jun”, “dec”, ... .
Die Zählung der Wochentage beginnt Sonntags “sun” mit 0.
Impulse können verwendet werden, um Summierungen oder Integrale zurückzusetzen oder entsprechende Werte in ein latch-Register zu übernehmen.
Beispiel | Impulszeitpunkt ... |
---|---|
{minute: 30, hour: 4} | täglich um 4:30 Uhr, "nach Betriebsschluss" |
{day: 1} | am 01.01. eines Monats um 0:00 Uhr |
{minute: '*/15'} | alle 15 Minuten, x:00, x:15, x:30, x:45 |
{hour: 2, weekday: 'sun'} | wöchentlich am Sonntag um 2:00 Uhr |
{day: 15, month: 'apr-sep'} | am 15. der Monate April bis September um 0:00 Uhr |
{hour: '6,9,14,18'} | täglich um 6, 9, 14 und 18 Uhr |
Beispiel
Im Beispiel 1b wird die Funktion timer()
zur Erzeugung eines Speicherimpulses zu einer festen Uhrzeit (Betriebsschluss) eingesetzt.
Verzögerung "delay"
Die folgenden Formeln dienen der Filterung und Verzögerung von Flanken eines Signals
delayed1_s = delay(signal, {...});
delayed2_s = delay(signal, reset, {...});
// Das Konfigurationsobjekt ist verpflichtend
delayedX_s = delay(..., { delayOn:<double>
, delayOff:<double>
, restart:<bool>
, startup: inf|<bool>
});
Eigenschaft | Wert | Beschreibung |
---|---|---|
delayOn | <dbl> | Zeit in Sekunden zur Verzögerung der positiven Flanke |
delayOff | <dbl> | Zeit in Sekunden zur Verzögerung der negativen Flanke |
restart | <bool> | Nachfolgende Flanken in der Wartezeit starten das Zeitintervall neu |
startup | inf/<bool> | Startbedingung für die Flankenerkennung, siehe nachfolgende Beschreibung |
Das Verhalten ist vom ausgegebenen Signalzustand abhängig. Ist dieser false, werden nur positive Flanken auf dem Eingangssignal signal und der Zeitparameter delayOn berücksichtigt. Ist der Zustand true, werden negative Flanken und der Zeitparameter delayOff berücksichtigt.
Die Zeitmessung beginnt jeweils mit der ersten eintreffenden Flanke und kann optional mit weiteren folgenden Flanken neu gestartet werden (restart: true). Der Ausgangszustand wechselt nur dann, wenn mit Ablauf der Zeit das Eingangssignal im entgegengesetzten Zustand anliegt. Damit werden nur kurze Signalwechsel gefiltert und Signalwechsel nur nach Stabilisierung des Signals verzögert weiter gegeben.
Mit einem true am reset Eingang wird der Ausgangszustand auf false zurück gesetzt und gehalten.
Die Funktion kann genutzt werden, um ein "prellendes" Schaltsignal zu filtern und zu stabilisieren.
Für den Systemstart muss festgelegt werden, wie mit der Vergangenheit des Eingangs signal umgegangen wird und ob damit beim Start unmittelbar eine Flanke erkannt und damit eine Wartezeit ausgelöst werden soll. Dafür dient die Eigenschaft startup:
-
inf: das erste Signal-Sample bestimmt den Wert in der Vergangenheit und damit den Ausgang vor Systemstart, eine Flanke wird damit nicht mit dem ersten Sample ausgelöst.
-
<bool>
: Der Eingang und der Ausgang werden mit diesem Signalwert (true, false) in der Vergangenheit vor Systemstart angenommen. Damit kann möglicherweise eine Flanke mit dem ersten Sample des Eingangs ausgelöst werden und eine delay-Zeit gestartet werden.
Puls "pulse"
Die folgenden Formeln wandeln eine wählbare Eingangsflanke auf signal in einen rechteckigen, boolschen Impuls der Dauer duration um (ähnlich einem Mono-Flop 74HC121 oder 74HC122). Mit einem true am Parameter reset wird der Ausgang auf false zurück gestellt und gehalten. Alle Parameter werden als <bool>
interpretiert.
p1 = pulse(signal, {...});
p2 = pulse(signal, reset, {...});
p3 = pulse(signal, reset, duration, {...});
// Das Konfigurationsobjekt ist verpflichtend
px = pulse(..., { edge:<int>
, duration:<double>
, restart:<bool>
, startup: inf|<bool>
});
Eigenschaft | Wert | Beschreibung |
---|---|---|
edge | <int> | Auswahl der steuernden Flanke: -1: negEdge, 0: anyEdge, +1: posEdge (default) |
duration | <dbl> | Dauer des Impulses in Sekunden |
restart | <bool> | Verlängerung des Impulses mit erneuter Flanke möglich |
startup | inf/<bool> | Startbedingung für die Flankenerkennung, siehe nachfolgende Beschreibung |
Das folgende Beispiel zeigt für edge = +1 das Verhalten für die Eigenschaft restart:
Für den Systemstart muss festgelegt werden, wie mit der Vergangenheit des Eingangs signal umgegangen wird und ob damit beim Start unmittelbar eine Flanke erkannt und damit ein Impuls ausgelöst werden soll. Dafür dient die Eigenschaft startup:
-
inf: das erste Signal-Sample bestimmt den Wert in der Vergangenheit vor Systemstart, eine Flanke wird damit nicht mit dem ersten Sample ausgelöst.
-
<bool>
: Der Eingang wird mit diesem Signalwert (true, false) in der Vergangenheit vor Systemstart angenommen. Damit kann möglicherweise eine Flanke mit dem ersten Sample ausgelöst werden.
Funktionsgenerator "periodic"
Die Funktion periodic()
kann als Funktionsgenerator eingesetzt werden und erzeugt ein periodisches Signal mit der Periodendauer period, solange der Eingang enable auf true gehalten wird. Die Signalform wird durch die Eigenschaft mode festgelegt. Die Ausgaberate erfolgt mit der globalen diskreten Abtastzeit discreteSampleTimeMs oder der gesetzten Ausgaberate fOut.
p1 = periodic(enable, {...});
p2 = periodic(enable, control, {...});
p3 = periodic(enable, control, period, {...});
// Das Konfigurationsobjekt ist verpflichtend
px = periodic(..., { period: <dbl>
, mode: <enum>
, reset: <enum>
, control: <dbl>
, fOut: <dbl>
, width: <uint>
, taps: [<uint>]|p##
});
Eigenschaft | Wert | Beschreibung |
---|---|---|
period | <dbl> | Konstante Periodendauer des Signalverlaufs in Sekunden, entspricht Eingang period Wertebereich: |
mode | <enum> | Betriebsart (def.: ramp) [rect, pwm, time, ramp, ramp2, sawtooth, 2Pi…] |
reset | <enum> | Rückstellung des Signalverlaufs mit [stop, start, none] |
control | <dbl> | Konstanter Steuerwert für PWM, entspricht Eingang control |
fOut | <dbl> | Optionale Ausgaberate für Datenpunkte in Hertz Wertbereich |
width | <uint> | PRBS Signal-Ausgabebreite Wertebereich |
taps | [<uint>]/p## | PRBS Rückführpositionen oder vordefiniertes Polynom p2..p12 |
Die optionalen Eingänge control und period haben Priorität über den fest eingestellten Eigenschaften. Ändert sich die Periodendauer während der Signalausgabe, wird der Signalverlauf stoßfrei an der aktuellen Ausgabeposition (*) fortgesetzt.
Auch wenn die Auswahl der Periodendauer und Ausgaberate zunächst keiner Beschränkung unterliegt, sind sinnvolle Werte im Hinblick auf die Funktion des smartCOREs zu wählen.
Werte für reset:
-
stop: (default) Der Ausgabewert wird mit enable == false zurückgesetzt.
-
start: Der Ausgabewert bleibt bis zum erneutem Start stehen und wird erst dann zurückgesetzt.
-
none: Die Ausgabe wird mit enable == false nur angehalten, nicht zurückgesetzt.
Ein paar Beispiele für Ausgabe-Modi in Verbindung mit der Periodendauer period, der Ausgaberate fOut, einem Steuersignal control und verschiedenen reset Einstellungen
Mode: rect
Ausgegeben wird ein <bool>
0-1-Rechtecksignal, wobei control die relative Lage der positiven Flanke im period-Zeitraum darstellt (default: 0.5). Reset-Zustand ist 0!
Mode: pwm
Ausgegeben wird ein <bool>
1-0-Rechtecksignal, wobei control die relative Lage der negativen Flanke im period-Zeitraum darstellt (PWM, default: 0.5). Reset-Zustand ist 0!
Mode: time
Ausgegeben werden Rampen mit den Zeitwerten in Sekunden
Mode: ramp (def.)
Ausgegeben werden Rampen mit der relativen Position im Interval als Skalierungswert
Mode: ramp2
Ausgegeben werden Rampen mit den Skalierungswerten , wobei der Rücksprung auf in der Mitte der Periodendauer liegt.
Mode: sawtooth
Ausgegeben wird ein Sägezahnförmiger Verlauf, wobei control die relative Lage der 1.0-Spitze im period-Zeitraum darstellt. Reset-Zustand ist 0.0!
Mode: 2pi
Ausgegeben wird die relative Poisition im Interval als Winkelwert für nachgeschaltete Winkelfunktionen.
wave = 10.0 * sin(periodic(true, { mode : 2pi
, period: 2.0 // Signal-Periode / s
, fOut: 100.0})); // Sample-Rate
Mode: prbs
Ausgabe eines Pseudo Binären Rauschsignals (pseudo random binary sequence) mit der Ausgabefrequenz fOut. Die Periodenlänge ergibt sich aus dem konfigurierten Generator, der Parameter period wird ignoriert.
Auf dem internen 64-bit Schieberegister sind NXOR-Rückführungen an den durch taps[] markierten Stellen vorgesehen. width (def: 0) ist die bit-Breite der Ausgabe-Maske für das Schieberegister, um das PRBS zur Generierung von pseudozufälligen Amplituden zu verwenden. Mit width: 0 wird nur eine <bool>
-Sequenz ausgegeben.
Für taps können auch vordefinierte Polynome p2 .. p12 als Rückführung für die Längen 2 .. 12 bit abgerufen werden.
Das PRBS Signal kann für die Paramater-Identifikation dynamischer Systeme verwendet werden.
Zählen und Messen
Zähler "counter"
Die folgenden Formeln zählen positive Flanken in verschiedenen Konfigurationen.
Die Bedeutung der Parameter ist vom eingestellten Betriebs-Mode abhängig!
c1 = counter(up);
c2 = counter(up, down); // mode: updown
c3 = counter(up, down, reset); // mode: updown
c4 = counter(up, down, reset, preset); // mode: updown
c5 = counter(count, dir); // mode: countdir
c6 = counter(count, dir, reset); // mode: countdir
c7 = counter(count, dir, reset, preset); // mode: countdir
c8 = counter(count, incr); // mode: countinc
c9 = counter(count, incr, reset); // mode: countinc
c10 = counter(count, incr, reset, preset); // mode: countinc
c11 = counter(A, B); // mode: qencoder
c12 = counter(A, B, reset); // mode: qencoder
c13 = counter(A, B, reset, preset); // mode: qencoder
// Optionale Konfiguration für alle Varianten
cX = counter(..., { mode: <enum> // verpflichtend, falls nicht 'updown'
, start: <int>
, preset: <int>
, lower: off|<int>
, upper: off|<int>
, range: <uint>
, modulo: <uint>
, storage: <str>
});
Im Mode updown (default) wird mit positiven Flanken auf up aufwärts und auf down abwärts gezählt (ähnlich einem 74HC193) . Kommen die Flanken exakt zum gleichen Zeitpunkt, wird gezählt.
Im Mode countdir werden positive Flanken am count Eingang gezählt und die Richtung wird unabhängig davon mit dem dir-Eingang vom Typ <dbl>
vorgegeben (ähnlich 74HC191). Ist dir > 0.0 (oder true), wird aufwärts gezählt, sonst mit dir <= 0.0 (oder false) abwärts. Default ist 1.0 bzw. true (aufwärts). Die Verwendung des Typs <dbl>
für die Richtung erlaubt die Nutzung eines analogen Geschwindigkeits-Messwerts (z.B. in "m/s"), um die Zählrichtung zu steuern. Andrerseits ist der Eingang kompatibel zu <bool>
Signalen.
Anwendungsbereiche sind die Positionsbestimmung für lineare oder rotatorische Bewegungen oder auch die richtungsabhängige Zählung von Objekten, die an einer Zählstation vorbeigeführt werden.
Im Mode countincr wird die Zählschrittweite über den incr-Eingang vom Typ <int>
mit steigender Flanke auf count zum Register addiert. Default ist 1 (aufwärts). Die Größenordnung von incr ist der eingestellten Zählerbreite, den Zählergrenzen, etc. sinnvoll anzupassen.
Im Mode qencoder werden alle Flanken auf den phasenverschobenen Signalen A und B gezählt. Die Verwendung der zwei Eingänge ist somit verpflichtend. Dabei gibt jeweils das Signal ohne Flanke die Zählrichtung an. Anwendungsbereiche sind die hochgenaue Positionsbestimmung für lineare oder rotatorische Bewegungen in 4-fach Auflösung ("Quadrature Encoder"). Dafür sollten die Flanken exakt die gleichen Abstände zueinander haben.
Für die im Bild gezeigte Anordnung ergibt sich folgendes Zählschema:
A | B | Rechtslauf Inkrementieren | Linkslauf Dekrementieren |
---|---|---|---|
0 | 0 | A: 0->1 | B: 0->1 |
1 | 0 | B: 0->1 | A: 1->0 |
1 | 1 | A: 1->0 | B: 1->0 |
0 | 1 | B: 1->0 | A: 0->1 |
0 | 0 | A: 0->1 | B: 0->1 |
Mit einem true am reset Eingang wird der Zähler auf preset (def: 0) gesetzt und gehalten. preset kann über die Eigenschaften oder als viertes Argument übergeben werden.
Das Zählregister ist vom Typ <int64>
.
Eigenschaft | Wert | Beschreibung |
---|---|---|
mode | <enum> | updown: Getrennte Zähleingänge für auf / ab (def.) countdir: Zähleingang und getrennte Richtung <dbl> (> 0.0: aufwärts)countincr: Takteingang und getrennte Schrittweite als <int> qencoder: Alle Flanken der Taktsignale A, B werden richtungsabhängig gezählt |
start | <int> | Startwert mit Start des smartCOREs |
preset | <int> | Rücksetzwert mit true auf Paraemetr r |
lower | off/<int> | Zählwert stoppt an unterer Grenze, kein Überlauf |
upper | off/<int> | Zählwert stoppt an oberer Grenze, kein Überlauf |
range | <uint> | Zählwert Bereich Überlauf von den Randwerten nach oder |
modulo | <uint> | Zählwert Bereich count %= modulo mit VorzeichenÜberlauf von den Randwerten nach 0 |
storage | <str> | Name eines persistenten Speichers für den internen Zustand. Damit bekommt nach einem Neustart des Systems der Ausgang den zuletzt gespeichert Wert. Der Inhalt dieses Speichers ist an keiner anderen Stelle im smartCORE nutzbar. |
Stoppuhr "stopwatch"
Die folgenden Formeln stellen eine Stoppuhr dar und messen die Länge eines Impulses pulse oder das Intervall zwischen zwei positiven Flanken auf pulse oder zwischen der ersten positiven Flanke auf beg zur nachfolgenden positiven Flanke auf end. Die Messung beginnt mit der Startbedingung immer bei . Mit einer Flanke am Eingang lap kann eine Zwischenzeit ausgegeben werden (latch = true). True am Eingang reset stellt die Stoppuhr und Ausgabe auf 0.0 und hält sie in diesem Zustand. Alle Eingänge werden als <bool>
interpretiert. Die Ausgabe erfolgt in Sekunden.
t1 = stopwatch(pulse);
t2 = stopwatch(beg,end);
t3 = stopwatch(beg,lap,end);
t4 = stopwatch(beg,lap,end,reset);
// Optionale Konfiguration für alle Varianten
tx = stopwatch(..., { latch: <bool>
, period: <bool>
, hold: <bool>
, restart: <bool>
, upper: off|<dbl>
});
Eigenschaft | Wert | Beschreibung |
---|---|---|
latch | <bool> | true: Ausgabe der Zeit erfolgt nur mit den steuernden Flanken (def.) false: Kontinuierliche Ausgabe der ansteigenden Messzeit |
period | <bool> | true: Messung zwischen zwei steigenden Flanken am Eingang pulse false: Messung der Zeit für pulse = true |
hold | <bool> | true: die Ausgabe wird nur mit Abschluss der Messung auf den neuen Messwert gesetzt. false: die Ausgabe wird mit neuer/laufender Messung auf 0 gesetzt. |
restart | <bool> | true: jede steigende Flanke an beg startet die Messung neu false: nur die erste steigende Flanke an beg startet die Messung (def.) |
upper | off/<dbl> | Wenn dieser Zeitwert erreicht wird, erfolgt die Ausgabe und die Messung wird abgebrochen. (def.: off) |
In der ersten Form wird nur ein Impulssignal pulse verwendet. Das folgende Diagramm zeigt verschiedene Konfigurationen und Ausgabemöglichkeiten zur Messung an einem Impulsssignal:
Die erste Zeile zeigt ein beliebiges zu messendes Impulssignal.
Die zweite Zeile zeigt für die Pulsdauermessung mit den aufsteigenden, gestrichelten Rampen die Zeit, die seit der zugehörenden Flanke am Fußpunkt links vergangen ist. In Magenta schließlich die Ausgabe der stopwatch()
Funktion für verschiedene Eigenschaften latch, hold oder upper.
Die dritte Zeile zeigt für die Periodenmessung mit den aufsteigenden, gestrichelten Rampen wieder die Zeit, die seit der zugehörenden Flanke am Fußpunkt links vergangen ist. In Orange oder Blau schließlich die Ausgabe der stopwatch()
Funktion in Abhängigkeit der Eigenschaften latch oder upper.
Für den Betrieb mit beg, lap und end Eingängen ist Konfiguration der Ausgabe entsprechend. Mit der Eigenschaft restart kann eine aktive Messung mit jeder neuen Flanke an beg wieder bei 0.0 beginnen, wodurch der Abstand ab der letzten steigenden Flanke zur Flanke auf end gemessen wird. In dieser Betriebsart kann die Ausgabe von Zwischenzeiten irreführend sein. Im folgenden Diagramm ist die Eigenschaft latch = true gesetzt, um die Ausgabe von Zwischenzeiten zu ermöglichen.
Die ersten drei Zeilen zeigen exemplarische Zeitverläufe der Eingangssignale beg, lap und end. Der lap-Eingang ist optional. In den gestrichelten Bereichen ist entweder eine Rückkehr des Signals nach false (grün) zu einem beliebigen Zeitpunkt möglich, da für den Eingang beg nur eine steigende Flanke relevant ist, oder das Signal darf jeden beliebigen Zustand annehmen (rot, blau), da die Uhr nicht gestartet ist.
In der unteren Zeile folgt wieder die Ausgabe der Funktion stopwatch()
für verschiedene Einstellungen der Eigenschaften restart und hold. Die aufsteigenden, gestrichelten Rampen zeigen die Zeit, die seit der zugehörenden Flanke am Fußpunkt links vergangen ist.
stopwatch()
misst nur die Länge eines einzelnen Ereignisses. Um die summierte Einschaltdauer eines Aggregates (Heizung, Kompressor, etc) zu ermitteln, ist die integrate(x, {...})
Funktion zielführend.
total_on_time = integrate(onState, {storage:'myTotalizerX'});
Dabei ist onState
ein <bool>
Statussignal, das als 0 oder 1 den Integranden bildet. Optional könnte noch ein Reset Signal zum Zurücksetzen des integrierten Wertes verwendet werden.