Pygame freeze auf RaspberryPi

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
petemanzel
User
Beiträge: 4
Registriert: Sonntag 23. Juni 2019, 08:57

Hallo, ich habe mein erstes Pythonscript mit dem Pygamemodul geschrieben welchesauf einem RaspberryPi 3 B+ für eine genze weile (1-2 Std.) super läuft. Dann friert alles ein und muss alles neustarten (Hardreset).

Kann das an meinem Script liegen?

Vielen Dank für jede Hilfe!

Code: Alles auswählen

import pygame, sys
from pygame.locals import *

import RPi.GPIO as GPIO                    
import time

GPIO.cleanup()

#Screen Resolution
WIDTH = 1920
HEIGHT = 1080
SEGMENT = WIDTH/4
BALKEN_HEIGHT = 500

#Colors
WHITE=(255,255,255)
black=(60,60,60)

green=(86,155,81)
yellow=(233,180,24)
red=(232,79,45)
blue=(34,159,163)

light_green=(170,204,168)
light_yellow=(255,218,147)
light_red=(245,175,143)
light_blue=(169,205,209)

#Images
image_buttom  = pygame.image.load("/home/pi/KEAN_Paris/Balken_unten_Paris.png")
image_top = pygame.image.load('/home/pi/KEAN_Paris/Balken_oben_Paris.png')

clock = pygame.time.Clock()

GPIO.setmode(GPIO.BCM)                      #Set GPIO pin numbering

#Sensor 1
TRIG4 = 14                                  
ECHO4 = 15
GPIO.setup(TRIG4,GPIO.OUT)                  #Set pin as GPIO out
GPIO.setup(ECHO4,GPIO.IN)                   #Set pin as GPIO in
seq4 = []                                   #Array for averaging

#Sensor 2
TRIG3 = 23                                  
ECHO3 = 24
GPIO.setup(TRIG3,GPIO.OUT)                   #Set pin as GPIO out
GPIO.setup(ECHO3,GPIO.IN)                    #Set pin as GPIO in
seq3 = []                                   #Array for averaging

#Sensor 3
TRIG2 = 8                                  
ECHO2 = 7
GPIO.setup(TRIG2,GPIO.OUT)                   #Set pin as GPIO out
GPIO.setup(ECHO2,GPIO.IN)                    #Set pin as GPIO in
seq2 = []                                   #Array for averaging

#Sensor 4
TRIG1 = 20                                  
ECHO1 = 21
GPIO.setup(TRIG1,GPIO.OUT)                   #Set pin as GPIO out
GPIO.setup(ECHO1,GPIO.IN)                    #Set pin as GPIO in
seq1 = []                                   #Array for averaging


#------------------------------------------------------------------------------------
def readSensor(trigger, echo):

    if True:
        GPIO.output(trigger, False)                    #Set TRIG as LOW
        #print ("Waitng For Sensor To Settle")
        #time.sleep(0.1)                         #Delay of 0.00001 seconds

        GPIO.output(trigger, True)                     #Set TRIG as HIGH
        time.sleep(0.00001)                         #Delay of 0.00001 seconds
        GPIO.output(trigger, False)                    #Set TRIG as LOW

        while GPIO.input(echo)==0:                  #Check whether the ECHO is LOW
            pulse_start = time.time()               #Saves the last known time of LOW pulse

        while GPIO.input(echo)==1:                  #Check whether the ECHO is HIGH
            pulse_end = time.time()                 #Saves the last known time of HIGH pulse 

        pulse_duration = pulse_end - pulse_start    #Get pulse duration to a variable
        DISTANCE = pulse_duration * 17150           #Multiply pulse duration by 17150 to get DISTANCE
        DISTANCE = round(DISTANCE, 3)               #Round to two decimal points

    return DISTANCE
    
#------------------------------------------------------------------------------------
def averageSensor(array, source):

    array.append(source)

    while len(array)>16:
        del array[0]

    average = sum(array) / len(array)
    average = round(average, 3)               #Round to two decimal points
    return average


#------------------------------------------------------------------------------------
def translate(value, leftMin, leftMax, rightMin, rightMax):

    # Figure out how 'wide' each range is
    leftSpan = leftMax - leftMin
    rightSpan = rightMax - rightMin

    # Convert the left range into a 0-1 range (float)
    valueScaled = float(value - leftMin) / float(leftSpan)

    # Convert the 0-1 range into a value in the right range.
    return rightMin + (valueScaled * rightSpan)
    print ("translate")




