Problem mit Macroschiene.

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
dravida
User
Beiträge: 11
Registriert: Donnerstag 8. Juli 2021, 03:52

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).
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@dravida

Wie sieht denn jetzt dein Code aus. Das sollte ja leicht einzubauen sein.
dravida
User
Beiträge: 11
Registriert: Donnerstag 8. Juli 2021, 03:52

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()
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@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()
dravida
User
Beiträge: 11
Registriert: Donnerstag 8. Juli 2021, 03:52

@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:
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Einrückungen sind in Python syntaktisch wichtig. Alles was zur Funktion main gehört, muß mindestens so weit eingerückt sein. Die Zeile mit `for` ist aber gar nicht eingerückt, steht also außerhalb der Funktion und wird beim Ausführen des Programms auch als erstes verarbeitet, wo es zu diesem Zeitpunkt und auf in diesem Namensraum den Namen ` modes` überhaupt nicht gibt, den gibt es nämlich nur innerhalb des Namensraums der Funktion `main`.
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@dravida,
ja ich weiß was ein Schrittmotor ist, habe damit aber in der Praxis noch nichts gemacht.
Ich denke "Step" muss sich auch nicht zwingend auf Steppermotor beziehen. Aber wenn, ich eine Schrittmotorsteuerung schon mal in der Praxis programmiert hätte, währe mir das vielleicht bekannt vorgekommen.

Du hattest meinen Code in dein Script kopiert, aber dabei alles 4 Zeichen zuweit nach links eingerückt, wie Sirius3, ja auch schon bemerkte.

Ich denke so sollte es richtig sein: (Wie gesagt, ohne Gewähr, da ich es nicht ausprobieren kann, und ich nicht sicher bin wie deine Steuerung genau funktioniert)

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()
Dein Link führt zu einem Eintrag bezüglich Numpy, der Python Bibliothek für numerische Mathematik. Das währe so wie mit "Kanonen auf Spatzen schießen"
In diesem Fall kann man das sicher ohne Numpy lösen.

Wenn der Code jetzt immer noch nicht funktioniert, kann ich nur vorschlagen, dass du mal die Bitmuster und in welcher Reigenfolge sie gesetzt werden als Text postest. Dann kann ich mir besser vorstellen was du erwartest.
dravida
User
Beiträge: 11
Registriert: Donnerstag 8. Juli 2021, 03:52

@Sirius3
Dann verstehe ich nun zumindest weshalb er das Programm nicht hat laufen lassen wollte. Danke!

@rogerb
Ich habe vor vielen Jahren mal ein wenig mit PHP, MySQL und html gespielt, dort ist deutlich mehr Raum für Fehler wie ich feststellen muss!

Was das Script angeht,
Der Driver bekommt zwar ein Signal, allerdings lässt sich der Motor nun nicht mehr schnell genug fahren damit überhaupt etwas passiert.
Zudem löst die Kamera zwar nun häufiger dafür aber gefühlt wahllos aus. (auch wenn ich den von dir angegebenen Wert auf Zeile 43 zwischen 1 & 100 ändere.)
(je tiefer ich mit dem delay gehe desto schneller sollte der Motor fahren, jedoch ist nach 0.01 keine Veränderung mehr ersichtlich.)

Code: Alles auswählen

root@storageBox:~/rail# python forum3.py 1 1000 0.00000001
Was ein Bitmuster ist habe ich dank Google zwar verstanden, nur weiß ich leider nicht was ich euch dazu schreiben soll...
Bild
Ich möchte:
1. Es wäre schön wenn ich das Programm mit Startparametern starten kann und nicht jedes Mal die Datei abändern muss.
2. Die Startparameter sollten folgende sein:
Richtung (aktuell 1&2, das passt).
Verfahren in Steps (aktuell sind es mit dem Programm 20100 das passt auch).
Verzögerung zwischen den einzelnen Steps (damit sich mein Fotomotiv... z.B. eine Biene nicht so bewegt dass sich die Stellung der Flügel verändert).
Alle wie viel Steps ein Foto aufgenommen werden soll (z.B. nach jedem 10. Step).
Eine Verzögerung nach jedem Foto bis der Motor weiter fährt (Ein Foto kann je nach Licht 1/200sec, oder auch 30sec benötigen).
Ich bitte das Chaos zu entschuldigen... Aktuell sieht die schiene so aus:
Bild

Hier seht ihr was die Kamera sieht:
Der Pi soll wenn das Python Programm läuft mit ein Wlan Netzwerk stellen und alle Startparameter via Webinterface auszuwählen sein.

Ich weiß dass ich mich wiederhole... aber ich bin euch echt dankbar dass ihr mir obwohl sich meine Kenntnisse in Grenzen halten so viel Geduld für mein Projekt aufbringt!
dravida
User
Beiträge: 11
Registriert: Donnerstag 8. Juli 2021, 03:52

Ich habe nun fast was ich möchte.
Ich führe das Programm nun mit einer zuvor festgelegten Anzahl von Wiederholungen aus, in dem Fall 10:

Code: Alles auswählen

for n in {1..10}; do python stack.py 2 195 0.01; done
Nun würde ich gerne:

Code: Alles auswählen

    # sleep 100ms to let things settle.
    sleep(0.1)

    # Trigger the camera shutter.
    shutter.on()
    sleep(0.1)
    shutter.off()

if __name__ == "__main__":
    main()
Mit einem Argument beim ausführen des Programms festlegen können.
Zudem stellt sich mir die Frage weshalb der Wert "0.1" dort 2 mal angegeben ist?
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

Mit einem Argument beim ausführen des Programms festlegen können.
Was möchtest du festlegen?
Du hattest ja in deinem ursprünglichen Programm schon die Möglichkeit Argumente einlesen zu können. Ich verstehe nicht was du meinst.
Zudem stellt sich mir die Frage weshalb der Wert "0.1" dort 2 mal angegeben ist?
Das war auch in deinem ursprünglichen Programm. Hast du das nicht selbst entschieden, so zu machen?
Antworten