I was facing a problem to break counter variable after every 1 second.
This counter variable will keep tract of vehicle wheel revolution per seond which will help to calculate speed.
Also how we can pass a parameter in a function callback inside GPIO.add_event_detect() method.
My code for calculating vehicle speed is as follows :
import time
import datetime
import RPi.GPIO as GPIO
def sensorCallback(channel,cir=1.884):
#Called if sensor output changes
ts = datetime.datetime.now()
s=ts.second
count=0
if s%59==0:
count=0
else:
#Magnet
count=count+1
speed = count*cir*3600/1000
print(speed)
def main():
count=0
r=30
cir = (2*3.14*r)/100
s=0
last=0
speed=0
try:
while True :
time.sleep(0.1)
except KeyboardInterrupt:
GPIO.cleanup()
GPIO.setmode(GPIO.BCM)
GPIO.setup(17 , GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(17, GPIO.BOTH, callback=sensorCallback(count), bouncetime=200)
I have Python code running on my raspberry pi 2b and a light sensor, which measures the amount of time it takes for the capacitor of the light sensor to charge and send the pin high:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
pin_to_circuit = 7
def rc_time (pin_to_circuit):
count = 0
#Output on the pin for
GPIO.setup(pin_to_circuit, GPIO.OUT)
GPIO.output(pin_to_circuit, GPIO.LOW)
time.sleep(0.1)
#Change the pin back to input
GPIO.setup(pin_to_circuit, GPIO.IN)
#Count until the pin goes high
while (GPIO.input(pin_to_circuit) == GPIO.LOW):
count += 1
if count > 1000000:
return True
else:
return count
#Catch when script is interrupted, cleanup correctly
try:
# Main loop
while True:
print rc_time(pin_to_circuit)
except KeyboardInterrupt:
pass
finally:
GPIO.cleanup()
I want when the count goes higher than 1000000, a MG90S, that I have also connected to the pi and a 4AA battery pack, moves about 90 degrees.
The code I was trying to integrate to move the servo:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
p.ChangeDutyCycle(7.5) # turn towards 90 degree
time.sleep(1) # sleep 1 second
p.stop()
GPIO.cleanup()
I want to combine these two Python codes. I tried for a bit, but I have almost no Python experience.
The code is now:
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
pin_to_circuit = 7
def move_90_degrees():
GPIO.setmode(GPIO.BOARD)
GPIO.setup(12, GPIO.OUT)
p = GPIO.PWM(12, 50)
p.start(7.5)
p.ChangeDutyCycle(7.5) # turn towards 90 degree
time.sleep(1) # sleep 1 second
p.stop()
def rc_time (pin_to_circuit):
count = 0
#Output on the pin for
GPIO.setup(pin_to_circuit, GPIO.OUT)
GPIO.output(pin_to_circuit, GPIO.LOW)
time.sleep(0.1)
#Change the pin back to input
GPIO.setup(pin_to_circuit, GPIO.IN)
#Count until the pin goes high
while (GPIO.input(pin_to_circuit) == GPIO.LOW):
count += 1
if count > 1000000:
return True
move_90_degrees()
else:
return count
#Catch when script is interrupted, cleanup correctly
try:
# Main loop
while True:
print rc_time(pin_to_circuit)
except KeyboardInterrupt:
pass
finally:
GPIO.cleanup()
The code does print True when the count exceeds 1000000, but the servo still doesn't move. The servo code on its own does however work correctly. (I forgot a bit of the servo code, that's why p wasn't defined, sorry.)
You could just integrate the code block you are using to move the MG90S into a function, insert it before or below your def rc_time (pin_to_circuit): (but first you have to define p inside, its not really clear what p refers to):
New Function from second code block:
def move_90_degrees():
p = '???'
GPIO.setup(12, GPIO.OUT)
p.ChangeDutyCycle(7.5) # turn towards 90 degree
time.sleep(1) # sleep 1 second
p.stop()
After defining this function, call it inside your first block like:
if count > 1000000:
move_90_degrees()
return True
else:
return count
That should work.
I've made a mistake in the code. I changed the order of the function call inside of the
if count > 1000000:
return True
move_90_degrees()
else:
return count
block to :
if count > 1000000:
move_90_degrees()
return True
else:
return count
otherwise, the code returns before the function call is executed. Is it working now?
I'm working on a Raspberry Pi project which displays a different video-loop depending on which of the 3 PIR motion sensors are "sensing motion". When no sensors are sensing anything, I want to display an additional video. So all in all there are 4 videos: left, middle, right, not-active.
Using Python 3.4.2 , I have managed to get videos playing when sensors are activated, but I am having difficulties getting a video to play when none of the sensors are active. I thought it would be a simple 'else' like clause, but apparently it is not. I've tried many different methods, but have ran out of ideas. Can someone help me integrate a "no motion detected" return to the code? The code is as below:
''' Import required stuff '''
import RPi.GPIO as GPIO #GPIO
import time #for delay
import subprocess #for omxplayer
''' GPIO setup '''
GPIO.setmode(GPIO.BCM) #GPIO setmode
PIR_PIN_L = 23 #define left pin
PIR_PIN_R = 24 #define right pin
PIR_PIN_M = 25 #define middle pin
GPIO.setup(PIR_PIN_L, GPIO.IN) #set left pin
GPIO.setup(PIR_PIN_R, GPIO.IN) #set right pin
GPIO.setup(PIR_PIN_M, GPIO.IN) #set middle pin
'''Definitions '''
def MOTIONL(PIR_PIN_L): #define motion on left
print("Motion Detected on Left!") #output if motion detected
def MOTIONR(PIR_PIN_R): #define motion on right
print("Motion Detected on Right!") #output if motion detected
def MOTIONM(PIR_PIN_M): #define motion in middle
print("Motion Detected at Middle!") #output if motion detected
''' Initiation '''
print("PIR Module Test (CTRL+C to exit)")
time.sleep(4)
print("Ready")
''' Sensing '''
try:
GPIO.add_event_detect(PIR_PIN_L, GPIO.RISING, callback=MOTIONL)
GPIO.add_event_detect(PIR_PIN_M, GPIO.RISING, callback=MOTIONM)
GPIO.add_event_detect(PIR_PIN_R, GPIO.RISING, callback=MOTIONR)
while 1:
time.sleep(100)
except KeyboardInterrupt:
print("Quit")
GPIO.cleanup()
I've replaced the video parts with print("Motion detected ...") for simplicity. If you can add a print("No motion detected") when no sensors are activated, it would be very helpful.
I managed to solve the issue, and thought I'll post it in case someone wants to use it. Note that the code has been changed quite considerably. It still uses very low CPU. The only difference is that this code is more efficient at picking up motions, but at the cost of higher false readings. That may be fixed by adjusting the knobs on the PIR sensor. The same concept can be applied to the code above.
''' Import required stuff '''
import RPi.GPIO as GPIO #GPIO
import time #for delay
''' GPIO setup '''
GPIO.setmode(GPIO.BCM) #GPIO setmode
PIR_PIN_L = 23 #define left pin
PIR_PIN_R = 24 #define right pin
PIR_PIN_M = 25 #define middle pin
GPIO.setup(PIR_PIN_L, GPIO.IN) #set left pin
GPIO.setup(PIR_PIN_R, GPIO.IN) #set right pin
GPIO.setup(PIR_PIN_M, GPIO.IN) #set middle pin
'''Definitions '''
def MOTIONL(): #define motion on left
if GPIO.input(PIR_PIN_L)==1 : #trigger condtion left being active
print("Motion Detected on Left") #output
time.sleep(3)
def MOTIONR(): #define motion on right
if GPIO.input(PIR_PIN_R)==1 : #trigger condtion right being active
print("Motion Detected on Right") #output
time.sleep(3)
def MOTIONM(): #define motion in middle
if GPIO.input(PIR_PIN_M)==1 : #trigger condtion middle being active
print("Motion Detected on Middle") #output
time.sleep(3)
def NOMOTION() :
if GPIO.input(PIR_PIN_L)==0 and GPIO.input(PIR_PIN_R)==0 and GPIO.input(PIR_PIN_M)==0 :
#above trigger condition is no sensor being active
print("No Motion Detected") #output
time.sleep(3)
''' Initiation '''
print("PIR Module Test (CTRL+C to exit)")
time.sleep(4)
print("Ready")
''' Sensing '''
try:
while 1: #calls defined functions simulatanously
NOMOTION()
MOTIONR()
MOTIONL()
MOTIONM()
except KeyboardInterrupt: #CTRL and C will reset shell
print("Quit")
GPIO.cleanup()
the print commands can be replaced with whatever function you wish to call.
I have a robot I am working on and am controlling it with PWM. The way I am controlling it is with a script that sets the PWM and then exits. I need it to set the PWM and then keep running. The reason I need it to exit is because I am just calling this script through an ssh connection each time the x and y values change. Normal digital outputs continue after the program exits but PWM doesn't with the way I have it setup.
Here is my code so far. It contains a lot of print statements to try to help me figure out what the problem was.
#filename: setMotors.py
import RPi.GPIO as GPIO
from sys import argv
from time import sleep
MOTOR_EN_1_PIN = 14
MOTOR_A_1_PIN = 15
MOTOR_B_1_PIN = 18
MOTOR_EN_2_PIN = 23
MOTOR_A_2_PIN = 24
MOTOR_B_2_PIN = 25
def mixXY(x, y):
"""
mixes x and y from a joystick to values for a 2 motor drive system
input: x (int or float), y (int or float)
output: (leftMotor (float), rightMotor (float)) tuple
"""
leftMotor = y + x
rightMotor = y - x
return (leftMotor, rightMotor)
def setMotorPWMS(leftMotor, rightMotor):
#left motor
if leftMotor == 0:
print("left motor 0")
GPIO.output(MOTOR_EN_1_PIN, 0)
motor1A.stop()
motor1B.stop()
elif leftMotor < 0:
print("left motor < 0")
GPIO.output(MOTOR_EN_1_PIN, 1)
motor1A.stop()
motor1B.ChangeDutyCycle(abs(leftMotor))
else:
print("left motor else")
GPIO.output(MOTOR_EN_1_PIN, 1)
motor1A.ChangeDutyCycle(leftMotor)
motor1B.stop()
#right motor
if rightMotor == 0:
print("right motor 0")
GPIO.output(MOTOR_EN_2_PIN, 0)
motor2A.stop()
motor2B.stop()
elif rightMotor < 0:
print("right motor < 0")
GPIO.output(MOTOR_EN_2_PIN, 1)
motor2A.stop()
motor2B.ChangeDutyCycle(abs(rightMotor))
else:
print("right motor else")
GPIO.output(MOTOR_EN_2_PIN, 1)
motor2A.ChangeDutyCycle(rightMotor)
motor2B.stop()
GPIO.setwarnings(False)
#setup
GPIO.setmode(GPIO.BCM)
GPIO.setup(MOTOR_EN_1_PIN, GPIO.OUT)
GPIO.setup(MOTOR_A_1_PIN, GPIO.OUT)
GPIO.setup(MOTOR_B_1_PIN, GPIO.OUT)
GPIO.setup(MOTOR_EN_2_PIN, GPIO.OUT)
GPIO.setup(MOTOR_A_2_PIN, GPIO.OUT)
GPIO.setup(MOTOR_B_2_PIN, GPIO.OUT)
motor1A = GPIO.PWM(MOTOR_A_1_PIN, 50)
motor1B = GPIO.PWM(MOTOR_B_1_PIN, 50)
motor2A = GPIO.PWM(MOTOR_A_2_PIN, 50)
motor2B = GPIO.PWM(MOTOR_B_2_PIN, 50)
motor1A.start(0)
motor1B.start(0)
motor2A.start(0)
motor2B.start(0)
if len(argv) <= 2:
print("Need to call with x and y from commandline")
else:
motorPWM = mixXY(int(argv[1]), int(argv[2]))
leftMotorPWM = motorPWM[0]
rightMotorPWM = motorPWM[1]
print("left motor:",leftMotorPWM)
print("right motor:", rightMotorPWM)
setMotorPWMS(leftMotorPWM, rightMotorPWM)
sleep(5)
print("done")
The way it would be called is with sudo python setMotors.py x y. Is there a way of keeping the PWM going after the program exits or a better way of doing this?
The RaspberryPi doesn't support hardware PWM, so it's emulated using a software loop. Basically, it sets the GPIO, sleeps a little, resets the GPIO, sleeps a little and loops. This is done in a separated thread which is killed when the program ends.
Thus, you have to find a way to keep your program alive in the background. If you look at the official example on use of PWM, you'll notice the endless loop that keeps the program alive until manually killed.
You should also add something like
try:
while 1:
time.sleep(0.5)
except KeyboardInterrupt:
pass
p.stop()
GPIO.cleanup()
to the end of your program, or something better constructed using the signal module.
Then, leave the process in the background before destroying the console
sudo python setMotors.py x y &
You could also let your program get daemonized.
Can someone please tell me how I would modify this code to come on more than once a day? I am very new to python and trying to get my pi to run this timer. I tried adding an additional variable to the array such as SatOn2 but it is ignored. Clearly I do not understand how this works in Python. This was originally intended to run xmas lights but I am modifying to run an irrigation drip timer.
Any help greatly appreciated. Thank You!
# Raspberry Pi custom Christmas light timer
# import GPIO module
import RPi.GPIO as GPIO
# set up GPIO pins as outputs
# This convention is for the "P1" header pin convention
# where the pins start with P1 in the upper left
# and go to P26 in the lower right, with odds in the
# left column and evens in the right column.
# So, pins P1-11 and P1-12 correspond to GPIO17 and
# GPIO18 respectively.
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)
GPIO.setup(12, GPIO.OUT)
# import date and time modules
import datetime
import time
# Enter the times you want the lights to turn on and off for
# each day of the week. Default is for lights to turn on at
# 5:30pm and off at 10:30pm on weekdays, on at 5:00pm and off
# at 11:30pm on weekends. Note that this is using a 24-hour clock.
MonOn = datetime.time(hour=17,minute=30,second=0)
MonOff = datetime.time(hour=22,minute=30,second=0)
TueOn = datetime.time(hour=17,minute=30,second=0)
TueOff = datetime.time(hour=22,minute=30,second=0)
WedOn = datetime.time(hour=17,minute=30,second=0)
WedOff = datetime.time(hour=22,minute=30,second=0)
ThuOn = datetime.time(hour=17,minute=30,second=0)
ThuOff = datetime.time(hour=22,minute=30,second=0)
FriOn = datetime.time(hour=17,minute=30,second=0)
FriOff = datetime.time(hour=22,minute=30,second=0)
SatOn = datetime.time(hour=17,minute=0,second=0)
SatOff = datetime.time(hour=23,minute=30,second=0)
SunOn = datetime.time(hour=17,minute=0,second=0)
SunOff = datetime.time(hour=23,minute=30,second=0)
# Store these times in an array for easy access later.
OnTime = [MonOn, TueOn, WedOn, ThuOn, FriOn, SatOn, SunOn]
OffTime = [MonOff, TueOff, WedOff, ThuOff, FriOff, SatOff, SunOff]
# Set a "wait time" in seconds. This ensures that the program pauses
# briefly after it turns the lights on or off. Otherwise, since the
# loop will execute more than once a second, it will try to keep
# turning the lights on when they are already on (or off when they are
# already off.
waitTime = 3
# Start the loop that will run until you stop the program or turn
# off your Raspberry Pi.
while True:
# get the current time in hours, minutes and seconds
currTime = datetime.datetime.now()
# get the current day of the week (0=Monday, 1=Tuesday, 2=Wednesday...)
currDay = datetime.datetime.now().weekday()
#Check to see if it's time to turn the lights on
if (currTime.hour - OnTime[currDay].hour == 0 and
currTime.minute - OnTime[currDay].minute == 0 and
currTime.second - OnTime[currDay].second == 0):
# set the GPIO pin to HIGH, equivalent of
# pressing the ON button on the remote
GPIO.output(11, GPIO.HIGH)
# wait for a very short period of time then set
# the value to LOW, the equivalent of releasing the
# ON button
time.sleep(.5)
GPIO.output(11, GPIO.LOW)
# wait for a few seconds so the loop doesn't come
# back through and press the "on" button again
# while the lights ae already on
time.sleep(waitTime)
#check to see if it's time to turn the lights off
elif (currTime.hour - OffTime[currDay].hour == 0 and
currTime.minute - OffTime[currDay].minute == 0 and
currTime.second - OffTime[currDay].second == 0):
# set the GPIO pin to HIGH, equivalent of
# pressing the OFF button on the remote
GPIO.output(12, GPIO.HIGH)
# wait for a very short period of time then set
# the value to LOW, the equivalent of releasing the
# OFF button
time.sleep(.5)
GPIO.output(12, GPIO.LOW)
# wait for a few seconds so the loop doesn't come
# back through and press the "off" button again
# while the lights ae already off
time.sleep(waitTime)
Something like this should work:
# Raspberry Pi custom Christmas light timer
# import GPIO module
import RPi.GPIO as GPIO
# set up GPIO pins as outputs
# This convention is for the "P1" header pin convention
# where the pins start with P1 in the upper left
# and go to P26 in the lower right, with odds in the
# left column and evens in the right column.
# So, pins P1-11 and P1-12 correspond to GPIO17 and
# GPIO18 respectively.
GPIO.setmode(GPIO.BOARD)
GPIO.setup(11, GPIO.OUT)
GPIO.setup(12, GPIO.OUT)
# import date and time modules
import datetime
import time
# Enter the times you want the lights to turn on and off for
# each day of the week. Default is for lights to turn on at
# 5:30pm and off at 10:30pm on weekdays, on at 5:00pm and off
# at 11:30pm on weekends. Note that this is using a 24-hour clock.
MonOn = datetime.time(hour=17,minute=30,second=0)
MonOff = datetime.time(hour=22,minute=30,second=0)
TueOn = datetime.time(hour=17,minute=30,second=0)
TueOff = datetime.time(hour=22,minute=30,second=0)
WedOn = datetime.time(hour=17,minute=30,second=0)
WedOff = datetime.time(hour=22,minute=30,second=0)
ThuOn = datetime.time(hour=17,minute=30,second=0)
ThuOff = datetime.time(hour=22,minute=30,second=0)
FriOn = datetime.time(hour=17,minute=30,second=0)
FriOff = datetime.time(hour=22,minute=30,second=0)
SatOn = datetime.time(hour=17,minute=0,second=0)
SatOff = datetime.time(hour=23,minute=30,second=0)
SunOn = datetime.time(hour=17,minute=0,second=0)
SunOff = datetime.time(hour=23,minute=30,second=0)
MonOnTwo = datetime.time(hour=12,minute=30,second=0)
MonOffTwo = datetime.time(hour=13,minute=30,second=0)
# Store these times in an array for easy access later.
OnTime = [[MonOn, MonOnTwo], [TueOn], [WedOn], [ThuOn], [FriOn], [SatOn], [SunOn]]
OffTime = [[MonOff, MonOffTwo], [TueOff], [WedOff], [ThuOff], [FriOff], [SatOff], [SunOff]]
# Set a "wait time" in seconds. This ensures that the program pauses
# briefly after it turns the lights on or off. Otherwise, since the
# loop will execute more than once a second, it will try to keep
# turning the lights on when they are already on (or off when they are
# already off.
waitTime = 3
halfWait = waitTime / 2
# Start the loop that will run until you stop the program or turn
# off your Raspberry Pi.
while True:
# get the current time in hours, minutes and seconds
currTime = datetime.datetime.now()
# get the current day of the week (0=Monday, 1=Tuesday, 2=Wednesday...)
currDay = datetime.datetime.now().weekday()
for dtimes in OnTime[currDay]:
#Check to see if it's time to turn the lights on
if (currTime.hour - dtimes.hour == 0 and
currTime.minute - dtimes.minute == 0 and
currTime.second - dtimes.second > -halfWait and
currTime.second - dtimes.second < halfWait):
# set the GPIO pin to HIGH, equivalent of
# pressing the ON button on the remote
GPIO.output(11, GPIO.HIGH)
# wait for a very short period of time then set
# the value to LOW, the equivalent of releasing the
# ON button
time.sleep(.5)
GPIO.output(11, GPIO.LOW)
for dtimes in OffTime[currDay]:
#check to see if it's time to turn the lights off
if (currTime.hour - dtimes.hour == 0 and
currTime.minute - dtimes.minute == 0 and
currTime.second - dtimes.second > -halfWait and
currTime.second - dtimes.second < halfWait):
# set the GPIO pin to HIGH, equivalent of
# pressing the OFF button on the remote
GPIO.output(12, GPIO.HIGH)
# wait for a very short period of time then set
# the value to LOW, the equivalent of releasing the
# OFF button
time.sleep(.5)
GPIO.output(12, GPIO.LOW)
# wait for a few seconds because it's pointless to burn energy
# with no benefit
time.sleep(waitTime)