Seite 1 von 2
Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 04:06
von dravida
Hallo,
ich baue mir gerade einen automatischen Makroschlitten welcher mit einem Python Script laufen soll.
Nach langer Suche habe ich folgendes Script gefunden und es mir was die "Pin Belegung" und "Steodelay" angeht angepasst.
Code: Alles auswählen
import sys
import wiringpi
from time import sleep
# direction (1)
# number of steps (200)
# delay between steps (2)
gpio = wiringpi.GPIO(wiringpi.GPIO.WPI_MODE_GPIO)
motor_pin_a = 17
motor_pin_b = 4
motor_pin_c = 27
motor_pin_d = 10
shutterpin = 9
gpio.pinMode(motor_pin_a,gpio.OUTPUT)
gpio.pinMode(motor_pin_b,gpio.OUTPUT)
gpio.pinMode(motor_pin_c,gpio.OUTPUT)
gpio.pinMode(motor_pin_d,gpio.OUTPUT)
gpio.pinMode(shutterpin,gpio.OUTPUT)
wiringpi.pinMode(shutterpin,1)
wiringpi.pinMode(motor_pin_a,1)
wiringpi.pinMode(motor_pin_b,1)
wiringpi.pinMode(motor_pin_c,1)
wiringpi.pinMode(motor_pin_d,1)
if sys.argv[1] == '1':
start=0
finish=int(sys.argv[2],base=10)
increment=1
else:
start=int(sys.argv[2],base=10)
finish=0
increment=-1
stepdelay=float(sys.argv[3])
a = [ '1000', '1100', '0100', '0110', '0010', '0011', '0001', '1001']
for j in range(start,finish,increment):
i = j%4
if a[i][0:1] == '1':
gpio.digitalWrite(motor_pin_a,gpio.HIGH)
else:
gpio.digitalWrite(motor_pin_a,gpio.LOW)
if a[i][1:2] == '1':
gpio.digitalWrite(motor_pin_b,gpio.HIGH)
else:
gpio.digitalWrite(motor_pin_b,gpio.LOW)
if a[i][2:3] == '1':
gpio.digitalWrite(motor_pin_c,gpio.HIGH)
else:
gpio.digitalWrite(motor_pin_c,gpio.LOW)
if a[i][3:4] == '1':
gpio.digitalWrite(motor_pin_d,gpio.HIGH)
else:
gpio.digitalWrite(motor_pin_d,gpio.LOW)
sleep(stepdelay)
# sleep 100ms to let things settle.
sleep(0.1)
# Trigger the camera shutter.
gpio.digitalWrite(shutterpin,gpio.HIGH)
sleep(0.1)
gpio.digitalWrite(shutterpin,gpio.LOW)
Soweit so gut...
Sobald ich dsa Script ausführe bekomme ich folgende Meldung:
Code: Alles auswählen
root@storageBox:~/rail# python macro.py
Traceback (most recent call last):
File "macro.py", line 29, in <module>
if sys.argv[1] == '1':
IndexError: list index out of range
Ich keinerlei Programmierkenntnisse und hoffe dennoch sehr dass mir hier geholfen werden kann.
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 07:34
von rogerb
Der Fehler ensteht weil du keine Kommandozeilenargumente übergeben hast.
sys.argv[0] ist immer der Skriptpfad.
alle folgenden Einträge in der Liste sind optional. Du must also erst prüfen ob es überhaupt mehr als einen Eintrag in der Liste gibt:
Bzw., da du ja teilweise noch mehr optionale Parameter erwartest muss dass entsprechend angepasst werden.
Vielleicht schaust du dir mal 'argparse' an um eine etwas komfortablere und robustere Argumentübergabe zu implementieren:
https://docs.python.org/3/library/argparse.html
Damit kannst du dann auch Fehleingaben behandeln. Denn wenn man falsche Werte für start, finish, increment eingibt, wird das zu ein Exception führen.
Code: Alles auswählen
# nicht nötig:
a[i][0:1]
# Es ist ja immer nur ein 'bit':
a[1][0]
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 08:09
von Sirius3
Als erstes sollte man die Codedopplungen etwas reduzieren:
Code: Alles auswählen
#!/usr/bin/env python
import sys
import wiringpi
from time import sleep
from itertools import cycle, islice
# direction (1)
# number of steps (200)
# delay between steps (2)
MOTOR_PINS = [17, 4, 27, 10]
SHUTTER_PIN = 9
MODES = [ '1000', '1100', '0100', '0110', '0010', '0011', '0001', '1001']
def initalize():
gpio = wiringpi.GPIO(wiringpi.GPIO.WPI_MODE_GPIO)
for motor_pin in MOTOR_PINS:
gpio.pinMode(motor_pin, gpio.OUTPUT)
gpio.pinMode(SHUTTER_PIN, gpio.OUTPUT)
return gpio
def main():
gpio = initialize()
if len(sys.argv) != 4:
print("Arguments: [direction] [steps] [stepdelay]")
return
direction = sys.argv[1]
steps = sys.argv[2]
stepdelay = float(sys.argv[3])
if direction:
modes = islice(cycle(MODES), steps)
else:
skip = -(steps % -len(MODES))
modes = islice(cycle(reversed(MODES)), skip, skip + steps)
for mode in modes:
for pin, value in zip(MOTOR_PINS, mode):
gpio.digitalWrite(pin, gpio.HIGH if value == '1' else gpio.LOW)
sleep(stepdelay)
# sleep 100ms to let things settle.
sleep(0.1)
# Trigger the camera shutter.
gpio.digitalWrite(SHUTTER_PIN, gpio.HIGH)
sleep(0.1)
gpio.digitalWrite(SHUTTER_PIN, gpio.LOW)
if __name__ == "__main__":
main()
Dann erwartet das Programm drei Kommandozeilenparameter: direction, number of steps und delay between steps.
Der Aufruf könnte also so aussehen:
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 08:22
von rogerb
@Sirius3, haben sich da nicht ein paar Fehler eingeschlichen?
'direction' wird gar nicht mehr verwendet.
Müsste es nicht
lauten?
Variablennamen die sich nur in der Groß- und Kleinschreibung unterscheiden, würde ich vermeiden.
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 08:27
von Sirius3
Danke rogerb. Hab's oben korrigiert. Eigentlich weiß ich, wann ich eine Konstante benutzen will und wann eine Variable. Daher halte ich das bei komplett GROSS gegen komplett klein nicht für so kritisch. Wäre nur ein Buchstabe unterschied, sähe das anders aus.
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 10:18
von __blackjack__
Wobei man vielleicht noch anmerken sollte, dass die zugrunde liegende `wiringpi`-Bibliothek vom Entwickler schon seit einer Weile nicht mehr gepflegt wird. Da sollte man sich besser nach einer Alternative umschauen. `gpiozero` beispielsweise.
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 14:32
von dravida
]Zunächst danke für eure Hilfe!
Wenn ich den Coode von "Sirius3" nutze:
bekomme ich folgenden Output:
Code: Alles auswählen
root@storageBox:~/rail# python programm.py 1 200 2
Traceback (most recent call last):
File "forum1.py", line 51, in <module>
main()
File "forum1.py", line 23, in main
gpio = initialize()
NameError: global name 'initialize' is not defined
Der Link den "rogerb" gepostet hat war leider nicht hilfreich da mir so ziemlich alle Basics in python fehlen.
Ich verstehe überwiegend was die einzelnen Zeilen in meinem Code machen, allerdings fehlt mir die nötige Expertise ihn selbst zu schreiben.
Mehr als das abändern von Werten ist mir leider "noch" nicht möglich und für das. Lernen der ganzen Sprache fehlt mir leider die Zeit.
Das WiringPi nicht mehr gepflegt wird habe ich heute morgen auch Festellen müssen.
Allerdings reicht das was es kann für meinen zweck aus.
Habe ich irgendwelche Vorteile mit "gpiozero" für meinen Verwendungszweck, __blackjack__?
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 14:54
von __deets__
@dravida Sirius3 hat einen simplen Schreibfehler gemacht. Vergleich mal genau die entsprechenden Namen.
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 15:21
von dravida
@_deets_
Er hat keinen Fehler gemacht sondern ich.
Ich wollte das ganze der Übersicht halber abändern, habe aber leider vergessen alles zu ändern.
Der Output sieht wie folgt aus:
Code: Alles auswählen
root@storageBox:~/rail# python forum1.py 1 200 2
Traceback (most recent call last):
File "forum1.py", line 51, in <module>
main()
File "forum1.py", line 23, in main
gpio = initialize()
NameError: global name 'initialize' is not defined
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 15:22
von Sirius3
Das auf gpiozero umzuschreiben, sollte recht einfach sein:
Code: Alles auswählen
#!/usr/bin/env python
import sys
from gpiozero import DigitalOutputDevice
from time import sleep
from itertools import cycle, islice
# direction (1)
# number of steps (200)
# delay between steps (2)
MOTOR_PINS = [17, 4, 27, 10]
SHUTTER_PIN = 9
MODES = [ '1000', '1100', '0100', '0110', '0010', '0011', '0001', '1001']
def initialize():
motor_pins = [
DigitalOutputDevice(pin)
for pin in MOTOR_PINS
]
shutter = DigitalOutputDevice(SHUTTER_PIN)
return motor_pins, shutter
def main():
if len(sys.argv) != 4:
print("Arguments: [direction] [steps] [stepdelay]")
return
direction = sys.argv[1]
steps = sys.argv[2]
stepdelay = float(sys.argv[3])
if direction:
modes = islice(cycle(MODES), steps)
else:
skip = -(steps % -len(MODES))
modes = islice(cycle(reversed(MODES)), skip, skip + steps)
motor_pins, shutter = initialize()
for mode in modes:
for pin, value in zip(motor_pins, mode):
pin.value = int(value)
sleep(stepdelay)
# sleep 100ms to let things settle.
sleep(0.1)
# Trigger the camera shutter.
shutter.on()
sleep(0.1)
shutter.off()
if __name__ == "__main__":
main()
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 15:35
von dravida
@Sirius3 ich bin dir sehr dankbar dass du dir die Mühe machst!
Welche Vorteile bietet mir "gpiozero"?
Beim ausführen bekomme ich folgenden Output:
Code: Alles auswählen
root@storageBox:~/rail# python forum2.py
Arguments: [direction] [steps] [stepdelay]
root@storageBox:~/rail# python forum2.py 1 200 2
Traceback (most recent call last):
File "forum2.py", line 52, in <module>
main()
File "forum2.py", line 32, in main
modes = islice(cycle(MODES), steps)
ValueError: Stop argument for islice() must be None or an integer: 0 <= x <= maxint.
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 16:02
von Sirius3
Ja, ich bin doof, weil ich es nicht testen kann. Man muß `steps` in ein int umwandeln.
Code: Alles auswählen
def main():
if len(sys.argv) != 4:
print("Arguments: [direction] [steps] [stepdelay]")
return
direction = sys.argv[1]
steps = int(sys.argv[2])
stepdelay = float(sys.argv[3])
if direction == "1":
modes = islice(cycle(MODES), steps)
else:
skip = -(steps % -len(MODES))
modes = islice(cycle(reversed(MODES)), skip, skip + steps)
...
gpiozero ist besser, weil es breiter unterstützt wird und noch aktiv weiterentwickelt wird.
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 16:26
von dravida
Ich danke dir!
Der Code läuft nun durch und die LEDs am Motor-Driver leuchten in der richtigen Reihenfolge auf.
Allerdings bewegt sich trotz "ticken" im Stepper nichts vor- oder rückwärts, des Weiteren löst die Kamera leider nicht aus.
Ich habe "gpiozero" nun gegoogelt und verstehe zumindest dass es allein deshalb wichtig ist, dass sobald eine neue python Version released ist ich (sofern weiterentwickelt) alles was ich über die GPIO Pins machen kann, auch mit dem neuen Python fortführen kann.
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 16:28
von hyle
Btw. Wenn Du das Skript mit
dravida hat geschrieben: Donnerstag 8. Juli 2021, 15:35
aufrufst, dann wird (zumindest beim Raspberry Pi OS) noch das veraltete und nicht mehr weiterentwickelte Python 2 verwendet.
Den Python 3 Interpreter nutzt Du mit:
Im Skript wäre dann der Shebang folgender:
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 17:07
von dravida
Der Motor fährt nun wie gewünscht (Feintuning von delay und stepcount) allerdings besteht noch das Problem dass die Kamera "permanent" auslöst sobald sie angesteckt ist.
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 17:46
von dravida
DIe Kamera löst nun immer nach Ende des Programms aus, ich möchte allerdings dass die Kamera bei einem von mir zuvor festgelegten Zeitpunkt auslöst (z.B. nach jedem 5. Step).
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 18:30
von rogerb
@dravida
Wie sieht denn jetzt dein Code aus. Das sollte ja leicht einzubauen sein.
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 19:02
von dravida
Das denke ich mir auch. Ich finde es auch interessant wie viel ich nebenbei aufschnappe, wobei es definitiv noch nicht dazu reicht etwas eigenes zu schreiben.
Mein Code sieht wie folgt aus:
Code: Alles auswählen
#!/usr/bin/env python
import sys
from gpiozero import DigitalOutputDevice
from time import sleep
from itertools import cycle, islice
# direction (1)
# number of steps (200)
# delay between steps (2)
MOTOR_PINS = [17, 4, 2, 10]
SHUTTER_PIN = 26
MODES = [ '1000', '1100', '0100', '0110', '0010', '0011', '0001', '1001']
def initialize():
motor_pins = [
DigitalOutputDevice(pin)
for pin in MOTOR_PINS
]
shutter = DigitalOutputDevice(SHUTTER_PIN)
return motor_pins, shutter
def main():
if len(sys.argv) != 4:
print("Arguments: [direction] [steps] [stepdelay]")
return
direction = sys.argv[1]
steps = int(sys.argv[2])
stepdelay = float(sys.argv[3])
if direction == "1":
modes = islice(cycle(MODES), steps)
else:
skip = -(steps % -len(MODES))
modes = islice(cycle(reversed(MODES)), skip, skip + steps)
motor_pins, shutter = initialize()
for mode in modes:
for pin, value in zip(motor_pins, mode):
pin.value = int(value)
sleep(stepdelay)
# sleep 100ms to let things settle.
sleep(0.1)
# Trigger the camera shutter.
shutter.on()
sleep(0.1)
shutter.off()
if __name__ == "__main__":
main()
Re: Problem mit Macroschiene.
Verfasst: Donnerstag 8. Juli 2021, 22:23
von rogerb
@dravida,
ich bin mir nicht ganz sicher was du mit "Step" meinst. Und ich kann es auch nicht selber ausprobieren.
Versuch doch mal die for-Schleife so zu verändern:
Code: Alles auswählen
for step_num, mode in enumerate(modes):
for pin, value in zip(motor_pins, mode):
pin.value = int(value)
sleep(stepdelay)
if step_num % 5 == 0:
# Trigger the camera shutter.
shutter.on()
sleep(0.1)
shutter.off()
Re: Problem mit Macroschiene.
Verfasst: Freitag 9. Juli 2021, 02:05
von dravida
@rogerb
Weißt du denn was ein Schrittmotor ist?
Falls nicht, hier ist es besser erklärt als ich es selbst könnte.
Andernfalls lernt vielleicht Jemand der sich den Thread durchliest noch etwas.
Der Schrittmotor ist ein Synchronmotor, bei dem der Läufer des Motors sich in kleinen Schritten bewegen kann.
Die prinzipielle Funktionsweise entspricht dabei der eines Synchronmotors mit einer hohen Polpaarzahl.
Der Motor hat bauartbedingt eine bestimmte Anzahl an Positionen (Schritten), die er bei einer Ansteuerung einnehmen kann.
Zur Steigerung der Genauigkeit beziehungsweise zur Vergrößerung der Schritt-Zahl werden die Pole des Rotormagneten gezahnt ausgeführt.
Ein ständiges Umpolen der Ständerwicklungen ermöglicht eine kontinuierliche Drehbewegung des Ankers.
Quelle: https://glossar.item24.com/glossarindex ... motor.html
Ich bin mir nicht sicher ob ich den Code richtig eingefügt habe, daher habe ich mehrere Optionen ausprobiert.
Allerdings machte es so am meisten Sinn für mich:
Code: Alles auswählen
#!/usr/bin/env python
import sys
from gpiozero import DigitalOutputDevice
from time import sleep
from itertools import cycle, islice
# direction (1)
# number of steps (200)
# delay between steps (2)
MOTOR_PINS = [17, 4, 2, 10]
SHUTTER_PIN = 26
MODES = [ '1000', '1100', '0100', '0110', '0010', '0011', '0001', '1001']
def initialize():
motor_pins = [
DigitalOutputDevice(pin)
for pin in MOTOR_PINS
]
shutter = DigitalOutputDevice(SHUTTER_PIN)
return motor_pins, shutter
def main():
if len(sys.argv) != 4:
print("Arguments: [direction] [steps] [stepdelay]")
return
direction = sys.argv[1]
steps = int(sys.argv[2])
stepdelay = float(sys.argv[3])
if direction == "1":
modes = islice(cycle(MODES), steps)
else:
skip = -(steps % -len(MODES))
modes = islice(cycle(reversed(MODES)), skip, skip + steps)
motor_pins, shutter = initialize()
for step_num, mode in enumerate(modes):
for pin, value in zip(motor_pins, mode):
pin.value = int(value)
sleep(stepdelay)
if step_num % 5 == 0:
# Trigger the camera shutter.
shutter.on()
sleep(0.1)
shutter.off()
if __name__ == "__main__":
main()
Ich bekomme egal wie ich den Code eingefügt habe
immer eine Meldung die etwas mit "step_num & modes" zu tun hat.
Code: Alles auswählen
root@storageBox:~/rail# python forum2.py 1 500 0.001
Traceback (most recent call last):
File "forum2.py", line 38, in <module>
for step_num, mode in enumerate(modes):
NameError: name 'modes' is not defined
Ich konnte aber etwas eventuell nützliches finden dass uns/dir vielleicht weiterhilft: