2020-09-26-舵机

【运行前确认舵机的COM口并在程序中更改。波特率默认为57600,舵机id默认为1 此舵机使用协议2.0,请确保打开的是2.0的程序】

windows下运行步骤

0.安装驱动程序 USB-to-serial-串口驱动
建议安装R Manager2.0(v2.0.1).exe
1.安装vscode和python
python安装建议勾选添加到系统路径的框选项
2.命令行安装pyserial:

pip install pyserial

3.vscode中安装python插件:
在这里插入图片描述

整个文件夹导入vscode:
优势是更便于管理。也可以不导入
步骤:
vscode选择打开文件夹
在这里插入图片描述
选择协议2文件夹在这里插入图片描述
打开如图
在这里插入图片描述
选择文件后改动com口,点击菜单“运行”

在这里插入图片描述
com口查看:电脑 右键–管理 再按下图查看
在这里插入图片描述

ubuntu运行准备

串口权限

ubuntu系统运行舵机代码,出现报错permission denied,error13
安装串口驱动和修改文件夹权限后仍然不行,最后查到是串口权限问题
解决:
命令终端输入:

sudo gedit /etc/udev/rules.d/70-ttyusb.rules

文件内容为:

KERNEL=="ttyUSB[0-9]*", MODE="0666"

保存。
增加访问权限:(命令终端输入)

sudo chmod 666 /dev/ttyUSB0

重新插入USB转串口设备,普通用户就有权限访问了。
串口编程中使用open()函数就能打开串口了.
link

ubuntu14.04 放开串口权限 - 白菜菜白 - 开发者的网上家园
https://www.cnblogs.com/lvchaoshun/p/5911903.html


串口驱动

我在使用过程中没有遇到串口驱动的问题,
报错时检查串口驱动是否正确安装

ubuntu下CH34×串口驱动安装_hnlyzxy123的博客-CSDN博客
https://blog.csdn.net/hnlyzxy123/article/details/82181027

查看串口信息

可以用如下命令查看串口信息:
ls -l /dev/ttyUSB*来查看相关的信息。

串口号

我在ubuntu系统下连接时用的是 /dev/ttyUSB0 如果连接多个硬件应检查是否是串口对应有错误。

相关文章

(2条消息) ubuntu串口的安装和使用(usb转串口)_稻草人的专栏-CSDN博客_ubuntu 串口
https://blog.csdn.net/u010925447/article/details/58049130

Protocol 2.0协议

https://emanual.robotis.com/docs/en/dxl/protocol2/

舵机指令包

Instruction Packet
Instruction Packet is the command data sent to the Device.
在这里插入图片描述

Header

前三个。The field that indicates the start of the Packet

Reserved

Uses 0X00 (Note that Reserved does not use 0XFD). The Reserved functions the same as Header.
The field that indicates an ID of the device that should receive the Instruction Packet and process it

Packet ID

Range : 0 ~ 252 (0x00 ~ 0xFC), which is a total of 253 numbers that can be used
Broadcast ID : 254 (0xFE), which makes all connected devices execute the Instruction Packet
253(0xFD), 255(0xFF) :避免与header发生重复

NOTE : If the Instruction Packet ID is set to the Broadcast ID(0xFE), Status Packet will not be returned for READ and WRITE Instructions.

Length

The field that indicates the length of packet field.
Devided into low and high bytes in the Instruction Packet
The Length has the size of Instruction, Parameters and CRC (Low / High bytes) fields
Length = the number of Parameters + 3
在这里插入图片描述

Status Packet includes 1 byte length ERROR data.

Instruction

The field that defines the type of commands.
在这里插入图片描述
在这里插入图片描述

Parameters

不一定有,长度也不一定,instruction的附加参数
As the auxiliary data field for Instruction, its purpose is different for each Instruction.
Method of expressing negative number data : This is different for each product, so please refer to the e-manual of the corresponding product.

CRC

16bit CRC field which checks if the Packet has been damaged during communication.

状态包(返回包)

比指令包多了一个ERROR
在这里插入图片描述

Instruction

Instruction of the Status Packet is designated to 0x55 (Status)

Error

The field that indicates the processing result of Instruction Packet

