|
最近,我产生了一个想法:制作数码相框,其中一种是从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分钟后,第一批原型机会停止工作。该应用程序开始崩溃,并永久显示相同的图像,而不是在选定的时间后显示下一个图像。
我在互联网上进行了一些研究,发现很多人遇到了类似的问题。第二个问题似乎是由于代码中的某些内存泄漏引起的。因此,我想分享自己的工作方式。
所需的材料清单: – Arduino Uno开发板 – 跳线 – 面包板 – KMR-1.8 SPI TFT显示屏(宽160像素,高128像素) – SD卡适配器
重要的提示: 不同制造商的各种版本的所谓的“ 1.8 TFT显示屏”都不大一样。并非全部都是100%兼容的。因此,如果您拥有TFT显示屏并且想使用本文来使其正常工作,请检查您的TFT显示屏是否确实与本文中使用的版本匹配:
接线方式: 为了使其工作,您需要在Arduino和TFT显示屏之间连接许多导线。我使用fritzing制作了一个显示所有接线的示意图:
Arduino的5V引脚连接到VCC引脚以及LED +引脚。 Arduino的GND引脚连接到TFT显示屏的GND和LED-。 Arduino的13号数字引脚也连接到两个引脚(SCK和SCL)。接下来,是连接完成的图片:
源代码 源代码依赖于三个头文件(和库):SPI.h(链接)、SD.h(链接)和TFT.h(链接)。在使用代码之前,请确保所有组件均已正确安装(在Arduino IDE中:工具->管理库…)。
不使用TFT库的默认初始化方法(“ TFTscreen.begin();”),解决了第一个问题。我发现了一个名为“ initR”的函数,该函数具有一个参数,可以执行特定芯片的初始化。本文使用的参数值是“ INITR_BLACKTAB”,然后可以正确显示颜色。另外,为了符合默认的初始化方法,我使用参数值“ 1”调用setRotation方法。最后,用于设置TFT库对象的代码如下所示: - // ...
- TFTscreen.initR(INITR_BLACKTAB);
- TFTscreen.setRotation(1);
- // ...
复制代码
通过避免任何可能的内存泄漏来解决第二个问题,即在每一位内存不再需要后立即释放。 因此,您会发现很多“关闭”方法调用以及一些奇怪的字符串处理。 当我编写代码时,以为可以精简一些代码。 但是,内存泄漏问题又回来了。 因此,该代码可能看起来很奇怪,但它可以工作。
以下是完整的源代码: - #include <SPI.h>
- #include <SD.h>
- #include <TFT.h>
- #define PIN_SD_CS 4
- #define PIN_TFT_CS 10
- #define PIN_DC 9
- #define PIN_RST 8
- #define DELAY_IMAGE_SWAP 60000 // each image is shown for 60 seconds
- TFT TFTscreen = TFT(PIN_TFT_CS, PIN_DC, PIN_RST);
- void setup() {
- // initialize default serial connection to send debug information
- Serial.begin(9600);
- while (!Serial) {
- // wait until default serial connection is fully set up
- }
-
- //The following two lines replace "TFTscreen.begin();" => avoids that red and blue (?) are swapped/interchanged
- TFTscreen.initR(INITR_BLACKTAB);
- TFTscreen.setRotation(1);
-
-
- TFTscreen.background(255, 255, 255); // prints black screen to TFT display
-
- init_SD(); // function call that initializes SD card
- }
- void init_SD() {
- // try to init SD card
- Serial.print(F("SD card init..."));
- if (!SD.begin(PIN_SD_CS)) {
- Serial.println(F("ERROR")); // failed
- return;
- }
- Serial.println(F("SUCCESS")); // ok
- }
- void loop() {
- File dir = SD.open("/"); // open root path on SD card
- File entry;
- char name[16];
- bool worked_once = false;
- while (entry = dir.openNextFile()) { // iteratively opens all files on SD card.
- Serial.print(F("Opened File: "));
- Serial.println(entry.name());
- strcpy(name, entry.name()); // file name is copied to variable "name"
- entry.close(); // After copying the name, we do not need the entry anymore and, therefore, close it.
- int filename_len = strlen(name);
- 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.
- PImage image = TFTscreen.loadImage(name); // loads the file from the SD card
- if (image.isValid()) { // If the loaded image is valid, we can display it on the TFT.
- Serial.println(F("Image is valid... drawing image."));
- TFTscreen.image(image, 0, 0); // this function call displays the image on the TFT.
- worked_once = true; // we set this variable to true, in order to indicate that at least one image could be displayed
- delay(DELAY_IMAGE_SWAP);
- } else {
- Serial.println(F("Image is not valid... image is not drawn."));
- }
- image.close(); // image is closed as we do not need it anymore.
- } else {
- Serial.println(F("Filename does not end with BMP!"));
- }
- }
- dir.close(); // directory is closed
- if (worked_once == false) { // if not a single image could be shown, we reconnect to the SD card reader.
- Serial.println(F("Warning: Printing an image did not work once! Trying to reinitalize SD card reader."));
- SD.end();
- init_SD();
- }
- }
复制代码
该代码在SD卡上查找图像文件(* .BMP),并显示每个图像60秒钟。 您可以通过将“ DELAY_IMAGE_SWAP”设置为新值来更改显示时间。
重要说明:SD卡上的图像文件必须作为BMP存储,分辨率为160×128像素(宽x高)。 此外,必须避免使用长文件名和特殊字符。
如果一切都正确完成,则基于Arduino的“数码相框”应该可以正确显示图片。 以下是一个示例图片:
|