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/__init__.py +38 -0
- emm_stepper/commands.py +1284 -0
- emm_stepper/configs.py +476 -0
- emm_stepper/device.py +900 -0
- emm_stepper/parameters.py +590 -0
- emm_stepper-1.0.0.dist-info/METADATA +1240 -0
- emm_stepper-1.0.0.dist-info/RECORD +10 -0
- emm_stepper-1.0.0.dist-info/WHEEL +5 -0
- emm_stepper-1.0.0.dist-info/licenses/LICENSE +21 -0
- emm_stepper-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1240 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: emm_stepper
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: ZDT X42S 第二代闭环步进电机控制库 (仅支持Emm固件)
|
|
5
|
+
Author-email: XHFB <2285273839@qq.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/yourusername/emm_stepper
|
|
8
|
+
Project-URL: Repository, https://github.com/yourusername/emm_stepper
|
|
9
|
+
Project-URL: Issues, https://github.com/yourusername/emm_stepper/issues
|
|
10
|
+
Keywords: stepper-motor,motor-control,serial,emm-firmware,zdt
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Requires-Python: >=3.7
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: pyserial>=3.5
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
21
|
+
Requires-Dist: black; extra == "dev"
|
|
22
|
+
Requires-Dist: flake8; extra == "dev"
|
|
23
|
+
Requires-Dist: mypy; extra == "dev"
|
|
24
|
+
Dynamic: license-file
|
|
25
|
+
|
|
26
|
+
# Emm Stepper - ZDT X42S 第二代闭环步进电机控制库
|
|
27
|
+
|
|
28
|
+
基于 **ZDT_X42S第二代闭环步进电机用户手册V1.0.3_251224**,仅支持 **Emm固件**,作者测试电机的固件为`ZDT_X42S_V1.0.7_260203`
|
|
29
|
+
|
|
30
|
+
## 参考文档
|
|
31
|
+
|
|
32
|
+
- [ZDT_X42S第二代闭环步进电机用户手册V1.0.3_251224](./ZDT_X42S第二代闭环步进电机用户手册V1.0.3_251224.pdf)
|
|
33
|
+
- [lyehe/ZDT_stepper](https://github.com/lyehe/ZDT_stepper) - 本项目参考其架构风格开发
|
|
34
|
+
|
|
35
|
+
## 目录
|
|
36
|
+
|
|
37
|
+
- [特性](#特性)
|
|
38
|
+
- [安装](#安装)
|
|
39
|
+
- [快速开始](#快速开始)
|
|
40
|
+
- [API参考](#api参考)
|
|
41
|
+
- [EmmDevice类](#emmdevice类)
|
|
42
|
+
- [参数类](#参数类)
|
|
43
|
+
- [枚举类型](#枚举类型)
|
|
44
|
+
- [使用示例](#使用示例)
|
|
45
|
+
- [注意事项](#注意事项)
|
|
46
|
+
|
|
47
|
+
## 特性
|
|
48
|
+
|
|
49
|
+
- ✅ 支持串口TTL/RS485通讯
|
|
50
|
+
- ✅ 支持多电机控制(同一串口不同地址)
|
|
51
|
+
- ✅ 速度模式控制(0-3000 RPM)
|
|
52
|
+
- ✅ 位置模式控制(脉冲数/角度/圈数)
|
|
53
|
+
- ✅ 原点回零功能(单圈就近/方向回零、多圈碰撞/限位回零)
|
|
54
|
+
- ✅ 堵转检测与保护
|
|
55
|
+
- ✅ 读取电机状态(位置、速度、电流、温度等)
|
|
56
|
+
- ✅ 参数配置(细分、电流、PID等)
|
|
57
|
+
|
|
58
|
+
## 安装
|
|
59
|
+
|
|
60
|
+
### 依赖
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
pip install pyserial
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### 导入库
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from serial import Serial
|
|
70
|
+
from emm_stepper import (
|
|
71
|
+
EmmDevice,
|
|
72
|
+
Direction,
|
|
73
|
+
MotionMode,
|
|
74
|
+
HomingMode,
|
|
75
|
+
ChecksumMode,
|
|
76
|
+
)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## 快速开始
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
from serial import Serial
|
|
83
|
+
from emm_stepper import EmmDevice, Direction
|
|
84
|
+
|
|
85
|
+
# 1. 创建串口连接
|
|
86
|
+
ser = Serial('COM9', 115200, timeout=0.1)
|
|
87
|
+
|
|
88
|
+
# 2. 创建电机实例
|
|
89
|
+
motor = EmmDevice(ser, address=1)
|
|
90
|
+
|
|
91
|
+
# 3. 使能电机
|
|
92
|
+
motor.enable()
|
|
93
|
+
|
|
94
|
+
# 4. 速度模式运动(100 RPM,顺时针)
|
|
95
|
+
motor.jog(speed=100, direction=Direction.CW, acceleration=10)
|
|
96
|
+
|
|
97
|
+
# 5. 等待2秒
|
|
98
|
+
import time
|
|
99
|
+
time.sleep(2)
|
|
100
|
+
|
|
101
|
+
# 6. 停止
|
|
102
|
+
motor.stop()
|
|
103
|
+
|
|
104
|
+
# 7. 位置模式运动(转动一圈)
|
|
105
|
+
motor.move_pulses(pulse_count=3200, speed=200, acceleration=20)
|
|
106
|
+
motor.wait_for_position(timeout=10)
|
|
107
|
+
|
|
108
|
+
# 8. 失能电机
|
|
109
|
+
motor.disable()
|
|
110
|
+
|
|
111
|
+
# 9. 关闭串口
|
|
112
|
+
ser.close()
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## API参考
|
|
116
|
+
|
|
117
|
+
### EmmDevice类
|
|
118
|
+
|
|
119
|
+
#### 初始化
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
EmmDevice(
|
|
123
|
+
serial_connection: Serial, # 串口连接对象
|
|
124
|
+
address: int = 1, # 电机地址 (1-255)
|
|
125
|
+
checksum_mode: ChecksumMode = ChecksumMode.FIXED, # 校验模式
|
|
126
|
+
delay: Optional[float] = None, # 通讯延迟(秒)
|
|
127
|
+
auto_test: bool = True, # 是否自动测试连接
|
|
128
|
+
)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
**参数说明:**
|
|
132
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
133
|
+
|------|------|--------|------|
|
|
134
|
+
| serial_connection | Serial | 必填 | pyserial的Serial对象 |
|
|
135
|
+
| address | int | 1 | 电机地址,范围1-255 |
|
|
136
|
+
| checksum_mode | ChecksumMode | FIXED | 校验模式:FIXED(0x6B)、XOR、CRC8 |
|
|
137
|
+
| delay | float | None | 命令间延迟时间 |
|
|
138
|
+
| auto_test | bool | True | 初始化时是否测试连接 |
|
|
139
|
+
|
|
140
|
+
#### 多电机控制
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
from serial import Serial
|
|
144
|
+
from emm_stepper import EmmDevice
|
|
145
|
+
|
|
146
|
+
# 创建串口连接(共享)
|
|
147
|
+
ser = Serial('COM9', 115200, timeout=0.1)
|
|
148
|
+
|
|
149
|
+
# 创建多个电机实例(不同地址)
|
|
150
|
+
motor1 = EmmDevice(ser, address=1)
|
|
151
|
+
motor2 = EmmDevice(ser, address=2)
|
|
152
|
+
motor3 = EmmDevice(ser, address=3)
|
|
153
|
+
|
|
154
|
+
# 分别控制
|
|
155
|
+
motor1.jog(speed=100)
|
|
156
|
+
motor2.jog(speed=200)
|
|
157
|
+
motor3.jog(speed=300)
|
|
158
|
+
|
|
159
|
+
# 关闭串口(由用户管理)
|
|
160
|
+
ser.close()
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
### 触发动作命令
|
|
166
|
+
|
|
167
|
+
#### calibrate_encoder()
|
|
168
|
+
触发编码器校准。电机将缓慢正转一圈然后反转一圈对编码器进行线性化校准。
|
|
169
|
+
|
|
170
|
+
```python
|
|
171
|
+
success = motor.calibrate_encoder()
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
#### restart()
|
|
175
|
+
重启电机。
|
|
176
|
+
|
|
177
|
+
```python
|
|
178
|
+
success = motor.restart()
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### zero_position()
|
|
182
|
+
将当前位置角度清零。
|
|
183
|
+
|
|
184
|
+
```python
|
|
185
|
+
success = motor.zero_position()
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
#### clear_protection()
|
|
189
|
+
解除堵转/过热/过流保护。
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
success = motor.clear_protection()
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### factory_reset()
|
|
196
|
+
恢复出厂设置。注意:恢复后需要断电重新上电,再空载校准电机编码器。
|
|
197
|
+
|
|
198
|
+
```python
|
|
199
|
+
success = motor.factory_reset()
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
### 运动控制命令
|
|
205
|
+
|
|
206
|
+
#### enable(sync=False)
|
|
207
|
+
使能电机(锁轴)。
|
|
208
|
+
|
|
209
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
210
|
+
|------|------|--------|------|
|
|
211
|
+
| sync | bool | False | 是否使用同步模式 |
|
|
212
|
+
|
|
213
|
+
```python
|
|
214
|
+
motor.enable()
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
#### disable(sync=False)
|
|
218
|
+
失能电机(松轴)。
|
|
219
|
+
|
|
220
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
221
|
+
|------|------|--------|------|
|
|
222
|
+
| sync | bool | False | 是否使用同步模式 |
|
|
223
|
+
|
|
224
|
+
```python
|
|
225
|
+
motor.disable()
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
#### jog(speed, direction, acceleration, sync)
|
|
229
|
+
速度模式运动。电机以指定速度持续运动,直到收到停止命令。
|
|
230
|
+
|
|
231
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
232
|
+
|------|------|--------|------|
|
|
233
|
+
| speed | int | 100 | 速度 (0-3000 RPM) |
|
|
234
|
+
| direction | Direction | CW | 运动方向 |
|
|
235
|
+
| acceleration | int | 10 | 加速度档位 (0-255) |
|
|
236
|
+
| sync | bool | False | 是否使用同步模式 |
|
|
237
|
+
|
|
238
|
+
```python
|
|
239
|
+
# 顺时针100RPM
|
|
240
|
+
motor.jog(speed=100, direction=Direction.CW, acceleration=10)
|
|
241
|
+
|
|
242
|
+
# 逆时针200RPM
|
|
243
|
+
motor.jog(speed=200, direction=Direction.CCW, acceleration=20)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
#### move_pulses(pulse_count, speed, direction, acceleration, motion_mode, sync)
|
|
247
|
+
位置模式运动(脉冲数)。默认16细分下,3200个脉冲=一圈360°。
|
|
248
|
+
|
|
249
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
250
|
+
|------|------|--------|------|
|
|
251
|
+
| pulse_count | int | 必填 | 脉冲数(正数CW,负数CCW) |
|
|
252
|
+
| speed | int | 100 | 速度 (0-3000 RPM) |
|
|
253
|
+
| direction | Direction | None | 运动方向(None则根据pulse_count正负判断) |
|
|
254
|
+
| acceleration | int | 10 | 加速度档位 (0-255) |
|
|
255
|
+
| motion_mode | MotionMode | RELATIVE_LAST | 运动模式 |
|
|
256
|
+
| sync | bool | False | 是否使用同步模式 |
|
|
257
|
+
|
|
258
|
+
```python
|
|
259
|
+
# 转动一圈(3200脉冲)
|
|
260
|
+
motor.move_pulses(pulse_count=3200, speed=200, acceleration=20)
|
|
261
|
+
|
|
262
|
+
# 反向转动半圈
|
|
263
|
+
motor.move_pulses(pulse_count=-1600, speed=200, acceleration=20)
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
#### move_degrees(degrees, speed, acceleration, motion_mode, microstep, sync)
|
|
267
|
+
位置模式运动(角度)。
|
|
268
|
+
|
|
269
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
270
|
+
|------|------|--------|------|
|
|
271
|
+
| degrees | float | 必填 | 角度(正数CW,负数CCW) |
|
|
272
|
+
| speed | int | 100 | 速度 (0-3000 RPM) |
|
|
273
|
+
| acceleration | int | 10 | 加速度档位 (0-255) |
|
|
274
|
+
| motion_mode | MotionMode | RELATIVE_LAST | 运动模式 |
|
|
275
|
+
| microstep | int | 16 | 细分值 |
|
|
276
|
+
| sync | bool | False | 是否使用同步模式 |
|
|
277
|
+
|
|
278
|
+
```python
|
|
279
|
+
# 转动90度
|
|
280
|
+
motor.move_degrees(degrees=90, speed=200, acceleration=20)
|
|
281
|
+
|
|
282
|
+
# 反向转动180度
|
|
283
|
+
motor.move_degrees(degrees=-180, speed=200, acceleration=20)
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
#### move_revolutions(revolutions, speed, acceleration, motion_mode, microstep, sync)
|
|
287
|
+
位置模式运动(圈数)。
|
|
288
|
+
|
|
289
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
290
|
+
|------|------|--------|------|
|
|
291
|
+
| revolutions | float | 必填 | 圈数(正数CW,负数CCW) |
|
|
292
|
+
| speed | int | 100 | 速度 (0-3000 RPM) |
|
|
293
|
+
| acceleration | int | 10 | 加速度档位 (0-255) |
|
|
294
|
+
| motion_mode | MotionMode | RELATIVE_LAST | 运动模式 |
|
|
295
|
+
| microstep | int | 16 | 细分值 |
|
|
296
|
+
| sync | bool | False | 是否使用同步模式 |
|
|
297
|
+
|
|
298
|
+
```python
|
|
299
|
+
# 转动2圈
|
|
300
|
+
motor.move_revolutions(revolutions=2, speed=300, acceleration=30)
|
|
301
|
+
|
|
302
|
+
# 反向转动0.5圈
|
|
303
|
+
motor.move_revolutions(revolutions=-0.5, speed=300, acceleration=30)
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
#### stop(sync=False)
|
|
307
|
+
立即停止电机。
|
|
308
|
+
|
|
309
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
310
|
+
|------|------|--------|------|
|
|
311
|
+
| sync | bool | False | 是否使用同步模式 |
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
motor.stop()
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
#### sync_move(device_params) [静态方法]
|
|
318
|
+
触发多机同步运动。使用广播地址发送,使所有缓存了命令的电机同步开始执行。
|
|
319
|
+
|
|
320
|
+
```python
|
|
321
|
+
# 先发送同步命令给各电机
|
|
322
|
+
motor1.jog(speed=100, sync=True)
|
|
323
|
+
motor2.jog(speed=200, sync=True)
|
|
324
|
+
|
|
325
|
+
# 触发同步运动
|
|
326
|
+
EmmDevice.sync_move(motor1.device_params)
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
### 原点回零命令
|
|
332
|
+
|
|
333
|
+
#### set_home_zero(store=True)
|
|
334
|
+
设置单圈回零的零点位置。将当前位置设置为单圈回零的零点位置。
|
|
335
|
+
|
|
336
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
337
|
+
|------|------|--------|------|
|
|
338
|
+
| store | bool | True | 是否存储(掉电不丢失) |
|
|
339
|
+
|
|
340
|
+
```python
|
|
341
|
+
motor.set_home_zero(store=True)
|
|
342
|
+
```
|
|
343
|
+
|
|
344
|
+
#### home(mode, sync)
|
|
345
|
+
触发回零。
|
|
346
|
+
|
|
347
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
348
|
+
|------|------|--------|------|
|
|
349
|
+
| mode | HomingMode | NEAREST | 回零模式 |
|
|
350
|
+
| sync | bool | False | 是否使用同步模式 |
|
|
351
|
+
|
|
352
|
+
**回零模式:**
|
|
353
|
+
| 模式 | 值 | 说明 |
|
|
354
|
+
|------|-----|------|
|
|
355
|
+
| NEAREST | 0 | 单圈就近回零 |
|
|
356
|
+
| DIRECTION | 1 | 单圈方向回零 |
|
|
357
|
+
| SENSORLESS | 2 | 无限位碰撞回零 |
|
|
358
|
+
| ENDSTOP | 3 | 限位开关回零 |
|
|
359
|
+
| ABS_ZERO | 4 | 回到绝对位置坐标零点 |
|
|
360
|
+
| LAST_POWER_OFF | 5 | 回到上次掉电位置 |
|
|
361
|
+
|
|
362
|
+
```python
|
|
363
|
+
# 单圈就近回零
|
|
364
|
+
motor.home(mode=HomingMode.NEAREST)
|
|
365
|
+
|
|
366
|
+
# 无限位碰撞回零
|
|
367
|
+
motor.home(mode=HomingMode.SENSORLESS)
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
#### stop_home()
|
|
371
|
+
强制中断并退出回零操作。
|
|
372
|
+
|
|
373
|
+
```python
|
|
374
|
+
motor.stop_home()
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
#### get_homing_status()
|
|
378
|
+
读取回零状态标志。
|
|
379
|
+
|
|
380
|
+
**返回值:** `HomingStatus` 对象
|
|
381
|
+
|
|
382
|
+
| 属性 | 类型 | 说明 |
|
|
383
|
+
|------|------|------|
|
|
384
|
+
| encoder_ready | bool | 编码器就绪 |
|
|
385
|
+
| calibrated | bool | 校准表就绪 |
|
|
386
|
+
| is_homing | bool | 正在回零 |
|
|
387
|
+
| homing_failed | bool | 回零失败 |
|
|
388
|
+
| over_temp | bool | 过热保护 |
|
|
389
|
+
| over_current | bool | 过流保护 |
|
|
390
|
+
| homing_state | str | 回零状态字符串 |
|
|
391
|
+
|
|
392
|
+
```python
|
|
393
|
+
status = motor.get_homing_status()
|
|
394
|
+
print(f"编码器就绪: {status.encoder_ready}")
|
|
395
|
+
print(f"已校准: {status.calibrated}")
|
|
396
|
+
print(f"回零状态: {status.homing_state}")
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
#### get_homing_params()
|
|
400
|
+
读取回零参数。
|
|
401
|
+
|
|
402
|
+
**返回值:** `HomingParams` 对象
|
|
403
|
+
|
|
404
|
+
```python
|
|
405
|
+
params = motor.get_homing_params()
|
|
406
|
+
print(f"回零模式: {params.homing_mode}")
|
|
407
|
+
print(f"回零速度: {params.homing_speed} RPM")
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
#### set_homing_params(params, store)
|
|
411
|
+
修改回零参数。
|
|
412
|
+
|
|
413
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
414
|
+
|------|------|--------|------|
|
|
415
|
+
| params | HomingParams | 必填 | 回零参数 |
|
|
416
|
+
| store | bool | True | 是否存储 |
|
|
417
|
+
|
|
418
|
+
```python
|
|
419
|
+
from emm_stepper.parameters import HomingParams
|
|
420
|
+
|
|
421
|
+
params = HomingParams(
|
|
422
|
+
homing_mode=HomingMode.SENSORLESS,
|
|
423
|
+
homing_speed=60,
|
|
424
|
+
homing_timeout=15000,
|
|
425
|
+
collision_speed=300,
|
|
426
|
+
collision_current=1000,
|
|
427
|
+
collision_time=100,
|
|
428
|
+
)
|
|
429
|
+
motor.set_homing_params(params, store=True)
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
### 读取系统参数命令
|
|
435
|
+
|
|
436
|
+
#### get_version()
|
|
437
|
+
读取固件版本和硬件版本。
|
|
438
|
+
|
|
439
|
+
**返回值:** `VersionParams` 对象
|
|
440
|
+
|
|
441
|
+
| 属性 | 类型 | 说明 |
|
|
442
|
+
|------|------|------|
|
|
443
|
+
| firmware_version | int | 固件版本号 |
|
|
444
|
+
| firmware_version_str | str | 固件版本字符串(如"V1.0.7") |
|
|
445
|
+
| hw_series | int | 硬件系列(0=X系列,1=Y系列) |
|
|
446
|
+
| hw_series_str | str | 硬件系列字符串 |
|
|
447
|
+
| hw_type | int | 硬件类型 |
|
|
448
|
+
| hw_type_str | str | 硬件类型字符串(如"X42") |
|
|
449
|
+
| hw_version | int | 硬件版本号 |
|
|
450
|
+
|
|
451
|
+
```python
|
|
452
|
+
version = motor.get_version()
|
|
453
|
+
print(f"固件版本: {version.firmware_version_str}")
|
|
454
|
+
print(f"硬件类型: {version.hw_type_str}")
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
#### get_motor_rh()
|
|
458
|
+
读取相电阻和相电感。
|
|
459
|
+
|
|
460
|
+
**返回值:** `MotorRHParams` 对象
|
|
461
|
+
|
|
462
|
+
| 属性 | 类型 | 说明 |
|
|
463
|
+
|------|------|------|
|
|
464
|
+
| phase_resistance | int | 相电阻 (mΩ) |
|
|
465
|
+
| phase_inductance | int | 相电感 (uH) |
|
|
466
|
+
|
|
467
|
+
```python
|
|
468
|
+
rh = motor.get_motor_rh()
|
|
469
|
+
print(f"相电阻: {rh.phase_resistance} mΩ")
|
|
470
|
+
print(f"相电感: {rh.phase_inductance} uH")
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
#### get_bus_voltage()
|
|
474
|
+
读取总线电压。
|
|
475
|
+
|
|
476
|
+
**返回值:** `int` - 总线电压 (mV)
|
|
477
|
+
|
|
478
|
+
```python
|
|
479
|
+
voltage = motor.get_bus_voltage()
|
|
480
|
+
print(f"总线电压: {voltage} mV ({voltage/1000:.2f} V)")
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
#### get_bus_current()
|
|
484
|
+
读取总线电流。
|
|
485
|
+
|
|
486
|
+
**返回值:** `int` - 总线电流 (mA)
|
|
487
|
+
|
|
488
|
+
```python
|
|
489
|
+
current = motor.get_bus_current()
|
|
490
|
+
print(f"总线电流: {current} mA")
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
#### get_phase_current()
|
|
494
|
+
读取相电流。
|
|
495
|
+
|
|
496
|
+
**返回值:** `int` - 相电流 (mA)
|
|
497
|
+
|
|
498
|
+
```python
|
|
499
|
+
current = motor.get_phase_current()
|
|
500
|
+
print(f"相电流: {current} mA")
|
|
501
|
+
```
|
|
502
|
+
|
|
503
|
+
#### get_encoder()
|
|
504
|
+
读取线性化编码器值。
|
|
505
|
+
|
|
506
|
+
**返回值:** `int` - 编码器值 (0-65535表示0-360°)
|
|
507
|
+
|
|
508
|
+
```python
|
|
509
|
+
encoder = motor.get_encoder()
|
|
510
|
+
angle = (encoder * 360) / 65536
|
|
511
|
+
print(f"编码器值: {encoder}, 角度: {angle:.2f}°")
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
#### get_encoder_degrees()
|
|
515
|
+
读取编码器角度。
|
|
516
|
+
|
|
517
|
+
**返回值:** `float` - 编码器角度 (度)
|
|
518
|
+
|
|
519
|
+
```python
|
|
520
|
+
angle = motor.get_encoder_degrees()
|
|
521
|
+
print(f"编码器角度: {angle:.2f}°")
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
#### get_pulse_count()
|
|
525
|
+
读取输入脉冲数。
|
|
526
|
+
|
|
527
|
+
**返回值:** `int` - 输入脉冲数(带符号)
|
|
528
|
+
|
|
529
|
+
```python
|
|
530
|
+
pulses = motor.get_pulse_count()
|
|
531
|
+
print(f"输入脉冲数: {pulses}")
|
|
532
|
+
```
|
|
533
|
+
|
|
534
|
+
#### get_target_position()
|
|
535
|
+
读取电机目标位置。
|
|
536
|
+
|
|
537
|
+
**返回值:** `float` - 目标位置角度 (度)
|
|
538
|
+
|
|
539
|
+
```python
|
|
540
|
+
position = motor.get_target_position()
|
|
541
|
+
print(f"目标位置: {position:.2f}°")
|
|
542
|
+
```
|
|
543
|
+
|
|
544
|
+
#### get_realtime_speed()
|
|
545
|
+
读取电机实时转速。
|
|
546
|
+
|
|
547
|
+
**返回值:** `int` - 实时转速 (RPM,带符号)
|
|
548
|
+
|
|
549
|
+
```python
|
|
550
|
+
speed = motor.get_realtime_speed()
|
|
551
|
+
print(f"实时转速: {speed} RPM")
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
#### get_realtime_position()
|
|
555
|
+
读取电机实时位置。
|
|
556
|
+
|
|
557
|
+
**返回值:** `float` - 实时位置角度 (度)
|
|
558
|
+
|
|
559
|
+
```python
|
|
560
|
+
position = motor.get_realtime_position()
|
|
561
|
+
print(f"实时位置: {position:.2f}°")
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
#### get_position_error()
|
|
565
|
+
读取电机位置误差。
|
|
566
|
+
|
|
567
|
+
**返回值:** `float` - 位置误差角度 (度)
|
|
568
|
+
|
|
569
|
+
```python
|
|
570
|
+
error = motor.get_position_error()
|
|
571
|
+
print(f"位置误差: {error:.4f}°")
|
|
572
|
+
```
|
|
573
|
+
|
|
574
|
+
#### get_temperature()
|
|
575
|
+
读取驱动温度。
|
|
576
|
+
|
|
577
|
+
**返回值:** `int` - 温度 (°C)
|
|
578
|
+
|
|
579
|
+
```python
|
|
580
|
+
temp = motor.get_temperature()
|
|
581
|
+
print(f"驱动温度: {temp}°C")
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
#### get_motor_status()
|
|
585
|
+
读取电机状态标志。
|
|
586
|
+
|
|
587
|
+
**返回值:** `MotorStatus` 对象
|
|
588
|
+
|
|
589
|
+
| 属性 | 类型 | 说明 |
|
|
590
|
+
|------|------|------|
|
|
591
|
+
| enabled | bool | 使能状态 |
|
|
592
|
+
| position_reached | bool | 位置到达 |
|
|
593
|
+
| stall_detected | bool | 堵转标志 |
|
|
594
|
+
| stall_protected | bool | 堵转保护 |
|
|
595
|
+
| left_limit | bool | 左限位开关状态 |
|
|
596
|
+
| right_limit | bool | 右限位开关状态 |
|
|
597
|
+
| power_off_flag | bool | 掉电标志 |
|
|
598
|
+
|
|
599
|
+
```python
|
|
600
|
+
status = motor.get_motor_status()
|
|
601
|
+
print(f"使能状态: {'已使能' if status.enabled else '未使能'}")
|
|
602
|
+
print(f"位置到达: {'是' if status.position_reached else '否'}")
|
|
603
|
+
print(f"堵转标志: {'是' if status.stall_detected else '否'}")
|
|
604
|
+
print(f"堵转保护: {'已触发' if status.stall_protected else '未触发'}")
|
|
605
|
+
```
|
|
606
|
+
|
|
607
|
+
#### get_pid()
|
|
608
|
+
读取PID参数。
|
|
609
|
+
|
|
610
|
+
**返回值:** `PIDParams` 对象
|
|
611
|
+
|
|
612
|
+
| 属性 | 类型 | 说明 |
|
|
613
|
+
|------|------|------|
|
|
614
|
+
| kp | int | 比例系数 |
|
|
615
|
+
| ki | int | 积分系数 |
|
|
616
|
+
| kd | int | 微分系数 |
|
|
617
|
+
|
|
618
|
+
```python
|
|
619
|
+
pid = motor.get_pid()
|
|
620
|
+
print(f"Kp: {pid.kp}, Ki: {pid.ki}, Kd: {pid.kd}")
|
|
621
|
+
```
|
|
622
|
+
|
|
623
|
+
#### get_config()
|
|
624
|
+
读取驱动配置参数。
|
|
625
|
+
|
|
626
|
+
**返回值:** `ConfigParams` 对象
|
|
627
|
+
|
|
628
|
+
| 属性 | 类型 | 说明 |
|
|
629
|
+
|------|------|------|
|
|
630
|
+
| motor_type | MotorType | 电机类型 |
|
|
631
|
+
| microstep | int | 细分值 |
|
|
632
|
+
| open_loop_current | int | 开环模式工作电流 (mA) |
|
|
633
|
+
| closed_loop_current | int | 闭环模式最大电流 (mA) |
|
|
634
|
+
| stall_protect | StallProtect | 堵转保护 |
|
|
635
|
+
| stall_speed | int | 堵转检测转速 (RPM) |
|
|
636
|
+
| stall_current | int | 堵转检测电流 (mA) |
|
|
637
|
+
| stall_time | int | 堵转检测时间 (ms) |
|
|
638
|
+
| position_window | int | 位置到达窗口 (*0.1度) |
|
|
639
|
+
|
|
640
|
+
```python
|
|
641
|
+
config = motor.get_config()
|
|
642
|
+
print(f"细分值: {config.microstep}")
|
|
643
|
+
print(f"闭环最大电流: {config.closed_loop_current} mA")
|
|
644
|
+
print(f"位置到达窗口: {config.position_window_deg}°")
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
#### get_system_status()
|
|
648
|
+
读取系统状态参数。
|
|
649
|
+
|
|
650
|
+
**返回值:** `SystemStatusParams` 对象
|
|
651
|
+
|
|
652
|
+
```python
|
|
653
|
+
status = motor.get_system_status()
|
|
654
|
+
print(f"总线电压: {status.bus_voltage} mV")
|
|
655
|
+
print(f"相电流: {status.phase_current} mA")
|
|
656
|
+
print(f"实时位置: {status.realtime_position_deg:.2f}°")
|
|
657
|
+
print(f"实时转速: {status.realtime_speed_rpm} RPM")
|
|
658
|
+
```
|
|
659
|
+
|
|
660
|
+
---
|
|
661
|
+
|
|
662
|
+
### 设置命令
|
|
663
|
+
|
|
664
|
+
#### set_id(new_id, store)
|
|
665
|
+
修改电机ID/地址。
|
|
666
|
+
|
|
667
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
668
|
+
|------|------|--------|------|
|
|
669
|
+
| new_id | int | 必填 | 新ID (1-255) |
|
|
670
|
+
| store | bool | True | 是否存储 |
|
|
671
|
+
|
|
672
|
+
```python
|
|
673
|
+
motor.set_id(new_id=2, store=True)
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
#### set_microstep(microstep, store)
|
|
677
|
+
修改细分值。
|
|
678
|
+
|
|
679
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
680
|
+
|------|------|--------|------|
|
|
681
|
+
| microstep | int | 必填 | 细分值 (1-256) |
|
|
682
|
+
| store | bool | True | 是否存储 |
|
|
683
|
+
|
|
684
|
+
```python
|
|
685
|
+
motor.set_microstep(microstep=32, store=True)
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
#### set_loop_mode(closed_loop, store)
|
|
689
|
+
修改开环/闭环控制模式。
|
|
690
|
+
|
|
691
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
692
|
+
|------|------|--------|------|
|
|
693
|
+
| closed_loop | bool | True | True为闭环,False为开环 |
|
|
694
|
+
| store | bool | True | 是否存储 |
|
|
695
|
+
|
|
696
|
+
```python
|
|
697
|
+
motor.set_loop_mode(closed_loop=True, store=True)
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
#### set_open_loop_current(current_ma, store)
|
|
701
|
+
修改开环模式工作电流。
|
|
702
|
+
|
|
703
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
704
|
+
|------|------|--------|------|
|
|
705
|
+
| current_ma | int | 必填 | 电流 (0-5000 mA) |
|
|
706
|
+
| store | bool | True | 是否存储 |
|
|
707
|
+
|
|
708
|
+
```python
|
|
709
|
+
motor.set_open_loop_current(current_ma=1200, store=True)
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
#### set_closed_loop_current(current_ma, store)
|
|
713
|
+
修改闭环模式最大电流。
|
|
714
|
+
|
|
715
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
716
|
+
|------|------|--------|------|
|
|
717
|
+
| current_ma | int | 必填 | 电流 (0-5000 mA) |
|
|
718
|
+
| store | bool | True | 是否存储 |
|
|
719
|
+
|
|
720
|
+
```python
|
|
721
|
+
motor.set_closed_loop_current(current_ma=3000, store=True)
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
#### set_pid(params, store)
|
|
725
|
+
修改PID参数。
|
|
726
|
+
|
|
727
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
728
|
+
|------|------|--------|------|
|
|
729
|
+
| params | PIDParams | 必填 | PID参数 |
|
|
730
|
+
| store | bool | True | 是否存储 |
|
|
731
|
+
|
|
732
|
+
```python
|
|
733
|
+
from emm_stepper.parameters import PIDParams
|
|
734
|
+
|
|
735
|
+
params = PIDParams(kp=18000, ki=10, kd=18000)
|
|
736
|
+
motor.set_pid(params, store=True)
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
#### set_motor_direction(direction, store)
|
|
740
|
+
修改电机运动正方向。
|
|
741
|
+
|
|
742
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
743
|
+
|------|------|--------|------|
|
|
744
|
+
| direction | Direction | CW | 运动方向 |
|
|
745
|
+
| store | bool | True | 是否存储 |
|
|
746
|
+
|
|
747
|
+
```python
|
|
748
|
+
motor.set_motor_direction(direction=Direction.CW, store=True)
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
#### set_position_window(window_deg, store)
|
|
752
|
+
修改位置到达窗口。
|
|
753
|
+
|
|
754
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
755
|
+
|------|------|--------|------|
|
|
756
|
+
| window_deg | float | 0.8 | 位置到达窗口 (度) |
|
|
757
|
+
| store | bool | True | 是否存储 |
|
|
758
|
+
|
|
759
|
+
```python
|
|
760
|
+
motor.set_position_window(window_deg=0.8, store=True)
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
#### set_heartbeat_time(time_ms, store)
|
|
764
|
+
修改心跳保护功能时间。
|
|
765
|
+
|
|
766
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
767
|
+
|------|------|--------|------|
|
|
768
|
+
| time_ms | int | 0 | 心跳保护时间 (ms),0表示关闭 |
|
|
769
|
+
| store | bool | True | 是否存储 |
|
|
770
|
+
|
|
771
|
+
```python
|
|
772
|
+
# 设置1秒心跳保护
|
|
773
|
+
motor.set_heartbeat_time(time_ms=1000, store=True)
|
|
774
|
+
|
|
775
|
+
# 关闭心跳保护
|
|
776
|
+
motor.set_heartbeat_time(time_ms=0, store=True)
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
#### set_auto_run(params)
|
|
780
|
+
存储一组速度参数,上电自动运行。
|
|
781
|
+
|
|
782
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
783
|
+
|------|------|--------|------|
|
|
784
|
+
| params | AutoRunParams | 必填 | 自动运行参数 |
|
|
785
|
+
|
|
786
|
+
```python
|
|
787
|
+
from emm_stepper.parameters import AutoRunParams
|
|
788
|
+
|
|
789
|
+
params = AutoRunParams(
|
|
790
|
+
store=True,
|
|
791
|
+
direction=Direction.CW,
|
|
792
|
+
speed=600,
|
|
793
|
+
acceleration=100,
|
|
794
|
+
enable_en_control=True,
|
|
795
|
+
)
|
|
796
|
+
motor.set_auto_run(params)
|
|
797
|
+
```
|
|
798
|
+
|
|
799
|
+
#### set_config(params, store)
|
|
800
|
+
修改驱动配置参数。
|
|
801
|
+
|
|
802
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
803
|
+
|------|------|--------|------|
|
|
804
|
+
| params | ConfigParams | 必填 | 配置参数 |
|
|
805
|
+
| store | bool | True | 是否存储 |
|
|
806
|
+
|
|
807
|
+
```python
|
|
808
|
+
config = motor.get_config()
|
|
809
|
+
config.microstep = 32
|
|
810
|
+
config.closed_loop_current = 3500
|
|
811
|
+
motor.set_config(config, store=True)
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
#### set_scale_input(enable, store)
|
|
815
|
+
修改命令速度值是否缩小10倍输入。
|
|
816
|
+
|
|
817
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
818
|
+
|------|------|--------|------|
|
|
819
|
+
| enable | bool | False | 是否使能(使能后输入1RPM实际为0.1RPM) |
|
|
820
|
+
| store | bool | True | 是否存储 |
|
|
821
|
+
|
|
822
|
+
```python
|
|
823
|
+
motor.set_scale_input(enable=True, store=True)
|
|
824
|
+
```
|
|
825
|
+
|
|
826
|
+
#### set_lock_button(lock, store)
|
|
827
|
+
修改锁定按键功能。
|
|
828
|
+
|
|
829
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
830
|
+
|------|------|--------|------|
|
|
831
|
+
| lock | bool | False | 是否锁定 |
|
|
832
|
+
| store | bool | True | 是否存储 |
|
|
833
|
+
|
|
834
|
+
```python
|
|
835
|
+
motor.set_lock_button(lock=True, store=True)
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
#### broadcast_get_id(serial_connection) [静态方法]
|
|
839
|
+
广播读取ID地址。当忘记电机ID地址时,可以单独接线该电机,广播读取该电机的地址。
|
|
840
|
+
|
|
841
|
+
```python
|
|
842
|
+
motor_id = EmmDevice.broadcast_get_id(ser)
|
|
843
|
+
print(f"电机ID: {motor_id}")
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
---
|
|
847
|
+
|
|
848
|
+
### 便捷方法
|
|
849
|
+
|
|
850
|
+
#### is_enabled()
|
|
851
|
+
检查电机是否使能。
|
|
852
|
+
|
|
853
|
+
**返回值:** `bool`
|
|
854
|
+
|
|
855
|
+
```python
|
|
856
|
+
if motor.is_enabled():
|
|
857
|
+
print("电机已使能")
|
|
858
|
+
```
|
|
859
|
+
|
|
860
|
+
#### is_position_reached()
|
|
861
|
+
检查是否到达目标位置。
|
|
862
|
+
|
|
863
|
+
**返回值:** `bool`
|
|
864
|
+
|
|
865
|
+
```python
|
|
866
|
+
if motor.is_position_reached():
|
|
867
|
+
print("已到达目标位置")
|
|
868
|
+
```
|
|
869
|
+
|
|
870
|
+
#### is_stalled()
|
|
871
|
+
检查是否堵转。
|
|
872
|
+
|
|
873
|
+
**返回值:** `bool`
|
|
874
|
+
|
|
875
|
+
```python
|
|
876
|
+
if motor.is_stalled():
|
|
877
|
+
print("电机堵转!")
|
|
878
|
+
motor.clear_protection()
|
|
879
|
+
```
|
|
880
|
+
|
|
881
|
+
#### wait_for_position(timeout, poll_interval)
|
|
882
|
+
等待电机到达目标位置。
|
|
883
|
+
|
|
884
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
885
|
+
|------|------|--------|------|
|
|
886
|
+
| timeout | float | 30.0 | 超时时间 (秒) |
|
|
887
|
+
| poll_interval | float | 0.1 | 轮询间隔 (秒) |
|
|
888
|
+
|
|
889
|
+
**返回值:** `bool` - True表示到达位置,False表示超时
|
|
890
|
+
|
|
891
|
+
```python
|
|
892
|
+
motor.move_pulses(pulse_count=3200, speed=200)
|
|
893
|
+
if motor.wait_for_position(timeout=10):
|
|
894
|
+
print("到达目标位置")
|
|
895
|
+
else:
|
|
896
|
+
print("超时未到达")
|
|
897
|
+
```
|
|
898
|
+
|
|
899
|
+
---
|
|
900
|
+
|
|
901
|
+
## 参数类
|
|
902
|
+
|
|
903
|
+
### Direction (枚举)
|
|
904
|
+
运动方向。
|
|
905
|
+
|
|
906
|
+
| 值 | 说明 |
|
|
907
|
+
|-----|------|
|
|
908
|
+
| CW | 顺时针 |
|
|
909
|
+
| CCW | 逆时针 |
|
|
910
|
+
|
|
911
|
+
### MotionMode (枚举)
|
|
912
|
+
位置模式运动类型。
|
|
913
|
+
|
|
914
|
+
| 值 | 说明 |
|
|
915
|
+
|-----|------|
|
|
916
|
+
| RELATIVE_LAST | 相对于上次目标位置 |
|
|
917
|
+
| ABSOLUTE | 绝对位置 |
|
|
918
|
+
| RELATIVE_CURRENT | 相对于当前位置 |
|
|
919
|
+
|
|
920
|
+
### HomingMode (枚举)
|
|
921
|
+
回零模式。
|
|
922
|
+
|
|
923
|
+
| 值 | 说明 |
|
|
924
|
+
|-----|------|
|
|
925
|
+
| NEAREST | 单圈就近回零 |
|
|
926
|
+
| DIRECTION | 单圈方向回零 |
|
|
927
|
+
| SENSORLESS | 无限位碰撞回零 |
|
|
928
|
+
| ENDSTOP | 限位开关回零 |
|
|
929
|
+
| ABS_ZERO | 回到绝对位置坐标零点 |
|
|
930
|
+
| LAST_POWER_OFF | 回到上次掉电位置 |
|
|
931
|
+
|
|
932
|
+
### ChecksumMode (枚举)
|
|
933
|
+
校验模式。
|
|
934
|
+
|
|
935
|
+
| 值 | 说明 |
|
|
936
|
+
|-----|------|
|
|
937
|
+
| FIXED | 固定值0x6B |
|
|
938
|
+
| XOR | 异或校验 |
|
|
939
|
+
| CRC8 | CRC8校验 |
|
|
940
|
+
|
|
941
|
+
### MotorType (枚举)
|
|
942
|
+
电机类型。
|
|
943
|
+
|
|
944
|
+
| 值 | 说明 |
|
|
945
|
+
|-----|------|
|
|
946
|
+
| OPEN_LOOP | 开环模式 |
|
|
947
|
+
| CLOSED_LOOP | 闭环模式 |
|
|
948
|
+
|
|
949
|
+
### StallProtect (枚举)
|
|
950
|
+
堵转保护模式。
|
|
951
|
+
|
|
952
|
+
| 值 | 说明 |
|
|
953
|
+
|-----|------|
|
|
954
|
+
| DISABLED | 禁用 |
|
|
955
|
+
| ENABLED | 启用 |
|
|
956
|
+
|
|
957
|
+
---
|
|
958
|
+
|
|
959
|
+
## 使用示例
|
|
960
|
+
|
|
961
|
+
### 基本速度控制
|
|
962
|
+
|
|
963
|
+
```python
|
|
964
|
+
from serial import Serial
|
|
965
|
+
from emm_stepper import EmmDevice, Direction
|
|
966
|
+
|
|
967
|
+
ser = Serial('COM9', 115200, timeout=0.1)
|
|
968
|
+
motor = EmmDevice(ser, address=1)
|
|
969
|
+
|
|
970
|
+
# 使能电机
|
|
971
|
+
motor.enable()
|
|
972
|
+
|
|
973
|
+
# 顺时针100RPM运行
|
|
974
|
+
motor.jog(speed=100, direction=Direction.CW, acceleration=10)
|
|
975
|
+
|
|
976
|
+
import time
|
|
977
|
+
time.sleep(3)
|
|
978
|
+
|
|
979
|
+
# 停止
|
|
980
|
+
motor.stop()
|
|
981
|
+
|
|
982
|
+
# 失能电机
|
|
983
|
+
motor.disable()
|
|
984
|
+
ser.close()
|
|
985
|
+
```
|
|
986
|
+
|
|
987
|
+
### 位置控制
|
|
988
|
+
|
|
989
|
+
```python
|
|
990
|
+
from serial import Serial
|
|
991
|
+
from emm_stepper import EmmDevice, MotionMode
|
|
992
|
+
|
|
993
|
+
ser = Serial('COM9', 115200, timeout=0.1)
|
|
994
|
+
motor = EmmDevice(ser, address=1)
|
|
995
|
+
|
|
996
|
+
motor.enable()
|
|
997
|
+
|
|
998
|
+
# 转动90度
|
|
999
|
+
motor.move_degrees(degrees=90, speed=200, acceleration=20)
|
|
1000
|
+
motor.wait_for_position(timeout=10)
|
|
1001
|
+
|
|
1002
|
+
# 转动到绝对位置180度
|
|
1003
|
+
motor.move_degrees(degrees=180, speed=200, motion_mode=MotionMode.ABSOLUTE)
|
|
1004
|
+
motor.wait_for_position(timeout=10)
|
|
1005
|
+
|
|
1006
|
+
# 转动2圈
|
|
1007
|
+
motor.move_revolutions(revolutions=2, speed=300)
|
|
1008
|
+
motor.wait_for_position(timeout=10)
|
|
1009
|
+
|
|
1010
|
+
motor.disable()
|
|
1011
|
+
ser.close()
|
|
1012
|
+
```
|
|
1013
|
+
|
|
1014
|
+
### 堵转检测与处理
|
|
1015
|
+
|
|
1016
|
+
```python
|
|
1017
|
+
from serial import Serial
|
|
1018
|
+
from emm_stepper import EmmDevice, Direction
|
|
1019
|
+
import time
|
|
1020
|
+
|
|
1021
|
+
ser = Serial('COM9', 115200, timeout=0.1)
|
|
1022
|
+
motor = EmmDevice(ser, address=1)
|
|
1023
|
+
|
|
1024
|
+
motor.enable()
|
|
1025
|
+
|
|
1026
|
+
# 以100RPM运行
|
|
1027
|
+
motor.jog(speed=100, direction=Direction.CW, acceleration=10)
|
|
1028
|
+
|
|
1029
|
+
# 监测堵转
|
|
1030
|
+
while True:
|
|
1031
|
+
time.sleep(0.1)
|
|
1032
|
+
if motor.is_stalled():
|
|
1033
|
+
print("检测到堵转!")
|
|
1034
|
+
motor.stop()
|
|
1035
|
+
motor.clear_protection()
|
|
1036
|
+
|
|
1037
|
+
# 反向转动3200脉冲
|
|
1038
|
+
motor.move_pulses(
|
|
1039
|
+
pulse_count=3200,
|
|
1040
|
+
speed=100,
|
|
1041
|
+
direction=Direction.CCW,
|
|
1042
|
+
acceleration=10
|
|
1043
|
+
)
|
|
1044
|
+
motor.wait_for_position(timeout=10)
|
|
1045
|
+
break
|
|
1046
|
+
|
|
1047
|
+
motor.disable()
|
|
1048
|
+
ser.close()
|
|
1049
|
+
```
|
|
1050
|
+
|
|
1051
|
+
### 原点回零
|
|
1052
|
+
|
|
1053
|
+
```python
|
|
1054
|
+
from serial import Serial
|
|
1055
|
+
from emm_stepper import EmmDevice, HomingMode
|
|
1056
|
+
import time
|
|
1057
|
+
|
|
1058
|
+
ser = Serial('COM9', 115200, timeout=0.1)
|
|
1059
|
+
motor = EmmDevice(ser, address=1)
|
|
1060
|
+
|
|
1061
|
+
motor.enable()
|
|
1062
|
+
|
|
1063
|
+
# 设置当前位置为零点
|
|
1064
|
+
motor.set_home_zero(store=True)
|
|
1065
|
+
|
|
1066
|
+
# 移动一段距离
|
|
1067
|
+
motor.move_degrees(degrees=180, speed=200)
|
|
1068
|
+
motor.wait_for_position(timeout=10)
|
|
1069
|
+
|
|
1070
|
+
# 回零
|
|
1071
|
+
motor.home(mode=HomingMode.NEAREST)
|
|
1072
|
+
|
|
1073
|
+
# 等待回零完成
|
|
1074
|
+
while True:
|
|
1075
|
+
time.sleep(0.1)
|
|
1076
|
+
status = motor.get_homing_status()
|
|
1077
|
+
if not status.is_homing:
|
|
1078
|
+
if status.homing_failed:
|
|
1079
|
+
print("回零失败")
|
|
1080
|
+
else:
|
|
1081
|
+
print("回零完成")
|
|
1082
|
+
break
|
|
1083
|
+
|
|
1084
|
+
motor.disable()
|
|
1085
|
+
ser.close()
|
|
1086
|
+
```
|
|
1087
|
+
|
|
1088
|
+
### 多电机同步控制
|
|
1089
|
+
|
|
1090
|
+
```python
|
|
1091
|
+
from serial import Serial
|
|
1092
|
+
from emm_stepper import EmmDevice, Direction
|
|
1093
|
+
|
|
1094
|
+
ser = Serial('COM9', 115200, timeout=0.1)
|
|
1095
|
+
|
|
1096
|
+
# 创建多个电机实例
|
|
1097
|
+
motor1 = EmmDevice(ser, address=1)
|
|
1098
|
+
motor2 = EmmDevice(ser, address=2)
|
|
1099
|
+
|
|
1100
|
+
motor1.enable()
|
|
1101
|
+
motor2.enable()
|
|
1102
|
+
|
|
1103
|
+
# 发送同步命令(不立即执行)
|
|
1104
|
+
motor1.jog(speed=100, direction=Direction.CW, sync=True)
|
|
1105
|
+
motor2.jog(speed=200, direction=Direction.CCW, sync=True)
|
|
1106
|
+
|
|
1107
|
+
# 触发同步执行
|
|
1108
|
+
EmmDevice.sync_move(motor1.device_params)
|
|
1109
|
+
|
|
1110
|
+
import time
|
|
1111
|
+
time.sleep(3)
|
|
1112
|
+
|
|
1113
|
+
# 同步停止
|
|
1114
|
+
motor1.stop(sync=True)
|
|
1115
|
+
motor2.stop(sync=True)
|
|
1116
|
+
EmmDevice.sync_move(motor1.device_params)
|
|
1117
|
+
|
|
1118
|
+
motor1.disable()
|
|
1119
|
+
motor2.disable()
|
|
1120
|
+
ser.close()
|
|
1121
|
+
```
|
|
1122
|
+
|
|
1123
|
+
### 读取电机状态
|
|
1124
|
+
|
|
1125
|
+
```python
|
|
1126
|
+
from serial import Serial
|
|
1127
|
+
from emm_stepper import EmmDevice
|
|
1128
|
+
|
|
1129
|
+
ser = Serial('COM9', 115200, timeout=0.1)
|
|
1130
|
+
motor = EmmDevice(ser, address=1)
|
|
1131
|
+
|
|
1132
|
+
# 读取版本信息
|
|
1133
|
+
version = motor.get_version()
|
|
1134
|
+
print(f"固件版本: {version.firmware_version_str}")
|
|
1135
|
+
print(f"硬件类型: {version.hw_type_str}")
|
|
1136
|
+
|
|
1137
|
+
# 读取电气参数
|
|
1138
|
+
print(f"总线电压: {motor.get_bus_voltage()} mV")
|
|
1139
|
+
print(f"相电流: {motor.get_phase_current()} mA")
|
|
1140
|
+
print(f"驱动温度: {motor.get_temperature()}°C")
|
|
1141
|
+
|
|
1142
|
+
# 读取位置信息
|
|
1143
|
+
print(f"编码器角度: {motor.get_encoder_degrees():.2f}°")
|
|
1144
|
+
print(f"实时位置: {motor.get_realtime_position():.2f}°")
|
|
1145
|
+
print(f"实时转速: {motor.get_realtime_speed()} RPM")
|
|
1146
|
+
|
|
1147
|
+
# 读取电机状态
|
|
1148
|
+
status = motor.get_motor_status()
|
|
1149
|
+
print(f"使能状态: {'已使能' if status.enabled else '未使能'}")
|
|
1150
|
+
print(f"位置到达: {'是' if status.position_reached else '否'}")
|
|
1151
|
+
print(f"堵转标志: {'是' if status.stall_detected else '否'}")
|
|
1152
|
+
|
|
1153
|
+
ser.close()
|
|
1154
|
+
```
|
|
1155
|
+
|
|
1156
|
+
### 修改配置参数
|
|
1157
|
+
|
|
1158
|
+
```python
|
|
1159
|
+
from serial import Serial
|
|
1160
|
+
from emm_stepper import EmmDevice
|
|
1161
|
+
from emm_stepper.parameters import PIDParams
|
|
1162
|
+
|
|
1163
|
+
ser = Serial('COM9', 115200, timeout=0.1)
|
|
1164
|
+
motor = EmmDevice(ser, address=1)
|
|
1165
|
+
|
|
1166
|
+
# 修改细分值
|
|
1167
|
+
motor.set_microstep(microstep=32, store=True)
|
|
1168
|
+
|
|
1169
|
+
# 修改闭环电流
|
|
1170
|
+
motor.set_closed_loop_current(current_ma=3000, store=True)
|
|
1171
|
+
|
|
1172
|
+
# 修改PID参数
|
|
1173
|
+
pid = PIDParams(kp=18000, ki=10, kd=18000)
|
|
1174
|
+
motor.set_pid(pid, store=True)
|
|
1175
|
+
|
|
1176
|
+
# 修改位置到达窗口
|
|
1177
|
+
motor.set_position_window(window_deg=0.5, store=True)
|
|
1178
|
+
|
|
1179
|
+
# 读取并修改配置
|
|
1180
|
+
config = motor.get_config()
|
|
1181
|
+
print(f"当前细分: {config.microstep}")
|
|
1182
|
+
config.microstep = 64
|
|
1183
|
+
motor.set_config(config, store=True)
|
|
1184
|
+
|
|
1185
|
+
ser.close()
|
|
1186
|
+
```
|
|
1187
|
+
|
|
1188
|
+
---
|
|
1189
|
+
|
|
1190
|
+
## 注意事项
|
|
1191
|
+
|
|
1192
|
+
### 通讯设置
|
|
1193
|
+
|
|
1194
|
+
1. **波特率**:默认115200,支持9600-921600
|
|
1195
|
+
2. **超时时间**:建议设置0.1秒以上
|
|
1196
|
+
3. **校验模式**:默认使用固定值0x6B,需与电机设置一致
|
|
1197
|
+
|
|
1198
|
+
### 电机使用
|
|
1199
|
+
|
|
1200
|
+
1. **首次使用**:需要进行编码器校准(`calibrate_encoder()`)
|
|
1201
|
+
2. **堵转保护**:触发后需要调用`clear_protection()`解除
|
|
1202
|
+
3. **位置模式**:运动完成后建议使用`wait_for_position()`等待到位
|
|
1203
|
+
4. **速度范围**:0-3000 RPM
|
|
1204
|
+
5. **加速度范围**:0-255档位
|
|
1205
|
+
|
|
1206
|
+
### 多电机控制
|
|
1207
|
+
|
|
1208
|
+
1. **地址设置**:每个电机需要设置不同的地址(1-255)
|
|
1209
|
+
2. **串口共享**:多个电机可以共享同一个串口连接
|
|
1210
|
+
3. **同步运动**:使用`sync=True`参数发送命令,然后调用`sync_move()`触发
|
|
1211
|
+
|
|
1212
|
+
### 回零功能
|
|
1213
|
+
|
|
1214
|
+
1. **单圈回零**:需要先设置零点位置(`set_home_zero()`)
|
|
1215
|
+
2. **碰撞回零**:需要设置合适的碰撞检测参数
|
|
1216
|
+
3. **限位回零**:需要正确接线限位开关
|
|
1217
|
+
|
|
1218
|
+
### 错误处理
|
|
1219
|
+
|
|
1220
|
+
```python
|
|
1221
|
+
try:
|
|
1222
|
+
motor = EmmDevice(ser, address=1)
|
|
1223
|
+
except Exception as e:
|
|
1224
|
+
print(f"连接失败: {e}")
|
|
1225
|
+
|
|
1226
|
+
# 检查命令执行结果
|
|
1227
|
+
if not motor.enable():
|
|
1228
|
+
print("使能失败")
|
|
1229
|
+
|
|
1230
|
+
# 检查堵转
|
|
1231
|
+
if motor.is_stalled():
|
|
1232
|
+
motor.clear_protection()
|
|
1233
|
+
```
|
|
1234
|
+
|
|
1235
|
+
---
|
|
1236
|
+
|
|
1237
|
+
## 许可证
|
|
1238
|
+
|
|
1239
|
+
MIT License
|
|
1240
|
+
|