Bit 7       			   	Bit 6 ~ Bit 0Alert	Error		    Number
Alert : When there has been a problem in the Device, this field is set as 1. Checking the Hardware error status value of the Control Table can indicate the cause of the problem.
Error Number : When there has been an Error in the processing of the Instruction Packet.
在这里插入图片描述

Packet Process

Processing Order of Transmission

Generate basic form of Packet and afterwards Byte Stuffing(0xFD)

  • Inspection range : Everything within the Instruction field to the Parameter field (not the CRC)
  • Processing method : When the pattern “0xFF 0xFF 0xFD” appears, add Byte Stuffing (0xFD) (If “0xFF 0xFF 0xFD” already exists, add a 0xFD to change it to “0xFF 0xFF 0xFD 0xFD”)

Length : Modify to Length with Byte Stuffing applied
CRC : Calculate CRC with Byte Stuffing applied

Processing Order of Reception

Search for Header(0xFF 0xFF 0xFD) : Ignore the Byte Stuffing(“0xFF 0xFF 0xFD 0xFD”).
Packet ID : If Packet ID is valid, receive additional transmission the size of Length
CRC : Calculate with the received Packet with Byte Stuffing included, and once CRC is matched then remove Byte Stuffing

sync_read_write

read
同一指令同时同多个设备读取。
在这里插入图片描述
由上图协议可知,param前四个为地址和数据长度,后面是id编号
在这里插入图片描述
这里初始化了同步读取的四个参数,分别为端口 数据包 地址 数据长度。。协议第二条要求地址和数据长度不可变。
类初始化四个参数:

后面继续添加要读取的舵机id(添加了两个):
在这里插入图片描述
发送,并获得返回数据:
在这里插入图片描述
使用完后,(程序即将退出时):
在这里插入图片描述
写入类似,多了个写入的目标位置值
在这里插入图片描述
write
在这里插入图片描述

bulk_read_write

用一个指令包从多个设备获取数据(可相同也可不同)
但是同样的id号只能出现一次,也就是说一个指令包只能在同一个设备读取一次。
Similar to Sync Read, this is an Instruction to read data from multiple devices simultaneously using one Instruction Packet
This Instruction can be used even if the Address and Data Length of the data for each device are not all the same.
The same ID cannot be used multiple times in the Parameter. In other words, it can only read once from each individual device.
If the Address of the data is not continual, an Indirect Address can be used.
Packet ID field : 0xFE (Broadcast ID)
在这里插入图片描述
NOTE : Status Packet is received from each Device.
在这里插入图片描述
以下是部分例程代码:

# Enable Dynamixel#1 Torque
dxl_comm_result, dxl_error = packetHandler.write1ByteTxRx(portHandler, DXL1_ID, ADDR_PRO_TORQUE_ENABLE, TORQUE_ENABLE)
if dxl_comm_result != COMM_SUCCESS:
    print("%s" % packetHandler.getTxRxResult(dxl_comm_result))
elif dxl_error != 0:
    print("%s" % packetHandler.getRxPacketError(dxl_error))
else:
    print("Dynamixel#%d has been successfully connected" % DXL1_ID)


# Add parameter storage for Dynamixel#1 present position
dxl_addparam_result = groupBulkRead.addParam(DXL1_ID, ADDR_PRO_PRESENT_POSITION, LEN_PRO_PRESENT_POSITION)
if dxl_addparam_result != True:
    print("[ID:%03d] groupBulkRead addparam failed" % DXL1_ID)
    quit()


while1循环

while 1:
    print("Press any key to continue! (or press ESC to quit!)")
    if getch() == chr(0x1b):
        break

    # Allocate goal position value into byte array
    param_goal_position = [DXL_LOBYTE(DXL_LOWORD(dxl_goal_position[index])), DXL_HIBYTE(DXL_LOWORD(dxl_goal_position[index])), DXL_LOBYTE(DXL_HIWORD(dxl_goal_position[index])), DXL_HIBYTE(DXL_HIWORD(dxl_goal_position[index]))]

    # Add Dynamixel#1 goal position value to the Bulkwrite parameter storage
    dxl_addparam_result = groupBulkWrite.addParam(DXL1_ID, ADDR_PRO_GOAL_POSITION, LEN_PRO_GOAL_POSITION, param_goal_position)
    if dxl_addparam_result != True:
        print("[ID:%03d] groupBulkWrite addparam failed" % DXL1_ID)
        quit()
    # Bulkwrite goal position and LED value
    dxl_comm_result = groupBulkWrite.txPacket()
    if dxl_comm_result != COMM_SUCCESS:
        print("%s" % packetHandler.getTxRxResult(dxl_comm_result))
    groupBulkWrite.clearParam()

    # Add Dynamixel#2 LED value to the Bulkwrite parameter storage
    dxl_addparam_result = groupBulkWrite.addParam(DXL1_ID, ADDR_PRO_LED_RED, LEN_PRO_LED_RED, [dxl_led_value[index]])
    if dxl_addparam_result != True:
        print("[ID:%03d] groupBulkWrite addparam failed" % DXL1_ID)
        quit()

    # Bulkwrite goal position and LED value
    dxl_comm_result = groupBulkWrite.txPacket()
    if dxl_comm_result != COMM_SUCCESS:
        print("%s" % packetHandler.getTxRxResult(dxl_comm_result))

    # Clear bulkwrite parameter storage
    groupBulkWrite.clearParam()

    while 1:
        # # Bulkread present position and LED status
        dxl_comm_result = groupBulkRead.txRxPacket()
        if dxl_comm_result != COMM_SUCCESS:
            print("%s" % packetHandler.getTxRxResult(dxl_comm_result))

        # Check if groupbulkread data of Dynamixel#1 is available
        dxl_getdata_result = groupBulkRead.isAvailable(DXL1_ID, ADDR_PRO_PRESENT_POSITION, LEN_PRO_PRESENT_POSITION)
        if dxl_getdata_result != True:
            print("[ID:%03d] groupBulkRead getdata failed" % DXL1_ID)
            quit()

        # # Check if groupbulkread data of Dynamixel#2 is available
        # dxl_getdata_result = groupBulkRead.isAvailable(DXL2_ID, ADDR_PRO_LED_RED, LEN_PRO_LED_RED)
        # if dxl_getdata_result != True:
        #     print("[ID:%03d] groupBulkRead getdata failed" % DXL2_ID)
        #     quit()

        # Get present position value
        dxl1_present_position = groupBulkRead.getData(DXL1_ID, ADDR_PRO_PRESENT_POSITION, LEN_PRO_PRESENT_POSITION)

        # # Get LED value
        # dxl2_led_value_read = groupBulkRead.getData(DXL2_ID, ADDR_PRO_LED_RED, LEN_PRO_LED_RED)

        # print("[ID:%03d] Present Position : %d \t [ID:%03d] LED Value: %d" % (DXL1_ID, dxl1_present_position, DXL2_ID, dxl2_led_value_read))

        if not (abs(dxl_goal_position[index] - dxl1_present_position) > DXL_MOVING_STATUS_THRESHOLD):
            break

    # Change goal position
    if index == 0:
        index = 1
        
    else:
        index = 0

indirect_address.py间接地址

地址错误,手册地址有误,可以参考给的标准调试程序里的地址
168地址 634数值
168 对应634
170 对应635 以此类推。。
在这里插入图片描述
在这里插入图片描述

注意:

程序中舵机地址的修改

经过测试发现,addr数据手册上有误,正确的数值要参考R Manager2.0(v2.0.1).exe这个示例程序内的地址(参考R+manager软件里面地址)
如下图左侧第一栏为正确的地址
在这里插入图片描述

位置-1

舵机位置模式运行时取值范围为1-4294967295
舵机4294967295(十六进制为0xFFFF FFFF)等价于-1

90度 125475.0 就近原则

设舵机例程程序中0点为0度。那么位置每加125475舵机正传90(面向舵机时,舵机逆时针旋转),减则反转,同时舵机会选择转动最少的方向执行,如从0到4294967295(对应-1),舵机会反转,而不会正转从0增加到该值。

0点问题

