6
$\begingroup$

I am having difficulty sustaining a connection between my Raspberry Pi (Model B running Raspbian) and my Arduino (Uno) while sending signals from the Raspberry Pi to a continuously rotating servo (PowerHD AR- 3606HB Robot Servo) via Python. I'm not sure if there is a more efficent way of sending servo instructions via Python to the Arduino to rotate the servo. I'm attempting to communicate signals from the Raspberry Pi to the Arduino via USB using what I believe is considered a "digital Serial connection". My current connection:

Wireless Xbox 360 Controller -> Wireless Xbox 360 Controller Receiver -> Raspberry Pi -> Externally Powered USB Hub -> Arduino -> Servo

Enter image description here

Servo connection to Arduino:
   Signal (Orange) - pin 9
   Power (Red) - +5 V
   Ground (Black) - GND

On the Raspberry Pi I have installed the following (although not all needed for addressing this problem):

The sketch I've uploaded to the Arduino Uno is the corresponding sketch provided with the Python-Arduino-Command-API. *Again, I'm not positive that this is the best method means of driving my servo from Python to Arduino (to the servo).

From the Raspberry Pi, I can see the Arduino is initially correctly connected via USB:

pi@raspberrypi ~/Python-Arduino-Command-API $ dir /dev/ttyA*
/dev/ttyACM0  /dev/ttyAMA0

and

pi@raspberrypi ~/Python-Arduino-Command-API $ lsusb
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 045e:0719 Microsoft Corp. Xbox 360 Wireless Adapter
Bus 001 Device 005: ID 1a40:0201 Terminus Technology Inc. FE 2.1 7-port Hub
Bus 001 Device 006: ID 0bda:8176 Realtek Semiconductor Corp. RTL8188CUS 802.11n WLAN Adapter
Bus 001 Device 007: ID 046d:c52b Logitech, Inc. Unifying Receiver
Bus 001 Device 008: ID 2341:0043 Arduino SA Uno R3 (CDC ACM)

From the Raspberry Pi, I'm able to rotate the servo as a test clockwise for one second, counter-clockwise for one second, then stop the servo, with the following Python script:

#!/usr/bin/env python
from Arduino import Arduino
import time

board = Arduino(9600, port='/dev/ttyACM0')

board.Servos.attach(9) # Declare servo on pin 9
board.Servos.write(9, 0) # Move servo to full speed, clockwise
time.sleep(1) # Sleep for 1 second
print board.Servos.read(9) # Speed check (should read "0")

board.Servos.write(9, 180)
time.sleep(1)
print board.Servos.read(9) # (Should read "180")

board.Servos.write(9, 90)
print board.Servos.read(9)
board.Servos.detach(9)

The output via the Raspberry Pi terminal reads:

0
180
90

Although this only performs full-speed in both direction (as well as the calibrated "stop" speed of 90), I have successfully alternated from a full-speed to slower speeds, for example, going from 0 up to 90 in increments of 10.

