精华内容
下载资源
问答
  • 串行舵机协议手册.pdf

    2021-01-22 14:04:44
    串行舵机协议可以参考手册内容。
  • 数字舵机顾名思义就是用数字的信号去驱动,多数的为UART总线,通讯模式为一主多从,总线上可以挂载多个设备,每个设备都有固定的IP地址,只有收到匹配对应的地址的设备,后面的数据才有效。一共用了TX,VCC,GND三根线...

           数字舵机顾名思义就是用数字的信号去驱动,多数的为UART总线,通讯模式为一主多从,总线上可以挂载多个设备,每个设备都有固定的IP地址,只有收到匹配对应的地址的设备,后面的数据才有效。一共用了TX,VCC,GND三根线。也就是只有输出信息,因为没有RX,所以不接受被控制端的反馈,这是它的唯一缺点。不过总线上都是快速的数据流,丢了一帧,下一帧又来了。所以不需要反馈也在情理之中。

          现在的舵机传输的是数字信号,多以扭力和角度来分类,小力矩的多为1kg-5kg。大力矩的为10kg-50kg。角度一般分为90度,180度,270度,360度。一般的数据舵机多用在高精度的机器人上面,已双轴的居多。因为其接线简单,可把所有的舵机级联起来。由主机统一控制,所以很受欢迎。

          数字舵机精度比普通的舵机会高一些。但是价格却贵很多,几十到上千都有。所以很难落入平常百姓家。那有没有一种可替代的方案呢,答案是有的。今天就为大伙分享最具性价比的可媲美数字舵机的替代方案。ZR001DU2P+普通PWM舵机。

          ZR001DU2P是一个UART接口输出2路PWM信号的专用SOC芯片,并且支持级联功能,可以级联最多255个从机。下面是芯片技术参数。

    接口标准

    - 通用的UART异步通讯协议,可选波特率38400,115200,1位开始,1位停止,无校验,TTL3.3-5V。

    - 双路PWM输出。

    - 总线可以级联多个设备(最多255)进行一主多从的控制模式。

    PWM输出特性

    - PWM固定输出范围100Hz。适合20ms周期的通用舵机。

    - 双路PWM输出,共用一个频率,独立的脉宽可调。

    - 脉宽周期为0-20ms,级数为4096。所以1ms的可调级数是204。

    - 可修改默认输出脉宽(需购买ZLINK烧录器)。

    高精度内部振荡器

    - 出厂时精度校准为 ±1%。

    - 内部带晶振故障检测电路。

    超宽的工作电压

    - 宽工作电压范围。(3V-5.5V)。

    - 上电自复位无需外部电路。

    - 上电电压检测电路,低电压自锁电路。

    超低的功耗

    - 3V 25 条件下的功耗 

    - 工作模式 2.2mA 。

    - 空闲模式 0.5mA 。

    - 掉电模式 <1 uA 。

    I/O和封装

    - 超小的封装SOP8窄体150mil,特别适合便携式低功耗的应用。

    电气特性

    - 工作温度 -45°C 到+85°C。

    - 存储温度 -65°C到 +125°C。

    - 各个引脚对地的电压VCC+0.5V。

    - 最大工作电压5.5V。

    - 每个I/O引脚的DC 电流20.0 mA。

    - VCC 与GND 引脚的DC 电流200.0 mA。

    应用领域

      - 无人机

      - LED调光

      - 电机调速

      - 玩具

      - 机器人

      - 工业动力设备

     

    单芯片直接能输出2路的PWM信号,可直接推动2个普通的舵机。

    ZR001DU2P的成本大伙到某宝去查查,大概批量价在2.5元左右,所以非常具有性价比了。而且精度还不错。可以做到0.3度左右。绝大多数的应用都能满足了。

     

    展开全文
  • 摘要UART串行总线舵机需要配合UART串行总线舵机转接板使用,它的作用是将舵机的单线转换为双线TTL接口(Rx接收端,Tx发送端),通过双线TTL串口接口与单片机进行通信。或者通过转接板上的USB转TTL芯片(CH340),通过USB...

    摘要  UART串行总线舵机需要配合UART串行总线舵机转接板使用,它的作用是将舵机的单线转换为双线TTL接口(Rx接收端,Tx发送端),通过双线TTL串口接口与单片机进行通信。或者通过转接板上的USB转TTL芯片(CH340),通过USB端口与PC进行通信。

    4a112128cda41711d8fa49e14c41989b.png

    转接板规格

    859b5da237ff199abf46bd106bb2adf5.png

    e88d7e694fc58f5c77400fc6e02c265e.png

    UART串行总线舵机转接板(以下简称转接板)上有两个PH2.0的插槽,任选其中一个,通过UART串行总线舵机(以下简称舵机)连接线将舵机与转接板相连接,插槽有防反插设计,所以不用担心接反。

    2a522640c4f5d10bf48d84f95129da11.png

    另外外接电源在给转接板供电的同时也给舵机进行供电,外接电源的电压范围取决于舵机的电压范围 

    2e3834dbdc5c447d15fc81c2a138ad0c.png

    转接板功能描述

    功能1: USB转单线TTL 舵机两侧各有一个接口,通过连接线把多个舵机就可以串联在一条串行总线上过USB线将串口转接板与电脑连接。如果电脑是Windows系统,可以通过舵机调试软件测试舵机相关的功能。果是其他操作系统,可以通过SDK测试舵机相关功能。示意图 71e84d30d210770da70e23ba93384d10.png实物图 以树莓派与2DOF舵机云台之间的连接为例cd43ae8c58a4254af18256c839af92a9.png功能2: TTL双线转单线如果是使用单片机(Arduino/STM32/C51/TI等)与舵机进行通信,需要将舵机转接板的TTL串口接口与单片机相连。示意图 以Arduino为例演示接线方法c91ef5f77ba9c55e78867bf28daaf683.pnga89cf05ff4d1010e8c1b2ad0ffe14a05.png备注1. 舵机转接板的工作电压是5V,请不要将5v电压接到单片机的3.3V管脚上,防止单片机芯片烧毁。若单片机独立供电,则舵机转接板的5v管脚可以悬空。2. RX代表接收端, TX代表发送端。功能3: USB转TTL串口转接板也可以当成普通的USB转TTL串口模块来使用。180dd1e3b8063d682ae4d446821a5a24.png常见问题转接板使用的USB转TTL串口芯片是CH340,需要在Windows上安装CH340的驱动。CH340驱动,请复制以下地址下载:http://www.wch.cn/download/CH341SER_EXE.html

    驱动安装完成之后,检查驱动是否安装成功。

    检查CH340驱动是否安装成功,可复制以下链接查看:

    https://jingyan.baidu.com/article/00a07f3872a90982d028dcb9.html

    97685df45edf087a3c3ac68f30c75ccf.png

     相关阅读 

    UART串行总线舵机 VS 传统PWM舵机UART串行总线舵机的结构与参数深圳高交会圆满落幕 格斗机器人获“优秀产品奖”格斗机器人亮相国际创客峰会,斩获至高荣誉奖蓝丝带MFSZ 2019制汇节邀请函 |铁甲钢拳--圆你机器人格斗梦

    28bee600cf850b82050248ce877e5a45.png

    您的“在看”是我们不断前行的动力

    展开全文
  • Dynamixel 串行库 Arduino 库,用于通过串行通信 v1.0 与 Dynamixel MX 系列伺服系统接口。 用法 有关示例代码,请参阅示例文件夹。 变更日志 2015 年 3 月 25 日 - 库迁移到 GitHub。 2013 年 4 月 25 日 - ...
  • 幻尔lx15D 舵机三维图

    2020-06-16 15:29:26
    串行总线舵机/机器人舵机/带反馈/高寿命高精度 LX-15D LX-15D舵机智能串行总线舵机LX-15D/机器人舵机/带反馈/高寿命高精度/幻尔
  • 在我们使用舵机的过程中,我们需要先对舵机进行配置,设置一下必要的参数,还要设置ID 文章目录一、配置舵机代码二、测试1.硬件连接2.测试 这部分在config_serial_servo文件里 一、配置舵机代码 # 配置串口舵机 #!/...

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


    这部分在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.测试

    在这里插入图片描述
    输入对应的编号就可以配置对应的信息

    展开全文
  • 串口总线舵机舵机命令

    千次阅读 2021-02-26 18:59:35
    文章目录一、舵机指令包格式二、串口舵机连接1.硬件连接2.74HC126D三、关于ctypes四、串口舵机命令代码 从今天开始学习 幻尔科技总线舵机通信协议 一、舵机指令包格式 帧头: 连续收到两个 0x55 ,表示有数据包到达...

    前言:
    关于一些前期配置,测试情况请观看下面这个博客
    驱动串口总线舵机


    从今天开始学习
    幻尔科技总线舵机通信协议
    关于这部分在SerialServoCmd文件里

    一、舵机指令包格式

    在这里插入图片描述

    帧头: 连续收到两个 0x55 ,表示有数据包到达。
    ID: 每个舵机都有一个 ID 号。ID 号范围 0~253,转换为十六进制 0x00~0xFD。广播 ID: ID 号 254(0xFE) 为广播 ID,若控制器发出的 ID 号为 254(0xFE),所有的舵机均接收指令,但都不返回应答信息,(读取舵机 ID 号除外,具体说明参见下面指令介绍)以防总线冲突。
    数据长度: 等于待发送的数据(包含本身一个字节)长度,即数据长度 Length加 3 等于这一包指令的长度,从帧头到校验和。
    指令: 控制舵机的各种指令,如位置、速度控制等。
    参数: 除指令外需要补充的控制信息。
    校验和: 校验和 Checksum,计算方法如下:
    Checksum = ~ (ID + Length + Cmd+ Prm1 + … Prm N)若括号内的计算和超出 255,则取最低的一个字节,“~”表示取反。

    说明:
    数据长度为 数据长度+指令+ 参数+校验和 参数个数 = 数据长度-3

    二、串口舵机连接

    1.硬件连接

    在这里插入图片描述

    2.74HC126D

    74HC126D介绍:
    功能描述:
    在这里插入图片描述
    可以看出,当OE输出高电平时 输入是高电平那么输出就是高电平,输入是低电平输出就是低电平。

    OE为低电平时不管输入状态是什么,输出都是高阻抗关断状态(抽象理解为悬空)

    高阻输出一般是指数字电路输出时不为高电平或低电平,而是相当于断开的一种状态,输出点的电位由后面的电路决定。

    这个芯片的作用就是,当需要写入的时候,拉低TX_CON,这样,串口TX发送什么,输出就是什么。拉高RX_CON,这样,串口接收RX就相当于悬空,什么也不干。接收数据也是如此.

    三、关于ctypes

    关于ctypes的介绍
    ctypes

    四、串口舵机命令代码

    # 串口舵机的命令
    #!/usr/bin/python3
    # encoding: utf-8
    import serial # 导入串口库
    import pigpio # 导入pigpio库  由c语言编写的库函数 并提供python接口
    import time # 导入时间库
    import ctypes # ctypes是Python的一个外部库,提供和C语言兼容的数据类型,可以很方便地调用C DLL中的函数。
    
    LOBOT_SERVO_FRAME_HEADER         = 0x55  # 机架头
    LOBOT_SERVO_MOVE_TIME_WRITE      = 1     # 移动时间写入
    LOBOT_SERVO_MOVE_TIME_READ       = 2     # 移动时间读
    LOBOT_SERVO_MOVE_TIME_WAIT_WRITE = 7     # 移动时间等待写
    LOBOT_SERVO_MOVE_TIME_WAIT_READ  = 8     # 移动时间等待读
    LOBOT_SERVO_MOVE_START           = 11    # 移动开始
    LOBOT_SERVO_MOVE_STOP            = 12    # 移动停止
    LOBOT_SERVO_ID_WRITE             = 13    # 舵机ID写
    LOBOT_SERVO_ID_READ              = 14    # 舵机ID读
    LOBOT_SERVO_ANGLE_OFFSET_ADJUST  = 17    # 角度偏移调整
    LOBOT_SERVO_ANGLE_OFFSET_WRITE   = 18    # 角度偏移写
    LOBOT_SERVO_ANGLE_OFFSET_READ    = 19    # 角度偏移读
    LOBOT_SERVO_ANGLE_LIMIT_WRITE    = 20    # 角度限制写
    LOBOT_SERVO_ANGLE_LIMIT_READ     = 21    # 角度限制读
    LOBOT_SERVO_VIN_LIMIT_WRITE      = 22    # VIN限制写
    LOBOT_SERVO_VIN_LIMIT_READ       = 23    # VIN限制读
    LOBOT_SERVO_TEMP_MAX_LIMIT_WRITE = 24    # TEMP最大限度写
    LOBOT_SERVO_TEMP_MAX_LIMIT_READ  = 25    # TEMP最大限度读
    LOBOT_SERVO_TEMP_READ            = 26    # TEMP读
    LOBOT_SERVO_VIN_READ             = 27    # VIN读
    LOBOT_SERVO_POS_READ             = 28    # POS读
    LOBOT_SERVO_OR_MOTOR_MODE_WRITE  = 29    # 模式写
    LOBOT_SERVO_OR_MOTOR_MODE_READ   = 30    # 模式读
    LOBOT_SERVO_LOAD_OR_UNLOAD_WRITE = 31    # 加载或卸载写
    LOBOT_SERVO_LOAD_OR_UNLOAD_READ  = 32    # 加载或卸载读
    LOBOT_SERVO_LED_CTRL_WRITE       = 33    # LED控制写
    LOBOT_SERVO_LED_CTRL_READ        = 34    # LED控制读
    LOBOT_SERVO_LED_ERROR_WRITE      = 35    # LED错误写
    LOBOT_SERVO_LED_ERROR_READ       = 36    # LED错误读
    
    pi = pigpio.pi()  # 初始化pigpio库,创建一个实例
    # ser=serial.Serial("/dev/ttyUSB0",9600,timeout=0.5) #使用USB连接串行口
    # ser=serial.Serial("/dev/ttyAMA0",9600,timeout=0.5) #使用树莓派的GPIO口连接串行口
    serialHandle = serial.Serial("/dev/ttyAMA0", 115200)  # 初始化串口, 波特率为115200
    
    
    # 使用pigpio配置驱动串口的引脚模式为输出
    def portInit():  # 配置用到的IO口
     # 说明  pigpio使用的是BCM编码  
        # RX_CON和TX_CON是使能信号  来决定TX还是RX输出servo signal
        pi.set_mode(17, pigpio.OUTPUT)  # 配置RX_CON 即 GPIO17 为输出
        pi.write(17, 0)# GPIO 17 低电平
        pi.set_mode(27, pigpio.OUTPUT)  # 配置TX_CON 即 GPIO27 为输出
        pi.write(27, 1) # GPIO 27 高电平
    
    
    portInit() # 执行端口初始化
    
    # 配置为串口写模式
    def portWrite():  # 配置单线串口为输出
        pi.write(27, 1)  # 拉高TX_CON 即 GPIO27  串口发送的是什么输出就是什么
        pi.write(17, 0)  # 拉低RX_CON 即 GPIO17  相当于悬空接受引脚,什么都不干
    
    # 配置为串口读模式
    def portRead():  # 配置单线串口为输入
        pi.write(17, 1)  # 拉高RX_CON 即 GPIO17
        pi.write(27, 0)  # 拉低TX_CON 即 GPIO27 悬空
    
    # 复位,重新打开串口
    def portRest(): # 端口复位
        time.sleep(0.1)   # 延迟100us
        serialHandle.close()# 关闭串口
        pi.write(17, 1)
        pi.write(27, 1)
        serialHandle.open() # 打开串口
        time.sleep(0.1)
    
    # 校验和 = ~(ID + Length+ Cmd + pr1+ .. + prn) 若超出255,则取最低的一个字节
    def checksum(buf):
        # 计算校验和
        sum = 0x00
        for b in buf:  # 求和
            sum += b # 累加
        sum = sum - 0x55 - 0x55  # 去掉命令开头的两个 0x55
        sum = ~sum  # 取反
        return sum & 0xff  # 取最低的一个字节
    
    # 串口舵机写命令
    # 指令包格式:0x55,0x55 ID号 数据长度,指令,参数1...参数n,校验和
    # 数据长度等于待发送的数据(包含本身1个字节)
    def serial_serro_wirte_cmd(id=None, w_cmd=None, dat1=None, dat2=None):
        portWrite()  # 端口写
            # bytearray() 方法返回一个新字节数组。这个数组里的元素是可变的,并且每个元素的值范围: 0 <= x < 256
        '''
        如果 source 为整数,则返回一个长度为 source 的初始化数组;
        如果 source 为字符串,则按照指定的 encoding 将字符串转换为字节序列;
        如果 source 为可迭代类型,则元素必须为[0 ,255] 中的整数;
        如果 source 为与 buffer 接口一致的对象,则此对象也可以被用于初始化 bytearray。
        如果没有输入任何参数,默认就是初始化数组为0个元素。
        '''
        # b'\x55\x55')    [0x55,0x55]
        buf = bytearray(b'\x55\x55')  # 帧头   buf = [0x55,0x55]
        buf.append(id) # buf = [0x55,0x55,id]
        # 指令长度
        if dat1 is None and dat2 is None:# dat1和dat2都为空
            buf.append(3) # buf = [0x55,0x55,id,3]  3个表示指令长度 指令 检验和
        elif dat1 is not None and dat2 is None: # dat1不为空dat2为空
            buf.append(4) # buf = [0x55,0x55,id,4] 4个表示指令长度,指令 dat1(低8位),校验和
        elif dat1 is not None and dat2 is not None: #dat1 和dat2都不为空
            buf.append(7)  # buf = [0x55,0x55,id,7] 7个表示指令长度,指令,dat1(高8位,低8位) dat2(高8位,低8位),校验和
    
        buf.append(w_cmd) # 把指令也添加到列表  # buf = [0x55,0x55,id,x,w_cmd]
        # 写数据
        if dat1 is None and dat2 is None: # dat1和dat2都为空
            pass # buf = [0x55,0x55,id,x,w_cmd]
        elif dat1 is not None and dat2 is None: # dat1不为空dat2为空
         # (dat1 & 0xff) 取最低位
            buf.append(dat1 & 0xff)  # buf = [0x55,0x55,id,x,w_cmd,dat1]
        elif dat1 is not None and dat2 is not None: # dat1 和 dat2 都不为空
            buf.extend([(0xff & dat1), (0xff & (dat1 >> 8))])  # 分低8位 高8位 放入缓存
            buf.extend([(0xff & dat2), (0xff & (dat2 >> 8))])  # 分低8位 高8位 放入缓存
        # 可能是buf = [0x55,0x55,id,x,w_cmd,dat1,dat2]
              
        # 校验和
        buf.append(checksum(buf)) # 到这数据有三种情况
        serialHandle.write(buf)  # 发送给串口
        
    # 串口舵机读命令 先发送读命令 再接收,不单独使用
    def serial_servo_read_cmd(id=None, r_cmd=None):
        portWrite() # 端口写
        buf = bytearray(b'\x55\x55')  # 帧头
        buf.append(id)# 添加舵机ID到列表
        buf.append(3)  # 指令长度
        buf.append(r_cmd)  # 指令
        buf.append(checksum(buf))  # 校验和
        serialHandle.write(buf)  # 发送
        time.sleep(0.00034) # 延迟 3.4us
    
    # 获取指定读取命令的数据
    def serial_servo_get_rmsg(cmd):
        serialHandle.flushInput()  # 清空接收缓存
        portRead()  # 将单线串口配置为输入
        time.sleep(0.005)  # 稍作延时,等待接收完毕
        count = serialHandle.inWaiting()    # 获取接收缓存中的字节数
        if count != 0:  # 如果接收到的数据不空
            recv_data = serialHandle.read(count) # 读取count字节个数据
            try:
            # recv_data[2] : id   recv_data[3]: 数据长度 
                if recv_data[0] == 0x55 and recv_data[1] == 0x55 and recv_data[4] == cmd: # 帧头正确  命令符合 匹配
                    dat_len = recv_data[3]  # 数据长度
                    serialHandle.flushInput()  # 清空接收缓存
                    # 数据长度为 数据长度+指令+ 参数+校验和  参数个数 = 数据长度-3
                    if dat_len == 4: # dat1为一个8位的参数dat2为空
                        # print ctypes.c_int8(ord(recv_data[5])).value    # 转换成有符号整型
                        return recv_data[5] # 返回这个8位的参数
                    elif dat_len == 5:  # dat1为一个16位的参数dat2为空
                        pos = 0xffff & (recv_data[5] | (0xff00 & (recv_data[6] << 8))) # 一个16位的数据
                        return ctypes.c_int16(pos).value
                    elif dat_len == 7: # dat1位16位的参数,dat2为16位的参数
                        pos1 = 0xffff & (recv_data[5] | (0xff00 & (recv_data[6] << 8)))
                        pos2 = 0xffff & (recv_data[7] | (0xff00 & (recv_data[8] << 8)))
                        return ctypes.c_int16(pos1).value, ctypes.c_int16(pos2).value
                else:  # 数据不正确,不符合接收数据的格式
                    return None
            except BaseException as e:
                print(e) # 打印异常
        else:  # 接收数据为空
            serialHandle.flushInput()  # 清空接收缓存
            return None
    
    
    展开全文
  • 我们总是需要让舵机去转动一定的角度,执行对应的动作。 文章目录前提:1.动作文件2.支持文件一、舵机运行代码二、测试 这一部分在Serial_Servo_Running文件里 前提: 因为这一部分需要运行动作组,所以需要动作文件...
  • 舵机串口控制

    2018-06-22 09:35:30
    舵机在很多机器人中比较重要,本程序只是对舵机进行串口的控制的调试
  • 舵机驱动程序

    千次阅读 2019-10-25 19:48:03
    舵机驱动程序 SG90 接线图 工作原理 转动方向与占空比有关 占空比大往右转 占空比小往左转 占空比0.5停止 程序 链接:https://pan.baidu.com/s/1F7BgWfz7RpCck3c_–Sirg 提取码:6d3a void TIM14_PWM_Init(u32 ...
  • 第9章 舵机控制

    千次阅读 2020-11-20 23:31:01
    有一种电机可以在程序的控制下,在一定范围内...模拟舵机和数字舵机的机械结构可以说是完全相同的,模拟舵机的控制电路为纯模拟电路,需要一直发送目标信号,才能转到指定的位置,响应速度较慢,无反应区较大;数字舵
  • 数字舵机Digital Servo和模拟舵机Analog Servo在基本机械结构方面是完全一样的,主要由马达、减速齿轮、控制电路等组成,而数字舵机和模拟舵机的最大区别则体现在控制电路上: 数字舵机的控制电路比模拟舵机多了...
  • STM32串口控制舵机

    千次阅读 多人点赞 2019-06-29 22:53:21
    舵机工作电压是多少? 一般供电范围是4.8V-6.0V电压,我这种舵机3V、5V不影响使用,个人觉得不要太大就行了。 舵机的三根线代表什么意思? 红色的是电源正极,黑色的是电源负极,白色的是信号线。有些舵机线是...
  • 用 Arduino 控制舵机

    千次阅读 2019-06-06 17:58:05
    舵机是一种位置伺服的驱动器,主要是由外壳、电路板、无核心马达、齿轮与位置检测器所构成。其工作原理是由接收机或者单片机发出信号给舵机,其内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号,将获得...
  • 什么叫舵机

    千次阅读 2017-08-22 13:51:52
    一:什么叫舵机 舵机是一种位置(角度)伺服的驱动器,它使信号转化为转矩和转速以驱动控制对象不断变化角度和方向并保持控制。舵机应用广泛,主要适用于航模(空模,车模,海模),机器人,玩具,工业等。选型时...
  • 单个舵机串口控制

    千次阅读 2017-04-30 17:19:48
    Arduino利用串口控制舵机其中有些教训 舵机的接线 接错了,烧坏了舵机 千万不能把信号线和地线接错了。 正确的接线如下 具体代码如下:int i,val; char a[3]; boolean output_flag; #include Servo servo1; void ...
  • 我们如何通过外部去控制树莓派串口总线舵机和PWM舵机。 网络无疑是一个很好的选择。 这一部分是在lsc.py文件中 关于socketserver部分参考 socketserver 文章目录调试工具1.网络调试助手2.树莓派一、控制命令1.设置...
  • Arduino对舵机的控制

    千次阅读 2017-05-05 17:54:59
    Arduino对舵机的控制 舵机是一种位置伺服的驱动器,主要是由外壳、电路板、无核心马达、齿轮与位置检测器所构成。其工作原理是由接收机或者单片机发出信号给舵机,其内部有一个基准电路,产生周期为20ms,宽度...
  • Arduino 控制舵机

    2016-03-30 10:47:00
    舵机是一种位置伺服的驱动器,主要是由外壳、电路板、无核心马达、齿轮与位置检测器所构成。其工作原理是由接收机或者单片机发出信号给舵机,其内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号,将获得...
  • 舵机抖动的解决方法

    万次阅读 多人点赞 2019-09-30 14:36:27
    首先,需要知道舵机的使用方法,简单来说,就是给一定时间的高电平,舵机能转动在一定的角度。其实,你只需给舵机一次能转动在一定角度的高低电平,之后只需保持上电状态,理论上舵机能保持不动。但这样极易出现波动...
  • 挂个链接:15kg串行总线智能舵机数字 机器人机械手臂(没收钱哈,纯自己觉得挺好的,推荐一下) 舵机优势 有位置反馈,这对做机器人、机械臂十分有帮助,可以进行运动学解算。 驱动板 总线协议 驱动库 ''' @...
  • ros总线舵机机械臂串口协议源码

    千次阅读 2017-11-20 16:56:21
    总线舵机机械臂moveit规划效果 现场 前文有普通模拟舵机diy的舵机手臂. 型号996r普通舵机用在手臂上可以说没有什么精度可言扭力也不行,ros试验无法使用. 所以diy手臂时选择舵机还是非常关键的...
  • STM32单线串口对总线舵机的控制

    万次阅读 多人点赞 2017-03-07 16:19:30
    总线伺服舵机串行总线智能舵机,实际上可以理解为数字舵机的衍生品,数字舵机与模拟舵机相比而言是控制系统设计上的颠覆,而总线伺服舵机对于舵机而言则是在功能和运用上的颠覆。舵机的运用方式实际上只能发挥出...
  • CDS5500-舵机使用说明

    2009-12-24 15:15:42
    关于串行通信的舵使用手册关于串行通信的舵使用手册关于串行通信的舵使用手册
  • 舵机+16路舵机驱动板+Arduino UNO机械臂测试代码解析 程序源码: // the setup function runs once when you press reset or power the board #include <Adafruit_PWMServoDriver.h> Adafruit_...
  • 难度: ★★读者: 适合有C语言或Python编程基础,对舵机和PWM等有一定了解的读者。往期相关文章:《 树莓派4B-WiringPi库的安装和使用 》《 入门WiringPi库的PWM接口 》没有安装WiringPi的读者,可先阅读往期文章,...
  • 通过控制PWM实现对6路舵机的控制
  • 32路舵机控制上位机软件,实现PC端直接控制舵机转动,动作存储,无需编程!
  • 不要再对各种电机、舵机傻傻分不清楚了

    千次阅读 多人点赞 2020-08-03 17:54:36
    你是否和木木一样,想要自己diy一个机器人,却对电机、舵机、步进电机、伺服电机、数字舵机、模拟舵机串行总线舵机……一大堆名词傻傻分不清楚?管你到底是啥,在我这都叫“马达”,哈哈哈哈哈!如果你也是这样...
  • 乐幻索尔总线舵机通信协议

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 388
精华内容 155
关键字:

串行舵机