raspberry pi sound based traffic lights - python

I am trying to implement a sensor-based traffic light for a school project. By that I mean, there is a sound sensor LM393 that acts as a switch. When it detects a sound, it will change the sequence of the traffic lights. For example, the traffic light would be something like this: Red LED for 2 sec, turn off red, yellow LED for 2 sec, turn off yellow, green led for 2 sec, turn off green, then this cycle repeats itself. If a sound is detected, the sequence is interrupted and the green light immediately becomes green for 5 sec and then the normal cycle starts again.
This is what I have so far:
import RPi.GPIO as GPIO
from time import sleep
from threading import Thread
from gpiozero import LED
#GPIO SETUP
red = LED(17)
gre=LED(24)
yel = LED(27)
channel = 23
emer_detec = False
GPIO.setmode(GPIO.BCM)
GPIO.setup(channel, GPIO.IN, pull_up_down = GPIO.PUD_UP)
def sound():
GPIO.add_event_detect(channel, GPIO.BOTH, bouncetime=1000) # let us know when the pin goes HIGH or LOW
GPIO.add_event_callback(channel, callback) # assign function to GPIO PIN, Run function on change
def regular():
while True:
if not GPIO.input(channel):
red.on()
sleep(2)
red.off()
yel.on()
sleep(2)
yel.off()
gre.on()
sleep(2)
gre.off()
def callback(channel):
print('Emergency vehicle detected')
red.off()
yel.off()
gre.on()
sleep(5)
gre.off()
sound_thread= Thread(target=sound)
sound_thread.daemon= True
sound_thread.start()
regular_thread= Thread(target=regular)
regular_thread.daemon= True
regular_thread.start()
# infinite loop
while True:
pass
At first, the two threads are running in parallel when there is a sound and all lights go off as expected. However, when the green light is turned on, the normal cycle is also running. How can I stop the normal cycle thread when the other thread is working? Is there any way to do this without using threads?

One quick way to solve this might be to have some kind of global flag that handles the state of the system. For example,
IS_REGULAR = True
def regular():
while True:
if not GPIO.input(channel) and not IS_REGULAR:
for col in [red, yel, gre]:
col.on()
sleep(2)
col.off()
if not IS_REGULAR: break
def callback(channel):
global IS_REGULAR
IS_REGULAR = False
print('Emergency vehicle detected')
red.off()
yel.off()
gre.on()
sleep(5)
gre.off()
IS_REGULAR = True

Related

How can run a time while checking for input from a PS at the same time?

I am trying to code a trafic light on a raspeberry pi and i am having trouble with a timer. The goal is to triger a trafic light sequence when ether one of two conditions is met.
condition 1: the Pushbutton is pressed 5 times.
or
condition 2: a timer expires allowing the sequence to start.
i have the following code:
#Importing Libraries
from gpiozero import Button, TrafficLights #enables the use of a pushbutton
from time import sleep #enables the use of a timer
#assign pins on raspberry pi
lightsA=TrafficLights(16,20,21) #assigns colors to traffic light of street A (R,A,G)
lightsB=TrafficLights(25,8,7) #assigns colors to traffic light of street B (R,A,G)
button = Button(10) #assigns pin ten to pushbutton
lightsA.red.on() #street A starts red by defaul
lightsB.green.on() #street A starts red by defaul
#keeps the program running in a loop until the setpoint is reached
count=0 #initial counter
while True:
button.wait_for_press()
button.wait_for_release()
count += 1 #increases counter by 1 when PS is pressed and released
def timer():
sleep(5)
return True
#when the button is pressed 5 times the setpoint is reached.
if count == 5 or timer() :
lightsB.green.off()
lightsB.amber.on()
sleep(4)
lightsB.amber.off()
lightsB.red.on()
sleep(1)
lightsA.red.off()
lightsA.green.on()
sleep(15)
lightsA.green.off()
lightsA.amber.on()
sleep()
lightsA.amber.off()
lightsA.red.on()
sleep(1)
lightsB.red.off()
lightsB.green.on()
I tried adding an elif statement as shown below, but once the pushbutton is pressed once, the timer starts and it stops counting is the pushbutton is press again so if the push button is pressed again it wount keep counting and the only way out is to let the program finish.
elif 0 < count < 5: #if the counter expires berore the count reaches 5, sequence starts.
sleep(5)
lightsB.green.off()
lightsB.amber.on()
sleep(4)
lightsB.amber.off()
lightsB.red.on()
sleep(1)
lightsA.red.off()
lightsA.green.on()
sleep(10) #Here the green light is shorter because volume is less.
lightsA.green.off()
lightsA.amber.on()
sleep(4)
lightsA.amber.off()
lightsA.red.on()
sleep(1)
lightsB.red.off()
lightsB.green.on()

How to make an LED on, in micropython by adding 5 seconds each time you press a push button