From the Raspberry Pi, I'm able to send input from my Xbox controller to drive the servo with a small custom Python script I've created along with xboxdrv (which works flawlessly with other projects I'm doing):

#!/usr/bin/python

from legopi.lib import xbox_read
from Arduino import Arduino

# To catch Ctrl+C
import signal
import sys

# The deadzone within which we ignore inputs, approximately 1/3 of total possible input
DEADZONE = 12000

def signal_handler(signal, frame):
    print "Stopping Wrapper"
    sys.exit(0)

# Capture Ctrl+C so we can shut down nicely
signal.signal(signal.SIGINT, signal_handler)

print "Starting Wrapper"
print "Press Ctrl+C at any time to quit"

board = Arduino(9600, port='/dev/ttyACM0')
board.Servos.attach(9)
board.Servos.write(9, 90)

for event in xbox_read.event_stream(deadzone=DEADZONE):
    print "Xbox event: %s" % (event)

    # If the RB button it's being held, rotate the servo counter-clockwise at full-speed.
    # When the RB button is released, stop the servo.
    if(event.key=='RB'):
        if(event.value>0):
            board.Servos.write(9, 180)
            print board.Servos.read(9)
        else:
            board.Servos.write(9, 90)
            print board.Servos.read(9)
        continue

This script runs, and I'm able to control the servo using the RB button on my controller. However, it eventually fails - sometimes after minutes, sometimes after seconds (rapid and intermittent input seemingly having no influence on expediting a crash). Input is no longer read by the script, the terminal comes to a halt, the servo freezes on whatever the last command given was (either spinning endlessly or stopped), and I'm forced to Ctrl + C out of the script. If I check to see if the Arduino is still connected to the Raspberry Pi, it shows that it has reconnected itself to the Raspberry Pi as "ttyACM1" (from /dev/ttyACM0 to /dev/ttyACM1):

pi@raspberrypi ~/robotarm $ dir /dev/ttyA*
/dev/ttyACM1  /dev/ttyAMA0

Why does the Arduino reconnect itself? Is there some other way I should be processing this information? Distance to the wireless Xbox receiver is not a factor as all of these pieces are adjacent to one another for testing purposes. It will prove impossible to use this servo as a wheel for my robot if I'm constantly tending to this issue.

$\endgroup$
  • $\begingroup$ I read you are using an USB connection between Raspberry Pi and Arduino. You are using the power from the USB to the Arduino and then to the Servo? So 800mA could be an issue, the USB should provide at maximum 500mA. Try to use an external power supply to the Arduino, at least 1A because of the motor, and try again. Anyway I think you could do a direct UART link without using the USB for that. More specifically the Arduino could be reseting, and as it is working with a USB-Serial converter, the fast reset with no signal could be changing the port at the Raspberry Pi. $\endgroup$ – Diego C Nascimento Jan 11 '14 at 20:49
  • 1
    $\begingroup$ Or a simple test, try removing the "servo" motor, and see if this occurs. If not, try adding a small current led instead of the servo and see if the signal is being transmitted. If so, is probably the "servo" motor that is getting to much current from the power supply "chain". $\endgroup$ – Diego C Nascimento Jan 11 '14 at 20:55
  • $\begingroup$ It almost sounds as if you have a bad physical connection between pi->hub->arduino. A faulty connector, or broken wire can be in the position to almost always be conducting, but when vibrated or wiggled, fail momentarily. This could cause the pi to assume the re-acquired Arduino is a another Arduino.I would be particularity suspicious of the Tx/Rx pair. $\endgroup$ – Mhz4.77 Jan 12 '14 at 15:23
  • $\begingroup$ @DiegoCNascimento Great test idea, the Arduino was able to process the information without crashing once I disconnected the "servo" (I understand how this piece of hardware essentially forfeits all rights to be identified as a true servo). Looked up the documentation on the part, it has a Stall current of 800mA. The servo was attempting to draw more than 500mA over USB and was triggering the Arduino's USB Overcurrent Protection feature. An appropriate power supply for the Arduino fixed the issue. $\endgroup$ – root Jan 12 '14 at 21:39
  • $\begingroup$ @DiegoCNascimento If you rephrase this solution as an actual answer I'll be happy to mark it as the answer. $\endgroup$ – root Jan 12 '14 at 21:40
4
+100
$\begingroup$

I suspect that your Arduino is reseting, by the fact that the stall current of the motor by the product sheet is $800mA$, and you are using the USB power, then Arduino regulator, to supply the motor.

As you are using the USB/Serial converter to make the connection to the Raspberry Pi, when it resets, it can be creating a new "virtual" serial port on the Raspberry Pi, like you are saying.

The USB maximum supply of current is near $500mA$ in this case, but in reality there's more than the motor, Arduino, and so on, so its less.

To test it, just disconnect the motor and see if don't reset or create a new "virtual" serial port.

Being the problem (or even if its not) you should power your motor from an external supply capable of suppling the required current under the voltage you want.

The servo was attempting to draw more than 500mA over USB and was triggering the Arduino's USB Overcurrent Protection feature. An appropriate power supply for the Arduino fixed the issue.

I still suggest you to use other power supply to the motor, or use the same power supply but not use the power from the Arduino to supply the motor. This is due that even with an external power supply the Arduino has an power regulator with a $1000mA$ capacity, and also this could put some noise on the ATMega supply. Of course the power supply should be in the motor voltage supply range.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.