Temperatur-Lüfter

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
T4m4go
User
Beiträge: 38
Registriert: Samstag 3. Juli 2021, 16:54

Vielen Dank!
Die map Funktion wollte ich schon verwenden, nur nicht für die Lüfter, sondern für das Poti.
Sonst kann ich ja keine Temperatur einstellen, ohne den Pi anzuschließen.
T4m4go
User
Beiträge: 38
Registriert: Samstag 3. Juli 2021, 16:54

Code: Alles auswählen

from machine import ADC, Pin
from machine import PWM
from time import sleep
from dht import DHT11, InvalidChecksum


fan = PWM(Pin(16))
fan.freq(25000)
pot = ADC(26)

DHTpin = Pin(21, Pin.OUT, Pin.PULL_DOWN)

def map(x, in_min, in_max, out_min, out_max):
    return int((x-in_min) * (out_max-out_min) / (in_max - in_min) + out_min)

while True:
    #tempp = map(pot.read_u16(),288, 65535,0,40)
    set_temperature = 20 #tempp
    #print("Tempp:", tempp, "ADC, ", pot.read_u16())
    start_speed = 1000
    kp = 10000  # Skalierungsfaktor stellt die Beziehung zwischen Temperatur und Geschwindigkeit dar

    sensor = DHT11(DHTpin)
    sleep(1.5)
    t = sensor.temperature
    h = sensor.humidity
        # hier wird eigentlich die Temperatur vom Sensor gelesen
        

    temp_difference = set_temperature - t

    speed_difference = -temp_difference * kp
    
    new_speed = round(start_speed) + round(speed_difference)

        # hier wird mit 'new_speed' die neue Geschwindigkeit für den Lüfter eingestellt
    fan.duty_u16(new_speed)
    
    if new_speed <= 0:
        fan.duty_u16(1000)
        
    if new_speed > 65000:
        fan.duty_u16(65000)
        
    print(t, "C")
    print(h, "%")
    print(fan.duty_u16(), "DutyCycle")  
Das Alte jetzt richtig dargestellt.
T4m4go
User
Beiträge: 38
Registriert: Samstag 3. Juli 2021, 16:54

Also das umgeschriebene Script funktioniert nicht, da es mit diesen min max Werten nicht stimmt.
Durch die Rechnung ergeben sich nämlich auch bei einer höheren gewünschten Temperatur zur tatsächlichen Temperatur eine Differenz, die die Lüftergeschwindigkeit erhöht - das wollte ich nicht, da es keinen Sinn macht.
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wenn die Temperaturdifferenz negativ ist, sollte auch die Geschwindigkeit negativ werden (spaetestens nach einer kurzen Zeit). Das ist logisch, weil natuerlich aus einem kuehlen dann ein heizen werden muesste. Das kann dein Luefter natuerlich nicht, aber der Algorithmus an sich stimmt. Alles, was du tun kannst, ist bei negativen Werten einfach die PWM auf 0 zu setzen.
T4m4go
User
Beiträge: 38
Registriert: Samstag 3. Juli 2021, 16:54

Das habe ich ja bei meinem Script gemacht (auf 1000).
Das Nächste wäre eine Veränderung des Potis zu erkennen und auf meinem LCD Display nur bei Veränderung die eingestellte Temperatur anzuzeigen.
Hab es schon mit button press... probiert, funktioniert aber nicht.
Ich hab noch add_action_detect (oder so ähnlich) im Kopf, finde dazu aber nichts.
Die print Geschichten sind nur zum probieren.
Mein Script mit dem LCD Display:

Code: Alles auswählen

from machine import I2C, ADC, Pin
from machine import PWM
from machine_i2c_lcd import I2cLcd
from time import sleep
from dht import DHT11, InvalidChecksum

i2c = I2C(0, sda=Pin(16), scl=Pin(17), freq=400000)
i2c_scan=i2c.scan()[0]
i2c_scan_hex=hex(i2c_scan)

I2C_ADDR = i2c_scan

lcd = I2cLcd(i2c, I2C_ADDR, 2, 16)

fan = PWM(Pin(18))
fan.freq(25000)
pot = ADC(26)

DHTpin = Pin(21, Pin.OUT, Pin.PULL_DOWN)

def map(x, in_min, in_max, out_min, out_max):
    return int((x-in_min) * (out_max-out_min) / (in_max - in_min) + out_min)
     
while True:
    tempp = map(pot.read_u16(),288, 65535,0,40)
    set_temperature = tempp
    print("Tempp:", tempp, "ADC, ", pot.read_u16())
    start_speed = 1000
    kp = 10000  # Skalierungsfaktor stellt die Beziehung zwischen Temperatur und Geschwindigkeit dar

    sensor = DHT11(DHTpin)
    sleep(1.5)
    t = sensor.temperature
    h = sensor.humidity
        # hier wird eigentlich die Temperatur vom Sensor gelesen
    lcd.hide_cursor()
    lcd.move_to(0,0)
    lcd.putstr("Temp:    " + str(t) + " C")
    lcd.move_to(0,1)
    lcd.putstr("Luftf.:  " + str(h) + " %")

    temp_difference = set_temperature - t

    speed_difference = -temp_difference * kp
    
    new_speed = round(start_speed) + round(speed_difference)

        # hier wird mit 'new_speed' die neue Geschwindigkeit für den Lüfter eingestellt
    fan.duty_u16(new_speed)
    
    if new_speed <= 0:
        fan.duty_u16(1000)
        
    if new_speed > 65000:
        fan.duty_u16(65000)
        
    print(t, "C")
    print(h, "%")
    print(fan.duty_u16(), "DutyCycle")
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich verstehe deine Frage nicht.
T4m4go
User
Beiträge: 38
Registriert: Samstag 3. Juli 2021, 16:54

Wenn sich der Analog Wert des Potis beim drehen verändert (egal wie) soll auf meinem Display die eingestellte Temperatur (in diesem Fall tempp) angezeigt werden.
Also quasi

Code: Alles auswählen

 lcd.putstr(str(tempp) + " C") 
, wenn ich tempp verändere, damit ich beim Einstellen auch sehe was ich einstelle und danach das Display wieder wie gewohnt die tatsächliche Temperatur und Luftfeuchtigkeit anzeigt(wie schon im Script:

Code: Alles auswählen

lcd.hide_cursor()
    lcd.move_to(0,0)
    lcd.putstr("Temp:    " + str(t) + " C")
    lcd.move_to(0,1)
    lcd.putstr("Luftf.:  " + str(h) + " %")
    
).
Zu dieser Veränderung des poti oder eingestellten Temperatur(tempp) - Wertes hab ich schon mal sowas wie add_action_detect ( oder so ähnlich) gesehen.
Zuletzt geändert von T4m4go am Donnerstag 25. November 2021, 15:27, insgesamt 1-mal geändert.
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und was geht nicht? Was ist denn da unklar? Du liest das poti ein, du schreibst auch schon Werte auf das Display, was ist jetzt die Huerde, den Sollwert zu schreiben?
T4m4go
User
Beiträge: 38
Registriert: Samstag 3. Juli 2021, 16:54

Der Sollwert soll nur am Display angezeigt werden, wenn er verändert wird.
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Warum? Dem Display ist doch egal, wenn du das einfach andauernd neu schreibst. Dein Monitor schreibt auch andauernd die Pixel neu, waehrend du nichts tust.
T4m4go
User
Beiträge: 38
Registriert: Samstag 3. Juli 2021, 16:54

Das Display ist 2x16, die 2 Spalten sind belegt und ich will nicht, dass es die ganze zeit hin und her springt.
Dazu müsste ich dann auch noch sleep einbauen und dann verzögert sich alles.
Mit erstellen von Threads oder usyncio kenn ich mich nicht aus, nur habe ich schonmal irgendwo, irgendwann bei einem Raspberry Pi 4 Projekt irgendwas mit add_action_detect verwendet, aber das ist ja leider nicht dasselbe wie microPython.
T4m4go
User
Beiträge: 38
Registriert: Samstag 3. Juli 2021, 16:54

Natürlich kann ich es jetzt auch alles auf eine "Seite" des Dislpays quetschen, sodass es funktioniert, aber das will ich nun mal nicht.
Ich würde gerne wissen ob es sowas gibt und wie man es verwendet.
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

add_action_detect funktioniert nicht bei analogen Werten. Das geht nur fuer digitale Ereignisse (Flankenwechsel). Und persoenlich wuerde ich auch alles gleichzeitig darstellen, weil es nunmal wichtig ist.

Wenn du sowas unbedingt willst, dann musst du das eben selbst programmieren - merk dir den alten Wert, und vergleiche ihn mit dem neuen. Wenn der neue signifikant (analog kann rauschen) anders ist, dann stellst du den dar. Dazu muss auch noch eine Timeout-Loesung, d.h. du musst den neuen Wert fuer eine gewisse Weile anzeigen.

Code: Alles auswählen

old_pot_value = 12345679 # sehr wichtig, muss genau diese Wert sein...
while True:
     new_pot_value = ...
     if abs(new_pot_value - old_pot_value) > 0.1:
             old_pot_value = new_pot_value
             show_set_point_timeout = time.time() + TIMEOUT
     if time.time() > show_set_point_timeout
             # show Temp & Humidity
     else:
             # show set point
T4m4go
User
Beiträge: 38
Registriert: Samstag 3. Juli 2021, 16:54

