vorhandenen Code in Klasse packen

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
frost.1989
User
Beiträge: 2
Registriert: Samstag 3. August 2019, 09:55

Hallo,

ich steuere mit einem Code einen Stepper-Motor an. Ich benutze dafür Micropython und einen ESP32. (funktioniert soweit)
Jetzt soll allerdings dieser Code in einer Klasse geschrieben sein.
Ich habe nur grundlegende Python Kentnisse und verstehe das Prinzip mit der Klasse nicht 100 prozentig.

Wäre jemand bereit diesen Code um eine Klasse zu erweitern? Der Motor soll anschließend das gleiche wie vorher machen. (Eine halbe Umdrehung, über move() in der Konsole)
Ich würde auch gerne eine Aufwandsentschädigung "zahlen" oder was auch immer.,
Alternativ würde ich mich über jede Hilfe freuen.
Dieses Thema ist nicht mein Fachgebiet.

Code: Alles auswählen

import machine 
import time 

# Definition der Pinbelegung

d1 = machine.Pin(19, machine.Pin.OUT) 
d2 = machine.Pin(18, machine.Pin.OUT) 
d3 = machine.Pin(17, machine.Pin.OUT) 
d4 = machine.Pin(16, machine.Pin.OUT) 


class Stepper():
  

  def move(direction='counterclockwise'):
      pins=[d1,d2,d3,d4]
      if direction=='clockwise':
          pins.reverse()

      for steps in range(250):
          for i in pins:
              i.value(1); time.sleep(0.005); i.value(0)
          steps+=1
          

move()
move('clockwise')
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da ist vieles im Argen. Auch ohne klasse. Die Idee, die drehrichtung über die Reihenfolge der Pins zu lösen, hat nicht nur unnötig hohe Kosten - sie ist auch falsch. Ruf mal zweimal clockwise hintereinander auf. Dann wird auch zweimal reversed. Und damit NICHT zweimal clockwise gedreht.

Das der schrittmotor sich so korrekt dreht kann ich mir auch nur schwer vorstellen. Entweder hast du einen Treiber verbaut der nur Richtung & schrittpuls kennt. Dann braucht’s aber nur zwei Pins. Oder 4 Pins (so wie dein Code suggeriert), doch dann muss da an den Pins ein bestimmtes Muster angelegt werden. Beschrieben zb hier : https://www.tigoe.com/pcomp/code/circui ... er-motors/

Bist du sicher, dass das Ding vernünftig läuft?

Zum ersten Problem: da ist die Lösung einfach, statt die Datenstruktur zu manipulieren muss die Tabelle per Index durchlaufen werden, und die Schrittweite ist dabei entweder 1 oder -1. Dabei muss natürlich der Bereichsüber/unterlauf abgefangen werden. Klassisch so:

pos = (pos + direction) % len(tabelle)

Und dann zur Frage: die Klasse braucht einen Konstruktor. Der legt die Pins an, und merkt sich die, sowie die aktuelle Position in der Schrittansteuerungs-Tabelle.

Und dann kann man entsprechende Methoden aufrufen.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Und noch ein Problem: das steps += 1 ist wirkungslos, da steps in der for-Schleife der Wert neu zugewiesen wird. Kann also auch weg.
Sirius3
User
Beiträge: 18270
Registriert: Sonntag 21. Oktober 2012, 17:20

Hast Du Dir schon ein Grundlagentutorial zu Klassen durchgearbeitet? Denn es hilft ja nicht viel, wenn jemand Dir das in eine richtige Klasse umschreibt, Du es aber dann nicht verstehst und auch nicht anwenden kannst.

Warum definierst Du d1 bis d4 die Du dann in eine Liste packst, anstatt die Pins gleich in eine Liste zu packen.

`i` ist ein ganz schlechter Name für einen Pin, `pin` wäre geeigneter. Pro Zeile nur eine Anweisung schreiben, vergiß am besten, dass es ; überhaupt gibt.


@__deets__: die Liste wird doch jedesmal neu erzeugt.
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@__deets__: Das Problem mit dem `reverse()` sehe ich nicht – die Liste wird ja bei jedem Aufruf neu erstellt.

