emm-stepper 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
emm_stepper/configs.py ADDED
@@ -0,0 +1,476 @@
1
+ """Emm固件步进电机配置常量.
2
+
3
+ 基于ZDT_X42S第二代闭环步进电机用户手册V1.0.3_251224。
4
+ """
5
+
6
+ from dataclasses import dataclass, field
7
+ from enum import IntEnum
8
+
9
+
10
+ class ExtendedIntEnum(IntEnum):
11
+ """扩展的整数枚举,支持字节表示."""
12
+
13
+ @property
14
+ def bytes(self) -> bytes:
15
+ """返回字节表示."""
16
+ return self.value.to_bytes(1, "big")
17
+
18
+
19
+ @dataclass(frozen=True)
20
+ class SystemConstants:
21
+ """系统常量."""
22
+
23
+ SERIAL_TIMEOUT: float = field(default=0.1)
24
+ MAX_RETRIES: int = field(default=3)
25
+ DEFAULT_BAUDRATE: int = field(default=115200)
26
+
27
+
28
+ class Code(ExtendedIntEnum):
29
+ """命令功能码 - Emm固件."""
30
+
31
+ # 触发动作命令
32
+ CAL_ENCODER = 0x06 # 触发编码器校准
33
+ RESTART = 0x08 # 重启电机
34
+ ZERO_POSITION = 0x0A # 将当前位置角度清零
35
+ CLEAR_PROTECTION = 0x0E # 解除堵转/过热/过流保护
36
+ FACTORY_RESET = 0x0F # 恢复出厂设置
37
+
38
+ # 运动控制命令
39
+ MULTI_MOTOR = 0xAA # 多电机命令
40
+ ENABLE = 0xF3 # 电机使能控制
41
+ JOG = 0xF6 # 速度模式控制(Emm)
42
+ POSITION = 0xFD # 位置模式控制(Emm)
43
+ ESTOP = 0xFE # 立即停止
44
+ SYNC_MOVE = 0xFF # 触发多机同步运动
45
+
46
+ # 原点回零命令
47
+ SET_HOME_ZERO = 0x93 # 设置单圈回零的零点位置
48
+ HOME = 0x9A # 触发回零
49
+ STOP_HOME = 0x9C # 强制中断并退出回零操作
50
+ GET_HOME_STATUS = 0x3B # 读取回零状态标志
51
+ GET_HOME_PARAM = 0x22 # 读取回零参数
52
+ SET_HOME_PARAM = 0x4C # 修改回零参数
53
+
54
+ # 读取系统参数命令
55
+ TIMED_RETURN = 0x11 # 定时返回信息命令
56
+ GET_VERSION = 0x1F # 读取固件版本和硬件版本
57
+ GET_MOTOR_RH = 0x20 # 读取相电阻和相电感
58
+ GET_PID = 0x21 # 读取PID参数
59
+ GET_INTEGRAL_STIFFNESS = 0x23 # 读取积分限幅/刚性系数
60
+ GET_BUS_VOLTAGE = 0x24 # 读取总线电压
61
+ GET_BUS_CURRENT = 0x26 # 读取总线电流
62
+ GET_PHASE_CURRENT = 0x27 # 读取相电流
63
+ GET_ENCODER = 0x31 # 读取线性化编码器值
64
+ GET_PULSE_COUNT = 0x32 # 读取输入脉冲数
65
+ GET_TARGET_POSITION = 0x33 # 读取电机目标位置
66
+ GET_REALTIME_TARGET = 0x34 # 读取电机实时设定的目标位置
67
+ GET_REALTIME_SPEED = 0x35 # 读取电机实时转速
68
+ GET_REALTIME_POSITION = 0x36 # 读取电机实时位置
69
+ GET_POSITION_ERROR = 0x37 # 读取电机位置误差
70
+ GET_BATTERY_VOLTAGE = 0x38 # 读取电池电压(Y42)
71
+ GET_TEMPERATURE = 0x39 # 读取驱动温度
72
+ GET_MOTOR_STATUS = 0x3A # 读取电机状态标志
73
+ GET_HOME_MOTOR_STATUS = 0x3C # 读取回零状态标志+电机状态标志
74
+ GET_IO_STATUS = 0x3D # 读取引脚IO电平状态
75
+ GET_COLLISION_RETURN_ANGLE = 0x3F # 读取碰撞回零返回角度
76
+ GET_POSITION_WINDOW = 0x41 # 读取位置到达窗口
77
+ GET_SYS_STATUS = 0x43 # 读取系统状态参数
78
+ GET_CONFIG = 0x42 # 读取驱动配置参数
79
+
80
+ # 读写驱动参数命令
81
+ GET_PROTECTION_THRESHOLD = 0x13 # 读取过热过流保护检测阈值
82
+ BROADCAST_GET_ID = 0x15 # 广播读取ID地址
83
+ GET_HEARTBEAT_TIME = 0x16 # 读取心跳保护功能时间
84
+ GET_OPTION_STATUS = 0x1A # 读取选项参数状态
85
+ SET_OPEN_LOOP_CURRENT = 0x44 # 修改开环模式工作电流
86
+ SET_CLOSED_LOOP_CURRENT = 0x45 # 修改闭环模式最大电流
87
+ SET_LOOP_MODE = 0x46 # 修改开环/闭环控制模式
88
+ SET_CONFIG = 0x48 # 修改驱动配置参数
89
+ SET_PID = 0x4A # 修改PID参数
90
+ SET_INTEGRAL_STIFFNESS = 0x4B # 修改积分限幅/刚性系数
91
+ SET_SCALE_INPUT = 0x4F # 修改命令速度值是否缩小10倍输入
92
+ SET_POWER_OFF_FLAG = 0x50 # 修改掉电标志
93
+ SET_COLLISION_RETURN_ANGLE = 0x5C # 修改碰撞回零返回角度
94
+ SET_HEARTBEAT_TIME = 0x68 # 修改心跳保护功能时间
95
+ SET_MICROSTEP = 0x84 # 修改细分值
96
+ SET_ID = 0xAE # 修改电机ID/地址
97
+ SET_LOCK_BUTTON = 0xD0 # 修改锁定按键功能
98
+ SET_POSITION_WINDOW = 0xD1 # 修改位置到达窗口
99
+ SET_PROTECTION_THRESHOLD = 0xD3 # 修改过热过流保护检测阈值
100
+ SET_MOTOR_DIRECTION = 0xD4 # 修改电机运动正方向
101
+ SET_FIRMWARE_TYPE = 0xD5 # 修改固件类型
102
+ SET_LOCK_PARAM = 0xD6 # 修改锁定修改参数功能
103
+ SET_MOTOR_TYPE = 0xD7 # 修改电机类型
104
+ SET_DMX512_PARAM = 0xD9 # 修改DMX512协议参数
105
+
106
+ # 上电自动运行命令
107
+ SET_AUTO_RUN = 0xF7 # 存储一组速度参数,上电自动运行
108
+
109
+
110
+ class Protocol(ExtendedIntEnum):
111
+ """协议辅助码."""
112
+
113
+ # 触发动作命令
114
+ CAL_ENCODER = 0x45
115
+ RESTART = 0x97
116
+ ZERO_POSITION = 0x6D
117
+ CLEAR_PROTECTION = 0x52
118
+ FACTORY_RESET = 0x5F
119
+
120
+ # 运动控制命令
121
+ ENABLE = 0xAB
122
+ ESTOP = 0x98
123
+ SYNC_MOVE = 0x66
124
+
125
+ # 原点回零命令
126
+ SET_HOME_ZERO = 0x88
127
+ STOP_HOME = 0x48
128
+ SET_HOME_PARAM = 0xAE
129
+
130
+ # 定时返回
131
+ TIMED_RETURN = 0x18
132
+
133
+ # 读取配置
134
+ GET_CONFIG = 0x6C
135
+ GET_SYS_STATUS = 0x7A
136
+ GET_DMX512_PARAM = 0x78
137
+
138
+ # 设置命令
139
+ SET_MICROSTEP = 0x8A
140
+ SET_ID = 0x4B
141
+ SET_OPEN_LOOP_CURRENT = 0x33
142
+ SET_CLOSED_LOOP_CURRENT = 0x66
143
+ SET_LOOP_MODE = 0xA6
144
+ SET_CONFIG = 0xD1
145
+ SET_PID = 0xC3
146
+ SET_AUTO_RUN = 0x1C
147
+ SET_SCALE_INPUT = 0x71
148
+ SET_MOTOR_DIRECTION = 0x60
149
+ SET_FIRMWARE_TYPE = 0x69
150
+ SET_MOTOR_TYPE = 0x35
151
+ SET_LOCK_BUTTON = 0xB3
152
+ SET_POSITION_WINDOW = 0x07
153
+ SET_PROTECTION_THRESHOLD = 0x56
154
+ SET_HEARTBEAT_TIME = 0x38
155
+ SET_INTEGRAL_STIFFNESS = 0x57
156
+ SET_COLLISION_RETURN_ANGLE = 0xAC
157
+ SET_LOCK_PARAM = 0x4B
158
+ SET_DMX512_PARAM = 0x90
159
+
160
+
161
+ class StatusCode(ExtendedIntEnum):
162
+ """状态码."""
163
+
164
+ FIXED_CHECKSUM = 0x6B # 固定校验码
165
+ SUCCESS = 0x02 # 命令正确
166
+ AT_ZERO = 0x12 # 触发回零时当前就在零点处
167
+ PARAM_ERROR = 0xE2 # 命令参数错误
168
+ FORMAT_ERROR = 0xEE # 命令格式错误
169
+ ACTION_COMPLETE = 0x9F # 动作执行完成
170
+
171
+
172
+ class ChecksumMode(ExtendedIntEnum):
173
+ """校验方式."""
174
+
175
+ FIXED = 0 # 固定0x6B
176
+ XOR = 1 # 异或校验
177
+ CRC8 = 2 # CRC-8校验
178
+ MODBUS = 3 # Modbus-RTU协议
179
+ DMX512 = 4 # DMX512协议
180
+
181
+ default = FIXED
182
+
183
+
184
+ class Address(int):
185
+ """电机地址 (1-255, 0为广播地址)."""
186
+
187
+ BROADCAST = 0
188
+ MIN = 0
189
+ MAX = 255
190
+ DEFAULT = 1
191
+
192
+ def __new__(cls, value: int = DEFAULT) -> "Address":
193
+ if not cls.MIN <= value <= cls.MAX:
194
+ raise ValueError(f"地址必须在 {cls.MIN} 到 {cls.MAX} 之间")
195
+ return super().__new__(cls, value)
196
+
197
+ @property
198
+ def bytes(self) -> bytes:
199
+ return self.to_bytes(1, "big")
200
+
201
+
202
+ class Direction(ExtendedIntEnum):
203
+ """运动方向."""
204
+
205
+ CW = 0 # 顺时针
206
+ CCW = 1 # 逆时针
207
+
208
+ default = CW
209
+
210
+
211
+ class SyncFlag(ExtendedIntEnum):
212
+ """同步标志."""
213
+
214
+ IMMEDIATE = 0 # 立即执行
215
+ SYNC = 1 # 先缓存当前命令
216
+
217
+ default = IMMEDIATE
218
+
219
+
220
+ class StoreFlag(ExtendedIntEnum):
221
+ """存储标志."""
222
+
223
+ NO_STORE = 0 # 不存储
224
+ STORE = 1 # 存储(掉电不丢失)
225
+
226
+ default = NO_STORE
227
+
228
+
229
+ class EnableFlag(ExtendedIntEnum):
230
+ """使能标志."""
231
+
232
+ DISABLE = 0 # 不使能(松轴)
233
+ ENABLE = 1 # 使能(锁轴)
234
+
235
+ default = ENABLE
236
+
237
+
238
+ class MotionMode(ExtendedIntEnum):
239
+ """运动模式."""
240
+
241
+ RELATIVE_LAST = 0 # 相对上一输入目标位置进行相对位置运动
242
+ ABSOLUTE = 1 # 相对坐标零点进行绝对位置运动
243
+ RELATIVE_CURRENT = 2 # 相对当前实时位置进行相对位置运动
244
+
245
+ default = RELATIVE_LAST
246
+
247
+
248
+ class HomingMode(ExtendedIntEnum):
249
+ """回零模式."""
250
+
251
+ NEAREST = 0 # 单圈就近回零
252
+ DIRECTION = 1 # 单圈方向回零
253
+ COLLISION = 2 # 无限位碰撞回零
254
+ LIMIT_SWITCH = 3 # 限位回零
255
+ ABS_ZERO = 4 # 回到绝对位置坐标零点
256
+ LAST_POWER_OFF = 5 # 回到上次掉电位置角度
257
+
258
+ default = NEAREST
259
+
260
+
261
+ class HomingDirection(ExtendedIntEnum):
262
+ """回零方向."""
263
+
264
+ CW = 0 # 顺时针
265
+ CCW = 1 # 逆时针
266
+
267
+ default = CW
268
+
269
+
270
+ class ControlMode(ExtendedIntEnum):
271
+ """控制模式."""
272
+
273
+ OPEN_LOOP = 0 # 开环模式
274
+ CLOSED_LOOP = 1 # FOC闭环模式
275
+
276
+ default = CLOSED_LOOP
277
+
278
+
279
+ class MotorType(ExtendedIntEnum):
280
+ """电机类型."""
281
+
282
+ DEGREE_09 = 0x19 # 0.9度步进电机
283
+ DEGREE_18 = 0x32 # 1.8度步进电机
284
+
285
+ default = DEGREE_18
286
+
287
+
288
+ class FirmwareType(ExtendedIntEnum):
289
+ """固件类型."""
290
+
291
+ X_FIRMWARE = 0 # X固件
292
+ EMM_FIRMWARE = 1 # Emm固件
293
+ EMM_TURBO = 2 # Emm固件狂暴模式
294
+
295
+ default = EMM_FIRMWARE
296
+
297
+
298
+ class BaudRate(ExtendedIntEnum):
299
+ """串口波特率."""
300
+
301
+ BAUD_9600 = 0
302
+ BAUD_19200 = 1
303
+ BAUD_25000 = 2
304
+ BAUD_38400 = 3
305
+ BAUD_57600 = 4
306
+ BAUD_115200 = 5
307
+ BAUD_256000 = 6
308
+ BAUD_512000 = 7
309
+ BAUD_921600 = 8
310
+
311
+ default = BAUD_115200
312
+
313
+ @property
314
+ def value_hz(self) -> int:
315
+ """返回实际波特率值."""
316
+ rates = [9600, 19200, 25000, 38400, 57600, 115200, 256000, 512000, 921600]
317
+ return rates[self.value]
318
+
319
+
320
+ class CanRate(ExtendedIntEnum):
321
+ """CAN通讯速率."""
322
+
323
+ CAN_10K = 0
324
+ CAN_20K = 1
325
+ CAN_50K = 2
326
+ CAN_83K = 3
327
+ CAN_100K = 4
328
+ CAN_125K = 5
329
+ CAN_250K = 6
330
+ CAN_500K = 7
331
+ CAN_800K = 8
332
+ CAN_1M = 9
333
+
334
+ default = CAN_500K
335
+
336
+
337
+ class ResponseMode(ExtendedIntEnum):
338
+ """控制命令应答方式."""
339
+
340
+ NONE = 0 # 不返回任何命令
341
+ RECEIVE = 1 # 只返回确认收到命令
342
+ REACHED = 2 # 只返回到位/回零完成命令
343
+ BOTH = 3 # 既返回确认收到命令,也返回动作完成命令
344
+ OTHER = 4 # 位置模式返回动作完成命令,其他返回确认收到命令
345
+
346
+ default = RECEIVE
347
+
348
+
349
+ class StallProtect(ExtendedIntEnum):
350
+ """堵转保护."""
351
+
352
+ DISABLE = 0 # 关闭堵转保护
353
+ ENABLE = 1 # 使能堵转保护
354
+ AUTO_ZERO = 2 # 堵转后复位为零点
355
+
356
+ default = ENABLE
357
+
358
+
359
+ class PulsePortMode(ExtendedIntEnum):
360
+ """脉冲端口复用模式."""
361
+
362
+ OFF = 0 # 关闭脉冲端口
363
+ OPEN = 1 # 开环模式
364
+ FOC = 2 # FOC闭环模式
365
+ ESI_RCO = 3 # 限位回零输入
366
+ PLR_ESI = 4 # 左右限位功能
367
+
368
+ default = FOC
369
+
370
+
371
+ class SerialPortMode(ExtendedIntEnum):
372
+ """通讯端口复用模式."""
373
+
374
+ OFF = 0 # 关闭通讯端口
375
+ ESI_ALO = 1 # 限位输入+报警输出
376
+ UART = 2 # 串口通讯
377
+ CAN = 3 # CAN通讯
378
+ ULR_ESI = 4 # 左右限位功能
379
+
380
+ default = UART
381
+
382
+
383
+ class EnableLevel(ExtendedIntEnum):
384
+ """En引脚有效电平."""
385
+
386
+ LOW = 0 # 低电平有效
387
+ HIGH = 1 # 高电平有效
388
+ HOLD = 2 # 一直有效
389
+
390
+ default = HOLD
391
+
392
+
393
+ class DirLevel(ExtendedIntEnum):
394
+ """Dir引脚有效电平."""
395
+
396
+ CW = 0 # 顺时针
397
+ CCW = 1 # 逆时针
398
+
399
+ default = CW
400
+
401
+
402
+ # CRC8查找表
403
+ CRC8_TABLE = bytes([
404
+ 0x00, 0x5E, 0xBC, 0xE2, 0x61, 0x3F, 0xDD, 0x83,
405
+ 0xC2, 0x9C, 0x7E, 0x20, 0xA3, 0xFD, 0x1F, 0x41,
406
+ 0x9D, 0xC3, 0x21, 0x7F, 0xFC, 0xA2, 0x40, 0x1E,
407
+ 0x5F, 0x01, 0xE3, 0xBD, 0x3E, 0x60, 0x82, 0xDC,
408
+ 0x23, 0x7D, 0x9F, 0xC1, 0x42, 0x1C, 0xFE, 0xA0,
409
+ 0xE1, 0xBF, 0x5D, 0x03, 0x80, 0xDE, 0x3C, 0x62,
410
+ 0xBE, 0xE0, 0x02, 0x5C, 0xDF, 0x81, 0x63, 0x3D,
411
+ 0x7C, 0x22, 0xC0, 0x9E, 0x1D, 0x43, 0xA1, 0xFF,
412
+ 0x46, 0x18, 0xFA, 0xA4, 0x27, 0x79, 0x9B, 0xC5,
413
+ 0x84, 0xDA, 0x38, 0x66, 0xE5, 0xBB, 0x59, 0x07,
414
+ 0xDB, 0x85, 0x67, 0x39, 0xBA, 0xE4, 0x06, 0x58,
415
+ 0x19, 0x47, 0xA5, 0xFB, 0x78, 0x26, 0xC4, 0x9A,
416
+ 0x65, 0x3B, 0xD9, 0x87, 0x04, 0x5A, 0xB8, 0xE6,
417
+ 0xA7, 0xF9, 0x1B, 0x45, 0xC6, 0x98, 0x7A, 0x24,
418
+ 0xF8, 0xA6, 0x44, 0x1A, 0x99, 0xC7, 0x25, 0x7B,
419
+ 0x3A, 0x64, 0x86, 0xD8, 0x5B, 0x05, 0xE7, 0xB9,
420
+ 0x8C, 0xD2, 0x30, 0x6E, 0xED, 0xB3, 0x51, 0x0F,
421
+ 0x4E, 0x10, 0xF2, 0xAC, 0x2F, 0x71, 0x93, 0xCD,
422
+ 0x11, 0x4F, 0xAD, 0xF3, 0x70, 0x2E, 0xCC, 0x92,
423
+ 0xD3, 0x8D, 0x6F, 0x31, 0xB2, 0xEC, 0x0E, 0x50,
424
+ 0xAF, 0xF1, 0x13, 0x4D, 0xCE, 0x90, 0x72, 0x2C,
425
+ 0x6D, 0x33, 0xD1, 0x8F, 0x0C, 0x52, 0xB0, 0xEE,
426
+ 0x32, 0x6C, 0x8E, 0xD0, 0x53, 0x0D, 0xEF, 0xB1,
427
+ 0xF0, 0xAE, 0x4C, 0x12, 0x91, 0xCF, 0x2D, 0x73,
428
+ 0xCA, 0x94, 0x76, 0x28, 0xAB, 0xF5, 0x17, 0x49,
429
+ 0x08, 0x56, 0xB4, 0xEA, 0x69, 0x37, 0xD5, 0x8B,
430
+ 0x57, 0x09, 0xEB, 0xB5, 0x36, 0x68, 0x8A, 0xD4,
431
+ 0x95, 0xCB, 0x29, 0x77, 0xF4, 0xAA, 0x48, 0x16,
432
+ 0xE9, 0xB7, 0x55, 0x0B, 0x88, 0xD6, 0x34, 0x6A,
433
+ 0x2B, 0x75, 0x97, 0xC9, 0x4A, 0x14, 0xF6, 0xA8,
434
+ 0x74, 0x2A, 0xC8, 0x96, 0x15, 0x4B, 0xA9, 0xF7,
435
+ 0xB6, 0xE8, 0x0A, 0x54, 0xD7, 0x89, 0x6B, 0x35,
436
+ ])
437
+
438
+
439
+ def calculate_checksum(data: bytes, mode: ChecksumMode = ChecksumMode.FIXED) -> int:
440
+ """计算校验码.
441
+
442
+ Args:
443
+ data: 需要计算校验的数据
444
+ mode: 校验模式
445
+
446
+ Returns:
447
+ 校验码
448
+ """
449
+ if mode == ChecksumMode.FIXED:
450
+ return StatusCode.FIXED_CHECKSUM
451
+ elif mode == ChecksumMode.XOR:
452
+ checksum = 0
453
+ for byte in data:
454
+ checksum ^= byte
455
+ return checksum
456
+ elif mode == ChecksumMode.CRC8:
457
+ crc8 = data[0]
458
+ for i in range(1, len(data)):
459
+ crc8 = CRC8_TABLE[crc8 ^ data[i]]
460
+ return crc8
461
+ else:
462
+ return StatusCode.FIXED_CHECKSUM
463
+
464
+
465
+ def add_checksum(data: bytes, mode: ChecksumMode = ChecksumMode.FIXED) -> bytes:
466
+ """添加校验码到数据末尾.
467
+
468
+ Args:
469
+ data: 原始数据
470
+ mode: 校验模式
471
+
472
+ Returns:
473
+ 带校验码的数据
474
+ """
475
+ checksum = calculate_checksum(data, mode)
476
+ return data + bytes([checksum])