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
Externally Powered USB Hub
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
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.