天天看点

串口总线舵机之配置舵机一、配置舵机代码二、测试

在我们使用舵机的过程中,我们需要先对舵机进行配置,设置一下必要的参数,还要设置ID

文章目录

  • 一、配置舵机代码
  • 二、测试
    • 1.硬件连接
    • 2.测试

这部分在config_serial_servo文件里

一、配置舵机代码

# 配置串口舵机
#!/usr/bin/python3
# encoding: utf-8
# 配置串口舵机的参数
# 每次只能配置一个舵机,且树莓派扩展板只能连接一个舵机,既是一个舵机一个舵机配置参数
import sys
if sys.version_info.major == 2:
    print('Please run this program with python3!')  # 请运行在python3的环境下
    sys.exit(0)  # 结束程序
    
from SerialServoCmd import *  # 导入串口舵机指令库

# 串口舵机设置ID
# oldid 原来的ID  newid 要设置的新的ID
def serial_servo_set_id(oldid, newid): 
    serial_serro_wirte_cmd(oldid, LOBOT_SERVO_ID_WRITE, newid) # 写入舵机id

# 串口舵机读ID
# id 如果不传参,默认广播 此时只能有一个舵机连接,否则会乱码 
def serial_servo_read_id(id=None):
    while True:
        if id is None:  # 如果这个id是空的
        #0xfe 为舵机的广播地址,总线上智能接一个舵机,不然都会返回数据造成总线冲突
            serial_servo_read_cmd(0xfe, LOBOT_SERVO_ID_READ)
        else:
            serial_servo_read_cmd(id, LOBOT_SERVO_ID_READ)  # 读取舵机的ID
        # 获取内容
        msg = serial_servo_get_rmsg(LOBOT_SERVO_ID_READ)  # 如果信息不是空
        if msg is not None: # 返回信息
            return msg 

# 串口舵机停止
# id: 要停止的舵机
def serial_servo_stop(id=None):
    serial_serro_wirte_cmd(id, LOBOT_SERVO_MOVE_STOP) # 发送命令舵机停止运行

# 配置偏差 掉电保护
# id:舵机id  d :偏差
def serial_servo_set_deviation(id, d=0):
    # 设置偏差  掉电不保护
    serial_serro_wirte_cmd(id, LOBOT_SERVO_ANGLE_OFFSET_ADJUST, d)  # 角度偏差调整
    # 设置为掉电保护
    serial_serro_wirte_cmd(id, LOBOT_SERVO_ANGLE_OFFSET_WRITE)  # 角度偏差写

# 串口舵机读取偏差值 范围-125--125  对应角度-30度--30度
# id:要读取的舵机ID
def serial_servo_read_deviation(id):
    # 发送读取偏差指令
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_ANGLE_OFFSET_READ) # 读取偏差值
        # 获取数据
        msg = serial_servo_get_rmsg(LOBOT_SERVO_ANGLE_OFFSET_READ)  # 返回偏差值的信息
        if msg is not None: # 消息不为空
            return msg # 返回消息(偏差值)
# 设置串口舵机转动范围
# id: 要设置的舵机  low: 最小角度的范围0-1000 high:最大角度范围0-1000
def serial_servo_set_angle_limit(id, low, high):
    serial_serro_wirte_cmd(id, LOBOT_SERVO_ANGLE_LIMIT_WRITE, low, high)  # 写入角度的转动范围
#读取舵机转动范围
# id: 要读取的舵机
def serial_servo_read_angle_limit(id):
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_ANGLE_LIMIT_READ) # 读取角度范围指令
        msg = serial_servo_get_rmsg(LOBOT_SERVO_ANGLE_LIMIT_READ) # 读取数据
        if msg is not None: # 消息不为空
            return msg  # 返回舵机的转动范围
# 设置串口舵机的电压值范围 4500-12000mv  4.5V-12V
def serial_servo_set_vin_limit(id, low, high):
    serial_serro_wirte_cmd(id, LOBOT_SERVO_VIN_LIMIT_WRITE, low, high)
# 读取串口舵机的电压值范围
def serial_servo_read_vin_limit(id):
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_VIN_LIMIT_READ) # 读舵机电压值
        msg = serial_servo_get_rmsg(LOBOT_SERVO_VIN_LIMIT_READ)
        if msg is not None:  # 消息不为空
            return msg
