Page 1 of 1

1.8TFT SPI 128x160 module SD-card and Display will not work together

Posted: Sun Apr 19, 2020 9:08 am
by ilioss
Hello,
In my project logging data from BME-280 and DS18B20 I found problems with the SD card and the TFT display.
ESP32 wroom32 dev.kit v1 DOIT wonderfull.
BME-280 and DS18B20 sensors.
Combined SD and TFT module 1.8 TFT SPI 128x160 with Async webserver,OTA,SPIFFS
The display works fine with OliKraus library Ucglib on Ucglib_ST7735_18x128x160 ( test )
The whole build together will give a malfunction on the SD card??? :roll:
Both SW_SPI and HW_SPI Oli Kraus GrapicsTest.ino works fine.
HW_SPI cd=4 , cs=15 , rst=12 note: only display
SW_SPI sclk=18 , data=23 , cd=4 , cs=15 , rst=12 note: only display

Combine test SD and Display
HW_SPI same pin as above used SD write and read works display came on delayed for 10 sec??
SW_SPI same ….. SD write and read works display will not work stay blank???????
rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371
ets Jun 8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:8896
load:0x40080400,len:5816
entry 0x400806ac
SD Card Type: SDHC
SD Card Size: 3829MB
Listing directory: /
DIR : /System Volume Information
FILE: /-.CSV SIZE: 2233
FILE: /test.txt SIZE: 1048576
FILE: /foo.txt SIZE: 13
Creating Dir: /mydir
Dir created
Listing directory: /
DIR : /System Volume Information
FILE: /-.CSV SIZE: 2233
FILE: /test.txt SIZE: 1048576
FILE: /foo.txt SIZE: 13
DIR : /mydir
Removing Dir: /mydir
Dir removed
Listing directory: /
DIR : /System Volume Information
Listing directory: /System Volume Information
FILE: /System Volume Information/WPSettings.dat SIZE: 12
FILE: /System Volume Information/IndexerVolumeGuid SIZE: 76
FILE: /-.CSV SIZE: 2233
FILE: /test.txt SIZE: 1048576
FILE: /foo.txt SIZE: 13
Writing file: /hello.txt
File written
Appending to file: /hello.txt
Message appended
Reading file: /hello.txt
Read from file: Hello World!
Deleting file: /foo.txt
File deleted
Renaming file /hello.txt to /foo.txt
File renamed
Reading file: /foo.txt
Read from file: Hello World!
1048576 bytes read for 3009 ms
1048576 bytes written for 5634 ms
Total space: 3821MB
Used space: 1MB

