三星9位段码VFD_ESP8266主控时钟实现

最终效果

使用蓝色膜显示效果时间显示温湿度显示
还是不错的哈哈哈,电路分为两块,VFD显示部分以及ESP8266主控部分

硬件介绍

显示屏

VFD显示屏显示驱动参数图片均来自淘宝,因为已经没有VFD变压器提供了,所以我使用了没有变压器的VFD驱动电路

VFD驱动

VFD驱动我使用了专用驱动IC-PT6312,需为此IC提供负高压(-20V以上)以驱动VFD栅极,以及提供灯丝的交变电压。

VFD电源电路

经过我不懈的努力在网上找到了,一个无变压器产生负压以及灯丝交变电压的电路:网站,有能用的当然是买过来啦,一块钱可以接受。
“本电路采用廉价的音频功放集成电路,通过文氏电路自激震荡,低压下能输出符合驱动灯丝要求的交流电源;同时利用高集成度的高频boost-bust驱动电路产生负高压驱动栅极,电路非常简单,无需调试,即可生成驱动VFD的三路电压,通过改变采样电路分压电阻,能适配不同电压要求的VFD屏。整套电路成本非常低,不用采用变压器,能达到93%的驱动效率,适合推动绝大多数负高压的VFD电路。”
——来自作者描述

VFD显示屏部分电路图

VFD显示屏部分电路因为使用ESP8266作为主控,IO不多,PT6312正好可以控制4个LED,以及按键检测,于是直接将这些集成到VFD显示板上了。
PT6312典型电路

ESP8266主控板

ESP8266主控板电路好像没啥特色哈哈哈,就不多讲啦。这里使用ETA6093的原因是我本来想使用电池的,但这个系统耗电量还是挺大的,接电池不能工作很久(就几小时),钰泰ETA6093三合一SOC电源管理芯片,支持1A开关充电,1A同步升压,充放电效率高。SOT23-5小型封装,集成度,外围少。搭配USB-C接口使用,可以做C口充放电功能。

代码介绍

写代码当然是Ctrl+CCtrl+V啦,能不用自己写的就一点也不自己写,这里使用ArduinoIDE编写ESP8266代码,以前一直不怎么喜欢Arduino(真香),疯狂使用别人的库就行啦,哈哈哈。
大量代码参考自(拷贝自)单片机菜鸟哥的ESP8266 Arduino教程
NTP网络校时代码则来自B站的一位大神的开源项目代码。

主要实现功能

这里偷懒直接截图一下我写的使用说明:
按键功能指示灯

配网

这里使用的是SmartConfig配网,可以在乐鑫官网下载安卓或者苹果对应的配网软件ESP-TOUCH进行配网(配置连接的WiFi信息)。
当然有兴趣的话,我推荐使用单片机菜鸟哥的ESP8266 Arduino教程里的wifimanager配网。

全部源码

很乱哈哈哈,就随便写写的,也没怎么整理,可以看到我原来使用的是红外控制,后来发现PT63212可是外接按键,就使用了按键控制了。

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <time.h>
#include <NTPClient.h>
//#include <IRremoteESP8266.h> //ESP8266红外控制库
//#include <IRrecv.h>
//#include <IRutils.h>
#include <RtcDS3231.h>
// #include "DHTesp.h"
#include <Wire.h>
#include <AHT10.h>
#include <Ticker.h> // Ticker can periodically call a function
#include <EEPROM.h>
#include <SPI.h>

#define DS3231_SDA 5
#define DS3231_SCL 4

#define ESP8266_LED 2
#define VFD_POWER 16
#define VFD_STB   15 // Pin cs  (SPI)


#define VFD_STB_H() digitalWrite(VFD_STB, HIGH)
#define VFD_STB_L() digitalWrite(VFD_STB, LOW)

#define ESP8266_LED_OFF() digitalWrite(ESP8266_LED, HIGH)
#define ESP8266_LED_ON() digitalWrite(ESP8266_LED, LOW)

#define VFD_POWER_ON() digitalWrite(VFD_POWER, HIGH)
#define VFD_POWER_OFF() digitalWrite(VFD_POWER, LOW)

#define MODE 0x05  // VFD Dan set ( 9 digit*13 segment)
#define LIGHT 0x05 // VFD Brightness settings (0x00-0x07)
#define ON 0x08    // Open Display
#define OFF 0x00   // Off Display