@frost.1989: Der gezeigte Code funktioniert so nicht, denn für die beiden `move()`-Aufrufe gibt keine Definition die da aufgerufen werden könnte → `NameError`.

Eingerückt wird in Python vier Leerzeichen pro Ebene.

`i` für etwas anderes als ganze Zahlen zu verwenden, insbesondere auch noch wenn es eine Laufvariable in einer Schleife ist, ist eine ganz schlechte, weil verwirrende Idee.

Das Semikolon wird in Python nur *sehr* selten verwendet. Eine Anweisung pro Zeile ist üblich.

Das erhöhen von `steps` am Ende der Schleife ist unsinnig weil der Wert beim nächsten Schleifendurchlauf sowieso gleich wieder überschrieben wird.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3: wo du recht hast!

@TE: vergiss meine Bemerkungen zur Falschheit der Ansteuerung wegen dem Reverse. Teuer und mir unverständlich warum es funktioniert ist es immer noch, und ich würde bei meiner Lösung bleiben. Aber der grobe Schnitzer war bei meinem lesen. Nicht im Code.
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Für eine Klasse gibt das IMHO keine Grund, die hätte ja nur eine `__init__()` und *eine* weitere Methode. Da reicht ein Closure (ungetestet):

Code: Alles auswählen

from machine import Pin
import time

STEPPER_PINS = [19, 18, 17, 16]

CLOCKWISE = 'clockwise'
COUNTERCLOCKWISE = 'counterclockwise'


def identity(argument):
    return argument


def make_stepper_move(pin_numbers):
    pins = [Pin(n, Pin.OUT) for n in pin_numbers]
    direction2function = {
        CLOCKWISE: reversed,
        COUNTERCLOCKWISE: identity,
    }
    
    def move(direction=COUNTERCLOCKWISE):
        direction_function = direction2function[direction]
        for _ in range(250):
            for pin in direction_function(pins):
                pin.on()
                time.sleep(0.005)
                pin.off()
    
    return move
    

move = make_stepper_move(STEPPER_PINS)
move()
move(CLOCKWISE)
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
kbr
User
Beiträge: 1508
Registriert: Mittwoch 15. Oktober 2008, 09:27

@frost.1989: Eine Klasse könnte so aussehen (wenngleich eine Klasse mit nur zwei Methoden, und eine davon __init__, etwas mager ist). Ich habe sie Dir geschrieben, damit Du lernbegleitend ein objektorientiertes Beispiel hast. Getestet habe ich es mangels geeigneter Hardware nicht.

Code: Alles auswählen

class Stepper:

    def __init__(self, steps=250, duration=0.005):
        self.pins = [machine.Pin(n, machine.Pin.OUT) for n in range(16, 20)]
        self.steps = range(steps)
        self.duration = duration
        
    def rotate(self, clockwise=True):
        pins = self.pins if clockwise else reversed(self.pins)
        for step in self.steps:
            for pin in pins:
                pin.value(1)
                time.sleep(self.duration)
                pin.value(0)
                
                
stepper = Stepper()
stepper.rotate()
stepper.rotate(clockwise=False)
Benutzeravatar
__blackjack__
User
Beiträge: 14047
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wenn man `steps` zum Argument macht, dann wahrscheinlich eher von der `rotate()`-Methode. Vermute ich mal.

Edit: Das Closure noch mal überarbeitet:

Code: Alles auswählen

from machine import Pin
import time

STEPPER_PINS = [19, 18, 17, 16]

CLOCKWISE = 'clockwise'
COUNTERCLOCKWISE = 'counterclockwise'


def make_stepper_move(pin_numbers, duration=0.005):
    pins = [Pin(n, Pin.OUT) for n in pin_numbers]
    
    def move(direction=COUNTERCLOCKWISE, steps=250):
        for _ in range(steps):
            for pin in reversed(pins) if direction == CLOCKWISE else pins:
                pin.on()
                time.sleep(duration)
                pin.off()
    
    return move
    

move = make_stepper_move(STEPPER_PINS)
move()
move('clockwise')
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
kbr
User
Beiträge: 1508
Registriert: Mittwoch 15. Oktober 2008, 09:27

@__blackjack__: je nach gewünschter Flexibilität könnte man den Stepper natürlich entsprechend anpassen.
Antworten