could you please help me :
I want to make an LED ON by pressing a button it Should stays ON for 5 seconds, but I want it to, if I push the button while it's ON, it will stay ON as long as the time added up. for example: when the LED is On and I push the button another time, it will be ON for 10 seconds.
I'm using raspberry pi pico, with Thonny
Here is my code :
from machine import Pin, Timer
import time
White_LED = Pin(15, Pin.OUT)
button = Pin(14, Pin.IN, Pin.PULL_DOWN)
while True:
if button.value() == 1:
White_LED.on()
time.sleep(5)
White_LED.off()
At the moment when you sleep for 5 seconds, the code stops. So, it won't notice if you press the button again.
I think you'll need to make use of interrupt handlers (https://docs.micropython.org/en/v1.8.6/pyboard/reference/isr_rules.html) , or you could implement a simple event loop yourself.
An event loop keeps looking for things that happen and performs some action when it does. Here's a rough idea of how you might do it.
from machine import Pin, Timer
import time
White_LED = Pin(15, Pin.OUT)
button = Pin(14, Pin.IN, Pin.PULL_DOWN)
button_was = 0
light_on_until = 0
while True:
# See if the state of the button has changed
button_now = button.value()
if button_now != button_was:
button_was = button_now
if button_now == 1:
# button is down, but it was up.
# Increase light on time by 5 seconds
if light_on_until > time.ticks_ms():
# light is already on, increase the time by 5,000 ms
light_on_until += 5000
else:
# light isn't on, so set time to 5 seconds from now (5,000 ms)
light_on_until = time.ticks_ms() + 5000
if light_on_until > time.ticks_ms():
# light should be on, so if it's currently off, switch it on
if White_LED.value() == 0:
White_LED.on()
else:
# light should be off, so if it's currently on, switch it off
if White_LED.value() == 1:
White_LED.off()

Using a sound sensor to collect data every 6 seconds and display if no sound is detected

I'm trying to collect sound data from a sound sensor connected to a raspberry pi 4. Right now I have it set up where it will print 1 every time sound is detected. However, when I try to add an else statement to print 0 when no sound is detected, it will only print 0 even if there is constant sound being played.
This is the code that works fine displaying 1 every time sound is detected.
import RPi.GPIO as GPIO
import time
SND_SNSR = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(SND_SNSR,GPIO.IN)
while True:
if (GPIO.input(SND_SNSR) == GPIO.LOW):
print("1")
time.sleep(0.1)
And this is the code I have for trying to get it to display every 6 seconds and display either 1 or 0 for sound or no sound but it's not working.
import RPi.GPIO as GPIO
import time
SND_SNSR = 18
GPIO.setmode(GPIO.BCM)
GPIO.setup(SND_SNSR,GPIO.IN)
while True:
if (GPIO.input(SND_SNSR) == GPIO.LOW):
print("1")
else:
print("0")
time.sleep(6)
Thanks for any help.

how to make a counter inside a loop in python 3?

I'm working on PIR sensor in order to detect the movement of human beings. Here is below the code that currently I am using and I just need to make a counter inside the loop in order to count the # of movements. Thanks in advance!!
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.IN) # PIR motion sensor
GPIO.setup(3, GPIO.OUT) #LED output pin
while True:
i=GPIO.input(11)
if i==0: #sensor is LOW
print "Not Occupied",i
GPIO.output(3, 0) #Turn OFF LED
time.sleep(0.1)
elif i==1: # sensor is HIGH
print "Occupied",i
GPIO.output(3, 1) #Turn ON LED
time.sleep(0.1)
When I was starting with Raspberry Pi, I was using only RPi.GPIO library, but now I am using only gpiozero library. I think, it is more clear than RPi.GPIO
Here is my solution of your problem using library gpiozero instead of RPi.GPIO:
from gpiozero import LED, MotionSensor
from signal import pause
pir = MotionSensor(11)
led = LED(3)
motion_counter = 0
def on_motion():
global motion_counter
led.on()
motion_counter += 1
print(motion_counter)
def on_no_motion():
led.off()
pir.when_motion = on_motion
pir.when_no_motion = on_no_motion
pause()
More about this great library: https://gpiozero.readthedocs.io/en/stable/
Your question is kind of confusing but here is how you would set a counter
counter = 0
while True:
counter += 1
i=GPIO.input(11)
if i==0: #sensor is LOW
print "Not Occupied",i
GPIO.output(3, 0) #Turn OFF LED
time.sleep(0.1)
elif i==1: # sensor is HIGH
print "Occupied",i
GPIO.output(3, 1) #Turn ON LED
time.sleep(0.1)`
print(counter)

Counter in Python for Rising Edges

Dear Stackoverflow Community!
I am currently on my first Project working with a Raspberry Pi. The task is to implement a TY-010 Photo Interruptor Sensor. What I want to do is following:
I want to count the interruptions in a given time (i.e 2 seconds). So something like that(not C, in Python):
d count how many Interruptions there are.
int i = 0
while(time != 3){
if(outputFunction == True)
i += 1;
}
You can find the whole Code beneath:
import RPi.GPIO as GPIO
import time
GPIO_PIN = 24
GPIO.setup(GPIO_PIN, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
print "Sensor-Test [Press STRG+C, to exit the Test]"
def outputFunction(null):
print("Signal detected")
GPIO.add_event_detect(GPIO_PIN, GPIO.RISING, callback=ausgabeFunktion, bouncetime=100)
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
GPIO.cleanup()
I am thankful for any help or advise !
You have wrong defined ouputFunction, if you want a function without arguments just leave it empty, like this:
def outputFunction():
print("Signal detected")
You can add a statement to verify if have passed x seconds, if you do time.sleep() you are stopping your code and if you press the button it won't work, so do it this way:
try:
t_to_wait = 2 #Set to 2 secs
t1 = time.time() #Get the start time
while True:
if GPIO.input(GPIO_PIN) == 1:
outputFunction()
if t1-time.time() > t_to_wait:
break #Exit the loop if have passed t_to_wait seconds
except KeyboardInterrupt:
GPIO.cleanup()
I also would recommend you to read some examples because it seems that you don't know python very well and the use of the GPIO module

Categories

Resources