[ESP8266/ESP32]FireBeetle 做一个 VGA 时钟 精华

3033浏览
查看: 3033|回复: 2

[ESP8266/ESP32] FireBeetle 做一个 VGA 时钟

[复制链接]
1987年4月2日, IBM 推出了 PS/2,这是Personal System/2 Model 80 (IBM 8580)的缩写。在这个电脑上引入了VGA(VideoGraphics Array)接口,它成为模拟信号的电脑显示标准。
FireBeetle 做一个 VGA 时钟图7
VGA接口共有15针,分成3排,每排5个孔,显卡上应用最为广泛的接口类型,绝大多数显卡都带有此种接口。它传输红、绿、蓝模拟信号以及同步信号(水平和垂直信号),从块头巨大的CRT显示器时代开始,VGA接口就被使用,并且一直沿用至今。
FireBeetle 做一个 VGA 时钟图1
VGA 公头
  
标号
  
名称
描述
标号
名称
描述
1
RED
视频红色
  
分量
9
KEY
保留
2
GREEN
视频绿色
  
分量
10
SGND
同步信号地
3
BLUE
视频蓝色
  
分量
11
NC
保留
4
NC
保留
12
Bi-Diorectional Data
SDA
5
GND
13
HSYNC
行同步信号
6
RGND
红色地
14
VSYNC
场同步信号
7
GGND
绿色地
15
Data Clock
SCL
8
BGND
蓝色地
简单的说,工作原理是:RG B 三个Pin 给出每一个点的颜色组成信息,显示器采样后即按照给出值显示,当显示完一行后,行同步信号通知显示器换行,如此进行,当一帧显示完成后场同步信号通知显示器这一帧结束了,请从最上面再进行显示。
对于我们来说,只要单片机足够快就可以模拟出 VGA 信号从而达到显示的目的。这次制作一个 VGA 转接板,配合 FireBeetle 在显示器上显示当前时间。
首先,本项目基于开源图形库FabGL【参考1 ,它是设计给ESP32的图形库。它实现了多个显示驱动程序,例如VGA接口的显示器以及I2CSPI 接口的液晶屏)。此外FabGL还可以从PS/2键盘和鼠标获取输入,方便实现简单的交互。硬件设计上 GPIO21/22 用作红色信号输出;GPIO18/19用作绿色信号输出;GPIO4/5用作蓝色信号输出;GPIO23用于 HSyncGPIO15用于VSync(定义在vga16controller.h)。每一种颜色使用2个电阻构成简单的 DAC 电路,因此可以显示 2^6=64种颜色。
最终给FireBeetle设计了一个 VGA Shield 如下:
FireBeetle 做一个 VGA 时钟图2
此外,引出所有的IO方便日后扩展其他功能。
FireBeetle 做一个 VGA 时钟图4
FireBeetle 做一个 VGA 时钟图3
此外,还有一个I2S DAC输出,为日后音频输出预留
FireBeetle 做一个 VGA 时钟图5
除了 FireBeetle提供电力,板子上还有一个 USB接口,可以直接将USB插入此处供电。
FireBeetle 做一个 VGA 时钟图6
PCB 布线如下:
FireBeetle 做一个 VGA 时钟图12
3D预览如下:
FireBeetle 做一个 VGA 时钟图8
制作好的 PCB 如下:
FireBeetle 做一个 VGA 时钟图9
用于颜色显示的电阻是必须的,其他的没有焊接。安装之后的样子:
FireBeetle 做一个 VGA 时钟图10接下来编写代码,基本原理是使用 FabGL 的终端(Terminal,相当于一个 ASCII 字符显示器),在上面使用 ASCII绘制转动的地球;此外,通过 WIFI 获得阿里NTP服务器提供的日期时间信息,一起输出到VGA接口上显示在屏幕上。
  1. #include "fabgl.h"
  2. #include "vtanimations.h"
  3. #include <WiFi.h>
  4. // VGA 显示
  5. fabgl::VGA16Controller DisplayController;
  6. fabgl::Terminal        Terminal;
  7. const char *ssid = "labz_001665"; //网络名称
  8. const char *password = "12345678"; //网络密码
  9. // 使用阿里的 NTP 获得当前时间
  10. const char* ntpServer = "ntp.aliyun.com";
  11. // 时区修正,我们在东八区
  12. const long  gmtOffset_sec = 8 * 60 * 60;
  13. // 夏令时修正
  14. const int   daylightOffset_sec = 0;
  15. void setup() {
  16.   struct tm timeinfo;
  17.   Serial.begin(115200);
  18.   // Connect to Wi-Fi
  19.   Serial.print("Connecting to ");
  20.   Serial.println(ssid);
  21.   WiFi.begin(ssid, password);
  22.   while (WiFi.status() != WL_CONNECTED) {
  23.     delay(500);
  24.     Serial.print(".");
  25.   }
  26.   Serial.println("");
  27.   Serial.println("WiFi connected.");
  28.   delay(2000);
  29.   Serial.println("Connect to NTP server");
  30.   // 从 NTP Server 获得时间
  31.   configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
  32.   // 如果没有成功获取,那么重启 ESP32
  33.   if (!getLocalTime(&timeinfo)) {
  34.     Serial.println("Failed to obtain time, retry");
  35.     delay(5000);
  36.     ESP.restart();
  37.   }
  38.   Serial.println("Got time");
  39.   // 取得时间后即可断开 WIFI
  40.   WiFi.disconnect(true);
  41.   WiFi.mode(WIFI_OFF);
  42.   DisplayController.begin();
  43.   // 设定分辨率
  44.   DisplayController.setResolution(VGA_640x480_60Hz);
  45.   // 创建 Terminal
  46.   Terminal.begin(&DisplayController);
  47.   Terminal.enableCursor(true);
  48.   // 背景为黑,文字绿色
  49.   Terminal.write("\e[40;92m");
  50.   // 请屏幕
  51.   Terminal.write("\e[2J");
  52.   Terminal.write("\e[20h");
  53.   //Terminal.write("\e[92m");
  54.   // 关闭光标
  55.   Terminal.enableCursor(false);
  56. }
  57. void loop() {
  58.   int i = 0;
  59.   while (i < sizeof(vt_animation) - 4) {
  60.     // 如果当前要发送回归第一行的命令,就输出当前时间
  61.     if (vt_animation[i] == 0x1B && vt_animation[i + 1] == 0x5B && vt_animation[i + 2] == 0x48) {
  62.       struct tm timeinfo;
  63.       // 取得当前时间
  64.       getLocalTime(&timeinfo);
  65.       char buf[60];
  66.       // 年月日
  67.       sprintf(buf, "\e[10;56H%d/%02d/%02d", timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday);
  68.       Serial.println(buf);
  69.       Terminal.write(buf);
  70.       //小时分钟秒
  71.       sprintf(buf, "\e[14;56H%02d:%02d:%02d", timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
  72.       Serial.println(buf);
  73.       Terminal.write(buf);
  74.       // 输出回归第一行的命令
  75.       Terminal.write(vt_animation[i]);
  76.       Terminal.write(vt_animation[i + 1]);
  77.       Terminal.write(vt_animation[i + 2]);
  78.       // 跳过这个命令
  79.       i = i + 3;
  80.     }
  81.     Terminal.write(vt_animation[i]);
  82.     i++;
  83.   }
  84. }
复制代码
这是在HP 显示器上测试的结果
FireBeetle 做一个 VGA 时钟图11
参考:


zoologist  高级技匠
 楼主|

发表于 2021-9-30 10:40:40

回复

使用道具 举报

zoologist  高级技匠
 楼主|

发表于 2021-10-10 20:44:32

工作的视频可以在 B站看到

https://www.bilibili.com/video/BV12u411Z7vG/
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail