【ESP32/MicroPython】基于ESP32的博客状态监控器

引子

单纯觉得我的ESP32吃灰太浪费了。纯纯伪需求。

那么,问题就来到了我的树莓派,What can I do with it?

功能

本次的小项目实现了这么几个功能:

  1. 通过ESP32连接Wi-Fi。
  2. 通过爬虫,检测博客是否宕机。
  3. 通过计时功能,每隔一个小时检测。
  4. 能够计算每天的宕机次数,并显示在一个八段数码管上。

ESP32

首先我们来简单介绍一下ESP32究竟是什么,通俗来讲,ESP32就是一个「带有Wi-Fi、蓝牙功能的微型电脑」,可以通过「一些管脚控制其它的电子外设工作」。长这个样子:

如您所见,在电路板的两侧有两排引脚,可以输出数字信号,接收信号,并对信号进行处理。在下面,是一个Micro USB接口,可以连接电脑下载程序,也可以连接充电器作为供电接口。

MicroPython

嵌入式通常使用C语言进行开发,但是最近几年也出现了能够用Python语言进行开发的方法——MicroPython。MicroPython就是为嵌入式设备专门设计的一种Python语言,是常用Python语言的精简版,也增加了一些嵌入式设备独有的库。利用MicroPython开发,相比于C语言效率非常高,牺牲的是一部分性能和存储空间。

环境配置

安装Thonny,随后右下角-「配置解释器」,选择MicroPython(ESP32),选择好端口,然后点击「安装或更新MicroPython(esptool)」,然后根据自己板子的实际情况,填好相关内容,下载即可。

当写好Python文件时,只需要在Thonny中点击「视图-文件」,然后在写好的文件上右键,点选「上传到/」即可。在ESP32中,只有main.py才会在上电后直接运行。

接线

这边本来想用FritZing画一个面包板连线图的,但是没有找到板子的资料,姑且口述吧,这里也不是特别重要。

面包板上有这么几个东西:一个红色LED、一个绿色LED、一个八段数码管、三个适当阻值的电阻、一个按钮、一块ESP32和若干杜邦线。

  1. 连接LED:随便找两个引脚,分别引出两根线,分别接到红绿LED的正极引脚,两个LED的负极引脚分别接到电阻上,然后接地。
  2. 连接数码管:我所使用的是5011AS共阴八段数码管,通过查询引脚图,则将3号和8号引脚接地,其余引脚连接到适当引脚即可。在ESP32中,大于34的引脚为纯输入引脚,所以需要选择34以内的引脚连接。
  3. 连接按键:我所使用的是四脚按键,这种按键长边的两个引脚是默认导通的,短边的两个引脚是不导通的,所以,可以在一个引脚上接一个电阻,随后接到ESP32的引脚上,另一个短边引脚则接地。

LED是为了显示「网络连接错误」和「正在验证博客状态」的,数码管是为了显示一天之内的宕机次数,而按键则是为了开启数码管,只有按下才开启数码管显示。

代码逻辑

代码逻辑其实很简单,可以分为以下几个部分:

  1. 初始化引脚。
  2. 连接Wi-Fi网络。
  3. 第一次检测网站是否宕机。
  4. 主循环:
    1. 检测按钮是否被按下。
    2. 检测时间是否满足要求。

初始化引脚

这里的操作很简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if __name__ == "__main__":
# Init GPIOs
error_light_pin = 23
working_light_pin = 22
eight_a = 25
eight_b = 26
eight_c = 19
eight_d = 18
eight_e = 17
eight_f = 32
eight_g = 33
eight_dot = 16
button_monitor = 13
eight_a_led = Pin(eight_a, Pin.OUT)
eight_b_led = Pin(eight_b, Pin.OUT)
eight_c_led = Pin(eight_c, Pin.OUT)
eight_d_led = Pin(eight_d, Pin.OUT)
eight_e_led = Pin(eight_e, Pin.OUT)
eight_f_led = Pin(eight_f, Pin.OUT)
eight_g_led = Pin(eight_g, Pin.OUT)
eight_dot_led = Pin(eight_dot, Pin.OUT)
error_led = Pin(error_light_pin, Pin.OUT)
working_led = Pin(working_light_pin, Pin.OUT)
button = Pin(button_monitor, Pin.IN, Pin.PULL_UP)

