Ich habe für den Raspberry ein Python Skript geschrieben, dass zeitgesteuert jeden Tag morgens einen Linearantrieb steuert, der am Frühbeet eines Schilkrötengeheges ein Tor bis zu einer durch einen Endschalter definierten Position auf- und abends wieder zu fährt.
Das Skript funktionierte 14 Tage lang klaglos, wie das Log file bestätigt. Gestern Abend bemerkte ich zufällig, dass die Ausführung ca. 7 Minuten verzögert stattfand und heute morgen fuhr das Tor auch 50 Minuten nach dem eingestellten Zeitpunkt nicht mehr auf.
Ich habe daraufhin in diesem Fehlerzustand folgendes geprüft:
1. Einloggen mittels SSH Konsole über WLAN: Funktionierte heute Morgen (im Fehlerzustand), gestern Abend jedoch nicht.
2. Systemzeit: Stimmte genau mit meiner Armbanduhr überein.
3. CPU Auslastung: Im Mittel wenige Prozent.
4. CPU Temperatur: 35°C.
5. Speicherverbrauch: Ca. 10%.
6. Log file des Python Skriptes: Hier konnte ich am Zeitstempel der einzelnen Prozess Schritte sehen, dass die Ausführung jedes einzelnen Schrittes gestern Abend bereits extrem verlangsamt war und anstelle von ms jetzt z.T. Minuten brauchte. Heute morgen war kein Eintrag mehr zu sehen. Ich hänge eine verkürzte Version an, mit dem ersten, einem weiteren Log von Vorgestern und dem letzten (verlangsamten) von Samstagabend. Man erkennt, dass sich keine schleichende Verlangsamung eingestellt hat.
Ich verwende den RPi B+ (single core) unter Raspbian Stretch mit Python 3.6.0 und folgenden Maßnahmen für einen Dauerbetrieb:
• Swapping ist deaktiviert,
• 2,5A Netzteil mit kurzem Anschlusskabel (Linearantrieb über separates 12V Netzteil versorgt)
• Log files /var/log/ werden auf USB Stick geschrieben.
• HW Watchdog aktiviert, jedoch nur auf OS freezes konfiguriert (Standardkonfig.)
• Kühlkörper auf SoC und Pwr. Mgt. Chip.
Nach einem reboot fuhr das Tor erwartungsgemäss auf.
Es scheint auf den ersten Blick kein Problem mit dem OS oder der Stromversorgung vorgelegen zu haben oder gibt es hier gegenteilige Meinungen? Ohne das näher belegen zu können habe ich den schedule Befehl im Verdacht. Ich würde als nächstes die Funktion mit dem schedule Befehl in der while 1 Schleife anstatt sekündlich in einem 30 sek. Intervall durchlaufen lassen, um die Häufigkeit der Ausführung des schedule Befehls zu reduzieren. Ist das sinnvoll?
Gibt es weitere Ideen was ich tun könnte um der Ursache auf die Schliche zu kommen?
Ich bin Python oder allgemein Programmieranfänger, benötige daher vermutlich etwas Kontext.
Im Voraus vielen Dank für Eure Tipps und viele Grüße
Werner
Das Skript:
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: utf-8 -*-
from datetime import datetime
import RPi.GPIO as GPIO
import schedule
import time
import logging
# Dieses Skript fährt das Tor bei Ausführung auf.
# GPIO Konfiguration
# RPi.GPIO Layout verwenden (wie Pin-Nummern)
GPIO.setmode(GPIO.BOARD)
# Alle Relais durch High setzen der entsprechenden GPIOs ausschalten.
# Four relais card:
FR_IN1: int = 15
FR_IN2: int = 13
FR_IN3: int = 11
FR_IN4: int = 7
GPIO.setup(FR_IN1, GPIO.OUT)
GPIO.setup(FR_IN2, GPIO.OUT)
GPIO.setup(FR_IN3, GPIO.OUT)
GPIO.setup(FR_IN4, GPIO.OUT)
GPIO.output(FR_IN1, GPIO.HIGH)
GPIO.output(FR_IN2, GPIO.HIGH)
GPIO.output(FR_IN3, GPIO.HIGH)
GPIO.output(FR_IN4, GPIO.HIGH)
# Two relais card:
TR_IN1: int = 16
TR_IN2: int = 18
GPIO.setup(TR_IN1, GPIO.OUT)
GPIO.setup(TR_IN2, GPIO.OUT)
GPIO.output(TR_IN1, GPIO.HIGH)
GPIO.output(TR_IN2, GPIO.HIGH)
# Geschaltete 230V Versorgung f. 12V Netzteil: Pin 16 (GPIO #4) auf Output setzen
AC230V_12V: int = 16
GPIO.setup(AC230V_12V, GPIO.OUT)
# Tor Endschalter f. Zustand "Geschlossen": Pin 33 (GPIO 13), auf Input setzen
# Achtung: Ursprünglicher GPIO 10 (Pin 19) wahrscheinlich durch Überspg. zerstört. Hängt noch parallel mit an GPIO13
End_swtch_closed: int = 33
GPIO.setup(End_swtch_closed, GPIO.IN)
# Tor Endschalter f. Zustand "Offen": Pin 37 (GPIO 26), auf Input setzen
# Achtung: Ursprünglicher GPIO 9 (Pin 21) wahrscheinlich durch Überspg. zerstört. Hängt noch parallel mit an GPIO26
End_swtch_open: int = 37
GPIO.setup(End_swtch_open, GPIO.IN)
# H-Brücke f. Linearmotor: IN1: Pin 12 (GPIO #18), IN2: Pin 26 (GPIO #7) auf Output setzen
H_brdg_EN1: int = 12
H_brdg_EN2: int = 26
GPIO.setup(H_brdg_EN1, GPIO.OUT)
GPIO.setup(H_brdg_EN2, GPIO.OUT)
def gate_linear_drive_off(self):
"""Motor über H-Brücke ausschalten, kurz darauf 230V für 12V Netzteil ausschalten"""
# Motor ausschalten.
GPIO.output(H_brdg_EN1, GPIO.LOW)
GPIO.output(H_brdg_EN2, GPIO.LOW)
# 12V Versorgung f. Linearantrieb abschalten.
time.sleep(1)
# Relais sind Low aktiv
GPIO.output(AC230V_12V, GPIO.HIGH)
def end_pos_open(self):
"""Hall sensor has detected end position, write log entry, call gate power off"""
logging.info("end_pos_open: Hallgeber hat *Offen* Endlage erkannt")
# Motor ausschalten.
GPIO.output(H_brdg_EN1, GPIO.LOW)
GPIO.output(H_brdg_EN2, GPIO.LOW)
logging.info("end_pos_open: Motor wurde von H-Brücke abgeschaltet")
# 12V Versorgung f. Linearantrieb abschalten.
time.sleep(1)
# Relais sind Low aktiv
GPIO.output(AC230V_12V, GPIO.HIGH)
logging.info("end_pos_open: Netzspannung für 12V Netzteil abgeschaltet")
def end_pos_closed(self):
"""Hall sensor has detected end position, write log entry, call gate power off"""
logging.info("end_pos_closed: Hallgeber hat *Zu* Endlage erkannt")
# Motor ausschalten.
GPIO.output(H_brdg_EN1, GPIO.LOW)
GPIO.output(H_brdg_EN2, GPIO.LOW)
logging.info("end_pos_closed: Motor wurde von H-Brücke abgeschaltet")
# 12V Versorgung f. Linearantrieb abschalten.
time.sleep(1)
# Relais sind Low aktiv
GPIO.output(AC230V_12V, GPIO.HIGH)
logging.info("end_pos_closed: Netzspannung für 12V Netzteil abgeschaltet")
def gate_open():
"""Ansteuern des Linearantriebes zum auffahren des Törchens"""
# 1. 12V Versorgung f. Linearantrieb einschalten
logging.info("----------- gate_open: Tor Öffnungsvorgang eingeleitet -----------")
GPIO.output(AC230V_12V, GPIO.LOW)
logging.info("gate_open: Netzspannung an 12V Netzteil eingeschaltet")
time.sleep(2)
# 2. Prüfen ob Tor nicht bereits offen ist. Näherungsschalter ist high bei Annäherung#
if GPIO.input(End_swtch_open) == GPIO.LOW:
logging.info("gate_open: Prüfung Torstatus vor Öffnungsvorgang ergab: Tor ist nicht bis Endposition offen")
# Interrupt konfigurieren: Wenn Endschalter für offene Torposition anspricht, dann Motor ausschalten
GPIO.add_event_detect(End_swtch_open, GPIO.RISING, callback=end_pos_open)
logging.info("gate_open: Interrupt durch Hallgeber in Position Offen konfiguriert")
# 3. Wenn Tor noch nicht offen, Motor in Öffnungsrichtung einschalten.
GPIO.output(H_brdg_EN2, GPIO.LOW)
GPIO.output(H_brdg_EN1, GPIO.HIGH)
logging.info("gate_open: Motor wurde durch H-Brücke gestartet, Richtung Position Auf")
time.sleep(20)
GPIO.remove_event_detect(End_swtch_open)
logging.info("gate_open: Interrupt End_swtch_open wurde gelöscht")
gate_linear_drive_off("1")
logging.info("----------- gate_open: Funktion wird verlassen ------------")
def gate_close():
"""Ansteuern des Linearantriebes zum zufahren des Törchens"""
logging.info("----------- gate_close: Tor Schließvorgang eingeleitet -----------")
# 1. 12V Versorgung f. Linearantrieb einschalten #
GPIO.output(AC230V_12V, GPIO.LOW)
logging.info("gate_close: Netzspannung an 12V Netzteil eingeschaltet")
time.sleep(2)
# 2. Prüfen ob Tor nicht bereits geschlossen ist. Näherungsschaltersignal ist low, wenn Törchen zu
if GPIO.input(End_swtch_closed) == GPIO.LOW:
logging.info("gate_close: Prüfung Torstatus vor Schließvorgang ergab: Tor ist nicht bis Endposition geschlossen")
# Interrupt konfigurieren: Wenn Endschalter für geschlossene Torposition anspricht, dann Motor ausschalten
GPIO.add_event_detect(End_swtch_closed, GPIO.RISING, callback=end_pos_closed)
logging.info("gate_close: Interrupt durch Hallgeber in Position Zu konfiguriert")
# 3. Wenn Tor noch nicht geschlossen, Motor in Schliessrichtung einschalten. #
GPIO.output(H_brdg_EN1, GPIO.LOW)
GPIO.output(H_brdg_EN2, GPIO.HIGH)
logging.info("gate_close: Motor wurde durch H-Brücke gestartet, Richtung Position Zu")
time.sleep(20)
GPIO.remove_event_detect(End_swtch_closed)
logging.info("gate_close: Interrupt End_swtch_closed wurde gelöscht")
gate_linear_drive_off("1")
logging.info("----------- gate_close: Funktion wird verlassen ------------")
def gate_check_on_reboot(oeffnungszeit, schliesszeit):
"""Falls ein Reboot während der Torfahrzeit erfolgte kann das nicht in Endposition stehende Tor zu- oder aufgefahren werden"""
logging.info("---------- gate_check_on_reboot: Gestartet. Passt Torstatus nach Neustart zur Tageszeit? ----------")
akt_zeit = datetime.today()
jahr = akt_zeit.year
monat = akt_zeit.month
tag = akt_zeit.day
soll_zeit = datetime.strptime(schliesszeit, '%H:%M')
soll_zeit_zu = soll_zeit.replace(year=jahr, month=monat, day=tag)
soll_zeit = datetime.strptime(oeffnungszeit, '%H:%M')
soll_zeit_auf = soll_zeit.replace(year=jahr, month=monat, day=tag)
if (akt_zeit < soll_zeit_auf) or (akt_zeit > soll_zeit_zu):
logging.info("gate_check_on_reboot: gate_close() wird aufgerufen um zu prüfen ob Tor geschlossen ist")
gate_close()
elif (akt_zeit > soll_zeit_auf) and (akt_zeit < soll_zeit_zu):
logging.info("gate_check_on_reboot: gate_open() wird aufgerufen um zu prüfen ob Tor offen ist")
gate_open()
logging.info("----------- gate_check_on_reboot: Funktion wird verlassen -----------")
def main():
logging.basicConfig(
filename="/var/log/tccu.log",
level=logging.DEBUG,
style="{",
format="{asctime} [{levelname:8}] {message}",
datefmt="%Y-%m-%d %H:%M:%S")
logging.info("------------ Skript gate_open_close.py gestartet ------------")
# Tor Öffnungs- und Schließzeiten
oeffnungszeit = "09:00"
schliesszeit = "19:45"
schedule.every().day.at(oeffnungszeit).do(gate_open)
schedule.every().day.at(schliesszeit).do(gate_close)
gate_check_on_reboot(oeffnungszeit, schliesszeit)
try:
while 1:
schedule.run_pending()
time.sleep(1)
except KeyboardInterrupt:
GPIO.cleanup()
logging.info("main: keyboardinterrupt ist erfolgt, exiting")
logging.info("GPIOs wurden zurückgesetzt")
except:
GPIO.cleanup()
logging.info("main: Eine Ausnahme ist aufgetreten, exiting")
logging.info("GPIOs wurden zurückgesetzt")
if __name__ == '__main__':
main()
Code: Alles auswählen
Log Einträge nach erstmaligem Start des Skriptes am 20.08.2019:
2019-08-20 19:45:00 [INFO ] Running job Every 1 day at 19:45:00 do gate_close() (last run: [never], next run: 2019-08-20 19:45:00)
2019-08-20 19:45:00 [INFO ] ----------- gate_close: Tor Schließvorgang eingeleitet -----------
2019-08-20 19:45:00 [INFO ] gate_close: Netzspannung an 12V Netzteil eingeschaltet
2019-08-20 19:45:02 [INFO ] gate_close: Prüfung Torstatus vor Schließvorgang ergab: Tor ist nicht bis Endposition geschlossen
2019-08-20 19:45:02 [INFO ] gate_close: Interrupt durch Hallgeber in Position Zu konfiguriert
2019-08-20 19:45:02 [INFO ] gate_close: Motor wurde durch H-Brücke gestartet, Richtung Position Zu
2019-08-20 19:45:14 [INFO ] end_pos_closed: Hallgeber hat *Zu* Endlage erkannt
2019-08-20 19:45:14 [INFO ] end_pos_closed: Motor wurde von H-Brücke abgeschaltet
2019-08-20 19:45:16 [INFO ] end_pos_closed: Netzspannung für 12V Netzteil abgeschaltet
2019-08-20 19:45:22 [INFO ] gate_close: Interrupt End_swtch_closed wurde gelöscht
2019-08-20 19:45:23 [INFO ] ----------- gate_close: Funktion wird verlassen ------------
2019-08-21 09:00:00 [INFO ] Running job Every 1 day at 09:00:00 do gate_open() (last run: [never], next run: 2019-08-21 09:00:00)
2019-08-21 09:00:00 [INFO ] ----------- gate_open: Tor Öffnungsvorgang eingeleitet -----------
2019-08-21 09:00:00 [INFO ] gate_open: Netzspannung an 12V Netzteil eingeschaltet
2019-08-21 09:00:02 [INFO ] gate_open: Prüfung Torstatus vor Öffnungsvorgang ergab: Tor ist nicht bis Endposition offen
2019-08-21 09:00:02 [INFO ] gate_open: Interrupt durch Hallgeber in Position Offen konfiguriert
2019-08-21 09:00:02 [INFO ] gate_open: Motor wurde durch H-Brücke gestartet, Richtung Position Auf
2019-08-21 09:00:15 [INFO ] end_pos_open: Hallgeber hat *Offen* Endlage erkannt
2019-08-21 09:00:15 [INFO ] end_pos_open: Motor wurde von H-Brücke abgeschaltet
2019-08-21 09:00:16 [INFO ] end_pos_open: Netzspannung für 12V Netzteil abgeschaltet
2019-08-21 09:00:22 [INFO ] gate_open: Interrupt End_swtch_open wurde gelöscht
2019-08-21 09:00:23 [INFO ] ----------- gate_open: Funktion wird verlassen ------------
Letzte Log Einträge *vor* verlangsamter Ausführung:
2019-09-06 19:45:00 [INFO ] Running job Every 1 day at 19:45:00 do gate_close() (last run: 2019-09-05 19:45:23, next run: 2019-09-06 19:45:00)
2019-09-06 19:45:00 [INFO ] ----------- gate_close: Tor Schließvorgang eingeleitet -----------
2019-09-06 19:45:00 [INFO ] gate_close: Netzspannung an 12V Netzteil eingeschaltet
2019-09-06 19:45:02 [INFO ] gate_close: Prüfung Torstatus vor Schließvorgang ergab: Tor ist nicht bis Endposition geschlossen
2019-09-06 19:45:02 [INFO ] gate_close: Interrupt durch Hallgeber in Position Zu konfiguriert
2019-09-06 19:45:02 [INFO ] gate_close: Motor wurde durch H-Brücke gestartet, Richtung Position Zu
2019-09-06 19:45:15 [INFO ] end_pos_closed: Hallgeber hat *Zu* Endlage erkannt
2019-09-06 19:45:15 [INFO ] end_pos_closed: Motor wurde von H-Brücke abgeschaltet
2019-09-06 19:45:16 [INFO ] end_pos_closed: Netzspannung für 12V Netzteil abgeschaltet
2019-09-06 19:45:22 [INFO ] gate_close: Interrupt End_swtch_closed wurde gelöscht
2019-09-06 19:45:23 [INFO ] ----------- gate_close: Funktion wird verlassen ------------
2019-09-07 09:00:00 [INFO ] Running job Every 1 day at 09:00:00 do gate_open() (last run: 2019-09-06 09:00:24, next run: 2019-09-07 09:00:00)
2019-09-07 09:00:00 [INFO ] ----------- gate_open: Tor Öffnungsvorgang eingeleitet -----------
2019-09-07 09:00:00 [INFO ] gate_open: Netzspannung an 12V Netzteil eingeschaltet
2019-09-07 09:00:02 [INFO ] gate_open: Prüfung Torstatus vor Öffnungsvorgang ergab: Tor ist nicht bis Endposition offen
2019-09-07 09:00:02 [INFO ] gate_open: Interrupt durch Hallgeber in Position Offen konfiguriert
2019-09-07 09:00:02 [INFO ] gate_open: Motor wurde durch H-Brücke gestartet, Richtung Position Auf
2019-09-07 09:00:16 [INFO ] end_pos_open: Hallgeber hat *Offen* Endlage erkannt
2019-09-07 09:00:16 [INFO ] end_pos_open: Motor wurde von H-Brücke abgeschaltet
2019-09-07 09:00:17 [INFO ] end_pos_open: Netzspannung für 12V Netzteil abgeschaltet
2019-09-07 09:00:22 [INFO ] gate_open: Interrupt End_swtch_open wurde gelöscht
2019-09-07 09:00:23 [INFO ] ----------- gate_open: Funktion wird verlassen ------------
Log Eintrag bei letzter stark verlangsamter Ausführung:
2019-09-07 19:45:31 [INFO ] Running job Every 1 day at 19:45:00 do gate_close() (last run: 2019-09-06 19:45:23, next run: 2019-09-07 19:45:00)
2019-09-07 19:47:57 [INFO ] ----------- gate_close: Tor Schließvorgang eingeleitet -----------
2019-09-07 19:49:06 [INFO ] gate_close: Netzspannung an 12V Netzteil eingeschaltet
2019-09-07 19:50:38 [INFO ] gate_close: Prüfung Torstatus vor Schließvorgang ergab: Tor ist nicht bis Endposition geschlossen
2019-09-07 19:52:05 [INFO ] gate_close: Interrupt durch Hallgeber in Position Zu konfiguriert
2019-09-07 19:54:31 [INFO ] gate_close: Motor wurde durch H-Brücke gestartet, Richtung Position Zu
2019-09-07 19:55:02 [INFO ] end_pos_closed: Hallgeber hat *Zu* Endlage erkannt
2019-09-07 19:58:16 [INFO ] end_pos_closed: Motor wurde von H-Brücke abgeschaltet
2019-09-07 19:59:22 [INFO ] gate_close: Interrupt End_swtch_closed wurde gelöscht
2019-09-07 20:02:23 [INFO ] end_pos_closed: Netzspannung für 12V Netzteil abgeschaltet