I wanted to output 'flame detected' or 'no flame detected' but I don't know how to implement this in a code. I've seen codes from google but they are using
GPIO.add_event_detect(17,GPIO.RISING, callback = mycallback, bouncetime = 600)
which only works when it is detecting flame.
In your example you are detecting a rising edge (the pin goes from low to high). A falling edge is the opposite so you could fire a separate callback with:
GPIO.add_event_detect(17, GPIO.FALLING, callback=other_callback, bouncetime=600)
However, I'd suggest you use GPIO Zero instead of RPi.GPIO as you may find it more intuitive:
from gpiozero import InputDevice
sensor = InputDevice(17)
while True:
sensor.wait_for_active()
print("Fire!")
sensor.wait_for_inactive()
print("No fire")
You might find that the logic is reversed (says "fire" when there's no fire) in which case use InputDevice(17, pull_up=True)
Alternatively to the code above you could use if sensor.is_active or use the callbacks mechanism sensor.when_activated = callback. See the gpiozero docs for more info.
Related
If I use the makecode editor to create the code, it generates:
pins.touch_set_mode(TouchTarget.P0, TouchTargetMode.CAPACITIVE)
However, if I try and run this, it can't find 'pins'.
Note: I then investigated further and found out how to do this before submitting my question...
Capacitive mode can be set for each pin, e.g.
from microbit import *
...
pin0.set_touch_mode(pin0.CAPACITIVE)
...
if pin0.is_touched():
...
The last line checks whether the pin is touched - usually in a loop.
Hope this saves other people some time...
I am new to pybricks and have found very little documentation to help answer my own query. I have written what I thought would be a simple program to spin my robot on the spot until the UltrasonicSensor sees something. It will then push forwards. If it is pushed backwards and sees a black line, it should try and swing out of the way.
The following code "works", but it's response to the Ultrasonic and Light sensors is significantly delayed:
#!/usr/bin/env pybricks-micropython
from pybricks.hubs import EV3Brick
from pybricks.ev3devices import Motor, ColorSensor, UltrasonicSensor
from pybricks.parameters import Port
from pybricks.tools import wait
ev3 = EV3Brick()
eyes = UltrasonicSensor(Port.S2)
left_motor = Motor(Port.B)
right_motor = Motor(Port.A)
right_light = ColorSensor(Port.S1)
left_light = ColorSensor(Port.S4)
while True:
if right_light.reflection() < 50:
ev3.speaker.say('black')
left_motor.run(500)
right_motor.run(-100)
wait(2000)
left_motor.run(500)
right_motor.run(500)
wait(1000)
if eyes.distance() > 200:
left_motor.run(500)
right_motor.run(-500)
else:
left_motor.run(-500)
right_motor.run(-500)
I can see in the (limited) documentation that you can apparently change motor settings but I can't find direction on how to do this (or even if it would be useful). Any help would be appreciated.
ev3.speaker.say(text) synthesizes speech as it goes. This is fun, but it is very slow. This is especially noticeable in a control loop like yours.
I'd recommend using ev3.speaker.beep() instead. You could even select the frequency based on the reflection value so you can "hear" what the sensor "sees".
So the problem was that I used the "run" command to move the motors. Run appears to have an acceleration and deceleration component.
I used "dc" instead of "run" and the motors instantly respond to the sensor data now.
Can you please tell me what's the best way to catch a low state (or falling-edge more precisely) of GPIO in an endless script?
To be clear I will run this script at boot (in the bg) and everytime when a user will push a button (connected to this GPIO) this will put this pin at LOW state. I want to detect each one of them and perform actions at every push.
I already have this code but it will consume to much CPU I think... I need sth like an interrupt in my mind :
import RPi.GPIO as GPIO
#Set GPIO numbering scheme to pinnumber
GPIO.setmode(GPIO.BCM)
#setup pin 4 as an input
GPIO.setup(4,GPIO.IN)
# To read the state
While true:
state = GPIO.input(4)
if state:
print('on')
else:
print('off')
EDIT
Here the pinout by BCM or BOARD, I will work with BCM
As you can the the pin number is 4 because my push button is on GPIO4.
Still get off all the time with your code or constant detection of edge event with the code of #jp-jee
EDIT
#!/usr/bin/env python3
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setup(4,GPIO.IN)
def Callback(channel):
print('pushed')
GPIO.add_event_detect(4, GPIO.FALLING, callback = Callback, bouncetime = 300)
while(True):
time.sleep(1)
Now my code print always pushed when the button is released and print nothing when I push it...
Take a look at the documentation of raspberry-gpio-python.
What you want is GPIO.add_event_detect(channel, GPIO.RISING) in combination with a callback function.
Since you're using a button, you also need to consider bouncing.
In the end, you will end up with something like this (taken from the linked website):
def my_callback(channel):
print('This is a edge event callback function!')
GPIO.add_event_detect(channel, GPIO.FALLING, callback=my_callback, bouncetime=200)
Have you tried to use interrupts?
import time
import RPi.GPIO as GPIO
GPIO.setup(4, GPIO.IN)
def Callback(channel):
state = GPIO.input(channel)
if state:
print('on')
else:
print('off')
GPIO.add_event_detect(4, GPIO.FALLING, callback = Callback, bouncetime = 300)
while(True):
time.sleep(1)
I am running into a problem with a simple program that changes the color of the background when it receives a command from a different machine through TCP. It takes like thirty seconds to change the color. I am running this through the local network so it should be near instant response. I am using wxPython for the frame. I don't think I have overly complicated code. Relevant code:
threader=threading.Thread(target=self.threading)
threader.start()
def threading(self):
host="192.168.1.122"
port=4100
s=socket.socket()
s.bind((host,port))
s.listen(1)
c,addr=s.accept()
print "Connected"
while 1:
data=c.recv(1024)
if not data:
break
data=data.split("_")
reading=int(data[1])
pin=int(data[0])
if pin == 1:
if reading<20:
self.front_left.SetBackgroundColour("red")
elif pin == 2:
if reading<20:
self.front_right.SetBackgroundColour("red")
elif pin == 3:
if reading<20:
self.bottom_left.SetBackgroundColour("red")
elif pin == 4:
if reading<20:
self.bottom_right.SetBackgroundColour("red")
else:
pass
c.close()
I need this code to be instant as this will be going on a robot that will tell if objects are too close(which is why there is red background when it gets within 20 cm of object). Any help will be greatly appreciated!
It appears that you are attempting to update wxPython code from a thread. This action is unsupported / undefined in wxPython. You need to use thread-safe methods to update the wxPython UI, such as wx.CallAfter or wx.PostEvent. See the following wxPython wiki page for some examples:
http://wiki.wxpython.org/LongRunningTasks
Basically, you'll want to do something like this in your if statements:
wx.CallAfter(self.bottom_right.SetBackgroundColour, "red")
I'm using GtkHScale (which is a slider) to perform seeking in a media player. I connected the "value_changed" signal of the widget to a callback so that the user can seek. I also set a timer, that will update the widget every 250ms so that it will show the current position in track. Unfortunately GTK fires the "value_changed" signal regardless of whether the slider was clicked by the user or updated by the timer. I tried seeking in the "clicked" signal, and the callback was fired, but it always sought to the beginning
You can keep track of whether the user is moving the slider by connecting to the button-press-event and button-release-event signals. When the user presses the mouse button you want to block the updates from the player so they don't move the slider when the user is trying to seek. In the button release handler you can unblock the updates.
One technique is to surround calls to gtk_range_set_value() for playback updates with g_signal_handler_block/unblock [1] calls. This allows the value and UI of the slider to be updated without triggering specific value changed handlers.
Python GTK+ 3 example showing on_value_changed is only called with interactive scrubbing:
from gi.repository import Gtk, GLib
def on_value_changed(hscale):
print('value-changed: %s' % hscale.get_value())
def on_timeout(hscale, handler_id):
# Block value-changed handler during timed playback updates.
with hscale.handler_block(handler_id):
hscale.set_value(hscale.get_value() + 1)
return True
hscale = Gtk.HScale()
hscale.set_range(0, 100)
handler_id = hscale.connect('value-changed', on_value_changed)
window = Gtk.Window()
window.set_size_request(500, 50)
window.add(hscale)
window.connect('destroy', Gtk.main_quit)
window.show_all()
GLib.timeout_add(100, on_timeout, hscale, handler_id)
Gtk.main()
[1] https://developer.gnome.org/gobject/stable/gobject-Signals.html#g-signal-handler-block