Yesterday, my 2.4" TFT touchscreen shield arrived at last! Despite the webpage claiming that it would work with the Adafruit TFTLCD and GFX libraries, it didn't!
I followed the instructions to change the flag in the Adafruit_TFTLCD.h file, breakout board to Arduino shield, to no avail.
In desperation, I tried an alternative library MCUFRIEND_kbv.h and all works as expected.
Good one... it looks like the same one I have, and much better than the LCD you previously used.
Next, you can start logging to SD storage, and a nice menu wouldn't go astray either 😉
Good one... it looks like the same one I have, and much better than the LCD you previously used.
Next, you can start logging to SD storage, and a nice menu wouldn't go astray either 😉
Yes, a vast improvement on the 20/04 LCD. My first laptop had a 320 x 240 resolution (CGA), albeit a 14" diagonal display, and weighed a ton.
I have been trying to get access to the SD reader on this unit but haven't cracked it yet, any tips??
I have been trying to get access to the SD reader on this unit but haven't cracked it yet, any tips??
Sure... it has to do with your chip select pin.
Load up the Arduino SD ReadWrite sketch from the examples.
Change:
if (!SD.begin(4)) {
To:
if (!SD.begin()) {
I looked up the begin(...) member function and it had a default value (SD_CHIP_SELECT_PIN), so I just tried using that by removing the argument and it worked.
If you know the "SS" pin (it's 10 for me) on your display unit, then correct it, otherwise try the above 🙂
Already got that sorted. All fine on the UNO but I had to run Pin 13 to 52, 12 to 50 and 11 to 51 on the Mega. With the shield mounted on the Uno, no access to any pins!
I wanted to run this past you. As the only way, I have found to delete the data from the screen, is to rewrite the current data in the background colour (black) and then write the new data in green to the display. Changing from one set of data to the next led to a long flicker, so I decided to change the values one at a time which decreases the length of time to change one displayed value.
I wrote this test sketch with dummy data to experiment:
void setup() { // put your setup code here, to run once: pinMode(11, INPUT); pinMode(12, INPUT); pinMode(13, INPUT); // intialise SD reader Serial.begin(9600); if(!SD.begin(10)){ Serial.println("SD card not initialised"); while(1); } tft.reset(); tft.begin(0x9341); tft.setRotation(0); tft.setTextSize(2); // set up the screen template tft.fillScreen(ILI9341_BLACK); tft.setCursor(0, 0); tft.setTextColor(ILI9341_DARKCYAN); tft.println("Pugwash Programming!"); tft.drawRect(60, 35, 120, 30, ILI9341_YELLOW); tft.setTextColor(ILI9341_WHITE); tft.setCursor(10, 87); tft.println("DATE: "); tft.setCursor(10, 117); tft.println("TIME: "); tft.setCursor(10, 147); tft.println("TEMP: "); tft.setCursor(10, 177); tft.println("PRESSURE: "); tft.setCursor(10, 207); tft.println("HUMIDITY: "); tft.setCursor(10, 237); tft.println("UV-INDEX: "); tft.setCursor(10, 267); tft.println("MAX TEMP: "); tft.setCursor(10, 297); tft.println("MIN TEMP: "); } void loop(void) { changeTitle(80, 92, 42, 42, "BALCONY", "ATTIC"); changeDataValue(75, 87, "2020-03-08", "2020-03-07"); changeDataValue(75, 117, "04:12:36", "14:11:46"); changeDataValue(75, 147, "08.45 C", "13.43 C"); changeDataValue(120, 177, "1010.67", "1009.56"); changeDataValue(120, 207, "50.21%", "40.45%"); changeDataValue(120, 237, "1.00", "0.00"); changeDataValue(120, 267, "18.45 C", "15.67 C"); changeDataValue(120, 297, "4.67 C", "3.23 C"); delay(5000); changeTitle(92, 80, 42, 42, "ATTIC", "BALCONY"); changeDataValue(75, 87, "2020-03-07", "2020-03-08"); changeDataValue(75, 117, "14:11:46", "04:12:36"); changeDataValue(75, 147, "13.43 C", "08.45 C"); changeDataValue(120, 177, "1009.56", "1010.67"); changeDataValue(120, 207, "40.45%", "50.21%"); changeDataValue(120, 237, "0.00", "1.00"); changeDataValue(120, 267, "15.67 C", "18.45 C"); changeDataValue(120, 297, "3.23 C", "4.67 C"); delay(5000); } void changeDataValue(int x1, int y1, String oldString, String newString){ tft.setTextColor(ILI9341_BLACK); tft.setCursor(x1, y1); tft.println(oldString); tft.setTextColor(ILI9341_GREEN); tft.setCursor(x1, y1); tft.println(newString); } void changeTitle(int x1, int x2, int y1, int y2, String oldString, String newString){ tft.setTextColor(ILI9341_BLACK); tft.setCursor(x1, y1); tft.println(oldString); tft.setTextColor(ILI9341_GREEN); tft.setCursor(x2, y2); tft.println(newString); }
Now when the data changes it runs down the screen like a wave!
Perhaps you have an idea of how to improve the performance of data changing on the screen?
I have another question for you! I was looking through the Adafruit example code and I discovered they were using the function yield(); quite a lot. I have seen this in Python when dealing with threads but I was wondering what its purpose is in an Arduino sketch. It must be there for a reason, but I would love to know "when and where" I should use it!
It must be there for a reason, but I would love to know "when and where" I should use it!
Maybe this ?
Eric
Interesting but it doesn't seem to apply to the Mega or Uno boards and the code examples are not directly nor indirectly invoking the scheduler.h library.
Ok, it is definitely intended for multi-thread usage. The standard Arduino defines it "weakly" as an empty function that can be redefined : it is in hooks.c (C:\Users\<<username>>\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.2\cores\arduino\hooks.c)
Here's the comment :
/**
* Empty yield() hook.
*
* This function is intended to be used by library writers to build
* libraries or sketches that supports cooperative threads.
*
* Its defined as a weak symbol and it can be redefined to implement a
* real cooperative scheduler.
*/
So for example for ESPduino it is redefined, to allow for background WiFi/BLE management
Eric
One thing I had noticed that Adafruit was calling the yield() function directly after the fillScreen() function, which is one of the most time consuming functions used with these TFT displays. I could quite understand using yield() in a multi-threaded program, but I am guessing when I say that this is only possible with a microprocessor and NOT with a microcontroller!!
So it is really doing nothing at all??
Yep ! In the base avr implementation from Arduino, the weak definition is :
static void __empty() {
// Empty
}
void yield(void) __attribute__ ((weak, alias("__empty")));
But keeping it called probably helps some libraries to be compatible with ESP or other multi-threaded platforms Arduino environments, because these platforms would actually need to keep some form of scheduling going on behind the scenes.
Eric
only possible with a microprocessor and NOT with a microcontroller
Well, an ESP32 has 2 cores, and usually the programmer uses one, while the other is best left to the system for ongoing communications.
Eric
Also in the ESP8266 Arduino Core library version of these functions, you can see mention of their yield() being delay(0) , and delay() itself giving some CPU time to comms : https://arduino-esp8266.readthedocs.io/en/2.6.1/reference.html#timing-and-delays
Eric
After refactoring the code I am now down to this:
#include <Adafruit_GFX.h> // Hardware-specific library #include <SPI.h> #include <SD.h> #include <MCUFRIEND_kbv.h> File myFile; MCUFRIEND_kbv tft; #define ILI9341_BLACK 0x0000 ///< 0, 0, 0 #define ILI9341_DARKCYAN 0x03EF ///< 0, 125, 123 #define ILI9341_YELLOW 0xFFE0 ///< 255, 255, 0 #define ILI9341_WHITE 0xFFFF ///< 255, 255, 255 #define ILI9341_GREEN 0x0FE0 ///< 0, 255, 0 String oldData[8] = {"2020-03-08", "04:12:36", "08.45 C", "1010.67", "50.21%", "1.00", "18.45 C", "4.67 C"}; String newData[8] = {"2020-03-07", "14:11:46", "13.43 C", "1009.56", "40.45%", "0.00", "15.67 C", "3.23 C"}; int xPos[8] = {75, 75, 75, 120, 120, 120, 120, 120}; int yPos[8] = {87, 117, 147, 177, 207, 237, 267, 297}; void setup() { // put your setup code here, to run once: pinMode(11, INPUT); pinMode(12, INPUT); pinMode(13, INPUT); // intialise SD reader Serial.begin(9600); if(!SD.begin(10)){ Serial.println("SD card not initialised"); while(1); } tft.reset(); tft.begin(0x9341); tft.setRotation(0); tft.setTextSize(2); // set up the screen template tft.fillScreen(ILI9341_BLACK); yield(); tft.setCursor(0, 0); tft.setTextColor(ILI9341_DARKCYAN); tft.println("Pugwash Programming!"); tft.drawRect(60, 35, 120, 30, ILI9341_YELLOW); tft.setTextColor(ILI9341_WHITE); tft.setCursor(10, 87); tft.println("DATE: "); tft.setCursor(10, 117); tft.println("TIME: "); tft.setCursor(10, 147); tft.println("TEMP: "); tft.setCursor(10, 177); tft.println("PRESSURE: "); tft.setCursor(10, 207); tft.println("HUMIDITY: "); tft.setCursor(10, 237); tft.println("UV-INDEX: "); tft.setCursor(10, 267); tft.println("MAX TEMP: "); tft.setCursor(10, 297); tft.println("MIN TEMP: "); } void loop(void) { changeTitle(80, 92, 42, 42, "BALCONY", "ATTIC"); for(int i = 0; i < 8; i++){ changeDataValue(xPos[i], yPos[i], oldData[i], newData[i]); } delay(5000); changeTitle(92, 80, 42, 42, "ATTIC", "BALCONY"); for(int i = 0; i < 8; i++){ changeDataValue(xPos[i], yPos[i], newData[i], oldData[i]); } delay(5000); } void changeDataValue(int x1, int y1, String oldString, String newString){ tft.setTextColor(ILI9341_BLACK); tft.setCursor(x1, y1); tft.println(oldString); tft.setTextColor(ILI9341_GREEN); tft.setCursor(x1, y1); tft.println(newString); yield(); } void changeTitle(int x1, int x2, int y1, int y2, String oldString, String newString){ tft.setTextColor(ILI9341_BLACK); tft.setCursor(x1, y1); tft.println(oldString); tft.setTextColor(ILI9341_YELLOW); tft.setCursor(x2, y2); tft.println(newString); yield(); }