smartpi 0.1.0__tar.gz
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.
- smartpi-0.1.0/PKG-INFO +12 -0
- smartpi-0.1.0/pyproject.toml +23 -0
- smartpi-0.1.0/setup.cfg +4 -0
- smartpi-0.1.0/src/smartpi/__init__.py +4 -0
- smartpi-0.1.0/src/smartpi/app_module.py +119 -0
- smartpi-0.1.0/src/smartpi/module.py +503 -0
- smartpi-0.1.0/src/smartpi/mpu6500.py +130 -0
- smartpi-0.1.0/src/smartpi.egg-info/PKG-INFO +12 -0
- smartpi-0.1.0/src/smartpi.egg-info/SOURCES.txt +10 -0
- smartpi-0.1.0/src/smartpi.egg-info/dependency_links.txt +1 -0
- smartpi-0.1.0/src/smartpi.egg-info/top_level.txt +1 -0
- smartpi-0.1.0/tests/test_module.py +48 -0
smartpi-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: smartpi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A library use for H2-RCU
|
|
5
|
+
Author-email: Driver_cai <1547363120@qq.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/Drvier_cai/smartpi
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/Driver/smartpi/issues
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.7
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=42"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "smartpi"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name="Driver_cai", email="1547363120@qq.com" },
|
|
10
|
+
]
|
|
11
|
+
description = "A library use for H2-RCU"
|
|
12
|
+
readme = "README.md"
|
|
13
|
+
requires-python = ">=3.7"
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
"Homepage" = "https://github.com/Drvier_cai/smartpi"
|
|
22
|
+
"Bug Tracker" = "https://github.com/Driver/smartpi/issues"
|
|
23
|
+
|
smartpi-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
import time
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
from smartpi.module import Uart3_funtions,base_driver
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class app_funtion:
|
|
8
|
+
#马达编码读取 port:连接M端口;
|
|
9
|
+
def read_motor_code(port:bytes) -> Optional[bytes]:
|
|
10
|
+
motor_str=[0xA0, 0x01, 0x01, 0xBE]
|
|
11
|
+
motor_str[0]=0XA0+port
|
|
12
|
+
response = Uart3_funtions.single_operate_sensor(motor_str)
|
|
13
|
+
if response:
|
|
14
|
+
return 0
|
|
15
|
+
else:
|
|
16
|
+
return -1
|
|
17
|
+
|
|
18
|
+
#马达速度控制 port:连接M端口;speed:0~100
|
|
19
|
+
def write_motor_speed(port:bytes,speed:bytes) -> Optional[bytes]:
|
|
20
|
+
motor_str=[0xA0, 0x01, 0x02, 0x71, 0x00, 0xBE]
|
|
21
|
+
motor_str[0]=0XA0+port
|
|
22
|
+
motor_str[4]=speed
|
|
23
|
+
response = Uart3_funtions.single_operate_sensor(motor_str)
|
|
24
|
+
if response:
|
|
25
|
+
return 0
|
|
26
|
+
else:
|
|
27
|
+
return -1
|
|
28
|
+
|
|
29
|
+
#马达速度编码控制 port:连接M端口;speed:0~100;code:0~65535
|
|
30
|
+
def motor_servoctl(port:bytes,speed:bytes,code:int) -> Optional[bytes]:
|
|
31
|
+
motor_str=[0xA0, 0x01, 0x04, 0x81, 0x00, 0x81, 0x00, 0x00, 0xBE]
|
|
32
|
+
motor_str[0]=0XA0+port
|
|
33
|
+
motor_str[4]=speed
|
|
34
|
+
motor_str[6]=code//256
|
|
35
|
+
motor_str[7]=code%256
|
|
36
|
+
response = Uart3_funtions.single_operate_sensor(motor_str)
|
|
37
|
+
if response:
|
|
38
|
+
return 0
|
|
39
|
+
else:
|
|
40
|
+
return -1
|
|
41
|
+
|
|
42
|
+
#马达方向控制 port:连接M端口;dir:
|
|
43
|
+
def write_motor_dir(port:bytes,direc:bytes) -> Optional[bytes]:
|
|
44
|
+
motor_str=[0xA0, 0x01, 0x06, 0x71, 0x00, 0xBE]
|
|
45
|
+
motor_str[0]=0XA0+port
|
|
46
|
+
motor_str[4]=direc
|
|
47
|
+
response = Uart3_funtions.single_operate_sensor(motor_str)
|
|
48
|
+
if response:
|
|
49
|
+
return 0
|
|
50
|
+
else:
|
|
51
|
+
return -1
|
|
52
|
+
|
|
53
|
+
#彩灯控制 port:连接P端口;command:0:关灯;1:红;2:绿;3:蓝;4:黄;5:紫;6:青;7:白
|
|
54
|
+
def color_lamp_operate(port:bytes,command:bytes) -> Optional[bytes]:
|
|
55
|
+
color_lamp_str=[0xA0, 0x05, 0x00, 0xBE]
|
|
56
|
+
color_lamp_str[0]=0XA0+port
|
|
57
|
+
color_lamp_str[2]=command
|
|
58
|
+
response = Uart3_funtions.single_operate_sensor(color_lamp_str)
|
|
59
|
+
if response:
|
|
60
|
+
return 0
|
|
61
|
+
else:
|
|
62
|
+
return -1
|
|
63
|
+
|
|
64
|
+
#触碰传感器 port:连接P端口
|
|
65
|
+
def read_switch(port:bytes) -> Optional[bytes]:
|
|
66
|
+
read_sw_str=[0xA0, 0x03, 0x01, 0xBE]
|
|
67
|
+
read_sw_str[0]=0XA0+port
|
|
68
|
+
response = Uart3_funtions.single_operate_sensor(read_sw_str)
|
|
69
|
+
if response:
|
|
70
|
+
return 0
|
|
71
|
+
else:
|
|
72
|
+
return -1
|
|
73
|
+
|
|
74
|
+
#光电读取 port:连接P端口;command:1:读取;2:开灯;3:关灯;
|
|
75
|
+
def light_operate(port:bytes,command:bytes) -> Optional[bytes]:
|
|
76
|
+
light_str=[0xA0, 0x02, 0x00, 0xBE]
|
|
77
|
+
light_str[0]=0XA0+port
|
|
78
|
+
light_str[2]=command
|
|
79
|
+
response = Uart3_funtions.single_operate_sensor(light_str)
|
|
80
|
+
if response:
|
|
81
|
+
return 0
|
|
82
|
+
else:
|
|
83
|
+
return -1
|
|
84
|
+
|
|
85
|
+
#温湿度读取 port:连接P端口;command:0:读取湿度;1:读取温度;
|
|
86
|
+
def humiture_operate(port:bytes,command:bytes) -> Optional[bytes]:
|
|
87
|
+
humiture_str=[0xA0, 0x0C, 0x01, 0x71, 0x00, 0xBE]
|
|
88
|
+
humiture_str[0]=0XA0+port
|
|
89
|
+
humiture_str[2]=command
|
|
90
|
+
response = Uart3_funtions.single_operate_sensor(humiture_str)
|
|
91
|
+
if response:
|
|
92
|
+
return 0
|
|
93
|
+
else:
|
|
94
|
+
return -1
|
|
95
|
+
|
|
96
|
+
#超声波读取 port:连接P端口;command:1:读取;
|
|
97
|
+
def ultrasonic_operate(port:bytes,command:bytes) -> Optional[bytes]:
|
|
98
|
+
ultrasonic_str=[0xA0, 0x06, 0x00, 0xBE]
|
|
99
|
+
ultrasonic_str[0]=0XA0+port
|
|
100
|
+
ultrasonic_str[2]=command
|
|
101
|
+
response = Uart3_funtions.single_operate_sensor(ultrasonic_str)
|
|
102
|
+
if response:
|
|
103
|
+
return 0
|
|
104
|
+
else:
|
|
105
|
+
return -1
|
|
106
|
+
|
|
107
|
+
#舵机控制 port:连接P端口;command:
|
|
108
|
+
def servo_operate(port:bytes,command:bytes,angle:bytes) -> Optional[bytes]:
|
|
109
|
+
servo_str=[0xA0, 0x0E, 0x01, 0x71, 0x00, 0xBE]
|
|
110
|
+
servo_str[0]=0XA0+port
|
|
111
|
+
servo_str[2]=command
|
|
112
|
+
servo_str[4]=angle
|
|
113
|
+
response = Uart3_funtions.single_operate_sensor(servo_str)
|
|
114
|
+
if response:
|
|
115
|
+
return 0
|
|
116
|
+
else:
|
|
117
|
+
return -1
|
|
118
|
+
|
|
119
|
+
|
|
@@ -0,0 +1,503 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
import serial,time,struct
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
from collections import deque
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# 命令常量
|
|
8
|
+
BOOT_UPDATE_H = 0XFF
|
|
9
|
+
BOOT_UPDATE_L = 0XFF
|
|
10
|
+
READ_MODEL_H = 0XFF
|
|
11
|
+
READ_MODEL_L = 0X01
|
|
12
|
+
READ_VERSION_H = 0XFF
|
|
13
|
+
READ_VERSION_L = 0X02
|
|
14
|
+
READ_FACTORY_H = 0XFF
|
|
15
|
+
READ_FACTORY_L = 0X03
|
|
16
|
+
READ_HW_ID_H = 0XFF
|
|
17
|
+
READ_HW_ID_L = 0X04
|
|
18
|
+
READ_NAME_H = 0XFF
|
|
19
|
+
READ_NAME_L = 0X05
|
|
20
|
+
WRITE_NAME_H = 0XFF
|
|
21
|
+
WRITE_NAME_L = 0X06
|
|
22
|
+
READ_CONNECT_H = 0XFF
|
|
23
|
+
READ_CONNECT_L = 0X07
|
|
24
|
+
READ_BAT_H = 0XFF
|
|
25
|
+
READ_BAT_L = 0X0C
|
|
26
|
+
|
|
27
|
+
UPDATE_REQUEST_H = 0XFF
|
|
28
|
+
UPDATE_REQUEST_L = 0X10
|
|
29
|
+
MAX_COM_LEN_H = 0XFF
|
|
30
|
+
MAX_COM_LEN_L = 0X11
|
|
31
|
+
DL_MESSAGE_H = 0XFF
|
|
32
|
+
DL_MESSAGE_L = 0X12
|
|
33
|
+
READ_STATUS_H = 0XFF
|
|
34
|
+
READ_STATUS_L = 0X13
|
|
35
|
+
PAGE_CHECK_H = 0XFF
|
|
36
|
+
PAGE_CHECK_L = 0X14
|
|
37
|
+
PAGE_SEND_H = 0XFF
|
|
38
|
+
PAGE_SEND_L = 0X15
|
|
39
|
+
|
|
40
|
+
READ_PERIPH_H = 0X01
|
|
41
|
+
READ_PERIPH_L = 0X01
|
|
42
|
+
SINGLE_OP_H = 0X01
|
|
43
|
+
SINGLE_OP_L = 0X02
|
|
44
|
+
MODE_CHANGE_H = 0X01
|
|
45
|
+
MODE_CHANGE_L = 0X03
|
|
46
|
+
SEND_CYCLE_H = 0X01
|
|
47
|
+
SEND_CYCLE_L = 0X04
|
|
48
|
+
|
|
49
|
+
frames_queue = deque()
|
|
50
|
+
buffer = bytearray()
|
|
51
|
+
HEADER = bytes.fromhex('86 AB') # 帧头
|
|
52
|
+
FOOTER = bytes.fromhex('CF') # 帧尾
|
|
53
|
+
MIN_FRAME_LEN = 9 # 最小帧长度
|
|
54
|
+
|
|
55
|
+
# 串口配置参数
|
|
56
|
+
SERIAL_PORT = "/dev/ttyS3" # 串口设备路径
|
|
57
|
+
BAUD_RATE = 115200 # 波特率
|
|
58
|
+
TIMEOUT = 0.1 # 读取超时时间(秒)
|
|
59
|
+
|
|
60
|
+
ser = serial.Serial(
|
|
61
|
+
port=SERIAL_PORT,
|
|
62
|
+
baudrate=BAUD_RATE,
|
|
63
|
+
bytesize=serial.EIGHTBITS, # 8位数据位
|
|
64
|
+
parity=serial.PARITY_NONE, # 无校验位
|
|
65
|
+
stopbits=serial.STOPBITS_ONE, # 1位停止位
|
|
66
|
+
timeout=TIMEOUT,
|
|
67
|
+
xonxoff=False, # 关闭软件流控
|
|
68
|
+
rtscts=False, # 关闭硬件流控
|
|
69
|
+
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
class base_driver:
|
|
73
|
+
def uart3_init() -> Optional[serial.Serial]:
|
|
74
|
+
"""初始化串口"""
|
|
75
|
+
try:
|
|
76
|
+
if ser.is_open:
|
|
77
|
+
print("UART3初始化成功")
|
|
78
|
+
return ser
|
|
79
|
+
else:
|
|
80
|
+
print("Error opening UART3")
|
|
81
|
+
return None
|
|
82
|
+
except Exception as e:
|
|
83
|
+
print(f"Error opening UART3: {e}")
|
|
84
|
+
return None
|
|
85
|
+
|
|
86
|
+
def calculate_pro_check(command_h: int, command_l: int, data: List[bytes] = None) -> int:
|
|
87
|
+
if data:
|
|
88
|
+
len_data = len(data)
|
|
89
|
+
base_sum = 0x86 + 0xAB + 0x00 + 0x09 + len_data + command_h + command_l + 0x01 + 0xCF
|
|
90
|
+
base_sum += sum(data)
|
|
91
|
+
else:
|
|
92
|
+
base_sum = 0x86 + 0xAB + 0x00 + 0x09 + command_h + command_l + 0x01 + 0xCF
|
|
93
|
+
|
|
94
|
+
return base_sum % 256 # 确保结果为单字节(原C代码未取模,需根据实际协议调整)
|
|
95
|
+
|
|
96
|
+
def write_data(command_h: int, command_l: int, send_data: bytes= None) -> Optional[bytes]:
|
|
97
|
+
buffer = bytearray()
|
|
98
|
+
HEADER = bytes.fromhex('86 AB') # 帧头
|
|
99
|
+
FOOTER = bytes.fromhex('CF') # 帧尾
|
|
100
|
+
MIN_FRAME_LEN = 9 # 最小帧长度
|
|
101
|
+
if send_data:
|
|
102
|
+
pro_check = base_driver.calculate_pro_check(command_h, command_l, list(send_data))
|
|
103
|
+
send_packet = [0x86, 0xAB, (0x09+len(send_data))//256, (0x09+len(send_data))%256, command_h, command_l, *send_data, 0x01, pro_check, 0xCF]
|
|
104
|
+
else:
|
|
105
|
+
pro_check = base_driver.calculate_pro_check(command_h, command_l)
|
|
106
|
+
send_packet = [0x86, 0xAB, 0x00, 0x09, command_h, command_l, 0x01, pro_check, 0xCF]
|
|
107
|
+
send_bytes = bytes(send_packet)
|
|
108
|
+
|
|
109
|
+
ser.write(send_bytes)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def check_frame(frame: bytes) -> bool:
|
|
113
|
+
# 简化版校验,实际应根据协议实现
|
|
114
|
+
if len(frame) < 9:
|
|
115
|
+
return False
|
|
116
|
+
|
|
117
|
+
# 计算校验和
|
|
118
|
+
calculated_checksum = (sum(frame[:-2])+frame[-1])%256
|
|
119
|
+
frame_checksum = frame[-2] # 倒数第二个字节是校验和
|
|
120
|
+
|
|
121
|
+
return calculated_checksum == frame_checksum
|
|
122
|
+
|
|
123
|
+
def process_received_data():
|
|
124
|
+
global buffer
|
|
125
|
+
# 读取所有可用数据
|
|
126
|
+
data = ser.read(ser.in_waiting or 1)
|
|
127
|
+
if data:
|
|
128
|
+
buffer.extend(data)
|
|
129
|
+
while len(buffer)>=2:
|
|
130
|
+
# for x in buffer:
|
|
131
|
+
# print(f"{x:02X}", end=' ')
|
|
132
|
+
# print("\n")
|
|
133
|
+
# 1. 查找帧头
|
|
134
|
+
start_idx = buffer.find(HEADER)
|
|
135
|
+
if start_idx == -1:
|
|
136
|
+
# 没有找到帧头,清空无效数据(保留最后可能的部分帧头)
|
|
137
|
+
#print("Header no found")
|
|
138
|
+
if len(buffer) > len(HEADER) - 1:
|
|
139
|
+
buffer = buffer[-len(HEADER) + 1:]
|
|
140
|
+
return
|
|
141
|
+
# 2. 检查帧头后的长度字段是否足够
|
|
142
|
+
if start_idx + 4 > len(buffer):
|
|
143
|
+
# 长度字段不完整,等待更多数据
|
|
144
|
+
return
|
|
145
|
+
# 3. 解析帧长度
|
|
146
|
+
frame_length = (buffer[start_idx + 2] << 8) + buffer[start_idx + 3]
|
|
147
|
+
# 4. 检查完整帧是否已到达
|
|
148
|
+
end_idx = start_idx + frame_length - 1
|
|
149
|
+
if end_idx >= len(buffer):
|
|
150
|
+
# 完整帧尚未完全到达
|
|
151
|
+
return
|
|
152
|
+
# 5. 检查帧尾
|
|
153
|
+
if buffer[end_idx] != ord(FOOTER):
|
|
154
|
+
# 跳过当前帧头,继续查找
|
|
155
|
+
print("End no found")
|
|
156
|
+
buffer = buffer[start_idx + 1:]
|
|
157
|
+
continue
|
|
158
|
+
# 6. 提取完整帧
|
|
159
|
+
frame = buffer[start_idx:end_idx + 1]
|
|
160
|
+
frames_queue.append(frame)
|
|
161
|
+
# 7. 从缓冲区移除已处理帧
|
|
162
|
+
buffer = buffer[end_idx + 1:]
|
|
163
|
+
# 处理所有完整帧
|
|
164
|
+
if len(frames_queue) > 0:
|
|
165
|
+
frame = frames_queue.popleft()
|
|
166
|
+
if base_driver.check_frame(frame):
|
|
167
|
+
return frame
|
|
168
|
+
else:
|
|
169
|
+
print("Check byte error")
|
|
170
|
+
|
|
171
|
+
# 功能函数类
|
|
172
|
+
class Uart3_funtions:
|
|
173
|
+
|
|
174
|
+
##############################################################################读取设备信息
|
|
175
|
+
"""固件升级模式"""
|
|
176
|
+
def boot_update() -> None:
|
|
177
|
+
base_driver.write_data(BOOT_UPDATE_H, BOOT_UPDATE_L)
|
|
178
|
+
while True:
|
|
179
|
+
response =base_driver.process_received_data()
|
|
180
|
+
if response:
|
|
181
|
+
display_data = response[6:-3]
|
|
182
|
+
if display_data[0]==0X03:
|
|
183
|
+
print("固件更新启动\n")
|
|
184
|
+
elif display_data[0]==0X01:
|
|
185
|
+
print("擦除中......",f"{10*display_data[1]}","%\n")
|
|
186
|
+
elif display_data[0]==0X02:
|
|
187
|
+
print("升级中......",f"{10*display_data[1]}","%\n")
|
|
188
|
+
elif display_data[0]==0X05:
|
|
189
|
+
print("更新成功!\n")
|
|
190
|
+
elif display_data[0]==0X06:
|
|
191
|
+
print("更新失败!\n")
|
|
192
|
+
else:
|
|
193
|
+
for x in display_data:
|
|
194
|
+
print(f"{x:02X}", end=' ')
|
|
195
|
+
print("\n")
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
"""读取设备型号"""
|
|
199
|
+
def read_device_model() -> Optional[bytes]:
|
|
200
|
+
base_driver.write_data(READ_MODEL_H, READ_MODEL_L)
|
|
201
|
+
start_time = time.time()
|
|
202
|
+
while True:
|
|
203
|
+
response =base_driver.process_received_data()
|
|
204
|
+
if response:
|
|
205
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
206
|
+
print(f"设备型号: {display_data}")
|
|
207
|
+
return display_data
|
|
208
|
+
else:
|
|
209
|
+
if time.time() - start_time > 3:
|
|
210
|
+
print("读取超时")
|
|
211
|
+
buffer.clear()
|
|
212
|
+
return -1
|
|
213
|
+
|
|
214
|
+
"""读取版本号"""
|
|
215
|
+
def read_version() -> Optional[bytes]:
|
|
216
|
+
base_driver.write_data(READ_VERSION_H, READ_VERSION_L)
|
|
217
|
+
start_time = time.time()
|
|
218
|
+
while True:
|
|
219
|
+
response =base_driver.process_received_data()
|
|
220
|
+
if response:
|
|
221
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
222
|
+
print(f"版本号: {display_data}")
|
|
223
|
+
return display_data
|
|
224
|
+
else:
|
|
225
|
+
if time.time() - start_time > 3:
|
|
226
|
+
print("读取超时")
|
|
227
|
+
buffer.clear()
|
|
228
|
+
return -1
|
|
229
|
+
|
|
230
|
+
"""读取工厂信息"""
|
|
231
|
+
def read_factory_data() -> Optional[bytes]:
|
|
232
|
+
base_driver.write_data(READ_FACTORY_H, READ_FACTORY_L)
|
|
233
|
+
start_time = time.time()
|
|
234
|
+
while True:
|
|
235
|
+
response =base_driver.process_received_data()
|
|
236
|
+
if response:
|
|
237
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
238
|
+
print(f"厂家信息: {display_data}")
|
|
239
|
+
return display_data
|
|
240
|
+
else:
|
|
241
|
+
if time.time() - start_time > 3:
|
|
242
|
+
print("读取超时")
|
|
243
|
+
buffer.clear()
|
|
244
|
+
return -1
|
|
245
|
+
|
|
246
|
+
"""读取硬件ID"""
|
|
247
|
+
def read_hardware_ID() -> Optional[bytes]:
|
|
248
|
+
base_driver.write_data(READ_HW_ID_H, READ_HW_ID_L)
|
|
249
|
+
start_time = time.time()
|
|
250
|
+
while True:
|
|
251
|
+
response =base_driver.process_received_data()
|
|
252
|
+
if response:
|
|
253
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
254
|
+
print(f"硬件ID: {display_data}")
|
|
255
|
+
return display_data
|
|
256
|
+
else:
|
|
257
|
+
if time.time() - start_time > 3:
|
|
258
|
+
print("读取超时")
|
|
259
|
+
buffer.clear()
|
|
260
|
+
return -1
|
|
261
|
+
|
|
262
|
+
"""读取设备名称"""
|
|
263
|
+
def read_device_name() -> Optional[bytes]:
|
|
264
|
+
base_driver.write_data(READ_NAME_H, READ_NAME_L)
|
|
265
|
+
start_time = time.time()
|
|
266
|
+
while True:
|
|
267
|
+
response =base_driver.process_received_data()
|
|
268
|
+
if response:
|
|
269
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
270
|
+
print(f"设备名称: {display_data}")
|
|
271
|
+
return display_data
|
|
272
|
+
else:
|
|
273
|
+
if time.time() - start_time > 3:
|
|
274
|
+
print("读取超时")
|
|
275
|
+
buffer.clear()
|
|
276
|
+
return -1
|
|
277
|
+
|
|
278
|
+
"""设置设备名称"""
|
|
279
|
+
def write_device_name(send_data: str) -> Optional[bytes]:
|
|
280
|
+
data_bytes = send_data.encode('utf-8')
|
|
281
|
+
base_driver.write_data(WRITE_NAME_H, WRITE_NAME_L, data_bytes)
|
|
282
|
+
start_time = time.time()
|
|
283
|
+
while True:
|
|
284
|
+
response =base_driver.process_received_data()
|
|
285
|
+
if response:
|
|
286
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
287
|
+
print(f"设置状态: {display_data}")
|
|
288
|
+
return display_data
|
|
289
|
+
else:
|
|
290
|
+
if time.time() - start_time > 3:
|
|
291
|
+
print("读取超时")
|
|
292
|
+
buffer.clear()
|
|
293
|
+
return -1
|
|
294
|
+
|
|
295
|
+
"""读取连接方式"""#长度位少了1
|
|
296
|
+
def read_connected() -> Optional[bytes]:
|
|
297
|
+
base_driver.write_data(READ_CONNECT_H, READ_CONNECT_L)
|
|
298
|
+
start_time = time.time()
|
|
299
|
+
while True:
|
|
300
|
+
response =base_driver.process_received_data()
|
|
301
|
+
if response:
|
|
302
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
303
|
+
print(f"连接方式: {display_data}")
|
|
304
|
+
return display_data
|
|
305
|
+
else:
|
|
306
|
+
if time.time() - start_time > 3:
|
|
307
|
+
print("读取超时")
|
|
308
|
+
buffer.clear()
|
|
309
|
+
return -1
|
|
310
|
+
|
|
311
|
+
"""读取电池电量"""
|
|
312
|
+
def read_battery() -> Optional[bytes]:
|
|
313
|
+
base_driver.write_data(READ_BAT_H, READ_BAT_L)
|
|
314
|
+
start_time = time.time()
|
|
315
|
+
while True:
|
|
316
|
+
response =base_driver.process_received_data()
|
|
317
|
+
if response:
|
|
318
|
+
display_data = response[6:-3]
|
|
319
|
+
# for x in display_data:
|
|
320
|
+
# print(f"{x:02X}", end=' ')
|
|
321
|
+
print(f"电池电量: {display_data}")
|
|
322
|
+
return display_data
|
|
323
|
+
else:
|
|
324
|
+
if time.time() - start_time > 3:
|
|
325
|
+
print("读取超时")
|
|
326
|
+
buffer.clear()
|
|
327
|
+
return -1
|
|
328
|
+
|
|
329
|
+
###############################################################################固件升级
|
|
330
|
+
|
|
331
|
+
"""下载更新请求"""
|
|
332
|
+
def update_request() -> Optional[bytes]:
|
|
333
|
+
base_driver.write_data(UPDATE_REQUEST_H, UPDATE_REQUEST_L)
|
|
334
|
+
start_time = time.time()
|
|
335
|
+
while True:
|
|
336
|
+
response =base_driver.process_received_data()
|
|
337
|
+
if response:
|
|
338
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
339
|
+
print(f"从机响应: {display_data}")
|
|
340
|
+
return display_data
|
|
341
|
+
else:
|
|
342
|
+
if time.time() - start_time > 3:
|
|
343
|
+
print("读取超时")
|
|
344
|
+
buffer.clear()
|
|
345
|
+
return -1
|
|
346
|
+
|
|
347
|
+
"""查询最大通讯长度"""
|
|
348
|
+
def read_max_com_len() -> Optional[bytes]:
|
|
349
|
+
base_driver.write_data(MAX_COM_LEN_H, MAX_COM_LEN_L)
|
|
350
|
+
start_time = time.time()
|
|
351
|
+
while True:
|
|
352
|
+
response =base_driver.process_received_data()
|
|
353
|
+
if response:
|
|
354
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
355
|
+
print(f"从机响应: {display_data}")
|
|
356
|
+
return display_data
|
|
357
|
+
else:
|
|
358
|
+
if time.time() - start_time > 3:
|
|
359
|
+
print("读取超时")
|
|
360
|
+
buffer.clear()
|
|
361
|
+
return -1
|
|
362
|
+
|
|
363
|
+
"""下载文件的信息"""
|
|
364
|
+
def download_massage() -> Optional[bytes]:
|
|
365
|
+
base_driver.write_data(DL_MESSAGE_H, DL_MESSAGE_L, file_data)#文件信息来源从哪获取?
|
|
366
|
+
start_time = time.time()
|
|
367
|
+
while True:
|
|
368
|
+
response =base_driver.process_received_data()
|
|
369
|
+
if response:
|
|
370
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
371
|
+
print(f"从机响应: {display_data}")
|
|
372
|
+
return display_data
|
|
373
|
+
else:
|
|
374
|
+
if time.time() - start_time > 3:
|
|
375
|
+
print("读取超时")
|
|
376
|
+
buffer.clear()
|
|
377
|
+
return -1
|
|
378
|
+
|
|
379
|
+
"""查询设备状态"""
|
|
380
|
+
def read_device_status() -> Optional[bytes]:
|
|
381
|
+
base_driver.write_data(READ_STATUS_H, READ_STATUS_L)
|
|
382
|
+
start_time = time.time()
|
|
383
|
+
while True:
|
|
384
|
+
response =base_driver.process_received_data()
|
|
385
|
+
if response:
|
|
386
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
387
|
+
print(f"从机响应: {display_data}")
|
|
388
|
+
return display_data
|
|
389
|
+
else:
|
|
390
|
+
if time.time() - start_time > 3:
|
|
391
|
+
print("读取超时")
|
|
392
|
+
buffer.clear()
|
|
393
|
+
return -1
|
|
394
|
+
|
|
395
|
+
"""发送页校验码"""
|
|
396
|
+
def write_page_check() -> Optional[bytes]:
|
|
397
|
+
base_driver.write_data(PAGE_CHECK_H, PAGE_CHECK_L, page_check_data)
|
|
398
|
+
start_time = time.time()
|
|
399
|
+
while True:
|
|
400
|
+
response =base_driver.process_received_data()
|
|
401
|
+
if response:
|
|
402
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
403
|
+
print(f"从机响应: {display_data}")
|
|
404
|
+
return display_data
|
|
405
|
+
else:
|
|
406
|
+
if time.time() - start_time > 3:
|
|
407
|
+
print("读取超时")
|
|
408
|
+
buffer.clear()
|
|
409
|
+
return -1
|
|
410
|
+
|
|
411
|
+
"""发送页数据"""
|
|
412
|
+
def write_page_check() -> Optional[bytes]:
|
|
413
|
+
base_driver.write_data(PAGE_SEND_H, PAGE_SEND_L, page_send_data)
|
|
414
|
+
start_time = time.time()
|
|
415
|
+
while True:
|
|
416
|
+
response =base_driver.process_received_data()
|
|
417
|
+
if response:
|
|
418
|
+
display_data = response[6:-3].decode(errors="ignore")
|
|
419
|
+
print(f"从机响应: {display_data}")
|
|
420
|
+
return display_data
|
|
421
|
+
else:
|
|
422
|
+
if time.time() - start_time > 3:
|
|
423
|
+
print("读取超时")
|
|
424
|
+
buffer.clear()
|
|
425
|
+
return -1
|
|
426
|
+
|
|
427
|
+
###############################################################################读取传感器信息
|
|
428
|
+
|
|
429
|
+
"""读取外设连接情况"""
|
|
430
|
+
def read_peripheral() -> Optional[bytes]:
|
|
431
|
+
base_driver.write_data(READ_PERIPH_H, READ_PERIPH_L)
|
|
432
|
+
start_time = time.time()
|
|
433
|
+
while True:
|
|
434
|
+
response =base_driver.process_received_data()
|
|
435
|
+
if response:
|
|
436
|
+
display_data = response[6:-3]
|
|
437
|
+
for x in display_data:
|
|
438
|
+
print(f"{x:02X}", end=' ')
|
|
439
|
+
print("\n")
|
|
440
|
+
return display_data
|
|
441
|
+
else:
|
|
442
|
+
if time.time() - start_time > 3:
|
|
443
|
+
print("读取超时")
|
|
444
|
+
buffer.clear()
|
|
445
|
+
return -1
|
|
446
|
+
|
|
447
|
+
"""单次操作外设"""
|
|
448
|
+
def single_operate_sensor(op_struct: bytes) -> Optional[bytes]:
|
|
449
|
+
base_driver.write_data(SINGLE_OP_H, SINGLE_OP_L, op_struct)
|
|
450
|
+
start_time = time.time()
|
|
451
|
+
while True:
|
|
452
|
+
response =base_driver.process_received_data()
|
|
453
|
+
if response:
|
|
454
|
+
display_data = response[6:-3]
|
|
455
|
+
for x in display_data:
|
|
456
|
+
print(f"{x:02X}", end=' ')
|
|
457
|
+
print("\n")
|
|
458
|
+
return display_data
|
|
459
|
+
else:
|
|
460
|
+
if time.time() - start_time > 3:
|
|
461
|
+
print("读取超时")
|
|
462
|
+
buffer.clear()
|
|
463
|
+
return -1
|
|
464
|
+
|
|
465
|
+
"""从机模式转换"""
|
|
466
|
+
def mode_change(send_data: str) -> Optional[bytes]:
|
|
467
|
+
base_driver.write_data(MODE_CHANGE_H, MODE_CHANGE_L, send_data)
|
|
468
|
+
start_time = time.time()
|
|
469
|
+
while True:
|
|
470
|
+
response =base_driver.process_received_data()
|
|
471
|
+
if response:
|
|
472
|
+
display_data = response[6:-3]
|
|
473
|
+
for x in display_data:
|
|
474
|
+
print(f"{x:02X}", end=' ')
|
|
475
|
+
print("\n")
|
|
476
|
+
return display_data
|
|
477
|
+
else:
|
|
478
|
+
if time.time() - start_time > 3:
|
|
479
|
+
print("读取超时")
|
|
480
|
+
buffer.clear()
|
|
481
|
+
return -1
|
|
482
|
+
|
|
483
|
+
"""智能模式发送周期"""
|
|
484
|
+
def mode_change(send_data: str) -> Optional[bytes]:
|
|
485
|
+
base_driver.write_data(SEND_CYCLE_H, SEND_CYCLE_L, send_data)
|
|
486
|
+
start_time = time.time()
|
|
487
|
+
while True:
|
|
488
|
+
response =base_driver.process_received_data()
|
|
489
|
+
if response:
|
|
490
|
+
display_data = response[6:-3]
|
|
491
|
+
for x in display_data:
|
|
492
|
+
print(f"{x:02X}", end=' ')
|
|
493
|
+
print("\n")
|
|
494
|
+
return display_data
|
|
495
|
+
else:
|
|
496
|
+
if time.time() - start_time > 3:
|
|
497
|
+
print("读取超时")
|
|
498
|
+
buffer.clear()
|
|
499
|
+
return -1
|
|
500
|
+
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
import time
|
|
3
|
+
import math
|
|
4
|
+
from smbus import SMBus
|
|
5
|
+
|
|
6
|
+
MPU_ADDR = 0x68 # 根据AD0引脚调整
|
|
7
|
+
I2C_BUS = 3 # I2C-3接口
|
|
8
|
+
ACCEL_RANGE = 0x00 # ±2g
|
|
9
|
+
GYRO_RANGE = 0x18 # ±2000°/s
|
|
10
|
+
SAMPLING_RATE = 100 # 100Hz
|
|
11
|
+
|
|
12
|
+
# DMP固件数据(示例数据,需根据传感器型号调整)
|
|
13
|
+
DMP_FIRMWARE = [
|
|
14
|
+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
15
|
+
# 此处省略实际固件数据(需从官方获取)
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
class MPU6500:
|
|
19
|
+
def __init__(self):
|
|
20
|
+
self.bus = SMBus(I2C_BUS)
|
|
21
|
+
self.registers = {
|
|
22
|
+
'PWR_MGMT_1': 0x6B,
|
|
23
|
+
'GYRO_CFG': 0x1B,
|
|
24
|
+
'ACCEL_CFG': 0x1C,
|
|
25
|
+
'SMPLRT_DIV': 0x19,
|
|
26
|
+
'USER_CTRL': 0x6A,
|
|
27
|
+
'FIFO_EN': 0x23,
|
|
28
|
+
'FIFO_COUNT_H': 0x72,
|
|
29
|
+
'FIFO_R_W': 0x74,
|
|
30
|
+
'DMP_CFG_1': 0x70,
|
|
31
|
+
'DMP_CFG_2': 0x71,
|
|
32
|
+
'WHO_AM_I': 0x75
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
self.gyro_scale = self._get_gyro_scale(GYRO_RANGE)
|
|
36
|
+
self.accel_scale = self._get_accel_scale(ACCEL_RANGE)
|
|
37
|
+
self._initialize_hardware()
|
|
38
|
+
# self._load_dmp_firmware()
|
|
39
|
+
self._configure_dmp()
|
|
40
|
+
|
|
41
|
+
def _initialize_hardware(self):
|
|
42
|
+
"""初始化硬件寄存器"""
|
|
43
|
+
self._write_reg('PWR_MGMT_1', 0x80) # 软复位
|
|
44
|
+
time.sleep(0.1)
|
|
45
|
+
self._write_reg('PWR_MGMT_1', 0x01) # 唤醒,选择陀螺仪X轴时钟
|
|
46
|
+
time.sleep(0.1)
|
|
47
|
+
|
|
48
|
+
self._write_reg('GYRO_CFG', GYRO_RANGE)
|
|
49
|
+
self._write_reg('ACCEL_CFG', ACCEL_RANGE)
|
|
50
|
+
self._write_reg('SMPLRT_DIV', (1000 // SAMPLING_RATE) - 1)
|
|
51
|
+
|
|
52
|
+
def _load_dmp_firmware(self):
|
|
53
|
+
"""加载DMP固件(示例,需替换为实际固件)"""
|
|
54
|
+
print("加载DMP固件...")
|
|
55
|
+
for addr, data in enumerate(DMP_FIRMWARE):
|
|
56
|
+
self._write_reg(0x40 + addr, data) # 固件从0x40地址开始写入
|
|
57
|
+
time.sleep(0.001)
|
|
58
|
+
print("固件加载完成")
|
|
59
|
+
|
|
60
|
+
def _configure_dmp(self):
|
|
61
|
+
"""配置DMP参数"""
|
|
62
|
+
self._write_reg('USER_CTRL', 0x00) # 禁用DMP
|
|
63
|
+
self._write_reg('FIFO_EN', 0x00) # 禁用FIFO
|
|
64
|
+
self._write_reg('DMP_CFG_1', 0x03) # 设置DMP采样率
|
|
65
|
+
self._write_reg('DMP_CFG_2', 0x00) # 禁用低功耗模式
|
|
66
|
+
|
|
67
|
+
self._write_reg('USER_CTRL', 0x10) # 复位FIFO
|
|
68
|
+
time.sleep(0.01)
|
|
69
|
+
self._write_reg('USER_CTRL', 0x80) # 启用DMP
|
|
70
|
+
time.sleep(0.1)
|
|
71
|
+
self._write_reg('FIFO_EN', 0x40) # 启用四元数FIFO
|
|
72
|
+
|
|
73
|
+
def _write_reg(self, reg, value):
|
|
74
|
+
"""安全写入寄存器(支持寄存器名称字符串或数值地址)"""
|
|
75
|
+
if isinstance(reg, str):
|
|
76
|
+
reg_addr = self.registers[reg]
|
|
77
|
+
else:
|
|
78
|
+
reg_addr = reg
|
|
79
|
+
|
|
80
|
+
try:
|
|
81
|
+
self.bus.write_byte_data(MPU_ADDR, reg_addr, value)
|
|
82
|
+
except Exception as e:
|
|
83
|
+
print(f"写入寄存器0x{reg_addr:02X}失败: {e}")
|
|
84
|
+
|
|
85
|
+
def read_dmp_quaternion(self):
|
|
86
|
+
"""读取DMP生成的四元数"""
|
|
87
|
+
high = self.bus.read_byte_data(MPU_ADDR, self.registers['FIFO_COUNT_H'])
|
|
88
|
+
low = self.bus.read_byte_data(MPU_ADDR, self.registers['FIFO_COUNT_H'] + 1)
|
|
89
|
+
fifo_len = (high << 8) | low
|
|
90
|
+
|
|
91
|
+
if fifo_len < 8:
|
|
92
|
+
return None
|
|
93
|
+
|
|
94
|
+
data = self.bus.read_i2c_block_data(MPU_ADDR, self.registers['FIFO_R_W'], 8)
|
|
95
|
+
return self._parse_quaternion(data)
|
|
96
|
+
|
|
97
|
+
def _parse_quaternion(self, bytes):
|
|
98
|
+
"""解析四元数(小端模式)"""
|
|
99
|
+
q1 = self._bytes_to_sint16(bytes[0:2]) / 32768.0
|
|
100
|
+
q2 = self._bytes_to_sint16(bytes[2:4]) / 32768.0
|
|
101
|
+
q3 = self._bytes_to_sint16(bytes[4:6]) / 32768.0
|
|
102
|
+
q4 = self._bytes_to_sint16(bytes[6:8]) / 32768.0
|
|
103
|
+
return (q1, q2, q3, q4)
|
|
104
|
+
|
|
105
|
+
def _bytes_to_sint16(self, bytes):
|
|
106
|
+
val = (bytes[1] << 8) | bytes[0]
|
|
107
|
+
return val if val < 32768 else val - 65536
|
|
108
|
+
|
|
109
|
+
def _get_gyro_scale(self, range_bits):
|
|
110
|
+
return {0x18: 16.4}[range_bits]
|
|
111
|
+
|
|
112
|
+
def _get_accel_scale(self, range_bits):
|
|
113
|
+
return {0x00: 16384.0}[range_bits]
|
|
114
|
+
|
|
115
|
+
if __name__ == "__main__":
|
|
116
|
+
mpu = MPU6500()
|
|
117
|
+
print("开始读取DMP数据...")
|
|
118
|
+
|
|
119
|
+
try:
|
|
120
|
+
while True:
|
|
121
|
+
q = mpu.read_dmp_quaternion()
|
|
122
|
+
if q:
|
|
123
|
+
norm = math.sqrt(sum(x**2 for x in q))
|
|
124
|
+
if norm > 0.5: # 仅输出有效四元数
|
|
125
|
+
print(f"四元数: {q}, 模长: {norm}")
|
|
126
|
+
else:
|
|
127
|
+
print("警告:四元数无效,模长过低")
|
|
128
|
+
time.sleep(0.1)
|
|
129
|
+
except KeyboardInterrupt:
|
|
130
|
+
print("程序停止")
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: smartpi
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: A library use for H2-RCU
|
|
5
|
+
Author-email: Driver_cai <1547363120@qq.com>
|
|
6
|
+
Project-URL: Homepage, https://github.com/Drvier_cai/smartpi
|
|
7
|
+
Project-URL: Bug Tracker, https://github.com/Driver/smartpi/issues
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Python: >=3.7
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
pyproject.toml
|
|
2
|
+
src/smartpi/__init__.py
|
|
3
|
+
src/smartpi/app_module.py
|
|
4
|
+
src/smartpi/module.py
|
|
5
|
+
src/smartpi/mpu6500.py
|
|
6
|
+
src/smartpi.egg-info/PKG-INFO
|
|
7
|
+
src/smartpi.egg-info/SOURCES.txt
|
|
8
|
+
src/smartpi.egg-info/dependency_links.txt
|
|
9
|
+
src/smartpi.egg-info/top_level.txt
|
|
10
|
+
tests/test_module.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
smartpi
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
import time
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
src_path = str(Path(__file__).resolve().parent.parent / "src")
|
|
6
|
+
sys.path.insert(0, src_path)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
from smartpi.module import Uart3_funtions, base_driver
|
|
10
|
+
from smartpi.app_module import app_funtion
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if __name__ == "__main__":
|
|
14
|
+
ser = base_driver.uart3_init()
|
|
15
|
+
if ser:
|
|
16
|
+
try:
|
|
17
|
+
# Uart3_funtions.boot_update()
|
|
18
|
+
# Uart3_funtions.read_device_model()
|
|
19
|
+
# Uart3_funtions.read_version()
|
|
20
|
+
# Uart3_funtions.read_factory_data()
|
|
21
|
+
# Uart3_funtions.read_hardware_ID()
|
|
22
|
+
# Uart3_funtions.read_device_name()
|
|
23
|
+
# Uart3_funtions.write_device_name("Martin")
|
|
24
|
+
# Uart3_funtions.read_connected()
|
|
25
|
+
# Uart3_funtions.read_battery()
|
|
26
|
+
# Uart3_funtions.read_peripheral()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
while True:
|
|
30
|
+
app_funtion.write_motor_dir(1,0)
|
|
31
|
+
app_funtion.write_motor_speed(1,100)
|
|
32
|
+
time.sleep(0.5)
|
|
33
|
+
app_funtion.write_motor_dir(1,1)
|
|
34
|
+
app_funtion.write_motor_speed(1,50)
|
|
35
|
+
time.sleep(0.5)
|
|
36
|
+
# app_funtion.servo_operate(1,1,0)
|
|
37
|
+
# time.sleep(0.5)
|
|
38
|
+
# app_funtion.servo_operate(1,1,180)
|
|
39
|
+
# time.sleep(0.5)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
except KeyboardInterrupt:
|
|
43
|
+
print("\n程序终止")
|
|
44
|
+
finally:
|
|
45
|
+
ser.close()
|
|
46
|
+
print("串口关闭")
|
|
47
|
+
|
|
48
|
+
|