uint8_t DisplayCache[9] = {0x00}; //'-' =0x40
uint8_t vfdmap[] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
uint8_t VFD_LED_Cmd = 0x0F;    //VFD LED灯命令
uint8_t VFD_LED_ONFlag = 0x01; //VFD LED允许点亮
uint8_t DisplayMode = 0x00;    //显示温湿度或时间
uint8_t KEYMode = 0x00; //按键功能模式
uint8_t VFD_LIGHT_Mode = 0x02; //亮度等级
uint8_t VFD_LIGHT = LIGHT; //亮度等级
uint16_t BAT_V_Value = 0;//电池电压
uint8_t LowPowerFlag = 0; //低电量
uint8_t LowPowerLED = 0; //低电量指示灯

void VFD_Init(void);
void VFD_Display(void);
void VFD_Display_Test(void);
void VFD_LED_ON(void);
void VFD_LED_OFF(void);
uint8_t SPIRead_PT6312(uint8_t dat);
AHT10 myAHT10(AHT10_ADDRESS_0X38);
uint8_t AHT10ReadStatus = 0;
uint8_t AHT10ErrorFlag = 0;

void SendCSToPT6312(void)
{
  VFD_STB_H();
  VFD_STB_L();
}
uint8_t SPIRead_PT6312(uint8_t dat)
{
  uint8_t data = 0x00;
  SendCSToPT6312();
  SPI.transfer(dat);
  delayMicroseconds(1);//延时1us
  data = SPI.transfer(0xF0);
  VFD_STB_H();
  return data;
}
void VFD_Init(void)
{
  uint8_t i;

  pinMode(VFD_STB, OUTPUT);
  digitalWrite(VFD_STB, HIGH);

  SendCSToPT6312();
  SPI.transfer(MODE); // 段位设置
  SendCSToPT6312();
  SPI.transfer(0x40); // 设定数据
  SendCSToPT6312();
  SPI.transfer(0xc0); // Set Address
  for (i = 0; i < 9; i++)
  {
    SPI.transfer(0x00); // Transfer display data low byte
    SPI.transfer(0x00); // High byte data transmission display
  }
  SendCSToPT6312();
  SPI.transfer(0x80 | ON | VFD_LIGHT); // Display Control
  VFD_STB_H();
}
void VFD_Display_Test(void)
{
  uint8_t i;
  SendCSToPT6312();
  SPI.transfer(0x40); // 设定数据
  SendCSToPT6312();
  SPI.transfer(0xc0);     // Set Address //设置起始地址 0x00
  for (i = 0; i < 9; i++) //发送数据
  {
    SPI.transfer(vfdmap[i]); // Transfer display data low byte              //前8位
    SPI.transfer(0x03);      // High byte data transmission display //后8位
  }
  SendCSToPT6312();
  SPI.transfer(0x80 | ON | VFD_LIGHT); // Display Control //显示控制
  VFD_STB_H();
}

void VFD_LED_ON(uint8_t ledx)
{
  if (VFD_LED_ONFlag)
  {
    // 打开LED显示
    SendCSToPT6312();
    SPI.transfer(0x41); // 设定LED
    switch (ledx)
    {
      case 1:
        VFD_LED_Cmd &= 0xFE;
        break;
      case 2:
        VFD_LED_Cmd &= 0xFD;
        break;
      case 3:
        VFD_LED_Cmd &= 0xFB;
        break;
      case 4:
        VFD_LED_Cmd &= 0xF7;
        break;
      default:
        VFD_LED_Cmd = ledx;
        break;
    }
    SPI.transfer(VFD_LED_Cmd); //
    VFD_STB_H();
  }
}
void VFD_LED_Send(uint8_t cmd)
{
  SendCSToPT6312();
  SPI.transfer(0x41); // 设定LED
  SPI.transfer(cmd);
  VFD_STB_H();
}
void VFD_LED_OFF(uint8_t ledx)
{
  // 关闭LED显示
  SendCSToPT6312();
  SPI.transfer(0x41); // 设定LED
  switch (ledx)
  {
    case 1:
      VFD_LED_Cmd |= 0x01;
      break;
    case 2:
      VFD_LED_Cmd |= 0x02;
      break;
    case 3:
      VFD_LED_Cmd |= 0x04;
      break;
    case 4:
      VFD_LED_Cmd |= 0x08;
      break;
    default:
      VFD_LED_Cmd = ledx;
      break;
  }
  SPI.transfer(VFD_LED_Cmd);
  VFD_STB_H();
}
void VFD_Display(void)
{
  uint8_t i;
  uint8_t *p = DisplayCache;
  SendCSToPT6312();
  SPI.transfer(0x40); // 设定数据
  SendCSToPT6312();
  SPI.transfer(0xc0);
  for (i = 0; i < 9; i++)
  {
    SPI.transfer(*p++);
    SPI.transfer(0x00);
  }
  SendCSToPT6312();
  SPI.transfer(0x80 | ON | VFD_LIGHT);
  VFD_STB_H();
}

