|
@@ -2,15 +2,18 @@
|
|
|
#-*- coding:utf-8 -*-
|
|
|
|
|
|
"""
|
|
|
- A Python driver for the Arduino microcontroller.
|
|
|
+ Copyright: 2016-2020 ROS小课堂 www.corvin.cn
|
|
|
+ Description: A Python driver for the Arduino microcontroller.
|
|
|
+ Author: corvin
|
|
|
+ History:
|
|
|
+ 20200329:增加获取电池剩余电量百分比函数.
|
|
|
"""
|
|
|
-
|
|
|
-from math import pi as PI
|
|
|
from serial.serialutil import SerialException
|
|
|
import thread, smbus, rospy, time, os
|
|
|
from serial import Serial
|
|
|
import sys, traceback
|
|
|
import numpy as np
|
|
|
+import roslib, rospy
|
|
|
|
|
|
|
|
|
class Arduino:
|
|
@@ -30,7 +33,7 @@ class Arduino:
|
|
|
self.i2c_smbus_num = i2c_smbus_num
|
|
|
self.i2c_slave_addr = i2c_slave_addr
|
|
|
|
|
|
- self.timeout = timeout
|
|
|
+ self.timeout = timeout
|
|
|
|
|
|
self.encoder_count = 0
|
|
|
self.writeTimeout = timeout
|
|
@@ -54,7 +57,7 @@ class Arduino:
|
|
|
|
|
|
def serial_connect(self):
|
|
|
try:
|
|
|
- print "Connecting to Arduino on port", self.serial_port, "..."
|
|
|
+ rospy.loginfo("Connecting to Arduino on port: " + self.serial_port)
|
|
|
self.serial_port = Serial(port=self.serial_port, baudrate=self.baudrate, timeout=self.timeout, writeTimeout=self.writeTimeout)
|
|
|
# The next line is necessary to give the firmware time to wake up.
|
|
|
time.sleep(1)
|
|
@@ -66,35 +69,29 @@ class Arduino:
|
|
|
raise SerialException
|
|
|
|
|
|
self.beep_ring(1)
|
|
|
- print "Connected at", self.baudrate
|
|
|
- print "Arduino is ready !"
|
|
|
+ rospy.loginfo("Arduino connected baudrate: "+str(self.baudrate))
|
|
|
except SerialException:
|
|
|
- print "Serial Exception:"
|
|
|
- print sys.exc_info()
|
|
|
- print "Traceback follows:"
|
|
|
- traceback.print_exc(file=sys.stdout)
|
|
|
- print "Cannot connect to Arduino!"
|
|
|
+ rospy.logerr("Cannot connect to Arduino !")
|
|
|
+ rospy.logerr(sys.exc_info())
|
|
|
+ rospy.logerr(traceback.print_exc(file=sys.stdout))
|
|
|
os._exit(1)
|
|
|
|
|
|
def i2c_connect(self):
|
|
|
try:
|
|
|
- print "Connecting to Arduino on IIC addr ", self.i2c_slave_addr, "..."
|
|
|
+ rospy.loginfo("Connecting to Arduino on IIC addr:"+self.i2c_slave_addr)
|
|
|
test = self.i2c_get_baud()
|
|
|
if test != self.baudrate:
|
|
|
time.sleep(1)
|
|
|
- print "Connecting ..."
|
|
|
test = self.i2c_get_baud()
|
|
|
if test != self.baudrate:
|
|
|
raise Exception
|
|
|
|
|
|
self.beep_ring(1)
|
|
|
- print "Connected at", self.baudrate
|
|
|
- print "Arduino is ready !"
|
|
|
+ rospy.loginfo("Arduino is connected by IIC !")
|
|
|
except Exception:
|
|
|
- print sys.exc_info()
|
|
|
- print "Traceback follows:"
|
|
|
- traceback.print_exc(file=sys.stdout)
|
|
|
- print "Cannot connect to Arduino IIC slave addr !"
|
|
|
+ rospy.logerr(sys.exc_info())
|
|
|
+ rospy.logerr(traceback.print_exc(file=sys.stdout))
|
|
|
+ rospy.logerr("Cannot connect to Arduino IIC slave addr !")
|
|
|
os._exit(1)
|
|
|
|
|
|
def open(self):
|
|
@@ -105,7 +102,6 @@ class Arduino:
|
|
|
def close(self):
|
|
|
''' Close the serial port or i2c bus connect.
|
|
|
'''
|
|
|
- print "Now disconnecting ..."
|
|
|
self.beep_ring(0)
|
|
|
if self.is_use_serial:
|
|
|
self.serial_port.close()
|
|
@@ -121,12 +117,12 @@ class Arduino:
|
|
|
def recv(self, timeout=0.5):
|
|
|
timeout = min(timeout, self.timeout)
|
|
|
''' This command should not be used on its own: it is called by the execute commands
|
|
|
- below in a thread safe manner. Note: we use read() instead of readline() since
|
|
|
- readline() tends to return garbage characters from the Arduino
|
|
|
+ below in a thread safe manner
|
|
|
'''
|
|
|
c = ''
|
|
|
value = ''
|
|
|
attempts = 0
|
|
|
+
|
|
|
while c != '\r':
|
|
|
c = self.serial_port.read(1)
|
|
|
value += c
|
|
@@ -185,11 +181,11 @@ class Arduino:
|
|
|
self.serial_port.write(cmd + '\r')
|
|
|
value = self.recv(self.timeout)
|
|
|
except:
|
|
|
- print "Exception executing command: " + cmd
|
|
|
+ rospy.logerr("Exception executing command: " + cmd)
|
|
|
attempts += 1
|
|
|
except:
|
|
|
self.mutex.release()
|
|
|
- print "Exception executing command: " + cmd
|
|
|
+ rospy.logerr("Exception executing command: " + cmd)
|
|
|
value = None
|
|
|
|
|
|
self.mutex.release()
|
|
@@ -215,11 +211,11 @@ class Arduino:
|
|
|
self.serial_port.write(cmd + '\r')
|
|
|
values = self.recv_array()
|
|
|
except:
|
|
|
- print("Exception executing command: " + cmd)
|
|
|
+ rospy.logerr("Exception executing command: " + cmd)
|
|
|
attempts += 1
|
|
|
except:
|
|
|
self.mutex.release()
|
|
|
- print "Exception executing command: " + cmd
|
|
|
+ rospy.logerr("Exception executing command: " + cmd)
|
|
|
raise SerialException
|
|
|
return []
|
|
|
|
|
@@ -252,12 +248,12 @@ class Arduino:
|
|
|
self.serial_port.write(cmd + '\r')
|
|
|
ack = self.recv(self.timeout)
|
|
|
except:
|
|
|
- print "Exception executing command: " + cmd
|
|
|
+ rospy.logerr("Exception executing command: " + cmd)
|
|
|
attempts += 1
|
|
|
except:
|
|
|
self.mutex.release()
|
|
|
- print "execute_ack exception when executing", cmd
|
|
|
- print sys.exc_info()
|
|
|
+ rospy.logerr("execute_ack exception when executing" + cmd)
|
|
|
+ rospy.logerr(sys.exc_info())
|
|
|
return 0
|
|
|
|
|
|
self.mutex.release()
|
|
@@ -268,14 +264,14 @@ class Arduino:
|
|
|
CWheel_Kp, CWheel_Kd, CWheel_Ki, CWheel_Ko ):
|
|
|
''' Set the PID parameters on the Arduino by serial
|
|
|
'''
|
|
|
- print "Updating PID parameters"
|
|
|
+ rospy.loginfo("Updating Motors 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)
|
|
|
self.execute_ack(cmd)
|
|
|
|
|
|
def i2c_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 ):
|
|
|
- print "Updating PID parameters by IIC"
|
|
|
+ rospy.loginfo("Updating PID parameters by IIC")
|
|
|
|
|
|
def get_baud(self):
|
|
|
''' Get the current baud rate on the serial port.
|
|
@@ -303,7 +299,7 @@ class Arduino:
|
|
|
def get_encoder_counts(self):
|
|
|
values = self.execute_array('e')
|
|
|
if len(values) != 3:
|
|
|
- print "Encoder count was not 3"
|
|
|
+ rospy.logerr("Encoder count was not 3")
|
|
|
raise SerialException
|
|
|
return None
|
|
|
else:
|
|
@@ -324,12 +320,12 @@ class Arduino:
|
|
|
result_flag = result_string.index('\r')
|
|
|
values=[int(e) for e in ''.join(result_string[:result_flag]).split('')]
|
|
|
except:
|
|
|
- print sys.exe_info()
|
|
|
+ rospy.logerr(sys.exe_info())
|
|
|
traceback.print_exc(file=sys.stdout)
|
|
|
return None
|
|
|
|
|
|
if len(values) != 3:
|
|
|
- print "Encoder count was not 3"
|
|
|
+ rospy.logwarn("Encoder count was not 3")
|
|
|
return None
|
|
|
else:
|
|
|
return values
|
|
@@ -354,8 +350,6 @@ class Arduino:
|
|
|
#rospy.loginfo("gripper operation ID:" + str(operation))
|
|
|
return self.execute_ack('z %d' %(operation))
|
|
|
|
|
|
-
|
|
|
-
|
|
|
def drive(self, AWheel, BWheel, CWheel):
|
|
|
''' Speeds are given in encoder ticks per PID interval
|
|
|
'''
|
|
@@ -402,29 +396,32 @@ class Arduino:
|
|
|
def beep_ring(self, value):
|
|
|
return self.execute_ack('p %d' %value)
|
|
|
|
|
|
- def detect_voltage(self):
|
|
|
- return self.execute('g')
|
|
|
-
|
|
|
def detect_current(self):
|
|
|
return self.execute('f')
|
|
|
|
|
|
def detect_distance(self): #检测三个红外测距传感器的返回值,一共返回三个值,分别为前,左,右三个测距值
|
|
|
+ #rospy.loginfo("detect distance")
|
|
|
return self.execute_array('h')
|
|
|
|
|
|
+ def getBatPercent(self): #获取电池的剩余电量百分比
|
|
|
+ percent = self.execute('g')
|
|
|
+ #rospy.loginfo("bat percent:" + str(percent))
|
|
|
+ return percent
|
|
|
+
|
|
|
def light_show(self, value):
|
|
|
return self.execute_ack('l %d' %value)
|
|
|
|
|
|
def get_pidin(self):
|
|
|
values = self.execute_array('i')
|
|
|
if len(values) != 3:
|
|
|
- print "pidin was not 3"
|
|
|
+ rospy.logerr("pidin was not 3")
|
|
|
raise SerialException
|
|
|
return None
|
|
|
else:
|
|
|
return values
|
|
|
|
|
|
def i2c_get_pidin(self):
|
|
|
- print "IIC Get Pidin !"
|
|
|
+ rospy.loginfo("IIC Get Pidin !")
|
|
|
#values = self.execute_array('i')
|
|
|
#if len(values) != 3:
|
|
|
# print "pidin was not 3"
|
|
@@ -436,14 +433,14 @@ class Arduino:
|
|
|
def get_pidout(self):
|
|
|
values = self.execute_array('o')
|
|
|
if len(values) != 3:
|
|
|
- print "pidout was not 3"
|
|
|
+ rospy.logerr("pidout was not 3")
|
|
|
raise SerialException
|
|
|
return None
|
|
|
else:
|
|
|
return values
|
|
|
|
|
|
def i2c_get_pidout(self):
|
|
|
- print "IIC Get Pidout !"
|
|
|
+ rospy.loginfo("IIC Get Pidout !")
|
|
|
#values = self.execute_array('o')
|
|
|
#if len(values) != 3:
|
|
|
# print "pidout was not 3"
|
|
@@ -464,21 +461,21 @@ if __name__ == "__main__":
|
|
|
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..."
|
|
|
+ rospy.loginfo("Sleeping for 1 second...")
|
|
|
time.sleep(1)
|
|
|
|
|
|
- print "Test Beep ring 3 times..."
|
|
|
+ rospy.loginfo("Test Beep ring 3 times...")
|
|
|
for i in range(3):
|
|
|
myArduino.beep_ring(1)
|
|
|
time.sleep(2.0)
|
|
|
|
|
|
- print "Did you heard the beep ring ?"
|
|
|
- print "Now print infrared sensors value:"
|
|
|
+ rospy.loginfo("Did you heard the beep ring ?")
|
|
|
+ rospy.loginfo("Now print infrared sensors value:")
|
|
|
values = myArduino.detect_distance()
|
|
|
distances = np.array([values[0], values[1], values[2]])
|
|
|
- print distances/100.0
|
|
|
+ rospy.loginf(distances/100.0)
|
|
|
|
|
|
myArduino.stop()
|
|
|
myArduino.close()
|
|
|
- print "Shutting down Arduino."
|
|
|
+ rospy.logwarn("Shutting down Arduino !")
|
|
|
|