赞
踩
转发: RP2040-ETH-DVI-ZERO: Adafruit IO Dashboard Monitor ( HDMI / DVI Mode )
项目介绍
我新开发了一块Raspberry Pi RP2040开发板,具有DVI/HDMI输出接口,使用W5100S作为网络接入,并具有TF卡插槽。我将这款开发板命名为“RP2040-ETH-DVI-ZERO”。
据我所知,RP2040-ETH-DVI-ZERO是第一款具有网络功能的RP2040 DVI开发板。
RP2040-ETH-DVI-ZERO采用与Raspberry Pi ZERO W官方相同的外部尺寸和接口设计,RP2040-ETH-DVI-ZERO可以使用Raspberry Pi ZERO W官方外壳。
RP2040-ETH-DVI-ZERO可以同时进行网络通信和图像DVI输出显示。
可以生成320*240分辨率的图像,并通过扩展至640*480(60Hz)输出到显示器
为什么要开发 RP2040-ETH-DVI-ZERO?
市面上有很多带DVI接口的RP2040开发板,但均不具备网络通信功能。由于PICO W的无线通讯部分占用大量动态内存,DVI输出功能无法与网络功能同时使用,或者其使用受到很大限制。因为使用W5100S可以让网络通信只使用少量的动态内存,所以我开发了RP2040-ETH-DVI-ZERO和项目。
这只是 W5100S 使用的动态内存的 2%。
这是 PICO W 使用的动态内存的 25%,对比相当明显。
RP2040-DVI-ETH-ZERO 硬件:
顶视图:
底视图:
我对W5100S部分使用与W5100S_EVB_PICO相同的引脚设计,因此我可以使用W5100S_EVB_PICO的所有参考代码。
该项目的名称是“Adafruit IO Dashboard Monitor”。我的想法是为 adafruit.io 开发一个通用的仪表板显示界面。所有显示内容均从adafruit.io获取,包括显示adafruit.io的dashboard框架并解析dashboard中包含的所有Block,自动订阅dashboard中包含的所有“feed”内容,并通过DVI输出到显示器。
因为是通用的显示框架,所以我在程序中没有定义任何固定的参数。所有参数都是通过Adafruit.io获取的,包括显示框架。
因为没有固定的参数,所以我们在第一次开机的时候需要通过内嵌的网页输入adafruit的访问参数。
RP2040-ETH-DVI-ZERO的屏幕显示:
通过浏览嵌入式网页输入三个参数,即 adafruit 的名称、密钥和仪表板 id。
通过浏览嵌入式网页输入三个参数,即 adafruit 的名称、密钥和仪表板 id。点击“提交”后,将被存储到RP2040内部的Flash中。下次打开RP2040-ETH-DVI-ZERO时,将跳过从浏览器获取参数的步骤,直接运行“获取adafruit仪表板”。
该嵌入网页的HTML代码:
- #ifndef PROGMEM
- #define PROGMEM
- #endif
-
- const char html_page[] PROGMEM = {
- "HTTP/1.1 200 OK\r\n"
- "Content-Type: text/html\r\n"
- "Connection: close\r\n" // the connection will be closed after completion of the response
- //"Refresh: 5\r\n" // refresh the page automatically every n sec
- "\r\n"
- "<!DOCTYPE HTML>"
- "<html>"
- "<head>"
- "<meta charset='UTF-8'>"
- "<title>RP2040-DVI-ETH-ZERO : adafruit io monitor</title>"
- "<link rel='icon' href='https://cdn-learn.adafruit.com/guides/images/000/000/570/medium800/AIO_LOGO.png' type='image/x-icon'>"
- "</head>"
- "<body>"
- "<p style='text-align:center;'>"
- "<img alt='ChatGPT' src='https://cdn-learn.adafruit.com/guides/images/000/000/570/medium800/AIO_LOGO.png' height='200' width='200'>"
- "<h1 align='center'>RP2040-DVI-ETH-ZERO</h1>"
- "<h1 align='center'>adafruit io monitor</h1>"
- "<div style='width:900px;margin: 0 auto;text-align: center'>"
- "<form action='/' method='post'>"
- "<input type='text' placeholder='adafruit io user' size='35' name='adafruit_user' required='required'/><br><br>"
- "<input type='text' placeholder='adafruit io key' size='35' name='adafruit_key' required='required'/><br><br>"
- "<input type='text' placeholder='adafruit io dashboard key' size='35' name='dashboard_key' required='required'/><br><br>"
- "<input type='submit' value='Submit' style='height:30px; width:80px;'/>"
- "</form>"
- "<div style='text-align: left;'>"
- "<h5>"
- "</h5>\r\n"
- "</div>"
- "</div>"
- "</body>\r\n"
- "<html>\r\n"
- };
获取adafruit.io的仪表板,我们可以得到屏幕上需要显示的所有框架的布局,包括所有块信息、位置、大小、对应的Feeds和Groups。
- #define dashboard_layout_max 16
- struct _Dashboard_Layout{
- boolean exist = false;
- uint8_t x;
- uint8_t y;
- uint8_t x_size;
- uint8_t y_size;
- String id;
- };
- _Dashboard_Layout dashboard_layout[dashboard_layout_max];
这是仪表板“RP2040-DVI-ETH-ZERO”的 Adafruit io 网络版本。
A_1_temp (W5100S_POE_EVB_PICO)
A_2_温度(W5100S_EVB_PICO)
A_3_temp (W5100S_EVB_PICO)
A_4_温度(W5500_EVB_PICO)
四块 PICO 板每 10 秒将这些内置温度传感器数据上传到 adafruit.io。
(因为我使用的是Adafruit的免费服务,所以通讯次数有限制)
这是我获取仪表板信息并重构显示框架后的仪表板。
在解析仪表板消息时,我们还获取了所有相关的 Feed 和 Group 信息。代码会自动订阅所有的Feed和Group,并将它们放入消息回调处理函数中。
- #define dashboard_block_max 16
- struct _Dashboard_block{
- boolean exist = false;
- String id;
- String name;
- String type;
- String label;
- uint16_t minValue;
- uint16_t maxValue;
- uint16_t minWarning;
- uint16_t maxWarning;
- uint8_t decimal;
- String feed_id;
- String feed_key;
- String feed_name;
- String group_key;
- };
- _Dashboard_block dashboard_block[dashboard_block_max];
消息回调处理代码:
- // you can also attach multiple feeds to the same
- // meesage handler function. both counter and counter-two
- // are attached to this callback function, and messages
- // for both will be received by this function.
- void feed_handle(AdafruitIO_Data *data) {
- Serial.print("received <- ");
- // since we are using the same function to handle
- // messages for two feeds, we can use feedName() in
- // order to find out which feed the message came from.
- Serial.print(data->feedName());
- Serial.print(" ");
- // print out the received count or counter-two value
- Serial.println(data->value());
-
- for(int i=0; i<dashboard_block_max; i++)
- {
- String Feed_data_decimal;
- if(dashboard_block[i].feed_key == data->feedName())
- {
- display.setTextColor(DashBoard_Text_Color);
-
- std::string Feed_data_decimal(data->value());
- if(Feed_data_decimal.find('.')!= -1)
- {
- Feed_data_decimal = (Feed_data_decimal.substr(0,Feed_data_decimal.find('.')+1+dashboard_block[i].decimal));
- Serial.println(Feed_data_decimal.c_str());
- }
- if(dashboard_block[i].type == "slider")
- {
- display.fillRoundRect(dashboard_layout[i].x*20+4,dashboard_layout[i].y*20+2+_y+dashboard_layout[i].y_size*20-16,dashboard_layout[i].x_size*20-8,10,3,DashBoard_Back_Color);
- display.fillRoundRect(dashboard_layout[i].x*20+5,dashboard_layout[i].y*20+2+_y+dashboard_layout[i].y_size*20-15,dashboard_layout[i].x_size*20-10,8,3,adafruit_grey);
- uint16_t slider_point = (atoi(data->value()))*(dashboard_layout[i].x_size*20-10)/100;
-
- display.fillRoundRect(dashboard_layout[i].x*20+5,dashboard_layout[i].y*20+2+_y+dashboard_layout[i].y_size*20-15,slider_point,8,3,DashBoard_Bar_Color);
- display.fillRect(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10-7,dashboard_layout[i].y*20+4+_y+10,30,10,DashBoard_Back_Color);
- display.setTextSize(1);
- display.setCursor(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10-7,dashboard_layout[i].y*20+4+_y+10);
- display.println(atoi(data->value()));
-
- }
- else if(dashboard_block[i].type == "gauge")
- {
- display.fillArc(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10,dashboard_layout[i].y*20+4+_y+40, 24, 30, 105, 75, DashBoard_Bar_Back_Color);
- display.setCursor(dashboard_layout[i].x*20 + 13, dashboard_layout[i].y*20 + _y + dashboard_layout[i].y_size*20 - 12);
- display.println(dashboard_block[i].minValue);
- display.setCursor(dashboard_layout[i].x*20 + dashboard_layout[i].x_size*20 -18 , dashboard_layout[i].y*20 + _y + dashboard_layout[i].y_size*20 - 12);
- display.println(dashboard_block[i].maxValue);
- display.setCursor(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10, dashboard_layout[i].y*20+4+_y+48);
-
- if((atoi(data->value()) <= dashboard_block[i].minWarning)||(atoi(data->value()) >= dashboard_block[i].maxWarning))
- {
- display.fillArc(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10,dashboard_layout[i].y*20+4+_y+40, 24, 30, 105, 105+ (atoi(data->value()) * 330 / 100), adafruit_red);
- DashBoard_warning = dashboard_block[i].maxWarning * 330 / 100;
- display.fillArc(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10,dashboard_layout[i].y*20+4+_y+40, 24, 30, 105+DashBoard_warning-1, 105+DashBoard_warning, BLACK);
- }
- else
- {
- display.fillArc(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10,dashboard_layout[i].y*20+4+_y+40, 24, 30, 105, 105+ (atoi(data->value()) * 330 / 100), DashBoard_Bar_Color);
- DashBoard_warning = dashboard_block[i].maxWarning * 330 / 100; display.fillArc(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10,dashboard_layout[i].y*20+4+_y+40, 24, 30, 105+DashBoard_warning-1, 105+DashBoard_warning, adafruit_red);
- }
- display.fillRect(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10-11,dashboard_layout[i].y*20+4+_y+30,30,10,DashBoard_Back_Color);
-
- display.setTextSize(1);
- display.setCursor(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10-11,dashboard_layout[i].y*20+4+_y+30);
- display.println(Feed_data_decimal.c_str());
- }
- }
- }
- }
将Feed和Group消息数据更新到显示屏后,效果如下:
由于该项目没有使用固定的显示参数,因此可以随着仪表板网页版的页面布局的任何变化而更改后续。
编辑布局后并保存。
那么RP2040-ETH-DVI-ZERO的显示界面也会相应改变显示布局。
仪表盘中包含了各个区块的警告值信息,显示界面也会根据警告值的不同显示不同。
我人为地提高了A_4_temp(W5500_EVB_PICO)的温度,您可以在屏幕上看到一条警告消息。
而且,显示界面的深色模式和浅色模式也会自动切换。
灯光模式视图:
我使用Arduino开发它,这些是该项目中使用的所有库:
- #include <AdafruitIO_Ethernet.h>
- #include <SPI.h>
- #include <EEPROM.h>
- #include <Ethernet.h>
- #include <LittleFS.h>
- #include <SD.h>
- #include <PicoDVI.h>
- #include <Arduino_GFX_Library.h>
- #include "html.h"
- #include "icon.h"
- #include <PNGdec.h>
- #include <iostream>
- #include <string>
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。