Ich habe es ausprobiert und ich komme damit nicht zurecht.
Wie muss ich das jetzt einbauen? Was weise ich old_pot_value zu?
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Was heisst du kommst nicht zurecht? Wie sieht der Code aus, welche Fehler gibt es?
T4m4go
User
Beiträge: 38
Registriert: Samstag 3. Juli 2021, 16:54

Ich weiß nicht was ich old_pot zuweisen soll
__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich sehe gerade, ich habe einen Tippfehler. Es muss old_pot_value heissen..... habe es korrigiert. Ein Minimum an selbst denken ist aber gerne genommen.
T4m4go
User
Beiträge: 38
Registriert: Samstag 3. Juli 2021, 16:54

Jetzt merke ich, dass ich die 1. Zeile des Codes übersehen habe.
T4m4go
User
Beiträge: 38
Registriert: Samstag 3. Juli 2021, 16:54

Ich hab jetzt schon Time und from machine Timer importiert aber er kann TIMEOUT nicht zuweisen.
Muss ich dafür einen Wert einsetzen?
Wenn ich einen Wert einsetze zeigt das Display nichts Verständliches an und mit clear() gar nichts mehr.

Code: Alles auswählen

from machine import I2C, ADC, Pin
from machine import PWM, Timer
from machine_i2c_lcd import I2cLcd
from time import sleep
from dht import DHT11, InvalidChecksum
import time

i2c = I2C(0, sda=Pin(16), scl=Pin(17), freq=400000)
i2c_scan=i2c.scan()[0]
i2c_scan_hex=hex(i2c_scan)

I2C_ADDR = i2c_scan

lcd = I2cLcd(i2c, I2C_ADDR, 2, 16)

fan = PWM(Pin(18))
fan.freq(25000)
pot = ADC(26)

DHTpin = Pin(21, Pin.OUT, Pin.PULL_DOWN)

def map(x, in_min, in_max, out_min, out_max):
    return int((x-in_min) * (out_max-out_min) / (in_max - in_min) + out_min)
     
while True:
    tempp = map(pot.read_u16(),288, 65535,0,40)
    #set_temperature = tempp
    print("Tempp:", tempp, "ADC, ", pot.read_u16())
    
    start_speed = 1000
    kp = 10000  # Skalierungsfaktor stellt die Beziehung zwischen Temperatur und Geschwindigkeit dar

    sensor = DHT11(DHTpin)
    sleep(1.5)
    t = sensor.temperature
    h = sensor.humidity
        # hier wird eigentlich die Temperatur vom Sensor gelesen
    #lcd.hide_cursor()
    #lcd.move_to(0,0)
    #lcd.putstr("Temp:     " + str(t) + " C")
    #lcd.move_to(0,1)
    #lcd.putstr("Luftf.:   " + str(h) + " %")
    old_pot_value = 12345679
    if abs(tempp - old_pot_value) > 0.1:
        old_pot_value = tempp
        show_set_point_timeout = time.time() + Timeout
    if time.time() > show_set_point_timeout:
        lcd.hide_cursor()
        lcd.move_to(0,0)
        lcd.putstr("Temp:     " + str(t) + " C")
        lcd.move_to(0,1)
        lcd.putstr("Luftf.:   " + str(h) + " %")# show Temp & Humidity
    else:
        lcd.clear()
        lcd.putstr("Tempp:     " + str(tempp) + " C")
        lcd.clear()
             
    temp_difference = tempp - t

    speed_difference = -temp_difference * kp
    
    new_speed = round(start_speed) + round(speed_difference)

        # hier wird mit 'new_speed' die neue Geschwindigkeit für den Lüfter eingestellt
    fan.duty_u16(new_speed)
    
    if new_speed <= 0:
        fan.duty_u16(1000)
        
    if new_speed > 65000:
        fan.duty_u16(65000)
        
    print(t, "C")
    print(h, "%")
    print(fan.duty_u16(), "DutyCycle")



__deets__
User
Beiträge: 14522
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du verstehst offensichtlich nicht das Prinzip von dem, was dieser Code bewirken soll. Sonst waere sowohl klar, dass TIMEOUT einen Wert in Sekunden zur Anzeige benoetigt, den du halt festlegen musst, und das es natuerlich auch totaler Quatsch ist, den Wert fuer old_pot_value *JEDES MAL IN DER SCHLEIFE NEU ZU SETZEN*. Das muss nur einmal vorher passieren, und das war es. Sonst ist doch der Wert *immer* anders als der gerade eingelesene (ausser der ist zufaellig 12345679), und du komms nie in den if-Zweig, sondern bleibst im else.

Da fehlen noch zu viele Grundlagen. So viel Nachhilfe kann ich nicht geben, tut mir leid. Viel Erfolg noch.
Antworten