In my program I used the HW_SPI for SD and display will not work together.
[code// ****************** AsyncWebserver ******************
#include <AsyncEventSource.h>
#include <ESPAsyncWebServer.h>
#include <AsyncTCP.h>

// *************** DALLAS temp. *****************
#include <OneWire.h>
#include <DallasTemperature.h>

//***** WIFI *************
#include <WiFi.h>
#include <WiFiUdp.h> // nodig voor de tijd NTP

//***** OTA *************
#include <ArduinoOTA.h> // Over the air programming

//****** SPIFFS *******
#include <SPIFFS.h> // SPIFFS file flashen

//*********ESPmDNS **********
#include <ESPmDNS.h>

//************* FS ****************
#include <FS.h>
#include <FSImpl.h>
#include <vfs_api.h>

//*********** DISPLAY ************************
#include "Ucglib.h"
Ucglib_ST7735_18x128x160_HWSPI ucg(/*cd=*/ 4, /*cs=*/ 15, /*reset=*/ 12);
//Ucglib_ST7735_18x128x160_SWSPI ucg(/*sclk=*/ 18, /*data=*/ 23, /*cd=*/ 4, /*cs=*/ 15, /*reset=*/ 12);
// ***** SD ****************
#include <SD.h>
#include <sd_defines.h>
#include <sd_diskio.h>
#include <SPI.h>
#define CS_PIN 2 // chipselect pin gedefinieerd SD card
File dataFile;
File filename;

//***** TIME *****
#include <time.h>
long timezone = 1;
byte daysavetime = 1;

//*********** DALLAS temp. *************
#define TEMP_SENSOR_PIN 5
OneWire oneWire(TEMP_SENSOR_PIN); // Set up a OneWire instance to communicate with OneWire devices
DallasTemperature sensors(&oneWire); // Create an instance of the temperature sensor class

//*************** BME280*************************
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C SDA=21 en SCL=22

//********* OTA *************
const char *OTAName = "ESP8266"; // A name and a password for the OTA service
const char *OTAPassword = "esp8266";
const char* mdnsName = "esp8266"; // Domain name for the mDNS responder

const char* ssid = "mmmmm"; // Replace with your network credentials
const char* password = "nnnnn";

const int ledPin = 13; // Set LED GPIO13
String ledState; // Stores LED state

String yy;
String mm;
String dd;
String hr;
String mi;
String se;

String dataMessage; // met gegevens om te loggen
String headerMessage; // file header met colom gegevens datum, tijd, tempbi,hum,press,tempbu
String tempbi; // van BME
String humidity; // van BME
String pressure; // van BME
String tempbu;
String temperature;

//************** FS ***********************
File fsUploadFile; // a File variable to temporarily store the received file

//************* WIFI server *******************

AsyncWebServer server(80);

// ********************* BME-280 *********************************
String getTemperature() { // Variable to store the HTTP request String header;
float temperature = bme.readTemperature();
Serial.println(temperature);
return String(temperature);
}

String getHumidity() {
float humidity = bme.readHumidity();
Serial.println(humidity);
return String(humidity);
}

String getPressure() {
float pressure = bme.readPressure()/ 100.0F;
Serial.println(pressure);
return String(pressure);
}

//********************** DS18B20 *************************************************
String readDSTemperatureC() { // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
sensors.requestTemperatures();
float tempbu = sensors.getTempCByIndex(0);
Serial.println(tempbu);
return String(tempbu);
}

//************************** LED etc.*******************************************
String processor(const String& var){ // Replaces placeholder with LED state value
Serial.println(var);
if(var == "STATE"){ // var in index.html page (id)
if(digitalRead(ledPin)){
ledState = "ON";
}
else{
ledState = "OFF";
}
Serial.print(ledState);
return ledState;
}
else if (var == "TEMPERATURE"){ // var in index.html page (id)
return getTemperature(); // BME-280 temperature binnen
}
else if (var == "HUMIDITY"){ // var in index.html page (id)
return getHumidity();
}
else if (var == "PRESSURE"){ // var in index.html page (id)
return getPressure();
}
else if (var == "TEMPBU"){ // var in index.html page (id)
return readDSTemperatureC(); // DS18B20 buiten
}
}

//**************** SET-UP *******************
void setup(){
Serial.begin(115200);
pinMode(ledPin, OUTPUT); // bool status;
pinMode(2, OUTPUT);

SPI.begin();
sensors.begin(); // Start up the DS18B20 library
bme.begin();
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}

startSD();
startWIFI();

ucg.begin(UCG_FONT_MODE_TRANSPARENT); // maakt achtergrond
ucg.setColor(0, 120, 0, 0);
ucg.setColor(2, 0, 120, 0);
ucg.setColor(1, 120, 0, 120);
ucg.setColor(3, 0, 120, 120);
ucg.drawGradientBox(0, 0, ucg.getWidth(), ucg.getHeight());

ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";

// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});

ArduinoOTA.begin();

if(!SPIFFS.begin()){ // Initialize SPIFFS
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}

server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){ // Route for root / web page
request->send(SPIFFS, "/index.html", String(), false, processor);
});

server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){ // was /favicon.ico
request->send(SPIFFS, "/favicon.png", "image/png");
});

server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){ // Route to load style.css file
request->send(SPIFFS, "/style.css", "text/css");
});

server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){ // Route to set GPIO to HIGH
digitalWrite(ledPin, HIGH);
request->send(SPIFFS, "/index.html", String(), false, processor);
});

server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){ // Route to set GPIO to LOW
digitalWrite(ledPin, LOW);
request->send(SPIFFS, "/index.html", String(), false, processor);
});

server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){ // Route to the BME Temperature
request->send_P(200, "text/plain", getTemperature().c_str());
});

server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){ // Route to the BME Humidity
request->send_P(200, "text/plain", getHumidity().c_str());
});

server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){ // Route to the BME Pressure
request->send_P(200, "text/plain", getPressure().c_str());
});

server.on("/tempbu", HTTP_GET, [](AsyncWebServerRequest *request){ // Route to the DS18B20 Temperature
request->send_P(200, "text/plain", readDSTemperatureC().c_str());
});
server.begin(); // Start server
}


//******************* LOOP *********************
void loop(){
ArduinoOTA.handle();
startTIME();
getReadings();
getBME();
useDisplay();
logSDCard();
}

//*************** VOIDS ***************