【small bug】调试过程中发现position到0附近会导致程序运行时舵机反应慢,舵机经过较长时间后才到0点。并接收下一目标位置2000
在这里插入图片描述
在这里插入图片描述
此情况可以通过避开0位置点,或者分析具体原因解决,猜测可能跟if判断当前位置是否到达指定位置的 那部分代码有关系,舵机需要移动的距离较小,并且要反方向转动,因此只能缓慢微调
可通过优化if判断来验证这一想法
【验证:避开0点后没有再出现此问题】
【10.2验证:对0位置点加 if 判断后没有反应慢问题了】通过将0位置点附近的目标范围设置大一些,并包括左右部分。
在这里插入图片描述

台式电脑出现list out of range

发现是台式电脑串口不稳定造成的,除了会出现list out of range外还会出现There is no status packet以及CRC校验的错误,一般有概率性不是必定出错。
在这里插入图片描述

出现的错误

length does not match

Succeeded to open the port
Succeeded to change the baudrate
[RxPacketError] The data length does not match as expected!

####已解决,舵机地址错误

clear_multi_turn.py

调试clear_multi_turn.py出现2个错误
在这里插入图片描述
第一个错误发生在设置舵机运行模式时。
【解决】经过分析,后,意外想到可能是电机运行状态的原因
通过禁止舵机转矩,再执行模式设置,程序没有再报错
在这里插入图片描述

原因是电机运行时eeprom中addr不能读写(例程中电机转动时部分设置项变灰色)
第二个错误有关kbhit函数,但似乎该函数与windows系统无关
尝试将该函数直接改成1
在这里插入图片描述
在这里插入图片描述
查看协议2.0发现,应该是固件版本低的问题
在这里插入图片描述
在这里插入图片描述

ping.py中id改为广播id-254后报错

id改为广播id-254后报错。但是发现通过串口助手可以正常发送!
【解决】广播id发送方式有另一个文件,而且接收方法与普通ping不同

RX_TIMEOUT

大致发包过程是将数据填入txpacket的list中,并将其发送出去,问题出现在接收返回包过程中,具体错误是RX_TIMEOUT,没接到返回的packet。具体原因未查出。【使用的协议1.0,,舵机是2.0的】
换为2.0的程序后此错误消失

not match as expected

报错信息:

Succeeded to open the port
Succeeded to change the baudrate
[RxPacketError] The data length does not match as expected!

后来发现是addr地址有错误,更正后此错误消失

其他错误

如电机使用2.0协议,结果打开了1.0协议的程序进行控制
编译中打开了被调用文件,修改/查看后没有返回主文件,导致运行报奇怪错误
and 送哦。。

剧照

在这里插入图片描述
在这里插入图片描述
涂中中蓝色为。。485转usb转接器在这里插入图片描述
在这里插入图片描述

其他

list

txpacket = [0] * (length + 7)
在python中, 如果用一个列表list1乘一个数字n 会得到一个新的列表list2, 这个列表的元素是list1的元素重复n次, 例如:

list1 = [0]
list2 = list1 * 5		# list2 = [0, 0, 0, 0, 0]

(3条消息) python 列表乘一个数字_hq_cjj的博客-CSDN博客
https://blog.csdn.net/hq_cjj/article/details/86659589

from . import XXX

我的理解是 from . import XXX默认的就是在当前程序所在文件夹里__init__.py程序中导入XXX,如果当前程序所在文件夹里没有__init__.py文件的话,就不能这样写,而应该写成from .A import XXX,A是指当前文件夹下你想导入的函数(或者其他的)的python程序名,如果你想导入的函数不在当前文件夹,那么就有可能用到 from … import XXX(即上一个文件夹中的__init__.py),或者from …A import XXX(即上一个文件夹中的文件A)
链接:https://www.zhihu.com/question/28688151/answer/66982373

setup.py

Python 库打包分发(setup.py 编写)简易指南 | Huoty’s Blog
https://blog.konghy.cn/2018/04/29/setup-dot-py/#part-2bb23717ee7e9bfc

Visual Studio Code快捷键

(3条消息) 【Visual Studio Code】VS Code在Linux/Mac/Windows中向前、向后定位的快捷键及修改方法_H_O_W_E的专栏-CSDN博客
https://blog.csdn.net/H_O_W_E/article/details/104944130

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

开心超人dev

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值