Eingabe wird nicht erkannt

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
tenor
User
Beiträge: 24
Registriert: Samstag 2. Januar 2016, 19:32

Hallo,
ich bin noch neu in der Python Welt. Ich habe etwas Erfahrung mit Mikrocontrollern, möchte jetzt aber den Raspi integrieren und dafür nutze ich die Gelegenheit mich mit Python zu beschäftigen.

Ich greife aktuelle von meinem Win10 PC via Putty und WinSCP auf den PI zu und Editiere mit nano.
Grundlegend habe ich ein Problem mit der Eingabe.
Im folgenden Beispiel funktionieren alle Eingaben, nur "r" funktioniert nicht und bringt mir die "Ungueltige Eingabe".
Ich hatte befürchtet das ich ein Problem mit Steuerzeichen habe, da ich den Code in Nano eingefügt hatte, daher hatte ich den Teil von Hand nochmal abgetippt. Aber er erkennt das "r" einfach nicht.
Woran liegt das?
Kann man die py Dateien auf Steuerzeichen durchsuchen lassen?
Besten Dank schon mal!

PS, Nutze Python 2

Code: Alles auswählen

import RPi.GPIO as GPIO
import time
import os

#Pin 18 als Ausgang deklarieren
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.OUT)
GPIO.setup(17, GPIO.OUT)
GPIO.setup(11, GPIO.OUT)
GPIO.setup(13, GPIO.OUT)

while True:
        # PWM mit 50Hz an Pin 18 starten

        # Richtungseingabe
        Eingabe = raw_input("Bitte treffen Sie Ihre Wahl 30-50-l-r: ")

        if Eingabe == "30":
			# PWM mit 30% Dutycycle (2ms) generieren
			GPIO.output(17, False)
			Servo = GPIO.PWM(18, 50)
			Servo.start(30)
			time.sleep(5)

        if(Eingabe == "50"):
			# PWM mit 50% Dutycycle (2ms) generieren
			GPIO.output(18, False)
			Servo = GPIO.PWM(17, 50)
			Servo.start(50)
			time.sleep(10)

		if Eingabe == "r":
			GPIO.output(11, True)
			GPIO.output(13, False)

		if Eingabe == "l":
			GPIO.output(11, False)
			GPIO.output(13, True)

        # Programm beenden
        elif(Eingabe == "q"):
                        print "Programm wird beendet......"
                        os._exit(1)
                        Servo.stop()
                        GPIO.cleanup()

        # Ungueltige Eingabe
        else:
                print "Ungueltige Eingabe!"

Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@tenor: mit Deinen Einrückungen stimmt etwas nicht, das Programm sollte eigentlich gleich mit einem IndentationError abbrechen. Ansonsten solltest Du mal Deine if-Abfragen durchgehen, wann welche Bedingung erfüllt ist, und wann demnach das else ganz am Schluß auch erfüllt ist.
tenor
User
Beiträge: 24
Registriert: Samstag 2. Januar 2016, 19:32

Danke, ich habe das mit Notepad++ schon ein paar mal geändert, was mich irritiert ist, das alles funktioniert, nur das "r"nicht.
elif mit q beendet sofort das Programm.
Ich habe das r extra schon um eine Position nach oben geholt und mit l getauscht. Trotzdem geht das l und das r nicht.

Wenn ich die Datei mit Notepad++ bearbeite und dann auf den PI laden, sind die Einrückungen in der Tat etwas daneben.
Das korrigiere ich dann mit dem nano Editor.
Ich habe auch kontrolliert, das keine Spaces dazwischen sind, sondern nur Tabs.
Ich finde den Fehler nicht.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Die Einrückung ist völlig verkehrt. Entscheide dich entweder für durchgängig Tabs oder für durchgängig Leerzeichen. Letzteres ist die bessere Wahl. Deinen Editor kannst du entsprechend konfigurieren, damit er dir für ein eingegebenes Tab vier Leerzeichen einfügt.

Wenn du Alternativen, zB. verschiedene mögliche Eingaben, testest, verwende immer elif, micht einen Mischmasch aus ifs und elifs. Lass die Klammern dabei weg. Weder if noch elif sind Funktionen, also sollte man seinen Code nicht so schreiben, als wären sie welche.

