ESP32学习,驱动LED点阵屏,蓝牙串口通信信息显示屏
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
练手:通过蓝牙串口连接,手机发送,ESP32接收信息,NVS存储,LED屏滚动显示。
前言
信息板虽然简单,用途还是很大的,先练习做个简单的。
蓝牙串口接收,NVS存储接收信息
直接上代码
代码如下(示例):
#include <Arduino.h>
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
#include <U8g2_for_Adafruit_GFX.h>
#include <BluetoothSerial.h>
#include <Preferences.h> //esp32 nvs 存储
#ifdef ESP32
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif
/*--------------------- MATRIX GPIO CONFIG -------------------------*/
#define R1_PIN 25
#define G1_PIN 26
#define B1_PIN 27
#define R2_PIN 14
#define G2_PIN 12
#define B2_PIN 13
#define A_PIN 23
#define B_PIN 19 // Changed from library default
#define C_PIN 5
#define D_PIN 17
#define E_PIN 32 //-1 //32
#define LAT_PIN 4
#define OE_PIN 15
#define CLK_PIN 16
/*--------------------- MATRIX PANEL CONFIG -------------------------*/
#define PANEL_RES_X 64//64 // Number of pixels wide of each INDIVIDUAL panel module.
#define PANEL_RES_Y 64//32 // Number of pixels tall of each INDIVIDUAL panel module.
#define PANEL_CHAIN 2//1 // Total number of panels chained one to another 55 * 4 width MAX
#define PANE_HEIGHT PANEL_RES_X
int16_t PANE_WIDTH=PANEL_RES_Y *PANEL_CHAIN;
HUB75_I2S_CFG::i2s_pins _pins={R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN, A_PIN, B_PIN, C_PIN, D_PIN, E_PIN, LAT_PIN, OE_PIN, CLK_PIN};
HUB75_I2S_CFG mxconfig(
PANEL_RES_X, // width
PANEL_RES_Y, // height
PANEL_CHAIN, // chain length
_pins, // pin mapping
HUB75_I2S_CFG::FM6126A // driver chip
);
MatrixPanel_I2S_DMA *dma_display = nullptr;
uint16_t myBLACK = dma_display->color565(0, 0, 0);
uint16_t myWHITE = dma_display->color565(255, 255, 255);
uint16_t myRED = dma_display->color565(255, 0, 0);
uint16_t myGREEN = dma_display->color565(0, 255, 0);
uint16_t myBLUE = dma_display->color565(0, 0, 255);
/*定义蓝牙串口*/
const char *pin = "1234";
String device_name = "MatrixINFO";
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
#if !defined(CONFIG_BT_SPP_ENABLED)
#error Serial Bluetooth not available or not enabled. It is only available for the ESP32 chip.
#endif
String BTInfo[]={"1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1","1"};
BluetoothSerial SerialBT;//定义蓝牙
U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;//定义字库
Preferences prefs; //设定nvs存储名称
String MacADD;
void setup() {
Serial.begin(115200);
pinMode(2,OUTPUT);
digitalWrite(2,HIGH);
//蓝牙开始
SerialBT.setPin(pin);
SerialBT.begin(device_name); //Bluetooth device name
Serial.print("ESP Board MAC Address: ");
MacADD=WiFi.macAddress();
Serial.println(WiFi.macAddress()); // 串口输出当前ESP32/ESP8266的MAC地址
uint8_t macAddr[6]; // 定义macAddr为uint8_t类型的数组,这个数组含有6个元素。
WiFi.macAddress(macAddr); //MAC地址会储存在这个macAddr数组里面
Serial.printf("用转存到数组的方式获取MAC地址: %02x:%02x:%02x:%02x:%02x:%02x\n", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]);
dma_display = new MatrixPanel_I2S_DMA(mxconfig);
dma_display->begin();
dma_display->setBrightness8(200); //0-255
dma_display->clearScreen();
dma_display->fillScreen(myWHITE);//测试一下满屏
dma_display->fillRect(0, 0, dma_display->width(), dma_display->height(), dma_display->color444(0, 15, 0));
delay(500);
dma_display->drawRect(0, 0, dma_display->width(), dma_display->height(), dma_display->color444(15, 15, 0));
delay(500);
dma_display->clearScreen();
u8g2Fonts.begin(*dma_display);
u8g2Fonts.setFontMode(1);
u8g2Fonts.setFontDirection(0);
u8g2Fonts.setFont(u8g2_font_wqy16_t_gb2312); //
//预存一些信息,自定义的识别符
BTInfo[0]="{N@0C@1辰龙巳蛇午马未羊$M@upR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[1]="{N@0C@2戌狗亥猪申猴酉鸡$M@upR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[2]="{N@0C@3子鼠丑牛寅虎卯兔$M@upR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[3]="{N@0C@4云母屏风烛影深,长河渐落晓星沉。嫦娥应悔偷灵药,碧海青天夜夜心。$M@leftR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[4]="{N@0C@5春雨惊春清谷天 夏满芒夏暑相连 秋处露秋寒霜降 冬雪雪冬小大寒$M@leftR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[5]="{N@0C@6独怜幽草涧边生,$M@upR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[6]="{N@0C@7上有黄鹂深树鸣,$M@upR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[7]="{N@0C@8春潮带雨晚来急,野渡无人舟自横。$M@upR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[8]="{N@0C@9独在异乡为异客,每逢佳节倍思亲。遥知兄弟登高处,遍插茱萸少一人。$M@leftR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[9]="{N@0C@10月落乌啼霜满天,江枫渔火对愁眠。姑苏城外寒山寺,夜半钟声到客船。$M@leftR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[10]="{N@0C@11君问归期未有期,巴山夜雨涨秋池。何当共剪西窗烛,却话巴山夜雨时。$M@leftR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[11]="{N@0C@12日照香炉生紫烟,遥看瀑布挂前川。飞流直下三千尺,疑是银河落九天。$M@leftR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[12]="{N@0C@13隐隐飞桥隔野烟,石矶西畔问渔船。桃花尽日随流水,洞在清溪何处边。$M@leftR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[13]="{N@0C@14北国风光 千里冰封万里雪飘$M@upR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[14]="{N@0C@15望长城内外 惟余莽莽 大河上下 顿失滔滔$M@upR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
BTInfo[15]="{N@0C@16山舞银蛇 原驰蜡象 欲与天公试比高$M@upR$200G$199B$200T$10E$F}" ;//up 静态屏 //left 滚动屏
NvsPrefsRead();//初始化读取NVS存储
Serial.println(F("*****************************************************"));
Serial.println(F("* ESP32-HUB75-MatrixPanel-Infomation *"));
Serial.println(F("*****************************************************"));
Serial.printf("The device with name \"%s\" is started.\nNow you can pair it with Bluetooth!\n", device_name.c_str());
}
uint8_t wheelval = 0;
void loop() {
ShowMartixInfo();
digitalWrite(2,!digitalRead(2));
}
void ShowMartixInfo(){
int16_t s;
for(int i=0;i<50;i++){
String Str=BTInfo[i];
if(Str.length()>10){
int X1=Str.indexOf("N@"); //读取N@索引 序号
int X2=Str.indexOf("C@"); //读取C@索引 内容
int X3=Str.indexOf("$M@"); //读取$M@索引 运动方式
int X4=Str.indexOf("R$"); //读取R$索引 颜色 红
int X5=Str.indexOf("G$"); //读取G$索引 颜色 绿
int X6=Str.indexOf("B$"); //读取B$索引 颜色 蓝
int X7=Str.indexOf("T$"); //读取T$索引 时间
int X8=Str.indexOf("E$F"); //读取E$F索引 结束符
String tmpStr=Str.substring(X2+2,X3); //截取有效字符串
String MovStr=Str.substring(X3+3,X4); //截取运动方式
SerialBT.print("i: ");SerialBT.print(i);SerialBT.print("tmpStr: ");SerialBT.print(tmpStr);SerialBT.print(" Mov: ");SerialBT.println(MovStr);
Serial.print("i: ");Serial.print(i);Serial.print(" tmpStr: ");Serial.print(tmpStr);Serial.print(" Mov: ");Serial.println(MovStr);
Serial.print("StrLen: ");Serial.println(u8g2Fonts.getUTF8Width(tmpStr.c_str()));
if(MovStr=="left"){
s= u8g2Fonts.getUTF8Width(tmpStr.c_str());
//Serial.print("getUTF8Width:left ");Serial.println(tmpStr);
u8g2Fonts.setForegroundColor(dma_display->color565(255, random(100), random(100)));
u8g2Fonts.drawUTF8(0,16,tmpStr.c_str());
u8g2Fonts.setForegroundColor(dma_display->color565(random(100), 255, random(100)));
u8g2Fonts.drawUTF8(0,38,tmpStr.c_str());
u8g2Fonts.setForegroundColor(dma_display->color565(255, random(100), 255));
u8g2Fonts.drawUTF8(0,61,tmpStr.c_str());
for (size_t i = 20; i < s; i=i+s/200){ //+PANE_WIDTH/2
dma_display->fillRect(0, 0, PANE_WIDTH,20, dma_display->color444(0, 0, 0));
u8g2Fonts.setForegroundColor(dma_display->color565(255, random(100), random(100)));
u8g2Fonts.drawUTF8(-i+PANE_WIDTH,16,tmpStr.c_str());
delay(20);
BTCallback();
}
for (size_t i = 20; i < s; i=i+s/200){ //+PANE_WIDTH/2
dma_display->fillRect(0, 22, PANE_WIDTH,20, dma_display->color444(0, 0, 0));
u8g2Fonts.setForegroundColor(dma_display->color565(random(100), 255, random(100)));
u8g2Fonts.drawUTF8(-i+PANE_WIDTH,38,tmpStr.c_str());
delay(20);
BTCallback();
}
for (size_t i = 20; i < s; i=i+s/200){ //+PANE_WIDTH/2
dma_display->fillRect(0, 43, PANE_WIDTH,20, dma_display->color444(0, 0, 0));
u8g2Fonts.setForegroundColor(dma_display->color565(255, random(100), 255));
u8g2Fonts.drawUTF8(-i+PANE_WIDTH,61,tmpStr.c_str());
delay(20);
BTCallback();
}
BTCallback();
delay(50);//if(i%128==0)delay(3000);
dma_display->clearScreen();
}else{
//Serial.print("getUTF8Width:up ");Serial.println(tmpStr);
String Str1=BTInfo[i+1];
String Str2=BTInfo[i+2];
String tmpStr1="";
String tmpStr2="";
X1=Str1.indexOf("N@"); //读取N@索引 序号
X2=Str1.indexOf("C@"); //读取C@索引 内容
X3=Str1.indexOf("$M@"); //读取$M@索引 运动方式
if(X1 == 1){
tmpStr1=Str1.substring(X2+2,X3); //截取有效字符串
}else{tmpStr1=tmpStr;}
X1=Str2.indexOf("N@"); //读取N@索引 序号
X2=Str2.indexOf("C@"); //读取C@索引 内容
X3=Str2.indexOf("$M@"); //读取$M@索引 运动方式
if(X1 == 1){
tmpStr2=Str2.substring(X2+2,X3); //截取有效字符串
}else{tmpStr2=tmpStr;}
u8g2Fonts.setFont(u8g2_font_wqy16_t_gb2312);
u8g2Fonts.setForegroundColor(dma_display->color565(255, random(100), random(100)));
u8g2Fonts.drawUTF8(1,16,tmpStr.c_str());// 一行显示8个字 共3行
u8g2Fonts.setForegroundColor(dma_display->color565(random(100), 255, random(100)));
u8g2Fonts.drawUTF8(1,38,tmpStr1.c_str());
u8g2Fonts.setForegroundColor(dma_display->color565(255, random(100), 255));
u8g2Fonts.drawUTF8(1,61,tmpStr2.c_str());
int16_t sS,Ss;
sS = u8g2Fonts.getUTF8Width(tmpStr.c_str());Ss=u8g2Fonts.getUTF8Width("矩阵信息隆重招商");
if(sS<=Ss){}else{
Serial.print(tmpStr.length());Serial.print(" 长度0 sS= ");Serial.print(sS);Serial.print(" Ss= ");Serial.println(Ss);
for(int jj=0;jj<2;jj++){
for (size_t ij = 0; ij <sS-Ss; ij=ij+1){
u8g2Fonts.setForegroundColor(dma_display->color565(255, random(100), random(100)));
u8g2Fonts.drawUTF8(-ij,16,tmpStr.c_str());// 一行显示8个字 共3行
delay(20);BTCallback();
dma_display->fillRect(0, 0, PANE_WIDTH,20, dma_display->color444(0, 0, 0));
}
for (size_t ij = 0; ij <sS-Ss; ij=ij+1){
dma_display->fillRect(0, 0, PANE_WIDTH,20, dma_display->color444(0, 0, 0));
u8g2Fonts.setForegroundColor(dma_display->color565(255, random(100), random(100)));
u8g2Fonts.drawUTF8(-sS+Ss+ij,16,tmpStr.c_str());// 一行显示8个字 共3行
delay(20);BTCallback();
}}
}
sS = u8g2Fonts.getUTF8Width(tmpStr1.c_str());Ss=u8g2Fonts.getUTF8Width("矩阵信息隆重招商");
if(sS<=Ss){}else{
Serial.print(tmpStr1.length());Serial.print(" 长度1 sS= ");Serial.print(sS);Serial.print(" Ss= ");Serial.println(Ss);
for(int jj=0;jj<2;jj++){
for (size_t ij = 0; ij <sS-Ss; ij=ij+1){
u8g2Fonts.setForegroundColor(dma_display->color565(random(100),255, random(100)));
u8g2Fonts.drawUTF8(-ij,38,tmpStr1.c_str());// 一行显示8个字 共3行
delay(20);BTCallback();
dma_display->fillRect(0, 22, PANE_WIDTH,20, dma_display->color444(0, 0, 0));
}
for (size_t ij = 0; ij <sS-Ss; ij=ij+1){
dma_display->fillRect(0, 22, PANE_WIDTH,20, dma_display->color444(0, 0, 0));
u8g2Fonts.setForegroundColor(dma_display->color565(random(100),255, random(100)));
u8g2Fonts.drawUTF8(-sS+Ss+ij,38,tmpStr1.c_str());// 一行显示8个字 共3行
delay(20);BTCallback();
}}
}
sS = u8g2Fonts.getUTF8Width(tmpStr2.c_str());Ss=u8g2Fonts.getUTF8Width("矩阵信息隆重招商");
if(sS<=Ss){}else{
Serial.print(tmpStr2.length());Serial.print(" 长度2 sS= ");Serial.print(sS);Serial.print(" Ss= ");Serial.println(Ss);
for(int jj=0;jj<2;jj++){
for (size_t ij = 0; ij <sS-Ss; ij=ij+1){
u8g2Fonts.setForegroundColor(dma_display->color565(255, random(100),255 ));
u8g2Fonts.drawUTF8(-ij,61,tmpStr2.c_str());// 一行显示8个字 共3行
delay(20);BTCallback();
dma_display->fillRect(0, 43, PANE_WIDTH,20, dma_display->color444(0, 0, 0));
}
for (size_t ij = 0; ij <sS-Ss; ij=ij+1){
dma_display->fillRect(0, 43, PANE_WIDTH,20, dma_display->color444(0, 0, 0));
u8g2Fonts.setForegroundColor(dma_display->color565(255, random(100),255 ));
u8g2Fonts.drawUTF8(-sS+Ss+ij,61,tmpStr2.c_str());// 一行显示8个字 共3行
delay(20);BTCallback();
}}
}
BTCallback();
delay(6000);
i=i+2;
dma_display->clearScreen();
BTCallback();
tmpStr= "矩阵信息隆重招商" ; //receivedString.substring(X2+2,X1); //截取有效字符串
int lenStr=tmpStr.length();
Serial.print("lenStr: ");Serial.print(lenStr);Serial.print(" tmpStr: ");Serial.println(tmpStr);
//根据宽度 通过计算 摆动显示
}
//此处统计播放内容和次数累计 读取某条目 序号,播放次数
}
}
}
void MartixInfo(String Str){//解析串口数据 进行矩阵Led显示
int X1=Str.indexOf("N@"); //读取N@索引 序号
int X2=Str.indexOf("C@"); //读取C@索引 内容
int X3=Str.indexOf("$M@"); //读取$M@索引 运动方式
int X4=Str.indexOf("R$"); //读取R$索引 颜色 红
int X5=Str.indexOf("G$"); //读取G$索引 颜色 绿
int X6=Str.indexOf("B$"); //读取B$索引 颜色 蓝
int X7=Str.indexOf("T$"); //读取T$索引 时间 ->不用时间改成单条序列号
int X8=Str.indexOf("E$F"); //读取E$F索引 结束符
int Num=Str.substring(X1+2,X2).toInt(); //截取有效字符串
Serial.print("X1: ");Serial.print(X1);Serial.print(" X2: ");Serial.print(X2);Serial.print(" X3: ");Serial.print(X3);Serial.print(" X4: ");Serial.println(X4);
Serial.print("Num: ");Serial.println(Num);
if(X1!=0 && X3!=0 && X8!=0){
BTInfo[Num]=Str;
NvsPrefsWrite(Num,Str);
//Serial.println(BTInfo[Num]);
}else{Serial.println("警告:字符信息不合规!");}
//BTInfo
}
void BTCallback(){ //在中断函数中读取蓝牙串口数据
if (SerialBT.available()) {
String receivedString = SerialBT.readStringUntil('\n'); // 读取到换行符为止的字符串
Serial.print(" receivedString: ");Serial.println(receivedString);
//调用数据读取函数
int lenStr=receivedString.length(); //字符串长度
int X1=receivedString.indexOf("$M@"); //判断合法符号
int X2=receivedString.indexOf("C@"); //判断合法符号
Serial.print(" lenstr: ");Serial.print(lenStr);Serial.print(" indexX1: ");Serial.println(X1);
String tmpStr=receivedString.substring(X2+2,X1); //截取有效字符串 矩阵信息隆重招商
lenStr=tmpStr.length();
Serial.print("lenStr: ");Serial.print(lenStr);Serial.print(" tmpStr: ");Serial.println(tmpStr);
if(tmpStr=="NvsClear"){
NvsPrefsClear();//
}else if(tmpStr.substring(0,5)=="light"){//设置亮度 0-255 light220 设置亮度220
int len=tmpStr.length();
String str=tmpStr.substring(5,len);
len=str.toInt();
if(len>=0 && len <=255){
Serial.print("light: ");Serial.println(len);
dma_display->setBrightness8(len);
}else{Serial.print("light: outrang ");Serial.println(len);}
}else{
if(lenStr>10)MartixInfo(receivedString);
}
}
}
void NvsPrefsRead(){
prefs.begin("mynamespace");
Serial.println("读取: ");
Serial.print("剩余空间: ");Serial.println(prefs.freeEntries());//查询剩余空间
char str[5];
for(int i=0;i<50;i++){
itoa(i,str,10);
BTInfo[i]=prefs.getString(str, BTInfo[i]);
Serial.print("序号: ");Serial.print(str);Serial.print(" 内容: ");Serial.println(BTInfo[i]);
}
prefs.end();
}
void NvsPrefsWrite(uint8_t index,String Str){
prefs.begin("mynamespace");
Serial.print("剩余空间: ");Serial.println(prefs.freeEntries());//查询剩余空间
char str[5];
itoa(index,str,10);
prefs.putString(str, Str);
Serial.print("写入内容: ");Serial.print(str);Serial.print(" "); Serial.println(Str);
BTInfo[index]=prefs.getString(str, "默认");
Serial.print("读取内容: ");Serial.print(str);Serial.print(" "); Serial.println(BTInfo[index]);
Serial.print("剩余空间: ");Serial.println(prefs.freeEntries());//查询剩余空间
prefs.end();
}
void NvsPrefsClear(){
prefs.begin("mynamespace"); //NvsClear 清除指令
Serial.print("清除空间:mynamespace! 现有剩余:");Serial.println(prefs.freeEntries());//查询剩余空间
prefs.clear();
Serial.print("剩余空间:");Serial.println(prefs.freeEntries());//查询剩余空间
prefs.end();
}
总结
代码简单,有注解,包括NVS存储读取,蓝牙串口通信等,不足之处还请指正。