基于Seeed XIAO ESP32S3 Sense制作的联网交互式任务计划管理系统
该项目使用了Seeed XIAO ESP32S3 Sense开发板,实现了联网交互式任务计划管理系统的设计,它的主要功能为:协助用户进行任务的规划,以及记录用户在任务上投入的时间并在达到截至时间后进行提示。
标签
嵌入式系统
显示
Seeed XIAO ESP32S3 Sense
一颗星
更新2025-08-01
沈阳理工大学
88

1、项目介绍

很荣幸能够参加本次由柴火创客赞助电子森林举办的2025交互标牌创客争霸赛活动。在日常生活中,为了达成某一目标而给自己安排任务是十分常见的,比如在准备考研或者考公时,需要合理安排每天学习各个科目的时间。为了满足该需求,本项目通过使用Seeed XIAO ESP32S3 Sense开发板,制作了一个联网交互式任务计划管理系统,其主要功能如下:

(1) 可以通过浏览器客户端来制定任务以及计划投入的时间,实现交互功能。

(2) 系统可以检测工位是否有人来决定工作状态是“工作中”还是“空闲中”,由此来准确记录自己在某个任务中投入的时间。

(3) 当开始任务后,可以根据工作状态进行计时,当工作投入时间达到计划时间后电路板可以进行提示。

2、硬件介绍

Seeed Studio XIAO系列是小型开发板,共享类似的硬件结构,尺寸实际上是拇指大小。这里的“XIAO”代表它的尺寸特征“小“,另一层意思是指它的功能强大“骁”。 Seeed Studio XIAO ESP32S3 Sense集成了摄像头传感器、数字麦克风和SD卡支持。结合嵌入式ML计算能力和摄影能力,这款开发板可以成为使用智能语音和视觉AI的绝佳工具。实物如下图所示。


Seeed Studio XIAO ESP32S3 Sense开发板


在检测座位是否有人时使用到了测距传感器,超声波测距传感器是一种利用超声波反射原理进行非接触式距离测量的电子设备。它通过向目标方向发射一定频率的超声波信号,并接收其从物体表面反射回来的回波,根据发射与接收之间的时间差,结合声速,计算出与物体之间的距离。超声测距传感器实物如下图所示。


超声测距传感器


系统的整体接线图如下所示。


系统整体接线图

3、方案框图和项目设计思路介绍

系统的前后端通过TCP/IP协议进行通讯,其中ESP32作为服务器端,浏览器作为客户端。开发板连接到WIFI后,浏览器通过访问开发板的IP地址进行信息的传输,客户端制订任务,开始任务等信息均可保存到ESP32服务器端,同时,服务器端的数据,如座位是否有人等信息也可在加载浏览器时传输到系统页面进行展示。当浏览器停止请求后,服务器端会对开始的任务进行计时,无论是在浏览器端还是服务器端,进行计时时会通过超声测距传感器来检测座位是否有人,如果没有人的话,计时暂停。同时,在服务器端进行计时时,程序会不断扫描是否有已经完成的任务,如果有完成的任务,则亮起LED灯进行提示。方案设计框架图如下图所示。


项目方案设计框架图


4、软件流程图及关键代码介绍

程序开始运行后,首先连接WIFI网络,连接成功以后注册TCP通信协议,然后等待相应IP端口的请求,如果超过指定的等待时间,ESP32会对已经开始的任务进行后端计时,无论是在浏览器端还是服务器端,进行计时时会通过超声测距传感器来检测座位是否有人来决定是否暂停计时。服务器端如果检测到有已经完成的任务,则通过亮起LED灯进行提示。当检测到有客户端请求时,则会先处理来自客户端的请求,实现任务计划的交互功能。软件流程图如下图所示。


软件流程图


(1) 通过使用超声测距传感器来检测座位上是否有人,当超声传感器检测到距离大于某个值时则判定作为没人。超声测距传感器通过向目标方向发射一定频率的超声波信号,并接收其从物体表面反射回来的回波,根据发射与接收之间的时间差,结合声速,计算出与物体之间的距离,其代码如下。