void startSD() {
SD.begin(2);
Serial.print("Initializing SD card...");
if (!SD.begin(2))
{
Serial.println("Card failed, or not present"); // see if the card is present and can be initialized:
while (1) ; // don't do anything more: nu mag door ook als er geen kaart is
}
Serial.println("card initialized.");
delay(10);
Serial.println("\r\n");
}

void startWIFI() {
WiFi.begin(ssid, password); // Connect to Wi-Fi
WiFi.mode(WIFI_STA);
while (WiFi.status() != WL_CONNECTED) {
delay(100); // was 1000
Serial.println("Connecting to WiFi..");
}

Serial.println(WiFi.localIP()); // Print ESP32 Local IP Address
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void getReadings(){ // Function to get DS18B20 temperature
sensors.requestTemperatures();
tempbu = sensors.getTempCByIndex(0); // Temperature in Celsius
}

void getBME() { // BME-280 readings
tempbi = bme.readTemperature();
humidity = bme.readHumidity();
pressure = bme.readPressure()/ 100.0F;
}

void logSDCard() {
String path = "/" + mm + "-" + dd + ".csv";
headerMessage = "Tijd, Tempbu, \n";
dataMessage = String(dd) + String(tempbu)+"\r\n";
File file = SD.open(path.c_str());
if(!file) {
Serial.println("File doens't exist");
Serial.println("Creating file...");
writeFile(SD, path.c_str(), headerMessage.c_str());
}
else {
Serial.println("File already exists");
}
file.close();

if (dd != dd) { // nieuwe dag
writeFile(SD, path.c_str(), headerMessage.c_str());
}
else {
appendFile(SD, path.c_str(), dataMessage.c_str());
}
}


void useDisplay(){
float tempbu = sensors.getTempCByIndex(0);
delay(20);
ucg_int_t y = 0;
ucg_int_t h = 14;
ucg.setRotate270();

y += h;
ucg.setFontMode(UCG_FONT_MODE_TRANSPARENT);
ucg.setPrintPos(4,y);
ucg.setFont(ucg_font_helvB08_tr);
ucg.print("Pressure:");
ucg.setFontMode(UCG_FONT_MODE_SOLID);
ucg.setFont(ucg_font_7x13_mr);
ucg.setColor(0, 255, 255, 255); // use white as main color for the font
ucg.setColor(1, 64, 64, 255); // use blue as background for SOLID mode
ucg.setPrintPos(80,y);
ucg.print(pressure);

y += h;
ucg.setFontMode(UCG_FONT_MODE_TRANSPARENT);
ucg.setPrintPos(4,y);
ucg.setFont(ucg_font_helvB08_tr);
ucg.print("Humidity:");
ucg.setFontMode(UCG_FONT_MODE_SOLID);
ucg.setFont(ucg_font_helvB08_tr);
ucg.setColor(0, 255, 255, 255); // use white as main color for the font
ucg.setColor(1, 64, 64, 255); // use blue as background for SOLID mode
ucg.setPrintPos(80,y);
ucg.print(humidity);

y += h;
ucg.setFontMode(UCG_FONT_MODE_TRANSPARENT);
ucg.setPrintPos(4,y);
ucg.setFont(ucg_font_helvB08_tr);
ucg.print("Temperature:");
ucg.setFontMode(UCG_FONT_MODE_SOLID);
ucg.setFont(ucg_font_helvB08_tr);
ucg.setColor(0, 255, 255, 255); // use white as main color for the font
ucg.setColor(1, 64, 64, 255); // use blue as background for SOLID mode
ucg.setPrintPos(80,y);
ucg.print(tempbi);


y += h;
ucg.setFontMode(UCG_FONT_MODE_TRANSPARENT);
ucg.setPrintPos(4,y);
ucg.setFont(ucg_font_helvB08_tr);
ucg.print("Temp. buiten:");
if (tempbu <= 20 ) {
ucg.setColor(0, 255, 40, 80);
ucg.setColor(1, 0, 255, 0);
ucg.setColor(2, 255, 0, 0);
ucg.setColor(3, 65, 255, 40);// 3,65,255,40
ucg.drawGradientBox(80-2, y-10, 40, 12);// red to green bar will erase the previous value
} else if(tempbu >20) {
ucg.setColor(3, 255, 40, 80);// 3,255,40,80
ucg.setColor(2, 0, 255, 0);
ucg.setColor(1, 255, 0, 0);
ucg.setColor(0, 65, 255, 40);
ucg.drawGradientBox(80-2, y-10, 40, 12);
}
ucg.setFontMode(UCG_FONT_MODE_TRANSPARENT);
ucg.setFont(ucg_font_7x13_mr);
ucg.setColor(0, 255, 255, 255); // use white as main color for the font
ucg.setPrintPos(80,y);
ucg.print(tempbu);

y += h;
ucg.setFontMode(UCG_FONT_MODE_TRANSPARENT);
ucg.setPrintPos(4,y);
ucg.setFont(ucg_font_helvB08_tr);
ucg.print("Status LED:");
if (digitalRead(ledPin )) {
ucg.setColor(3, 255, 40, 80);
ucg.setColor(2, 0, 255, 0);
ucg.setColor(1, 255, 0, 0);
ucg.setColor(0, 65, 255, 40);
ucg.drawGradientBox(80-2, y-10, 40, 12); // red to green bar will erase the previous value
ucg.setFontMode(UCG_FONT_MODE_TRANSPARENT);
ucg.setFont(ucg_font_7x13_mr);
ucg.setColor(0, 255, 255, 255); // use white as main color for the font
ucg.setPrintPos(80,y);
ucg.print("ON");
} else {
ucg.setColor(0, 255, 40, 80);
ucg.setColor(1, 0, 255, 0);
ucg.setColor(2, 255, 0, 0);
ucg.setColor(3, 65, 255, 40);
ucg.drawGradientBox(80-2, y-10, 40, 12);

ucg.setFontMode(UCG_FONT_MODE_TRANSPARENT);
ucg.setFont(ucg_font_7x13_mr);
ucg.setColor(0, 255, 255, 255); // use white as main color for the font
ucg.setPrintPos(100,y);
ucg.print("OFF");

}
}

void startmDNS() {
// Set up mDNS responder:
// - first argument is the domain name, in this example
// the fully-qualified domain name is "esp8266.local"
// - second argument is the IP address to advertise
// we send our IP address on the WiFi network
if (!MDNS.begin("esp32")) {
Serial.println("Error setting up MDNS responder!");
while(1) {
delay(100);
}
}
Serial.println("mDNS responder started");
server.begin(); // Start TCP (HTTP) server
Serial.println("TCP server started");
MDNS.addService("http", "tcp", 80); // Add service to MDNS-SD
}

void appendFile(fs::FS &fs, const char * path, const char * message) { // Append data to the SD card (DON'T MODIFY THIS FUNCTION)
Serial.println("");
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file) {
Serial.println("Failed to open file for appending");
return;
}
if(file.print(message)) {
Serial.println("Message");
Serial.print(dataMessage.c_str());
Serial.println("Appended");
} else {
Serial.println("Append failed");
}
file.close();
}

