Python detect_event() just works in IDE - python

I'm working on a script for my raspberry PI and standing in front of a problem.
I like to interpret the edges of several GPIO-Inputs. Therefor, I'm using the python functions GPIO.event_detected and GPIO.add_event_detect.
This works fine in the IDE, but if I try to use the script with the Shell sudo python3 script.py nothing happens when I press the Buttons.
I'm initializing the GPIOs with:
numbtns = len(buttons)
index = 0
for index in range(numbtns):
GPIO.setup(buttons[index], GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(buttons[index],GPIO.RISING,bouncetime=200)`
And check the buttons with:
if(GPIO.event_detected(GPIO_RADIO)):
Any ideas why this doesn't work in the shell?
Edit: here is a compilation of interesting code snippets out of my script
import RPi.GPIO as GPIO
import time
import os
from threading import Thread
#GPIO-Belegung
GPIO_RADIO = 18
GPIO_PREV = 11
GPIO_NEXT = 9
GPIO_DOWN = 17
GPIO_UP = 15
GPIO_SELECT = 14
GPIO_MUSIK = 16
GPIO_TEMPERATUR = 4
# GPIO Konfig
GPIO.setmode(GPIO.BCM)
buttons =[GPIO_RADIO,GPIO_PREV,GPIO_NEXT,GPIO_TEMPERATUR,GPIO_DOWN,GPIO_UP,GPIO_SELECT]
def init_gpio(buttons):
numbtns = len(buttons)
index = 0
for index in range(numbtns):
GPIO.setup(buttons[index], GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.add_event_detect(buttons[index],GPIO.RISING,bouncetime=200)
def main():
...
init_gpio(buttons)
...
while True:
if(GPIO.event_detected(GPIO_RADIO)):
do something...
....
if __name__ == '__main__':
main()

Related

setting rpi-gpio pin on high after running a python script

I'm building a photogrametry setup with raspberry pi and stepper motor.
The python script runs fine, but i got a problem with setting a pin to high after the script ran through.
The stepper driver has an enable input, which diasables the motor with high input, so i set the pin (gpio26) on high on boot with pigpio, this works fine. While running the python script, the pin is set on low, so the stepper can proceed, after proceeding i want to set the pin on high again.
i tried following commands:
os.system('pigs w 26 1') and
subprocess.call("pigs w 26 1", shell=True)
for a moment they work, but after exiting the script the pin is set on low again.
It's like the commands are resetted after the script stops.
Where is my fault?
Thank you
Edit:
Here is the gpio related code:
import os, sys
import subprocess
from time import sleep
from gpiozero import DigitalOutputDevice as stepper
def InitGPIO():
try:
global step_pul #pulse
global step_en #enable
step_pul=stepper(21)
step_en=stepper(26)
print ("GPIO initialisiert.")
except:
print ("Fehler bei der GPIO-Initialisierung.")
def motor_step():
SPR=40000 #steps per rotation
step_count = SPR
delay = .000025
for x in range(step_count):
step_pul.on()
sleep(delay)
step_pul.off()
sleep(delay)
InitGPIO()
step_en.off()
for i in range(1):
#camTrigger(1)
motor_step()
#os.system('sudo -u root -S pigs w 26 1')
subprocess.call("pigs w 26 1", shell=True)
When i type pigs w 26 1 in the shell, it works...
To make my comment an answer:
Gpiozero only resets the pins it touches, so if you don't initialize or touch pin 26 with gpiozero (i.e. replace step_en.off() with pigs w 26 0 and don't even initialize step_en), it shouldn't also reset the pin:
import os
import time
import gpiozero
step_pul = gpiozero.DigitalOutputDevice(21)
def motor_step():
SPR = 40000 # steps per rotation
step_count = SPR
delay = .000025
for x in range(step_count):
step_pul.on()
time.sleep(delay)
step_pul.off()
time.sleep(delay)
# Enable motor
os.system("pigs w 26 0")
for i in range(1):
# camTrigger(1)
motor_step()
# Disable motor
os.system("pigs w 26 1")

Run Script as parallel Subprocess

i'm pretty new to python, so my knowledge is quiet basic. (i'm a system engineer)
i have a raspberry pi, an led strip and a python script to simulate a fire on the led strip :D
now i want to start the script by pressing my flic button. i found the fliclib sdk on github and installed it. my problem is now, how to handle the event correctly. i successfully can start the script, but i'd like to stop it by doublepress the flic button. but it seems like i'm stuck in the fire.py script as soon as i press the button once. can anybody help me how to set this up correctly please? :-)
Edit after suggestion:
i just edited my scripts as the following. i can see when the button is pressed once or twice with this output:
Starting Fire
Stopping Fire
but the led wont turn on, seems like, fire.py isn't opened or something like that.. when i set button=1 in fire.py itself, the fire turns on.
main.py
#!/usr/bin/env /usr/bin/python3
# -*- coding: utf-8 -*-
import flicbutton
import fire
button = 0
flicbutton.py
#!/usr/bin/env /usr/bin/python3
# -*- coding: utf-8 -*-
import fliclib
client = fliclib.FlicClient("localhost")
MyButton1 = '80:e4:da:71:83:42' #turquoise flic button
def got_button(bd_addr):
cc = fliclib.ButtonConnectionChannel(bd_addr)
cc.on_button_single_or_double_click_or_hold = some_handler
cc.on_connection_status_changed = \
lambda channel, connection_status, disconnect_reason: \
print(channel.bd_addr + " " + str(connection_status) + (" " + str(disconnect_reason) if connection_status == fliclib.ConnectionStatus.Disconnected else ""))
client.add_connection_channel(cc)
def got_info(items):
print(items)
for bd_addr in items["bd_addr_of_verified_buttons"]:
got_button(bd_addr)
def some_handler(channel, click_type, was_queued, time_diff):
if channel.bd_addr == MyButton1:
try:
if click_type == fliclib.ClickType.ButtonSingleClick:
print("Starting Fire")
button=1
if click_type == fliclib.ClickType.ButtonDoubleClick:
print("Stopping Fire")
button=2
if click_type == fliclib.ClickType.ButtonHold:
print("ButtonHold has not been assigned an action")
except Exception:
import datetime
print('An error occured: {:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now()))
client.get_info(got_info)
client.on_new_verified_button = got_button
client.handle_events()
fire.py
import RPi.GPIO as GPIO
import threading
import time
import random
import math
R = 17
G = 22
pwms = []
intensity = 1.0
def initialize_gpio():
GPIO.setmode(GPIO.BCM)
GPIO.setup([17,22], GPIO.OUT)
def red_light():
p = GPIO.PWM(R, 300)
p.start(100)
pwms.append(p)
while True:
p.ChangeDutyCycle(min(random.randint(50, 100) * math.pow(intensity + 0.1, 0.75), 100) if intensity > 0 else 0)
rand_flicker_sleep()
def green_light():
global green_dc
p = GPIO.PWM(G, 300)
p.start(0)
pwms.append(p)
while True:
p.ChangeDutyCycle(random.randint(5, 10) * math.pow(intensity, 2) if intensity > 0 else 0)
rand_flicker_sleep()
def rand_flicker_sleep():
time.sleep(random.randint(3,10) / 100.0)
def fan_the_flame(_):
global intensity
intensity = min(intensity + 0.25, 1.0)
def light_candle():
threads = [
threading.Thread(target=red_light),
threading.Thread(target=green_light),
## threading.Thread(target=burning_down)
]
for t in threads:
t.daemon = True
t.start()
for t in threads:
t.join()
def startfire():
try:
initialize_gpio()
print("\nPress ^C (control-C) to exit the program.\n")
light_candle()
except KeyboardInterrupt:
pass
finally:
for p in pwms:
p.stop()
def stopfire():
GPIO.cleanup()
#if __name__ == '__main__':
# main()
if button == 1:
startfire()
if button == 2:
stopfire()
Have a common (global variable) that both codes can read, you can put this in a standalone file that both codes can access. So script 1 updates this variable like
if(single press): variable=1
elif(double press): variable=2
then in fire.py you can poll the variable.
if(varaible==1): start/stop fire
elif(variable==2): stop/start fire
else: #throw error
I'm sure there are more efficient ways to do this, but this method should be the easiest to understand.

GPIO control in while true:

Hey guys i get all the time the failure:
photo_booth.py:18: RuntimeWarning: This channel is already in use, continuing anyway. Use GPIO.setwarnings(False) to disable warnings.
GPIO.setup(RELAI, GPIO.OUT)
I also try to control al relays with the GPIO 18 but it is not working at all.
I tried it with some others but nothing changed. the relais i all the time on and it is not turning off with the command. what is my problem?
can you please tell me the problem ?
#!/usr/bin/python
import RPi.GPIO as GPIO, time, os, subprocess, signal
# GPIO setup
GPIO.setmode(GPIO.BCM)
SWITCH = 24
GPIO.setup(SWITCH, GPIO.IN)
RESET = 25
GPIO.setup(RESET, GPIO.IN)
RELAI = 19
GPIO.setup(RELAI, GPIO.OUT)
GPIO.output(RELAI, GPIO.LOW)
j = 0
k = 0
def entprellen(schalter):
entprellungs_puffer = 0
schalter_puffer = 0
for i in range(1, 11):
entprellungs_puffer = entprellungs_puffer +1
schalter_puffer = schalter_puffer + schalter
time.sleep(0.05)
if entprellungs_puffer == schalter_puffer:
print("entprellt")
return 1
else:
return 0
while True:
if(GPIO.input(SWITCH)):
j = entprellen(GPIO.input(SWITCH))
if (j):
GPIO.output(RELAI,GPIO.LOW)
time.sleep(0.5)
print("pose!")
print("SNAP")
gpout = subprocess.check_output("gphoto2 --capture-image-and-download --filename /home/pi/photobooth_images/photobooth%H%M%S.jpg", stderr=subprocess.STDOUT, shell=True)
print(gpout)
print("please wait while your photos print...")
subprocess.call("sudo /home/pi/scripts/photobooth/assemble_and_print", shell=True)
time.sleep(10)
print("ready for next round")
GPIO.output(RELAI,GPIO.HIGH)
GPIO.cleanup()
Thanks #stevieb and #johnny Mopp
Yes i understand the diffrence between the BCM ond BOARD mode. actually it was possible to run.
the Problem was : i connect it like here https://www.youtube.com/watch?v=TVR2SCMN8xY but it did not work. then i tried to change form 5 to 3.3V on the pi and it worked. the problem is the relay is not switching properly. i red on many sides very diffrent thinks about the relays. so i dont no really what to do. i bougth now two relays :
this is the first one :
https://www.amazon.de/gp/product/B01G1ENSTS/ref=ppx_yo_dt_b_asin_title_o03__o00_s00?ie=UTF8&psc=1
thats almost the same but diffrent brand:
https://www.amazon.de/gp/product/B00UFW1YNK/ref=ppx_yo_dt_b_asin_title_o01__o00_s00?ie=UTF8&psc=1
i hoped the second one is better because its the same one as shown in the tutorial. but no changes.
now i bought this one :
https://www.ebay.de/itm/252993630298
it has one pin to supply the coil directly with the 5V and the 3.3 is for switching.
do you think it will work or do you have other ideas ????
Thank you for your help!

GPIO output initially on and GPIO.output

I'm new to python and am attempting to control solenoid valves using a relay, RPi, PIR sensor and python script. I found a script posted online I used as a base and modified it a bit to switch my relay. Everything seems to be working as expected overall, but I've noticed the following:
As soon as I run the script in terminal, the relay switches are on. After first trigger , they will stay off until the following trigger. Why are they intially on?
In my code I'm using GPIO.output(<variable>,False) to switch on and GPIO.output(<variable>,True) to turn off which seems backward. Shouldn't the False argument turn the switch off and True turn on?
Code below. Any pointers or insight would be appreciated! Thanks!
# Import required Python libraries
import RPi.GPIO as GPIO
import time
import random
# Use BCM GPIO references
# instead of physical pin numbers
GPIO.setmode(GPIO.BCM)
# Define GPIO to use on Pi
pir = 17
arm_one = 23
arm_two = 24
print "PIR Module Test (CTRL-C to exit)"
# Set pin as input
GPIO.setup(pir,GPIO.IN)
GPIO.setup(arm_one,GPIO.OUT)
GPIO.setup(arm_two,GPIO.OUT)
current_state = 0
previous_state = 0
def getRandomNum():
random_sleep=random.uniform(0,1)
return random_sleep;
try:
print "Waiting for PIR to settle ..."
# Loop until PIR output is 0
while GPIO.input(pir)==1:
current_state = 0
print " Ready"
# Loop until users quits with CTRL-C
while True:
# Read PIR state
current_state = GPIO.input(pir)
if current_state==1 and previous_state==0:
# PIR is triggered
print " Motion detected!"
for i in range(5):
GPIO.output(arm_one,False)
GPIO.output(arm_two,False)
time.sleep(1)
GPIO.output(arm_one,True)
time.sleep(getRandomNum())
GPIO.output(arm_two,True)
time.sleep(getRandomNum())
GPIO.output(arm_one,False)
time.sleep(getRandomNum())
GPIO.output(arm_one,True)
GPIO.output(arm_two,False)
time.sleep(getRandomNum())
GPIO.output(arm_two,True)
# Record previous state
previous_state=1
elif current_state==0 and previous_state==1:
# PIR has returned to ready state
print " Ready"
GPIO.output(arm_one,True)
GPIO.output(arm_two,True)
previous_state=0
# Wait for 10 milliseconds
time.sleep(0.01)
except KeyboardInterrupt:
print " Quit"
# Reset GPIO settings
GPIO.cleanup()

Pulse width reader printing same value every time

I'm connecting my raspberry pi to a 2.4ghz rc reciever, and I am trying to use python to interpret the pulse width signal. I am using an input pin to read the time while there is no input, then the time when there is an input, then subtracting the two.
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BOARD)
GPIO.setup(13,GPIO.IN)
GPIO.setup(15,GPIO.OUT)
GPIO.output(15,GPIO.HIGH)
start = time.time()
stop = time.time()
x = 0
y = 0
while(x == 0):
if(GPIO.input(13) == 0):
start = time.time()
x = 1
while(y == 0):
if(GPIO.input(13) == 1):
stop = time.time()
y = 1
Width = stop-start
print(Width)
GPIO.cleanup()
The issue I am having is that no matter how long I make the pulse width (by manually connecting and disconnecting pin 13 and 15), it prints ~.006. It also will not print until I disconnect the pins from each other, although I haven't been able to figure out why.
Pin 13 might be floating. I'd suggest you replace ...
GPIO.setup(13,GPIO.IN)
... with ...
GPIO.setup(13,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
Here's an example of how to do this with interrupts:
#!/usr/bin/env python3
# example of reading PWM with GPIO interrupts
# Warning: Linux isn't built for real-time applications.
# A Raspberry Pi with Jessie will not produce reliable results
# That said...
import RPi.GPIO as GPIO
import time
GPIOpin_IN = 13
GPIOpin3v3 = 1 # fixed at 3v3 volts
myStart = None
myStop = None
GPIO.setmode(GPIO.BOARD)
GPIO.setup(GPIOpin_IN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
def pinGoesUp(gpioIdentity):
myStart = time.time()
def pinGoesDown(gpioIdentity):
myStop = time.time()
GPIO.add_event_detect(GPIOpin_IN, GPIO.RISING, callback=pinGoesUp)
GPIO.add_event_detect(GPIOpin_IN, GPIO.FALLING, callback=pinGoesDown)
while True:
if myStop < myStart:
Width = stop-start
print(Width)`
documentation on gpio input.
On a side note, you're going to have difficulty getting reliable readings. Jessie is not intended to provide real-time interaction, and frequently takes small vacations to do other tasks.

Categories