# 设置舵机最高温度限制 范围50-100度 默认值85度
def serial_servo_set_max_temp(id, m_temp):
    serial_serro_wirte_cmd(id, LOBOT_SERVO_TEMP_MAX_LIMIT_WRITE, m_temp) # 舵机最高温度指令
# 读取舵机最高温度限制
def serial_servo_read_temp_limit(id):
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_TEMP_MAX_LIMIT_READ) # 读舵机最高温度指令
        msg = serial_servo_get_rmsg(LOBOT_SERVO_TEMP_MAX_LIMIT_READ) # 读数据
        if msg is not None:
            return msg
# 读取舵机当前的实际角度位置值  
def serial_servo_read_pos(id):
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_POS_READ) # 读当前位置指令
        msg = serial_servo_get_rmsg(LOBOT_SERVO_POS_READ)  # 读数据
        if msg is not None:  # 消息不为空
            return msg
#读取舵机内部实时温度
def serial_servo_read_temp(id):
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_TEMP_READ) # # 读舵机温度指令
        msg = serial_servo_get_rmsg(LOBOT_SERVO_TEMP_READ) #读数据
        if msg is not None:  #消息不为空
            return msg
# 读取舵机内部当前输入电压值
def serial_servo_read_vin(id):
    while True:
        serial_servo_read_cmd(id, LOBOT_SERVO_VIN_READ) # 读电压指令
        msg = serial_servo_get_rmsg(LOBOT_SERVO_VIN_READ) #读数据
        if msg is not None: #消息不为空
            return msg
# 把舵机复位到中位
def serial_servo_rest_pos(oldid):
    # 舵机清零偏差和P值中位(500)
    serial_servo_set_deviation(oldid, 0)    # 清零偏差
    time.sleep(0.1)
    serial_serro_wirte_cmd(oldid, LOBOT_SERVO_MOVE_TIME_WRITE, 500, 100) # 设置舵机角度为500,移动时间为100ms

# 显示舵机当前的状态
# id:要显示的舵机  默认广播, 
def show_servo_state(id = None):
    oldid = serial_servo_read_id(id) #读出舵机的id
    portRest() # 端口复位
    if oldid is not None: # 如果ID是不是空的
        print('当前的舵机ID是:%d' % oldid)
        pos = serial_servo_read_pos(oldid) # 读出舵机的位置
        print('当前的舵机角度:%d' % pos)
        portRest()

        now_temp = serial_servo_read_temp(oldid) # 现在舵机的温度
        print('当前的舵机温度:%d°' % now_temp)
        portRest()

        now_vin = serial_servo_read_vin(oldid) #读电压值
        print('当前的舵机电压:%dmv' % now_vin)
        portRest()

        d = serial_servo_read_deviation(oldid) #读偏差值
        print('当前的舵机偏差:%d' % ctypes.c_int8(d).value) 
        portRest()

        limit = serial_servo_read_angle_limit(oldid) #读转动角度范围
        print('当前的舵机可控角度为%d-%d' % (limit[0], limit[1]))
        portRest()

        vin = serial_servo_read_vin_limit(oldid) #读电压值范围
        print('当前的舵机报警电压为%dmv-%dmv' % (vin[0], vin[1]))
        portRest()

        temp = serial_servo_read_temp_limit(oldid) #读温度范围
        print('当前的舵机报警温度为50°-%d°' % temp)
        portRest()

    return oldid # 返回舵机的id

