Heizungssteuerung für Mietobjekt mit Gastherme

Du hast eine Idee für ein Projekt?
Antworten
Necromc
User
Beiträge: 8
Registriert: Sonntag 20. Dezember 2020, 12:24

Hallo zusammen,

da ich an meiner Gastherme nicht ran darf habe ich mir eine Halterung für die Funksteuerung gebastelt wo ein Stepper Motor den an aus Schalter bedient.
Ein Script habe ich im Internet gefunden damit dreht der Motor in Schleife 360 Grad nach Links dann nach rechts der soll aber nur eine bestimmte Umdrehung machen damit mir der Schalter nicht abreißt.

Könntet ihr mir helfen aus dem vorhandenen Script ein schlankes Script zu erstellen der nach dem ausführen auch gleich den Motor abstellt? Also GPIO.Cleanup ausführt?


Gruß,

Sebastian
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Wo ist denn das Skript? Und was funktioniert daran konkret nicht?
Necromc
User
Beiträge: 8
Registriert: Sonntag 20. Dezember 2020, 12:24

Hier der Code

Code: Alles auswählen

#!/usr/bin/env python3
########################################################################
# Filename    : SteppingMotor.py
# Description : Drive SteppingMotor
# Author      : www.freenove.com
# modification: 2019/12/27
########################################################################
import RPi.GPIO as GPIO
import time 

motorPins = (12, 16, 18, 22)    # define pins connected to four phase ABCD of stepper motor
CCWStep = (0x01,0x02,0x04,0x08) # define power supply order for rotating anticlockwise 
CWStep = (0x08,0x04,0x02,0x01)  # define power supply order for rotating clockwise

def setup():    
    GPIO.setmode(GPIO.BOARD)       # use PHYSICAL GPIO Numbering
    for pin in motorPins:
        GPIO.setup(pin,GPIO.OUT)
        
# as for four phase stepping motor, four steps is a cycle. the function is used to drive the stepping motor clockwise or anticlockwise to take four steps    
def moveOnePeriod(direction,ms):    
    for j in range(0,4,1):      # cycle for power supply order
        for i in range(0,4,1):  # assign to each pin
            if (direction == 1):# power supply order clockwise
                GPIO.output(motorPins[i],((CCWStep[j] == 1<<i) and GPIO.HIGH or GPIO.LOW))
            else :              # power supply order anticlockwise
                GPIO.output(motorPins[i],((CWStep[j] == 1<<i) and GPIO.HIGH or GPIO.LOW))
        if(ms<3):       # the delay can not be less than 3ms, otherwise it will exceed speed limit of the motor
            ms = 3
        time.sleep(ms*0.001)    
        
# continuous rotation function, the parameter steps specifies the rotation cycles, every four steps is a cycle
def moveSteps(direction, ms, steps):
    for i in range(steps):
        moveOnePeriod(direction, ms)
        
# function used to stop motor
def motorStop():
    for i in range(0,4,1):
        GPIO.output(motorPins[i],GPIO.LOW)
            
def loop():
    while True:
        moveSteps(1,3,512)  # rotating 360 deg clockwise, a total of 2048 steps in a circle, 512 cycles
        time.sleep(0.5)
        moveSteps(0,3,512)  # rotating 360 deg anticlockwise
        time.sleep(0.5)

def destroy():
    GPIO.cleanup()             # Release resource

if __name__ == '__main__':     # Program entrance
    print ('Program is starting...')
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # Press ctrl-c to end the program.
        destroy()


Funktionieren tut er wie es wohl sein soll er dreht 360 Grad links danach rechtsrum und das immer im Wechsel.
Ich benötige aber nur eine kurze Drehung und danach soll er ausgehen.