void VFD_DisplayX(uint8_t x)
{
  uint8_t i;
  uint8_t *p = DisplayCache;
  SendCSToPT6312();
  SPI.transfer(0x40); // 设定数据
  SendCSToPT6312();
  SPI.transfer(0xc0);
  for (i = 0; i < 9; i++)
  {
    SPI.transfer(*p++);
    SPI.transfer(x);
  }
  SendCSToPT6312();
  SPI.transfer(0x80 | ON | VFD_LIGHT);
  VFD_STB_H();
}

void VFD_Display_Numb(uint8_t numb, uint8_t x, uint8_t len)
{
  for (uint8_t i = 0; i < len; i++)
  {
    DisplayCache[x--] = vfdmap[numb % 10];
    numb /= 10;
  }
}

#define DEFAULT_STASSID "Xiaomi"
#define DEFAULT_STAPSW  "12345678"
struct wificonfig_type
{
  char stassid[64];
  char stapsw[64];
};
wificonfig_type wificonfig;
unsigned long epoch = 0;
uint8_t Second_temp = 0;
time_t t;
tm *tt;
char ch[21] = {0};
WiFiUDP ntpUDP;
// DHTesp dht11;
// You can specify the time server pool and the offset (in seconds, can be
// changed later with setTimeOffset() ). Additionaly you can specify the
// update interval (in milliseconds, can be changed using setUpdateInterval() ).
NTPClient timeClient(ntpUDP, "time1.aliyun.com", 3600 * 8, 60000 * 30);
RtcDS3231<TwoWire> Rtc(Wire);

