Einzelnen Pin von COM Anschluss abfragen

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
Henkman
User
Beiträge: 7
Registriert: Dienstag 4. April 2017, 16:53

Hallo
Ich habe mit pygame ein Programm entworfen mit dem man über die Pfeiltasten das nächste oder das vorherige Bild aufrufen kann. Nun möchte ich die Pfeiltasten durch einen Fußtaster ersetzen, der ein Eigenbau ist. Er wird über die Serielle Schnitstelle angeschlossen. Der Taster für nächstes Bild ist mit Pin 6 und 7, der für vorheriges Bild mit Pin 4 und 8 belegt (Jeweils ein Plus 5V und ein DSR/CTS Pin). Wie kann ich das Signal abfangen/ auslesen welches durch die Verbindung der beiden Pins jeweils entsteht? Habe schon viele Foren durchforstet aber keine Antwort gefunden :K

VIelen Dank schonmal für eure Mühen

MFG
Henkman
BlackJack

@Henkman: Schau Dir mal das PySerial-Package an.
Henkman
User
Beiträge: 7
Registriert: Dienstag 4. April 2017, 16:53

Hab ich schon werd da aber irgendwie nicht schlau draus.
Also den COM Anschluss aufrufen klappt aber das mit den einzelnen Pins krieg ich nicht hin. :|
BlackJack

@Henkman: Was genau funktioniert denn nicht? Die Pins die man lesen kann existieren als Attribute auf dem `Serial`-Objekt. Einfacher geht's ja kaum.
Henkman
User
Beiträge: 7
Registriert: Dienstag 4. April 2017, 16:53

@ BlackJack: Ich weiß einfach nicht wie ich die Pins auslese also mit welchem Code. hast du vllt mal ein Beispiel für mich?
Bisher hab ich nur das:

Code: Alles auswählen

import serial

ser = serial.Serial(port='COM1', baudrate=9600, timeout=1)
ser.setDTR(True)
try:
    ser.isOpen()
    print("ok")
except:
    print("closed")
if(ser.isOpen()):
    while(1):
        try:
            print(ser.read())
        except Exception:
            print("geht nicht")
else:
    print("geschlossen")
Würde mich sehr freuen wenn du mir da den passenden Befehl sagen kannst.
Zuletzt geändert von Anonymous am Dienstag 4. April 2017, 20:43, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@Henkman: Der Code ist ziemlich unsinnig. Lass diese Ausnahmebehandlung weg. Und das `ser.isOpen()` macht auch keinen Sinn weil das auf *jeden Fall* offen ist so wie Du das `Serial`-Objekt erstellst. Sollte das öffnen nicht klappen hätte Zeile 3 schon eine Ausnahme ausgelöst die Du nicht behandelt hättest.

Die Klammern um die Bedingungen von ``if`` und ``while`` gehören da nicht hin, und `read()` willst Du doch gar nicht, warum machst Du das dann?

Du kannst die DTR-Leitung setzen, andere aber nicht lesen? Das ist eigenartig.

Wobei man die Methoden nicht mehr verwenden sollte, die Leitungen haben Attribute/Properties bekommen.
Henkman
User
Beiträge: 7
Registriert: Dienstag 4. April 2017, 16:53

@BlackJack: Den Code hab ich so aus einem Forum übernommen. Das read() ist nur zum gucken ob das klappt. Wie würdest du es machen? Kannst du mir ein Beispiel Code nennen? Das wäre sehr nett.
BlackJack

@Henkman: `Serial`-Objekte haben die lesbaren Leitungen unter ihren Namen als Attribute die man einfach abfragen kann. Schau Dir in der Dokumentation einfach mal die Attribute von `Serial` an.
Henkman
User
Beiträge: 7
Registriert: Dienstag 4. April 2017, 16:53

