去年做了个基于oled屏幕的小电视,但是受限于技术力和屏幕尺寸限制,做出来的东西只能说是很不完善。

正好看到了vfd屏幕,很酷,决定做一个。

1 用u8g2库点亮vfd屏幕

1.1 u8g2库的安装

淘宝卖家给了个魔改过的u8g2库,我很不解,但是很好用(bushi

vfd屏u8g2库 – 天鹅绒房间 (qwqpap.xyz)

关于u8g2库的安装这里简略说明

解压放在你arduino ide 的\Arduino\libraries\下就可以。

1.2 u8g2库的使用方法

首先我们需要屏幕驱动的名字,然后创建对应的对象就可以啦。

对于本例而言,我们使用一块分辨率 256*50, 驱动为GP1287AI的vfd屏幕,故你的代码应该开头包含这样一段

#include <U8g2lib.h>
U8G2_GP1287AI_256X50_1_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 15, /* reset=*/ 2);

那么传递的参数就是自定义的接线了

比如此例中SCK线接的18 SDA接的23,而CS和RESET如上,是自定义的15和2,还得记得给灯丝使能一个高电平信号才能亮熬。

具体的线如图,接反了可能会干烂不少东西(

然后是初始化和输出一行文字

我们需要了解的是u8g2的坐标系是以左上角为0点,→为x,↓为y,字体会在虚拟光标坐标的右上角开始打印。

这是一个知识水平不太高的实例。

#include <U8g2lib.h>
U8G2_GP1287AI_256X50_1_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 15, /* reset=*/ 2);
void setup(void) {
  u8g2.begin();//初始化u8g2库
  u8g2.setContrast(255);//亮度设置 0-255
  u8g2.enableUTF8Print();///使用utf8
}
void loop(void) {
  u8g2.setFont(u8g2_font_wqy12_t_gb2312); //设置中文字体
  //u8g2.firstPage();
  do {
    u8g2.setCursor(0, 20);//设置光标位置
    u8g2.print("苟利国家生死以");//打印文本	
    u8g2.setCursor(0, 40);
    u8g2.print("岂因祸福避趋之");
  } while ( u8g2.nextPage() );
  delay(2000);
}

所以可以用来做一些很酷的例子了。

对于本例而言,已经可以实现基本的功能了捏

1.3 u8g2库的各个函数

这个实在是太多了,我有空整理整理

2 获取天气预报

这里使用和风天气的api来获取数据,需要提前的和风天气注册一个账号获得你的私钥

当然,为了不自己搓解析json的数据,我们来调用有的库:ESP32_Heweather.h

非常感谢这个大佬的库,实在是方便啊啊啊

请在arduino ide里面安装,好像是有什么很重要的依赖来着qwq

2.1初始化和调用

#include <ESP32_Heweather.h>
#include <Wire.h>
#include "stdio.h"
const char* ssid     = "Triority";     // WiFi名称
const char* password = "@"; // WiFi密码

String UserKey = "**********************************";   // 私钥 https://dev.heweather.com/docs/start/get-api-keyx
String Location = "1******"; // 城市代码 https://github.com/heweather/LocationList,表中的 Location_ID
String Unit = "m";             // 公制-m/英制-i
String Lang = "zh";            // 语言 英文-en/中文-zh
//注意,使用中文请务必确保使用u8g2的中文字体和utf8编码,不然会寄
float ROUND = 1;             // 更新间隔<小时>空气质量API 1小时更新一次
WeatherNow weatherNow;         // 建立weatherNow对象
WeatherForecast WeatherForecast;  
AirQuality AirQuality; 

//这个是连接wifi的函数捏
void ConnectWiFi(){
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to ");
  Serial.print(ssid);
 
  int i = 0;
  while (WiFi.status() != WL_CONNECTED && (i < 10)) {
    delay(1000);
    Serial.print('.');
    i++;
  }
  if (i == 10) { // 10s失败
 
    Serial.println("WiFi Connection Failed");
  } else { // 成功
 
  }
}
void setup(void) {
  
  ConnectWiFi();
  delay(2000);               //连接wifi
  weatherNow.config(UserKey, Location, Unit, Lang);
  WeatherForecast.config(UserKey, Location, Unit, Lang); 
  AirQuality.config(UserKey, Location, Unit, Lang);

 
  
}

2.2 把天气打印在屏幕

当成功更新天气,weathernow.get()返回一个true的布尔值,根据这个我们可以这样来写

