0

Thanks to the community i create a scrip that check status of 3 ultrasonic sensors and depending on the status omxplayer will play a movie or other. Problem is that after few while and video loops CPU got blocket at 100% and PI is not able to read sensor information. Here you can find the code and the CPU status

#!/usr/bin/python
# -----------------------
# Import required Python libraries
# -----------------------
import time
import RPi.GPIO as GPIO
import os
import sys
from subprocess import Popen
import pygame
from pygame.locals import *

# -----------------------
# Define some functions
# -----------------------

def measure(trig, echo, fstime):
# Define GPIO variables
GPIO_TRIGGER = trig
GPIO_ECHO    = echo

GPIO.setup(GPIO_TRIGGER,GPIO.OUT)  # Trigger
GPIO.setup(GPIO_ECHO,GPIO.IN)      # Echo

GPIO.output(GPIO_TRIGGER, False)

if fstime:
   print ("Waiting For Sensor To Settle")
   time.sleep(2)

# This function measures a distance
GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
start = time.time()

while GPIO.input(GPIO_ECHO)==0:
  start = time.time()

while GPIO.input(GPIO_ECHO)==1:
  stop = time.time()

elapsed = stop-start
distance = (elapsed * 17150)
distance = round(distance, 2)

return distance

# -----------------------
# Main Script
# -----------------------

# Use BCM GPIO references
# instead of physical pin numbers
GPIO.setmode(GPIO.BCM)

# Movie setup
movie1 = "/home/pi/Videos/UH3234_Overview.mp4"
movie2 = "/home/pi/Videos/UH7230_Overview.mp4"
movie3 = "/home/pi/Videos/UH3232_Overview.mp4"
movie4 = "/home/pi/Videos/general.mp4" #Ask for new one

# Setup default distances
Ddist = 5
player = False
fstime = True
p1_prev = False
p2_prev = False
p3_prev = False

print ("Sensors Measurement")
omxc = Popen(['omxplayer', '-b', '--loop', '--no-osd', movie4])
print ("Play General video: ", omxc)
general = True

pygame.init()
BLACK = (0, 0, 0)
WIDTH = 1920
HEIGTH = 1200
windowSurface = pygame.display.set_mode((WIDTH, HEIGTH), 0, 32)

try:


    while True:
        windowSurface.fill(BLACK)
        pygame.display.flip()

        dist1 = measure(23,24,fstime)
        dist2 = measure(20,21,fstime)
        dist3 = measure(13,19,fstime)

        print ("Distance 1: ", dist1)
        print ("Distance 2: ", dist2)
        print ("Distance 3: ", dist3)

        p1 = dist1 > Ddist
        p2 = dist2 > Ddist
        p3 = dist3 > Ddist

        if (p1 != p1_prev and p1):
            os.system('killall omxplayer.bin')
            omxc = Popen(['omxplayer', '-b', '--loop', '--no-osd', movie1])         
            print ("Play video1: ", omxc)
            print ("Sensor 1 active")
            general = False
        elif (p2 != p2_prev and p2):
            os.system('killall omxplayer.bin')
            omxc = Popen(['omxplayer', '-b', '--loop', '--no-osd', movie2])         
            print ("Play video2: ", omxc)
            print ("Sensor 2 active")
            general = False
        elif (p3 != p3_prev and p3):
            os.system('killall omxplayer.bin')
            omxc = Popen(['omxplayer', '-b', '--loop', '--no-osd', movie3])         
            print ("Play video3: ", omxc)
            print ("Sensor 3 active")
            general = False
        elif (not p1 and not p2 and not p3 and not general):
            os.system('killall omxplayer.bin')
            omxc = Popen(['omxplayer', '-b', '--loop', '--no-osd', movie4])         
            print ("Play General: ", omxc)
            print ("back to normal")
            general = True
        else:
            print("No video change")

        p1_prev = p1
        p2_prev = p2
        p3_prev = p3
        if (fstime):
          fstime = False
        time.sleep(1)

except KeyboardInterrupt:
    # user pressed CTRL-C
    # Reset GPIO setting
    os.system('killall omxplayer.bin')
    GPIO.cleanup()

enter image description here

Any idea what might be the issue?

Thanks for your support!

1

The most likely explanation is it gets stuck in one of the while loops.

while GPIO.input(GPIO_ECHO)==0:
   start = time.time()

while GPIO.input(GPIO_ECHO)==1:
   stop = time.time()

I would change those loops as follows.

timeout = time.time() + 1.0

start = time.time()

while GPIO.input(GPIO_ECHO)==0:
   if start > timeout:
      break
   start = time.time()

stop = time.time()

while GPIO.input(GPIO_ECHO)==1:
   if stop > timeout:
      break
   stop = time.time()
  • Hi, thanks for the answer! At this moment it the system does not fail, I will keep playing it for few hours to see the result. Thank for the tip! – Victor Ram Sep 11 at 12:43
0

Be aware that it's impossible to make a script 100% bug-free while using killall for process control. There always will be an edge case where SIGKILL will be delivered too late or even to the wrong process.

The proper solution is to note PIDs of the processes you have started, kill them using those PIDs, and then wait for them to terminate:

omxc = Popen(['omxplayer.bin', args ...]); # save the process ID in the Popen object

# now you want to stop it
omxc.terminate(); # sends the same signal as killall
omxc.wait(); # wait for omxplayer to close gracefully
  • Thanks for the tip. At this moment the problem is not the killall process but mainly the sensor reading. I'm using the killall because i need to play 3 different videos depending on the sensor that has been activated. Other option I read online was to buffer videos but it might overload the raspberry PI. Any suggestion? Thanks – Victor Ram Sep 11 at 12:48
  • @VictorRam Killing is fine as long as you kill a specific process that you have spawned. I added an example. – Dmitry Grigoryev Sep 12 at 7:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.