Below is the code i ran on the Intel Galileo Gen2. I'm just wondering why when the object come really close to the ultrasonic sensor the program stops and complain about that the variable sig "local variable 'sig' referenced before assignment"?
import mraa
import time
trig = mraa.Gpio(0)
echo = mraa.Gpio(1)
trig.dir(mraa.DIR_OUT)
echo.dir(mraa.DIR_IN)
def distance(measure='cm'):
trig.write(0)
time.sleep(0.2)
trig.write(1)
time.sleep(0.00001)
trig.write(0)
while echo.read() == 0:
nosig = time.time()
while echo.read() == 1:
sig = time.time()
# et = Elapsed Time
et = sig - nosig
if measure == 'cm':
distance = et * 17150
elif measure == 'in':
distance = et / 0.000148
else:
print('improper choice of measurement!!')
distance = None
return distance
while True:
print(distance('cm'))
Your problem is that the spike produced by your sensor is too short to be noticed, as the sampling-frequency of your while echo.read() is limited.
This then never defines the variable sig.
To overcome this, define sig = None when entering the function, and then later test for it being None - then you know you can't use your measurement.
If you want to sample with higher frequency, you need to use a language that is faster than Python, e.g. C++.
The problem is:
while echo.read() == 0:
nosig = time.time()
while echo.read() == 1:
sig = time.time()
if the first condition is met and has not returned to 1 by the time the next line is read then sig will never get a value.
Related
I have a problem with the Jsn-sr04t water proof ultrasonic sensor, knowing that the connection in the raspberry pi zero W1 is well made becouse it is activated but the readings of this are totally wrong, the pins were entered correctly but this one seems to have a data entry error. I tried several programs in python that were used on this same sensor model
PD: I'm aware that this works, because I tested it on an arduino mega and the sensor worked correctly
import RPi.GPIO as GPIO
import os
import time
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO_TRIGGER = 10
GPIO_ECHO = 8
TRIGGER_TIME = 0.00001
MAX_TIME = 0.004 # max time waiting for response in case something is missed
GPIO.setup(GPIO_TRIGGER, GPIO.OUT) # Trigger
GPIO.setup(GPIO_ECHO, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Echo
GPIO.output(GPIO_TRIGGER, False)
def measure():
# Pulse the trigger/echo line to initiate a measurement
GPIO.output(GPIO_TRIGGER, True)
time.sleep(TRIGGER_TIME)
GPIO.output(GPIO_TRIGGER, False)
# ensure start time is set in case of very quick return
start = time.time()
timeout = start + MAX_TIME
while GPIO.input(GPIO_ECHO) == 0 and start <= timeout:
start = time.time()
if(start > timeout):
return -1
stop = time.time()
timeout = stop + MAX_TIME
# Wait for end of echo response
while GPIO.input(GPIO_ECHO) == 1 and stop <= timeout:
stop = time.time()
if(stop <= timeout):
elapsed = stop-start
distance = float(elapsed * 34300)/2.0
else:
return -1
return distance
if __name__ == '__main__':
try:
while True:
distance = measure()
if(distance > -1):
print("Measured Distance = %.1f cm" % distance)
else:
print("#")
time.sleep(0.5)
except KeyboardInterrupt:
print("Measurement stopped by User")
GPIO.cleanup()
constantly OUTPUT: "#"
Seems like an issue with the GPIO settings or a timing issue as the same setup works with an Arduino.
Try with higher trigger on time (maybe 20us)
After elapsed calculation, print the elapsed time on the screen and check the actual value
If it still doesn't work, then you can also checkout the alternate output options like serial UART, PWM, etc. You can get more details here -
https://tutorials.probots.co.in/communicating-with-a-waterproof-ultrasonic-sensor-aj-sr04m-jsn-sr04t/
I have a class for a DC-motor. It has attributes that can e.g. change the set rotational speed.
In order to control the actual speed I would like to run a thread that guards the acceleration. So if a user sets a new speed the thread will slowly increase the actual speed to match the set speed.
My approach:
import time
import threading
import RPi.GPIO as GPIO
class motorController:
#constructors
def __init__(self,maxPower,powerPin,directionPin,direction=True):
self.maxPower = abs(maxPower)
self.power = 0 #initially off
self.setPower = 0
#set pins motors are connected to
self.powerPin = powerPin
self.directionPin = directionPin
self.direction = direction
#initialize PWM
GPIO.setmode(GPIO.BCM)
#initialize powerPin
GPIO.setup(self.powerPin, GPIO.OUT) # set pin to output
self.powerPwm = GPIO.PWM(self.powerPin, 100) # Initialize PWM on pwmPin 100Hz frequency, max is 8kHz, min is 10Hz
self.powerPwm.start(self.power) # Start PWM with 0% duty cycle
#initialize directionPin
GPIO.setup(self.directionPin, GPIO.OUT,initial=self.direction) # set pin to output
#initialize controll deamon
self.__lastCall = time.time()
self.setPointIsNotReached = threading.Condition() #currently unused
self.deamonTimeLock = threading.Lock()
self.controllThread = threading.Thread(target=self.__powerControllerDeamon())
self.controllThread.setDaemon(True)
self.controllThread.start()
def setTargetPower(self,setPower):
setPower = min(setPower,self.maxPower)
self.setPower = max(setPower,-self.maxPower)
with self.deamonTimeLock:
self.__lastDeamonCall = t
def __setPower(self,power):
#limit power to maxPower
self.power = min(abs(power),self.maxPower)
self.powerPwm.ChangeDutyCycle(self.power)
#set rotation direction
if power < 0:
self.direction = False
else:
self.direction = True
GPIO.output(self.directionPin, self.direction) #set to 3.3V if direction is true, or 0V if direction is false
def __powerControllerDeamon(self):
#private method that controls the power of the motor
t = time.time()
dt = t-self.__lastCall
if self.power > self.setPower:
m = -50 #ramp from 100 to 0 in minimal 2 sec
else:
m = 20 # ramp from 0 to 100 in minimal 5sec
newPower = self.power + m * dt
#detect if power is reched through change of sign
dP = self.setPower - self.power
dP2 = self.setPower - newPower
if dP*dP2 <= 0: #change of sign or one is zero
newPower = self.setPower #set point reached
else:
with self.setPointIsNotReached
self.setPointIsNotReached.notify()#set point NOT reached
print(newPower)
self.__setPower(newPower)
with self.deamonTimeLock:
self.__lastDeamonCall = t
and
from motorController import motorController as mC
import time
try:
m1 = mC(100,18,17)
m1.setTargetPower(100)
time.sleep(10) #should have powered up by now
except BaseException as e:
import RPi.GPIO as GPIO
GPIO.cleanup()
raise(e)
In this example, the thread function is called once and then never again.
I'm new to threading and python. My questions:
Can I create a thread from a constructor and have it running until the main program ends (that's why i set deamon true)?
If the answer is yes, what's my mistake?
Your __powerControllerDeamon method should contain a loop that runs until it reaches the desired speed or until it is told to stop.
Since it doesn't contain a loop, it will run once and exit.
Note that this loop should also contain a small amount of sleep, to prevent it from hogging the CPU.
I'm new to programming in general and this is my first post here, so please explain like I'm five.
This is a random string combination generator (sorry if I don't know how to call it properly) and I want to make the program start counting time since A key is first pressed until Q is pressed, without counting repeats caused by pressing A.
I also know that this might come handy, but I don't really know how to make it work.
Here's the code:
import random
import os
print('hello world')
while True:
while True:
key = msvcrt.getch().lower()
if key == b'a':
os.system('cls')
alpha = random.randint(1, 2)
bravo = random.randint(1, 2)
if alpha == 1:
print('foo')
elif alpha == 2:
print('bar')
if bravo == 1:
print('spam')
elif bravo == 2:
print('eggs')
elif key == b'q':
os.system('cls')
print('elapsed time: mm:ss') #this is where i want to have shown time elapsed from pressing A for the first time until pressing Q
break
We create start uninitialized (as None) outside the loop
When a is pressed, we check if start is uninitialized (if start is None)
2.1. If it is uninitialized. we initialize with current time
When q is pressed
3.1. We check if start is initialized (if start is not None), (to cover the case that q is the first input so we won't do the next step if start is uninitialized)
3.2. If start is initialized we print elapsed time
import random
import os
from timeit import default_timer as timer
print('hello world')
start = None
while True:
while True:
key = msvcrt.getch().lower()
if key == 'a':
# If start time is uninitialized
if start is None:
# Initialize start time
start = timer()
os.system('cls')
alpha = random.randint(1, 2)
bravo = random.randint(1, 2)
if alpha == 1:
print('foo')
elif alpha == 2:
print('bar')
if bravo == 1:
print('spam')
elif bravo == 2:
print('eggs')
elif key == 'q':
os.system('cls')
if start is not None:
end = timer()
print(f'elapsed time: {end - start}')
break
I'm on Raspberry Pi, using Python.
I would like to receive continuous input from a distance sensor and have the distance value determine whether or not to send output.
I have a output function, gogo, and a sense function, sense, which updates the distance value.
I'd like to have the output start when below 20 distance and the output stop when the distance reaches threshold of 20, but the only solution that I can see is another loop.
My code is not working and I'm thinking that there's a nice solution, but I am not well-versed in loops.
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
distance = 40.0
TRIG = 4
ECHO = 18
GPIO.setup(TRIG,GPIO.OUT)
GPIO.setup(ECHO,GPIO.IN)
GPIO.setup(23, GPIO.OUT)
GPIO.setup(24, GPIO.OUT)
GPIO.setup(25, GPIO.OUT)
def gogo():
Motor1A = 23
Motor1B = 24
Motor1E = 25
GPIO.setup(Motor1A,GPIO.OUT)
GPIO.setup(Motor1B,GPIO.OUT)
GPIO.setup(Motor1E,GPIO.OUT)
print "Turning motor on"
GPIO.output(Motor1A,GPIO.HIGH)
GPIO.output(Motor1B,GPIO.LOW)
GPIO.output(Motor1E,GPIO.HIGH)
def sense():
GPIO.output(TRIG, True)
time.sleep(0.00001)
GPIO.output(TRIG, False)
while GPIO.input(ECHO) == False:
start = time.time()
while GPIO.input(ECHO) == True:
end = time.time()
sig_time = end-start
#CM:
distance = sig_time / 0.000058
#inches:
#distance = sig_time / 0.000148
print('Distance: {} centimeters'.format(distance))
while distance > 20.0:
print (distance)
sense()
else:
print (distance)
gogo()
sense()
GPIO.cleanup()
The problem is scope; distance is constantly in your 40 main code. It gets updated only in sense()
First, let's edit sense to return the value of distance
def sense():
GPIO.output(TRIG, True)
time.sleep(0.00001)
GPIO.output(TRIG, False)
while GPIO.input(ECHO) == False:
start = time.time()
while GPIO.input(ECHO) == True:
end = time.time()
sig_time = end-start
#CM:
distance = sig_time / 0.000058
#inches:
#distance = sig_time / 0.000148
print('Distance: {} centimeters'.format(distance))
return distance
you should also probably create a function that turns the motor off
you need to define distance, also let's make a loop that runs forever. right now, your loop only runs until distance< 20
distance = sense()
while True:
if distance > 20:
<call motor off function here>
print (distance)
else:
print (distance)
gogo()
distance = sense() #now we're checking distance every cycle
I am trying to switch on and off the LED based on a set set_car_id returning some value within a time interval. If the set returns some value, i want the LED to be brighter for 8 seconds. In the code shown below, once the set returns a value, the LED is switched on for 8 seconds. But, if the set returns a value at 5 second (within the 8 sec), then the LED won't be switched on till next 13 sec, it will be on for 3 more seconds and then suddenly switches off. I am showing only smaller part of the code. Any suggestions to solve?
last_bright_time = None
last_dim_time = None
new_action = -1
def LED_control(set_car_id):
global last_bright_time
global last_dim_time
curr_time = time.time()
should_remain_bright = False
should_remain_dim = False
if (new_action == 0): #new_action ==0 corresponds to set_car_id returning some value
if last_bright_time == None:
last_bright_time = time.time()
if (curr_time - last_bright_time) < 8:
should_remain_bright = True
if ((len(set_car_id) > 0) or should_remain_bright = True):
car_light(1) # function to bright the LED
last_dim_time = None
else:
car_light(0) # function to dim the LED
last_bright_time = None
Try this:
import time
while True:
brighten()
time.sleep(8)
dim()
time.sleep(8)
If you want something more precise:
import time
def sleep():
time_start = time.time()
while time.time() < time_start + 8000:
pass
while True:
brighten()
sleep()
dim()
sleep()
In the pieces of code above, you have to define the brighten and dim functions.