/*
   保存参数到EEPROM
*/
void wifisaveConfig()
{
  Serial.println("Save config!");
  Serial.print("stassid:");
  Serial.println(wificonfig.stassid);
  Serial.print("stapsw:");
  Serial.println(wificonfig.stapsw);

  EEPROM.begin(1024);
  uint8_t *p = (uint8_t*)(&wificonfig);
  for (int i = 0; i < sizeof(wificonfig); i++)
  {
    EEPROM.write(i, *(p + i));
  }
  EEPROM.commit();//保存更改的数据
}
/*
   从EEPROM加载参数
*/
void wifiloadConfig()
{
  EEPROM.begin(1024);
  uint8_t *p = (uint8_t*)(&wificonfig);
  for (int i = 0; i < sizeof(wificonfig); i++)
  {
    *(p + i) = EEPROM.read(i);
  }
  EEPROM.commit();//保存更改的数据
  Serial.println("-----Read config-----");
  Serial.print("stassid:");
  Serial.println(wificonfig.stassid);
  Serial.print("stapsw:");
  Serial.println(wificonfig.stapsw);
}
uint8_t smartConfig(void)
{
  uint8_t i = 0, count = 0;
  WiFi.mode(WIFI_STA);
  Serial.println("\r\nWait for Smartconfig");
  VFD_LED_ON(3); //LED3亮 表示正在自动配网
  for (i = 0; i < 9; i++)
    DisplayCache[i] = 0x00;
  delay(2000);
  // 等待配网
  WiFi.beginSmartConfig();
  while (1)
  {
    Serial.print(".");

    if (i >= 9)
    {
      for (i = 0; i < 9; i++)
        DisplayCache[i] = 0x00;
      i = 0;
    }
    DisplayCache[i] = 0x80;
    VFD_DisplayX(0x03); //VFD显示
    i++;
    delay(500);

    if (WiFi.smartConfigDone())
    {
      Serial.println("SmartConfig Success");
      Serial.printf("SSID:%s\r\n", WiFi.SSID().c_str());
      Serial.printf("PSW:%s\r\n", WiFi.psk().c_str());
      //      Serial.println(WiFi.smartConfigDone());
      strcpy(wificonfig.stassid,  WiFi.SSID().c_str());
      strcpy(wificonfig.stapsw, WiFi.psk().c_str());
      //      WiFi.setAutoConnect(true); // 设置自动连接
      break;
    }
    count++;
    if (count >= 80) //40S
    {
      VFD_LED_OFF(3); //LED3灭 表示正在自动配网结束
      Serial.println(WiFi.smartConfigDone());
      return 1;       //联网失败
    }
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  VFD_LED_OFF(3); //LED3灭 表示正在自动配网结束
  return 0;       //联网成功
}

Ticker myTicker1;             //建立一个需要定时调度的对象
//Ticker myTicker2;             //建立一个需要定时调度的对象
//Ticker myTicker3;             //建立一个需要定时调度的对象
Ticker myTicker4;             //建立一个需要定时调度的对象
uint8_t TimeDisplay_Flag = 0; //时间是否刷新显示
uint8_t T_H_Display_Flag = 0; //温湿度是否刷新显示
uint8_t TimeShowMode = 1;     //时间显示模式
uint8_t Daytemp = 0xFF;       //时间天数缓存
uint8_t KEYScanFlag = 0; //按键扫描
uint8_t ADCGETFlag = 0; //ADC电压获取
uint8_t ADCGETCount = 0; //ADC电压获取次数
void tickerHandle1() //0.5到时间时需要执行的任务
{
  //    Serial.println(millis()); //打印当前时间
  static uint8_t times_num1 = 0;
  static uint8_t times_num2 = 0;

  TimeDisplay_Flag = 1;
  if (++times_num1 >= 5)
  {
    times_num1 = 0;
    T_H_Display_Flag = 1;
  }
  if (++times_num2 >= 3)
  {
    LowPowerLED ^= 0x01; //取反
    times_num2 = 0;
  }
}

//void tickerHandle2() //10s到时间时需要执行的任务
//{
//  TimeShowMode = 0x01; //
//  myTicker2.detach();  //停止当前任务
//}
//void tickerHandle3() //1s到时间时需要执行的任务
//{
//  AHT10ReadDataFlag = 1; //
//}
void tickerHandle4() //20ms到时间时需要执行的任务
{
  KEYScanFlag = 1; //
  ADCGETFlag = 1;
}
void NTP_TimeCheck(void) //NTP网络对时校准DS3231
{
  if (WiFi.status() == WL_CONNECTED)
  {
    timeClient.begin();
    Rtc.Begin();
    timeClient.update();
    epoch = timeClient.getEpochTime();

    t = epoch;
    tt = localtime(&t);
    RtcDateTime compiled = RtcDateTime(tt->tm_year + 1900, tt->tm_mon + 1, tt->tm_mday, tt->tm_hour, tt->tm_min, tt->tm_sec);
    Serial.println();
    strftime(ch, sizeof(ch) - 1, "%Y-%m-%d %H:%M:%S", tt); //年-月-日 时-分-秒
    Serial.println(ch);

    printDateTime(compiled);
    Serial.println();
    if (!Rtc.GetIsRunning())
    {
      Serial.println("RTC was not actively running, starting now");
      Rtc.SetIsRunning(true);
    }
    RtcDateTime now = Rtc.GetDateTime();
    if (now < compiled)
    {
      Serial.println("RTC is older than compile time!  (Updating DateTime)");
      Rtc.SetDateTime(compiled);
    }
    else if (now > compiled)
    {
      Serial.println("RTC is newer than compile time. (this is expected)");
      Rtc.SetDateTime(compiled);
    }
    else if (now == compiled)
    {
      Serial.println("RTC is the same as compile time! (not expected but all is fine)");
    }
    Rtc.Enable32kHzPin(false);
    Rtc.SetSquareWavePin(DS3231SquareWavePin_ModeNone);
    timeClient.end();
  }
}
uint8_t WIFI_Connect(uint8_t configflag)
{
  uint8_t time_count = 0, i = 0;
  uint8_t configflagtemp=configflag;
  WiFi.mode(WIFI_STA);
  //  WiFi.setAutoConnect(true); // 设置自动连接
  WiFi.setAutoReconnect(true);//设置断开连接后重连
  WiFi.begin(wificonfig.stassid, wificonfig.stapsw);

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
    if (i >= 9)
    {
      for (i = 0; i < 9; i++)
        DisplayCache[i] = 0x00;
      i = 0;
    }
    DisplayCache[i] = 0x80;
    VFD_DisplayX(0x02); //VFD显示
    i++;
    
    if (++time_count == 16) //超过8s未连接成功,启动自动配网
    {
      if(configflagtemp)
      {
        if (smartConfig()) //自动配网失败
        {
          return 1;
        }
        else //自动配网成功
        {
          wifisaveConfig();
          ESP.restart(); //复位
          break;
        }
      }
      else
      {
        return 1;//联网失败
      }
    }
  }

  WiFi.setSleepMode(WIFI_MODEM_SLEEP); //
  return 0;
}

