Accesing GPIO input via Capacitance sensor using python 3 - python

Hi good people out there! I'm new in to this subject, and need some help. I'm trying to write a little domotica project where I can switch some relays via Raspberry_2 GPIO pins using a capacitance touch sensor (SainSmart TTP223B) and GUI widgets as well. My GUI part works perfectly but when I try to add this module and run the app my GUI doesn't show at all, but touching the sensor I do hear relay working. I thing there is a problem with "While" statement but can't figure out what is wrong. here is a sample of this troubling code:
GPIO.setup(22, GPIO.IN, GPIO.PUD_DOWN)
prevState = False
currState = False
while True:
time.sleep(0.3)
prevState = currState
currState = GPIO.input(22)
if currState != prevState:
GPIO.setup(25,GPIO.OUT)
GPIO.output(25,False)
time.sleep(0.3)
GPIO.output(25,True)

Related

How can I make the Raspberry Pico not automount as USB storage while using Circuit Python

I am using Circuit Python on a Raspberry Pi Pico to give me hardware buttons for keyboard shortcuts. I am using Circuit Python as opposed to MicroPython because it has the USB_HID library.
I don't want the Pico to automatically mount as USB storage when being plugged in. I just want it to act as a HID device. I am aware that I can write a boot.py script in addition to a code.py but I can't find anywhere online what to put in this which would prevent it from mounting as a USB device. I also still want it to mount as USB sometimes (when a button is pressed/GPIO pin is connected) so there is a still a way for me to change the code on the device.
Is this possible? And, if so, what should the boot.py look like to only mount when a certain GPIO pin is connected?
I recently came across a need to do the same that you are looking for, and after a decent rabbit hole, have determined that it can't be done at this time.
https://github.com/adafruit/circuitpython/issues/1015
Looks like the request was opened a few years ago and is still listed as open.
I am not sure if running a pi zero in "gadget" mode can accomplish this or not, but may be worth a look
The code below is what I use. Roughly, it checks to see if a button connected to one of the Pico's IO pins. If the button is pressed when the cable is plugged in, then it mounts as a USB drive. If the button is not pressed, it's not mounted:
import storage
import board, digitalio
# If not pressed, the key will be at +V (due to the pull-up).
# https://learn.adafruit.com/customizing-usb-devices-in-circuitpython/circuitpy-midi-serial#circuitpy-mass-storage-device-3096583-4
button = digitalio.DigitalInOut(board.GP2)
button.direction = digitalio.Direction.INPUT
button.pull = digitalio.Pull.UP
# Disable devices only if button is not pressed.
if button.value:
print(f"boot: button not pressed, disabling drive")
storage.disable_usb_drive()
This was adapted from examples on Adafruit's site
Here's a good HID guide:
https://learn.adafruit.com/circuitpython-essentials/circuitpython-hid-keyboard-and-mouse
Here's the HID example:
import time
import board
import digitalio
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS
from adafruit_hid.keycode import Keycode
# A simple neat keyboard demo in CircuitPython
# The pins we'll use, each will have an internal pullup
keypress_pins = [board.A1, board.A2]
# Our array of key objects
key_pin_array = []
# The Keycode sent for each button, will be paired with a control key
keys_pressed = [Keycode.A, "Hello World!\n"]
control_key = Keycode.SHIFT
# The keyboard object!
time.sleep(1) # Sleep for a bit to avoid a race condition on some systems
keyboard = Keyboard(usb_hid.devices)
keyboard_layout = KeyboardLayoutUS(keyboard) # We're in the US :)
# Make all pin objects inputs with pullups
for pin in keypress_pins:
key_pin = digitalio.DigitalInOut(pin)
key_pin.direction = digitalio.Direction.INPUT
key_pin.pull = digitalio.Pull.UP
key_pin_array.append(key_pin)
# For most CircuitPython boards:
led = digitalio.DigitalInOut(board.D13)
# For QT Py M0:
# led = digitalio.DigitalInOut(board.SCK)
led.direction = digitalio.Direction.OUTPUT
print("Waiting for key pin...")
while True:
# Check each pin
for key_pin in key_pin_array:
if not key_pin.value: # Is it grounded?
i = key_pin_array.index(key_pin)
print("Pin #%d is grounded." % i)
# Turn on the red LED
led.value = True
while not key_pin.value:
pass # Wait for it to be ungrounded!
# "Type" the Keycode or string
key = keys_pressed[i] # Get the corresponding Keycode or string
if isinstance(key, str): # If it's a string...
keyboard_layout.write(key) # ...Print the string
else: # If it's not a string...
keyboard.press(control_key, key) # "Press"...
keyboard.release_all() # ..."Release"!
# Turn off the red LED
led.value = False
time.sleep(0.01) ```
The example only prints Hello World, so it's not very useful, but it's a good base to mod.
i try this and it work
https://learn.adafruit.com/circuitpython-essentials/circuitpython-storage
it not write to code.pi but in boot.py you have to create the file first.

Python - scheduler blocks interrupt

I am using a system based on a raspberry to control some stuff. At the moment I am just testing it with turning a led on and off.
My plan is: Press a button to open a valve. Press the button again to close it - but if the button is not pressed, close it after a set time. My current script is as follows: (I know that this will not turn the led off on the second press)
import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library
import time,sched
s = sched.scheduler(time.time, time.sleep)
def button_callback(channel):
print("Button was pushed!")
print(time.time())
GPIO.output(18,GPIO.HIGH)
s.enter(10, 1, turnoff,argument='')
s.run()
def turnoff():
print "LED off"
print(time.time())
GPIO.output(18,GPIO.LOW)
btpin=22
ledpin=18
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
GPIO.setup(btpin, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(ledpin,GPIO.OUT)
GPIO.add_event_detect(btpin,GPIO.RISING,callback=button_callback)
message = input("Press enter to quit\n\n")
GPIO.cleanup()
If I press the button and then leaves things alone, the led will turn off after 10 secs. But, if I press the button again immideately, nothing happens before the scheduler has finished, then a new press is registered. I had expected that the scheduler was spun of in the background so that when I pressed the button again, the callback would have ran again so I would have gotten the "Button was pushed" message (and everything happening afterwards would not have had any effect as GPIO 18 already was high and the scheduled call to turnoff would have happened after turnoff already had run.
Is it possible to use the sched library to do what I want or do I have to use some other techniques? I know I can either do it the simple way, by looping looking for a pressed button rather than registering a callback, or probably a more complicated way by creating a new thread that will pull the GPIO down after a given time - but is there something I have not understood in sched or is there some other library that gives me what I want - a way to tell python do do something a bit in the future without interfering with what else is going on.
(I do not need a very accurate timing - and also, this is just a part of what I intend to make a more complex control system, I manage to do exactly what I want using an arduino, but that will limit the further development)
Thanks to the tip from #stovfl, I rewrote the first part of my code:
import time,threading
def button_callback(channel):
pin=18
print("Button was pushed!")
print(time.time())
GPIO.output(pin,GPIO.HIGH)
t = threading.Timer(10.0, turnoff)
t.start()
and it works just like I wanted

Raspberry Pi Interrupts Python (GPIO Library)

I have a little problem with my little raspberry project, I have hooked up an LCD screen and a bunch of buttons to it, from my university course about micro-controllers I've learned that interrupts always trigger, no matter where the code is (but it was an actual microprocessor written in C). I found an "equivalent" in python, GPIO library. Normally a program is in a infinite loop waiting for an interrupt.
GPIO.add_event_detect(4, GPIO.RISING, callback=interrupt, bouncetime=200)
I set them up this way, they all go to the same method and check which button was pressed and run another method that I want (e.g one is for displaying time, another for IP address etc). A thing is, one of those methods I've done is in an infinite loop that another button press should break, but from this point a method
while not GPIO.event_detected(4):
doesn't work (calling this method in any other doesn't either if its in this loop, and all other button that I have set up will not react at all too), if it was my default while loop it does tho. I don't have much experience in either micro-controllers and python, its just hobby thing at the moment. If needed I'll share my entire code but I think its quite tangled.
Ok I am providing a simplified example, same same thing happens as in my original code. After an interrupt happens, buttons will not react, doesn't matter if I use while not GPIO.event_detected(19) or GPIO.add_event_callback(26, callback=second_interrupt).
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Button 1
GPIO.setup(19, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Button 2
def interrupt(channel):
print "interrupt"
if channel == 26:
print "in loop"
GPIO.add_event_callback(26, callback=second_interrupt) #Trying to use this won't trigger second interrupt
while not GPIO.event_detected(19): #and this wont ever trigger
time.sleep(1)
print "inside loop"
def second_interrupt():
print "second interrupt"
GPIO.add_event_detect(26, GPIO.RISING, callback=interrupt, bouncetime=200) # add rising edge detection on a channel
GPIO.add_event_detect(19, GPIO.RISING, callback=interrupt, bouncetime=200) # add rising edge detection on a channel
while (True):
time.sleep(1)
if GPIO.event_detected(19): #this version works if I wont enter an interrupt first
second_interrupt()
There are several things going on in your code. I suspect that what's really causing the problem is that you need to exit the interrupt handler before another interrupt callback can be triggered...but there is also a confusing mix of callback-based handlers and the GPIO.event_detected method.
I think you can simplify things by performing less manipulation of your interrupt configuration. Just have a state variable that starts at 0, increment it to 1 on the first interrupt, so the next time the interrupt method is called you know it's the second interrupt. No need to try setting multiple handlers like that.
Keeping in mind that I don't actually know what you're trying to do...I imagine something like this:
import RPi.GPIO as GPIO
import time
state = 0
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(19, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def interrupt_handler(channel):
global state
print("interrupt handler")
if channel == 19:
if state == 1:
state = 0
print("state reset by event on pin 19")
elif channel == 26:
if state == 0:
state = 1
print("state set by event on pin 26")
GPIO.add_event_detect(26, GPIO.RISING,
callback=interrupt_handler,
bouncetime=200)
GPIO.add_event_detect(19, GPIO.RISING,
callback=interrupt_handler,
bouncetime=200)
while (True):
time.sleep(0)

Lighting program - GPIO on/off on raspberry pi runtimewarning

Hello i have been trying to work this one out by myself for over a week now but i think its time to ask the question.
This is my first program with python and i intend to control my aquarium with various functions.
The first function i am programming is a lighting schedule (shortened the code a bit for this post)
The code executes okay but the GPIO pin 2 isnt turning on and off properly. and im also getting a "runtimewarning this channel is already in use"
Can i please have a bit of guidance, im sure its something simple and noob :)
here is my code
#Lighting Program
import RPi.GPIO as GPIO
import datetime
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
#Declare Lighting On/Off Times
on_time_Monday = 600
off_time_Monday = 2330
rest of the days here
#Find out what day of the week it is
day = datetime.datetime.now()
day_of_week = day.isoweekday()
#find out what time it is
Current_time = datetime.datetime.strftime(datetime.datetime.now(),'%H%M')
#convert the time to an int so it can be compared
Current_time_INT = int(Current_time)
#Schedule on / off
if (day_of_week == 1) and (Current_time_INT > on_time_Monday and Current_time_INT < off_time_Monday) :
Light_on_off = 'on'
Using 'elif' for tues wed etc etc
else :
Light_on_off = 'off'
Now enable the outputs
#CALL OUTPUTS ON / OFF
GPIO.setup(2, GPIO.OUT)
if Light_on_off == 'on':
GPIO.output(2, GPIO.HIGH)
else:
GPIO.output(2, GPIO.LOW)
GPIO.cleanup()
In my experience "runtimewarning this channel is already in use" comes up when you have previously setup the GPIO pin, but haven't called
GPIO.cleanup().
I see that in your code, but I would suspect that for some reason it is not actually running.
Sometimes it is helpful to test out a GPIO pin in the terminal by running the python interpreter. It is especially useful to test if you have wired your circuit correctly.
>>>import RPi.GPIO as GPIO
>>>GPIO.setmode(GPIO.BCM)
>>>GPIO.setwarnings(False)
>>>GPIO.setup(2, GPIO.OUT)
>>>GPIO.output(2, GPIO.HIGH)
>>>GPIO.input(2)
True
>>>GPIO.output(2, GPIO.LOW)
>>>GPIO.input(2)
False
>>>GPIO.cleanup()
If your circuit is wired correctly you should be able to turn your light on and off this way. When you call GPIO.input(2) the interpreter responds with the current state of the pin. This enables you to make sure the pin is working even without a working external circuit. Once you know that it is working you can move on from there.
One simple way to flip a light switch on and off would be to use cron jobs. I have used this method successfully in the past.
You can write two short scripts, one that turns the light on, and one that turns it off.
Example: lightOn.py (replace 'HIGH' with 'LOW' for lightOff.py)
#!/usr/bin/env python
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(2, GPIO.OUT)
GPIO.output(2, GPIO.HIGH)
GPIO.cleanup()
Now you can create a crontab to automatically run the script at the times you want.
For example:
0 6 * * * /home/pi/lightOn.py
0 18 * * * /home/pi/lightOff.py
Would turn the light on everyday at 6AM and off at 6PM

Python Script - Nesting an if / else under an if inside a while True: on - Raspberry Pi

Python is my first interaction with a programming language, I started learning yesterday.
I'm trying to control LEDs from physical momentary switches through a Raspberry Pi and it's GPIO pins.
I have wired the switches and have a piece of code that turns each of 4 LEDs on or off.
I have a 5th switch to turn on or off all 4 LEDs at once depending on the state of an unwired pin.
The code for each LED looks like this:
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(4,GPIO.OUT)
GPIO.output(4,0)
GPIO.setup(18,GPIO.OUT)
GPIO.output(18,0)
while True:
input_state = GPIO.input(10)
if input_state == False:
GPIO.output(4, not GPIO.input(4))
time.sleep(0.1)
GPIO.output(18, GPIO.input(4))
time.sleep(0.4)
Where pin 10 is an input wired to my switch, 4 is the pin that gets turned on and powers the LED and pin 18 is a pin I use to turn on/off all LEDs at the same time with another switch. I have 4 versions of this script, 1 for each LED and just the pins used are changed.
The code to turn on/off all pins at the same time looks like this:
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.IN, pull_up_down=GPIO.PUD_UP)
chan_list = (4,17,22,27)
GPIO.setup(chan_list,GPIO.OUT)
GPIO.output(chan_list,0)
GPIO.setup(18,GPIO.OUT)
GPIO.output(18,0)
while True:
input_state = GPIO.input(26)
if input_state == False:
chan_list = (4,17,22,27)
GPIO.output(18, not GPIO.input(18))
time.sleep(0.1)
GPIO.output(chan_list, GPIO.input(18))
time.sleep(0.4)
These codes work really well. I have them all setup to launch on startup as background processes.
I want to use pin 18 to turn on an indicator LED that turns on if any of the four LEDs are turned on and that stays on if any LEDs are turned off unless all 4 of the LEDs are turned off. This works fine using the all on/off button. The problem comes up when I use the individual LED buttons to turn off individual LEDs. In the current setup as soon as I turn off any individual LED pin 18 is turned off.
I'm trying to find a code solution to get around this issue so that pin 18 (the indicator LED) is on when any of the 4 LEDs are on and is only off if all 4 LEDs are off.
I was thinking some kind of nested series of if / else: conditions but my limited knowledge is stopping my success.
An example piece of code that I have tried is this:
import RPi.GPIO as GPIO
import time
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(4,GPIO.OUT)
GPIO.output(4,0)
GPIO.setup(18,GPIO.OUT)
GPIO.output(18,0)
while True:
input_state = GPIO.input(10)
if input_state == False:
if GPIO.output(17) == True:
GPIO.output(4, not GPIO.input(4))
else:
if GPIO.output(22) == True:
GPIO.output(4, not GPIO.input(4))
else:
if GPIO.output(27) == True:
GPIO.output(4, not GPIO.input(4))
else:
GPIO.output(4, not GPIO.input(4))
time.sleep(0.1)
GPIO.output(18, GPIO.input(4))
time.sleep(0.4)
This gives an error:
Traceback (most recent call last):
File "pin10test.py", line 20, in <module>
if GPIO.output(17) == True:
TypeError: function takes exactly 2 arguments (1 given)
My intention is that when a button press is detected the it will go:
If pin 17 is on, toggle pin 4. If not go to next check.
If pin 22 is on, toggle pin 4. If not go to next check.
If pin 27 is on, toggle pin 4. If not go to final else:
toggle pin 4, sleep 0.1, set pin 18 to whatever pin 4 was just set to, sleep 0.4.
Then I'd adjust this piece of script into the script for each button.
This way pin 18 only changes state to off if all pins are off.
Any help in getting this script right is appreciated.
Any ideas or tips on how to improve this is also appreciated.
input_state = GPIO.input(10)
and
if input_state == False:
should be at the same level of indentation, which is exactly what the error message is saying. There is no reason to indent the second line (since the previous one doesn't open a new block, so indenting it is an error).

Categories

Resources