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

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.

Related

Sending commands to uart on python

I am trying to write a pyserial command to the uart port to control the robot arm.
I have some manual:
manual for arm
manual command example
I use pyserial like that:
import serial
from time import sleep
port = serial.Serial("/dev/ttyUSB0", baudrate=9600, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=8, timeout=1)
port.write(b"\x055\x55\x0B\x03\x02\x20\x03\x02\xB0\x04\x09\xFC\x03\xaa")
sleep(0.3)
#port.write(b"\x05")
#sleep(0.3)
#port.write(b"\x06")
#sleep(0.03)
#port.write(b"\x08\x01\x00")
print('send')
At first I tried to run it in one line, the buzzer will beep that the command was accepted, but the hand does not move.
Then I tried to split the Header separately for the Length in the next line and the Command with Parameters in the next.
Tell me how you can send these commands to the port, maybe there is something ready to do this in Python?
LSC Series Servo Controller Communication Protocol V1.2 manual says:
If the user transmits the correct data to the servo
controller, the blue LED 2 on the controller will flash one time, indicating that the
correct data have been received. If the user transmits the wrong data, then the blue
LED2 will not have any reaction and will keep the bright, then the buzzer will beepbeep twice to remind the user of the data error.
The only thing in that manual about that buzzer is that it beeps 2 times if there is a data error...

How do I get immediate response between motors and sensors?

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.

Problems with Micropython command time_pulse_us on Microbit

I would like to ask some help from you. I'm trying to connect a distance sensor to my microbit but when I use the command "time_pulse_us" it always gives -2 or -1. I read the documentation, I understand the meaning of those numbers but I think there's a problem with the command or probably I'm using it the wrong way.
In that regard, I wrote a simple snippet to test the command. Could you tell me what's wrong with it?
from microbit import * //to import microbit modules
from machine import * //to import the time_pulse_us command
while True:
pin1.write_digital(0)
time = time_pulse_us(pin2, 1) //to begin the timing
pin1.write_digital(1) //this pin is connected to an LED
sleep(1000)
value = pin2.read_digital() //gives 1, as this pin is reading the voltage from the led
pin1.write_digital(0) //this will make the time_pulse command to end timing
display.scroll(time) //it should display the duration of the pulse.
//Displays -2 instead.
display.scroll(value) //gives 1, as expected
Why is this not working?
time_pulse_us() runs sequentially, not in the background, so at the call it will wait 1 second for the pin to reach 1, which it will not do, hence time will be set to -2, before the program goes on to the next command write_digital(1).

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.

Raspberry Pi GPIO stops working after some time

when using the GPIO library on the Raspberry PI and having an example code like this:
while True:
GPIO.setup(21, GPIO.OUT)
pwm = GPIO.PWM(21, 50)
pwm.start(0)
for i in range(0, 101, 2):
pwm.ChangeDutyCycle(i)
time.sleep(0.03)
for i in range(100, -1, -2):
pwm.ChangeDutyCycle(i)
time.sleep(0.03)
pwm.stop()
GPIO.cleanup(21)
time.sleep(1)
The code might stop suddenly after a while. No error, just no changes via pwm are recognized any longer. Anyone got an idea why this is?
This issue has been mentioned here in the old sourceforge repo:
https://sourceforge.net/p/raspberry-gpio-python/tickets/111/
https://sourceforge.net/p/raspberry-gpio-python/tickets/94/
Its because the GPIO library by default creates a new pthread for every call without cleaning up afterwards, but the number of threads might be limited to a number of 250 or so.
I created a fork of this repo (https://github.com/wuestkamp/raspberry-gpio-python) which solves this and contains instructions on how to use this on your PI.