void writeFile(fs::FS &fs, const char * path, const char * message) { // Write to the SD card (DON'T MODIFY THIS FUNCTION)
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file) {
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)) {
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}

void startTIME() {
Serial.println("Contacting Time Server");
configTime(3600*timezone, daysavetime*3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
struct tm tmstruct ;
delay(100);
hr = (tmstruct.tm_hour);
mi = (tmstruct.tm_min);
se = (tmstruct.tm_sec);
tmstruct.tm_year = 0;
getLocalTime(&tmstruct, 5000);
Serial.printf("\nNow is : %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct.tm_year)+1900,( tmstruct.tm_mon)+1, tmstruct.tm_mday,tmstruct.tm_hour , tmstruct.tm_min, tmstruct.tm_sec);
Serial.println("");

int yy = (tmstruct.tm_year)+1900;
String year;
year=String(yy);
Serial.println(year);
int mm = (tmstruct.tm_mon)+1;
String month;
month=String(mm);
Serial.println(month);
int dd = (tmstruct.tm_mday);
String day;
day=String(dd);
Serial.println(day);
}


//********* HELPER FUNCTIES **************************************
String formatBytes(size_t bytes) { // convert sizes in bytes to KB and MB
if (bytes < 1024) {
return String(bytes) + "B";
} else if (bytes < (1024 * 1024)) {
return String(bytes / 1024.0) + "KB";
} else if (bytes < (1024 * 1024 * 1024)) {
return String(bytes / 1024.0 / 1024.0) + "MB";
}
}

String getContentType(String filename) { // determine the filetype of a given filename, based on the extension
if (filename.endsWith(".html")) return "text/html";
else if (filename.endsWith(".css")) return "text/css";
else if (filename.endsWith(".js")) return "application/javascript";
else if (filename.endsWith(".ico")) return "image/x-icon";
else if (filename.endsWith(".gz")) return "application/x-gzip";
return "text/plain";
}][/code]

I already looked into the postings related to SD problems withgout any luck s.a SdFat from Greig.
Any help on this issue is more than welcome.
Like to hear,
ilioSS

Re: 1.8TFT SPI 128x160 module SD-card and Display will not work together

Posted: Sat Apr 25, 2020 8:46 am
by ilioss
Hi all,

After some time to spent to solve this problem I found the solution in using he library from adafruit.
I found this in the Rui Santos TFT tutorial.
In fact I do not know why it didn,t work with the former libraries. :?
But at last I have a working project to read display and log the weather readings.

For me this issue is closed.

Regards,
ilioSS
Appending to file: /4-25.csv
Message
10:37:31,22.25,39.12,1016.02,20.50
Appended

Code: Select all

// ***************  AsyncWebserver *******************
#include <AsyncEventSource.h>
#include <ESPAsyncWebServer.h>
#include <AsyncTCP.h>
 
// ***************  DALLAS temp. *********************
#include <OneWire.h>
#include <DallasTemperature.h>

//****************  WIFI *****************************
#include <WiFi.h>
#include <WiFiUdp.h>                    // nodig voor de tijd NTP

//****************  OTA ******************************
#include <ArduinoOTA.h>                 // Over the air programming

//**************** SPIFFS ****************************
#include <SPIFFS.h>                     // SPIFFS file flashen

//**************** ESPmDNS  **************************
#include <ESPmDNS.h>

//**************** FS  *******************************
#include <FS.h>
#include <FSImpl.h>
#include <vfs_api.h>


#include <Adafruit_GFX.h>    // Core graphics library
#include <Adafruit_ST7735.h> // Hardware-specific library for ST7735
#define TFT_CS        15
#define TFT_RST        12    // Or set to -1 and connect to Arduino RESET pin
#define TFT_DC         4

 Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST);