void setup()
{
  uint8_t time_out = 0;
  // put your setup code here, to run once:
  Serial.begin(115200);
  //  strcpy(wificonfig.stassid, DEFAULT_STASSID);
  //  strcpy(wificonfig.stapsw, DEFAULT_STAPSW);
  //  wifisaveConfig();
  wifiloadConfig();
  // dht11.setup(2, DHTesp::DHT11); // Connect DHT sensor to GPIO 2
  pinMode(VFD_POWER, OUTPUT);
  VFD_POWER_ON(); //开启显示电源

  pinMode(ESP8266_LED, OUTPUT);
  ESP8266_LED_OFF();//关闭LED

  delay(500);
  SPI.begin();
  SPI.setBitOrder(LSBFIRST);
  //    SPI.setClockDivider(SPI_CLOCK_DIV32);
  VFD_Init();                         //VFD初始化
  VFD_DisplayX(0x02);                 //VFD显示

  //  Wire.begin(DS3231_SDA, DS3231_SCL); // due to limited pins, use pin 0 and 2 for SDA, SCL
  while (myAHT10.begin(DS3231_SDA, DS3231_SCL) != true)
  {
    Serial.println(F("AHT10 not connected or fail to load calibration coefficient")); //(F()) save string to flash & keeps dynamic memory free
    time_out++;
    delay(1000);
    if (time_out >= 6)
    {
      AHT10ErrorFlag = 1;
      break;
    }
  }
  if (!AHT10ErrorFlag)
  {
    Serial.println(F("AHT10 OK"));
  }
  myAHT10.setNormalMode();
  if (WIFI_Connect(0))                 //联网失败
  {
    //    VFD_LED_ON(2); //LED2亮 表示不联网
    VFD_LED_Cmd &= 0xFD;
    VFD_LED_Cmd |= 0x08;
    VFD_LED_Send(VFD_LED_Cmd); //LED2亮 LED4灭 表示不联网
  }
  else
  {
    //    VFD_LED_ON(4);   //LED4亮
    VFD_LED_Cmd &= 0xF7;
    VFD_LED_Cmd |= 0x02;
    VFD_LED_Send(VFD_LED_Cmd); //LED4亮 LED2灭 表示不联网
    NTP_TimeCheck(); //NTP对时
  }
  WiFi.setAutoReconnect(false);//设置断开连接后不重连
  //  //WiFi.disconnect(); //断开连接,但仍然处于无线终端模式,只是清除了SSID和密码
  WiFi.disconnect(true);//断开连接,直接关闭无线终端模式
  //  VFD_LED_ON(2); //LED2亮 表示不联网
  VFD_LED_Cmd &= 0xFD;
  VFD_LED_Cmd |= 0x08;
  VFD_LED_Send(VFD_LED_Cmd); //LED2亮 LED4灭 表示不联网

  myTicker1.attach_ms(500, tickerHandle1); //初始化调度任务,每0.5秒执行一次tickerHandle1()
  //  myTicker3.attach(2, tickerHandle3); //初始化调度任务,每2秒执行一次tickerHandle3()
  myTicker4.attach_ms(50, tickerHandle4); //初始化调度任务,每50ms执行一次tickerHandle4()
}

