181 lines
5.4 KiB
Python
181 lines
5.4 KiB
Python
import network
|
|
import socket
|
|
import struct
|
|
from machine import Timer, ADC, Pin, WDT
|
|
import array
|
|
import gc
|
|
import time
|
|
import random
|
|
|
|
# 配置信息
|
|
SSID = "Obscura"
|
|
PASSWORD = "Obscura2024"
|
|
UDP_HOST = "222.186.10.253"
|
|
UDP_PORT = 6002
|
|
SERIAL_NUMBER = "ES01-208742cf95-efe5fb"
|
|
WATCHDOG_TIMEOUT = 20000 # 增加看门狗超时时间到20秒
|
|
|
|
class HighSpeedCollector:
|
|
def __init__(self):
|
|
# 初始化看门狗
|
|
self.wdt = WDT(timeout=WATCHDOG_TIMEOUT)
|
|
|
|
self.sock = None
|
|
self.is_connected = False
|
|
self.sample_timer = Timer(0)
|
|
self.running = False
|
|
|
|
# ADC配置
|
|
self.adc = ADC(Pin(3))
|
|
self.adc.atten(ADC.ATTN_11DB)
|
|
self.adc.width(ADC.WIDTH_12BIT)
|
|
|
|
# 看门狗定时器
|
|
self.wdt_timer = Timer(1)
|
|
self.wdt_timer.init(period=WATCHDOG_TIMEOUT // 4, # 每5秒喂一次狗
|
|
mode=Timer.PERIODIC,
|
|
callback=self._feed_watchdog)
|
|
|
|
def _feed_watchdog(self, _):
|
|
"""定期喂狗"""
|
|
try:
|
|
self.wdt.feed()
|
|
except Exception as e:
|
|
print("喂狗失败:", str(e))
|
|
|
|
def connect_wifi(self):
|
|
wlan = network.WLAN(network.STA_IF)
|
|
wlan.active(True)
|
|
if not wlan.isconnected():
|
|
wlan.connect(SSID, PASSWORD)
|
|
connect_start = time.ticks_ms()
|
|
while not wlan.isconnected():
|
|
# 检查WiFi连接超时(30秒)
|
|
if time.ticks_diff(time.ticks_ms(), connect_start) > 30000:
|
|
raise Exception("WiFi连接超时")
|
|
gc.collect()
|
|
self.wdt.feed() # WiFi连接过程中喂狗
|
|
time.sleep(1)
|
|
|
|
def setup_udp(self):
|
|
"""初始化UDP连接"""
|
|
try:
|
|
gc.collect()
|
|
if self.sock:
|
|
try:
|
|
self.sock.close()
|
|
except:
|
|
pass
|
|
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
self.sock.setblocking(False)
|
|
self.sock.sendto(SERIAL_NUMBER.encode(), (UDP_HOST, UDP_PORT))
|
|
print(f"首次连接,发送序列号: {SERIAL_NUMBER}")
|
|
self.is_connected = True
|
|
except Exception as e:
|
|
print("UDP初始化失败:", str(e))
|
|
self.is_connected = False
|
|
self.sock = None
|
|
|
|
def _sample_and_send(self, _):
|
|
"""直接采样并发送数据"""
|
|
if not self.is_connected:
|
|
return
|
|
|
|
try:
|
|
# 在采样开始时也喂狗
|
|
self.wdt.feed()
|
|
|
|
# 检查是否有序列号请求
|
|
try:
|
|
data, addr = self.sock.recvfrom(1024)
|
|
if data == b'REQUEST_SERIAL':
|
|
self.sock.sendto(SERIAL_NUMBER.encode(), addr)
|
|
return
|
|
except:
|
|
pass
|
|
|
|
# 使用相对时间戳
|
|
if not hasattr(self, 'start_time'):
|
|
self.start_time = time.ticks_ms()
|
|
|
|
relative_ms = time.ticks_diff(time.ticks_ms(), self.start_time)
|
|
timestamp = relative_ms % 65536
|
|
|
|
# 采集50个数据点
|
|
samples = array.array('H', [self.adc.read() for _ in range(50)])
|
|
|
|
packed_data = struct.pack(
|
|
'<HH50H',
|
|
timestamp,
|
|
0, # chunk_index
|
|
*samples
|
|
)
|
|
|
|
self.sock.sendto(packed_data, (UDP_HOST, UDP_PORT))
|
|
|
|
except Exception as e:
|
|
print('发送数据错误:', str(e))
|
|
self.is_connected = False
|
|
self.sock = None
|
|
|
|
def start(self):
|
|
"""启动采样和发送"""
|
|
self.running = True
|
|
try:
|
|
self.sample_timer.init(
|
|
freq=20, # 每秒20次采样和发送
|
|
mode=Timer.PERIODIC,
|
|
callback=self._sample_and_send
|
|
)
|
|
print("采样定时器启动成功 - 频率: 20Hz")
|
|
except Exception as e:
|
|
print(f"采样定时器启动失败: {e}")
|
|
self.running = False
|
|
|
|
def stop(self):
|
|
"""停止采样"""
|
|
self.running = False
|
|
self.sample_timer.deinit()
|
|
self.wdt_timer.deinit() # 停止喂狗定时器
|
|
if self.sock:
|
|
try:
|
|
self.sock.close()
|
|
except:
|
|
pass
|
|
|
|
def main():
|
|
gc.enable()
|
|
collector = None
|
|
retry_count = 0
|
|
max_retries = 3
|
|
|
|
while retry_count < max_retries:
|
|
try:
|
|
print(f"初始化采集器... (尝试 {retry_count + 1}/{max_retries})")
|
|
collector = HighSpeedCollector()
|
|
|
|
collector.connect_wifi()
|
|
collector.setup_udp()
|
|
collector.start()
|
|
|
|
print("进入主循环...")
|
|
while collector.running:
|
|
gc.collect()
|
|
time.sleep(0.1)
|
|
|
|
break # 如果正常运行,跳出重试循环
|
|
|
|
except Exception as e:
|
|
print("程序出错:", str(e))
|
|
retry_count += 1
|
|
if collector:
|
|
collector.stop()
|
|
time.sleep(5) # 等待5秒后重试
|
|
|
|
if collector:
|
|
collector.stop()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|