-
Notifications
You must be signed in to change notification settings - Fork 26
中文 Readme
RS-485 插头型号: Molex 5264 (4 pin)
下载项目:
git clone --recurse-submodules https://github.com/dukelec/cdstep.git
CDBUS GUI Tool: https://github.com/dukelec/cdbus_gui
上电后,先往 state
写 1,然后往 tc_pos
写入目标位置 ,步进电机便会转动。
修改配置后,往 save_conf
写 1 保存配置到 flash。
如果需要恢复默认配置,修改 magic_code
为其它值,保存到 flash,然后重新上电即可。
调试打印窗口:
波形窗口:
波形细节、IAP 升级、数据导入导出(包含寄存器、log、波形):
CDSTEP 是一个开源步进电机控制器,它使用 RS485 接口,默认波特率为 115200 bps, 最高 > 10 Mbps,默认地址为 0xfe.
最底层协议为 CDBUS,其帧格式为:
src, dst, len, [payload], crc_l, crc_h
由 3 字节头、数据 和 最后 2 字节的 CRC 结尾(算法同 ModBus RTU 的 CRC)。
CDBUS 协议具体参见: https://cdbus.org
Payload 部分为 CDNET 协议,同时支持 CDNET L0 和 L1 两个版本。
CDNET 协议具体参见: https://github.com/dukelec/cdnet
CDNET 和 TCP/IP 中的 UDP 的概念比较类似,主要参考 UDP 的端口号的概念。
譬如最简单的 CDNET L0 协议,从主机默认端口发送一个字节数据 0x00 到 CDSTEP 的 1 号端口的格式:
01 00
第一个字节是目标端口号,然后跟数据即可。
以上示范,完整的 CDBUS 协议帧为(主机地址默认为 0,CDSTEP 为 0xfe):
00 fe 02 01 00 crc_l crc_h
以上示范,端口 1 是设备信息相关的,端口号可以看做 主命令号,首字节数据约定为 子命令号, 子命令号 0x00 是读设备信息。
CDSTEP 一共有 4 个端口接收指令,分別是:
唯一一个子命令号 0 是用来查询信息。
返回 0x80 + 设备信息字符串,譬如 M: cdstep; S: 23ff7660d405535353733034; SW: v1.1
.
参数表在代码中是 csa_t
类型的全局结构体,csa 为 Config Status Area 的缩写,它的前半部分可以写入 Flash 中,以保存一些用户设置,
上电时从 flash 中恢复 csa 的前半部分数据。而后部分数据为运行中的一些变量,通过此接口把这些变量暴露给用户,让用户直接读写可以大大简化代码。
不过,我们在读写前后,可以通过预先定义的 hook 钩子函数,对写入数据进行安全检查,或是定义写入后需要执行的动作。 而对于读取命令,可以提前为用户準备其所需要的数据格式,譬如格式转换。
另外,为了方便用户整体同步 csa 信息,我们定义了 csa 的哪些区域可写,不可写的区域用户不用小心避开,写入的数据直接会被忽略。
譬如,我们可以直接把 pid 对象放在 csa 表中,pid 对象中有一些是内部变量,不应该被用户修改, 有了可写区域限制,用户可以非常方便的整块写入数据,不用担心写到不该写的数据。
读写参数表的子命令为:
read: 0x00, offset_16, len_8 | return [0x80, data]
read_dft: 0x01, offset_16, len_8 | return [0x80, data]
write: 0x20, offset_16 + [data] | return [0x80] on success
譬如设置电机锁舵并进入位置模式。电机状态 state
值为 0 不锁舵,为 1 锁舵。
state
本身的地址是 0x00b8
,长度 1 个字节,那么上电后需要锁舵,发送以下数据到端口 5 即可:
20 b8 00 01
20
是子命令 write
,b8 00
是地址 0x00b8 的小端格式(除非特別说明,否则都是用小端),最后一个 01
是写入数值。
修改 csa_t
的定义,可能会影响到很多寄存器的地址,如果每次都是手工计算各寄存器的地址,很麻烦且容易出错,所以,我们通过 csa_list_show
这个函数,
上电时自动打印出所有寄存器的地址、类型,以及说明信息,可以直接拷贝到配置文档中。
每次修改 csa_t
的定义后,请同时修改其中的 conf_ver
版本号。
位置模式常用的参数表项有:
tc_pos, type: int32_t
tc_speed, type: uint32_t
tc_accel, type: uint32_t
我们可以通过端口 5 来写这些数据,但是,有的时候我们还想去写非连续的其它 表项,这样就要拆分多条命令,效率低,且容易导致数据不同步。
而且,我们还想设备同时回覆电机的错误码和一些运行数据,但不同模式下我们关心的运行数据不尽相同,如果写死会比较不方便。
参数表项内有 快速读写 通道的配置:(qxchg 是 quick exchange 的缩写)
regr_t qxchg_set[5];
regr_t qxchg_ret[5];
以上数组,首个 size 值为 0 的元素表示它和后序的未使用,元素的定义:
typedef struct {
uint16_t offset;
uint16_t size;
} regr_t; // reg range
qxchg_set
和 qxchg_ret
是 快速读写 的 子命令 20
所用,
预先设置好写哪些数据,以及返回哪些数据,然后发送 20
+ 需要写的数据就可以了,
会返回 80
+ 返回的数据。
qxchg_set
默认设定只用了一个元素,指向 tc_pos
, tc_speed
和 tc_accel
这 3 个表项所在的区域,
如果需要修改目标位置参数 tc_pos
为 0,向 端口 6 写数据 20 00 00 00 00
即可(20
是子命令号)。
如果需要同时修改目标位置和目标速度,譬如位置改为 0x00001000,速度改为 0x00000500,则写入 20 00 10 00 00 00 05 00 00
.
子命令 2f
支持接收包含多个设备数据的广播或组播包。
可以通过此接口实现 IAP 升级。
子命令为:
erase: 0x2f, addr_32, len_32 | return [0x80] on success
write: 0x20, addr_32 + [data] | return [0x80] on success
read: 0x00, addr_32, len_8 | return [0x80, data]
cal crc: 0x10, addr_32, len_32 | return [0x80, crc_16] # modbus crc
先要把需要写的区域擦除,然后写入数据,最后调用 crc 计算所写数据是否正确即可。 也可以读回所有数据来判断,速度会稍慢一点。
Bootloader 上电后,先使用默认波特率 115200,如果收到主机设置 keep_in_bl
的命令就保持此波特率,如果一秒锺内没有收到该命令,则切换到 Flash 中保存的波特率继续等待命令,如果再过一秒依然没收到命令,则跳转执行 APP 固件。Bootloader 和 APP 共享 csa 配置的开头部分,其中包含了用户设置的波特率。
如果不知道 CDSTEP 当前的 ID 号,可以发送 info 命令到广播地址 0xff 进行搜寻。
当前 MCU Flash 总共 128K, 每页大小为 2K, 前 24K 存放 Bootloader,最后 2K 存放 csa 参数表,其余为 APP.
和 快速读写 通道的 qxchg_XXX
数组一样,波形数据用同样的方式定义需要上报的数据的组成,可以自由配置想要观察的变量。
和 qxchg_XXX
不同的是,一个数据包会存放很多组数据,等数据包满到一定程度再发送给主机。
如果是固定周期的情况,譬如 FOC 电机,可以在电流环中为一个变量(譬如 loop_cnt
)每次加 1,然后只需要把 loop_cnt
写在每个数据包的最前面即可。
但我们这个 stepper motor 控制,周期不固定,所以要把时间信息和其它被观察的变量,每次都一起记录。
使用 plot 调试时,建议把设备的波特率设置高一些。
如果数据量很大,CDSTEP 会把连续的信息保存在 buffer 中,buffer 满之后,会等待 buffer 完全清空再继续,能最大程度保证数据的连续性,避免细节丟失。