提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
ESP32学习,驱动LED点阵屏,时钟、日历、天气、新闻显示
—(一)
前言
提示:这里可以添加本文要记录的大概内容:
arduino学习了一段时间,虽然学的不精,也老想着弄点作品。拿到了ESP32这个模块,参考了好多文章资料,就学习着整个作品。跟单片机打交道,不外乎输入输出,屏幕输出是运行结果的显示,就先做个时钟显示吧
一、ESP32是什么?
esp32芯片是espressif乐鑫信息科技推出的一块wifi芯片,拥有40nm工艺、双核32位mcu、2.4ghz双模wifi和蓝牙芯片、主频高达230mhz。esp32芯片采用tensilica xtensa lx6微处理器,包括双核心和单核版本,内置天线开关,rf射频模块,功率放大器,低噪声接收放大器,滤波器和电源管理模块。
双列30P,方便连接接口,手工做个电路板吧。
还有空间,加了电源插针和按钮开关,方便后续开发。
刚开始写文章,错误之处还请指正。
二、简要模块和代码
1.引入能用到的库和HUB75接口
代码如下(示例):
#include <WiFi.h>
#include <WiFiUdp.h>
#include <TimeLib.h>
#include "time.h"
#include <HTTPClient.h>
#include <WebServer.h>
#include <DNSServer.h>
#include <esp_wifi.h>
#include <ESPmDNS.h>
#include <ArduinoJson.h>
//#include <BluetoothSerial.h> //后期可用到蓝牙,相互切换使用
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
#include <U8g2_for_Adafruit_GFX.h>
#include <Preferences.h> //esp32 nvs 存储
#include <Update.h>
#include "OneButton.h" //导入按键检测库
//HUB75对应esp32接口
/*--------------------- 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 //
#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
2.NVS数据读取保存
代码如下(示例):
Preferences prefs; //设定nvs存储名称
//读取nvs存储
void NvsPrefsRead(String Ckey,String mod){ //Ckey 读取键值 mod 读取模式 All 全部读取 待完善
prefs.begin("mynamespace");
if(mod!="All"){
Serial.print("剩余空间: ");Serial.println(prefs.freeEntries());//查询剩余空间
Serial.print("读取: mynamespace .showMode: ");
//showMode 循环显示模式的读取
showMode=(prefs.getString("showMode", "0")).toInt();
flagColor=(prefs.getString("flagColor", "0")).toInt();
Serial.print(showMode);Serial.print(" flagColor: ");Serial.println(flagColor);
}
prefs.end();
}
void NvsPrefsWrite(String Ckey,uint8_t index,String Str){ //Ckey 写入键值 Str 写入内容
prefs.begin("mynamespace");
Serial.print("剩余空间: ");Serial.println(prefs.freeEntries());//查询剩余空间
prefs.putString(Ckey.c_str(), Str);
Serial.print("写入内容: ");Serial.print(Ckey);Serial.print(": "); Serial.println(Str);
Str=prefs.getString(Ckey.c_str(), "默认");
Serial.print("读取内容: ");Serial.print(Ckey);Serial.print(": "); Serial.println(Str);
Serial.print("剩余空间: ");Serial.println(prefs.freeEntries());//查询剩余空间
prefs.end();
}
3.MATRIX HUB75_I2S_CFG 定义和显示
代码如下(示例):
#define PANEL_RES_X 64 //定义矩阵宽度X
#define PANEL_RES_Y 64 // 定义矩阵高度Y
#define PANEL_CHAIN 2 // 数量 128*64 64*2 64
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
//初始化LED屏
void init_LED() {
dma_display = new MatrixPanel_I2S_DMA(mxconfig);
dma_display->begin();
dma_display->setBrightness8(15); //0-255亮度
dma_display->fillScreen(myRED); //全红
dma_display->clearScreen();
dma_display->setCursor(x, y);//设定光标位置
dma_display->setTextSize(1);//字符大小
dma_display->setTextColor(dma_display->color565(255, 255, 0));//颜色
dma_display->print(words);//输出
}
);
4.U8G2中文字库
代码如下(示例):
U8G2_FOR_ADAFRUIT_GFX u8g2Fonts;//定义中文字库
u8g2Fonts.begin(*dma_display);
u8g2Fonts.setFontMode(1);
u8g2Fonts.setFontDirection(0);
u8g2Fonts.setFont(u8g2_font_wqy16_t_gb2312); //16点阵字体
int s= u8g2Fonts.getUTF8Width("木林森");//子串长度(点阵数)
u8g2Fonts.setForegroundColor(dma_display->color565(255, random(100), random(100)));
u8g2Fonts.drawUTF8(80,61,"木林森");//根据点阵位置显示汉字
5.button库的应用
代码如下(示例):
OneButton button(buttonPin, true);
OneButton button2(buttonPin2, true);
//按键函数调用
button.setDebounceMs(80); //设置消抖时长
button.setClickMs(80); //设置最短单击时长
button.setPressMs(5000); //长按最短时长
button.setIdleMs(2000) ; //空闲有效时长
button.attachClick(oneClickPrg);
button.attachDoubleClick(oneClickPrg);
button.attachMultiClick(oneClickPrg);
button.attachLongPressStart(oneClickPrg);
button2.attachClick(twoClickPrg);
button2.attachDoubleClick(twoClickPrg);
button2.attachLongPressStart(twoClickPrg);
//下面代码需放在loop
button.tick(); //按键函数持续关注
button2.tick();
6.网络获取新闻条目
代码如下(示例):
//网络获取新闻条目
//链接示例:Url163="https://3g.163.com/touch/reconstruct/article/list/BAI67OGGwangning/1-1.html"; //163新闻条目 1-1;10-1;15-1 意思: 第15条 获取1条
void News163FromWifi(const char* Url163_){
HTTPClient http;
int httpCode;
http.begin(Url163_);
httpCode = http.GET(); //Make the request
if (httpCode > 0) { //Check for the returning code
String payload = http.getString();
//Serial.println(payload);
StaticJsonDocument<1024> doc; //分配内存,静态
/*
artiList({"BAI67OGGwangning":[{"docid":"ISJ1PNU60514R9OJ",
"source":"环球网资讯","title":"德国防长:德军内部对话在新加坡遭窃听 是\"个人失误\"",
"priority":82,"hasImg":1,"url":"https://3g.163.com/news/article/ISJ1PNU60514R9OJ.html",
"commentCount":282,"imgsrc3gtype":"1","stitle":"",
"digest":"来源:环球时报【环球时报驻德国特约记者青木】俄媒近日曝光德国",
"imgsrc":"http://dingyue.ws.126.net/2024/0306/7a2a5ef7j00s9wct0001ud000sg00izg.jpg",
"ptime":"2024-03-06 10:10:18"}]})
*/
int X1=payload.indexOf("[{"); //读取N@索引 序号
Serial.print("X1: ");Serial.print(X1);
int X2=payload.indexOf("}]"); //读取C@索引 内容
Serial.print(" X2: ");Serial.println(X2);
if(X1>1) payload=payload.substring(X1+1,X2+1);
//Serial.print("payload: ");Serial.println(payload);
DeserializationError error = deserializeJson(doc, payload);
if (error) {
Serial.println("JSON parsing failed!");
} else {
String str=doc["title"].as<String>();
Serial.println(str);
ShowNewsMatrix(str);
}
}else{
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
https://3g.163.com/touch/reconstruct/article/list/BAI67OGGwangning/1-1.html
7.时间、日历、农历、天气界面显示
代码如下(示例):
//表盘界面显示时间
void FaceClockTime(){
initFaceClockTime();
showHour(hou,myColor[flagColor]);
if(minu==minuOld){}else{
FillTab(16,10,24,22,myBLACK);//清屏
if(minu<10){
displayNumber(0,16,8,myColor[flagColor]);
displayNumber(minu,28,8,myColor[flagColor]);
}else{
displayNumber(minu/10,16,8,myColor[flagColor]);
displayNumber(minu%10,28,8,myColor[flagColor]);
}
minuOld=minu;
}
FillTab(22,33,14,8,myBLACK);//清屏
if(sec<10){
drawText("0",22,33);
drawText(String(sec),30,33);
}else{
drawText(String(sec/10),22,33);
drawText(String(sec%10),30,33);
}
dma_display->drawPixel(miaoZB[sec][0]+PianyiX,miaoZB[sec][1]+PianyiY,myWHITE);
if(bigTimeFlag>=15){
//可以加标志显示日期
FillTab(56,0,72,50,myBLACK);//清屏
displayNumbers2(year1,78,0,myColor[flagColor]);
if(month1<10){
displayNumbers2(0,91,0,myColor[flagColor]);
displayNumbers2(month1,99,0,myColor[flagColor]);
}else{
displayNumbers2(month1,99,0,myColor[flagColor]);
}
if(day1<10){
displayNumbers2(0,112,0,myColor[flagColor]);
displayNumbers2(day1,120,0,myColor[flagColor]);
}else{
displayNumbers2(day1,120,0,myColor[flagColor]);
}
//显示农历
u8g2Fonts.setFont(u8g2_font_wqy12_t_gb2312);
u8g2Fonts.setForegroundColor(myColor[rand()%9]);
String nongli=china_animals+" "+china_monthday;
u8g2Fonts.drawUTF8(60,28,nongli.c_str());
//显示天气
String tianqi=weekHZ[week]+ " "+Weather+" "+Temp+"℃";
u8g2Fonts.drawUTF8(60,44,tianqi.c_str());
bigTimeFlag=0;//计数重启
}
bigTimeFlag++;
}
8.天气、农历获取
代码如下(示例):
//网络获取天气信息
void WeitherFromWifi(){
if(weather_getOK==1)return;
String url_xinzhi = "https://api.seniverse.com/v3/weather/now.json?key=";//心知天气API接口网址
url_xinzhi += tqAPI;
url_xinzhi += "&location=";
url_xinzhi += CiTy;
url_xinzhi += "&language=zh-Hans&unit=c";
HTTPClient http;
http.begin(url_xinzhi);
Serial.println(url_xinzhi);
int httpGet = http.GET();
Serial.printf("HTTPGET is %d\n",httpGet);
if(httpGet > 0){
weather_getOK=1;
String json = http.getString();
Serial.println(json);
StaticJsonDocument<1024> doc; //分配内存,静态
deserializeJson(doc, json);
/*{"results":[{"location":{"id":"WWHPMHEV4CS4","name":"临沂","country":"CN","path":"临沂,临沂,山东,中国",
"timezone":"Asia/Shanghai","timezone_offset":"+08:00"},
"now":{"text":"晴","code":"1","temperature":"14"},
"last_update":"2024-02-12T17:50:13+08:00"}]}*/
Weather = doc["results"][0]["now"]["text"].as<String>(); //天气
Temp = doc["results"][0]["now"]["temperature"].as<String>(); // 实况温度
Serial.print(" Weather: ");Serial.print(Weather);Serial.print(" Temp: ");Serial.print(Temp);Serial.println("");Serial.println("");
}else
{
Serial.printf("Wrong code, error: %s\n", http.errorToString(httpGet).c_str());
}
http.end();
}
//网络获取农历换算
void NongliFromWifi(){
if(china_getOK==1)return;
String url_xinzhi = "http://v.juhe.cn/calendar/day?date="; //聚合数据 //农历API接口网址
// http://v.juhe.cn/calendar/day?date=2023-10-23&key=自己的KEY
url_xinzhi += String(year1);
url_xinzhi += "-";
url_xinzhi += String(month1);
url_xinzhi += "-";
url_xinzhi += String(day1);
url_xinzhi += "&key="+nlAPI;
HTTPClient http;
http.begin(url_xinzhi);
int httpGet = http.GET();
Serial.printf("HTTPGET is %d\n",httpGet);
if(httpGet > 0)
{
china_getOK=1;
String json = http.getString();
Serial.println(json);
StaticJsonDocument<1024> doc; //分配内存,静态
/*
//聚合数据内容
{"reason":"Success","result":{"data":{"animalsYear":"兔","weekday":"星期一","lunarYear":"癸卯年","lunar":"九月初九","year-month":"2023-10","date":"2023-10-23","suit":"安葬.入殓.成服.除服.破土.迁坟","avoid":"馀事勿取","holiday":"重阳节","desc":""}},"error_code":0}
*/
deserializeJson(doc, json);
china_year = doc["result"]["data"]["lunarYear"].as<String>(); //农历 年
china_monthday = doc["result"]["data"]["lunar"].as<String>(); // 月
china_animals = doc["result"]["data"]["animalsYear"].as<String>(); // 日
china_holiday = doc["result"]["data"]["holiday"].as<String>();
if(china_holiday=="null"){china_holiday="";}
Serial.print(" 农历: ");Serial.print(china_year);Serial.print(" ");
Serial.print(china_animals);Serial.print(" ");
Serial.print(china_monthday);Serial.print(" ");
Serial.print(china_holiday);Serial.println("");
}else{
Serial.printf("Wrong code, error: %s\n", http.errorToString(httpGet).c_str());
}
http.end();
}
总结
以上是刚学习esp32驱动Matrix LED屏的部分代码模块,也是网络学习总结的,还在逐步完善,后续再增加一些传感器,丰富功能。学习学习还是挺有意义的。等代码上传网盘就跟帖发布。