NodeMCU(ESP8266)使用UDP控制8x8点阵显示

前言

之前写一篇关于 Arduino Max7219 案例,展示如何使用arduino+Max7219控制8x8点阵显示内容。最近恰好在搞esp8266,所以想用(esp8266+8x8点阵)做一个时钟出来, 但是无奈当时就只有一个8x8的点阵,做时钟需要一个32x8的点阵;所以就先拿这个8x8点阵试试效果。众所周知搞点阵显示是需要取模的, 但是取模毕竟是程序上的效果,并非真实的显示效果,所以我就在想为啥不能用手机来控制点阵取模, 直接就能看到效果,不满意还能直接改不用每次都写入到程序中去,说干就干。

视频展示

废话不多说,先发一个效果视频。

原理

其实原理比较简单;

  1. ESP8266连接上WiFi,然后开启UDP服务,端口为1234
  2. 在同一路由器的网络下,用户通过微信小程序向esp8266广播数据
  3. esp8266接收到数据以后就向Max7219点阵中写入数据

硬件部分

关于MAX72198x8点阵的介绍我就不搬运了,大家有兴趣可以参考这篇文章,写的比较详细:

Arduino 学习笔记 | 单片机控制驱动MAX7219 8*8 LED点阵显示模块

WIFI UPD库函数啥的可以参考这篇(里面包括UDP协议的介绍):
太极创客 ESP8266 – WiFiUDP库

硬件接线

接线可参考如下接线图(不擅长画图,随便画一画):

代码

秉承不重复造轮子的思想(其实是不想自己去摸索),驱动max7219我们使用了LedControl库;这个库默认是没有的, 需要自己到库文件管理中搜索(工具->管理库->搜索LedControl->选第一个);

代码:

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
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <LedControl.h>

#define ssid "WiFi名称"
#define password "WiFi密码"
#define upd_port 1234
int DIN = D7;
int CS = D6;
int CLK = D5;

// 示例化对象
LedControl lc = LedControl(DIN, CLK, CS, 1);
//实例化WiFiUDP对象
WiFiUDP Udp;
// 等待连接WiFi图案
byte wifiicon[8] = {0x3C, 0x42, 0x99, 0x24, 0x42, 0x18, 0x0, 0x18};
// 接收UDP数据包数组
byte packetBuffer[9];

void setup() {
// 打开串口
Serial.begin(115200);
// 启动时,MAX72XX处于省电模式
lc.shutdown(0, false);
// 将亮度设置为最大值
lc.setIntensity(0, 8);
// 清除显示
lc.clearDisplay(0);
// 显示连接wifiicon
show(wifiicon);
// 连接到wifi
WiFi.begin(ssid, password);
// 等待连接
while (WiFi.status() != WL_CONNECTED) {
delay(5000);
}
Serial.println("连接成功");
// 启动Udp监听服务
if (Udp.begin(upd_port)) {
Serial.println("监听成功");
// 打印本地的ip地址,在UDP工具中会使用到
//WiFi.localIP().toString().c_str()用于将获取的本地IP地址转化为字符串
Serial.printf("现在收听IP:%s, UDP端口:%d\n", WiFi.localIP().toString().c_str(), upd_port);
} else {
Serial.println("监听失败");
}
// 初始化完成显示一个动画
animation();
lc.clearDisplay(0);
}

void loop() {
//解析Udp数据包
int packetSize = Udp.parsePacket();
//解析包不为空
if (packetSize) {
//收到Udp数据包
//Udp.remoteIP().toString().c_str()用于将获取的远端IP地址转化为字符串
Serial.printf("收到来自远程IP:%s(远程端口:%d)的数据包字节数:%d\n", Udp.remoteIP().toString().c_str(), Udp.remotePort(), packetSize);
Udp.read(packetBuffer, 9);
// 这里我们将第9位数据固定为某个值,用于判断我们的数据包格式是否正常,(避免随便发个数据包都可以生效)
if (packetBuffer[8] == 0xef) {
show(packetBuffer);
//向udp工具发送消息
Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
char replyPacket[1] = {0x01};
//把数据写入发送缓冲区
Udp.write(replyPacket);
//发送数据
Udp.endPacket();
}
}
}

/**
显示内容
*/
void show(byte *data) {
for (int i = 0; i < 8; i++) {
lc.setRow(0, i, data[i]);
}
}

/**
开机动画
*/
void animation() {
byte temp[64][8];
int a = 0x1, b = 0x00, fx = 0x00;
for (int i = 0; i < 64; i++) {
// 重置数据
if (b == 0xff || b == 0x00) {
fx = fx == 0x00 ? 0x01 : 0x00;
a = fx == 0x00 ? 0x1 : 0x80;
b = 0x00;
} else {
a = fx == 0x00 ? (a << 0x1) : (a >> 0x1) ;
}
b += a | 0x00;
for (int j = 0; j <= 8; j++) {
if (j == i / 8) {
temp[i][i / 8] = (byte)b;
} else if (j < i / 8) {
temp[i][j] = (byte)0xff;
} else {
temp[i][j] = (byte)0x00;
}
}
}
for (int i = 0; i < 64; i++) {
for (int j = 0; j < 8; j++) {
lc.setRow(0, j, temp[i][j]);
delay(10);
}
}
}

微信小程序

为了方便操作,这里我们直接使用微信小程序来控制。

  • 如果想自己增加更多功能,这里有微信小程序的开源代码(其实也没多少代码):

    esp8266-udp-lattice

  • 如果你只是想体验一下这个功能,可以使用我个人的微信小程序(微信扫码进入即可):

结尾

这里我提供一个8x8点阵的在线取模工具,做的比较粗糙,如果有需要改进的地方欢迎在评论区留言。

8x8点阵的在线取模工具

参考文章

Arduino Max7219 案例

太极创客 ESP8266 – WiFiUDP库

Arduino 学习笔记 | 单片机控制驱动MAX7219 8*8 LED点阵显示模块