// *************** SD   ******************************
#include <SD.h>
#include <sd_defines.h>
#include <sd_diskio.h>
#include <SPI.h>
#define CS_PIN 2                        // chipselect pin gedefinieerd SD card


//**************** TIME ******************************
#include <time.h>
long timezone = 1; 
byte daysavetime = 1;

//**************** DALLAS temp. **********************
#define TEMP_SENSOR_PIN 5
OneWire oneWire(TEMP_SENSOR_PIN);       // Set up a OneWire instance to communicate with OneWire devices
DallasTemperature sensors(&oneWire);    // Create an instance of the temperature sensor class

//**************** BME280 ****************************
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme;                    // I2C  SDA=21 en SCL=22

//**************** OTA *******************************
const char *OTAName = "ESP8266";        // A name and a password for the OTA service
const char *OTAPassword = "esp8266";
const char* mdnsName = "esp8266";       // Domain name for the mDNS responder

const char* ssid     = "nnnnn";    // Replace with your network credentials
const char* password = "bbbbbbb";

const int ledPin = 13;                  // Set LED GPIO13  
String ledState;                        // Stores LED state

String yy;
String year;
String mm;
String month;
String dd;
String day;
String hr;
String mi;
String se;

String dataMessage;                     // met gegevens om te loggen
String headerMessage;                   // file header met colom gegevens datum, tijd, tempbi,hum,press,tempbu
String tempbi;                          // van BME
String humidity;                        // van BME
String pressure;                        // van BME
String tempbu;    
String temperature;

//**************** FS ********************************
File fsUploadFile;                      // a File variable to temporarily store the received file

//**************** WIFI server ***********************

AsyncWebServer server(80);

// *************** BME-280 ***************************
String getTemperature() {               // Variable to store the HTTP request String header;
  float temperature = bme.readTemperature(); 
  Serial.println(temperature);
  return String(temperature);
}
  
String getHumidity() {
  float humidity = bme.readHumidity();
  Serial.println(humidity);
  return String(humidity);
}

String getPressure() {
  float pressure = bme.readPressure()/ 100.0F;
  Serial.println(pressure);
  return String(pressure);
}

//**************** DS18B20 ***************************
String readDSTemperatureC() {           // Call sensors.requestTemperatures() to issue a global temperature and Requests to all devices on the bus
  sensors.requestTemperatures(); 
  delay(20);
 float  tempbu = sensors.getTempCByIndex(0); 
 delay(20);
  Serial.println(tempbu);
  return String(tempbu);
}