Ich kenne mich leider absolut nicht mit Python aus :(
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Auch wenn es wenig bringt, die ganzen Schrott-Skripte im Internet verbessern zu wollen:

Code: Alles auswählen

#!/usr/bin/env python3
from RPi import GPIO
import time 

MOTOR_PINS = (12, 16, 18, 22)    # define pins connected to four phase ABCD of stepper motor

def setup():    
    GPIO.setmode(GPIO.BOARD)       # use PHYSICAL GPIO Numbering
    GPIO.setup(MOTOR_PINS,GPIO.OUT)

def destroy():
    # Release resource
    GPIO.cleanup()

def move_one_period(direction, delay):    
    """ as for four phase stepping motor, four steps is a cycle. the function is
    used to drive the stepping motor clockwise or anticlockwise to take four steps"""
    
    # the delay can not be less than 3ms, otherwise it will exceed speed limit of the motor
    delay = max(delay, 3) * 0.001
    steps = MOTOR_PINS if direction == 1 else reversed(MOTOR_PINS)
    for step in steps: # cycle for power supply order
        for pin in MOTOR_PINS: # assign to each pin
            GPIO.output(pin, step == pin)
        time.sleep(delay)
        
def move_steps(direction, steps, delay=3):
    """ continuous rotation function, the parameter steps specifies
    the rotation cycles, every four steps is a cycle"""
    for i in range(steps):
        move_one_period(direction, delay)
        
def motor_stop():
    """ function used to stop motor """
    GPIO.output(MOTOR_PINS, GPIO.LOW)
            
def loop():
    while True:
        move_steps(1, 512)  # rotating 360 deg clockwise, a total of 2048 steps in a circle, 512 cycles
        time.sleep(0.5)
        move_steps(0, 512)  # rotating 360 deg anticlockwise
        time.sleep(0.5)

def main():
    print('Program is starting...')
    setup()
    try:
        loop()
    except KeyboardInterrupt:  # Press ctrl-c to end the program.
        pass
    finally:
        destroy()

if __name__ == '__main__':
    main()
Wenn Du weniger als 360° drehen willst, mußt Du in `loop` die 512 entsprechend anpassen, und wenn Du nicht dauernd hin und her drehen willst, dann mußt Du `loop` durch einen Aufruf von move_steps ersetzen.
Necromc
User
Beiträge: 8
Registriert: Sonntag 20. Dezember 2020, 12:24

Habe das eben mal nach meinem Verständnis geändert
Dort habe ich loop mit move_step ersetzt

Code: Alles auswählen

def main():
    print('Program is starting...')
    setup()
    try:
        move_steps()
    except KeyboardInterrupt:  # Press ctrl-c to end the program.
        pass
    finally:
        destroy()



Und im Move_Step part habe ich es wie folgt geändert

Code: Alles auswählen

def move_steps(direction, steps, delay=3):
    """ continuous rotation function, the parameter steps specifies
    the rotation cycles, every four steps is a cycle"""
    for i in range(steps): (512)
        move_one_period(1, 3)
Jedoch startet es nicht und folgender Fehler wird ausgegeben

Code: Alles auswählen

>>> %Run SteppingMotor1.py
Traceback (most recent call last):
  File "/usr/lib/python3.7/ast.py", line 35, in parse
    return compile(source, filename, mode, PyCF_ONLY_AST)
  File "/home/pi/Desktop/SteppingMotor1.py", line 31
    move_one_period(1, 3)
    ^
IndentationError: unexpected indent

Wo liegt jetzt mein Fehler?
nezzcarth
User
Beiträge: 1632
Registriert: Samstag 16. April 2011, 12:47

In Python setzt man pro Einrückungsebene vier Leerzeichen. Wenn das nicht konsistent ist, oder man Leerzeichen und Tabs mischt, kommt es zu solchen Fehlern. (Technisch gesehen ist es nur wichtig, dass die Einrückung konsistent ist. Die vier Leerzeichen sind jedoch eine Konvention, die man unbedingt einhalten sollte).
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

@nezzcarth: falsch geraten.

@Necromc: falsch geraten. Bzw. ein Grundverständnis von Programmierung in Python solltest Du schon haben, wenn Du ein Pythonprogramm verändern willst. move_steps erwartet mindestens zwei Parameter, die Richtung -1 oder 1 und die Anzahl Schritte in 512/360 Grad. Du hast aber (leere Klammern) keinen Parameter übergeben. Statt dessen hast Du irgendwo (512) hingeschrieben, womit der Compiler von Python natürlich nichts anfangen kann.
Necromc
User
Beiträge: 8
Registriert: Sonntag 20. Dezember 2020, 12:24

@Sirius3
heißt die Richtung und steps kommen direkt nach move_steps in die klammer?
Hatte ja eigentlich eher auf sowas wie geb da move_steps ein und hier die Richtung dann müsste es klappen. Ich weiß es ist ungünstig das ich mich null auskenne mit Python aber da ich es sonst eher selten bis gar nicht benötige hatte ich gehofft hier schnell und unkompliziert Hilfe zu finden.

Falls es nicht allzu teuer ist würde ich euch auch für die Mühen bezahlen :)
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Das Problem ist nicht, dir eine Zahl irgendwo in eine Klammer zu schreiben.

Sondern das ein solches Projekt ein dauerndes hin-und-her ist. Denn ohne Vorliegen des gesamten(!) mechanischen Aufbaus hat man keine Moeglichkeit einzuschaetzen, was denn da nun genau passieren kann und muss. Braucht es einen Endabschalter, damit das System auch bei einem ungeplanten Stromausfall sicher wieder in eine Grundstellung kann? Muss man sich merken, welchen Zustand das System hat, oder kann man das auch "erfahren" - sprichwoertlich, zb durch einen weiteren Taster, oder anderen Sensor wie Licht oder Magnet oder oder oder. Sollte man ueberhaupt Python und einen PI benutzen, oder nicht viel besser einen Microcontroller, der robuster gegen Stromverlust und leichter aufzusetzen ist?

