Non-latching GPIO output that needs to disregard input - gpio

New to programming, so I'll try my best to explain:
I'm trying to use a Pi Zero in my solar setup to switch the power-on input on an x86 motherboard (basically operating as the power button). The idea is that a battery voltage monitor sets pin 14 on the Pi high when the battery is at a high enough voltage. The script reads this input then switches an output (26) on the Pi, which in turn closes a relay for one second, which will then activate the power-on input on the motherboard.
The problem is that I cannot get the output (26) to turn off after one second. The script won't ignore pin 14, and just keeps the output (26) high. (Pin 14 is naturally held high by the battery monitor until the battery level falls down below a certain threshold)
import RPi.GPIO as GPIO
from time import sleep
GPIO.setmode(GPIO.BCM)
GPIO.setup(14,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(26,GPIO.OUT)
GPIO.output(26, 1)
while True:
if GPIO.input(14)==1:
GPIO.output(26, 0)
sleep(1)
GPIO.output(26, 1)
else:
GPIO.output(26, 1)
GPIO.cleanup()

Here's one possible solution that polls the value of GPIO14 1/second
and uses the variable power_on to figure out how we respond to the
value:
import RPi.GPIO as GPIO
from time import sleep
GPIO.setmode(GPIO.BCM)
GPIO.setup(14,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(26,GPIO.OUT)
GPIO.output(26, 1)
power_on = False
while True:
if not power_on:
if GPIO.input(14) == 1:
GPIO.output(26, 0)
sleep(1)
GPIO.output(26, 1)
power_on = True
else:
if GPIO.input(14) == 0:
power_off = True
time.sleep(1)
# Note that you're never going to reach this line.
GPIO.cleanup()
Alternatively, you can have your code block until pin 14 changes, leading to something like this:
import RPi.GPIO as GPIO
from time import sleep
GPIO.setmode(GPIO.BCM)
GPIO.setup(14,GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(26,GPIO.OUT)
GPIO.output(26, 1)
while True:
GPIO.wait_for_edge(14, GPIO.RISING)
GPIO.output(26, 0)
sleep(1)
GPIO.output(26, 1)
# Note that you're never going to reach this line.
GPIO.cleanup()
This uses GPIO.wait_for_edge() to wait for a rising edge on GPIO14 (a low ➡️ high transition), and then triggers your relay.

Related

while loop (Python) becomes slow after 500 cycle in Raspberry Pi 4

I am making one project with analog sensors using a raspberry pi 4 controller (4GB ram). I have connected 9 sensors currently, I am using while loop for an infinite cycle. The code is very simple taking input from sensors and using the canvas library changing the colour of shapes when it gets pressed and remains the same when not. The problem is after 500-550 cycles it is getting slower. As the number of cycles increases the response rate becomes slower and slower. Can anyone please suggest how can I overcome this problem?
I am also a noob in coding so please guide me if I did some mistake. I am writing code for only one sensor because it is the same for all the sensors.
Code:
from tkinter import *
import Rpi.GPIO as GPIO
import time
import tkinter as tk
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(7, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
.
.
.
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
root=tk.Tk()
canvas = tk.Canvas(root, bg='white', width=500, height=500)
canvas.grid()
canvas.bind('<key>', lambda event: root.destroy() if (event.char == 'q') else 0)
while True:
def sense1(on):
square1= canvas.create_rectangle(5, 5, 105, 105, width=0, fill='red' if on else 'green')
.
.
.
def sense9(on):
square9= canvas.create_rectangle(235, 235, 335, 335, width=0, fill='red' if on else 'green')
global S1,...,S9
if GPIO.input(7) == GPIO.HIGH:
S1 = sense1(True)
else:
S1 = sense1(False)
.
.
.
if GPIO.input(18) == GPIO.HIGH:
S9 = sense9(True)
else:
S9 = sense9(False)
root.update_idletasks()
root.update()
same code I have written for the other 8 sensors.
Check core temperature.
The while loop can cause the temperature of the microprocessor to rise. The raspberry has a self-protection mechanism that is activated when the core temperature is very high, generating a drop in performance. I suggest you change the while loop to callbacks
Saludos!

Python 3 Subprocess does not terminate with signal.SIGINT

I've read many of the questions here on SO, but none of the solutions seem to solve my problem. I have a file called "light_led.py" which looks like this
import RPi.GPIO as gpio
import time
# Set the mode for the GPIO numbering
gpio.setmode(gpio.BCM)
pin = 23
# Set the GPIO as output
gpio.setup(pin, gpio.OUT, initial=gpio.LOW)
try:
while True: # Run forever
gpio.output(pin, gpio.HIGH) # Turn on
time.sleep(1) # Sleep for 1 second
gpio.output(pin, gpio.LOW) # Turn off
time.sleep(1) # Sleep for 1 second
except KeyboardInterrupt:
# cleanup all GPIO
gpio.cleanup()
print('Cleaned up')
It simply toggles an LED on and off. This file is called in the following script
import RPi.GPIO as gpio
import time
import subprocess
import signal
# Set the mode for the GPIO numbering
gpio.setmode(gpio.BCM)
pin = 24
# Set the GPIO as input w/ pull up
gpio.setup(pin, gpio.IN, pull_up_down = gpio.PUD_UP)
# Initialize
pin_prev = gpio.input(pin)
while True:
pin = gpio.input(pin)
if (pin == 0) and (pin_prev == 1):
process = subprocess.Popen('python <PATH-TO-FILE>/light_led.py', shell=True)
print('Should be blinking')
if (pin == 1) and (pin_prev == 0):
process.send_signal(signal.SIGINT)
print('Should be off')
# Update previous state
pin_prev = pin
# Slight pause to debounce
time.sleep(0.05)
The files run fine and do what they're suppose to. The only problem I'm having is that I can't stop the blinking light by "flipping the switch". In other words, I'm having trouble with this process.send_signal(signal.SIGINT). There are not errors, so I don't have much to report.
I've tried process.terminate() and os.kill(process.pid, signal.SIGINT), both with no luck. I just want to stop the subprocess from running and continue with the main toggle script. From what I read, "signal.SIGINT" should invoke the "KeyboardInterrupt" in the subprocess...but maybe not?

Raspberry Pi relays and Python, how do I turn off and on a relay in separate functions?

I'm new to Raspberry Pi and are working on a Pi3 program that will switch on and off an irrigation pump though a 1 channel relay.
I've made a function that works well, that takes a delay variable and starts the relay then waits for the delay until it stops the relay again.
However, I also need to be able to turn the relay on in another function, and leave it on until the user turns it off again, and I can't seem to get that working.
When I try it, nothing happens with the relay (except for the normal having power indicating led on it).
This is my working function:
#This function switches on the relay for a set period of time, and then shuts it off again
def relay_control(wait_time):
# Sleeping for a second
time.sleep(1)
print("Relay control function")
# We will be using the BCM GPIO numbering
GPIO.setmode(GPIO.BCM)
# Selecting which GPIO to target
GPIO_CONTROL = 6
# Set CONTROL to OUTPUT mode
GPIO.setup(GPIO_CONTROL, GPIO.OUT)
# Starting the relay
GPIO.output(GPIO_CONTROL, True)
# Sleeping for set amount of time
try:
time.sleep(wait_time)
except:
time.sleep(60)
print("Setting delay failed, using default 60 seconds")
# Stopping the relay
GPIO.output(GPIO_CONTROL, False)
# Cleanup
GPIO.cleanup()
And then I have tried these two functions, but it just doesn't work:
#This function switches on the relay - Doesn't currently work
def relay_on():
# Sleeping for a second
time.sleep(1)
# We will be using the BCM GPIO numbering
GPIO.setmode(GPIO.BCM)
# Selecting which GPIO to target
GPIO_CONTROL = 6
# Set CONTROL to OUTPUT mode
GPIO.setup(GPIO_CONTROL, GPIO.OUT)
#Starting the relay
GPIO.output(GPIO_CONTROL, False)
#Logging the event
logging.basicConfig(format='%(asctime)s %(message)s', filename='/home/pi/GardenBrain/events.log', level=logging.INFO)
logging.info('Relay has been manually switched on, from functions.py')
time.sleep(5)
#Cleanup
GPIO.cleanup()
#This function switches on the relay off - Doesn't currently work
def relay_off():
# Sleeping for a second
time.sleep(1)
# We will be using the BCM GPIO numbering
GPIO.setmode(GPIO.BCM)
# Selecting which GPIO to target
GPIO_CONTROL = 6
# Set CONTROL to OUTPUT mode
GPIO.setup(GPIO_CONTROL, GPIO.OUT)
#Stopping the relay
GPIO.output(GPIO_CONTROL, True)
#Logging the event
logging.basicConfig(format='%(asctime)s %(message)s', filename='/home/pi/GardenBrain/events.log', level=logging.INFO)
logging.info('Relay has been manually switched off, from functions.py')
#Cleanup
GPIO.cleanup()
Can anyone see what the problem is and help me get it working?
Any help is greatly appreciated!
Also, the working function seem to freeze my Raspberry Pi for a while. It's all powered though the GPIO pins, and the system has a 7" touchscreen display (which the system is being USB powered through), the mentioned 230v 1-channel relay and a Sense Hat.
I solved it myself by writing the function in a different way. This one works well and both starts and stops the relay as intended.
#This function switches on the relay on or off and expects the argument 'on' or 'off'
def relay_manual(action):
# Selecting which GPIO to target
GPIO_CONTROL = 6
if action == "on":
# Sleeping for a second
time.sleep(1)
# We will be using the BCM GPIO numbering
GPIO.setmode(GPIO.BCM)
# Set CONTROL to OUTPUT mode
GPIO.setup(GPIO_CONTROL, GPIO.OUT)
#Starting the relay
GPIO.output(GPIO_CONTROL, True)
#Logging the event
logging.basicConfig(format='%(asctime)s %(message)s', filename='/home/pi/GardenBrain/events.log', level=logging.INFO)
logging.info('Relay has been manually switched on, from functions.py')
elif action == "off":
try:
#Stopping the relay
GPIO.output(GPIO_CONTROL, False)
except:
# We will be using the BCM GPIO numbering
GPIO.setmode(GPIO.BCM)
# Set CONTROL to OUTPUT mode
GPIO.setup(GPIO_CONTROL, GPIO.OUT)
#Starting the relay
GPIO.output(GPIO_CONTROL, False)
#Logging the event
logging.basicConfig(format='%(asctime)s %(message)s', filename='/home/pi/GardenBrain/events.log', level=logging.INFO)
logging.info('Relay has been manually switched off, from functions.py')
#Cleanup
GPIO.cleanup()
You should move the code GPIO.setmode() and GPIO.setup() out of your functions as it only need to be setup once.
This is how the code some looks like:
def relay_on():
GPIO.output(GPIO_CONTROL, False)
logging.basicConfig(format='%(asctime)s %(message)s', filename='/home/pi/GardenBrain/events.log', level=logging.INFO)
logging.info('Relay has been manually switched on, from functions.py')
def relay_off():
GPIO.output(GPIO_CONTROL, True)
logging.basicConfig(format='%(asctime)s %(message)s', filename='/home/pi/GardenBrain/events.log', level=logging.INFO)
logging.info('Relay has been manually switched off, from functions.py')
# The main program setup the GPIO
GPIO_CONTROL = 6
GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_CONTROL, GPIO.OUT)
# Get input from user to turn on or off relay
while True:
data = input("Input 'on'/'off' to turn on/off relay, or 'exit' to end ")
if data == 'on':
relay_on()
elif data == 'off':
relay_off()
elif data == 'exit':
# program end, clean up GPIO
GPIO.cleanup()

Raspberry Pi 3 - One pin sending different voltage (4.25 instead of 3.3)

I am working with the SainSmart 16-Channel Relay board and everything is working fine except for one pin is sending a different voltage. This is causing the relay to shutoff after a few seconds. All the pins show 3.3v except for pin 4 that is showing 4.25v when I test the terminal with my multi-meter. I have added a 1k resister inline with the GPIO pin because the board is designed for Arduino and not the Raspberry Pi. The resister has corrected the voltage difference issue because 15 other relays work fine. Also I am reading this voltage issue before the 1k resistor so it should be effecting this.
I have changed out the Raspberry Pi board and the relay board with another thinking that was the issue and am receiving the exact same voltage. Any ideas as to what the issue could be would be greatly appreciated.
Below is the code I am using to test pins 2-8.
from tkinter import *
import RPi.GPIO as GPIO
class Create_Button:
def __init__(self,pin):
self.pin = pin
GPIO.setup(self.pin, GPIO.OUT)
GPIO.output(self.pin, GPIO.HIGH)
self.b = Button(text="Pin %s" % self.pin + " - Turn Relay On", command=self.toggle)
self.b.pack()
def toggle(self):
print(self.pin)
if GPIO.input(self.pin):
GPIO.output(self.pin, GPIO.LOW)
self.b.config(text="Pin %s" % self.pin + " - Turn Relay On")
else:
GPIO.output(self.pin, GPIO.HIGH)
self.b.config(text="Pin %s" % self.pin + " - Turn Relay Off")
root = Tk()
root.title("Toggler")
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(FALSE)
for pin_count in range(2,9+1):
button = Create_Button(pin_count)
quitButton = Button(root, text="Quit", command=exit)
quitButton.pack(side=LEFT)
root.mainloop()
GPIO.cleanup()

Python ability to manage 2 or more physical buttons

I am making a camera. I am using a RPi 3 and python. I am using 2 GPIO attached to momentary switches. With the first button I want to be able to take pictures. The second one runs a script to shutdown the system, but IT IS NOT WORKING. This is the code. Please help.
import RPi.GPIO as GPIO
from gpiozero import Button
import time
import os
from time import sleep
from picamera import PiCamera
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
GPIO.setup(18, GPIO.IN, pull_up_down = GPIO.PUD_DOWN)
button1 = Button(17)
button2 = Button(18)
camera = PiCamera()
channel = 1
if GPIO.input(18):
button2.wait_for_press()
print("Here I will run the shutdown code")
if GPIO.input(17):
frame = 1
while True:
try:
button1.wait_for_press()
camera.capture('/home/pi/Vinpics/frame%03d.jpg' % frame)
frame += 1
except KeyboardInterrupt:
print("Just a place holder")

Resources