Ich will das der 2.Servo (den ich gerade mit raspberry pi programmiere in Python) auch bewegt. Kann mir jemand helfen?

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
adsfgjh
User
Beiträge: 1
Registriert: Montag 8. November 2021, 21:21

Das ist der Code


import RPi.GPIO as GPIO
import time
import getpass
OFFSE_DUTY = 0.5 #define pulse offset of servo
SERVO_MIN_DUTY = 2.5+OFFSE_DUTY #define pulse duty cycle for minimum angle of servo
SERVO_MAX_DUTY = 12.5+OFFSE_DUTY #define pulse duty cycle for maximum angle of servo
servoPin = 12
servoPin1 = 40


def map( value, fromLow, fromHigh, toLow, toHigh): # map a value from one range to another range
return (toHigh-toLow)*(value-fromLow) / (fromHigh-fromLow) + toLow

def setup():
global p
GPIO.setmode(GPIO.BOARD) # use PHYSICAL GPIO Numbering
GPIO.setup(servoPin, GPIO.OUT)
GPIO.output(servoPin, GPIO.LOW)

p = GPIO.PWM(servoPin, 50)# set Frequece to 50Hz
p.start(0) # Set initial Duty Cycle to 0

def setup1():
global p1
GPIO.setmode(GPIO.BOARD)
GPIO.setup(servoPin1, GPIO.OUT)
GPIO.output(servoPin1, GPIO.LOW)

p1 = GPIO.PWM(servoPin1, 50)
p1.start(0)

def servoWrite(angle): # make the servo rotate to specific angle, 0-180
if(angle < 0):
angle = 0
elif(angle > 180):
angle = 180
p.ChangeDutyCycle(map(angle, 0, 180, SERVO_MIN_DUTY,SERVO_MAX_DUTY)) # map the angle to duty cycle and output it

def servoWrite1(angle): # make the servo rotate to specific angle, 0-180
if(angle < 0):
angle = 0
elif(angle > 180):
angle = 180
p1.ChangeDutyCycle(map(angle, 0, 180, SERVO_MIN_DUTY,SERVO_MAX_DUTY)) # map the angle to duty cycle and output it

def loop():
passwort = getpass.getpass("Passwort: ")
if (passwort == "123456"):
a = input("Möchten sie den Tresor öffnen oder schließen : ")
if (a == "öffnen") or (a == "Öffnen"):
for dc in range(0, 100, 1): # make servo rotate from 0 to 180 deg
servoWrite(dc) # Write dc value to servo
time.sleep(0.01)
time.sleep(0.45)
for dc in range(180, 0, 1):
servoWrite1(dc)
time.sleep(0.01)
time.sleep(5)
loop()
if (a == "schließen") or (a == "Schließen"):
for dc in range(100, 10, -1): # make servo rotate from 180 to 0 deg
servoWrite(dc)
time.sleep(0.01)
time.sleep(0.45)
for dc in range(0, 180, 1):
servoWrite1(dc)
time.sleep(0.01)
time.sleep(5)
loop()
else:
loop()

def destroy():
p.stop()
GPIO.cleanup()

if __name__ == '__main__': # Program entrance
print ('Program is starting...')
setup()
setup1()
try:
loop()
except KeyboardInterrupt: # Press ctrl-c to end the program.
destroy()
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@adsfgjh,

das erste Problem welches du angehen solltest, ist deinen Code so umbauen, dass er keine globalen Variablen mehr verwendet. Das verwirrt nur, weil man nicht mehr nachvollziehen kann, wo eigentlich diese Variablen geändert werden.
Die Funktionen müssen diese Variablen statt dessen als Eingangsparameter erhalten.
Jetzt hast du zwei Funktionen die eigentlich das gleiche tun: servoWrite und servoWrite1. Die kannst du zusammenführen in eine indem du p bzw. p1 (die Namen sind zu kurz und wenig aussagekräftig) an diese Funktion über gibst. Das gleiche gilt für die Funktionen setup und setup1
Das ist dann auch der Schritt in die Richtung mehrere Servos anzusteuern. Je allgemeingültiger die Funktionen aufgebaut sind um so leichter kann man das Programm erweitern.