Habs geschafft :)
Hab aber leider noch ein Problem, dass dem fertigen Programm im weg steht ...
Ich frage True am Pin ab aber er führt die Definitionen Bild_vor und Bild_zurueck nicht aus sieht jemand meinen Fehler?
Ich weiß der Code ist nicht sehr ordentlich und es kann sein, dass dort noch Befehle drin sind die unsinnig sind, weil ich vorher etwas anderes probiert hatte.
Hier der Code:

Code: Alles auswählen

import pygame
from win32api import GetSystemMetrics
from pygame.locals import *
import os
import sys
import time
import serial

ser = serial.Serial(port='COM1', baudrate=9600, timeout=1)


valueh = GetSystemMetrics(0)
valuew = GetSystemMetrics(1)

pygame.init()
screen = pygame.display.set_mode((valueh,valuew), pygame.FULLSCREEN)
pygame.display.set_caption("Empfänger")
clock = pygame.time.Clock()
pygame.mouse.set_visible(0)

try:
    NummerLan = open("C:/Tanzmusik/Nummer.txt","r")

    N = NummerLan.read()

    NummerLan.close()

    Z = 1

    Y = 1

    Nummer = N

    Liste ="C:/Tanzmusik/" + str(Nummer)
    Inhalt = os.listdir(Liste)
    Y = len(Inhalt)
    print (Y)

    S = 1

    while Z <= Y:
        if Z == 1:
            image = pygame.image.load("C:/Tanzmusik/" + str(Nummer) + "/" + str(Z) + ".jpg")
            image = pygame.transform.scale(image, (valueh, valuew))
            image1 = image
        elif Z == 2:
            image = pygame.image.load("C:/Tanzmusik/" + str(Nummer) + "/" + str(Z) + ".jpg")
            image = pygame.transform.scale(image, (valueh, valuew))
            image2 = image
        elif Z == 3:
            image = pygame.image.load("C:/Tanzmusik/" + str(Nummer) + "/" + str(Z) + ".jpg")
            image = pygame.transform.scale(image, (valueh, valuew))
            image3 = image
        elif Z == 4:
            image = pygame.image.load("C:/Tanzmusik/" + str(Nummer) + "/" + str(Z) + ".jpg")
            image = pygame.transform.scale(image, (valueh, valuew))
            image4 = image
        Z = Z + 1
    Z = 1

    if image1.get_alpha() is None:
        image1 = image1.convert()
    else:
        image1 = image1.convert_alpha()
    screen.blit(image1, (0, 0))
    pygame.display.flip()
except:
    print("Nix")

def input(events):
    global S
    for event in events:
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
        else:
            print(event)
        if event.type == KEYDOWN:
            if event.key == K_ESCAPE:
                Run = False
                QUIT

def Bild_vor():
                if S < Y:
                    S = S + 1
                    print (S)
                    if S == 1:
                        image = image1
                        if image.get_alpha() is None:
                            image = image.convert()
                        else:
                            image = image.convert_alpha()
                        screen.blit(image, (0, 0))
                    elif S == 2:
                        image = image2
                        if image.get_alpha() is None:
                            image = image.convert()
                        else:
                            image = image.convert_alpha()
                        screen.blit(image, (0, 0))
                    elif S == 3:
                        image = image3
                        if image.get_alpha() is None:
                            image = image.convert()
                        else:
                            image = image.convert_alpha()
                        screen.blit(image, (0, 0))
                    elif S == 4:
                        image = image4
                        if image.get_alpha() is None:
                            image = image.convert()
                        else:
                            image = image.convert_alpha()
                        screen.blit(image, (0, 0))

def Bild_zurueck():
                if S >= 1:
                    S = S - 1
                    print (S)
                    if S == 1:
                        image = image1
                        if image.get_alpha() is None:
                            image = image.convert()
                        else:
                            image = image.convert_alpha()
                        screen.blit(image, (0, 0))
                    elif S == 2:
                        image = image2
                        if image.get_alpha() is None:
                            image = image.convert()
                        else:
                            image = image.convert_alpha()
                        screen.blit(image, (0, 0))
                    elif S == 3:
                        image = image3
                        if image.get_alpha() is None:
                            image = image.convert()
                        else:
                            image = image.convert_alpha()
                        screen.blit(image, (0, 0))
                    elif S == 4:
                        image = image4
                        if image.get_alpha() is None:
                            image = image.convert()
                        else:
                            image = image.convert_alpha()
                        screen.blit(image, (0, 0))
                    
                    pygame.display.flip()

