当前位置:   article > 正文

RP2040-ETH-DVI-ZERO:Adafruit IO 仪表板监视器( HDMI / DVI 模式)_rp2040 模拟hdmi

rp2040 模拟hdmi
 新开发的Raspberry Pi RP2040开发板,带有DVI接口和以太网。该项目可以显示 adafruit IO 仪表板并跟踪任何更改。

转发: RP2040-ETH-DVI-ZERO: Adafruit IO Dashboard Monitor ( HDMI / DVI Mode )

Surf5 Design Contest


项目介绍

我新开发了一块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代码:

  1. #ifndef PROGMEM
  2. #define PROGMEM
  3. #endif
  4. const char html_page[] PROGMEM = {
  5. "HTTP/1.1 200 OK\r\n"
  6. "Content-Type: text/html\r\n"
  7. "Connection: close\r\n" // the connection will be closed after completion of the response
  8. //"Refresh: 5\r\n" // refresh the page automatically every n sec
  9. "\r\n"
  10. "<!DOCTYPE HTML>"
  11. "<html>"
  12. "<head>"
  13. "<meta charset='UTF-8'>"
  14. "<title>RP2040-DVI-ETH-ZERO : adafruit io monitor</title>"
  15. "<link rel='icon' href='https://cdn-learn.adafruit.com/guides/images/000/000/570/medium800/AIO_LOGO.png' type='image/x-icon'>"
  16. "</head>"
  17. "<body>"
  18. "<p style='text-align:center;'>"
  19. "<img alt='ChatGPT' src='https://cdn-learn.adafruit.com/guides/images/000/000/570/medium800/AIO_LOGO.png' height='200' width='200'>"
  20. "<h1 align='center'>RP2040-DVI-ETH-ZERO</h1>"
  21. "<h1 align='center'>adafruit io monitor</h1>"
  22. "<div style='width:900px;margin: 0 auto;text-align: center'>"
  23. "<form action='/' method='post'>"
  24. "<input type='text' placeholder='adafruit io user' size='35' name='adafruit_user' required='required'/><br><br>"
  25. "<input type='text' placeholder='adafruit io key' size='35' name='adafruit_key' required='required'/><br><br>"
  26. "<input type='text' placeholder='adafruit io dashboard key' size='35' name='dashboard_key' required='required'/><br><br>"
  27. "<input type='submit' value='Submit' style='height:30px; width:80px;'/>"
  28. "</form>"
  29. "<div style='text-align: left;'>"
  30. "<h5>"
  31. "</h5>\r\n"
  32. "</div>"
  33. "</div>"
  34. "</body>\r\n"
  35. "<html>\r\n"
  36. };

获取adafruit.io的仪表板,我们可以得到屏幕上需要显示的所有框架的布局,包括所有块信息、位置、大小、对应的Feeds和Groups。

  1. #define dashboard_layout_max 16
  2. struct _Dashboard_Layout{
  3. boolean exist = false;
  4. uint8_t x;
  5. uint8_t y;
  6. uint8_t x_size;
  7. uint8_t y_size;
  8. String id;
  9. };
  10. _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,并将它们放入消息回调处理函数中。

  1. #define dashboard_block_max 16
  2. struct _Dashboard_block{
  3. boolean exist = false;
  4. String id;
  5. String name;
  6. String type;
  7. String label;
  8. uint16_t minValue;
  9. uint16_t maxValue;
  10. uint16_t minWarning;
  11. uint16_t maxWarning;
  12. uint8_t decimal;
  13. String feed_id;
  14. String feed_key;
  15. String feed_name;
  16. String group_key;
  17. };
  18. _Dashboard_block dashboard_block[dashboard_block_max];

消息回调处理代码:

  1. // you can also attach multiple feeds to the same
  2. // meesage handler function. both counter and counter-two
  3. // are attached to this callback function, and messages
  4. // for both will be received by this function.
  5. void feed_handle(AdafruitIO_Data *data) {
  6. Serial.print("received <- ");
  7. // since we are using the same function to handle
  8. // messages for two feeds, we can use feedName() in
  9. // order to find out which feed the message came from.
  10. Serial.print(data->feedName());
  11. Serial.print(" ");
  12. // print out the received count or counter-two value
  13. Serial.println(data->value());
  14. for(int i=0; i<dashboard_block_max; i++)
  15. {
  16. String Feed_data_decimal;
  17. if(dashboard_block[i].feed_key == data->feedName())
  18. {
  19. display.setTextColor(DashBoard_Text_Color);
  20. std::string Feed_data_decimal(data->value());
  21. if(Feed_data_decimal.find('.')!= -1)
  22. {
  23. Feed_data_decimal = (Feed_data_decimal.substr(0,Feed_data_decimal.find('.')+1+dashboard_block[i].decimal));
  24. Serial.println(Feed_data_decimal.c_str());
  25. }
  26. if(dashboard_block[i].type == "slider")
  27. {
  28. 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);
  29. 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);
  30. uint16_t slider_point = (atoi(data->value()))*(dashboard_layout[i].x_size*20-10)/100;
  31. 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);
  32. 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);
  33. display.setTextSize(1);
  34. display.setCursor(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10-7,dashboard_layout[i].y*20+4+_y+10);
  35. display.println(atoi(data->value()));
  36. }
  37. else if(dashboard_block[i].type == "gauge")
  38. {
  39. 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);
  40. display.setCursor(dashboard_layout[i].x*20 + 13, dashboard_layout[i].y*20 + _y + dashboard_layout[i].y_size*20 - 12);
  41. display.println(dashboard_block[i].minValue);
  42. 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);
  43. display.println(dashboard_block[i].maxValue);
  44. display.setCursor(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10, dashboard_layout[i].y*20+4+_y+48);
  45. if((atoi(data->value()) <= dashboard_block[i].minWarning)||(atoi(data->value()) >= dashboard_block[i].maxWarning))
  46. {
  47. 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);
  48. DashBoard_warning = dashboard_block[i].maxWarning * 330 / 100;
  49. 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);
  50. }
  51. else
  52. {
  53. 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);
  54. 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);
  55. }
  56. 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);
  57. display.setTextSize(1);
  58. display.setCursor(dashboard_layout[i].x*20+dashboard_layout[i].x_size*10-11,dashboard_layout[i].y*20+4+_y+30);
  59. display.println(Feed_data_decimal.c_str());
  60. }
  61. }
  62. }
  63. }

将Feed和Group消息数据更新到显示屏后,效果如下:

由于该项目没有使用固定的显示参数,因此可以随着仪表板网页版的页面布局的任何变化而更改后续。

编辑布局后并保存。

那么RP2040-ETH-DVI-ZERO的显示界面也会相应改变显示布局。

仪表盘中包含了各个区块的警告值信息,显示界面也会根据警告值的不同显示不同。

我人为地提高了A_4_temp(W5500_EVB_PICO)的温度,您可以在屏幕上看到一条警告消息。

而且,显示界面的深色模式和浅色模式也会自动切换。

灯光模式视图:

我使用Arduino开发它,这些是该项目中使用的所有库:

  1. #include <AdafruitIO_Ethernet.h>
  2. #include <SPI.h>
  3. #include <EEPROM.h>
  4. #include <Ethernet.h>
  5. #include <LittleFS.h>
  6. #include <SD.h>
  7. #include <PicoDVI.h>
  8. #include <Arduino_GFX_Library.h>
  9. #include "html.h"
  10. #include "icon.h"
  11. #include <PNGdec.h>
  12. #include <iostream>
  13. #include <string>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/659587
推荐阅读
相关标签
  

闽ICP备14008679号