White screen with ILI9341 & SD data logger

Status
Not open for further replies.

Matadormac

Well-known member
White screen with ILI9341 & SD data logger - SOLVED

Hello. I have been struggling with this for most of this past week. I believe the issue is in the SPI coding I am using. I have tried to implement transactions, etc. I can implement SPI transactions when only working with the ILI9341 display or the SD datalogger sketches (from the Teensyduino installed examples) but when I combine the two I have problems and although the first loop iteration shows a black screen with two lines of text showing:
1. Just testing!...
2. Now, we loop!...

It then goes to a white screen on the tft. I have to physically remove the TFT from the female pin header holding it and then reseat it to "unfreeze" it. Only after "unfreezing" it can I successfully run the sketch "graphicstest" from the ILI9341_t3 example.

The serial output shows that the data logging is going on and the sketch is looping. Here is the first output with a few cycles of the data logging:

ILI9341 Test!
Display Power Mode: 0xDE
MADCTL Mode: 0x3C
Pixel Format: 0x7
Image Format: 0x0
Self Diagnostic: 0xE0
Initializing SD card...card initialized.
211,632,258
128,633,230
105,633,313
96,633,290
76,633,307

TFT connections are as per the recommendations on the PJRC page. SD connections are the same with the exception that its chip select is pin 20.

Thank you for all help and advice.

Here is the test sketch I am working with:
Code:
#include "SPI.h"
#include "ILI9341_t3.h"
#include <SD.h>

// For the Adafruit shield, these are the default.
#define TFT_DC  9
#define TFT_CS 10

const int chipSelect = 20;

// Use hardware SPI (on Uno, #13, #12, #11) and the above for CS/DC
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);

SPISettings tftSettings = SPISettings(30000000, MSBFIRST, SPI_MODE0);
//SPISettings tftSettings = SPISettings(25000000, MSBFIRST, SPI_MODE0);
SPISettings SD_Settings = SPISettings(25000000, MSBFIRST, SPI_MODE0);


void setup() {
  // put your setup code here, to run once:

  SPI.begin();
  // initalize the  data ready and chip select pins:
  pinMode(TFT_CS, OUTPUT);
  pinMode(chipSelect, OUTPUT);
  digitalWrite(chipSelect, HIGH);
  SPI.beginTransaction(tftSettings);
  digitalWrite(TFT_CS, LOW);
  //  digitalWrite(chipSelect, HIGH);
  //====================================================
  tft.begin();
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_YELLOW);
  tft.setTextSize(2);
  tft.setRotation(1);
  tft.println("Just testing!...");
  digitalWrite(10, HIGH);
  SPI.endTransaction();

  Serial.begin(9600);
  while (!Serial) ; // wait for Arduino Serial Monitor
  Serial.println("ILI9341 Test!");
  // read diagnostics (optional but can help debug problems)
  uint8_t x = tft.readcommand8(ILI9341_RDMODE);
  Serial.print("Display Power Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDMADCTL);
  Serial.print("MADCTL Mode: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDPIXFMT);
  Serial.print("Pixel Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDIMGFMT);
  Serial.print("Image Format: 0x"); Serial.println(x, HEX);
  x = tft.readcommand8(ILI9341_RDSELFDIAG);
  Serial.print("Self Diagnostic: 0x"); Serial.println(x, HEX);
  //=====================================================
  Serial.print("Initializing SD card...");
  SPI.beginTransaction(SD_Settings);
  digitalWrite(chipSelect, LOW);
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
    digitalWrite(chipSelect, HIGH);
    SPI.endTransaction();
  }
  Serial.println("card initialized.");
}

void loop() {
  // put your main code here, to run repeatedly:

  SPI.beginTransaction(tftSettings);
  digitalWrite(20, HIGH);
  digitalWrite(TFT_CS, LOW);
  tft.setCursor(0, 20);
  tft.println("Now, we loop!...");
  digitalWrite(10, HIGH);
  SPI.endTransaction();
  delay(1000);
  // make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ",";
    }
  }

  SPI.beginTransaction(SD_Settings);
  digitalWrite(10, HIGH);
  digitalWrite(chipSelect, LOW);
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    //    digitalWrite(chipSelect, HIGH);
    //    SPI.endTransaction();
    // print to the serial port too:
    Serial.println(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
  digitalWrite(chipSelect, HIGH);
  SPI.endTransaction();
  //=========================================================
  SPI.beginTransaction(tftSettings);
  digitalWrite(20, HIGH);
  digitalWrite(TFT_CS, LOW);
  tft.setCursor(0, 30);
  tft.println(dataString);
  digitalWrite(10, HIGH);
  SPI.endTransaction();
  delay(1000);

}
 
Last edited:
Sorry I don't have time to do a complete look over and maybe run.

But some things jump out at me as some things to look at:

In Setup you have a digitalWrite (10, HIGH) followed by SPI.endTransaction?

In between your beginTransaction and I assume this endTransaction, you have the TFT.begin, which will put the pins it want's into appropriate state. In this case SPI mode (pins in MODE 3), which your digitalWrite might clobber back to Mode1...

You should never touch Pin 10 as it is in control by the ILI9341_t3 library. So again in Loop, you muck with it.

Also in setup, if SD.begin fails, you have a return statement followed by lines that do things like SPI.endTransaction, which will never be called.

