Hallo zusammen.
habe mir über die Tage ein neuen pi4b+ mit dem oben genannten board zusammen gebaut.
Dort gibt es ein phyton script, welches anhand der CPU temp. die drehzal regelt !
Diese würde ich gerne in FHEM abfragen. Mit fehlt jedoch ein Punkt wo ich ansetzen könnte.
Hier mal die beiden Scripts in phyton.
1. zum steuern des fan.
#!/usr/bin/python
import pigpio
import time
servo = 13
pwm = pigpio.pi()
pwm.set_mode(servo, pigpio.OUTPUT)
pwm.set_PWM_frequency( servo, 25000 )
pwm.set_PWM_range(servo, 100)
while(1):
#get CPU temp
file = open("/sys/class/thermal/thermal_zone0/temp")
temp = float(file.read()) / 1000.00
temp = float('%.2f' % temp)
file.close()
if(temp > 30):
pwm.set_PWM_dutycycle(servo, 40)
if(temp > 50):
pwm.set_PWM_dutycycle(servo, 50)
if(temp > 55):
pwm.set_PWM_dutycycle(servo, 75)
if(temp > 60):
pwm.set_PWM_dutycycle(servo, 90)
if(temp > 65):
pwm.set_PWM_dutycycle(servo, 100)
if(temp < 30):
pwm.set_PWM_dutycycle(servo, 0)
time.sleep(1)
hier zum auslesen der drehzahl über die console
#!/usr/bin/python
# this python code is base python 2, not python 3
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
TACH = 16
PULSE = 2
WAIT_TIME = 1
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(TACH, GPIO.IN, pull_up_down=GPIO.PUD_UP)
t = time.time()
rpm = 0
def fell(n):
global t
global rpm
dt = time.time() - t
if dt < 0.005: return
freq = 1 / dt
rpm = (freq / PULSE) * 60
t = time.time()
GPIO.add_event_detect(TACH, GPIO.FALLING, fell)
try:
while True:
print "%.f RPM" % rpm
rpm = 0
time.sleep(1)
except KeyboardInterrupt:
GPIO.cleanup()
Hier noch den link zur seite mit der software.
https://wiki.geekworm.com/X735_V2.5_Software (https://wiki.geekworm.com/X735_V2.5_Software)
Wie kann man den entsprechenden gpio in fhem abfragen ?!?!
Danke im vorraus
Gruß
Sascha
Z.B. statt:
print "%.f RPM" % rpm
(oder zusätzlich ;) )
sowas:
/usr/bin/perl /opt/fhem/fhem.pl 7072 "setreading Devicename Readingname $rpm" 2>&1 > /dev/null
oder auch mittels echo und nc oder per http(s)...
Otto hat glaub ich einen Blog dazu, also wie Daten von Shell-Script nach fhem...
EDIT: z.B. https://heinz-otto.blogspot.com/2017/03/csrf-token-und-fhem.html
EDIT: siehe auch https://github.com/heinz-otto/fhemcl und https://forum.fhem.de/index.php/topic,115715.msg1100408.html#msg1100408
EDIT: es ginge/geht sicher auch das Script aufzuteilen. Also den Teil der zu Beginn immer muss (einrichten der GPIO usw.) einmal bei Systemstart auszuführen (lassen) und den Teil, wo abgefragt wird dann zyklisch per at aus fhem heraus aufrufen oder per cron... -> es gibt (wie so oft) viele Möglichkeiten ;)
Dazu dann eben telnet in fhem und ein Device was die Daten aufnimmt (zur Not ein dummy ;) )...
Allerdings würde ich die Abfrage etwas länger pausieren lassen -> sleep länger machen...
Oder eben (falls du das Shell-Script nicht laufen lassen willst) in das Python auch z.B. Telnet richtung fhem, allerdings weiß ich nicht wie man das in Python macht...
Gruß, Joachim
Danke erstmal. Werde nächstes Jahr mal schauen.
Gruß Sascha
Zitat von: MadMax-FHEM am 31 Dezember 2021, 11:50:39
EDIT: es ginge/geht sicher auch das Script aufzuteilen. Also den Teil der zu Beginn immer muss (einrichten der GPIO usw.) einmal bei Systemstart auszuführen (lassen) und den Teil, wo abgefragt wird dann zyklisch per at aus fhem heraus aufrufen oder per cron... -> es gibt (wie so oft) viele Möglichkeiten ;)
Danke für deine Ausführungen.
Es wurde ein Phyton script eingerichtet, welches beim booten des pi automatisch mit ausgeführt wird.
Wenn ich in der Console folgendes eingebe, dann wird im Sekundentakt die Umdrehung des Lüfters ausgegeben !
python /home/pi/x735-v2.5/read_fan_speed.py
Das Script habe ich oben im Post mit angehangen.
Ich wollte nur wissen, ob ich an dem Script vorbei die RPM des Lüfters abfragen kann?
Oder ob ich das Script dafür von FHEM aus aufrufen muss bzw kann.
Und wenn, dann wie ?
Generell möchte ich die RPM in ein Reading schreiben.
Genau so sollte es möglich sein, evtl. die RPM zu steuern. in 1. Linie geht es mir um die Abfrage.
Danke und Gruß
Sascha
Ah, ist mir gar nicht aufgefallen, sind ja beides python Scripts...
Dachte das zweite wäre ein Shell-Script...
Dann passt die Zeile so leider wohl nicht.
Wie man telnet mit Python macht weiß ich leider nicht...
Was ich eigenartig finde (bzw. nur unter bestimmten Bedinungen funktionieren dürfte) ist der "Autostart".
So wie ich das überflogen habe funktioniert das, wenn sich der User pi einloggt wird es gestartet.
Also nur, wenn sich tatsächlich der User pi einloggt oder eben "autologin to console" aktiviert ist (dann eben "immer")...
Wie ist das Script gedacht, irgendwie (wie geschrieben: Python ist nicht meine Welt) sieht es nach (wie du auch schreibst) sekündlicher Ausgabe aus (while Schleife).
Was passiert, wenn du das Script so abänderst (kannst ja eine Kopie anlegen):
cp /home/pi/x735-v2.5/read_fan_speed.py home/pi/x735-v2.5/read_fan_speed_once.py
[code]
#!/usr/bin/python
# this python code is base python 2, not python 3
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
TACH = 16
PULSE = 2
WAIT_TIME = 1
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(TACH, GPIO.IN, pull_up_down=GPIO.PUD_UP)
t = time.time()
rpm = 0
def fell(n):
global t
global rpm
dt = time.time() - t
if dt < 0.005: return
freq = 1 / dt
rpm = (freq / PULSE) * 60
t = time.time()
GPIO.add_event_detect(TACH, GPIO.FALLING, fell)
try:
print "%.f RPM" % rpm
GPIO.cleanup()
Dann sollte 1x die aktuelle Fan-Speed ausgegeben werden?
(ob das mit einem laufenden Script "kollidiert": keine Ahnung -> besser mal den [eh komischen] Autostart rausnehmen)
Wenn das tut, dann entweder rausfinden wie man mit Python telnet oder http(s) Aufrufe macht, dann entsprechend die Zeilen von mir anpassen und statt dem print-Befehl einbauen (wie ja bereits geschrieben).
Alternative (aber nicht sonderlich schön ;) ) das Python per bash Script aufrufen und dann meine Zeilen (angepasst) einbauen.
In etwa so:
#!/bin"bash
# sollte auch ohne vorangestelltes python gehen, dass es ein python script ist, steht ja im script selbst
speed=$(/home/pi/x735-v2.5/read_fan_speed_once.py)
# Devicename -> halt das fhem device eintragen welches den Wert erhalten soll [kann auch ein dummy sein]
# Readingname -> anpassen wie das Reading heißen soll, das den Wert erhält
/usr/bin/perl /opt/fhem/fhem.pl 7072 "setreading Devicename Readingname $speed" 2>&1 > /dev/null
Das neue bash-Script ausführbar machen (chmod +x Scriptname) und dann mal auf der Console aufrufen:
./Scriptname
(vorausgesetzt du befindest dich dort wo auch das Script ist)
EDIT: nicht vergessen, dazu ist ein telnet-Device in fhem notwendig! Ansonsten eben einen http(s) Aufruf einbauen, siehe Links...
Wenn das geht, kannst du überlegen, wie du es aufgerufen haben willst:
- zyklisch per cron
- zyklisch per at aus fhem
- ...
Beim Steuern kann man das ähnlich machen, müsste man eben nur schauen wie man Parameter an ein Python Script weiter gibt und dort dann statt des temperaturabhängigen Setzens der Geschwindigkeit eben auf den übergebenen Wert setzen...
Ich hoffe der Autostart für das "Steuer-Script" ist anders gelöst?
Weil sonst ist es wohl wie geschrieben: es wird nur autom. gestartet, wenn sich der User pi einloggt (kann nat. auch automatisch erfolgen, Einstellbar z.B. per raspi-config), ansonsten wird die Geschwindigkeit nicht geregelt...
(so sehe ich das jedenfalls)
Schöner ist nat. entweder das Python ganz auf bash umschreiben (es steuert bzw. frägt ja "nur" GPIO ab, das geht auch mit bash) oder eben die telnet oder http(s) Aufrufe Richtung fhem eben in Python programmieren...
Gruß, Joachim
Besteht die Möglichkeit das PWM Signal vom GPIO 13 mittels des Moduls RPI_GPIO auszuwerten ????
Für mich sind es im Moment "zuviele" Zwischenwege um an das Ergebnis zu kommen.
Gruß
Sascha
Zitat von: sash.sc am 02 Januar 2022, 13:43:06
Besteht die Möglichkeit das PWM Signal vom GPIO 13 mittels des Moduls RPI_GPIO auszuwerten ????
Ich weiß nicht genau wie der Wert per GPIO geliefert wird: TACHO -> Analogwert.
Keine Ahnung, ob das RPI_GPIO das kann.
Wenn du das Modul kennst: probiere es aus...
Zitat von: sash.sc am 02 Januar 2022, 13:43:06
Für mich sind es im Moment "zuviele" Zwischenwege um an das Ergebnis zu kommen.
Naja, so viele Schritte sind es auch nicht... ;)
Die "Abwandlung" des Python-Scripts ja nur, weil wir keine "Endlosschleife" brauchen/wollen (die mMn eh keinen Sinn macht: wer will sich schon auf der Console dauernd die Werte anschauen ;) ).
Der "Einbau" bzw. der Aufruf des abgewandelten Python Scripts in ein bash-Script ja nur, weil ich nicht weiß, wie man aus Python eben telnet-Aufrufe macht...
Wenn du das weißt/rauskriegst, dann einfach (wie geschrieben) das einbauen... :)
Ansonsten: was spricht gegen ausprobieren von den geposteten Dingen? 8)
Es gibt auch ein Python-fhem-Modul womit sich wohl Python-Code/-Sctipte/-... "in" fhem Module "wandeln" lassen, habe ich aber noch nicht genutzt...
Glaube das hier: https://forum.fhem.de/index.php/topic,63816.msg550395.html#msg550395
Gruß, Joachim
Hallo Joachim.
Habe es versucht jetzt mal umzusetzen. Script nach deine Vorgabe abgeändert und eigens gespeichert.
Das 2. Script angelegt und die Daten agepasst, zwecks device und reading, und ausführbar gemacht.
Habe das ganze dann in der comandbar in fhem mit
{system ("/home/pi/x735-v2.5/read_fan.sh")}
ausgeführt. Dauerte einen Moment und es kam der Wert -1 zurück.
Kein reading wurde geändert. Telnet ist auf FHEM aktiviert (Test mit iobroker).
Habe dein script nochmal angepasst.
bekomme da aber nur den Wert 0 RPM zurück
#!/usr/bin/python
# this python code is base python 2, not python 3
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
TACH = 16
PULSE = 2
WAIT_TIME = 1
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(TACH, GPIO.IN, pull_up_down=GPIO.PUD_UP)
t = time.time()
rpm = 0
def fell(n):
global t
global rpm
dt = time.time() - t
if dt < 0.005: return
freq = 1 / dt
rpm = (freq / PULSE) * 60
t = time.time()
GPIO.add_event_detect(TACH, GPIO.FALLING, fell)
try:
print "%.f RPM" % rpm
rpm = 0
except KeyboardInterrupt:
GPIO.cleanup()
Das script weclhes von fhem aufgerufen werden soll.
#!/bin/bash
# sollte auch ohne vorangestelltes python gehen, dass es ein python script ist, steht ja im script selbst
speed=$(/home/pi/x735-v2.5/read_fan_speed_once.py)
# Devicename -> halt das fhem device eintragen welches den Wert erhalten soll [kann auch ein dummy sein]
# Readingname -> anpassen wie das Reading heißen soll, das den Wert erhält
/usr/bin/perl /opt/fhem/fhem.pl 7072 "setreading testdummy rpm $speed" 2>&1 > /dev/null
Habe nochmal getestet, das script was kontinuierlich die rpm ausliest. Dort ist der 1. immer 0 rpm. Erst der 2. Wert zeigt die richtigen RPM an.
Gruß
sascha
Ok, das -1 ist normal bei Aufruf mit system ;)
Und der Aufruf mit system aus fhem heraus ist BLOCKIEREND, sollte so also nicht genutzt werden...
...außer mit einem '&' am Ende ;)
Und du hast nicht so gemacht wie geschrieben, leider...
Aber nun sind ja einige Infos da.
Wir brauchen dann wohl zumindest einen Schleifenlauf, baue ich morgen mal um...
Nur zur Sicherheit:
du hast einen dummy angelegt?
du hast ein telnet Device auf 7072 OHNE User/PW?
Was passiert, wenn du:
/usr/bin/perl /opt/fhem/fhem.pl 7072 "setreading testdummy rpm 10" 2>&1 > /dev/null
in der LINUX Console eingibst?
Oder wird nun (doch) das Reading rpm im Device testdummy gesetzt?
Gruß, Joachim
Was passiert mit diesem Script, aufgerufen auf der Linux-Console ;)
#!/usr/bin/python
# this python code is base python 2, not python 3
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
TACH = 16
PULSE = 2
WAIT_TIME = 1
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(TACH, GPIO.IN, pull_up_down=GPIO.PUD_UP)
t = time.time()
rpm = 0
def fell(n):
global t
global rpm
dt = time.time() - t
if dt < 0.005: return
freq = 1 / dt
rpm = (freq / PULSE) * 60
t = time.time()
GPIO.add_event_detect(TACH, GPIO.FALLING, fell)
while True:
print "%.f RPM" % rpm
if rpm > 0: break
rpm = 0
time.sleep(1)
GPIO.cleanup()
Es sollte laufen und einen Wert größer 0 ausgeben und dann beendet sein.
Wichtig bei Python ist wohl die "Einrückung", also das GPIO.cleanup muss wohl ganz an den Zeilenanfang...
Aber das ist nur mein aktuelles "Python-Wissen" (aus "Experimenten")... ;)
Gruß, Joachim
Über die Linux console wird das reading geschrieben.
Zitat von: sash.sc am 02 Januar 2022, 22:30:53
Über die Linux console wird das reading geschrieben.
Mit welcher Variante jetzt?
Das letzte Python von mir und eingebaut in das bash-Script?
EDIT: weil NUR das Python-Script schreibt ja (noch) kein Reading nach fhem! ;)
Du solltest (erst mal) nur das letzte Pythin Script ausführen, um zu sehen, ob denn ein rpm Wert kommt ;)
Ich denke ich habe auch das Telnet gelöst...
Jetzt muss ich aber wirklich wissen: WAS GENAU hast du probiert und WAS GENAU geht nun!
Wenn mein letztes Python (also NUR das Python!) Script auf der Linux Console einen "brauchbaren" Wert ausgibt, dann baue ich da das Telnet-Zeugs ein...
Wenn du willst, kannst du das auch gleich zyklisch lassen, also das "Original-Script" nehmen, den Timer länger machen (nicht alle Sekunde) und dann statt dem Print Befehl den Telnet-Befehl einbauen.
Dann kannst du das angepasste Original-Python-Script wieder "autostart-bar" machen.
ALLERDINGS: mir kommt die im git beschriebene "autostart-Variante" sehr "eigenartig" vor!
Daher würde ich eher das Script OHNE "Dauer-While" zyklisch per cron aufrufen...
EDIT: hier der Code für Telnet IM Python-Script
zu Beginn, gleich nach dem #!/.../python
import telnetlib
tn = telnetlib.Telnet('localhost',7072)
und statt dem Print-Befehl:
tn.write(b"setreading testdummy rpm %s\n"%rpm)
EDIT: hier mal eingebaut in meine letzte Python-Script-Version, in der Annahme, dass es funktioniert ;) (sollte 1x laufen und den aktuellen RPM nach fhem in den dummy schreiben und dann "fertig" sein)
#!/usr/bin/python
# this python code is base python 2, not python 3
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
import telnetlib
tn = telnetlib.Telnet('localhost',7072)
TACH = 16
PULSE = 2
WAIT_TIME = 1
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(TACH, GPIO.IN, pull_up_down=GPIO.PUD_UP)
t = time.time()
rpm = 0
def fell(n):
global t
global rpm
dt = time.time() - t
if dt < 0.005: return
freq = 1 / dt
rpm = (freq / PULSE) * 60
t = time.time()
GPIO.add_event_detect(TACH, GPIO.FALLING, fell)
while True:
print "%.f RPM" % rpm
if rpm > 0:
tn.write(b"setreading testdummy rpm %s\n"%rpm)
break
rpm = 0
time.sleep(1)
GPIO.cleanup()
Bin gespannt auf deine Antworten, damit es etwas klarer wird, was nun geht und was nicht (wäre besser, wenn du genau machen würdest was ich schreibe oder zumindest schreiben würdest WAS GENAU DU WOMIT GENAU gemacht hast und WIE GENAU das Ergebnis war ;) )
Gruß, Joachim
Zitat von: MadMax-FHEM am 02 Januar 2022, 22:11:39
/usr/bin/perl /opt/fhem/fhem.pl 7072 "setreading testdummy rpm 10" 2>&1 > /dev/null
in der LINUX Console eingibst?
Gruß, Joachim
In der Linux Console wird damit das reading in testdummy geschrieben mit dem Wert 10.
Habe dann das Phyton script so angepasst bzw übernommen wie aus deinem lestzten Post.
#!/usr/bin/python
# this python code is base python 2, not python 3
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
import telnetlib
tn = telnetlib.Telnet('localhost',7072)
TACH = 16
PULSE = 2
WAIT_TIME = 1
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(TACH, GPIO.IN, pull_up_down=GPIO.PUD_UP)
t = time.time()
rpm = 0
def fell(n):
global t
global rpm
dt = time.time() - t
if dt < 0.005: return
freq = 1 / dt
rpm = (freq / PULSE) * 60
t = time.time()
GPIO.add_event_detect(TACH, GPIO.FALLING, fell)
while True:
print "%.f RPM" % rpm
if rpm > 0:
tn.write(b"setreading testdummy rpm %s\n"%rpm)
break
rpm = 0
time.sleep(1)
GPIO.cleanup()
Und es in der Console ausgeführt.
1. Wert 0rpm
2. Wert 2544 rpm
Edit:
Habe gesehen, dass das angepasste Script auch den Wert in testdummy schreibt. ;D ;D ;D ;D
Wie ruft man aus FHEM das Script auf ?
DANKE !!!!!!!!
Gruß
Sascha
Hallo Sascha,
freut mich, war nicht sicher, ob mein Python-Zeugs auch tut ;) :)
Warum nicht per cron ausführen lassen?
Aber wenn du (unbedingt) aus fhem raus willst:
Script nach /opt/fhem "schieben" (oder dort in einen Unterordner wenn du willst):
sudo mv /home/pi/Script.py /opt/fhem/
Dann nat. die Besitzrechte korrigieren:
sudo chown fhem:dialout /opt/fhem/*.py
sollte zwar schon ausführbar sein aber sicher ist sicher ;)
sudo chmod +x /opt/fhem/*.py
ANMERKUNG: besser statt *.py den Scriptnamen ausschreiben! (aber es sollte unter /opt/fhem/ nicht allzuviele py-Scripte geben ;) )
Aufruf dann aus fhem z.B. per at:
define atRPM at *00:01:00 "/opt/fhem/Script.py"
(hier geht nat. *.py nicht ;) )
Somit sollte alle Minute (oder ändern) das Script aufgerufen werden und den Wert setzen...
Wenn du willst, kannst du das Python-Script auch erst mal (nach dem Verschieben etc.) aus fhem aufrufen (bevor du das at definierst):
"/opt/fhem/Script.py"
INKL.!! Der Anführungszeichen in FhemWeb...
U.U. kann es sein, dass fhem ein Python-Script nicht einfach so aufrufen kann (z.B. python nicht gefunden etc.), dann mal folgendes probieren:
which python
Das dann "merken" (kopieren) und VOR den Scriptaufruf dazu nehmen:
"KopiertesHier /opt/fhem/Script.py"
Sollte dann sowas ähnliches ergeben:
"/usr/bin/python /opt/fhem/Script.py"
(evtl. dann die #! Zeile aus dem Python Script entfernen)
Es kann allerdings sein, dass (ab und an) "komische" Sachen im fhem-Log stehen, da bei einem Aufruf aus fhem heraus Fehler etc. im fhem-Log landen (auch verbose hilft dann nicht).
Wie man das bei Python-Scripten unterdrücken kann: keine Ahnung...
Es ginge auch das Script von einer Unit-Datei (Service-Start-Script) aufzurufen und dann wieder eine Endlos-Schleife einbauen...
Liegt an dir...
Gruß, Joachim
Zitat von: MadMax-FHEM am 03 Januar 2022, 16:32:07
Aufruf dann aus fhem z.B. per at:
define atRPM at *00:01:00 "/opt/fhem/Script.py"
Hallo Joachim.
Also, per DOIF und at geht es nicht.
Bekomme dann folgende Meldung im LOG File
RuntimeError: Not running on a RPi!
GPIO.setup(TACH, GPIO.IN, pull_up_down=GPIO.PUD_UP)
File "/opt/fhem/RPM/read_fan_speed_once.py", line 16, in <module>
Traceback (most recent call last):
Habe das ganze dann per crontab angelegt, im Minutentakt.
Das funktioniert......
Gruß
Sascha
Hm...
Wie hast du cron eingerichtet?
Als User pi?
(oder global/system, dann verm. root)
Evtl. darf der User fhem nichts mit GPIO machen, evtl. müsste man den User fhem in eine bestimmte Gruppe stecken, da bin ich aber leider überfragt... :-\
EDIT: du kannst ja mal schauen wo der User pi überall drin steckt ;)
groups pi
Geht denn:
"/opt/fhem/RPM/read_fan_speed_once.py"
in FhemWeb?
(würde aber erwarten, dass nicht, weil so wird es ja per at/DOIF aufgerufen)
Wenn es für dich so passt, dann lass es...
...bzw. ist die Variante es vom System aus aufrufen zu lassen eh "besser"... 8)
Wenn es nun (für dich) funktioniert, setzt du dann noch ein [gelöst] davor, danke.
Wenn nicht: was fehlt?
Gut das "Ansteuern" ist noch gewünscht...
Da wird allerdings verm. das GPIO-Problem wieder auftauchen...
Aber auch hier würde ich das durch das System machen lassen, da ja abhängig von der Temperatur geregelt wird.
Wie würdest du das mit fhem machen wollen?
Temperatur mittels System-Aufrufen abfragen und dann per Python-Script den Lüfter-Speed setzen?
Etwas "umständlich", oder? ;)
Gruß, Joachim
Danke für Deine Hilfe.
Der AUfruf mit den Anführungszeichen funktioniert nicht im FHEMWEB, aber egal.
Habe es in einen cronjobvom system (sudo crontab) eingetragen.
@reboot python /home/pi/x735-v2.5/pwm_fan_control.py
@reboot ntpdate -s 0.de.pool.ntp.org
0 */12 * * * ntpdate -s 0.de.pool.ntp.org
* * * * * /opt/fhem/RPM/read_fan_speed_once.py
beim booten wird auch das im ersten post genannte python script für die lüfterkontrolle aufgerufen.
Die Installationsanweisung gab der Hersteller.
Ich denke dass es reicht im Minutentakt den Lüfter abzufragen.
Ich habe auch mal mit den Werten für die Temp.abfrage gespielt bzw. dann das Leistunglevel angepasst um zu schauen, ob die Drehzahl sich ändert. Das funktioniert auch ohne Probleme.
Es wäre "nice to Have" den PWM/Tacho Pin abzufragen und das ganze über FHEM zu steuern. Aber auch nur weil man es evtl. könnte.
Aber so macht es auch seinen Job.
Mit FEHM würde ich das ganze über ein DOIF realisieren. Temp.grenzen gestaffelt und dann entsprechend die Drehzahl setzen.
Dank Deiner Unterstützung funktiniert es ganz gut mit der Abfrage.
Danke nochmal
Gruß
Sascha
P.S.: Für die, die es interessiert. Beim booten wird ein python Script aufgerufen, welches dei CÜU Temp. abfragt.
Das Script fragt regelmäßig die Temp. und passt das PWM (Taktung des Lüfters).
Abgefragt wird die Drehzal mit einem 2. Pythonscript. Das Orginal wurde von Joachim angepasst, dass keine Dauerschleife läuft.
Wenn der Rückgabewert der Drehzal größer 0 ist, dann wird der Wert über telnet in das Device mit dem Reading geschrieben.
Und die Abfrage ist beendet.
Das 2. Script wird über ein crontab vom system im Minutentakt aufgerufen und wieder das Reading geschrieben im entsprechenden Device.
Die Drehzahl frage ich ab, um zu schauen wie der Lüfter sich verhält, als Ergänzung zur RPI Systemvisualisierung im FEHM.
Hallo MadMax-FHEM
Ich bräuchte nochmal deine Hilfe.
Ich habe mein System von buster auf bullseye geupdatet. Dabei wurde python2 entfernt.
Jetzt versuche ich das Script, welches die Drehzahl in fhem schreibt, umzuschreiben.
Ein Teil klappt schonmal. Es hakt aber hier.
pi@raspberrypi:~/x735-v2.5 $ python3 read_fan_speed_once.py
0 RPM
2292 RPM
Traceback (most recent call last):
File "/home/pi/x735-v2.5/read_fan_speed_once.py", line 37, in <module>
tn.write(b"setreading testdummy state %s\n"%rpm)
TypeError: %b requires a bytes-like object, or an object that implements __bytes__, not 'float'
hier das teilweise angepasste script
#!/usr/bin/python
# this python code is base python 2, not python 3
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
import telnetlib
tn = telnetlib.Telnet('localhost',7072)
TACH = 16
PULSE = 2
WAIT_TIME = 1
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(TACH, GPIO.IN, pull_up_down=GPIO.PUD_UP)
t = time.time()
rpm = 0
def fell(n):
global t
global rpm
dt = time.time() - t
if dt < 0.005: return
freq = 1 / dt
rpm = (freq / PULSE) * 60
t = time.time()
GPIO.add_event_detect(TACH, GPIO.FALLING, fell)
while True:
print("%.f RPM" % rpm)
if rpm > 0:
tn.write(b"setreading testdummy state %s\n"%rpm)
break
rpm = 0
time.sleep(1)
GPIO.cleanup()
Problem ist bei dem teil unten mit dem schreiben in den testdummy
Gruß
Sascha
Ich weiß nicht, ob ich da viel helfen kann, leider.
Ich hab auch nur nach Python Telnet gegoogelt und bin dann bei dem Code gelandet.
Also "telnetlib"...
Evtl. dort mal schauen was man machen kann.
Oder in Python schauen, wie man den Datentyp "wandelt"...
Ich kann mal schauen aber ich bin jetzt auch kein Python Programmierer...
Gruß, Joachim
Ich weiß es ist schon ne Weile her...
...evtl. auch gar nicht mehr interessant aber ich dachte mir: was soll's ;)
Ich habe mir kürzlich ein POE-Hat für meinen PI besorgt, eines wo man alle GPIO noch nutzen kann :)
(weil ich muss ja mein EnOcean-Funkmodul da irgendwie drauf kriegen)
Was ich bislang an POE-Adaptern hatte war Mist...
...hoffe der hier ist besser...
So, nun aber:
der Hat steckt großflächig über dem PI und hat (daher) einen Lüfter ;)
Erste Idee war den Lüfter rauszubauen, dann ist zumindest mal nicht komplett "verdeckt"...
...dann dachte ich mir, ach doch mal schauen wegen Lüftersteuerung :)
Zunächst einfach nach Befehlen gesucht und nur mittels an/aus, das war dann wieder bash-Script.
Da Daten von fhem zu holen und hin zu schreiben konnte ich ja schon.
-> schnell fertig
Aber nicht so schön...
Dann weiter gesucht und hierauf gestoßen: https://www.raspberry-buy.de/Tutorial_Kuehlung_Luefterregelung_am_Raspberry_Pi.html
Das Script hat mich dann an den Thread hier erinnert und da dachte ich mir, versuch's doch mal...
So, nun aber wirklich ;)
Ich habe das Script angepasst und kann Parameter (Temperaturwerte/Lüftergeschwindigkeit) aus fhem auslesen und auch Temperatur und Lüftergeschwindigkeit an fhem zurück geben.
Z.B. folgender dummy (bei mir ist es ein AptToDate-Device / ist aber egal)
defmod fhem_Server dummy
attr fhem_Server userattr my_fanSettingsLow my_fanSettingsMed my_fanSettingsHigh
attr fhem_Server alias FHEM Server
attr fhem_Server icon system_fhem
attr fhem_Server my_fanSettingsHigh 55,100
attr fhem_Server my_fanSettingsLow 40,50
attr fhem_Server my_fanSettingsMed 45,75
Über die Attribute kann man (on the fly) einstellen wann welche Lüftergeschwindigkeit laufen soll:
my_fanSettingsHigh 55,100
my_fanSettingsLow 40,50
my_fanSettingsMed 45,75
Vorne die Temperatur und dahinter, durch Komma getrennt, die Lüftergeschwindigkeit.
Hier das Script:
#! /usr/bin/python3
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
import os
import telnetlib
# telnet connection to fhem
tn = telnetlib.Telnet('localhost',7072)
# Zählweise der Pins auf GPIO-Nummern festlegen
GPIO.setmode(GPIO.BCM);
# Warnmeldungen ausschalten
GPIO.setwarnings(False);
# Konstanten definieren
FAN_OUT_PIN = 13 # Lüfter-Ausgang (FAN_OUT_PIN) ist GPIO33 (PIN33)
FAN_STARTUP_TIME=1 # fan speedup time used in startFan()
# variables for fhem -> adopt to your needs!
FHEM_SERVER="fhem_Server"
ATTR_FAN_SETTINGS_LOW="my_fanSettingsLow"
ATTR_FAN_SETTINGS_MED="my_fanSettingsMed"
ATTR_FAN_SETTINGS_HIGH="my_fanSettingsHigh"
READING_FAN_SPEED="fanSpeed"
READING_FAN_SPEED_PERCENT="fanSpeedPercent"
READING_CPU_TEMP="cpu_temp"
TASK_SLEEP_TIME=10
DEBUG_OUTPUT=False # True: output to console | False: no output (service mode)
# GPIO Eingänge definieren
GPIO.setup(FAN_OUT_PIN, GPIO.OUT) # definiert unseren Lüfter-Pin als Ausgang
GPIO.output(FAN_OUT_PIN, GPIO.LOW) # setzt unseren Ausgang auf Low (0 => 0V)
# PWM-Channel initialisieren
pwm1 = GPIO.PWM(FAN_OUT_PIN, 10) # Frequenz ab 10 Hz funktioniert ganz gut
pwm1.start(100.0)
# Funktionen definieren
def debugOut(text="", context="general"): # debug output (if set to True)
if DEBUG_OUTPUT:
output = "DEBUGOUT: " + str(context) + " | " + str(text)
print(output)
def getCpuTemp(): # ermittelt die CPU-Temperatur und gibt sie als String zurück
raw = os.popen("vcgencmd measure_temp").readline()
cpuTemp = (raw.replace("temp=","").replace("'C\n",""))
debugOut(cpuTemp, "getCpuTemp")
return(cpuTemp)
def sendCpuTemp(cpuTemp): # send CPU temp to fhem
debugOut(cpuTemp, "sendCpuTemp")
tn.write(bytes("setreading " + FHEM_SERVER + " " + READING_CPU_TEMP + " " + str(cpuTemp) + "\n", encoding='utf-8'))
return
def setFanDuty(sfdc = 0.0): # Setzt den Dutycycle für den Lüfter
pwm1.ChangeDutyCycle(sfdc)
debugOut(sfdc, "setFanDuty")
return
def startFan(): # Setzt den Lüfter für 1s Anlaufzeit auf 100%
fanOutput = 100.0
setFanDuty(fanOutput)
debugOut("Anlaufzeit: " + str(FAN_STARTUP_TIME), "startFan")
time.sleep(FAN_STARTUP_TIME)
return
def readTempLow(): # read low temp from fhem
tn.write(bytes("{AttrVal('" + FHEM_SERVER + "','" + ATTR_FAN_SETTINGS_LOW + "','42,55')}\n",encoding='utf8'))
raw = ((tn.read_some()).decode('utf-8').split(","))[0]
debugOut(raw, "readTempLow")
return(raw)
def readTempMed(): # read medium temp from fhem
tn.write(bytes("{AttrVal('" + FHEM_SERVER + "','" + ATTR_FAN_SETTINGS_MED + "','45,80')}\n",encoding='utf8'))
raw = ((tn.read_some()).decode('utf-8').split(","))[0]
debugOut(raw, "readTempMed")
return(raw)
def readTempHigh(): # read high temp from fhem
tn.write(bytes("{AttrVal('" + FHEM_SERVER + "','" + ATTR_FAN_SETTINGS_HIGH + "','55,100')}\n",encoding='utf8'))
raw = ((tn.read_some()).decode('utf-8').split(","))[0]
debugOut(raw, "readTempHigh")
return(raw)
def readSpeedLow(): # read fan speed for temp low from fhem
tn.write(bytes("{AttrVal('" + FHEM_SERVER + "','" + ATTR_FAN_SETTINGS_LOW + "','42,55')}\n",encoding='utf8'))
raw = (tn.read_some()).decode('utf-8').split(",")
raw = raw[1].replace('\n', '')
debugOut(raw, "readSpeedLow")
return(raw)
def readSpeedMed(): # read fan speed for temp medium from fhem
tn.write(bytes("{AttrVal('" + FHEM_SERVER + "','" + ATTR_FAN_SETTINGS_MED + "','45,80')}\n",encoding='utf8'))
raw = (tn.read_some()).decode('utf-8').split(",")
raw = raw[1].replace('\n', '')
debugOut(raw, "readSpeedMed")
return(raw)
def readSpeedHigh(): # read fan speed for temp high from fhem
tn.write(bytes("{AttrVal('" + FHEM_SERVER + "','" + ATTR_FAN_SETTINGS_HIGH + "','55,100')}\n",encoding='utf8'))
raw = (tn.read_some()).decode('utf-8').split(",")
raw = raw[1].replace('\n', '')
debugOut(raw, "readSpeedHigh")
return(raw)
def sendFanSpeed(speed): # send fan speed to fhem
debugOut(str(speed), "sendFanSpeed")
tn.write(bytes("setreading " + FHEM_SERVER + " " + READING_FAN_SPEED + " " + str(speed) + "\n", encoding='utf-8'))
tn.write(bytes("setreading " + FHEM_SERVER + " " + READING_FAN_SPEED_PERCENT + " " + str(speed) + "%\n", encoding='utf-8'))
# Hauptprogramm starten
cpuTemp = getCpuTemp()
debugOut("CPU-Temperatur: " + str(cpuTemp) + " °C")
fanOutput = 0.0
while True:
cpuTemp = float(getCpuTemp())
# read settings from fhem
fanTempLow = float(readTempLow())
fanTempMed = float(readTempMed())
fanTempHigh = float(readTempHigh())
fanSpeedLow = float(readSpeedLow())
fanSpeedMed = float(readSpeedMed())
fanSpeedHigh = float(readSpeedHigh())
# calculate fan speed according to settings
if cpuTemp < fanTempLow:
fanOutput = 0.0
elif cpuTemp > fanTempHigh:
fanOutput = fanSpeedHigh
elif cpuTemp > fanTempMed:
if fanOutput < fanSpeedMed:
startFan()
fanOutput = fanSpeedMed
elif cpuTemp > fanTempLow - 0.1:
if fanOutput < fanSpeedLow:
startFan()
fanOutput = fanSpeedLow
setFanDuty(fanOutput) # set calculated fan speed
# send data to fhem
sendFanSpeed(fanOutput)
sendCpuTemp(cpuTemp)
debugOut("CPU-Temperatur: " + str(cpuTemp) + " °C / Lüfterausgang: " + str(fanOutput) + "%" + " tl:" + str(fanTempLow) + " tm:" + str(fanTempMed) + " th:" + str(fanTempHigh) + " | sl:" + str(fanSpeedLow) + " sm:" + str(fanSpeedMed) + " sh:" + str(fanSpeedHigh))
time.sleep(TASK_SLEEP_TIME) # wait until next loop
pwm1.stop()
Kann man sicher noch verbessern aber für mich taugt das erst mal...
Wenn man im Script dann noch debugOutput auf False setzt und folgendes Unit-File unter /etc/systemd/system (z.B. fan-control.service) platziert und den Dienst entsprechend aktiviert und startet, dann läuft das Script als daemon :)
[Unit]
Description=fan control
After=fhem.service
Requires=fhem.service
[Service]
ExecStart=/opt/fhem/own-scripts/001-maintenance/fan-control.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EDIT: Unit File bearbeitet. Bin aber immer noch nicht sicher, ob das so tut... Weil ja die Abhängigkeit zu fhem. Evtl. besser im Python abfangen? Evtl. später... Mal sehen...
Pfad zum Script nat. anpassen ;)
Läuft aktuell unter Bullseye.
Ich musste (interessanterweise) nichts weiter installieren oder tun...
Gruß, Joachim
Danke
Nach langer Zeit habe ich es ausprobiert, und es funktioniert.
Musste erstmal überlegen wie das ganze als daemon einzubinden ist. Aber jetzt geht´s.
Kann man das ganze auch von der Drehzahl abhängig machen, ohne feste Werte ?
Wenn ja, wie
Danke nochmal
Zitat
Kann man das ganze auch von der Drehzahl abhängig machen, ohne feste Werte ?
Wenn ja, wie
Verstehe nicht was du meinst...
Du kannst für niedrige, mittlere und hohe Temperatur angeben
1. was bedeutet niedrig, mittel bzw. hoch (also welche Temp)
2. mit welcher Drehzahl der Lüfter dann jeweils laufen soll...
Einstellbar per Attribut.
Die aktuelle Temp und Drehzahl steht dann im Dummy (wo auch die Attribute hängen)...
EDIT:
Zitat
Über die Attribute kann man (on the fly) einstellen wann welche Lüftergeschwindigkeit laufen soll:
my_fanSettingsHigh 55,100
my_fanSettingsLow 40,50
my_fanSettingsMed 45,75
Vorne die Temperatur und dahinter, durch Komma getrennt, die Lüftergeschwindigkeit.
my_fanSettingsHigh Temperatur ab wann high ist,Drehzahl für hohe Temp
Zitat
attr fhem_Server userattr my_fanSettingsLow my_fanSettingsMed my_fanSettingsHigh
attr fhem_Server my_fanSettingsHigh 55,100
attr fhem_Server my_fanSettingsLow 40,50
attr fhem_Server my_fanSettingsMed 45,75
Das mit daemon steht doch auch beschrieben?
Zumindest für Systeme mit systemd...
EDIT: gut, ich bin bzgl. der Abhängigkeit zu fhem immer noch unschlüssig... Aber ich glaube so läuft das bei mir aktuell? (muss ich mal schauen)
Gruß, Joachim
Du hast ja 3 Stufen für die Drehzahl fest gelegt.
Ich meine das ganze stufenlos, wie ein frequenzumrichter, Regeln zu lassen.
Notfalls könnte ich noch mehrere Abstufungen einbauen, um es ein bisschen feiner zu gestalten.
Gruß und danke
Sascha
Ah, ok.
Naja, Basis (von dir und dann auch mir) war ja das Python-Script.
Das ist im Prinzip eben geblieben (3 Stufen), ich habe es nur per fhem parametrisierbar gemacht und auch eine Rückmeldung an fhem eingebaut.
Wenn du einen brauchbaren Algorithmus hast für stufenlos, kann man das sicher einbauen...
Allerdings muss ich anmerken (nachdem es bereits einige zeit läuft):
der Lüfter läuft quasi konstant mit 55 Umdrehungen (also mittlere Stufe)
(Temp.: so um die 40+Grad)
An einem anderen PI (ein PI4) läuft ein "großer Lüfter" (ist so ein "stackable Gehäuse" / also für mehrere PI "übereinander", habe aber nur einen drin stecken) angeschlossen an 3,3V, also "dauer-an".
Die Temp des PI liegt so beo 40Grad.
Daher war/ist das eine nette Spielerei, allerdings überlege ich, ob ich nicht einfach den Lüfter auch an 3,3V durchlaufen lasse...
Bzw. bei "stufenlos" kommt noch dazu, dass die "Bastellösung" hier ja von einem Lüfter ausgeht, der eigentlich nicht gesteuert werden kann (daher ja die "Transistorendstufe"), drum ja auch der "Anlaufschubbs", wenn die Geschwindigkeit geändert wird -> startFan()
Evtl. wäre es dann besser einen steuerbaren Lüfter (mit 3 Anschlüssen: +/- pwm) zu nehmen...
Gruß, Joachim