if(weatherNow.get()){
    WeatherForecast.get();
    AirQuality.get();
 

  
 
  
  
    sprintf(line_1,"北京市 昌平区");
    sprintf(line_2,"预报温度:%d°C 最低:%d°C",weatherNow.getTemp(),WeatherForecast.getTempMin(0));
    sprintf(line_3,"当前天气:%s 明日:%s",weatherNow.getWeatherText(),WeatherForecast.getTextDay(1));
    sprintf(line_4,"风力: %d 体感温度: %d°C",weatherNow.getWindScale(),weatherNow.getFeelLike());
    sprintf(line_5,"降雨量: %3.1fmm 紫外强度: %d",weatherNow.getPrecip(),WeatherForecast.getUvIndex(0));
    sprintf(line_6,"空气质量:%s",AirQuality.getCategory());
  u8g2.setFont(u8g2_font_wqy12_t_gb2312); //设置中文字体
  u8g2.firstPage();
  do {
    u8g2.setCursor(0, 10);
    u8g2.print(line_1);	
    u8g2.setCursor(0,20);
    u8g2.print(line_2);
    u8g2.setCursor(0, 30);
    u8g2.print(line_3);
    u8g2.setCursor(0, 40);
    u8g2.print(line_4);	
    u8g2.setCursor(0, 50);
    u8g2.print(line_5);
    u8g2.setCursor(150, 10);
    u8g2.print(line_6);
  } while ( u8g2.nextPage() );
  delay(2000);
 
 
  }

当然这样是顺便给做好了字符串直接用就可以用,写这个的时候本人还在昌平读书捏,所以这个是昌平的天气预报,改成你的城市就可以,用英文也是可以的 。

这样就完成了 天气信息的获取,需要其他数据可以去看那个库的说明。

3 从传感器获取数据

这里使用了SHT31温湿度传感器,气压传感器确实没有什么用,我就给扔了(其实是坏了)。这个传感器使用经典的iic协议和esp32进行通信,而esp32的iic接线如下,照着SDA和SCL接就可以啦。

iic协议的原理不再赘述,可以去找找视频康康

这里一样是懒狗操作,直接调库。使用了经典的Adafruit_SHT31.h这个库,在arduino ide就有,非常好用,这里给出一些初始化和使用的方法。

#include "stdio.h"
#include "Adafruit_SHT31.h"

Adafruit_SHT31 sht31 = Adafruit_SHT31();

void setup(){
if (! sht31.begin(0x44)) {   // Set to 0x45 for alternate i2c addr
    Serial.println("Couldn't find SHT31");
    while (1) delay(1);
  }
}
void loop(){
  char a[50];
  char b[50];
  char c[50];
  sprintf(a,"室内温度:%.2f°C",sht31.readTemperature());
  sprintf(b,"你好");
  sprintf(c,"室内湿度:%.2f °",sht31.readHumidity());
}

这里也是把数据提前和汉字拼在一起,然后往屏幕打印就好了

4 拼在一起,然后美化

#include <Arduino.h>
#include <U8g2lib.h>
#include <Wire.h>
//#include "DFRobot_BMP280.h"
#include "stdio.h"
#include "Adafruit_SHT31.h"
#include <ESP32_Heweather.h>
U8G2_GP1287AI_256X50_1_3W_HW_SPI u8g2(U8G2_R0, /* cs=*/ 15, /* reset=*/ 2);
//DFRobot_BMP280 bmp280; 
////typedef DFRobot_BMP280_IIC    BMP;    // ******** use abbreviations instead of full names ********

//BMP   bmp280(&Wire, BMP::eSdoLow);
bool enableHeater = false;
uint8_t loopCnt = 0;
Adafruit_SHT31 sht31 = Adafruit_SHT31();
//const char* ssid     = "@";
const char* ssid     = "88888888888888";     // WiFi名称
//const char* password = "@"; // WiFi密码
const char* password = "888888888888";
String UserKey = "88888888888888888888";   // 私钥 https://dev.heweather.com/docs/start/get-api-keyx
String Location = "101010700"; // 城市代码 https://github.com/heweather/LocationList,表中的 Location_ID
String Unit = "m";             // 公制-m/英制-i
String Lang = "zh";            // 语言 英文-en/中文-zh
float ROUND = 1;             // 更新间隔<小时>空气质量API 1小时更新一次
WeatherNow weatherNow;         // 建立weatherNow对象
WeatherForecast WeatherForecast;  
AirQuality AirQuality; 
int qwq = 34;
char line_1[50];
char line_2[50];
char line_3[50];
char line_4[50];
char line_5[50];
char line_6[50];