Du überschreibst die eingebaute map() Funktion von Python. Das solltest du vermeiden indem du deine Funktion anders benennst.
Dass sich die loop Funktion immer wieder selbst aufruft ist keine gute Idee. Denn irgendwann ist die maximale Rekursionstiefe erreicht. Daher sollte das in einer Endlosschleife laufen.
Statt zu prüfen ob der Benutzer die Befehle klein oder groß geschrieben hat sollte man die Eingaben in die Kleinschreibung umwandeln und dann nur das prüfen.

Einmal ist die Schrittweite in der Range-Funktion positiv obwohl herunter gezählt werden soll.
Die destroy Funktion stoppt nur eins der beiden pwm Signale.
Wenn man seinen Code mit anderen teilt, sollte man sich auch an die üblichen Namenskonventionen halten, damit der Code leichter zu lesen ist. Also Variablen- und Funktionsnamen werden komplett klein geschrieben und Konstanten komplett groß.
Die Namen sollte auch aus mehr als zwei Buchstaben bestehen, damit man besser versteht wofür sie stehen.

Wenn du ein weiteres Servo ansteuern möchtest, muss das zunächst in die Menu-Funktion eingebaut werden.
Hier ist ein Zwischenschritt um zu verdeutlichen, was ich meine. Ich habe gerade keinen Raspberry zur Hand mit dem ich das testen könnte.
Man könnte es sicher noch weiter verbessern und möglicherweise enthält meine Version auch noch Fehler.

Code: Alles auswählen

import time
import getpass
import RPi.GPIO as GPIO

OFFSE_DUTY = 0.5  # define pulse offset of servo
SERVO_MIN_DUTY = 2.5 + OFFSE_DUTY  # define pulse duty cycle for minimum angle of servo
SERVO_MAX_DUTY = 12.5 + OFFSE_DUTY  # define pulse duty cycle for maximum angle of servo
SERVO_PIN0 = 12
SERVO_PIN1 = 40


def range_map(value, from_low, from_high, to_low, to_high):
    """map a value from one range to another range"""
    return (to_high - to_low) * (value - from_low) / (from_high - from_low) + to_low


def setup(servo_pin):
    GPIO.setmode(GPIO.BOARD)  # use PHYSICAL GPIO Numbering
    GPIO.setup(servo_pin, GPIO.OUT)
    GPIO.output(servo_pin, GPIO.LOW)

    pwm_signal = GPIO.PWM(servo_pin, 50)  # set Frequece to 50Hz
    pwm_signal.start(0)  # Set initial Duty Cycle to 0
    return pwm_signal


def servo_write(pwm_signal, angle):
    """make the servo rotate to specific angle, 0-180"""
    if angle < 0:
        angle = 0
    elif angle > 180:
        angle = 180
    # map the angle to duty cycle and output it
    pwm_signal.ChangeDutyCycle(range_map(angle, 0, 180, SERVO_MIN_DUTY, SERVO_MAX_DUTY))


def loop(pwm_signal0, pwm_signal1):
    while True:
        passwort = getpass.getpass("Passwort: ")
        if passwort == "123456":
            user_input = input("Möchten sie den Tresor öffnen oder schließen: ")
            if user_input.lower() == "öffnen":
                for duty_cycle in range(0, 100, 1):  # make servo rotate from 0 to 180 deg
                    servo_write(pwm_signal0, duty_cycle)  # Write dc value to servo
                    time.sleep(0.01)
                time.sleep(0.45)
                for duty_cycle in range(180, 0, -1):
                    servo_write(pwm_signal1, duty_cycle)
                    time.sleep(0.01)
                time.sleep(5)
            elif user_input.lower() == "schließen":
                for duty_cycle in range(100, 10, -1):  # make servo rotate from 180 to 0 deg
                    servo_write(pwm_signal0, duty_cycle)
                    time.sleep(0.01)
                time.sleep(0.45)
                for duty_cycle in range(0, 180, 1):
                    servo_write(pwm_signal1, duty_cycle)
                    time.sleep(0.01)
                time.sleep(5)


if __name__ == "__main__":  # Program entrance
    print("Program is starting...")
    pwm_signal0 = setup(SERVO_PIN0)
    pwm_signal1 = setup(SERVO_PIN1)
    try:
        loop(pwm_signal0, pwm_signal1)
    except KeyboardInterrupt:  # Press ctrl-c to end the program.
        print("Program is ending")
    finally:
        pwm_signal0.stop()
        pwm_signal1.stop()
        GPIO.cleanup()
Antworten