#----------------------------------------------------------------------------------
def main():
    pygame.init()
    pygame.font.init()
    pygame.mouse.set_visible(0) 
    font = pygame.font.SysFont("PibotoCondensed", 120, True)
    #frame_rate = 20
    
    #DISPLAY=pygame.display.set_mode((WIDTH,HEIGHT))

    DISPLAY=pygame.display.set_mode((0,0), pygame.FULLSCREEN)
    while True:
        
        for event in pygame.event.get():
            if event.type==QUIT:
                pygame.quit()
                sys.exit()


        keys=pygame.key.get_pressed()
        if keys[pygame.K_ESCAPE]:
            pygame.quit()

        pygame.draw.rect(DISPLAY,light_green,(0,0,WIDTH/4,HEIGHT))
        pygame.draw.rect(DISPLAY,light_yellow,(SEGMENT,0,WIDTH/4,HEIGHT))
        pygame.draw.rect(DISPLAY,light_red,(SEGMENT*2,0,WIDTH/4,HEIGHT))
        pygame.draw.rect(DISPLAY,light_blue,(SEGMENT*3,0,WIDTH/4,HEIGHT))
        
        
        BALKEN_green = readSensor(TRIG4, ECHO4)
        average4 = averageSensor(seq4, BALKEN_green)
        #print (average4)                                   #read Sensor max/min values for setup 
        green_HEIGHT = translate(average4,13,37,HEIGHT-580/214*139,HEIGHT)

        BALKEN_yellow = readSensor(TRIG3, ECHO3)
        average3 = averageSensor(seq3, BALKEN_yellow)
        #print (average3)                                   #read Sensor max/min values for setup 
        yellow_HEIGHT = translate(average3,6,23.5,HEIGHT-580,HEIGHT)

        BALKEN_red = readSensor(TRIG2, ECHO2)
        average2 = averageSensor(seq2, BALKEN_red)
        #print (average2)                                   #read Sensor max/min values for setup 
        red_HEIGHT = translate(average2,13,37,HEIGHT-580/214*32,HEIGHT)

        BALKEN_blue = readSensor(TRIG1, ECHO1)
        average1 = averageSensor(seq1, BALKEN_blue)
        #print (average1)                                   #read Sensor max/min values for setup 
        blue_HEIGHT = translate(average1,18,38,HEIGHT-580/214*38,HEIGHT)
               

        pygame.draw.rect(DISPLAY,green,[0,green_HEIGHT-250,WIDTH/4,HEIGHT],0)
        pygame.draw.rect(DISPLAY,yellow,(SEGMENT,yellow_HEIGHT-250,WIDTH/4,HEIGHT))
        pygame.draw.rect(DISPLAY,red,[SEGMENT*2,red_HEIGHT-250,WIDTH/4,HEIGHT],0)
        pygame.draw.rect(DISPLAY,blue,(SEGMENT*3,blue_HEIGHT-250,WIDTH/4,HEIGHT))

        DISPLAY.blit(image_buttom,(0,HEIGHT-250))
        DISPLAY.blit(image_top,(0,0))

        #green Text
        co2value_green = translate(average4,13,37,139,0)
        co2value_green = round(co2value_green,)
        if co2value_green <= 0:
            co2value_green = 0
        if co2value_green >= 139:
            co2value_green = 139

        co2_green = "{0}".format(co2value_green)
        text = font.render(co2_green, True, black)
        text_rect = text.get_rect(center=(SEGMENT/2, 500))
        DISPLAY.blit(text, text_rect)

        #yellow Text
        co2value_yellow = translate(average3,6,23.5,214,0)
        co2value_yellow = round(co2value_yellow,)
        if co2value_yellow <= 0:
            co2value_yellow = 0
        if co2value_yellow >= 214:
            co2value_yellow = 214
            
        co2_yellow = "{0}".format(co2value_yellow)
        text = font.render(co2_yellow, True, black)
        text_rect = text.get_rect(center=(SEGMENT+SEGMENT/2, 500))
        DISPLAY.blit(text, text_rect)

        #red Text
        co2value_red = translate(average2,13,37,32,0)
        co2value_red = round(co2value_red,)
        if co2value_red <= 0:
            co2value_red = 0
        if co2value_red >= 32:
            co2value_red = 32
            
        co2_red = "{0}".format(co2value_red)
        text = font.render(co2_red, True, black)
        text_rect = text.get_rect(center=(SEGMENT*2+SEGMENT/2, 500))
        DISPLAY.blit(text, text_rect)

        #blue Text
        co2value_blue = translate(average1,18,38,38,0)
        co2value_blue = round(co2value_blue,)
        if co2value_blue <= 0:
            co2value_blue = 0
        if co2value_blue >= 38:
            co2value_blue = 38

        co2_blue = "{0}".format(co2value_blue)
        text = font.render(co2_blue, True, black)
        text_rect = text.get_rect(center=(SEGMENT*3+SEGMENT/2, 500))
        DISPLAY.blit(text, text_rect)

        pygame.event.pump()
        pygame.display.update()

        clock.tick(30)