// 连接WiFi
void ConnectWiFi(){
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("Connecting to ");
  Serial.print(ssid);
 
  int i = 0;
  while (WiFi.status() != WL_CONNECTED && (i < 10)) {
    delay(1000);
    Serial.print('.');
    i++;
  }
  if (i == 10) { // 10s失败
 
    Serial.println("WiFi Connection Failed");
  } else { // 成功
 
  }
}
void ShowWeather(){
  char a[50];
  char b[50];
  char c[50];
  sprintf(a,"室内温度:%.2f°C",sht31.readTemperature());
  sprintf(b,"have a good day");
  sprintf(c,"室内湿度:%.2f °",sht31.readHumidity());
  float t = sht31.readTemperature();
if(qwq>30){
  if(weatherNow.get()){
    WeatherForecast.get();
    AirQuality.get();
 

  
 
  
  
    sprintf(line_1,"北京市 昌平区");
    sprintf(line_2,"预报温度:%d°C 最低:%d°C",weatherNow.getTemp(),WeatherForecast.getTempMin(0));
    sprintf(line_3,"当前天气:%s 明日:%s",weatherNow.getWeatherText(),WeatherForecast.getTextDay(1));
    sprintf(line_4,"风力: %d 体感温度: %d°C",weatherNow.getWindScale(),weatherNow.getFeelLike());
    sprintf(line_5,"降雨量: %3.1fmm 紫外强度: %d",weatherNow.getPrecip(),WeatherForecast.getUvIndex(0));
    sprintf(line_6,"空气质量:%s",AirQuality.getCategory());
  u8g2.setFont(u8g2_font_wqy12_t_gb2312); 
  //u8g2.firstPage();
  do {
    u8g2.setCursor(0, 10);
    u8g2.print(line_1);	
    u8g2.setCursor(0,20);
    u8g2.print(line_2);
    u8g2.setCursor(0, 30);
    u8g2.print(line_3);
    u8g2.setCursor(0, 40);
    u8g2.print(line_4);	
    u8g2.setCursor(0, 50);
    u8g2.print(line_5);
    u8g2.setCursor(0, 60);
    u8g2.print(line_6);
    u8g2.setCursor(150, 11);
    u8g2.print(line_6);	
    u8g2.setCursor(150, 30);
    u8g2.print(a);
    u8g2.setCursor(150, 50);
    u8g2.print(c);
  } while ( u8g2.nextPage() );
  delay(2000);
  qwq = 0;
 
  }
else {
  qwq = 30;    // 更新失败
u8g2.setFont(u8g2_font_timR08_tr); 
//u8g2.firstPage();
  do {
  u8g2.setCursor(0, 30);
  u8g2.print("ERROR code");
  u8g2.setCursor(0, 50);
  u8g2.print(weatherNow.getServerCode());
  } 
while ( u8g2.nextPage() );
ConnectWiFi();
}
}
else{
  u8g2.setFont(u8g2_font_wqy12_t_gb2312);  
//u8g2.firstPage();
  do {
    u8g2.setCursor(0, 10);
    u8g2.print(line_1);	
    u8g2.setCursor(0, 20);
    u8g2.print(line_2);
    u8g2.setCursor(0, 30);
    u8g2.print(line_3);
    u8g2.setCursor(0, 40);
    u8g2.print(line_4);	
    u8g2.setCursor(0, 50);
    u8g2.print(line_5);
    u8g2.setCursor(0, 60);
    u8g2.print(line_6);
    u8g2.setCursor(150, 11);
    u8g2.print(line_6);	
    u8g2.setCursor(150, 30);
    u8g2.print(a);
    u8g2.setCursor(150, 50);
    u8g2.print(c);
  } while ( u8g2.nextPage() );
  delay(2000);
qwq = qwq + 1;}
}


void setup(void) {
  u8g2.begin();
  u8g2.setContrast(255);//亮度设置 0-255
  u8g2.enableUTF8Print();///使用utf8
  ConnectWiFi();
  delay(2000);               //连接wifi
  weatherNow.config(UserKey, Location, Unit, Lang);
  WeatherForecast.config(UserKey, Location, Unit, Lang); 
  AirQuality.config(UserKey, Location, Unit, Lang);

  
  Serial.begin(9600);
  
  
  //if (!bmp280.begin()) {  
    //Serial.println("Could not find a valid BMP280 sensor!");
    //while (1);//别动,删了就挂壁
    
  //}//sht31
  //  while (!Serial)
  //  delay(10);     // will pause Zero, Leonardo, etc until serial console opens
 
  Serial.println("SHT31 test");
  if (! sht31.begin(0x44)) {   // Set to 0x45 for alternate i2c addr
    Serial.println("Couldn't find SHT31");
    while (1) delay(1);
  }
}

void loop(void) {
  
  
//u8g2.setFont(u8g2_font_wqy12_t_gb2312);

 
  u8g2.setFont(u8g2_font_profont12_mf);  


  ShowWeather();
  delay(3000);
 
 
}

特别提示

这个淘宝屏幕上面的裸露金属会带90v直流电压,无比小心,我要被电死咯,而且接触金属就会被烧烂,我的已经买新的了