Steck deinen Code in eine Funktion und ruf diese auf. Dann brauchst du auch kein os._exit(), sondern lediglich ein return, su.

Und: Was, glaubst du, bewirken die zwei Zeilen nach dem os._exit(1)? Wann werden diese Zeilen jemals ausgeführt? Nachdem das Programm beendet wurde?

Statt die Pins jedesmal über ihre Nummern zu adressieren, solltest du für jeden Pin einen symbolischen Namen vergeben, über den der Pin dann angesprochen werden kann. Sonst musst du, falls du mal was umsteckst, jede Stelle im Code anpassen, wo die Pin-Adresse steht, statt nur einmal oben im Code.

Kommentare sollten erklären, warum der Code macht, was er macht. Was der Code macht muss man nicht erklären, denn das steht ja schon da - als Code. Wer den nicht lesen kann, dem helfen die Kommentare auch nicht.

Wenn deine erste Eingabe ein q ist, bekommst du einen NameError weil Servo nicht definiert ist.

Ungetestet und vermutlich immer noch verkehrt:

Code: Alles auswählen

import RPi.GPIO as GPIO
import time


OUT_PIN = 17
SERVO_PIN = 18
RIGHT_PIN = 11
LEFT_PIN = 13


def main()

    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(OUT_PIN, GPIO.OUT)
    GPIO.setup(SERVO_PIN, GPIO.OUT)
    GPIO.setup(RIGHT_PIN, GPIO.OUT)
    GPIO.setup(LEFT_PIN, GPIO.OUT)

    SERVO = GPIO.PWM(SERVO_PIN, 50)

    while True:

        command = raw_input('Bitte treffen Sie Ihre Wahl 30-50-l-r-q: ')

        if command == '30':
            GPIO.output(OUT_PIN, False)
            SERVO.start(30)
            time.sleep(5)

        elif command == '50':
            GPIO.output(SERVO_PIN, False)
            SERVO.start(50)
            time.sleep(10)

        elif command == 'r':
            GPIO.output(RIGHT_PIN, True)
            GPIO.output(LEFT_PIN, False)

        elif command == 'l':
            GPIO.output(RIGHT_PIN, False)
            GPIO.output(LEFT_PIN, True)

        elif command == 'q':
            print 'Programm wird beendet......'
            SERVO.stop()
            GPIO.cleanup()
            return

        else:
            print 'Ungueltige Eingabe!'


if __name__ == '__main__':
    main()
In specifications, Murphy's Law supersedes Ohm's.
tenor
User
Beiträge: 24
Registriert: Samstag 2. Januar 2016, 19:32

Wow!
Besten Dank für deine ausführliche Antwort, das bringt mich eindeutig weiter!
Ich hatte eben die ifs gegen elifs getauscht und dann hatte es funktioniert, aber deine Verbesserungen werde ich komplett übernehmen!

Viele Grüße
Tenor
tenor
User
Beiträge: 24
Registriert: Samstag 2. Januar 2016, 19:32

Ich habe noch ein Problem mit dem GPIO.cleanup().
An den Ausgängen 17 und 18 ist ein Motortreiber angeschlossen.
Das Cleanup bewirkt wohl einen undefinierten Zustand und der Ausgang des Motortreibers lässt den Motor "zittern".

Wenn ich das Cleanup weg lasse, ist alles ok.
Muss das Cleanup sein?
BlackJack

@tenor: Verzeih mir das Wortspiel, aber *sauberer* ist das schon die `cleanup()`-Funktion aufzurufen. Vielleicht müsstest Du vorher die Motoren noch explizit abschalten? Und falls die Links/Rechts-Geschichte auch etwas mit den Motoren zu tun hat, auch dort dafür sorgen das beim Beenden alles aus ist.
tenor
User
Beiträge: 24
Registriert: Samstag 2. Januar 2016, 19:32

Hi,
die Motoren schalte ich wieder ab, anbei der aktuelle Code:

Code: Alles auswählen

import RPi.GPIO as GPIO
import time
import os

PIN_OUT_1 = 29
PIN_OUT_2 = 31
PIN_RECHTS = 28
PIN_LINKS = 30

#GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIN_OUT_1, GPIO.OUT)
GPIO.setup(PIN_OUT_2, GPIO.OUT)
GPIO.setup(PIN_RECHTS, GPIO.OUT)
GPIO.setup(PIN_LINKS, GPIO.OUT)

