Reputation: 123
I am trying to make an autonomous car that has a line sensor and a ultrasonic sensor. The car needs to go forwards if the the line sensor on the left and right is activated
if pin16.read_digital == 1 & pin 15.read_digital == 1
pin2.write_anlog(180)
The above code works fine. I have finished the code which integrates the line sensor and the ultrasonic sensor. The finished code is below :
from microbit import *
from neopixel import NeoPixel
import time
import machine
def setup():
display.off()
np = NeoPixel(pin0, 5)
np.clear()
pin4.set_pull(pin4.PULL_UP)
pin1.set_analog_period(20)
pin2.set_analog_period(20)
pin15.set_pull(pin15.PULL_UP)
pin16.set_pull(pin16.PULL_UP)
def distance():
pin3.write_digital(0)
time.sleep_us(2)
pin3.write_digital(1)
time.sleep_us(10)
pin3.write_digital(0)
output = machine.time_pulse_us(pin4, 1)
return output * 0.034 / 2
def forward():
pin2.write_analog(1)
def backward():
pin2.write_analog(180)
def stop():
pin2.write_analog(90)
def line():
if pin15.read_digital() == 1 & pin16.read_digital() == 1:
return True
else:
return False
setup()
# pin1.write_analog(90)
sleep(200)
# pin1.write_analog(70) right
# pin1.write_analog(150) right
while True:
if (distance() > 5) & line():
forward()
else:
stop()
This works fine, however when I try to put the left and right in, it does not work. How do I fix this ? The code for left and right is below
while True:
if pin15.read_digital() == 1 & pin16.read_digital() == 0:
pin1.write_analog(180)
pin2.write_analog(95)
time.sleep(500)
pin2.write_analog(90)
elif pin15.read_digital() == 0 & pin16.read_digital() == 1:
pin1.write_analog(70)
pin2.write_analog(180)
time.sleep(500)
pin2.write_analog(90)
Upvotes: 1
Views: 104
Reputation: 82929
You should use and
instead of &
. &
is bitwise and, which binds stronger than ==
, whereas and
is logical and, which binds weaker than ==
.
>>> a, b = 0, 1
>>> a == 0 and b == 1
True
>>> a == 0 & b == 1
False
The latter example, which corresponds to your if
statements, is parsed as a == (0 & 1) == 1
, i.e. 0 == 0 == 1
(and this, by Python comparison chaining, is not (0 == 0) == 1
, which would evaluate to True
, but (0 == 0) and (0 == 1)
).
For a == 1 & b == 1
this is not a problem, but in all other cases, it will behave unexpectedly.
>>> cases = [(0, 0), (0, 1), (1, 0), (1, 1)]
>>> [a == 0 & b == 0 for a, b in cases] # should be [True, False, False, False]
[True, True, False, False] # but evaluates as "a == 0 == 0"
>>> [a == 0 & b == 1 for a, b in cases] # should be [False, True, False, False]
[False, False, False, False] # but evaluates as "a == 0 == 1"
>>> [a == 1 & b == 0 for a, b in cases] # should be [False, False, True, False]
[True, False, False, False] # but evaluates as "a == b == 0"
>>> [a == 1 & b == 1 for a, b in cases] # should be [False, False, False, True]
[False, False, False, True] # evaluates as "a == b == 1" ("correct")
Upvotes: 1
Reputation: 21
I'm not an expert in Arduino nor in the Neopixel library. However, aren't you missing the forward case in your third block of code? Also, it's better to use and
instead of &
, because &
is a bitwise operator and is ranked higher than == in the operator precedence rules, as tobias_k says (you could use parenthesis to work around this if you wanted to, but why would you prefer the bitwise operator?). No need of the == operator, by the way. An integer is automatically evaluated as False in an if statement if it's 0, and True otherwise:
while True:
read_left, read_right = pin15.read_digital(), pin16.read_digital()
if read_left and read_right:
# your code to go forward
elif read_left and not read_right:
# your code to turn left
elif not read_left and read_right:
# your code to turn right
else:
# your code when no line is detected, if you want to handle this case
Upvotes: 1