Taktgeber, NTP Sync, syncroner Start
-
- User
- Beiträge: 21
- Registriert: Montag 11. September 2017, 20:27
Läuft...Reichte nicht, nur nach SEQUENCE zu triggern, sondern das [pos][1] musste da noch mit rein.
Die LED wird jetzt angesteuert. Hab zwar noch ne Warnung, weil der Channel already in use ist. Aber das findet sich, denke ich... Spannend wird es jetzt, wie syncron das ganze geht, wenn das auf zwei getrennten Raspis läuft..
Und das Tutorial... Sehr umfangreich. Hab da aber nicht die Lösung gefunden, weil ich da dieses Problem nicht finden konnte. Gibt viele Beispiele. Auch das googlen nach Codefragmenten ist schwierig, wenn man nicht die richtigen Fragen stellt. (Zitat: Das fünfte Element;)
Die LED wird jetzt angesteuert. Hab zwar noch ne Warnung, weil der Channel already in use ist. Aber das findet sich, denke ich... Spannend wird es jetzt, wie syncron das ganze geht, wenn das auf zwei getrennten Raspis läuft..
Und das Tutorial... Sehr umfangreich. Hab da aber nicht die Lösung gefunden, weil ich da dieses Problem nicht finden konnte. Gibt viele Beispiele. Auch das googlen nach Codefragmenten ist schwierig, wenn man nicht die richtigen Fragen stellt. (Zitat: Das fünfte Element;)
Ich weiss nicht, was "Reichte nicht, nur nach SEQUENCE zu triggern, sondern das [pos][1] musste da noch mit rein." uns sagen soll. Das klingt nicht wirklich danach als ob du verstanden hast, was deine GPIO-Modifikation wirklich an problemen hatte. Wie dem auch sei, das Tutorial muss man durcharbeiten, nicht durchsuchen. Und da lernt man dann auch, warum es einen Unterschied zwischen
und
gibt.
Code: Alles auswählen
while True:
print('a')
print('b')
Code: Alles auswählen
while True:
print('a')
print('b')
-
- User
- Beiträge: 21
- Registriert: Montag 11. September 2017, 20:27
Ja, das mit dem einrücken hatte ich gesehen. Der Editor Geany zeigt das ja sogar an, wenn ich diese Klammern im Code richtig deute.
Und das Tut durcharbeiten, ist zeitlich nicht drin. So gerne ich das auch machen würde. Mit diesem kleinen Programm geht es erstmal nur um einen Versuch, wie genau diese Berechnungen sind, und wie gross die Abweichungen sind. Wenn das ausreichend ist, wird es daran gehen, eine eigenen Hardware dafür zu entwickeln. Die dann aber wahrscheinlich irgendein SOC sein wird, auf dem dann was ganz abgespecktes laufen muss.
Der aktuelle Stand ist dieser:
Und das Tut durcharbeiten, ist zeitlich nicht drin. So gerne ich das auch machen würde. Mit diesem kleinen Programm geht es erstmal nur um einen Versuch, wie genau diese Berechnungen sind, und wie gross die Abweichungen sind. Wenn das ausreichend ist, wird es daran gehen, eine eigenen Hardware dafür zu entwickeln. Die dann aber wahrscheinlich irgendein SOC sein wird, auf dem dann was ganz abgespecktes laufen muss.
Der aktuelle Stand ist dieser:
Code: Alles auswählen
import time
import math
import bisect
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
GPIO.setup(40, GPIO.OUT)
SEQUENCE = [
(1000, True),
(2000, False),
(7000, True),
(3000, False),
(5000, True),
(2000, False),
]
PERIOD = sum(t for t, _ in SEQUENCE) / 1000.0 # in seconds
def main():
absolute_sequence = [0]
for ts, _ in SEQUENCE:
absolute_sequence.append(absolute_sequence[-1] + ts)
del absolute_sequence[0]
while True:
time.sleep(.1)
offset = int(math.fmod(time.time(), PERIOD) * 1000)
pos = bisect.bisect_left(absolute_sequence, offset)
if SEQUENCE[pos][1] == True:
GPIO.output(40, GPIO.HIGH)
else:
GPIO.output(40, GPIO.LOW)
# print(offset, pos, SEQUENCE[pos][1])
if __name__ == '__main__':
main()
GPIO.cleanup()
- __blackjack__
- User
- Beiträge: 14051
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@RudiOnTheAir: Die aktuelle Stand sieht falsch aus weil da teilweise Tabulatorzeichen zum Einrücken benutzt werden. Konvention ist vier Leerzeichen pro Ebene, keine Tabs.
Man vergleicht nicht mit literalen Wahrheitswerten. Da kommt wieder ein Wahrheitswert bei heraus. Entweder der, den man sowieso schon hatte, dann hätte man auch gleich den nehmen können, oder dessen Gegenteil. Dafür gibt es ``not``.
Das ``if``/``else`` ist aber sowieso überflüssig, denn beide Zweige unterscheiden sich ja nur durch diesen Wahrheitswert den man bereits hat, und einfach nur einsetzen braucht, in die eine Zeile die da in beiden Zweigen steht.
Edit: GPIO Setup/Cleanup gehören nicht auf Modulebene sondern ins Hauptprogramm und das Aufräumen sollte man durch ein ``try``/``finally`` absichern, so dass es auch ausgeführt wird wenn das Programm durch eine Ausnahme abgebrochen wird.
Man vergleicht nicht mit literalen Wahrheitswerten. Da kommt wieder ein Wahrheitswert bei heraus. Entweder der, den man sowieso schon hatte, dann hätte man auch gleich den nehmen können, oder dessen Gegenteil. Dafür gibt es ``not``.
Das ``if``/``else`` ist aber sowieso überflüssig, denn beide Zweige unterscheiden sich ja nur durch diesen Wahrheitswert den man bereits hat, und einfach nur einsetzen braucht, in die eine Zeile die da in beiden Zweigen steht.
Edit: GPIO Setup/Cleanup gehören nicht auf Modulebene sondern ins Hauptprogramm und das Aufräumen sollte man durch ein ``try``/``finally`` absichern, so dass es auch ausgeführt wird wenn das Programm durch eine Ausnahme abgebrochen wird.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
-
- User
- Beiträge: 21
- Registriert: Montag 11. September 2017, 20:27
Fraglich jetzt, ob das nur quick and dirty ist, aber der korrekten Berechnung grundsätzlich nicht im Weg steht, oder ob das hinderlich ist für die Genauigkeit. Als erstes Ergebnis ist festzustellen, das die LED sichtbar unsyncron an und aus gehen. Man muss aber schon genau hinsehen. Genaueres kann dann das Oszi sagen... Ich habe den NTP Pool n.de.pool.ntp.org eingetragen und die beiden Raspi hängen an unterschiedlichen LAN Anschlüssen.
Die Tabs kann ich ja noch rausnehmen. Wie das mit dem if/else dann aussehen muss, ist mir noch nicht klar. Wie gefragt. Macht das was an Temp oder Genaugkeit? Ich will morgen mal einen festen NTP vorgeben, damit die Dinger nicht aus dem Pool was raussuchen...
Die Tabs kann ich ja noch rausnehmen. Wie das mit dem if/else dann aussehen muss, ist mir noch nicht klar. Wie gefragt. Macht das was an Temp oder Genaugkeit? Ich will morgen mal einen festen NTP vorgeben, damit die Dinger nicht aus dem Pool was raussuchen...
-
- User
- Beiträge: 21
- Registriert: Montag 11. September 2017, 20:27
Das Programm muss doch die Berechnungen noch schaffen.? Oder ist das überhaupt kein Problem.?
Interessant ist, je länger ich die beiden LED im Auge behalte... Mal ist die eine minimal vorrauseilend, mal die andere. Die beiden Pi sind auch noch unterschiedlich. Einer hat kein Onboard WLAN, das ist wohl ein altes Modell. Ist vieleicht ein unfairer Vergleich...
Will mal 0.01 probieren. Hab grad gelesen, das die Genaugkeit davon letztlich vom OS abhängt....
Interessant ist, je länger ich die beiden LED im Auge behalte... Mal ist die eine minimal vorrauseilend, mal die andere. Die beiden Pi sind auch noch unterschiedlich. Einer hat kein Onboard WLAN, das ist wohl ein altes Modell. Ist vieleicht ein unfairer Vergleich...
Will mal 0.01 probieren. Hab grad gelesen, das die Genaugkeit davon letztlich vom OS abhängt....
Warum rechnest Du nicht einfach aus, wie lange Du schlafen mußt?
Code: Alles auswählen
def main():
next_time = time.time()
next_time -= next_time % -PERIOD
while True:
for delay, on in SEQUENCE:
GPIO.output(40, on)
next_time += delay / 1000
time.sleep(next_time - time.time())
-
- User
- Beiträge: 21
- Registriert: Montag 11. September 2017, 20:27
Ähm, das blicke ich jetzt nicht. Ist es nicht so, das die Timer vom genauen Takt des Rechner abhängen. Und wenn der eine Schwankung hat...? Das Ziel ist es an verschiedenen Orten einen syncronen Takt zu erzeugen. Die einzige Referenz ist NTP bzw. DCF77 / GPS...
EDIT:
Hab die SleepZeit jetzt auf 0.01
Sieht besser aus. So rein optisch.
EDIT:
Hab die SleepZeit jetzt auf 0.01
Sieht besser aus. So rein optisch.
Zuletzt geändert von RudiOnTheAir am Mittwoch 5. Februar 2020, 16:48, insgesamt 1-mal geändert.
- __blackjack__
- User
- Beiträge: 14051
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@RudiOnTheAir: Dieses Konstrukt…
…ruft `output()` letztlich mit 1 als zweitem Argument auf wenn ``SEQUENCE[pos][1]`` den Wert `True` ergibt (also 1 als Zahl betrachtet) und mit 0 wenn ``SEQUENCE[pos][1]`` den Wert `False` (also 0 als Zahl betrachtet). Das heisst das ist nichts anderes als einfach nur diese eine Zeile:
`time.time()` hängt natürlich von irgendeinem Timer ab, aber das sollte ”Wall clock”-Werte liefern. In Sekunden.
Code: Alles auswählen
if SEQUENCE[pos][1] == True:
GPIO.output(40, GPIO.HIGH)
else:
GPIO.output(40, GPIO.LOW)
Code: Alles auswählen
GPIO.output(40, SEQUENCE[pos][1])
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
@Sirius3: Da ist ein Einruekungsfehler drin. Und time.sleep darf nicht negativ sein, was es bei dir (EDIT: glaube ich..) aber wird, wenn man in der Periode nicht zufaellig richtig liegt. Aber die Grundidee ist cool, weil es auf das doch etwas schwergewichtigere bisecten verzichtet 
Ja und? In Sirius3 code wird doch die wall-clock time.time() verwandt. Genauso wie in meinem. Das ist die offizielle Zeitbasis, die via NTP (oder spaeter DCF) auch drift-kompensiert ist.RudiOnTheAir hat geschrieben: Mittwoch 5. Februar 2020, 16:46 Ähm, das blicke ich jetzt nicht. Ist es nicht so, das die Timer vom genauen Takt des Rechner abhängen.
-
- User
- Beiträge: 21
- Registriert: Montag 11. September 2017, 20:27
Hmm, der "Sirius3" Code ersetzt jetzt welchen Part.? Alles unterhalb von PERIOD = sum... bis vor if __name...?
Das ganze nochmal komplett, mit allen nötigen Korrekturen:
Da das GPIO.output hoffentlich nicht länger dauert als die Pause dazwischen, sollte time.sleep niemals negative Werte annehmen. Ich habe aber zur Sicherheit ein max eingebaut, die Schleife synchronisiert sich danach wieder von alleine, falls der NTP die Zeit mehrere Sekunden vorsetzen sollte.
Code: Alles auswählen
import time
from RPi import GPIO
LED_PIN = 40
SEQUENCE = [
(1000, True),
(2000, False),
(7000, True),
(3000, False),
(5000, True),
(2000, False),
]
PERIOD = sum(t for t, _ in SEQUENCE) / 1000.0 # in seconds
def main():
GPIO.setmode(GPIO.BOARD)
GPIO.setup(LED_PIN , GPIO.OUT)
try:
next_time = time.time()
next_time -= next_time % -PERIOD
while True:
for delay, on in SEQUENCE:
GPIO.output(LED_PIN, on)
next_time += delay / 1000.0
time.sleep(max(0, next_time - time.time()))
finally:
GPIO.cleanup()
if __name__ == '__main__':
main()
-
- User
- Beiträge: 21
- Registriert: Montag 11. September 2017, 20:27
Danke. Ich teste das morgen. Wird auch interessant zu sehen, wie lange das dauert wenn NTP weg ist weil kein Netzwerk. Wann das sichtbar weg driftet. Ich vermute nur wenige Stunden.
Das Puls Pausen Verhältnis ist übrigens sehr variabel. Kann also auch nur kurz on sein und dann eine lange Pause oder umgekehrt.
Das Puls Pausen Verhältnis ist übrigens sehr variabel. Kann also auch nur kurz on sein und dann eine lange Pause oder umgekehrt.
- __blackjack__
- User
- Beiträge: 14051
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@RudiOnTheAir: Wieso sollte das nach wenigen Stunden driften? NTP ist ja nur zum synchronisieren und nicht um ständig die Zeit vorzugeben. So furchtbar ungenau/schwankend sollten die Timer im Raspi nicht sein, und um einen konstanten Drift sollte sich der Kernel kümmern.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Doch, ich kann mir gut vorstellen, dass der recht stark driftet. Der PI hat keine RTC, und AFAIK keinen Quartz. Wie auch immer genau er seinen Takt herstellt, wenn es zB Temperatur-Schwankungen gibt, wird das um ein paar Prozent abweichen. Eine RTC zu verbauen waere beim NTP-Szenario ein Weg das einzudaemmen. Da aber DCF77 verwandt werden soll, ist das denke ich mal eh kein Problem - das koennte zumindest permanent die System-Zeit korrigieren. Ob es das tut weiss ich aber auch nicht. Gleiches gilt auch fuer NTP, wie oft das eigentlich gestartet wird - kA.
-
- User
- Beiträge: 21
- Registriert: Montag 11. September 2017, 20:27
Der NTPD läuft ja permanent. Und wie oft der schaut kann man einstellen. AFAIK ist der Max Wert für den Interval 1024 Sekunden.
-
- User
- Beiträge: 21
- Registriert: Montag 11. September 2017, 20:27
Zur Info für technisch Interessierte an diesem Aufbau.
Die beiden LED sind für das Auge syncron. Das Oszi sieht natürlich trotzdem einen kleinen Versatz. Konkret sind das im Mittel 4,1 ms. Code von Siruis...
Siehe Bild.

Jetzt kommt der Test, wie schnell das wegläuft ohne NTP...
Die beiden LED sind für das Auge syncron. Das Oszi sieht natürlich trotzdem einen kleinen Versatz. Konkret sind das im Mittel 4,1 ms. Code von Siruis...
Siehe Bild.

Jetzt kommt der Test, wie schnell das wegläuft ohne NTP...