GPIO-Pins sind auch nach einem Neustart belegt Möglichkeit diese Freizugeben?

HerrInfo

Aktives Mitglied
Hallo zusammen, immer wenn ich das beigefügte Programm über die Konsole (auf einem Raspberry Pi) starte, funktioniert es beim ersten Mal und beim zweiten Mal( nach einem Neustart) bekomme ich folgenden Fehler:
Code:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/gpiozero/pins/pi.py", line 408, in pin
    pin = self.pins[info]
          ~~~~~~~~~^^^^^^
KeyError: PinInfo(number=11, name='GPIO17', names=frozenset({'J8:11', 17, '17', 'BCM17', 'GPIO17', 'BOARD11', 'WPI0'}), pull='', row=6, col=1, interfaces=frozenset({'', 'dpi', 'uart', 'spi', 'gpio'}))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/pi/Desktop/Server.py", line 9, in <module>
    LED = gpiozero.LED(17)
          ^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 103, in __call__
    self = super().__call__(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/gpiozero/output_devices.py", line 192, in __init__
    super().__init__(pin, active_high=active_high,
  File "/usr/lib/python3/dist-packages/gpiozero/output_devices.py", line 74, in __init__
    super().__init__(pin, pin_factory=pin_factory)
  File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 75, in __init__
    super().__init__(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/gpiozero/devices.py", line 549, in __init__
    pin = self.pin_factory.pin(pin)
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/gpiozero/pins/pi.py", line 410, in pin
    pin = self.pin_class(self, info)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/gpiozero/pins/lgpio.py", line 126, in __init__
    lgpio.gpio_claim_input(
  File "/usr/lib/python3/dist-packages/lgpio.py", line 755, in gpio_claim_input
    return _u2i(_lgpio._gpio_claim_input(handle&0xffff, lFlags, gpio))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/lgpio.py", line 458, in _u2i
    raise error(error_text(v))
lgpio.error: 'GPIO busy'

Ich verstehe nicht ganz, warum der gpio-Pin als belegt angezeigt wird, obwohl es beim ersten Mal funktioniert, wenn ich den Pin ändere, und beim zweiten Mal der Fehler wieder auftritt. Hier ist das Programm:
Python:
import socket
import threading
import time

time.sleep(3)

import gpiozero

LED = gpiozero.LED(17)


def handle_client(client_socket):
    try:
        while True:
            data = client_socket.recv(1024)
            if not data:
                break
            message = data.decode('utf-8')

            # Extract location from the message
            location_start = message.find('&location:') + 10
            location_end = message.find('&', location_start)
            location = message[location_start:location_end]

            # Remove location from the message
            message = message[location_end + 2:]

            print(f'Nachricht erhalten: {message}')
            if message == "Motion detected":
                print(f"Bewegung erkannt in {location}! Schalte LED ein.")
                LED.on()
            elif message == "Motion stopped":
                print(f"Bewegung gestoppt in {location}! Schalte LED aus.")
                LED.off()
            elif message == "Temperature is critical! Shutting down...":
                print(f"Temperatur ist kritisch in {location}! Schalte LED ein.")
                print("There might be a fire! Cut off the power supply! And check IMEDIATELY!")
                LED.on()
            else:
                print(f"Unbekannte Nachricht from {location}. LED bleibt aus.")
                LED.off()
    finally:
        # Get IP address of the client
        ip = client_socket.getpeername()[0]
        print(f"Client with IP: {ip} disconnected from {location}. Turning on LED.")
        LED.on()
       
        # Check if the socket is still open before closing it
        if not client_socket._closed:
            client_socket.close()


def get_ip():
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.settimeout(0)
    try:
        # doesn't even have to be reachable
        s.connect(('10.254.254.254', 1))
        IP = s.getsockname()[0]
    except Exception:
        IP = '127.0.0.1'
    finally:
        s.close()
    return IP


def start_server(port=65432):
    host = get_ip()
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
        server_socket.bind((host, port))
        server_socket.listen()
        print(f'Server gestartet und lauscht auf {host}:{port}')

        while True:
            client_socket, addr = server_socket.accept()
            print(f'Verbunden mit {addr}')
            client_thread = threading.Thread(target=handle_client, args=(client_socket,))
            client_thread.start()


if __name__ == "__main__":
    try:
        LED.off()
        start_server()
    except KeyboardInterrupt:
        print("Server wird heruntergefahren.")

Dazu kommt noch das es in der IDE problemlos funktioniert.
Hat jemand von euch eine Idee wie man das Problem verhindern kann? Ich habe da an so etwas wie GPIO.cleanup() gedacht, diese Funktion gibt es aber in der gpiozero libary nicht, da diese die libary dies bereits automatisch tut.
 

White_Fox

Top Contributor
Gibt es irgendeine Funktion wie freePins() oder so?

Ohne Ahnung davon zu haben wie das auf der Himbeertorte funktoniert würde ich mal vermuten, daß da vielleicht irgendwelche Hardwareressourcen noch als belegt markiert oder für einen anderen (deinen alten) Prozess reserviert sind. Gibst du alles ordnungsgemäß wieder frei? Läuft dein Programm vom ersten Start vielleicht noch irgendwo im Hintergrund oder so?
 

HerrInfo

Aktives Mitglied
Das Programm läuft auf einem frischen Pi. Kann sein, dass von irgendwelchen Testversionen des Programms die Pins noch belegt sind, aber die sollten nach einem Neustart eigentlich wieder frei sein. Und es gibt die Methode GPIO.cleanup() diese habe ich mal testweise auch vor und nach dem Programmstart aufgerufen, ändert aber nicht am Ergebnis.
 

KonradN

Super-Moderator
Mitarbeiter
Also Du musst da auch ein LED.close() aufrufen, nachdem Du die LED angesprochen hast. Also vor dem beenden des Scripts.

Dann ist wichtig, dass der Prozess auch wirklich beendet werden muss. Wie beendest Du denn den Server? Wenn das Script noch laufen sollte und nicht beendet wurde, dann würde das auch dieses Verhalten erklären.

Wenn du sicher bist, dass das andere Script wirklich beendet wurde, dann könntest Du mit dem GPIO.cleanup() das tatsächlich beheben. Oder - falls Du nur diesen einen Pin freigeben willst, dann würde sowas gehen:
Python:
import RPi.GPIO as GPIO

GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.OUT)
GPIO.cleanup(17)

Aber wie gesagt: Stell sicher, dass der andere Prozess nicht mehr läuft!
 

Neue Themen


Oben