//**************** LED  etc.**************************
String processor(const String& var){   // Replaces placeholder with LED state value
  Serial.println(var);
  if(var == "STATE"){                  // var in index.html page (id)
    if(digitalRead(ledPin)){
      ledState = "ON";
    }
    else{
      ledState = "OFF";
    }
    Serial.print(ledState);
    return ledState;
  }
  else if (var == "TEMPERATURE"){     // var in index.html page (id)
    return getTemperature();          // BME-280 temperature binnen
  }
  else if (var == "HUMIDITY"){        // var in index.html page (id)
    return getHumidity();
  }
  else if (var == "PRESSURE"){        // var in index.html page (id)
    return getPressure();
  } 
  else if (var == "TEMPBU"){          // var in index.html page (id)
    return readDSTemperatureC();      // DS18B20 buiten
  }
}

//**************** SET-UP ****************************
 void setup(){
 Serial.begin(115200);
 pinMode(ledPin, OUTPUT);             //  bool status;
 pinMode(2, OUTPUT);
 SPI.begin();
 sensors.begin();                     // Start up the DS18B20 library
 bme.begin();  
   if (!bme.begin(0x76)) {
     Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
 initSD();
 startWIFI();
 initTFT();
// startTIME();
 startOTA();


  if(!SPIFFS.begin()){                                                    // Initialize SPIFFS
    Serial.println("An Error has occurred while mounting SPIFFS");
    return;
  }

  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){            // Route for root / web page
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });
  
  server.on("/favicon.ico", HTTP_GET, [](AsyncWebServerRequest *request){ //  was    /favicon.ico
    request->send(SPIFFS, "/favicon.png", "image/png");
  }); 
  
  server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request){   // Route to load style.css file
    request->send(SPIFFS, "/style.css", "text/css");
  });
 
  server.on("/on", HTTP_GET, [](AsyncWebServerRequest *request){          // Route to set GPIO to HIGH
    digitalWrite(ledPin, HIGH);    
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });
 
  server.on("/off", HTTP_GET, [](AsyncWebServerRequest *request){          // Route to set GPIO to LOW
    digitalWrite(ledPin, LOW);    
    request->send(SPIFFS, "/index.html", String(), false, processor);
  });

  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){  // Route to the BME Temperature
    request->send_P(200, "text/plain", getTemperature().c_str());
  });
  
  server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){     // Route to the BME Humidity
    request->send_P(200, "text/plain", getHumidity().c_str());
  });
  
  server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){     // Route to the BME Pressure
    request->send_P(200, "text/plain", getPressure().c_str());
  });
 
  server.on("/tempbu", HTTP_GET, [](AsyncWebServerRequest *request){       // Route to the DS18B20 Temperature
    request->send_P(200, "text/plain", readDSTemperatureC().c_str());
   });
  server.begin();                                                          // Start server
  }
 