Eingabe = "leer"

while Eingabe !="q":
    # Richtungseingabe
    Eingabe = raw_input("Bitte treffen Sie Ihre Wahl 30-50-l-r-q: ")

    if Eingabe == "30":
       # GPIO.output(PIN_OUT_1, False)
        GPIO.output(PIN_OUT_2, False)
        Servo = GPIO.PWM(PIN_OUT_1, 50)
        Servo.start(30)
        time.sleep(5)
        Servo.stop()

    elif Eingabe == "50":
        GPIO.output(PIN_OUT_1, False)
        #GPIO.output(PIN_OUT_2, False)
        Servo = GPIO.PWM(PIN_OUT_2, 50)
        Servo.start(50)
        time.sleep(5)
        Servo.stop()
        
    elif Eingabe == "r":
        GPIO.output(PIN_RECHTS, True)
        GPIO.output(PIN_LINKS, False)
        time.sleep(2)
        GPIO.output(PIN_RECHTS, False)
        GPIO.output(PIN_LINKS, False)       
        
    elif Eingabe == "l":
        GPIO.output(PIN_RECHTS, False)
        GPIO.output(PIN_LINKS, True)
        time.sleep(2)
        GPIO.output(PIN_RECHTS, False)
        GPIO.output(PIN_LINKS, False)

    elif(Eingabe == "q"):
        print "Programm wird beendet......"
        GPIO.cleanup()
        exit
        # Ungueltige Eingabe
    else:
        print "Ungueltige Eingabe!"
Die 4 Pins gehen auf einen Motortreiber L6205.
Mittlerweile bin ich zu den Pins am P5 Header gewechselt. Wenn ich zurück auf GPIO 4 und 5 gehe, funktioniert es gar nicht mehr.
Sprich der Motor läuft dauerhaft!
Da ich nur die Pins am Raspi tausche, schließe ich einen Fehler an der Schaltung aus.

Gibt es noch eine andere Konfiguration? Interne Pullups, etc. die man beachten muss?
tenor
User
Beiträge: 24
Registriert: Samstag 2. Januar 2016, 19:32

versehentlich den alten Code gepostet, hier der neue:

Code: Alles auswählen

import RPi.GPIO as GPIO
import time
import os

PIN_OUT_1 = 29
PIN_OUT_2 = 31
PIN_RECHTS = 28
PIN_LINKS = 30

#GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIN_OUT_1, GPIO.OUT)
GPIO.setup(PIN_OUT_2, GPIO.OUT)
GPIO.setup(PIN_RECHTS, GPIO.OUT)
GPIO.setup(PIN_LINKS, GPIO.OUT)

Eingabe = "leer"

while Eingabe !="q":
    # Richtungseingabe
    Eingabe = raw_input("Bitte treffen Sie Ihre Wahl 30-50-l-r-q: ")

    if Eingabe == "30":
       # GPIO.output(PIN_OUT_1, False)
        GPIO.output(PIN_OUT_2, False)
        Servo = GPIO.PWM(PIN_OUT_1, 50)
        Servo.start(30)
        time.sleep(5)
        Servo.stop()

    elif Eingabe == "50":
        GPIO.output(PIN_OUT_1, False)
        #GPIO.output(PIN_OUT_2, False)
        Servo = GPIO.PWM(PIN_OUT_2, 50)
        Servo.start(50)
        time.sleep(5)
        Servo.stop()
        
    elif Eingabe == "r":
        GPIO.output(PIN_RECHTS, True)
        GPIO.output(PIN_LINKS, False)
        time.sleep(2)
        GPIO.output(PIN_RECHTS, False)
        GPIO.output(PIN_LINKS, False)       
        
    elif Eingabe == "l":
        GPIO.output(PIN_RECHTS, False)
        GPIO.output(PIN_LINKS, True)
        time.sleep(2)
        GPIO.output(PIN_RECHTS, False)
        GPIO.output(PIN_LINKS, False)

    elif(Eingabe == "q"):
        print "Programm wird beendet......"
        GPIO.cleanup()
        exit
        # Ungueltige Eingabe
    else:
        print "Ungueltige Eingabe!"
Antworten