Also as such if the SD.begin succeeds, you don't deselect your chipselect nor endTransaction.

Got to run. Hope that helps

Kurt
 
Thank you Kurt. Took your advice, also went and did further looking in the SD_Fat and ILI9341 libraries to see what and how the SPI transactions were being handled.

I went back to basics and stripped out all the SPI transaction scripting I had put in to the example above.

Still had trouble though and it came down to having the TFT refresh immediately following the data logging to the SD card. Once I moved the TFT refresh to BEFORE the SD card datalogging, everything began to work as it should.

Current project code is:
Code:
//This sketch works for saving/data logging date/time to SD card
//Real problem was SD card writing was taking too long and running over
//TFT calls.
//Solved by moving TFT refresh to BEFORE calling for logging of data to SD.

#include <SPI.h>
#include "ILI9341_t3.h"
#include <Wire.h>
#include <RTClib.h>
#include <Adafruit_BME280.h>
#include "Adafruit_TSL2591.h"
#include <Timer.h>
#include "font_Arial.h"
//#include "font_TimesNewRoman.h"
#include <TimeLib.h>
#include <SdFat.h>

//==========================================
#define TFT_DC  9
#define TFT_CS 10
const uint8_t chipSelect = 20;
//==========================================
ILI9341_t3 tft = ILI9341_t3(TFT_CS, TFT_DC);
//==========================================
#define FILE_BASE_NAME "Data"
// File system object.
SdFat sd;

// Log file.
SdFile file;
// Error messages stored in flash.
#define error(msg) sd.errorHalt(F(msg))
//================================================================
RTC_DS1307 rtc;
char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
//=============================================
// Variables
Timer t;
float h = 0;
float tC = 0;
float tF = 0;
float ftcandle;
float uvAmount;
//float uvOrigin;
float luxReal;
float infraredReal;
float irReal;
float luxVal;
int i;
float outputVoltage;
float uvIntensity;
long int theYear;
long int theMonth;
long int theDay;
long int theHour;
long int theMinute;
long int theSecond;
String nameOfFile;
long sampleRate;
float sampleRateSeconds;
float sampleRateMinutes;
float sampleRateHours;
float luxHrs;
float luxHrsTotal;
float irHrs;
float irHrsTotal;
float uvHrs;
float uvHrsTotal;
float inP;
float hpaP;
int betweenReadings;

//================================================



void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  while (!Serial && (millis() <= 1000));
  delay(100);
  pinMode(TFT_CS, OUTPUT);
  digitalWrite(TFT_CS, HIGH);
  pinMode(chipSelect, OUTPUT);
  digitalWrite(chipSelect, HIGH);
  Serial.println("This sketch works for saving/data logging date/time to SD card");
  Serial.println("Now working on TFT with SD.");
  Serial.println("______________________________________________");
  //=================================================
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  if (! rtc.isrunning()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
  }
  delay(1000);
  //=================================================
  betweenReadings = 3000;
  t.every(betweenReadings, takeReadings);
  delay(100);
  Wire.begin();
  delay(100);
  //================================================
  const uint8_t BASE_NAME_SIZE = sizeof(FILE_BASE_NAME) - 1;
  char fileName[13] = FILE_BASE_NAME "00.csv";
  delay(100);
  // Initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  if (!sd.begin(chipSelect, SPI_FULL_SPEED)) {
    Serial.println(F("SD card initilization failed!"));
  } else {
    Serial.println(F("SD card initilization done."));
  }
  SPI.begin();
  delay(100);
  //==========================================
  // Find an unused file name.
  if (BASE_NAME_SIZE > 6) {
    error("FILE_BASE_NAME too long");
  }
  while (sd.exists(fileName)) {
    if (fileName[BASE_NAME_SIZE + 1] != '9') {
      fileName[BASE_NAME_SIZE + 1]++;
    } else if (fileName[BASE_NAME_SIZE] != '9') {
      fileName[BASE_NAME_SIZE + 1] = '0';
      fileName[BASE_NAME_SIZE]++;
    } else {
      error("Can't create file name");
    }
  }
  if (!file.open(fileName, O_CREAT | O_WRITE | O_EXCL)) {
    error("file.open");
  }
  do {
    delay(100);
  } while (Serial.read() >= 0);
  Serial.print(F("Logging to: "));
  Serial.println(fileName);
  nameOfFile = (fileName);
  // Write data header.
  writeHeader();
  delay(100);
  //=============================================
  digitalWrite(chipSelect, HIGH);
  digitalWrite(TFT_CS, LOW);
  tft.begin();
  delay(100);
  tft.fillScreen(ILI9341_BLACK);
  tft.setTextColor(ILI9341_YELLOW);
  tft.setTextSize(2);
  tft.setRotation(1);
  tft.println("Now working on adding TFT...");
  Serial.println("Working on adding TFT");
  tft.setCursor(0,20);
  tft.println("Added SD pin set LOW");
  PrintFileName();
  delay(5000);
  //===============================================
}

void loop() {
  // put your main code here, to run repeatedly:
  t.update();
}


View attachment b_Readings.inoView attachment a_SD_Card.inoView attachment c_Clock.inoView attachment d_RefreshData.ino
 
Status
Not open for further replies.
Back
Top