void loop()
{
  static bool time_valid_flag = true;
  static bool time_valid_flag_temp = true;
  static uint8_t wifi_connect_flag = 0;
  static uint8_t KEYMode_temp = 0xFF;
  static uint8_t VFD_LIGHT_Mode_temp = 0xFF;
  uint8_t KEY_value = 0x00;
  uint8_t time_out = 0x00;
  float humidity = 0.0F;
  float temperature = 0.0F;
  uint16_t u16_humidity = 0;
  int16_t i16_temperature = 0;
  static uint32_t u32_adc_value = 0;
  static uint8_t LowPowerFlagtemp = 0xFF;
  static uint8_t LowPowercount = 0;
  if (VFD_LIGHT_Mode_temp != VFD_LIGHT_Mode)
  {
    VFD_LIGHT_Mode_temp = VFD_LIGHT_Mode;
    switch (VFD_LIGHT_Mode_temp)
    {
      case 0:
        VFD_LIGHT = 0x02;
        break;
      case 1:
        VFD_LIGHT = 0x04;
        break;
      case 2:
        VFD_LIGHT = 0x07;
        break;
    }
    SendCSToPT6312();
    SPI.transfer(0x80 | ON | VFD_LIGHT); // Display Control
    VFD_STB_H();
  }
  if (ADCGETFlag)
  {
    ADCGETFlag = 0;
    //    Serial.println(analogRead(A0)/102.4); //打印输出ADC引脚上电压
    u32_adc_value += analogRead(A0);

    ADCGETCount++;
    if (ADCGETCount >= 50)
    {
      u32_adc_value /= ADCGETCount;
      u32_adc_value *= 1000;//100

      BAT_V_Value = u32_adc_value / 1024;
      u32_adc_value = 0;
      ADCGETCount = 0;
//      Serial.println(BAT_V_Value); //打印输出ADC引脚上电压
      if (BAT_V_Value <= 370)
      {
        LowPowercount++;
      }
      else
      {
        LowPowercount = 0;
        LowPowerFlag = 0;
      }
      if(LowPowercount>=6)//联系测得6次较低
      {
        LowPowercount=0;
        LowPowerFlag = 1;
      }
    }
  }
  if (LowPowerFlagtemp != LowPowerFlag)
  {
    LowPowerFlagtemp = LowPowerFlag;
    if (!LowPowerFlagtemp)
    {
      ESP8266_LED_OFF();
      VFD_POWER_ON(); //开启显示电源
      delay(500);
      VFD_Init();                         //VFD初始化
      VFD_DisplayX(0x02);                 //VFD显示
      VFD_LED_ON(VFD_LED_Cmd); //点亮LED
    }
    else
    {
      if (WiFi.status() == WL_CONNECTED)//已联网
      {
        WiFi.setAutoReconnect(false);//设置断开连接后不重连
        WiFi.disconnect(true);//断开连接,直接关闭无线终端模式
        VFD_LED_Cmd &= 0xFD;
        VFD_LED_Cmd |= 0x08;
        VFD_LED_Send(VFD_LED_Cmd); //LED2亮 LED4灭 表示不联网
      }
      VFD_POWER_OFF(); //关闭显示电源
      Serial.println(F("LOWPower!"));
    }
  }
  if (LowPowerFlagtemp)
  {
    if (LowPowerLED)
    {
      ESP8266_LED_ON();
    }
    else
    {
      ESP8266_LED_OFF();
    }

  }
  else
  {
    if (KEYMode_temp != KEYMode)
    {
      KEYMode_temp = KEYMode;
      if (KEYMode_temp)
      {
        ESP8266_LED_ON();
      }
      else
      {
        ESP8266_LED_OFF();
      }
    }
    if (KEYScanFlag)
    {
      KEYScanFlag = 0;

      KEY_value = SPIRead_PT6312(0x43);
      KEY_value &= 0x0F;

      //    Serial.print(KEY_value, HEX);
      //    Serial.println();
      if (KEY_value != 0x0F)
      {
        time_out = 0x00;
        if (!KEYMode)
        {
          switch (KEY_value)
          {
            case 0x07://KEY4 日期显示

              TimeShowMode ^= 0x01; //取反
              Daytemp = 0xFF; //立即刷新显示
              Second_temp = 0xFF; //立即刷新显示

              break;
            case 0x0B://KEY3 温湿度显示
              if (!AHT10ErrorFlag)
              {
                DisplayMode ^= 0x01; //取反
                T_H_Display_Flag = 1; //立即刷新显示
              }
              break;
            case 0x0D://KEY2 指示灯开关
              VFD_LED_ONFlag ^= 0x01; //取反
              if (VFD_LED_ONFlag)
              {
                VFD_LED_ON(VFD_LED_Cmd); //点亮LED
              }
              else
              {
                VFD_LED_Send(0x0F); //熄灭全部LED
              }
              break;
            case 0x0E://KEY1 按键模式切换
              KEYMode = 0x01;
              break;
          }
        }
        else
        {
          switch (KEY_value)
          {
            case 0x07://KEY4
              VFD_LIGHT_Mode++;
              if (VFD_LIGHT_Mode >= 3)
              {
                VFD_LIGHT_Mode = 0;
              }
              break;
            case 0x0B://KEY3
              wifi_connect_flag = 1; //启动联网
              break;
            case 0x0D://KEY2
              if (WiFi.status() == WL_CONNECTED)//已联网
              {
                WiFi.setAutoReconnect(false);//设置断开连接后不重连
                WiFi.disconnect(true);//断开连接,直接关闭无线终端模式
                VFD_LED_Cmd &= 0xFD;
                VFD_LED_Cmd |= 0x08;
                VFD_LED_Send(VFD_LED_Cmd); //LED2亮 LED4灭 表示不联网
              }
              break;
            case 0x0E://KEY1
              KEYMode = 0x00;
              break;
          }
        }
        do {
          delay(10);
          KEY_value = SPIRead_PT6312(0x43);
          KEY_value &= 0x0F;
          if (++time_out >= 20)
            break;
        } while (KEY_value != 0x0F);
      }
    }
    if (!DisplayMode)
    {
      if (TimeDisplay_Flag)
      {
        time_valid_flag = Rtc.IsDateTimeValid();
        if (time_valid_flag != time_valid_flag_temp)
        {
          time_valid_flag_temp = time_valid_flag;
          if (!time_valid_flag_temp)
          {
            if (Rtc.LastError() != 0)
            {
              // we have a communications error
              // see https://www.arduino.cc/en/Reference/WireEndTransmission for
              // what the number means
              Serial.print("RTC communications error = ");
              Serial.println(Rtc.LastError());
            }
            else
            {
              // Common Cuases:
              //    1) the battery on the device is low or even missing and the power line was disconnected
              Serial.println("RTC lost confidence in the DateTime!");
            }
            VFD_LED_ON(1); //LED1亮 时间数据失效
          }
          else
          {
            VFD_LED_OFF(1); //LED1灭 时间数据有效
          }
        }
        RtcDateTime now = Rtc.GetDateTime();
        if (TimeShowMode)
        {
          if (Second_temp != now.Second())
          {

            //  Serial.println(timeClient.getFormattedTime());
            //  Serial.println(epoch);
            //  Serial.println(tt->tm_sec);
            VFD_Display_Numb(now.Second(), 8, 2);
            DisplayCache[0] = 0x40; //'-' =0x40
            VFD_Display_Numb(now.Minute(), 5, 2);
            DisplayCache[3] = 0x40; //'-' =0x40
            VFD_Display_Numb(now.Hour(), 2, 2);
            DisplayCache[6] = 0x40; //'-' =0x40

            VFD_Display();
            Daytemp = 255;
            //    strftime(ch, sizeof(ch) - 1, "%Y-%m-%d %H:%M:%S", tt);     //年-月-日 时-分-秒
            //    Serial.println(ch);

            // printDateTime(now);
            // Serial.println();
            Second_temp = now.Second();
            //    delay(1000);
          }
        }
        else
        {
          if (Daytemp != now.Day())
          {
            VFD_Display_Numb(now.Day(), 8, 2);
            DisplayCache[6] = 0x40; //'-' =0x40
            VFD_Display_Numb(now.Month(), 5, 2);
            DisplayCache[3] = 0x40; //'-' =0x40
            VFD_Display_Numb(now.DayOfWeek(), 2, 2);
            DisplayCache[0] = 0x40; //'-' =0x40
            VFD_Display();
            Daytemp = now.Day();
          }
        }

        TimeDisplay_Flag = 0;
      }
    }
    else//显示温湿度
    {
      if (T_H_Display_Flag)
      {
        T_H_Display_Flag = 0;

        temperature = myAHT10.readTemperature(AHT10_FORCE_READ_DATA);
        humidity = myAHT10.readHumidity(AHT10_USE_READ_DATA);//myAHT10.readTemperature(AHT10_FORCE_READ_DATA)
        Serial.println();
        Serial.print(F("Temperature: ")); Serial.print(temperature); Serial.println(F(" +-0.3C")); //by default "AHT10_FORCE_READ_DATA"
        Serial.print(F("Humidity...: ")); Serial.print(humidity);    Serial.println(F(" +-2%"));   //by default "AHT10_FORCE_READ_DATA"
        u16_humidity = humidity * 10;
        i16_temperature = temperature * 10;
        if (i16_temperature < 0)
        {
          DisplayCache[0] = 0x40; //'-' =0x40
          i16_temperature = -i16_temperature;
        }
        else
        {
          DisplayCache[0] = 0x00; //'-' =0x40
        }
        VFD_Display_Numb(i16_temperature / 10, 2, 2); //温度整数部分
        DisplayCache[2] |= 0x80; //加入小数点
        VFD_Display_Numb(i16_temperature % 10, 3, 1); //温度小数部分
        DisplayCache[4] = 0x39; //加入‘C’

        VFD_Display_Numb(u16_humidity / 10, 6, 2); //温度整数部分
        DisplayCache[6] |= 0x80; //加入小数点
        VFD_Display_Numb(u16_humidity % 10, 7, 1); //温度小数部分
        DisplayCache[8] = 0x76; //加入‘H’
        VFD_Display();
      }
    }
    if (wifi_connect_flag)
    {
      wifi_connect_flag = 0;
      if (WiFi.status() != WL_CONNECTED)//未联网
      {
        if (WIFI_Connect(1)) //联网失败
        {
          //        VFD_LED_ON(2); //LED2亮 表示不联网
          VFD_LED_Cmd &= 0xFD;
          VFD_LED_Cmd |= 0x08;
          VFD_LED_Send(VFD_LED_Cmd); //LED2亮 LED4灭 表示不联网
        }
        else
        {
          //        VFD_LED_OFF(2); //LED2灭 表示联网
          //        VFD_LED_ON(4);   //LED4亮
          VFD_LED_Cmd &= 0xF7;
          VFD_LED_Cmd |= 0x02;
          VFD_LED_Send(VFD_LED_Cmd); //LED4亮 LED2灭 表示不联网
          NTP_TimeCheck(); //NTP对时
        }
      }
      else//已经联网
      {
        VFD_LED_OFF(2); //LED2灭 表示联网
        NTP_TimeCheck(); //NTP对时
      }
    }
  }
}
#define countof(a) (sizeof(a) / sizeof(a[0]))