class HCSR04:
"""
Driver to use the untrasonic sensor HC-SR04.
The sensor range is between 2cm and 4m.

The timeouts received listening to echo pin are converted to OSError('Out of range')

"""
# echo_timeout_us is based in chip range limit (400cm)
def __init__(self, trigger_pin, echo_pin, echo_timeout_us=500*2*30):
"""
trigger_pin: Output pin to send pulses
echo_pin: Readonly pin to measure the distance. The pin should be protected with 1k resistor
echo_timeout_us: Timeout in microseconds to listen to echo pin.
By default is based in sensor limit range (4m)
"""
self.echo_timeout_us = echo_timeout_us
# Init trigger pin (out)
self.trigger = Pin(trigger_pin, mode=Pin.OUT, pull=None)
self.trigger.value(0)

# Init echo pin (in)
self.echo = Pin(echo_pin, mode=Pin.IN, pull=None)

def _send_pulse_and_wait(self):
"""
Send the pulse to trigger and listen on echo pin.
We use the method `machine.time_pulse_us()` to get the microseconds until the echo is received.
"""
self.trigger.value(0) # Stabilize the sensor
sleep_us(5)
self.trigger.value(1)
# Send a 10us pulse.
sleep_us(10)
self.trigger.value(0)
try:
pulse_time = time_pulse_us(self.echo, 1, self.echo_timeout_us)
# time_pulse_us returns -2 if there was timeout waiting for condition; and -1 if there was timeout during the main measurement. It DOES NOT raise an exception
# ...as of MicroPython 1.17: http://docs.micropython.org/en/v1.17/library/machine.html#machine.time_pulse_us
if pulse_time < 0:
MAX_RANGE_IN_CM = const(500) # it's really ~400 but I've read people say they see it working up to ~460
pulse_time = int(MAX_RANGE_IN_CM * 29.1) # 1cm each 29.1us
return pulse_time
except OSError as ex:
if ex.args[0] == 110: # 110 = ETIMEDOUT
raise OSError('Out of range')
raise ex

def distance_mm(self):
"""
Get the distance in milimeters without floating point operations.
"""
pulse_time = self._send_pulse_and_wait()

# To calculate the distance we get the pulse_time and divide it by 2
# (the pulse walk the distance twice) and by 29.1 becasue
# the sound speed on air (343.2 m/s), that It's equivalent to
# 0.34320 mm/us that is 1mm each 2.91us
# pulse_time // 2 // 2.91 -> pulse_time // 5.82 -> pulse_time * 100 // 582
mm = pulse_time * 100 // 582
return mm

def distance_cm(self):
"""
Get the distance in centimeters with floating point operations.
It returns a float
"""
pulse_time = self._send_pulse_and_wait()

# To calculate the distance we get the pulse_time and divide it by 2
# (the pulse walk the distance twice) and by 29.1 becasue
# the sound speed on air (343.2 m/s), that It's equivalent to
# 0.034320 cm/us that is 1cm each 29.1us
cms = (pulse_time / 2) / 29.1
return cms

(2) 为了使系统可以联网,需要通过Seeed XIAO ESP32S3 Sense开发板上的WIFI模块进行联网,其代码如下。

sta = network.WLAN(network.STA_IF)
if not sta.isconnected():
print('WIFI is connecting to network')
sta.active(True)
sta.connect('nava11','12345678')
while not sta.isconnected():

pass

(3) Seeed XIAO ESP32S3 Sense作为服务器端,需要通过TCP/IP协议与浏览器客户端进行信息的交互,其代码如下。

def start_server():
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(('',80))
s.listen(5)
s.settimeout(3)
print('Web server listening on http://0.0.0.0:80')
while True:
try:
conn, addr = s.accept()
handle_request(conn)
except OSError as e:
# 没有客户端连接,执行你想做的操作
run_background_tasks()
except Exception as e:
print("服务器错误:", e)
# 启动 Web 服务器

start_server()

(4) 服务器端相应客户端请求的代码如下

def handle_request(conn):
try:
request = conn.recv(1024).decode()
if not request:
return
print("Request:\n", request)

# 路由解析
method, path, *_ = request.split()
content = ""
if path == '/':
init_load = 'HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n' + web_server()
conn.send(init_load)
elif path == '/distance':
distance_value = ultrasonic.distance_cm()
content = f"{distance_value:.2f}"
response = build_response(content)

elif path == '/submit-task' and method == "POST":
body = get_body(request)
data = ujson.loads(body)
task_name = data.get('task')
task_time = data.get('time')
task_ifstart = data.get('ifstart')
tasks[task_name] = {"time": int(task_time), "ifstart": int(task_ifstart)}
print("任务已保存:", tasks)
content = "任务已保存"
response = build_response(content)