Das sind Stunden Arbeit, und gruebeln, wie man's loest. Das passiert hier (oder sonstwo) nicht einfach auf Zuruf. Wenn du Glueck hast, dann gibt es woanders (in eher Heizungssteuerungs Foren zB) Leute, die sich diese Arbeit selbst fuer dein Modell schonmal gemacht haben, und eine fertige Loesung anbieten koennen. Und sich mit dem Problemraum auch besser auskennen. Da wuerde ich mich eher umschauen.
Necromc
User
Beiträge: 8
Registriert: Sonntag 20. Dezember 2020, 12:24

@__deets__

Hier mal ein paar Bilder zur Veranschaulichung.
Es ist wirklich nichts besonderes und bei Stromausfall kann auch nichts kaputt gehen denn ich werde es in meiner Automatisierung so einrichten das er nur einmal in eine Richtung drehen kann.

Ich wage es zu bezweifeln das so etwas in einem Heizungsforum besser aufgehoben ist.


Bild
Bild
Bild
Bild


Gruß
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du hast doch keine Ahnung, wo der Motor steht, wenn das Programm startet. Und der Drehschalter ist doch sicher in beide Richtungen begrenzt. Wenn das System also abschmiert waehrend einer Bewegung hast du also einen beliebigen Zwischenzustand. Von dem das Programm aber keinerlei Ahnung hat. Und es entsprechend ueberdreht. Was natuerlich alles loesbar ist, es gibt ja absolute Positionsgeber. Muss man aber dann auch noch einbinden, mechanisch, elektrisch, und ins Programm.

Aber du willst es ja so. Hier dein Seil zum selbst erhaengen:

Die Funktion

Code: Alles auswählen

def loop():
    while True:
        move_steps(1, 512)  # rotating 360 deg clockwise, a total of 2048 steps in a circle, 512 cycles
        time.sleep(0.5)
        move_steps(0, 512)  # rotating 360 deg anticlockwise
        time.sleep(0.5)
definiert das Verhalten. Wenn du nur einmal eine bestimmten Menge Schritte durchfuehrt, dann sieht das eben so aus

Code: Alles auswählen

def loop():
    move_steps(1, 512)  # rotating 360 deg clockwise, a total of 2048 steps in a circle, 512 cycles
Und da kannst du jetzt die erste Zahl fuer die Richtung und die zweite fuer die Anzahl der Schritte angeben.
Necromc
User
Beiträge: 8
Registriert: Sonntag 20. Dezember 2020, 12:24

@__deets__

Erstmal frohe Weihnachten :) auch an allen anderen natürlich und vielen Dank für die Hilfe.

Ich weiß mein denken und Aufbau ist etwas halbgar und könnte mich vielleicht einen teuren Nachkauf kosten.
Die Bewegung sollte weniger als eine Sekunde dauern und so lange ich auf den Batteriestand achte sollte eigentlich nichts passieren :D
Benutzeravatar
pillmuncher
User
Beiträge: 1482
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Necromc hat geschrieben: Donnerstag 24. Dezember 2020, 19:52 Die Bewegung sollte weniger als eine Sekunde dauern und so lange ich auf den Batteriestand achte sollte eigentlich nichts passieren :D
Famous last words...
In specifications, Murphy's Law supersedes Ohm's.
Necromc
User
Beiträge: 8
Registriert: Sonntag 20. Dezember 2020, 12:24

Habs das eben auch noch mal ausprobiert und anstatt 1, 512 1, 80 genommen.

Code: Alles auswählen

def loop():
    move_steps(1, 512)  # rotating 360 deg clockwise, a total of 2048 steps in a circle, 512 cycles
aber da es ja immer noch Loop modus ist dreht er natürlich durchgängig...
Necromc
User
Beiträge: 8
Registriert: Sonntag 20. Dezember 2020, 12:24

Konnte jetzt noch einen Code finden der macht was ich möchte.
Pin-belegung musste ich etwas ändern aber nun läufts trotzdem vielen Dank an alle :)

Code: Alles auswählen

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
control_pins = [7,11,13,15]
for pin in control_pins:
  GPIO.setup(pin, GPIO.OUT)
  GPIO.output(pin, 0)
halfstep_seq = [
  [1,0,0,0],
  [1,1,0,0],
  [0,1,0,0],
  [0,1,1,0],
  [0,0,1,0],
  [0,0,1,1],
  [0,0,0,1],
  [1,0,0,1]
]
for i in range(80):
  for halfstep in range(8):
    for pin in range(4):
      GPIO.output(control_pins[pin], halfstep_seq[halfstep][pin])
    time.sleep(0.001)
GPIO.cleanup()
Antworten