Moin zusammen,
ich hab ein kleines Problem: Ich programmiere mit micropython meinen
esp32 für den Antrieb eines StepperMotors.
Dazu habe ich eine Klasse mit Methoden geschrieben. Es funktoiniert auch
alles soweit und der Motor lässt sich steuern. Was ich aber nicht ganz
verstehe ist, sobald ich eine Methode zur Stuerung des Motors aufrufe,
wird bei mir die _init_-Methode auch immer wieder aufgerufen. Dies
erkenne ich daran, dass in meinem Ausgabefenster für jeden Schritt des
Motors "Init der Klasse" erscheint. Warum deklariert er jedes Mal das
Objekt neu?
Kann es eventuell daran liegen, dass man in der _init_-Methode keine
Ausgänge definieren darf?
Danke für die Hilfe.
Hier mein Code:
class stepper_motor() :
def
__init__(self,step=0,times=0.005,Seq=[],out1=16,out2=17,out3=18,out4=19)
:
'''Initialisierung der Klasse'''
import machine
print('Init der Klasse')
self.step1 = step
self.times = times
self.out1 = machine.Pin(out1, machine.Pin.OUT)
self.out2 = machine.Pin(out2, machine.Pin.OUT)
self.out3 = machine.Pin(out3, machine.Pin.OUT)
self.out4 = machine.Pin(out4, machine.Pin.OUT)
self.out1.value(0)
self.out2.value(0)
self.out3.value(0)
self.out4.value(0)
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]]
self.Seq = Seq
def setzPin(self,w1,w2,w3,w4):
'''Methode zur Setzung der Ausgaenge'''
self.out1.value(w1)
self.out2.value(w2)
self.out3.value(w3)
self.out4.value(w4)
def vorwaerts(self, step):
'''Methode für vorwaerts'''
import time
for i in range(step):
for j in range(len(self.Seq)):
stepper_motor().setzPin(self.Seq[j][0], self.Seq[j][1],
self.Seq[j][2], self.Seq[j][3])
time.sleep(self.times)
Ähm, gerade gesehen... stepper_motor().setzPin(self.Seq[j][0], self.Seq[j][1], self.Seq[j][2], self.Seq[j][3]) ist natürlich falsch, es muss srlf.setzPin(self.Seq[j][0], self.Seq[j][1], self.Seq[j][2], self.Seq[j][3])
Ich habe in uPyCraft programmiert. Dies hat eine Eingabefenster, sodass
man direkt im esp32 programmieren kann. Alternativ kann man auch Putty
nutzen.
Dann kann man recht einfach den Code auf den esp32 laden und ausführen.
c = stepper_motor()
Mit dieser Zeile wird das Objekt erzeugt und initalisiert. Es erscheint
einmal Init der Klasse, was auch richtig ist. Danach rufe ich die
Methode auf:
c.vorwaerts(30)
Anschließend sehe ich im Ausgabefenster 30mal Init der Klasse
auffloppen. Das müsste meiner Meinung nach eigentlich doch nicht
auftauchen.
test schrieb: > ist natürlich falsch, es muss > > srlf.setzPin(self.Seq[j][0], self.Seq[j][1], self.Seq[j][2], > self.Seq[j][3]) Danke dir das hat geklappt. Endlich den Fehler gefunden :) Kannst du mir erklären, warum ich eigentlich nicht stepper_motor(). schreiben darf?
"srlf" meint natürlich "self" "import time" kann natürlich nach _init_
test schrieb: > "import time" kann natürlich nach _init_ Dann bekomme ich einen Fehler gemeldet, dass er time nicht kennt. Ich weiß zurzeit noch nicht wie ich auf die Bibliothek in der init verweisen kann. Kannst du mir da weiterhelfen? Danke
dux1 schrieb: > warum ich eigentlich nicht stepper_motor(). schreiben darf? Weil das der Name der Klasse (eine reine Schablone nach der die Objekte erstellt werden) ist. Schreibt du das hin dann erstellt Python auf Basis der Klasse ein neues Objekt (also der eigentliche Programmcode). Also Klassen sind Definitionen für Objekte, Objekte ist das was man nutzt. Du hast deine stepper_motor Klasse, dann erstellst du im Programm basierend auf dieser Klasse dein Motor Objekt. Und dieses Motor Objekt nutzt du. Hast du zwei Motoren dann erstellst du halt ein motor1 und ein motor2 Objekt basierend auf deiner stepper_motor Klasse (Theoretisch, praktisch müsstest du deine Klasse dafür anders programmieren). Dann kannst du motor1.vorwaerts und motor2.vorwaerts im Code benutzen. Ich hoffe das war halbwegs verständlich. Wenn nicht gibt es hier sicher welche die es besser erklären können. Und ein Buch/Kurs über objektorientierter Programmierung wäre evtl. auch hilfreich. Das sind so die Grundlagen.
dux1 schrieb: > test schrieb: >> "import time" kann natürlich nach init > > Dann bekomme ich einen Fehler gemeldet, dass er time nicht kennt. Ich > weiß zurzeit noch nicht wie ich auf die Bibliothek in der init verweisen > kann. Kannst du mir da weiterhelfen? > Danke Kann auch sein das ich mich da jetzt vertan habe. Lass einfach so wenns geht, schad ja nix. Sah für mich erstmal nur seltsam aus.
test schrieb: > Ich hoffe das war halbwegs verständlich. Wenn nicht gibt es hier sicher > welche die es besser erklären können. Doch das war für mich verständlich. Danke dir :)
Ich habe mir den Code Deiner Schrittmotor-Klasse eben mal angeschaut, und mir sind da noch ein paar andere Sachen aufgefallen, die ich persönlich ändern würde: - Die Methode "vorwaerts" funktioniert nach einer etwas fragwürdigen Logik: Durch die verschachtelte Schleife kann man den Motor immer nur um ein Vielfaches der hartkodierten 8 Halbschritte bewegen; man kann also auch nur 1/8 aller möglichen Schritte anfahren - Du hast den Namen der Klasse klein geschrieben. Normalerweise beginnen Klassennamen mit einem Grossbuchstaben. Auf diese Weise kann man auch schneller einer Klasse an sich und den Instanzen dieser Klasse unterscheiden; das hätte in diesem Fall evtl. auch den ursprünglichen Fehler vermieden - self.step1 wird offenbar gar nicht benutzt, auch der der __init__-Funktion übergebene "step"-Parameter hat somit keine Funktion - Man kann der __init__-Funktion zwar einen "Seq"-Parameter übergeben, der wird in der Praxis aber komplett ignoriert, stattdessen wird self.Seq in der __init__-Funktion eh auf einen hartkodierten Wert gesetzt. Weiterhin würde ich empfehlen, diese Variable nicht "Seq", sondern "seq" zu nennen, weil der Name "Seq" (also mit Grossbuchstabe am Anfang) halt suggeriert, dass es sich dabei um eine Klasse handelt - Eventuell wäre es sinnvoll, "import time" aus der "vorwaerts"-Funktion vor die Klasse zu verschieben, damit time nur ein einziges Mal importiert wird, statt bei jedem Aufruf der vorwaerts-Funktion. Weil ich den Grundgedanken Deiner Schrittmotor-Klasse aber gar nicht schlecht fand und so etwas bislang noch nicht in meiner Sammlung hatte, habe ich Deine Klasse übrigens etwas angepasst folgendermassen in meine Sammlung aufgenommen:
1 | import machine |
2 | import time |
3 | |
4 | def value_with_default(value, default_value): |
5 | return (value or default_value) |
6 | |
7 | class Stepper_Motor(): |
8 | def __init__(self, initial_step=None, step_time=None, steps=None, enabled=None, pin_1_id=None, pin_2_id=None, pin_3_id=None, pin_4_id=None): |
9 | self.pin_1 = machine.Pin(value_with_default(pin_1_id, 16), machine.Pin.OUT) |
10 | self.pin_2 = machine.Pin(value_with_default(pin_2_id, 17), machine.Pin.OUT) |
11 | self.pin_3 = machine.Pin(value_with_default(pin_3_id, 18), machine.Pin.OUT) |
12 | self.pin_4 = machine.Pin(value_with_default(pin_4_id, 19), machine.Pin.OUT) |
13 | self.set_steps(steps) |
14 | self.set_step_time(step_time) |
15 | self.set_enabled(enabled) |
16 | self.set_step(initial_step) |
17 | |
18 | def set_steps(self, steps=None): |
19 | self.steps = value_with_default(steps, [ |
20 | [1,0,0,0], |
21 | [1,1,0,0], |
22 | [0,1,0,0], |
23 | [0,1,1,0], |
24 | [0,0,1,0], |
25 | [0,0,1,1], |
26 | [0,0,0,1], |
27 | [1,0,0,1], |
28 | ]) |
29 | self.number_of_steps = len(self.steps) |
30 | |
31 | def set_step_time(self, step_time=None): |
32 | self.step_time = value_with_default(step_time, 0.005) |
33 | |
34 | def set_pin_states(self, pin_1_state, pin_2_state, pin_3_state, pin_4_state): |
35 | self.pin_1.value(pin_1_state) |
36 | self.pin_2.value(pin_2_state) |
37 | self.pin_3.value(pin_3_state) |
38 | self.pin_4.value(pin_4_state) |
39 | |
40 | def set_pins(self) |
41 | if self.enabled: |
42 | step_pin_states = self.steps[self.step % self.number_of_steps] |
43 | self.set_pin_states(step_pin_states[0], step_pin_states[1], step_pin_states[2], step_pin_states[3]) |
44 | else: |
45 | self.set_pins(0, 0, 0, 0) |
46 | |
47 | def set_step(self, step=None): |
48 | self.step = value_with_default(step, 0) |
49 | self.set_pins() |
50 | |
51 | def set_enabled(self, enabled=None): |
52 | self.enabled = value_with_default(enabled, True) |
53 | self.set_step(self.step) |
54 | |
55 | def move(self, number_of_steps): |
56 | step_delta = 1 |
57 | if (number_of_steps < 0): |
58 | step_delta = -1 |
59 | number_of_steps = -number_of_steps |
60 | for step in range(number_of_steps): |
61 | self.set_step(self.step + step_delta) |
62 | time.sleep(self.step_time) |
63 | |
64 | def forward(self, number_of_steps=None): |
65 | self.move(value_with_default(number_of_steps, 1)) |
66 | |
67 | def reverse(self, number_of_steps=None): |
68 | self.move(-value_with_default(number_of_steps, 1)) |
Hallo Joachim S., danke dir für deine Hilfe. Man sieht das du dich schon ausführlich mit der Thematik beschäftigt hast. Ich beschäftige mich erstmals mit Klassen und Objekten. Ist ne Laboraufgabe bei uns. Joachim S. schrieb: > Die Methode "vorwaerts" funktioniert nach einer etwas fragwürdigen > Logik: Durch die verschachtelte Schleife kann man den Motor immer nur um > ein Vielfaches der hartkodierten 8 Halbschritte bewegen; man kann also > auch nur 1/8 aller möglichen Schritte anfahren Du hast in dieser Sache recht, aber wenn ich nur ein Vektor dieser Sequenz ausführe bewegt sich der Motor nicht. Der brauch einmal den kompletten Durchlauf. Oder die Bewegung ist so minimal, dass die mit dem Auge nicht sichtbar ist. Mfg dux1
test schrieb: > "import time" kann natürlich nach _init_ Blödsinn. Alle Importe kommen global oben hin, das ist so Usus, und das ist sinnvoll, viele erfahrene Leute haben lange und hart nachgedacht um die empfohlenen Gepflogenheiten zu erarbeiten. Grundsätzlich gilt: Vieles was bei statisch getypten Sprachen vom Compiler erzwungen wird muss man sich bei dynamischen Sprachen per Konvention festlegen und sich auch sklavisch dran halten (also in dem Fall die offiziellen Styleguides für Python) sonst verliert man schnell den Überblick und driftet in ein unstrukturiertes Chaos ab und alle anderen (allen voran auch das zukünftge Selbst nach einigen Jahren Erfahrung) werden den lieblos hingeworfenen Code hassen und ihn aufräumen wollen. Der erste Schritt zu mehr diesbezüglicher Disziplin ist es im Editor oder in der IDE den Linter einzuschalten und auf schärfste Stufe zu stellen und dann so lange am Code zu arbeiten bis alle Warnungen verschwunden sind. Manches mag überpenibel erscheinen aber alles hat einen tieferen Sinn den man irgendwann erkennen wird - spätestens dann wenn man mal Quellcode von jemand anderem in die Finger bekommt der alle gut gemeinten Empfehlungen in den Wind geschossen hat.
dux1 schrieb: > Joachim S. schrieb: >> Die Methode "vorwaerts" funktioniert nach einer etwas fragwürdigen >> Logik: Durch die verschachtelte Schleife kann man den Motor immer nur um >> ein Vielfaches der hartkodierten 8 Halbschritte bewegen; man kann also >> auch nur 1/8 aller möglichen Schritte anfahren > > Du hast in dieser Sache recht, aber wenn ich nur ein Vektor dieser > Sequenz ausführe bewegt sich der Motor nicht. Der brauch einmal den > kompletten Durchlauf. Oder die Bewegung ist so minimal, dass die mit dem > Auge nicht sichtbar ist. Klar, wenn Du jeden Halbschritte ansteuern kannst, statt wie in Deiner aktuellen Fassung immer ein Vielfaches aller acht Halbschritte, dann ist jeder einzelne Schritt nur noch 1/8 so gross. Wenn Dir die Schritte damit zu klein sind, dann übergebe der vorwaerts()-Funktion doch einfach einen 8-mal so grossen Wert? Aber falls Du dennoch dabei bleiben willst, immer ein Vielfaches aller acht Halbschritte zu gehen, dann macht es allerdings wenig Sinn, überhaupt Halbschritte zu gehen - dann kannst Du auch gleich Vollschritte gehen, indem Du Seq einfach abänderst in:
1 | Seq = [ |
2 | [1,1,0,0], |
3 | [0,1,1,0], |
4 | [0,0,1,1], |
5 | [1,0,0,1], |
6 | ] |
oder
1 | Seq = [ |
2 | [1,0,0,0], |
3 | [0,1,0,0], |
4 | [0,0,1,0], |
5 | [0,0,0,1], |
6 | ] |
Die erste Version hat ein kräftigeres Drehmoment, benötigt aber auch doppelt so viel Strom.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.