How do I get immediate response between motors and sensors? - micropython

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.

Related

Microbit V1 servo motor's problem, it always does the entire return

the thing is that i'm working with Python in Micro Python for Microbit Editor.
I'm trying to set the angle of a servomotor, but the thing is that it is giving the entire return.
pin0.set_analog_period(20)
while True:
pin0.write_analog(50)
sleep(3000)
pin0.write_analog(75)
The same thing is happening when I try to code it with blocks

How to set Pin touch mode to capacitive on micro:bit v2 in MicroPython

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...

How does the stalled() function work in Pybricks-MicroPython

MicroPython 2.0 beta 5
Trying to understand how the stalled() function on the motor works. I run a motor at dc of 100, and hold the wheel so that it cannot move.
But the stalled function doesn't fire, indeed whatever I do I don't seem able to get it to return True?
I tried with less power, but still not able to get anything out of this function.
#!/usr/bin/env pybricks-micropython
from pybricks import ev3brick as brick
from pybricks.ev3devices import Motor
from pybricks.parameters import Port, Stop
left_motor = Motor(Port.B)
speed = 800
# option 1
left_motor.dc(100)
# option 2
#left_motor.run_until_stalled(speed, Stop.HOLD, 100)
while True:
if left_motor.stalled():
print("stalled")
If I use option 1: the motor runs, I hold it until it stops, nothing reported. I let go and off it goes again.
If I use option 2: the motor runs, I hold it, it stops. But at no point do I see a report saying it stalled.
A motor is stalled when it can't reach its target speed or angle, despite applying the maximum duty cycle.
Your example can be adapted like this:
#!/usr/bin/env pybricks-micropython
from pybricks.ev3devices import Motor
from pybricks.parameters import Port
from pybricks.tools import wait
# Initialize the motor
left_motor = Motor(Port.B)
# Start running the motor at 500 deg/s
left_motor.run(500)
# Do nothing until we are stalled
while not left_motor.stalled():
wait(10)
# Stop the motor
left_motor.stop()
This example is equivalent to the one-liner left_motor.run_until_stalled(500). The manual approach can be useful if you want to extend it to multiple motors.
The dc() method in the question does not set a target speed or angle; it sets the duty cycle directly, so there is no stall information.
Note: the left_motor.stalled() method is instead accessible through left_motor.control.stalled() as of Pybricks version Pybricks 2.0. It is in public beta only as of March 2020, so I'm not sure the version reported in the original post in August 2019 is correct.

How to add conditional statement to a flame sensor?

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.

Running two or more motors at the same time with PiFace Relay Plus and Motor Extra

I have a question. I have a Raspberry Pi connected to PiFace Relay Plus and PiFace Motor Extra. Is it possible to run two or more motors at the same time?
I have no problem with running one motor:
import pifacerelayplus
import time
pfr = pifacerelayplus.PiFaceRelayPlus(pifacerelayplus.MOTOR_DC)
pfr.motors[0].forward()
time.sleep(5)
pfr.motors[0].coast()
I also managed to run one motor and than next one:
import pifacerelayplus
import time
pfr = pifacerelayplus.PiFaceRelayPlus(pifacerelayplus.MOTOR_DC)
pfr.motors[0].forward()
time.sleep(5)
pfr.motors[0].coast()
time.sleep(2)
pfr.motors[1].forward()
time.sleep(5)
time.motors[1].coast()
But I can't find out how to make both motors run at the same time. I tried this code, but that only runs the first motor, than the program ends and the first motor still runs and never stops. The second motor never starts to run.
import pifacerelayplus
import time
pfr = pifacerelayplus.PiFaceRelayPlus(pifacerelayplus.MOTOR_DC)
pfr.motors[0].forward()
pfr.motors[1].forward()
time.sleep(5)
pfr.motors[0].coast()
pfr.motors[1].coast()
I even tried to create another variable "prf2" for second motor, but it didn't help neither. I'm glad for any help.
Are you getting any error when running the program? Looking at the source code of pifacerelayplus, it is INTENDED to fail if you give two motor commands within 0.15 seconds, on the grounds that the startup surge of two motors at once is likely to be more than your power supply can handle. A couple of short sleep()s should avoid this issue.