Run = True

while Run:
    clock.tick(20)
    input(pygame.event.get())
    try:
        Vor = ser.getCTS()
        Zurueck = ser.getDSR()
        if Vor == True:
            Bild_vor
            print(Vor)
            time.sleep(0.5)
        if Zurueck == True:
            Bild_zurueck
            print(Zurueck)
            time.sleep(0.5)
        NummerLan = open("C:/Tanzmusik/Nummer.txt","r")
        N = NummerLan.read()
        if N != Nummer:
            Nummer = N
            Liste ="C:/Tanzmusik/" + str(Nummer)
            Inhalt = os.listdir(Liste)
            Y = len(Inhalt)
            while Z <= Y:
                if Z == 1:
                    image = pygame.image.load("C:/Tanzmusik/" + str(Nummer) + "/" + str(Z) + ".jpg")
                    image = pygame.transform.scale(image, (valueh, valuew))
                    image1 = image
                elif Z == 2:
                    image = pygame.image.load("C:/Tanzmusik/" + str(Nummer) + "/" + str(Z) + ".jpg")
                    image = pygame.transform.scale(image, (valueh, valuew))
                    image2 = image
                elif Z == 3:
                    image = pygame.image.load("C:/Tanzmusik/" + str(Nummer) + "/" + str(Z) + ".jpg")
                    image = pygame.transform.scale(image, (valueh, valuew))
                    image3 = image
                elif Z == 4:
                    image = pygame.image.load("C:/Tanzmusik/" + str(Nummer) + "/" + str(Z) + ".jpg")
                    image = pygame.transform.scale(image, (valueh, valuew))
                    image4 = image
                Z = Z + 1
            Z = 1
            S = 1

            if image1.get_alpha() is None:
                image1 = image1.convert()
            else:
                image1 = image1.convert_alpha()
            screen.blit(image1, (0, 0))
            pygame.display.flip()
        
    except:
            print("Nix")
Zuletzt geändert von Anonymous am Mittwoch 5. April 2017, 09:20, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@Henkman: Das ist viel zu unübersichtlich als das man sich da durchlesen möchte.

Die ``try``/``except``\s gehören ersatzlos gestrichen oder durch *sinnvolle* Behandlung von *konkreten* Ausnahmen ersetzt. So wie es da jetzt steht erschwert es nur die Fehlersuche.

Auf Modulebene sollte nur Code stehen der Konstanten, Funktionen, und Klassen definiert. Keine Variablen! Und schon gar nicht Variablen, Hauptprogramm, und Funktionsdefinitionen gemischt. Funktionen sollten keine Werte, ausser Konstanten, verwenden die nicht als Argumente übergeben wurden, und ``global`` geht gar nicht. Wenn eine Funktion ein Ergebnis hat, dann gibt man das als Rückgabewert an den Aufrufer zurück. Das durcheinander was da jetzt steht ist nicht leicht nachvollziehbar.

Es gibt auch viel zu viele Code-Wiederholungen. Code und Daten sollte man nicht wiederholen und auch nicht geringfügig geänderte Kopien verwenden. Dafür gibt es Schleifen und Funktionen.

`N`, `Z`, `Y`, `S` sind alles schlechte Namen, weil der Leser nicht sieht was die Werte bedeuten sollen. Auch generische Namen wie `Liste` oder `Nummer` helfen nicht wirklich beim Verständnis. Noch schlimmer wenn `Liste` dann an eine Zeichenkette gebunden wird und nicht an eine Liste.

`input()` ist bereits der Name einer eingebauten Funktion, die sollte man nicht verdecken.

