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

文章目录

  • 一、舵机指令包格式
  • 二、串口舵机连接
    • 1.硬件连接
    • 2.74HC126D
  • 三、关于ctypes
  • 四、串口舵机命令代码

从今天开始学习
幻尔科技总线舵机通信协议
关于这部分在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 signalpi.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 即 GPIO17pi.write(27, 0)  # 拉低TX_CON 即 GPIO27 悬空# 复位,重新打开串口
def portRest(): # 端口复位time.sleep(0.1)   # 延迟100usserialHandle.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 = 0x00for b in buf:  # 求和sum += b # 累加sum = sum - 0x55 - 0x55  # 去掉命令开头的两个 0x55sum = ~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()  # 清空接收缓存# 数据长度为 数据长度+指令+ 参数+校验和  参数个数 = 数据长度-3if 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).valueelif 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).valueelse:  # 数据不正确,不符合接收数据的格式return Noneexcept BaseException as e:print(e) # 打印异常else:  # 接收数据为空serialHandle.flushInput()  # 清空接收缓存return None

串口总线舵机之舵机命令相关推荐

  1. 舵机任意角度程序_真香!!!飞特发布性价比超高的19kg磁编码360°双轴串口总线舵机STS3215...

    2020年4月6日,深圳飞特模型有限公司发布了2020年新款磁编码版本的TTL串口总线舵机.这款舵机是基于SCS215电位器版本开发的更高性能的磁编码版本,不仅具备了飞特SM高端系列的高性价比功能,又 ...

  2. 串口总线舵机之socket网络指令

    我们如何通过外部去控制树莓派串口总线舵机和PWM舵机. 网络无疑是一个很好的选择. 这一部分是在lsc.py文件中 关于socketserver部分参考 socketserver 文章目录 调试工具 ...

  3. 51单片机控制舵机,舵机不动的定时器原因

    舵机: 红色:VCC 棕色:GND 黄色:PWM 这是定时器0初始化: unsigned cha count = 0; unsigned char timer1 ;void Timer1_Init() ...

  4. 串口工具SecureCRT不能输入命令

    串口工具SecureCRT不能输入命令 在做测试串口和PC 实现文件互传实验时,发现串口工具SecureCRT不能输入命令安回车没有反应. 解决方法: Session Options -> Co ...

  5. arduino控制小车转向_舵机和舵机控制板

    在很多项目中需要用到舵机.比如机器人,伺服系统等方面.步进电机是可以设定转过多少角度,而舵机是可以设定转到的位置,可以说是指哪打哪,Arduino智能小车的前轮转弯系统便是用的这种原理,在工业上机器人 ...

  6. 舵机就是舵机,可不是步进!

    转自:http://www.360doc.com/content/16/0902/11/1286300_587730834.shtml 是否有人, 从前以为舵机是步进电机的? PCB哥知道,从前一定有 ...

  7. 全双工串口、半双工串口总线及其转换

    全双工串口.半双工串口总线及其转换 前言 全双工串口 半双工串口总线 两者转换 软硬件配合方案 纯电路方案 前言 这是本人在接触串口总线时的一些总结,希望能对大家有所帮助,若有谬误之处,恳请各位指正. ...

  8. 小车舵机控制linux软件,在Linux(Ubuntu)上使用串口控制ROBOTIS Dynamxiel舵机

    声明:此文档版权归属于北京小芽科技,可以转载,但要声明出处(北京小芽科技博客xiaoyatec.com) 硬件配置: 1.USB2Dynamixel串口模块 2.SMPS2Dynamixel电源模块 ...

  9. 学习 stm32(TTL)串口通信控制16路舵机控制板(维特智能)

    学习STM32Core平台串口2连接维特智能串口Normal协议,然后通过串口1直接连接舵机控制板(TTL),接收进行通信:需要看产品文档的可以直接官网搜索文档. 16路舵机控制板官方产品网址 在查看 ...

  10. STM32+DMA串口+RC信号控制舵机

    文章目录 前言 一.RC遥控器PWM信号 二.关于舵机 三.STM32串口DMA 四.CUBEMX配置设置 五.串口+DMA通讯 六.PWM输出 七.串口控制舵机 八.通讯测试 九.PWM输出测试 十 ...

最新文章

  1. W7程序计算机面板介绍,win7系统隐藏任意程序运行界面的详细步骤
  2. 【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | 通信场景 | Channel 通信机制 | Channel 支持的通信数据类型 | Channel 类型 )
  3. pandas如何获取某一个元素的行号,也就是索引值
  4. cobaltstrike安装_CobaltStrike + Metasploit 组合安装
  5. Servlet快速入门及运行流程
  6. html中如何让图片交错,HTML5/Canvas 光圈交错幻觉
  7. 我终于知道公司前端为啥不加班了…
  8. 光耦p621引脚图_光耦继电器类型,带有示例和电路图的应用
  9. 我们为什么需要SDN?---致新人
  10. 【转】处理wording的一些参考
  11. 简述RedHat 7 Linux系统
  12. matlab2009a下载 win7,MATLAB R2009a完美安装及下载
  13. 网络工程师中级--下午科目
  14. Matlab选题之十大热门课题推荐
  15. DS90UB953-Q1-DS90UB954-Q1调试记录
  16. MFC绘图工具High-speed Charting Control(VS2019)
  17. mac 投影android手机屏幕尺寸,mac电脑投屏到投影仪的方法(苹果投屏到电脑屏幕图文教程详解)...
  18. Android 自动化测试——monkey的使用
  19. 【OpenCV 例程300篇】206. Photoshop 色阶调整算法
  20. 【牛客网】---多态经典选择题

热门文章

  1. opencv 学习(3)几何图形的简单识别
  2. android按钮添加音效,Android中为按钮设置点击音效
  3. word2010分页设置页眉
  4. 解决teamviewer访问超时限制的问题
  5. 以太坊实战之《如何正确处理nonce》
  6. 企业PC终端安全问题分析及整改措施
  7. matlab 安装 提取错误,安装时 提取文件错误
  8. iOS打包静态库(完整篇)
  9. 接口implement
  10. vue-学生信息管理系统