连接Wi-Fi

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Init Networks
SSID = "<YOUR WIFI SSID>"
PSWD = "<YOUR WIFI PSWD>"
wlan = network.WLAN(network.STA_IF)
wlan.active(True)

# Connection
print("Connecting to {SSID}")
wlan.connect(SSID, PSWD)
while not wlan.isconnected():
error_led.value(1)
time.sleep(1)
error_led.value(0)
print("Done.")

WIFI通常有AP和STA模式,AP相当于热点,STA相当于客户端。

检测网站是否宕机

这里就使用HTTP状态码进行检测,逻辑如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def get_status_code():
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36',
...
}

url = "https://www.coderlock.site"
rqg = requests.get(url, headers=headers)
return int(rqg.status_code)

def work(working_led):
fail_time = 0
working_led.value(1)
status_code = get_status_code()
if status_code != 200:
fail_time = 1
working_led.value(0)
return fail_time

在主函数中:

1
2
3
fail_time = 0
print("Start Working!")
fail_time += work(working_led)

检测按键是否被按下

我们的按键接地,所以在引脚内部要使用上拉输入,检测逻辑如下:

1
2
3
4
5
6
7
8
while True:
if button.value() == 0:
print("Button Pressed!")
num_list = show_num_list(fail_time % 10)
num_list.append(1 if fail_time > 10 else 0)
show_num(num_list, eight_a_led, eight_b_led, eight_c_led, eight_d_led, eight_e_led, eight_f_led, eight_g_led, eight_dot_led)
time.sleep(3)
show_num([0,0,0,0,0,0,0,0], eight_a_led, eight_b_led, eight_c_led, eight_d_led, eight_e_led, eight_f_led, eight_g_led, eight_dot_led)

这里其实最好加一个防抖处理。我将dot位用作十位。

显示数字

显示数字没什么好说的,就是根据想要的数字,分别控制不同引脚的高电平,我们的是共阴数码管,所以给高电平是亮:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
def show_num_list(num: int):
res = [0 for i in range(7)]
if num == 0:
res = [1,1,1,1,1,1,0]
elif num == 1:
res = [0,1,1,0,0,0,0]
elif num == 2:
res = [1,1,0,1,1,0,1]
elif num == 3:
res = [1,1,1,1,0,0,1]
elif num == 4:
res = [0,1,1,0,0,1,1]
elif num == 5:
res = [1,0,1,1,0,1,1]
elif num == 6:
res = [1,0,1,1,1,1,1]
elif num == 7:
res = [1,1,1,0,0,0,0]
elif num == 8:
res = [1,1,1,1,1,1,1]
elif num == 9:
res = [1,1,1,1,0,1,1]
else:
pass
return res

def show_num(num_list, eight_a_led, eight_b_led, eight_c_led, eight_d_led, eight_e_led, eight_f_led, eight_g_led, eight_dot_led):
eight_a_led.value(num_list[0])
eight_b_led.value(num_list[1])
eight_c_led.value(num_list[2])
eight_d_led.value(num_list[3])
eight_e_led.value(num_list[4])
eight_f_led.value(num_list[5])
eight_g_led.value(num_list[6])
eight_dot_led.value(num_list[7])

检测时间

我设定的是一个小时检测一次:

1
2
3
4
5
6
curr_hour, curr_min, curr_sec = time.localtime()[3:6]
if curr_hour == 23:
fail_time = 0
if curr_min == 0 and curr_sec == 0:
print("Scanning...")
fail_time += work(working_led)

完整代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
import network
from machine import Pin
import time
import requests

error_light_pin = 23

def led_on(led):
while True:
led.value(1)
time.sleep(1)