//****************  LOOP  ****************************
void loop(){
 ArduinoOTA.handle();

 

     Serial.println("Contacting Time Server");
  configTime(3600*timezone, daysavetime*3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
  struct tm tmstruct ;
    delay(2000);
      yy = (tmstruct.tm_year)+1900;
      mm = ( tmstruct.tm_mon)+1;
      dd = tmstruct.tm_mday;
      hr = (tmstruct.tm_hour);
      mi = (tmstruct.tm_min);
      se = (tmstruct.tm_sec); 
  int yy = (tmstruct.tm_year)+1900;
  String year;
  year=String(yy);
  Serial.println(year); 
  int mm = (tmstruct.tm_mon)+1;
  String month;
  month=String(mm);
  Serial.println(month);
  int dd = (tmstruct.tm_mday);
  String day;
  day=String(dd);
  Serial.println(day);
      
    
    tmstruct.tm_year = 0;
    getLocalTime(&tmstruct, 5000);
    Serial.printf("\nNow is : %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct.tm_year)+1900,( tmstruct.tm_mon)+1, tmstruct.tm_mday,tmstruct.tm_hour , tmstruct.tm_min, tmstruct.tm_sec);
    Serial.println("");
    
    String path = "/" + month + "-" + day + ".csv";  // format maand dag 
    headerMessage = "Tijd, temperature,humidity,pressure,tempbu \n";              // tijd,temperature, humidity, pressure, tempbu
    dataMessage = String(hr) + ":" + String(mi) + ":" + String(se) + "," + String(temperature) + "," + String(humidity) + "," + String(pressure) + "," + String(tempbu)+ "\r\n";  // uur:minuut:sec,temperature, humidity, pressure, tempbu
    File file = SD.open(path.c_str());
     if(!file) {
     Serial.println("File doens't exist");
     Serial.println("Creating file...");
     writeFile(SD, path.c_str(), headerMessage.c_str());
    }
    else {
    Serial.println("File already exists");  
    }
    file.close();
  
    if (dd != dd) {                // nieuwe dag
     writeFile(SD, path.c_str(), headerMessage.c_str());
    }
    else {          
      appendFile(SD, path.c_str(), dataMessage.c_str());// SD
      }

 getReadings();
 getBME();
 displayText();


  
 delay(1000);
}

//**************** VOIDS *****************************
/*
void startTIME() {
      Serial.println("Contacting Time Server");
      configTime(3600*timezone, daysavetime*3600, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
      struct tm tmstruct ;
      delay(100);
      yy = (tmstruct.tm_year)+1900;
      mm = ( tmstruct.tm_mon)+1;
      dd = (tmstruct.tm_mday);
      hr = (tmstruct.tm_hour);
      mi = (tmstruct.tm_min);
      se = (tmstruct.tm_sec); 
      tmstruct.tm_year = 0;
      getLocalTime(&tmstruct, 5000);
      Serial.printf("\nNow is : %d-%02d-%02d %02d:%02d:%02d\n",(tmstruct.tm_year)+1900,( tmstruct.tm_mon)+1, tmstruct.tm_mday,tmstruct.tm_hour , tmstruct.tm_min, tmstruct.tm_sec);
      Serial.println("");

  int yy = (tmstruct.tm_year)+1900;
  String year;
  year=String(yy, DEC);
  Serial.println(year);
  Serial.println(yy); 
  int mm = (tmstruct.tm_mon)+1;
  String month;
  month=String(mm);
  Serial.println(month);
  Serial.println(mm);
  int dd = (tmstruct.tm_mday);
  String day;
  day=String(dd, DEC);
  Serial.println(day);
  Serial.println(dd);
 }
*/
 void startOTA(){
ArduinoOTA
    .onStart([]() {
      String type;
      if (ArduinoOTA.getCommand() == U_FLASH)
        type = "sketch";
      else                                // U_SPIFFS
        type = "filesystem";
      
      Serial.println("Start updating " + type);  // NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
    })
    .onEnd([]() {
      Serial.println("\nEnd");
    })
    .onProgress([](unsigned int progress, unsigned int total) {
      Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
    })
    .onError([](ota_error_t error) {
      Serial.printf("Error[%u]: ", error);
      if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
      else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
      else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
      else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
      else if (error == OTA_END_ERROR) Serial.println("End Failed");
    });

  ArduinoOTA.begin();

  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
 }

 void initTFT(){
   tft.initR(INITR_BLACKTAB);   // initialize a ST7735S chip, black tab
   tft.setTextWrap(false); // Allow text to run off right edge
   tft.fillScreen(ST77XX_BLACK);
}

void displayText() {
  
    tft.setRotation(-45);
    tft.fillScreen(ST77XX_BLACK);
    tft.setCursor(0, 0);
    tft.setTextColor(ST77XX_RED);
    tft.setTextSize(2);
    tft.print("Temp:");
    tft.setTextColor(ST77XX_YELLOW);
    tft.setTextSize(2);
    tft.println(temperature);
    tft.setTextColor(ST77XX_GREEN);
    tft.setTextSize(2);
    tft.print("Hum: ");
    tft.setTextColor(ST77XX_GREEN);
    tft.setTextSize(2);
    tft.println(humidity);
    tft.setTextColor(ST77XX_BLUE);
    tft.setTextSize(2);
    tft.print("Pres:");
    tft.setTextColor(ST77XX_BLUE);
    tft.println(pressure);
    tft.setCursor(0,90);
    tft.setTextColor(ST77XX_RED);
    tft.setTextSize(2);
    tft.print("Tempbu:");
    tft.setTextColor(ST77XX_YELLOW);
    tft.setTextSize(2);
    tft.println(tempbu);
    tft.setTextSize(1);
    tft.setTextColor(ST77XX_GREEN);
    tft.print(yy);
    tft.print(":");
    tft.print(mm);
    tft.print(":");
    tft.print(dd);
    tft.print("  ");
    tft.print(hr);
    tft.print("-");
    tft.print(mi);
    tft.print("-");
    tft.println(se);
}

void initSD() {
    SD.begin(2);
    Serial.print("Initializing SD card...");
    if (!SD.begin(2))
     {      
     Serial.println("Card failed, or not present");    // see if the card is present and can be initialized:
     while (1) ;                                       // don't do anything more:  nu mag door ook als er geen kaart is
     }
    Serial.println("card initialized.");
    delay(10);
    Serial.println("\r\n");
  }

void startWIFI() {
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);                         // Connect to Wi-Fi
    {
   while (WiFi.waitForConnectResult() != WL_CONNECTED) {  // while (WiFi.status() != WL_CONNECTED)
    delay(5000);  // was 1000
    Serial.println("Connecting to WiFi..");
   
  Serial.println(WiFi.localIP());                                         // Print ESP32 Local IP Address
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
   }
 }
}
void getReadings(){  // Function to get DS18B20 temperature
     sensors.requestTemperatures(); 
     delay(20);
     tempbu = sensors.getTempCByIndex(0);         // Temperature in Celsius
     delay(20);
  }
 
void getBME() {    // BME-280 readings
    temperature = bme.readTemperature(); 
    humidity = bme.readHumidity();
    pressure = bme.readPressure()/ 100.0F;
  }
/*
void logSDCard()  {
    String path = "/" +  mm + "-" +  dd + ".csv";
    headerMessage = "Tijd, Tempbu, \n";
    dataMessage = String(dd) + String(tempbu)+"\r\n";
    File file = SD.open(path.c_str());
     if(!file) {
     Serial.println("File doens't exist");
     Serial.println("Creating file...");
     writeFile(SD, path.c_str(), headerMessage.c_str());
    }
    else {
    Serial.println("File already exists");  
    }
    file.close();
  
    if (dd != dd) { // nieuwe dag
     writeFile(SD, path.c_str(), headerMessage.c_str());
    }
    else {          
      appendFile(SD, path.c_str(), dataMessage.c_str());// SD
      }
   }

*/
void startmDNS() {
    // Set up mDNS responder:
    // - first argument is the domain name, in this example
    //   the fully-qualified domain name is "esp8266.local"
    // - second argument is the IP address to advertise
    //   we send our IP address on the WiFi network
    if (!MDNS.begin("esp32")) {
        Serial.println("Error setting up MDNS responder!");
        while(1) {
            delay(100);
        }
    }
    Serial.println("mDNS responder started");
    server.begin();                          // Start TCP (HTTP) server
    Serial.println("TCP server started");
    MDNS.addService("http", "tcp", 80);     // Add service to MDNS-SD
}

void appendFile(fs::FS &fs, const char * path, const char * message) {  // Append data to the SD card (DON'T MODIFY THIS FUNCTION)
    Serial.println("");
    Serial.printf("Appending to file: %s\n", path);
    File file = fs.open(path, FILE_APPEND);
    if(!file) {
    Serial.println("Failed to open file for appending");
    return;
  }
    if(file.print(message)) {
    Serial.println("Message");
    Serial.print(dataMessage.c_str());
    Serial.println("Appended");
    } else {
     Serial.println("Append failed");
    }
    file.close();
  }

void writeFile(fs::FS &fs, const char * path, const char * message) {  // Write to the SD card (DON'T MODIFY THIS FUNCTION)
     Serial.printf("Writing file: %s\n", path);
     File file = fs.open(path, FILE_WRITE);
     if(!file) {
     Serial.println("Failed to open file for writing");
     return;
    }
     if(file.print(message)) {
     Serial.println("File written");
    } else {
     Serial.println("Write failed");
    }
     file.close();
  }




//********* HELPER FUNCTIES **************************************
String formatBytes(size_t bytes) {                 // convert sizes in bytes to KB and MB
  if (bytes < 1024) {
    return String(bytes) + "B";
  } else if (bytes < (1024 * 1024)) {
    return String(bytes / 1024.0) + "KB";
  } else if (bytes < (1024 * 1024 * 1024)) {
    return String(bytes / 1024.0 / 1024.0) + "MB";
  }
}

String getContentType(String filename) {            // determine the filetype of a given filename, based on the extension
  if (filename.endsWith(".html")) return "text/html";
  else if (filename.endsWith(".css")) return "text/css";
  else if (filename.endsWith(".js")) return "application/javascript";
  else if (filename.endsWith(".ico")) return "image/x-icon";
  else if (filename.endsWith(".gz")) return "application/x-gzip";
  return "text/plain";
}