# 如果是单独执行这个程序的话
if __name__ == '__main__':
    portInit()  # 端口复位
    oldid = show_servo_state() # 打印舵机的信息
    while True:
        print ('*' * 50)  # 打印50个*字符
        print ('1、设置舵机ID号')
        print ('2、设置舵机偏差')
        print ('3、设置舵机转动角度范围')
        print ('4、设置舵机电压报警范围')
        print ('5、设置舵机温度报警范围')
        print ('6、显示舵机状态')
        print ('7、中位舵机')
        print ('8、退出')
        print ('*' * 50)
        num = int(input('请输入需要配置的数字')) # 输入一个int型数字
        num6_flag = 0
        while 1 <= num <= 7: # 这个数字在1-7范围内
            if num == 1:
                num6_flag = 0
                n_id = int(input('请输入新的舵机ID号(范围:0-253)')) # 输入新舵机ID
                if n_id > 253:
                    print ('超过范围,请重新输入')
                else:
                    serial_servo_set_id(oldid, n_id) # 设置新舵机id
                    portRest()
                    if serial_servo_read_id() == n_id: # 读取舵机的ID
                        # 设置不成功的话继续设置
                        oldid = n_id # 设置成功
                        print ('设置成功')
                        break
            elif num == 2:
                num6_flag = 0
                n_d = int(input('请输入舵机偏差值(范围:-125 ~ 125)'))  # 输入舵机的偏差值
                if n_d < -125 or n_d > 125: # 超出范围
                    print ('超过范围,请重新输入')
                else:
                    serial_servo_set_deviation(oldid, n_d) # 设置舵机的偏差值
                    time.sleep(0.1)
                    portRest()
                    zf_d = serial_servo_read_deviation(oldid) # 读舵机的偏差值
                    if zf_d > 127:  # 负数 最高位是1
                        zf_d = -(0xff - (zf_d - 1)) # 转换为正值
                    if zf_d == n_d:
                        print ('设置成功')
                        break # 跳出循环
            elif num == 3:
                num6_flag = 0
                print ('请输入舵机的转动范围(0 ~ 1000)')
                low_ang_limit = int(input('请输入低范围值'))
                high_ang_limit = int(input('请输入高范围值'))
                # 还需要判断low_ang_limit >high_ang_limit的情况
                if low_ang_limit < 0 or high_ang_limit < 0 or low_ang_limit >= 1000 or high_ang_limit > 1000:
                    print ('超过范围,请重新输入')
                else:
                    serial_servo_set_angle_limit(oldid, low_ang_limit, high_ang_limit) 
                    portRest()
                    lim = serial_servo_read_angle_limit(oldid) # 读取舵机的角度范围
                    if lim[0] == low_ang_limit and lim[1] == high_ang_limit:
                        print ('设置成功')
                        break # 跳出循环
            elif num == 4:
                num6_flag = 0
                print ('请输入舵机的电压报警范围(4500 ~ 12000)mv')
                low_vin_limit = int(input('请输入低范围值'))
                high_vin_limit = int(input('请输入高范围值'))
                # 还需要判断low_vin_limit > high_vin_limit的情况
                if low_vin_limit < 4500 or high_vin_limit < 4500 or low_vin_limit >= 12000 or high_vin_limit > 12000:
                    print ('超过范围,请重新输入')
                else:
                    serial_servo_set_vin_limit(oldid, low_vin_limit, high_vin_limit)
                    portRest()
                    vin = serial_servo_read_vin_limit(oldid) # 读电压值范围
                    if vin[0] == low_vin_limit and vin[1] == high_vin_limit:
                        print ('设置成功')
                        break
            elif num == 5:
                num6_flag = 0
                n_temp = int(input('请输入舵机的温度报警范围(范围:50-100)度'))
                if n_temp > 100 or n_temp < 50:
                    print ('超过范围,请重新输入')
                else:
                    serial_servo_set_max_temp(oldid, n_temp) # 设置舵机的温度报警上限
                    portRest()
                    if serial_servo_read_temp_limit(oldid) == n_temp:
                        # 不成功继续
                        print ('设置成功')
                        break
            elif num == 6: # 显示舵机状态
                if num6_flag == 0:
                    oldid = show_servo_state() # 显示舵机的状态
                    num6_flag = 1
                break # 跳出循环    
            elif num == 7: # 中位舵机
                num6_flag = 0
                serial_servo_rest_pos(oldid) # 设置舵机到中位
                print ('中位成功')
                break # 跳出循环
        # 没有进入循环
        if num == 8:
            break # 跳出大循环 退出程序
        elif num < 1 or num > 8: # 不在菜单范围内
            print ('输入有误,请重新输入')




           

二、测试

1.硬件连接

我连接的是6号舵机

串口总线舵机之配置舵机一、配置舵机代码二、测试

2.测试

串口总线舵机之配置舵机一、配置舵机代码二、测试

输入对应的编号就可以配置对应的信息