Skip to content

Commit 28fb259

Browse files
committed
added README and debug.py
1 parent 578ccfc commit 28fb259

File tree

3 files changed

+159
-0
lines changed

3 files changed

+159
-0
lines changed

README.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# Tuya CO2 Sensor firmware located at 'user' directory
2+
Original library README below.
3+
14
# About
25

36
FwLib_STC8 is a lite firmware library for STC8G/STC8H series MCU.

user/README.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
https://developer.tuya.com/en/docs/iot/zt3l-module-datasheet?id=Ka438n1j8nuvu
2+
https://developer.tuya.com/en/docs/iot/tuya-zigbee-module-uart-communication-protocol?id=K9ear5khsqoty#dataFormat
3+
https://www.tinytronics.nl/index.php?route=product/product/get_file&file=4660/MTP40-F-CO2-sensor-module-single-channel.pdf

user/debug.py

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import serial
2+
import time
3+
4+
log = bytearray()
5+
6+
7+
def get_bytes(n):
8+
d = ser.read(n)
9+
log.extend(d)
10+
# print(d.hex())
11+
return d
12+
13+
14+
def log_flush():
15+
print(len(log), log.hex())
16+
log.clear()
17+
18+
19+
def get_byte():
20+
return get_bytes(1)[0]
21+
22+
23+
def get_int(n):
24+
return int.from_bytes(get_bytes(n))
25+
26+
27+
prev_time = None
28+
29+
30+
def get_time():
31+
global prev_time
32+
t = time.time()
33+
if prev_time is None:
34+
d = 0
35+
else:
36+
d = t - prev_time
37+
prev_time = t
38+
return f'[{d:.03f}]'
39+
40+
41+
class Tuya:
42+
CMDS = {
43+
0x1: 'QPI',
44+
0x2: 'RNS',
45+
0x3: 'CZM',
46+
0x6: 'RSP',
47+
0x20: 'QZS'
48+
}
49+
50+
@staticmethod
51+
def wait_start():
52+
b = None
53+
i = 0
54+
while True:
55+
bp = b
56+
b = get_byte()
57+
i += 1
58+
if (bp, b) == (0x55, 0xaa):
59+
skipped = i - 2
60+
if skipped:
61+
print('skipped', skipped)
62+
return
63+
64+
@staticmethod
65+
def main():
66+
while True:
67+
Tuya.wait_start()
68+
ver = get_byte()
69+
assert ver == 2
70+
seq = get_int(2)
71+
cmd = get_byte()
72+
len = get_int(2)
73+
data = get_bytes(len)
74+
75+
csum = sum(log) % 256
76+
77+
check = get_byte()
78+
79+
cmd_name = Tuya.CMDS.get(cmd, '')
80+
if cmd == 0x6 and len == 8:
81+
parsed = f'CO2:{int.from_bytes(data[-4:])}'
82+
elif cmd == 0x1 and len == 28:
83+
parsed = data.decode()
84+
elif cmd == 0x2 and len == 1:
85+
parsed = {0: 'not paired', 1: 'paired', 2: 'exc', 3: 'pairing'}[data[0]]
86+
else:
87+
parsed = ''
88+
log_flush()
89+
print(f'{seq:04X} {cmd:02X}:{cmd_name} {len:3d}[{data.hex()}] {parsed} {csum == check}')
90+
91+
92+
class Sensor:
93+
@staticmethod
94+
def wait_start():
95+
b = None
96+
i = 0
97+
while True:
98+
bp = b
99+
b = get_byte()
100+
i += 1
101+
if (bp, b) == (0x42, 0x4d):
102+
skipped = i - 2
103+
if skipped:
104+
print('skipped', skipped)
105+
return
106+
107+
@staticmethod
108+
def main():
109+
while True:
110+
Sensor.wait_start()
111+
inst = get_byte()
112+
assert inst == 0xA0
113+
cmd = get_int(2)
114+
len = get_int(2)
115+
data = get_bytes(len)
116+
csum = sum(log)
117+
check = get_int(2)
118+
cmd_name = Sensor.CMDS.get(cmd, '')
119+
if cmd == 0x3 and len == 5:
120+
parsed = f'CO2:{int.from_bytes(data[:-1])} V:{data[-1]}'
121+
else:
122+
parsed = ''
123+
log_flush()
124+
print(f'{get_time()} {cmd:02X}:{cmd_name} {len:3d}[{data.hex()}] {parsed} {csum == check}')
125+
126+
127+
class Trim:
128+
@staticmethod
129+
def main():
130+
tp = None
131+
ts = None
132+
avg_sum = 0
133+
avg_num = 0
134+
while True:
135+
b = get_byte()
136+
t = time.time_ns()
137+
if ts is None:
138+
ts = t
139+
if tp is not None:
140+
d = t - tp
141+
avg_sum += d
142+
avg_num += 1
143+
avg = avg_sum / avg_num
144+
avg2 = (t - ts) / avg_num
145+
print(d, avg, avg2, avg_num, b)
146+
tp = t
147+
148+
149+
if __name__ == '__main__':
150+
ser = serial.Serial('/dev/ttyUSB1', baudrate=9600)
151+
152+
Sensor.main()
153+
# Tuya.main()

0 commit comments

Comments
 (0)