|
@@ -1,14 +1,15 @@
|
|
|
#!/usr/bin/env python
|
|
|
+#-*- coding:utf-8 -*-
|
|
|
|
|
|
"""
|
|
|
- A Python driver for the Arduino microcontroller running the
|
|
|
- ROSArduinoBridge firmware.
|
|
|
+ A Python driver for the Arduino microcontroller.
|
|
|
"""
|
|
|
|
|
|
from math import pi as PI
|
|
|
import sys, traceback
|
|
|
from serial.serialutil import SerialException
|
|
|
from serial import Serial
|
|
|
+import numpy as np
|
|
|
import thread
|
|
|
import smbus
|
|
|
import rospy
|
|
@@ -22,15 +23,16 @@ class Arduino:
|
|
|
N_ANALOG_PORTS = 10
|
|
|
N_DIGITAL_PORTS = 54
|
|
|
|
|
|
- def __init__(self, is_use_serial, serial_port="/dev/ttyACM0", baudrate=57600,i2c_smbus_num=1, i2c_slave_addr=8, timeout=0.5):
|
|
|
- self.PID_RATE = 40 # Do not change this! It is a fixed property of the Arduino PID controller.
|
|
|
+ def __init__(self, is_use_serial,serial_port="/dev/ttyACM0",baudrate=57600,i2c_smbus_num=1,i2c_slave_addr=8,timeout=0.5):
|
|
|
+ self.PID_RATE = 40 #Don't change this ! It is a fixed property of the Arduino PID controller.
|
|
|
self.PID_INTERVAL = 25
|
|
|
|
|
|
- self.is_use_serial = is_use_serial
|
|
|
- self.serial_port = serial_port
|
|
|
- self.baudrate = baudrate
|
|
|
+ self.is_use_serial = is_use_serial #与下位机arduino的通信方式是否使用串口还是IIC
|
|
|
|
|
|
- self.i2c_smbus_num = i2c_smbus_num
|
|
|
+ self.serial_port = serial_port
|
|
|
+ self.baudrate = baudrate
|
|
|
+
|
|
|
+ self.i2c_smbus_num = i2c_smbus_num
|
|
|
self.i2c_slave_addr = i2c_slave_addr
|
|
|
|
|
|
self.timeout = timeout
|
|
@@ -64,7 +66,6 @@ class Arduino:
|
|
|
test = self.get_baud()
|
|
|
if test != self.baudrate:
|
|
|
time.sleep(1)
|
|
|
- print "Connecting ..."
|
|
|
test = self.get_baud()
|
|
|
if test != self.baudrate:
|
|
|
raise SerialException
|
|
@@ -82,7 +83,6 @@ class Arduino:
|
|
|
|
|
|
def i2c_connect(self):
|
|
|
try:
|
|
|
-
|
|
|
print "Connecting to Arduino on IIC addr ", self.i2c_slave_addr, "..."
|
|
|
test = self.i2c_get_baud()
|
|
|
if test != self.baudrate:
|
|
@@ -102,18 +102,20 @@ class Arduino:
|
|
|
print "Cannot connect to Arduino IIC slave addr !"
|
|
|
os._exit(1)
|
|
|
|
|
|
-
|
|
|
def open(self):
|
|
|
''' Open the serial port.
|
|
|
'''
|
|
|
self.serial_port.open()
|
|
|
|
|
|
def close(self):
|
|
|
- ''' Close the serial port.
|
|
|
+ ''' Close the serial port or i2c bus connect.
|
|
|
'''
|
|
|
+ print "Now disconnecting ..."
|
|
|
self.beep_ring(0)
|
|
|
- self.serial_port.close()
|
|
|
- self.i2c_bus.close()
|
|
|
+ if self.is_use_serial:
|
|
|
+ self.serial_port.close()
|
|
|
+ else:
|
|
|
+ self.i2c_bus.close()
|
|
|
|
|
|
def send(self, cmd):
|
|
|
''' This command should not be used on its own: it is called by the execute commands
|
|
@@ -163,7 +165,7 @@ class Arduino:
|
|
|
'''
|
|
|
try:
|
|
|
values = self.recv(self.timeout * self.N_ANALOG_PORTS).split()
|
|
|
- return map(int, values)
|
|
|
+ return map(float, values)
|
|
|
except:
|
|
|
return []
|
|
|
|
|
@@ -179,7 +181,6 @@ class Arduino:
|
|
|
|
|
|
ntries = 1
|
|
|
attempts = 0
|
|
|
-
|
|
|
try:
|
|
|
self.serial_port.write(cmd + '\r')
|
|
|
value = self.recv(self.timeout)
|
|
@@ -200,7 +201,7 @@ class Arduino:
|
|
|
return value
|
|
|
|
|
|
def execute_array(self, cmd):
|
|
|
- ''' Thread safe execution of "cmd" on the Arduino returning an array.
|
|
|
+ ''' Thread safe execution of "cmd" on the Arduino returning an float array.
|
|
|
'''
|
|
|
self.mutex.acquire()
|
|
|
try:
|
|
@@ -228,7 +229,7 @@ class Arduino:
|
|
|
return []
|
|
|
|
|
|
try:
|
|
|
- values = map(int, values)
|
|
|
+ values = map(float, values)
|
|
|
except:
|
|
|
values = []
|
|
|
|
|
@@ -247,7 +248,6 @@ class Arduino:
|
|
|
|
|
|
ntries = 1
|
|
|
attempts = 0
|
|
|
-
|
|
|
try:
|
|
|
self.serial_port.write(cmd + '\r')
|
|
|
ack = self.recv(self.timeout)
|
|
@@ -271,7 +271,7 @@ class Arduino:
|
|
|
def update_pid(self, AWheel_Kp, AWheel_Kd, AWheel_Ki, AWheel_Ko,
|
|
|
BWheel_Kp, BWheel_Kd, BWheel_Ki, BWheel_Ko,
|
|
|
CWheel_Kp, CWheel_Kd, CWheel_Ki, CWheel_Ko ):
|
|
|
- ''' Set the PID parameters on the Arduino
|
|
|
+ ''' Set the PID parameters on the Arduino by serial
|
|
|
'''
|
|
|
print "Updating PID parameters"
|
|
|
cmd = 'u '+str(AWheel_Kp)+':'+str(AWheel_Kd)+':'+str(AWheel_Ki)+':'+str(AWheel_Ko)+':'+str(BWheel_Kp)+':'+str(BWheel_Kd)+':'+str(BWheel_Ki)+':'+str(BWheel_Ko)+':'+str(CWheel_Kp)+':'+str(CWheel_Kd)+':'+str(CWheel_Ki)+':'+str(CWheel_Ko)
|
|
@@ -339,7 +339,6 @@ class Arduino:
|
|
|
else:
|
|
|
return values
|
|
|
|
|
|
-
|
|
|
def reset_encoders(self):
|
|
|
''' Reset the encoder counts to 0 by serial port
|
|
|
'''
|
|
@@ -370,19 +369,6 @@ class Arduino:
|
|
|
except:
|
|
|
return None
|
|
|
|
|
|
- def drive_m_per_s(self, AWheel, BWheel, CWheel):
|
|
|
- ''' Set the motor speeds in meters per second.
|
|
|
- '''
|
|
|
- aWheel_revs_per_second = float(AWheel) / (self.wheel_diameter * PI)
|
|
|
- bWheel_revs_per_second = float(BWheel) / (self.wheel_diameter * PI)
|
|
|
- cWheel_revs_per_second = float(CWheel) / (self.wheel_diameter * PI)
|
|
|
-
|
|
|
- aWheel_ticks_per_loop = int(aWheel_revs_per_second * self.encoder_resolution * self.PID_INTERVAL * self.gear_reduction)
|
|
|
- bWheel_ticks_per_loop = int(bWheel_revs_per_second * self.encoder_resolution * self.PID_INTERVAL * self.gear_reduction)
|
|
|
- cWheel_ticks_per_loop = int(cWheel_revs_per_second * self.encoder_resolution * self.PID_INTERVAL * self.gear_reduction)
|
|
|
-
|
|
|
- self.drive(aWheel_ticks_per_loop , bWheel_ticks_per_loop, cWheel_ticks_per_loop)
|
|
|
-
|
|
|
def stop(self):
|
|
|
''' Stop all three motors.
|
|
|
'''
|
|
@@ -410,9 +396,6 @@ class Arduino:
|
|
|
def pin_mode(self, pin, mode):
|
|
|
return self.execute_ack('c %d %d' %(pin, mode))
|
|
|
|
|
|
- def alarm_write(self, value):
|
|
|
- return self.execute_ack('f %d' %value)
|
|
|
-
|
|
|
def beep_ring(self, value):
|
|
|
return self.execute_ack('p %d' %value)
|
|
|
|
|
@@ -422,6 +405,9 @@ class Arduino:
|
|
|
def detect_current(self):
|
|
|
return self.execute('f')
|
|
|
|
|
|
+ def detect_distance(self): #检测三个红外测距传感器的返回值,一共返回三个值,分别为前,左,右三个测距值
|
|
|
+ return self.execute_array('h')
|
|
|
+
|
|
|
def light_show(self, value):
|
|
|
return self.execute_ack('l %d' %value)
|
|
|
|
|
@@ -463,28 +449,33 @@ class Arduino:
|
|
|
#else:
|
|
|
# return values
|
|
|
|
|
|
-""" Basic test for connectivity """
|
|
|
+""" Basic test for connectivity by serial port or IIC bus"""
|
|
|
if __name__ == "__main__":
|
|
|
+ is_use_serial = True
|
|
|
portName = "/dev/ttyACM0"
|
|
|
baudRate = 57600
|
|
|
|
|
|
- myArduino = Arduino(port=portName, baudrate=baudRate, timeout=0.5)
|
|
|
+ iic_smbus = 1
|
|
|
+ iic_num = 8
|
|
|
+
|
|
|
+ myArduino = Arduino(is_use_serial, serial_port=portName, baudrate=baudRate, i2c_smbus_num=iic_smbus, i2c_slave_addr=iic_num, timeout=0.5)
|
|
|
myArduino.connect()
|
|
|
|
|
|
print "Sleeping for 1 second..."
|
|
|
time.sleep(1)
|
|
|
|
|
|
- print "Reading on analog port 0", myArduino.analog_read(0)
|
|
|
- print "Reading on digital port 0", myArduino.digital_read(0)
|
|
|
- print "Blinking the LED 3 times"
|
|
|
+ print "Test Beep ring 3 times..."
|
|
|
for i in range(3):
|
|
|
- myArduino.digital_write(13, 1)
|
|
|
- time.sleep(1.0)
|
|
|
- #print "Current encoder counts", myArduino.encoders()
|
|
|
- print "Connection test successful.",
|
|
|
+ myArduino.beep_ring(1)
|
|
|
+ time.sleep(2.0)
|
|
|
+
|
|
|
+ print "Did you heard the beep ring ?"
|
|
|
+ print "Now print infrared sensors value:"
|
|
|
+ values = myArduino.detect_distance()
|
|
|
+ distances = np.array([values[0], values[1], values[2]])
|
|
|
+ print distances/100.0
|
|
|
|
|
|
myArduino.stop()
|
|
|
myArduino.close()
|
|
|
-
|
|
|
print "Shutting down Arduino."
|
|
|
|