void printDateTime(const RtcDateTime &dt)
{
  char datestring[25];

  snprintf_P(datestring,
             countof(datestring),
             PSTR("%02u/%02u/%04u %02u:%02u:%02u %02u"),
             dt.Month(),
             dt.Day(),
             dt.Year(),
             dt.Hour(),
             dt.Minute(),
             dt.Second(),
             dt.DayOfWeek());
  Serial.print(datestring);
}

制作过程

焊接好的控制板与显示板:
焊好的PCB板待焊接ESP-12F主控及VFD显示屏的PCB板和几个做好的:
组合

相关资料

资料内容:链接
上传资料内容

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
通用VFD显示模块的设计原理说明与制作过程讲解,展示如何在业余条件下完成一个通用的VFD显示模块的设计与制作过程。 制作特点 使用大尺寸的优质VFD显示屏,屏幕包含9位带小数点、逗号及下指针的标准8字笔段结构字符,通用性强,可以取代大部分LED数字显示屏模块; 使用无变压器的驱动电路,板上电路独立完交流灯丝电压与负高压驱动阳极与栅极,符合VFD屏驱动规范,显示效果优良无闪烁; 全板采用全贴片零件制作,所有零件全部藏于显示屏下方机,实现了超薄外观; 模块主设计使用单片机驱动方案,板上自带的单片机不仅可以完成各驱动功能,同时也具备了模块自检功能,可在无外部单片机驱动的情况下,自主完成自检显示; 程序已经预写入单片机内,用户无需配备专用的写入器设备。模块制作容易,调试简单,仅需配备普通万用表即可,适合初级电子爱好者自制; 公开源Arduino驱动程序,仅需添加几行应用代即可实现显示,显示过程中不消耗单片机资源,简单易用;源使用纯C语言编写,移植简单,完全可支持51、STM等单片机; 所有接口引线全部通过插针引出,可选择单排针或双排针连接方式。模块与单片机的接口引线仅3根,节约单片机I/O口资源。 模块与ARDUINO UNO线路连接图 模块焊接对照图 ARDUINO VFD显示模块演示视频 电路城语:免费分享设计资料,不提供技术支持,请大家使用前验证资料的正确性! 附件包含以下资料: 模块电路图 模块焊接对照图 BOM元件表 INRC09SS49T ARDUINO VFD显示模块源代 通用VFD显示模块设计原理说明 亚克力外壳设计文件(其中边条部分请使用2.8mm厚度的亚克力板激光切割,上下板及边板使用1.8mm厚度的亚克力板激光切割。组装请使用M2螺丝与螺母)
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值