main()
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

ich vermute eher RPi.GPIO. Das ist Mist. Ersetz das mal mit pigpio & schau, ob’s besser wird.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Das ›as‹ bei Import benutzt man, um einem Modul einen anderen Namen zu geben, aber das heißt schon GPIO, das `as` ist also unsinnig.
GPIO.cleanup wird am Ende des Programms, nicht am Anfang, aufgerufen.

Funktionen und Variablenamen schreibt man klein_mit_unterstrich. Nur Konstanten werden KOMPLETT_GROSS geschrieben.

Warum hat Sensor 1 die Nummer 4 und Sensor 1 die Nummer 1?
Dass Du fast alles für jeden der 4 Sensoren im Code kopiert hast, macht in lang und schlecht wartbar. Das was Du machst, ist schon so komplex, dass es sinnvoll ist, dafür eine Klasse zu definieren.

In ›readSensor‹ hast Du busy-Waits für das Signal, ohne aber einen Timeout definiert zu haben. Benutzte wait_for_edge oder besser noch event_dectect, um alle 4 Sensoren gleichzeitig abzufragen.

Man rundet erst bei der Ausgabe. Vor allem der falsche Kommentar!
›averageSensor‹ ist besonders kritisch, weil Du da ein Array veränderst, ohne das explizit klar zu machen.
petemanzel
User
Beiträge: 4
Registriert: Sonntag 23. Juni 2019, 08:57

Hallo Sirius3.

Vielen Dank für deine Hilfe.
Ich habe so gut ich kann deine Tips umgesetzt.

Sirius3 hat geschrieben: Sonntag 23. Juni 2019, 14:01 Das ›as‹ bei Import benutzt man, um einem Modul einen anderen Namen zu geben, aber das heißt schon GPIO, das `as` ist also unsinnig.
GPIO.cleanup wird am Ende des Programms, nicht am Anfang, aufgerufen.

Funktionen und Variablenamen schreibt man klein_mit_unterstrich. Nur Konstanten werden KOMPLETT_GROSS geschrieben.

Warum hat Sensor 1 die Nummer 4 und Sensor 1 die Nummer 1?
Dass Du fast alles für jeden der 4 Sensoren im Code kopiert hast, macht in lang und schlecht wartbar. Das was Du machst, ist schon so komplex, dass es sinnvoll ist, dafür eine Klasse zu definieren.

In ›readSensor‹ hast Du busy-Waits für das Signal, ohne aber einen Timeout definiert zu haben. Benutzte wait_for_edge oder besser noch event_dectect, um alle 4 Sensoren gleichzeitig abzufragen.

Man rundet erst bei der Ausgabe. Vor allem der falsche Kommentar!
›averageSensor‹ ist besonders kritisch, weil Du da ein Array veränderst, ohne das explizit klar zu machen.
zu 1. Muss ich mal auf dem Pi ausprobieren
zu 2. Habe nun alles klein geschrieben
zu.3. Habe jetzt die Reihenfolge korrigiert
Ich habe noch nie eine Klasse definiert. Würde ich aber gerne.
zu 3. Habe das jetzt mit event_detect geändert (ist das so richtig?)
zu 4. Ich runde doch bei der Ausgabe der funktion. Kommentar ist jetzt korrigiert.

Code: Alles auswählen

import pygame, sys
from pygame.locals import *

import RPi.GPIO as GPIO                 
import time

#Screen Resolution
width = 1920
height = 1080
segment = width/4
balken_height = 500

#Colors
WHITE=(255,255,255)
black=(60,60,60)

green=(86,155,81)
yellow=(233,180,24)
red=(232,79,45)
blue=(34,159,163)

light_green=(170,204,168)
light_yellow=(255,218,147)
light_red=(245,175,143)
light_blue=(169,205,209)

#Images
image_buttom  = pygame.image.load("/home/pi/KEAN_Paris/Balken_unten_Paris.png")
image_top = pygame.image.load('/home/pi/KEAN_Paris/Balken_oben_Paris.png')

