我们总是需要让舵机去转动一定的角度,执行对应的动作。
这一部分在Serial_Servo_Running文件里
前提:
因为这一部分需要运行动作组,所以需要动作文件和支持文件
1.动作文件
2.支持文件
需要将下面的文件拷贝到当前目录
一、舵机运行代码
# 串口舵机运行 动作组调用
#!/usr/bin/env python3
# encoding: utf-8
import time # 时间模块
import os # 系统OS
import sqlite3 as sql # 数据库
import SerialServoCmd as ssc # 串口舵机命令
import config_serial_servo # 配置串口舵机
import threading # 线程
from hwax import HWAX # 未知 驱动动作组的 不可缺少,文件夹有一个HWAX.so文件
runningAction = False # 运行动作组不成立
stopRunning = False # 停止运行不成立
online_action_num = None # 动作组编号为空
online_action_times = -1 # 执行时间为空载
update_ok = False # 更新动作组不成立
action_group_finish = True # 动作组完成成立
# 设置串口舵机的位置和时间
# 时间参数意义:舵机在参数时间内从当前角度匀速转动到参数角度
# s_id:要设置的舵机 pos:0-1000 对应角度 0-240度 s_time:时间0-30000ms 0-30s
def serial_setServo(s_id, pos, s_time):
if pos > 1000: # 最大位置是1000 对应角度0-240
pos = 1000
elif pos < 0:
pos = 0
else:
pass
if s_time > 30000: # 最大时间是30000ms = 30s
s_time = 30000
elif s_time < 10: # 最小时间是10ms
s_time = 10
ssc.serial_serro_wirte_cmd(s_id, ssc.LOBOT_SERVO_MOVE_TIME_WRITE, pos, s_time)
# 设置舵机偏差值
# servoId:要设置的舵机 d:偏差值
def setDeviation(servoId, d):
global runningAction # 全局变量
if servoId < 1 or servoId > 16: # 舵机号的范围 1-16个舵机
return
if d < -200 or d > 200: # 偏差值的范围
return
if runningAction is False: # 如果当前不在运行状态就设置偏差值
config_serial_servo.serial_servo_set_deviation(servoId, d)
# 停止全部舵机
def stop_servo():
for i in range(16):
config_serial_servo.serial_servo_stop(i+1) # 依次让每一个舵机都停止
# 停止动作组
def stop_action_group():
global stopRunning, online_action_num, online_action_times, update_ok
update_ok = False # 更新ok不成立
stopRunning = True # 停止运行成立
online_action_num = None # 动作组的编号为空
online_action_times = -1 # 动作组的次数为空载状态
time.sleep(0.1) # 延时100ms
# 获取动作完成标志
def action_finish():
global action_group_finish
return action_group_finish #获取动作组完成标志
# 运行动作组,无法发送停止信号
# actNum:动作组的名字,字符串类型
def runAction(actNum):
global runningAction # 运行动作组
global stopRunning # 停止运行
global online_action_times # 运行动作组次数
if actNum is None: # 动作名字为空
return
# 判断动作组的类型
hwaxNum = "/home/pi/Desktop/Serial_SteerEngine/ActionGroups/" + actNum + ".hwax" # 获取动作组的路径
actNum = "/home/pi/Desktop/Serial_SteerEngine/ActionGroups/" + actNum + ".d6a"
if os.path.exists(hwaxNum) is True: # hwax路径存在
if runningAction is False: # 如果当前舵机不在运行状态
runningAction = True # 设置舵机正在运行
ssc.portWrite() # 端口复位
hwax = HWAX(hwaxNum, ssc.serialHandle)
hwax.reset()
while True:
if stopRunning is True: # 如果是停止运行
stopRunning = False
print('stop') # 输入提示信息
break
ret = hwax.next()
if ret is None:
hwax.reset()
break
hwax.close() # 关闭这个文件
runningAction = False
elif os.path.exists(actNum) is True: # d6a路径存在
if runningAction is False:
runningAction = True
ag = sql.connect(actNum) # 连接数据库
# 游标就像您打开文件所得到的文件句柄一样,只要文件打开成功,
#该文件句柄就可代表该文件
cu = ag.cursor() # 获取数据库可操作对象
'''
使用Cursor对象执行insert,update,delete语句时,执行结果由rowcount返回影响的行数,就可以拿到执行结果
使用Cursor对象执行select语句时,通过featchall()返回select的全部数据结果集。结果集是一个list,
每个元素都是一个tuple,对应一行记录,按建表的字段顺序排列。
fetchone()返回一条结果,是一个tuple,每个元素是一个字段值。
'''
cu.execute("select * from ActionGroup") # 从ActionGroup查找全部数据
while True:
act = cu.fetchone() # 获取一条查询的结果
if stopRunning is True: # 如果是停止运行
stopRunning = False
print('stop') # 输入提示信息
break
if act is not None: # 查询到数据
# 设置每一个舵机的act[2 + i]位置act[1]运行时间
for i in range(0, len(act)-2, 1): # len(act)-2 : 第一个是 第二个是运行时间
serial_setServo(i+1, act[2 + i], act[1]) # ID 位置 时间
time.sleep(float(act[1])/1000.0) # 转换为秒
else: # 没有查找到数据
break
runningAction = False # 运行状态停止
cu.close() # 关闭游标
ag.close() # 关闭数据库连接
else: # 路径不存在
runningAction = False
print("未能找到动作组文件")
# 线程运行动作
def online_thread_run_acting():
global online_action_times, online_action_num, update_ok, action_group_finish
while True: # 在线程里 死循环
if update_ok: # 更新ok 就是说动作组有变化
if online_action_times == 0: # 如果在线动作次数等于0,执行无限次
# 无限次运行
if action_group_finish: # 动作还在执行中,不允许动作发生改变
action_group_finish = False
runAction(online_action_num) # 运行 online_action_num 动作
elif online_action_times > 0: # 如果在线动作次数大于0,执行online_action_times次
# 有次数运行
if action_group_finish: # 动作还在执行中,不允许动作发生改变
action_group_finish = False
runAction(online_action_num) # 运行 online_action_num 动作
online_action_times -= 1 # 运行次数减一次
if online_action_times == 0:
online_action_times = -1 # 运行完成后,进入空载
else:
# 空载
if not action_group_finish: # 如果动作组没有完成
action_group_finish = True # 动作组完成
time.sleep(0.001) # 延时1ms
else: # 更新不ok 没有动作发生变化
# 查看上一次动作是否完成
if not action_group_finish: # 如果动作组没有完成
action_group_finish = True # 动作组完成
time.sleep(0.001) # 延时1ms
# 开始动作线程
def start_action_thread():
th1 = threading.Thread(target=online_thread_run_acting) # 运行动作组
th1.setDaemon(True) # 设置为后台线程,这里默认是True
th1.start()
# 改变动作组的值
# actNum:动作名 actTimes:运行次数
def change_action_value(actNum, actTimes):
global online_action_times, online_action_num, update_ok, stopRunning, action_group_finish
# 动作组都完成了之后才能允许动作发生改变
if action_group_finish: # 如果动作组完成了
online_action_times = actTimes # 动作执行的次数
online_action_num = actNum # 执行动作组的编号
stopRunning = False # 停止运行不成立
update_ok = True # 更新ok成立
# 单独执行的时候运行
if __name__ == '__main__':
# 开启动作组线程,update_ok =True 就运行动作
start_action_thread() # 开启一个动作组的线程
# 动作一改变 update_ok =True 就会运行动作
change_action_value('1', 0) # 改变动作 运行动作1,执行无限次
time.sleep(2) # 延时2s
stop_action_group() # 停止动作组
二、测试
舵机会执行动作,2s后停止。