Nummerierte Namen sind ein „code smell“. Da will man sich entweder bessere Namen ausdenken oder gar keine einzelnen Namen verwenden sondern eine Datenstruktur. Oft eine Liste. Wie zum Beispiel hier mit den Bildern.

Das mit den Zahlen `S` und `Y` ist alles andere als robust gelöst. Einerseits berücksichtigt der Code nur vier Bilder, andererseits ist die Obergrenze im Code die Anzahl der Dateien und Verzeichnisse in dem Verzeichnis. Da würde man eher entweder die tatsächliche Anzahl der *Bilder* ermitteln deren Dateiname eine Nummer ist und sich daran orientieren, oder fest von einer Anzahl von solchen Dateien ausgehen.

Und was den unnötigen Code angeht: der gesamte erste ``try``/``except``-Code, immerhin 48 Zeilen, scheint unnötig zu sein. Oder halt auch nicht, aber warum sollen *wir* das lesen und herausfinden müssen?
BlackJack

`valueh` und `valuew` sind falsch benannt. Davon abgesehen das man hier raten muss das `h` für `height` und `w` für `width` stehen soll, sind die Werte vertauscht!

Vergleiche mit literalen `True` oder `False` macht man nicht. Da kommt nur wieder ein Wahrheitswert bei heraus. Je nach Vergleichsoperation entweder der Wahrheitswert den man eh schon hatte, oder die Negation davon, also sollte man gleich den Wert nehmen, oder die Negation davon.

Dateien die man öffnet sollte man auch wieder schliessen. Die ``with``-Anweisung ist dabei hilfreich.

Pfade setzt man mit `os.path.join()` zusammen und nicht mit Zeichenkettenoperationen.

Hier das ganze mal ohne die ganzen Codewiederholungen und in einer sinnvolleren Reihenfolge (ungetestet):

Code: Alles auswählen

import os
import time

import pygame
from pygame.locals import *
from serial import Serial
from win32api import GetSystemMetrics

BASE_PATH = 'C:Tanzmusik'
IMAGE_SET_FILENAME = os.path.join(BASE_PATH, 'Nummer.txt')
IMAGME_NAME_TEMPLATE = os.path.join(BASE_PATH, '{}', '{}.jpg')


def main_loop():
    with Serial('COM1') as serial:
        size = (GetSystemMetrics(0), GetSystemMetrics(1))
        screen = pygame.display.set_mode(size, pygame.FULLSCREEN)
        pygame.display.set_caption('Empfänger')
        pygame.mouse.set_visible(0)
        clock = pygame.time.Clock()

        image_set_name = None
        images = None
        current_image_index = None
        display_new_image = False

        while True:
            with open(IMAGE_SET_FILENAME, 'r') as image_set_file:
                new_image_set_name = next(image_set_file).strip()

            if new_image_set_name != image_set_name:
                image_set_name = new_image_set_name
                images = list()
                for i in range(1, 5):
                    try:
                        image = pygame.image.load(
                            IMAGME_NAME_TEMPLATE.format(image_set_name, i)
                        )
                    except pygame.error:
                        break
                    image = pygame.transform.scale(image, size)
                    if image.get_alpha() is None:
                        image = image.convert()
                    else:
                        image = image.convert_alpha()
                    images.append(image)
                current_image_index = 0
                display_new_image = True

            for event in pygame.event.get():
                if (
                    event.type == QUIT
                    or event.type == KEYDOWN and event.key == K_ESCAPE
                ):
                    return

            next_image_flag = serial.cts
            previous_image_flag = serial.dsr
            if next_image_flag:
                current_image_index += 1
            if previous_image_flag:
                current_image_index -= 1
            if next_image_flag or previous_image_flag:
                display_new_image = True
                time.sleep(0.5)
            current_image_index = current_image_index % len(images)

            if display_new_image:
                display_new_image = False
                screen.blit(images[current_image_index], (0, 0))
                pygame.display.flip()

            clock.tick(20)
    