def show_num_list(num: int):
res = [0 for i in range(7)]
if num == 0:
res = [1,1,1,1,1,1,0]
elif num == 1:
res = [0,1,1,0,0,0,0]
elif num == 2:
res = [1,1,0,1,1,0,1]
elif num == 3:
res = [1,1,1,1,0,0,1]
elif num == 4:
res = [0,1,1,0,0,1,1]
elif num == 5:
res = [1,0,1,1,0,1,1]
elif num == 6:
res = [1,0,1,1,1,1,1]
elif num == 7:
res = [1,1,1,0,0,0,0]
elif num == 8:
res = [1,1,1,1,1,1,1]
elif num == 9:
res = [1,1,1,1,0,1,1]
else:
pass
return res

def show_num(num_list, eight_a_led, eight_b_led, eight_c_led, eight_d_led, eight_e_led, eight_f_led, eight_g_led, eight_dot_led):
eight_a_led.value(num_list[0])
eight_b_led.value(num_list[1])
eight_c_led.value(num_list[2])
eight_d_led.value(num_list[3])
eight_e_led.value(num_list[4])
eight_f_led.value(num_list[5])
eight_g_led.value(num_list[6])
eight_dot_led.value(num_list[7])

def get_status_code():
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36',
...
}

url = "https://www.coderlock.site"
rqg = requests.get(url, headers=headers)
return int(rqg.status_code)

def work(working_led):
fail_time = 0
working_led.value(1)
status_code = get_status_code()
if status_code != 200:
fail_time = 1
working_led.value(0)
return fail_time

if __name__ == "__main__":
# Init LEDs
error_light_pin = 23
working_light_pin = 22
eight_a = 25
eight_b = 26
eight_c = 19
eight_d = 18
eight_e = 17
eight_f = 32
eight_g = 33
eight_dot = 16
button_monitor = 13
eight_a_led = Pin(eight_a, Pin.OUT)
eight_b_led = Pin(eight_b, Pin.OUT)
eight_c_led = Pin(eight_c, Pin.OUT)
eight_d_led = Pin(eight_d, Pin.OUT)
eight_e_led = Pin(eight_e, Pin.OUT)
eight_f_led = Pin(eight_f, Pin.OUT)
eight_g_led = Pin(eight_g, Pin.OUT)
eight_dot_led = Pin(eight_dot, Pin.OUT)
error_led = Pin(error_light_pin, Pin.OUT)
working_led = Pin(working_light_pin, Pin.OUT)
button = Pin(button_monitor, Pin.IN, Pin.PULL_UP)

# Init Networks
SSID = "<YOUR SSID HERE>"
PSWD = "<YOUR PSWD HERE>"
wlan = network.WLAN(network.STA_IF)
wlan.active(True)

# Connection
print("Connecting to {SSID}")
wlan.connect(SSID, PSWD)
while not wlan.isconnected():
error_led.value(1)
time.sleep(1)
error_led.value(0)
print("Done.")

# Init Time
fail_time = 0
print("Start Working!")
fail_time += work(working_led)

# Main Function
print("Looping!")
while True:
if button.value() == 0:
print("Button Pressed!")
num_list = show_num_list(fail_time % 10)
num_list.append(1 if fail_time > 10 else 0)
show_num(num_list, eight_a_led, eight_b_led, eight_c_led, eight_d_led, eight_e_led, eight_f_led, eight_g_led, eight_dot_led)
time.sleep(3)
show_num([0,0,0,0,0,0,0,0], eight_a_led, eight_b_led, eight_c_led, eight_d_led, eight_e_led, eight_f_led, eight_g_led, eight_dot_led)

curr_hour, curr_min, curr_sec = time.localtime()[3:6]
if curr_hour == 23:
fail_time = 0
if curr_min == 0 and curr_sec == 0:
print("Scanning...")
fail_time += work(working_led)
文章作者:
文章链接: https://www.coderlock.site/2026/01/22/【ESP32-MicroPython】基于ESP32的博客状态监控器/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 寒夜雨