clock = pygame.time.Clock()

GPIO.setmode(GPIO.BCM)                                  #Set GPIO pin numbering

#Sensor 1
trig1 = 20                                  
echo1 = 21
GPIO.setup(trig1,GPIO.OUT)                              #Set pin as GPIO out
GPIO.setup(echo1,GPIO.IN)                               #Set pin as GPIO in
seq1 = []                                               #Array for averaging

#Sensor 2
trig2 = 8                                  
echo2 = 7
GPIO.setup(trig2,GPIO.OUT)                              #Set pin as GPIO out
GPIO.setup(echo2,GPIO.IN)                               #Set pin as GPIO in
seq2 = []                                               #Array for averaging

#Sensor 3
trig3 = 23                                  
echo3 = 24
GPIO.setup(trig3,GPIO.OUT)                              #Set pin as GPIO out
GPIO.setup(echo3,GPIO.IN)                               #Set pin as GPIO in
seq3 = []                                               #Array for averaging

#Sensor 4
trig4 = 14                                  
echo4 = 15
GPIO.setup(trig4,GPIO.OUT)                              #Set pin as GPIO out
GPIO.setup(echo4,GPIO.IN)                               #Set pin as GPIO in
seq4 = []                                               #Array for averaging

#------------------------------------------------------------------------------------
def readSensor(trigger, echo):

    if True:
        GPIO.output(trigger, False)                     #Set trig as LOW
        #print ("Waitng For Sensor To Settle")
        #time.sleep(0.1)                                #Delay of 0.00001 seconds

        GPIO.output(trigger, True)                      #Set trig as HIGH
        time.sleep(0.00001)                             #Delay of 0.00001 seconds
        GPIO.output(trigger, False)                     #Set trig as LOW

        GPIO.add_event_detect(echo, GPIO.RISING)        #Add rising edge detection on a channel
        while GPIO.event_detected(echo)==0:             #Check whether the echo is LOW
            pulse_start = time.time()                   #Saves the last known time of LOW pulse

        while GPIO.event_detected(echo)==1:             #Check whether the echo is HIGH
            pulse_end = time.time()                     #Saves the last known time of HIGH pulse 

        pulse_duration = pulse_end - pulse_start        #Get pulse duration to a variable
        distance = pulse_duration * 17150               #Multiply pulse duration by 17150 to get distance
        distance = round(distance, 3)                   #Round to three decimal points

    return distance
    
#------------------------------------------------------------------------------------
def averageSensor(array, source):

    array.append(source)

    while len(array)>16:                                #Set the size of the array
        del array[0]                                    #Delete the oldest value of the array

    average = sum(array) / len(array)                   #Calculate average
    average = round(average, 3)                         #Round to three decimal points
    return average


#------------------------------------------------------------------------------------
def translate(value, leftMin, leftMax, rightMin, rightMax):

    # Figure out how 'wide' each range is
    leftSpan = leftMax - leftMin
    rightSpan = rightMax - rightMin

    # Convert the left range into a 0-1 range (float)
    valueScaled = float(value - leftMin) / float(leftSpan)

    # Convert the 0-1 range into a value in the right range.
    return rightMin + (valueScaled * rightSpan)
    print ("translate")




