风筝
发表于: 2020-2-4 22:09:16 | 显示全部楼层

最近,我产生了一个想法:制作数码相框,其中一种是从SD卡加载图像并显示每个图像一段时间。我记得有一个小型TFT显示屏KMR-1.8 SPI,该显示器可以与Arduino Uno一起使用。当我深入了解KMR-1.8 SPI时,意识到它也具有内置的SD卡读取器。此外,我找到了内置SD卡读卡器的即用型库,并在TFT显示屏上显示了图像。由于这些原因,我认为制作这样的数码相框非常容易。


当我开始实施第一行代码并将Arduino Uno连接到KMR-1.8 SPI时,遇到了两个主要问题。首先,图像文件的颜色与KMR-1.8显示的颜色不匹配。其次,大约5分钟后,第一批原型机会停止工作。该应用程序开始崩溃,并永久显示相同的图像,而不是在选定的时间后显示下一个图像。


我在互联网上进行了一些研究,发现很多人遇到了类似的问题。第二个问题似乎是由于代码中的某些内存泄漏引起的。因此,我想分享自己的工作方式。

kmr18_tft.png


所需的材料清单:

–  Arduino Uno开发板

–  跳线

–  面包板

–  KMR-1.8 SPI TFT显示屏(宽160像素,高128像素)

–  SD卡适配器


重要的提示:

不同制造商的各种版本的所谓的“ 1.8 TFT显示屏”都不大一样。并非全部都是100%兼容的。因此,如果您拥有TFT显示屏并且想使用本文来使其正常工作,请检查您的TFT显示屏是否确实与本文中使用的版本匹配:

kmr_18_fron.png


接线方式:

为了使其工作,您需要在Arduino和TFT显示屏之间连接许多导线。我使用fritzing制作了一个显示所有接线的示意图:

fritzing_arduino_tft_bb.jpg


Arduino的5V引脚连接到VCC引脚以及LED +引脚。 Arduino的GND引脚连接到TFT显示屏的GND和LED-。 Arduino的13号数字引脚也连接到两个引脚(SCK和SCL)。接下来,是连接完成的图片:

wiring_arduino_tft_display.jpg


源代码

源代码依赖于三个头文件(和库):SPI.h(链接)、SD.h(链接)和TFT.h(链接)。在使用代码之前,请确保所有组件均已正确安装(在Arduino IDE中:工具->管理库…)。


不使用TFT库的默认初始化方法(“ TFTscreen.begin();”),解决了第一个问题。我发现了一个名为“ initR”的函数,该函数具有一个参数,可以执行特定芯片的初始化。本文使用的参数值是“ INITR_BLACKTAB”,然后可以正确显示颜色。另外,为了符合默认的初始化方法,我使用参数值“ 1”调用setRotation方法。最后,用于设置TFT库对象的代码如下所示:

  1. // ...
  2. TFTscreen.initR(INITR_BLACKTAB);
  3. TFTscreen.setRotation(1);
  4. // ...
复制代码

通过避免任何可能的内存泄漏来解决第二个问题,即在每一位内存不再需要后立即释放。 因此,您会发现很多“关闭”方法调用以及一些奇怪的字符串处理。 当我编写代码时,以为可以精简一些代码。 但是,内存泄漏问题又回来了。 因此,该代码可能看起来很奇怪,但它可以工作。


以下是完整的源代码:

  1. #include <SPI.h>
  2. #include <SD.h>
  3. #include <TFT.h>
  4. #define PIN_SD_CS 4
  5. #define PIN_TFT_CS 10
  6. #define PIN_DC 9
  7. #define PIN_RST 8
  8. #define DELAY_IMAGE_SWAP 60000 // each image is shown for 60 seconds
  9. TFT TFTscreen = TFT(PIN_TFT_CS, PIN_DC, PIN_RST);
  10. void setup() {
  11.   // initialize default serial connection to send debug information
  12.   Serial.begin(9600);
  13.   while (!Serial) {
  14.     // wait until default serial connection is fully set up
  15.   }
  16.   
  17.   //The following two lines replace "TFTscreen.begin();" => avoids that red and blue (?) are swapped/interchanged
  18.   TFTscreen.initR(INITR_BLACKTAB);
  19.   TFTscreen.setRotation(1);
  20.   
  21.   
  22.   TFTscreen.background(255, 255, 255); // prints black screen to TFT display
  23.   
  24.   init_SD(); // function call that initializes SD card
  25. }
  26. void init_SD() {
  27.   // try to init SD card
  28.   Serial.print(F("SD card init..."));
  29.   if (!SD.begin(PIN_SD_CS)) {
  30.     Serial.println(F("ERROR")); // failed
  31.     return;
  32.   }
  33.   Serial.println(F("SUCCESS")); // ok
  34. }
  35. void loop() {
  36.   File dir = SD.open("/"); // open root path on SD card
  37.   File entry;
  38.   char name[16];
  39.   bool worked_once = false;
  40.   while (entry = dir.openNextFile()) { // iteratively opens all files on SD card.
  41.     Serial.print(F("Opened File: "));
  42.     Serial.println(entry.name());
  43.     strcpy(name, entry.name()); // file name is copied to variable "name"
  44.     entry.close(); // After copying the name, we do not need the entry anymore and, therefore, close it.
  45.     int filename_len = strlen(name);
  46.     if ((filename_len >= 4 && strcmp(name + filename_len - 4, ".BMP") == 0)) { // check if the current filename ends with ".BMP". If so, we might have an image.
  47.       PImage image = TFTscreen.loadImage(name); // loads the file from the SD card
  48.       if (image.isValid()) { // If the loaded image is valid, we can display it on the TFT.
  49.         Serial.println(F("Image is valid... drawing image."));  
  50.         TFTscreen.image(image, 0, 0); // this function call displays the image on the TFT.
  51.         worked_once = true; // we set this variable to true, in order to indicate that at least one image could be displayed
  52.         delay(DELAY_IMAGE_SWAP);
  53.       } else {
  54.         Serial.println(F("Image is not valid... image is not drawn."));  
  55.       }  
  56.       image.close(); // image is closed as we do not need it anymore.
  57.     } else {
  58.       Serial.println(F("Filename does not end with BMP!"));  
  59.     }
  60.   }
  61.   dir.close(); // directory is closed
  62.   if (worked_once == false) { // if not a single image could be shown, we reconnect to the SD card reader.
  63.     Serial.println(F("Warning: Printing an image did not work once! Trying to reinitalize SD card reader."));        
  64.     SD.end();
  65.     init_SD();
  66.   }
  67. }
复制代码

该代码在SD卡上查找图像文件(* .BMP),并显示每个图像60秒钟。 您可以通过将“ DELAY_IMAGE_SWAP”设置为新值来更改显示时间。


重要说明:SD卡上的图像文件必须作为BMP存储,分辨率为160×128像素(宽x高)。 此外,必须避免使用长文件名和特殊字符。


如果一切都正确完成,则基于Arduino的“数码相框”应该可以正确显示图片。 以下是一个示例图片:

tractor_tft_display.jpg

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题 700 | 回复: 1483



手机版|

GMT+8, 2024-5-8 10:31 , Processed in 0.041067 second(s), 6 queries , Gzip On, MemCache On. Powered by Discuz! X3.5

YiBoard一板网 © 2015-2022 地址:河北省石家庄市长安区高营大街 ( 冀ICP备18020117号 )

快速回复 返回顶部 返回列表