elif path == '/delete-task' and method == "POST":
body = get_body(request)
data = ujson.loads(body)
task_name = data.get('task')
if task_name in tasks:
del tasks[task_name]
print("任务已删除:", task_name)
content = "任务已删除"
else:
content = "任务不存在"
response = build_response(content)

elif path == '/get-tasks':
content = ujson.dumps(tasks) # 返回任务字典,格式:{"任务1": 60, "任务2": 120}
response = build_response(content, content_type="application/json")



else:
content = "404 Not Found"
response = build_response(content, status_code=404)



conn.send(response)
except Exception as e:
print("错误:", e)
finally:
conn.close()

def build_response(content, status_code=200, content_type="text/plain"):
return f"""HTTP/1.1 {status_code} OK\r
Content-Type: {content_type}\r
Content-Length: {len(content)}\r
\r
{content}""".encode()

def get_body(request):
parts = request.split("\r\n\r\n", 1)
return parts[1] if len(parts) > 1 else ""

(5) 当没有客户端请求时,服务器端需要进行倒计时,并在检测到有任务达到截至时间时亮起LED灯,其代码如下

judge = 0
def run_background_tasks():
global judge
distance_value = ultrasonic.distance_cm()
for task_name, info in tasks.items():
if isinstance(info, dict):
if info.get("time") == 1:
judge = 1
print(f"{task_name} 时间为1,执行操作")
break
if (judge==1) :
judge=0
led.value(0)
else:
led.value(1)
time.sleep(0.5)
if(distance_value <= 100):
for task_name in list(tasks.keys()):
task = tasks[task_name]
if isinstance(task, dict) and task.get("ifstart") == 1:
if task["time"] > 1:
task["time"] -= 1
print("工作中")
print(task_name, '剩余时间:' , task["time"])
else:
print("任务完成:", task_name)
task["time"] = 1

else:
print('休闲中')


5、功能展示图及说明

(1) 系统的界面首先会展示工位是否有人这一信息,如果有人,则状态会显示为”工作中“,如果没有人,则状态会显示为”空闲中“,效果如下图展示。


休闲中状态


工作中状态


(2) 可以通过网页制订任务实现与作为服务器的Seeed XIAO ESP32S3 Sense开发板的交互,当开始任务后,如果状态为工作中,则进行任务的计时,如果状态为空闲中,则暂停计时。效果如下图所示。


系统的任务录入及计时


(3) 当在服务器端检测到有任务完成时,则会亮起LED灯进行提示,效果如下图所示。


LED灯亮起

(4) 当删除已经完成的任务后,LED灯熄灭,效果如下图所示。


LED灯熄灭

6、项目中遇到的难题和解决方法

在编写 HTML 网页的过程中,最初我将获取页面组件的操作与向服务器发送请求的逻辑一同放置在一个循环中执行。这样做虽然逻辑上看似简洁,但在实际运行中却引发了严重的性能问题:由于频繁地访问 DOM 元素与不断发起网络请求,导致浏览器页面出现卡顿现象,请求响应也经常出现阻塞,严重影响了用户体验。为了解决这一问题,我查阅了大量相关资料,并结合实际测试,最终决定将页面组件的获取代码与网络请求代码分离开来,分别放在合适的函数或事件触发机制中进行处理。优化后的代码结构更加清晰合理,系统运行也变得流畅稳定,不仅提高了页面的响应速度,也为后续的功能扩展打下了良好的基础。

7、对本次活动的心得体会

本次基于 Seeed XIAO ESP32S3 Sense 制作的联网交互式任务计划管理系统项目,使我深入了解了物联网终端设备在实际应用中的开发与部署流程。通过结合 Wi-Fi 通信、传感器数据采集与网页前端交互,我完成了一个可远程访问、实时更新任务状态的系统。项目过程中,不仅提升了我对嵌入式编程、网络通信协议以及网页设计的理解,还锻炼了整体系统架构设计和调试能力。此次实践让我体会到软硬结合的魅力,也增强了解决实际问题的能力,为今后的工程开发积累了宝贵经验,希望电子森林可以举办更多这样有意义的活动。

附件下载
micropython代码.rar
可运行的代码
团队介绍
沈阳理工大学的学生
团队成员
一颗星
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号