#----------------------------------------------------------------------------------
def main():
    pygame.init()
    pygame.font.init()
    pygame.mouse.set_visible(0) 
    font = pygame.font.SysFont("PibotoCondensed", 120, True)
        
    #DISPLAY=pygame.display.set_mode((width,height))

    DISPLAY=pygame.display.set_mode((0,0), pygame.FULLSCREEN)
    while True:
        
        for event in pygame.event.get():
            if event.type==QUIT:
                pygame.quit()
                sys.exit()


        keys=pygame.key.get_pressed()
        if keys[pygame.K_ESCAPE]:
            pygame.quit()

        pygame.draw.rect(DISPLAY,light_green,(0,0,width/4,height))
        pygame.draw.rect(DISPLAY,light_yellow,(segment,0,width/4,height))
        pygame.draw.rect(DISPLAY,light_red,(segment*2,0,width/4,height))
        pygame.draw.rect(DISPLAY,light_blue,(segment*3,0,width/4,height))
        
        
        balken_green = readSensor(trig4, echo4)
        average4 = averageSensor(seq4, balken_green)
        #print (average4)                                           #read Sensor max/min values for setup 
        green_height = translate(average4,13,37,height-580/214*139,height)

        balken_yellow = readSensor(trig3, echo3)
        average3 = averageSensor(seq3, balken_yellow)
        #print (average3)                                           #read Sensor max/min values for setup 
        yellow_height = translate(average3,6,23.5,height-580,height)

        balken_red = readSensor(trig2, echo2)
        average2 = averageSensor(seq2, balken_red)
        #print (average2)                                           #read Sensor max/min values for setup 
        red_height = translate(average2,13,37,height-580/214*32,height)

        balken_blue = readSensor(trig1, echo1)
        average1 = averageSensor(seq1, balken_blue)
        #print (average1)                                           #read Sensor max/min values for setup 
        blue_height = translate(average1,18,38,height-580/214*38,height)
               

        pygame.draw.rect(DISPLAY,green,[0,green_height-250,width/4,height],0)
        pygame.draw.rect(DISPLAY,yellow,(segment,yellow_height-250,width/4,height))
        pygame.draw.rect(DISPLAY,red,[segment*2,red_height-250,width/4,height],0)
        pygame.draw.rect(DISPLAY,blue,(segment*3,blue_height-250,width/4,height))

        DISPLAY.blit(image_buttom,(0,height-250))
        DISPLAY.blit(image_top,(0,0))

        #green Text
        co2value_green = translate(average4,13,37,139,0)
        co2value_green = round(co2value_green,)
        if co2value_green <= 0:
            co2value_green = 0
        if co2value_green >= 139:
            co2value_green = 139

        co2_green = "{0}".format(co2value_green)
        text = font.render(co2_green, True, black)
        text_rect = text.get_rect(center=(segment/2, 500))
        DISPLAY.blit(text, text_rect)

        #yellow Text
        co2value_yellow = translate(average3,6,23.5,214,0)
        co2value_yellow = round(co2value_yellow,)
        if co2value_yellow <= 0:
            co2value_yellow = 0
        if co2value_yellow >= 214:
            co2value_yellow = 214
            
        co2_yellow = "{0}".format(co2value_yellow)
        text = font.render(co2_yellow, True, black)
        text_rect = text.get_rect(center=(segment+segment/2, 500))
        DISPLAY.blit(text, text_rect)

        #red Text
        co2value_red = translate(average2,13,37,32,0)
        co2value_red = round(co2value_red,)
        if co2value_red <= 0:
            co2value_red = 0
        if co2value_red >= 32:
            co2value_red = 32
            
        co2_red = "{0}".format(co2value_red)
        text = font.render(co2_red, True, black)
        text_rect = text.get_rect(center=(segment*2+segment/2, 500))
        DISPLAY.blit(text, text_rect)

        #blue Text
        co2value_blue = translate(average1,18,38,38,0)
        co2value_blue = round(co2value_blue,)
        if co2value_blue <= 0:
            co2value_blue = 0
        if co2value_blue >= 38:
            co2value_blue = 38

        co2_blue = "{0}".format(co2value_blue)
        text = font.render(co2_blue, True, black)
        text_rect = text.get_rect(center=(segment*3+segment/2, 500))
        DISPLAY.blit(text, text_rect)

        pygame.event.pump()
        pygame.display.update()

        clock.tick(30)
        
        GPIO.cleanup()


main()
petemanzel
User
Beiträge: 4
Registriert: Sonntag 23. Juni 2019, 08:57

Hallo deets,
hab das versucht aber das Script bleibt dann sofort beim cleanup() hängen.
__deets__ hat geschrieben: Sonntag 23. Juni 2019, 09:23 ich vermute eher RPi.GPIO. Das ist Mist. Ersetz das mal mit pigpio & schau, ob’s besser wird.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

? Was hast du versucht? Hast du Code? Und Fehlermeldungen?
petemanzel
User
Beiträge: 4
Registriert: Sonntag 23. Juni 2019, 08:57

__deets__ hat geschrieben: Sonntag 23. Juni 2019, 21:33 ? Was hast du versucht? Hast du Code? Und Fehlermeldungen?

Code: Alles auswählen

GPIO.setmode(GPIO.BCM)                                  #Set GPIO pin numbering
Hier bekomme ich die folgende Fehlermeldung:
module 'pigpio' has no attribute 'setmode'
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Niemand hat gesagt, dass man pigpio ohne Änderung einfach als Ersatz für RPIO nutzen kann.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du musst schon die Dokumentation zu pigpio lesen. Installieren. Und deinen code umschreiben.
Antworten