103浏览
查看: 103|回复: 5

[项目] 【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目

[复制链接]
【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目图2

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目图1

驴友花雕  中级技神
 楼主|

发表于 3 天前

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目图1

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目图2
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 3 天前

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目图2

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目图1
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 3 天前

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目

  【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
  实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
  项目之一百一十九:ESP32+GC9A01之随机移动表针的专业仪表盘

实验开源代码

  1. /*
  2.   【Arduino】189种传感器模块系列实验(资料代码+仿真编程+图形编程)
  3.   实验二百四十九:1.28寸圆形彩色TFT显示屏 高清IPS 模块 240*240 SPI接口GC9A01驱动
  4.   项目之一百一十九:ESP32+GC9A01之随机移动表针的专业仪表盘
  5. */
  6. //       GC9A01---------- ESP32
  7. //       RST ------------ NC(复位引脚,此处未连接)
  8. //       CS ------------- D4(片选引脚,连接到ESP32的D4引脚)
  9. //       DC ------------- D2(数据/命令选择引脚,连接到ESP32的D2引脚)
  10. //       SDA ------------ D23 (green)(主数据输出引脚,连接到ESP32的D23引脚,绿色线)
  11. //       SCL ------------ D18 (yellow)(时钟信号引脚,连接到ESP32的D18引脚,黄色线)
  12. //       GND ------------ GND(接地引脚,连接到ESP32的接地端)
  13. //       VCC -------------3V3(电源引脚,连接到ESP32的3.3V电源)
  14. // 定义指针的长度、宽度、半径和颜色
  15. #define NEEDLE_LENGTH 35  // 可见长度
  16. #define NEEDLE_WIDTH   5  // 指针宽度 - 设置为奇数
  17. #define NEEDLE_RADIUS 90  // 指针顶端的半径
  18. #define NEEDLE_COLOR1 TFT_MAROON  // 指针外围颜色
  19. #define NEEDLE_COLOR2 TFT_RED     // 指针中心颜色
  20. #define DIAL_CENTRE_X 120  // 表盘中心的X坐标
  21. #define DIAL_CENTRE_Y 120  // 表盘中心的Y坐标
  22. // 加载字体
  23. #include "NotoSansBold36.h"
  24. #define AA_FONT_LARGE NotoSansBold36
  25. #include <TFT_eSPI.h>
  26. TFT_eSPI tft = TFT_eSPI();  // 创建TFT对象
  27. TFT_eSprite needle = TFT_eSprite(&tft);  // 用于指针的精灵对象
  28. TFT_eSprite spr    = TFT_eSprite(&tft);  // 用于显示刻度的精灵对象
  29. // 加载jpeg图片数据
  30. #include "dial.h"
  31. // 包含jpeg解码库
  32. #include <TJpg_Decoder.h>
  33. uint16_t* tft_buffer;  // 用于存储TFT屏幕像素块的缓冲区
  34. bool      buffer_loaded = false;  // 缓冲区是否已加载
  35. uint16_t  spr_width = 0;  // 精灵宽度
  36. uint16_t  bg_color =0;  // 背景颜色
  37. // 这个函数将在解码jpeg文件时被调用
  38. bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
  39. {
  40.   // 如果图片超出了屏幕边界,停止进一步解码
  41.   if ( y >= tft.height() ) return 0;
  42.   // 该函数会自动剪裁图像块,并将其渲染到TFT屏幕上
  43.   tft.pushImage(x, y, w, h, bitmap);
  44.   // 返回1以解码下一个块
  45.   return 1;
  46. }
  47. // 初始化设置
  48. void setup()   {
  49.   Serial.begin(115200); // 仅用于调试
  50.   // 设置字节顺序(对于TFT_eSPI设置为true)
  51.   TJpgDec.setSwapBytes(true);
  52.   // 必须给jpeg解码器指定渲染函数
  53.   TJpgDec.setCallback(tft_output);
  54.   tft.begin();
  55.   tft.setRotation(2);
  56.   tft.fillScreen(TFT_BLACK);
  57.   // 绘制表盘
  58.   TJpgDec.drawJpg(0, 0, dial, sizeof(dial));
  59.   tft.drawCircle(DIAL_CENTRE_X, DIAL_CENTRE_Y, NEEDLE_RADIUS-NEEDLE_LENGTH, TFT_DARKGREY);
  60.   // 加载字体并创建显示刻度的精灵
  61.   spr.loadFont(AA_FONT_LARGE);
  62.   spr_width = spr.textWidth("777"); // 数字7在此字体中最宽
  63.   spr.createSprite(spr_width, spr.fontHeight());
  64.   bg_color = tft.readPixel(120, 120); // 从表盘中心获取颜色
  65.   spr.fillSprite(bg_color);
  66.   spr.setTextColor(TFT_WHITE, bg_color, true);
  67.   spr.setTextDatum(MC_DATUM);
  68.   spr.setTextPadding(spr_width);
  69.   spr.drawNumber(0, spr_width/2, spr.fontHeight()/2);
  70.   spr.pushSprite(DIAL_CENTRE_X - spr_width / 2, DIAL_CENTRE_Y - spr.fontHeight() / 2);
  71.   // 绘制标签文字
  72.   tft.setTextColor(TFT_WHITE, bg_color);
  73.   tft.setTextDatum(MC_DATUM);
  74.   tft.drawString("(degrees)", DIAL_CENTRE_X, DIAL_CENTRE_Y + 48, 2);
  75.   // 在创建指针之前,定义指针在TFT上的旋转中心点
  76.   tft.setPivot(DIAL_CENTRE_X, DIAL_CENTRE_Y);
  77.   // 创建指针精灵
  78.   createNeedle();
  79.   // 将指针位置重置为0
  80.   plotNeedle(0, 0);
  81.   delay(2000);  // 延迟2秒
  82. }
  83. // 主循环
  84. void loop() {
  85.   uint16_t angle = random(241); // 随机生成0到240范围内的角度
  86.   // 以每次40ms的增量绘制指针到随机角度
  87.   plotNeedle(angle, 30);
  88.   // 在新位置暂停2.5秒
  89.   delay(2500);
  90. }
  91. // 创建指针精灵
  92. void createNeedle(void)
  93. {
  94.   needle.setColorDepth(16);  // 设置颜色深度
  95.   needle.createSprite(NEEDLE_WIDTH, NEEDLE_LENGTH);  // 创建指针精灵
  96.   needle.fillSprite(TFT_BLACK); // 用黑色填充精灵
  97.   // 定义相对于精灵左上角的指针旋转点
  98.   uint16_t piv_x = NEEDLE_WIDTH / 2; // 精灵的旋转点x(在中间)
  99.   uint16_t piv_y = NEEDLE_RADIUS;    // 精灵的旋转点y
  100.   needle.setPivot(piv_x, piv_y);     // 设置旋转点
  101.   // 在精灵中绘制红色指针
  102.   needle.fillRect(0, 0, NEEDLE_WIDTH, NEEDLE_LENGTH, TFT_MAROON);
  103.   needle.fillRect(1, 1, NEEDLE_WIDTH-2, NEEDLE_LENGTH-2, TFT_RED);
  104.   // 获取旋转后边界的参数
  105.   int16_t min_x;
  106.   int16_t min_y;
  107.   int16_t max_x;
  108.   int16_t max_y;
  109.   // 计算必须从TFT上抓取的最坏情况区域(45度旋转时)
  110.   needle.getRotatedBounds(45, &min_x, &min_y, &max_x, &max_y);
  111.   // 计算缓冲区大小并分配用于抓取TFT区域的缓冲区
  112.   tft_buffer =  (uint16_t*) malloc( ((max_x - min_x) + 2) * ((max_y - min_y) + 2) * 2 );
  113. }
  114. // 将指针移动到新位置
  115. void plotNeedle(int16_t angle, uint16_t ms_delay)
  116. {
  117.   static int16_t old_angle = -120; // 初始角度为-120度
  118.   // 边界框参数
  119.   static int16_t min_x;
  120.   static int16_t min_y;
  121.   static int16_t max_x;
  122.   static int16_t max_y;
  123.   if (angle < 0) angle = 0; // 限制角度以模拟指针停止
  124.   if (angle > 240) angle = 240;
  125.   angle -= 120; // 从-120度开始
  126.   // 逐步移动指针,直到达到新角度
  127.   while (angle != old_angle || !buffer_loaded) {
  128.     if (old_angle < angle) old_angle++;
  129.     else old_angle--;
  130.     // 仅在偶数值时绘制指针以提高绘制性能
  131.     if ( (old_angle & 1) == 0)
  132.     {
  133.       if (buffer_loaded) {
  134.         // 将原始区域推回到屏幕上以擦除旧指针图形
  135.         tft.pushRect(min_x, min_y, 1 + max_x - min_x, 1 + max_y - min_y, tft_buffer);
  136.       }
  137.       if ( needle.getRotatedBounds(old_angle, &min_x, &min_y, &max_x, &max_y) )
  138.       {
  139.         // 在绘制指针之前抓取该区域的副本
  140.         tft.readRect(min_x, min_y, 1 + max_x - min_x, 1 + max_y - min_y, tft_buffer);
  141.         buffer_loaded = true;
  142.       }
  143.       // 在新位置绘制指针,指针图像中的黑色为透明
  144.       needle.pushRotated(old_angle, TFT_BLACK);
  145.       // 在下一次更新之前延迟
  146.       delay(ms_delay);
  147.     }
  148.     // 更新表盘中心的数字
  149.     spr.setTextColor(TFT_WHITE, bg_color, true);
  150.     spr.drawNumber(old_angle+120, spr_width/2, spr.fontHeight()/2);
  151.     spr.pushSprite(120 - spr_width / 2, 120 - spr.fontHeight() / 2);
  152.     // 在指针接近新位置时稍微放慢速度
  153.     if (abs(old_angle - angle) < 10) ms_delay += ms_delay / 5;
  154.   }
  155. }
复制代码


回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 3 天前

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目

实验场景图  动态图

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目图2

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目图1
回复

使用道具 举报

驴友花雕  中级技神
 楼主|

发表于 3 天前

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目

实验场景图  动态图

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目图1

【花雕学编程】Arduino动手做(249)--GC9A01专业仪表盘项目图2
回复

使用道具 举报

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

本版积分规则

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

硬件清单

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

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

mail