def main():
    pygame.init()
    main_loop()
    pygame.quit()


if __name__ == '__main__':
    main()
`main_loop()` ist eigentlich zu lang, aber um das auf Funktionen aufteilen zu können muss man anfangen Variablen zu Objekten zusammen zu fassen, weil der Zustand aus zu vielen Werten besteht als das man die einzeln alle in der Gegend herum reichen möchte. Also `collections.namedtupel()` oder eigene Klassen.
Henkman
User
Beiträge: 7
Registriert: Dienstag 4. April 2017, 16:53

@ BlackJack
Danke für deine Mühe :)
Habe den Code getestet und funktioniert super. besten Dank! :mrgreen:
Bei "BASE_PATH = 'C:\Tanzmusik' " hast du den "\" vergessen aber den Fehler hab ich schnell gefunden :wink:

Gruß Henkman
BlackJack

Eigener Datentyp für ein `ImageSet` und auf Funktionen aufgeteilt:

Code: Alles auswählen

import os
import time
from collections import namedtuple

import pygame
from pygame.locals import *
from serial import Serial
from win32api import GetSystemMetrics

BASE_PATH = 'C:/Tanzmusik'
IMAGE_SET_FILENAME = os.path.join(BASE_PATH, 'Nummer.txt')
IMAGE_NAME_TEMPLATE = os.path.join(BASE_PATH, '{}', '{}.jpg')

ImageSet = namedtuple('ImageSet', 'name images current_index size')


def get_current_image(image_set):
    return image_set.images[image_set.current_index]


def change_current_image(image_set, offset):
    return image_set._replace(
        current_index=(
            (image_set.current_index + offset) % len(image_set.images)
        )
    )


def load_image(filename, size):
    image = pygame.transform.scale(pygame.image.load(filename), size)
    if image.get_alpha() is None:
        image = image.convert()
    else:
        image = image.convert_alpha()
    return image


def load_image_set(name, size):
    images = list()
    try:
        for i in range(1, 5):
            images.append(load_image(IMAGE_NAME_TEMPLATE.format(name, i), size))
    except pygame.error:
        pass  # Stop at first image that could not be loaded.

    return ImageSet(name, images, 0, size)


def update_image_set(image_set, display_new_image):
    with open(IMAGE_SET_FILENAME, 'r') as image_set_file:
        new_image_set_name = next(image_set_file).strip()

    if new_image_set_name != image_set.name:
        image_set = load_image_set(image_set.name, image_set.size)
        display_new_image = True

    return image_set, display_new_image


def get_pedal(serial):
    result = 0
    if serial.cts:
        result += 1
    if serial.dsr:
        result -= 1
    return result


def process_pedal(serial, image_set, display_new_image):
    adjustment = get_pedal(serial)
    if adjustment != 0:
        image_set = change_current_image(image_set, adjustment)
        display_new_image = True
        time.sleep(0.5)

    return image_set, display_new_image


def main_loop():
    with Serial('COM1') as serial:
        size = (GetSystemMetrics(0), GetSystemMetrics(1))
        screen = pygame.display.set_mode(size, pygame.FULLSCREEN)
        pygame.display.set_caption('Empfänger')
        pygame.mouse.set_visible(0)
        clock = pygame.time.Clock()

        image_set = ImageSet(None, None, None, size)
        display_new_image = False

        while True:
            for event in pygame.event.get():
                if (
                    event.type == QUIT
                    or event.type == KEYDOWN and event.key == K_ESCAPE
                ):
                    return

            image_set, display_new_image = update_image_set(
                image_set, display_new_image
            )
            image_set, display_new_image = process_pedal(
                serial, image_set, display_new_image
            )

            if display_new_image:
                display_new_image = False
                screen.blit(get_current_image(image_set), (0, 0))
                pygame.display.flip()

            clock.tick(20)
    

def main():
    pygame.init()
    main_loop()
    pygame.quit()


if __name__ == '__main__':
    main()
Antworten