Error while setting serial port parameters

Error while setting serial port parameters: 9,600 N 8 1
Error opening serial port 'COM14'. (Can't set mask)

I am getting this after I perform a software based reset on a AdaFruit Feather M4. I see the error and the IDE serial monitor is locked up and I cannot even close it. If I perform a power reset and then I regain control of the IDE and the serial monitor.

Post the actual error message.

If the baud rate contains a comma, that is a problem.

This is the actual error message:

Error while setting serial port parameters: 9,600 N 8 1
Error opening serial port 'COM14'. (Can't set mask)

In the program the baud rate is set with
Serial.begin(9600);
In the Serial Monitor the baud rate selected is 9600

I am not sure why the error message has the thousands formatting with the ,

"Can't set mask" suggests to me that the code tries to do something impossible.

Please post the complete Arduino code, using code tags.

Since that error message is produced by the PC operating system, why did you choose COM14? Is it actually assigned to the Arduino, when the USB cable is plugged in?

This is a rather large bit of code. The newest is a reset at 1AM. The reset is when my current issue started.

For this I added the function:
void(* resetFunc) (void) = 0; //declare reset function @ address 0
and in the loop is the bit of code

  if (GetTmloint == 1)
  {
    if (oldReset == 1)
    {
      Serial.print(GetTmloint);
      Serial.println(" Reset Hour **************************");         
      resetFunc();
    }    
  }

The full code below

/*Web client, WiFi, SD & RA8875

  This sketch connects to several websites api.openweathermap.org, local a local InfluxDB and also currently a MySQL DB via PHP
  using a WiFi shield and then displays the data on images from the flash chip.

  This example is written for a network using WPA encryption. For
  WEP or WPA, change the WiFi.begin() call accordingly.

  Circuit:
   Adafruit Feather M4 Express - Featuring ATSAMD51 - ATSAMD51 Cortex M4
     Product ID: 3857
   Adafruit AirLift FeatherWing – ESP32 WiFi Co-Processor 
     Product ID: 4264
   RA8875 Driver Board for 40-pin TFT Touch Displays - 800x480 Max
     PRODUCT ID: 1590
   7.0" 40-pin TFT Display - 800x480 with Touchscreen
     Product ID: 2354
   DS3231 Precision RTC FeatherWing - RTC Add-on For Feather Boards
     PRODUCT ID: 3028


2023-07-15 add restart time to serial monitor
2023-07-13 Hour is not advancing for reset
2023-07-12 adding daily resets
2023-05-04 Disabled waiting for serial connection
2022-05-21 possible fix for "unable to connect" discover with WiFi.disconnect(); and try again
2022-05-19 Getting occasional "unable to connect" errors trying to connect to server: api.openweathermap.org - Possible fix
2022-04-12 the 2020-03-14 Version touch worked and 2020-03-15 Version touch stopped working
2022-04-12 0xF7 looks to be the built in font degree symbol
2022-04-09 Touch Screen is not registering touches
2022-04-09 Sunrise/Sunset and Forcast are only updated every 10 minutes, 144 Times a day
2022-04-07 Forcast Temp03 & Temp04 have not been converted - Issue Fixed
2022-04-07 WindChill issue seems to be noticed when Wind Speed is 0? - issue Fixed
2022-04-01 WindChill was showing higher than actual temperature Added ( ) around elements
2022-03-27 Switching forcast Open Weather Maps OneCall API for Forecasts and posibly Sunrise,Sunset 
2022-03-14 changed php path from http://ip/php-demo/index1.php to http://ip/index1.php
2022-03-13 Changed color from Blue background Black squares to Dark Turquoise background & medium Turquoise Squares.
Also added Heat Index, Windchill and Dew point.  Also set RTC to UTC time so CST and CDT worked correctly
2022-03-06 Move the Temprature over if it is a 3 digit temperature
2022-03-03 through Docker container PHP-Apache script able to pull Local InfluxDB into display
2022-02-26 Switch to HKS562 the mysql DB has bad data so is not needed
2022-01-06 redraw box for Sunrise Sunset when data is updated to ensure old data is not visable.
2022-01-02 Extract Sunrise and Sunset and able to print it, but it is not converting to local time correctly - Issue fixed
2022-01-01 Adjust Forcast Formating for Temp
2021-12-31 convertToTime and stringUtcToLocal Are able toconvert Forecast JSON UTC DateTime to local DateTime
2021-12-29 convertToTime function may work for strptime. Have it partially working able to convert to DateTime then time_t. Able then call myTZ.toLocal to convert from utc to local TimeZone.
need to find where date info is at and convert  some of the steps to a function. - Issue Fixed
2021-12-27 strptime does not seem to be available for parsing to a time_t - Issue Solution Found (ConvertToTime & stringUtcToLocal)
2021-12-22 getWeatherForecast parsing issue was a JSON buffer size issue  json buffer 24000 can pull 24 3Hour data sets.  Next parse to find Max/min temp,wind,humidity and other data point - Issue Fixed
2021-12-21 Added getWeatherForecast it is having a JSON parseing issue Also added Sunrise-Sunset function time_t is not working correctly although this could be a parseing issue also - Issue Forecast fixed - Issue Sunrise/Set not working Partially Fixed
2021-12-18  Unable to pull influxdb data from: http://10.197.1.57:8086/query?db=Garden&q=SELECT%20*%20FROM%20%22Station%22%20WHERE%20station%20=%2092%20ORDER%20BY%20DESC%20LIMIT%201 - Issue
2021-12-05  currently not woring with builtin data storage  BMP header has an issue  - Issue
2021-12-04  Rebuilding display  finding what works and what does not for the M4.
2021-11-01  using code from older display to use new data sources and M4 feather its builtin Flash, ESP32 WiFi Coprocessor, and a more accurate RTC.

FUNCTIONS Manifest:
void setup()                                                               - Starts and sets up the hardware and varibles
void loop()                                                                - Main Loop
void printWifiStatus()                                                     - Print WiFi status after startup
void guiOff()                                                              - based on what the PIR sensor sees disables the display
void guiOn()                                                               - based on what the PIR sensor sees enables the display
time_t tmConvert_t(int YYYY, byte MM, byte DD, byte hh, byte mm, byte ss)  - Not yet used
time_t convertToTime(String calTimestamp)                                  - String Formated Time and Converts to time_t called by stringUtcToLocal
time_t stringUtcToLocal(String FCTime)                                     - String Formated Time and Converts to Local time_t
char * makeDateString(time_t t, char *ds)                                  - Formats Date String
char * makeJustDateString(time_t t, char *ds)                              - Formats Date String
char * makeAltDateString(time_t t, char *ds)                               - Formats Date String
char * makeDayString(time_t t, char *ds)                                   - Formats Date String
char * makeWeekDayString(time_t t, char *ds)                               - Formats Date String
char * makeTimeString(time_t t, char *ds)                                  - Formats Date String
char * makeHrMinTimeString(time_t t, char *ds)                             - Formats Date String
void mainGui()                                                             - Main GUI display Function
void checkWiFi()                                                           - Checks WiFi Status
void bmpDraw(const char *filename, int x, int y)                           - Draw Background Image
uint16_t read16(File f)                                                    - called by bmpDraw
uint32_t read32(File f)                                                    - called by bmpDraw
uint16_t color565(uint8_t r, uint8_t g, uint8_t b)                         - called by bmpDraw
byte decToBcd(byte val)                                                    - called by bmpDraw            
void SIRtouch()                                                            - Touch Screen Routine
void getLocalDataQuery()                                                   - Get local InfluxDB Weather Data
void ShowMaxMin(int xcnt, float tmax, float tmin)                          - Not currently Used
void getWeatherforcast()                                                   - Get Weather 3hr Forcast data
void getSunriseSunset()                                                    - Get Sunrise - Sunset data from Forcast site
double heatIndex(double tempF, double Humidity)                            - Calculate Heat Index from Temperature in F and Humidity
*/
#include<avr/dtostrf.h>
#include <Timezone.h>
#include <TimeLib.h>
#include <ArduinoJson.h> //code is for version 5.xx
#include <SPI.h>
//#include <WiFi101.h>
#include <WiFiNINA.h>
#include <Adafruit_GFX.h>
#include <Adafruit_RA8875.h>
//#include <Fonts/FreeSansBold12pt7b.h>
//#include <Fonts/FreeSansBold24pt7b.h>
//#include <SD.h>
#include "SdFat.h"
#include "Adafruit_SPIFlash.h"
#include <Wire.h>
#include <RTClib.h>

//#include "moonphases.h" //moon phase icons
//Timezone info for Timezone.h
time_t central, utc, curentTime;
// US Eastern Time Zone (Chicago, St Louis)
//TimeChangeRule myDST = {"EDT", Second, Sun, Mar, 2, -240};    // Daylight time = UTC - 4 hours
//TimeChangeRule mySTD = {"EST", First, Sun, Nov, 2, -300};     // Standard time = UTC - 5 hours
TimeChangeRule myDST = {"CDT", Second, Sun, Mar, 2, -300};    // Daylight time = UTC - 5 hours
TimeChangeRule mySTD = {"CST", First, Sun, Nov, 2, -360};     // Standard time = UTC - 6 hours
//TimeChangeRule myDST = {"MDT", Second, Sun, Mar, 2, -360};    // Daylight time = UTC - 6 hours
//TimeChangeRule mySTD = {"MST", First, Sun, Nov, 2, -420};     // Standard time = UTC - 7 hours
//TimeChangeRule myDST = {"PDT", Second, Sun, Mar, 2, -420};    // Daylight time = UTC - 7 hours
//TimeChangeRule mySTD = {"PST", First, Sun, Nov, 2, -480};     // Standard time = UTC - 8 hours
Timezone myTZ(myDST, mySTD);
TimeChangeRule *tcr;        // pointer to the time change rule, use to get TZ abbrev

char DtTme[20];
int oldReset;
DateTime GetTm;
DateTime GetBoot;
time_t GetBootutc;
time_t GetBootlocal;
time_t GetTmutc;
char GetBootut[20];
time_t GetTmlocal;
char GetTmlo[3];
char GetBootlo[20];
String GetTmloStr;
int GetTmloint;


//Ideally this should be set by above - Work in progress
const int GMT = -5; //change this to adapt it to your time zone

//RTC
//RTC_PCF8523 rtc;
RTC_DS3231 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

char filename[15];

#if defined(__SAMD51__) || defined(NRF52840_XXAA)
  Adafruit_FlashTransport_QSPI flashTransport(PIN_QSPI_SCK, PIN_QSPI_CS, PIN_QSPI_IO0, PIN_QSPI_IO1, PIN_QSPI_IO2, PIN_QSPI_IO3);
#else
  #if (SPI_INTERFACES_COUNT == 1 || defined(ADAFRUIT_CIRCUITPLAYGROUND_M0))
    Adafruit_FlashTransport_SPI flashTransport(SS, &SPI);
  #else
    Adafruit_FlashTransport_SPI flashTransport(SS1, &SPI1);
  #endif
#endif

Adafruit_SPIFlash flash(&flashTransport);

// file system object from SdFat
FatFileSystem fatfs;
 
// Pin mapping
//
// Set on the ability to turn the display on and off
int inPin = 15; //Defines Feather M0/4 Pin A1/15 as inpin for toggling the display on and off
int dspon = 0;
int dsponbefore = 0;
int mark_time;

// change this to match your SD shield or module;
// Adafruit SD shields and modules: pin 10
//Not needed with new Proc otherwise will change
//const int chipSelect = 10;

#include "arduino_secrets.h"
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
char ssid[] = SECRET_SSID;    // your network SSID (name)
char pass[] = SECRET_PASS;    // your network password (use for WPA, or use as key for WEP)
int keyIndex = 0;             // your network key Index number (needed only for WEP)
int status = WL_IDLE_STATUS;

// Configure the pins used for the ESP32 connection
#define SPIWIFI       SPI  // The SPI port
#define SPIWIFI_SS    13   // Chip select pin
#define ESP32_RESETN  12   // Reset pin
#define SPIWIFI_ACK   11   // a.k.a BUSY or READY pin
#define ESP32_GPIO0   10

// Library only supports hardware SPI at this time
// Connect SCLK to UNO Digital #13 (Hardware SPI clock)
// Connect MISO to UNO Digital #12 (Hardware SPI MISO)
// Connect MOSI to UNO Digital #11 (Hardware SPI MOSI)
#define RA8875_INT 5
#define RA8875_CS 9
#define RA8875_RESET 6

#define BUFFPIXEL 20

// Color definitions
#define BLACK    0x0000
#define BLUE     0x001F
#define RED      0xF800
#define GREEN    0x07E0
#define CYAN     0x07FF
#define BROWN    0x51E5
#define MAGENTA  0xF81F
#define YELLOW   0xFFE0
#define WHITE    0xFFFF
#define DRKTURQUOISE  0x1B4C
#define MEDTURQUOISE  0x2450

Adafruit_RA8875 tft = Adafruit_RA8875(RA8875_CS, RA8875_RESET);
tsPoint_t       _tsLCDPoints[3];
tsPoint_t       _tsTSPoints[3];
tsMatrix_t      _tsMatrix;
uint16_t tx, ty;
uint16_t x, y;

// This is calibration data for the raw touch data to the screen coordinates
//larger max shrinks dot spread and smaller max increases dot spread
#define TS_MINX 44
#define TS_MINY 130
#define TS_MAXX 775
#define TS_MAXY 510
long lastDebounceTime = 0;
long debounceDelay = 500;

//set GUI display
char GuidisplayState[] = "M1";      //M1 = main GUI screen    - Copied to Test
uint32_t currentMillis;        // store the current value from millis()
uint32_t previousMillis;       // for comparison with currentMillis
uint32_t samplingInterval;     // Frenquency to update display in MilliSeconds (millis)
uint32_t currentMillis1;        // store the current value from millis()
uint32_t previousMillis1;       // for comparison with currentMillis
uint32_t samplingInterval1;     // Frenquency to update display in MilliSeconds (millis)
uint16_t displayChange;         // Does the display need to be changed 0 = No 1 = Yes

// open weather map
String apiKey = SECRET_APIKEY; // open weather map data source API Key
String location= "4281730"; //the city you want the weather for  ?q=cityname
//String location = "4272788";     // The city ID you want the weather from json list ?id=citynumber
char server[] = "api.openweathermap.org";

// open the Local Weather Data
char server1[] = "10.197.1.100";

// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP & port 443 is default for HTTPS):
WiFiClient client;
//WiFiSSLClient client;
//Open Weather Map Query
//Find lat lon for weather data site
//http ://api.openweathermap.org/geo/1.0/direct?q=Haysville,KS,US&limit=10&appid=4e8bda75d9c60964...
//Forecast query
//https ://api.openweathermap.org/data/2.5/onecall?lat=37.5644615&lon=-97.3522675&units=imperial&exclude=minutely,hourly,alerts&appid=4e8bda75d9c60964... 
//[{"name":"Haysville","lat":37.5644615,"lon":-97.3522675,"country":"US","state":"Kansas"}]
// INFLUXDB Query
//http ://10.197.1.57:8086/query?db=Garden&q=SELECT * FROM "Station" WHERE station = 92 ORDER BY DESC LIMIT 1                  //index1.php
//http ://10.197.1.57:8086/query?db=Garden&q=SELECT MEAN("windspeed") FROM "Station" WHERE station = 92 and time > now() - 10m //WindAvg.php
//http ://10.197.1.57:8086/query?db=Garden&q=SELECT MAX("windspeed") FROM "Station" WHERE station = 92 and time > now() - 60m  //WindMax.php


void(* resetFunc) (void) = 0; //declare reset function @ address 0
/* Example Command to call reset function
resetFunc(); 
 */ 

void setup() {
  //-----------------------------------------------------------------------------------------------------------setup
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
 /*
 while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }  
 */
  //Configure pins for Adafruit ESP32 WiFi CoProcessor
  WiFi.setPins(SPIWIFI_SS, SPIWIFI_ACK, ESP32_RESETN, ESP32_GPIO0, &SPIWIFI);
  //Configure pins for Adafruit ATWINC1500 Breakout
  //WiFi.setPins(11, 13, 12);

  //Displays current file path when compiled
  Serial.println(__FILE__);
  display_Running_Sketch();

  //***************RTC Start*******************
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  //For RTC_PCF8523
  /*if (! rtc.initialized()) {
    Serial.println("RTC is NOT running!");
  }*/

  //setup reset 
  //This is my brute force to prevent loss of connection to Open Weather Map
  //I have not been able to detect loss of connection and then restart the network connection
  //Other than by reboot
  //Reset during hour 1AM
  GetBoot = rtc.now();
  oldReset = 0; // 0 means Arduino recently Reset during 1 AM. 1 means after reset the hour is now 2 AM and Reset has now been armed for next 1 AM.

  //***************SD/Flash config and start*******************
  // Start file system on the flash
  flash.begin();
  // Initialize flash library and check its chip ID.
  if (!flash.begin()) {
    Serial.println("Error, failed to initialize flash chip!");
    while(1) yield();
  }
  Serial.print("Flash chip JEDEC ID: 0x"); Serial.println(flash.getJEDECID(), HEX);

  // First call begin to mount the filesystem.  Check that it returns true
  // to make sure the filesystem was mounted.
  if (!fatfs.begin(&flash)) {
    Serial.println("Error, failed to mount formatted filesystem!");
    Serial.println("Was the flash chip formatted with the SdFat_format example?");
    while(1) yield();
  }
  Serial.println("Mounted filesystem!");

  File rootDir = fatfs.open("/");
  if (!rootDir) {
    Serial.println("Error, failed to open root directory!");
    while(1) yield();
  }
  if (!rootDir.isDirectory()) {
    Serial.println("Error, expected root to be a directory!");
    while(1) yield();
  }
  Serial.println("Listing children of directory /:");
  File child = rootDir.openNextFile();
  while (child) {
    char filename[64];
    child.getName(filename, sizeof(filename));
    
    // Print the file name and mention if it's a directory.
    Serial.print("- "); Serial.print(filename);
    if (child.isDirectory()) {
      Serial.print(" (directory)");
    }
    Serial.println();
    // Keep calling openNextFile to get a new file.
    // When you're done enumerating files an unopened one will
    // be returned (i.e. testing it for true/false like at the
    // top of this while loop will fail).
    child = rootDir.openNextFile();
  }

  //***************WiFi config and start*******************
  // check for the presence of the WiFi shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi shield not present");
    // don't continue:
    while (true);
  }
  // attempt to connect to WiFi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    // Connect to WPA/WPA2 network. Change this line if using open or WEP network:
    status = WiFi.begin(ssid, pass);
    // wait 10 seconds for connection:
    delay(10000);
  }
  Serial.println("Connected to wifi");
  printWifiStatus();

  //**************Start and Test RA8875/Display**************
  Serial.println("RA8875 start");
  // Initialise the display using 'RA8875_480x272' or 'RA8875_800x480' 
  if (!tft.begin(RA8875_800x480)) {
    Serial.println("RA8875 Not Found!");
  } else {
    Serial.println("Found RA8875");
    //enable and Test the display
    tft.displayOn(true);
    tft.GPIOX(true);      // Enable TFT - display enable tied to GPIOX
    tft.PWM1config(true, RA8875_PWM_CLK_DIV1024); // PWM output for backlight
    tft.PWM1out(255);
    // With hardware accelleration this is instant
    tft.fillScreen(RA8875_WHITE);
    // Test with PWM
    for (uint8_t i = 255; i != 0; i -= 5 )
    {
      tft.PWM1out(i);
      delay(10);
    }
    for (uint8_t i = 0; i != 255; i += 5 )
    {
      tft.PWM1out(i);
      delay(10);
    }
    tft.PWM1out(255);
    //test file of Red, Yellow, Green, Cyan, Magenta, and Black
    tft.fillScreen(RA8875_RED);
    delay(500);
    tft.fillScreen(RA8875_YELLOW);
    delay(500);
    tft.fillScreen(RA8875_GREEN);
    delay(500);
    tft.fillScreen(RA8875_CYAN);
    delay(500);
    tft.fillScreen(RA8875_MAGENTA);
    delay(500);
    tft.fillScreen(RA8875_BLACK);
    samplingInterval = 120000;  //Updates any Local data  (every 120 Seconds 2 Minutes)
    samplingInterval1 = 600000;  //Updates Forcast and Sunset data (every 600 Seconds 10 Minutes)
    displayChange = 1;         //Causes loop to paint initial display
  }
  Serial.print("(");
  Serial.print(tft.width());
  Serial.print(", ");
  Serial.print(tft.height());
  Serial.println(")");

  // Enable the touch screen
  Serial.println("Enabled the touch screen");
  pinMode(RA8875_INT, INPUT);
  digitalWrite(RA8875_INT, HIGH);
  tft.touchEnable(true);
  //attachInterrupt(digitalPinToInterrupt(RA8875_INT), SIRtouch, CHANGE);

  Serial.print("Status: "); Serial.println(tft.readStatus(), HEX);
  Serial.println("Waiting for touch events ...");

  mainGui();
  guiOff();
  Serial.println("The display should be off");
  delay(5000);
  guiOn();
  Serial.println("The display should be on");


  //****************Show Current Time********************
  Serial.println("What is the current time");
  DateTime tm = rtc.now();
  time_t utc = tm.unixtime();
  time_t local = myTZ.toLocal(utc, &tcr);
  char ut[20];
  makeDateString(utc, ut);
  strcpy(ut, DtTme); //Copy Global DtTime from makeTimeString to ut
  Serial.print(ut);
  Serial.println(" UTC");
  char lo[20];
  makeDateString(local, lo);
  strcpy(lo, DtTme); //Copy Global DtTime from makeTimeString to lo
  Serial.print(lo);
  Serial.print(" ");
  Serial.println(tcr -> abbrev);
  // TTN Test
  //getTTNquery();
  //Setup digital input pin for Display Presence Control
  pinMode(inPin, INPUT);    // sets the digital pin 15 as input
  mark_time = millis();
  previousMillis = (millis()-900000);
  previousMillis1 = (millis()-900000);
}

void loop() {
  //-------------------------------------------------------------------------------------------------- LOOP
  checkWiFi();
  float xScale = 1024.0F / tft.width();
  float yScale = 1024.0F / tft.height();
  //********************************************************************************
  // To protect the display blank it when no one is present
  dspon = digitalRead(inPin);   // read the input pin
  if (dspon != 1) {
    /*Serial.print("millis : ");
    Serial.print(millis());
    Serial.print("     marked time : ");
    Serial.println(mark_time);*/
    if (millis () - mark_time > 30000) {
      //For Small LCD displays
      //display.clearDisplay();
      //display.display();
      //For Larger RA8875 TFT displays where the display takes a bit to paint
      guiOff();
      if (dsponbefore != 0) {
         Serial.println("The Sensor does not sees motion - Display off");
         dsponbefore = 0;
      }
    }
  }
  if (dspon == 1) {
    mark_time = millis();
    guiOn();
    if (dsponbefore != 1) {
       Serial.print("The Sensor sees motion - Display on   ");
       Serial.println(__FILE__);
       dsponbefore = 1;
    }       
  }
  //********************************************************************************
  // Wait around for touch events
  if (! digitalRead(RA8875_INT))
  {
    if (tft.touched())
    {
      Serial.print(millis() - lastDebounceTime); Serial.print(" > or = < "); Serial.println(debounceDelay);
      if ((millis() - lastDebounceTime) > debounceDelay)
      {
        lastDebounceTime = millis();  //Debounce touch screen
        Serial.print("Touch: ");
        tft.touchRead(&tx, &ty);
        Serial.print(tx); Serial.print(", "); Serial.println(ty);
        Serial.print(tx / xScale); Serial.print(", "); Serial.println(ty / yScale);
        tx = map(tx, TS_MINX, TS_MAXX, 0, tft.width());
        ty = map(ty, TS_MINY, TS_MAXY, 0, tft.height());
        Serial.print("("); Serial.print(tx); Serial.print(", ");
        Serial.print(ty); Serial.println(") ");
        SIRtouch();
        // Draw a circle 
        tft.fillCircle((uint16_t)(tx / xScale), (uint16_t)(ty / yScale), 4, RA8875_WHITE);
      } //close Debounce Touch read
    } //close Touch check
  } //close reading touch interrupt line
  //********************************************************************************
  // Look for local time 01:00 AM reset arduino on start and time hour 01 set skip alarm at hour 02 remove skip alarm
  // 86400000 milliseconds per day
  //Serial.print(" Current Millis = ");
  //Serial.print(millis());
  //Get Current UTC Time -> Extract UNIX Time -> Convert to Local Time -> Convert Time string to Char -> Convert Char to String -> Convert String to Int
  GetTm = rtc.now();
  GetTmutc = GetTm.unixtime();
  GetTmlocal = myTZ.toLocal(GetTmutc, &tcr);
  makeHrTimeString(GetTmlocal, GetTmlo);
  strcpy(GetTmlo, DtTme); //Copy Global DtTime from makeTimeString to GetBootlo
  GetTmloStr = String(GetTmlo);
  GetTmloint = GetTmloStr.toInt();

  if (GetTmloint == 1)
  {
    if (oldReset == 1)
    {
      Serial.print(GetTmloint);
      Serial.println(" Reset Hour **************************");         
      resetFunc();
    }    
  }
  //Compare Pointer GetTmlo as uintptr_t to integer
  if (GetTmloint >= 2 && oldReset != 1)
  {
    oldReset = 1;
    Serial.print(GetTmloint);
    Serial.println(" Hour");
  } 
  //********************************************************************************
  //Update weather every 60 Seconds
  //convert the weather down load to use tick and update every minute
  currentMillis = millis();
  if (currentMillis - previousMillis > samplingInterval) {
    previousMillis = currentMillis;
  //
  // Calculate the Boot and reset hours to be displayed during weather data update
  GetBootutc = GetBoot.unixtime();
  GetBootlocal = myTZ.toLocal(GetBootutc, &tcr);
  makeDateString(GetBootutc, GetBootut);
  strcpy(GetBootut, DtTme); //Copy Global DtTime from makeTimeString to GetBootut
  Serial.print(GetBootut);
  Serial.println(" UTC");
  makeDateString(GetBootlocal, GetBootlo);
  strcpy(GetBootlo, DtTme); //Copy Global DtTime from makeTimeString to GetBootlo
  Serial.print(GetBootlo);
  Serial.print(" ");
  //Serial.println(tcr -> abbrev);
  Serial.print(tcr -> abbrev);
  Serial.println(" Local Start Time");
  //
  //This should be the trigger on the Arduino Reset when equal to 1
  Serial.print(GetTmloint);
  Serial.print(" Current Local Hour : ");
  Serial.print(oldReset);
  Serial.println(" Arm Value");
  Serial.println("(0 = Not Armed, Just reset at 1 AM, 1 = Armed, Ready to reset at 1 AM)");
  //
  // rest of the commands
    getLocalDataQuery();
    getLocalWindMaxQuery();
    getLocalWindAvgQuery();
  }
  //********************************************************************************
  //Update Forcast and Sunset every 600 Seconds
  //Open Weather Maps updates every 10 Minutes
  currentMillis1 = millis();
  if (currentMillis1 - previousMillis1 > samplingInterval1) {
    previousMillis1 = currentMillis1;
    // rest of the commands
    getSunriseSunset();
    getWeatherforcast();
  }
  //********************************************************************************
  // check if display changed or if we need a refresh
  if (displayChange == 1) {
    if (GuidisplayState == "M1") {
      mainGui();
      displayChange = 0;
    }
  }
}

void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

void guiOff() {
  tft.displayOn(false);
  tft.PWM1out(0);
}

void guiOn() {
  tft.displayOn(true);
  tft.PWM1out(255);
}
//************************************************************************************************************************ Date/Time
// Convert time_t to a Date/Time string
char * makeDateString(time_t t, char *ds)
{
  tmElements_t tm;
  breakTime(t, tm);
  sprintf(DtTme, "%02d/%02d/%02d %02d:%02d:%02d", (tm.Year + 1970 - 2000), tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second); // This prints date and time
  ds = DtTme;
  //Serial.println(ds);
  return DtTme;
}
//************************************************************************************************************************ Date
// Convert time_t to just a Date string
char * makeJustDateString(time_t t, char *ds)
{
  tmElements_t tm;
  breakTime(t, tm);
  sprintf(DtTme, "%02d/%02d/%02d", tm.Month, tm.Day, (tm.Year + 1970 - 2000)); // This prints date MM/DD/YY
  ds = DtTme;
  //Serial.println(ds);
  return DtTme;
}
//************************************************************************************************************************ Date
// Convert time_t to just a Date string without slash in Year Month Day
char * makeAltDateString(time_t t, char *ds)
{
  tmElements_t tm;
  breakTime(t, tm);
  sprintf(DtTme, "%04d%02d%02d", (tm.Year + 1970), tm.Month, tm.Day); // This prints date YYYYMMDD
  ds = DtTme;
  //Serial.println(ds);
  return DtTme;
}

//************************************************************************************************************************ Date
// Convert time_t to just a Date string without slash in Year Month Day
char * makeDayString(time_t t, char *ds)
{
  tmElements_t tm;
  breakTime(t, tm);
  sprintf(DtTme, "%02d", tm.Day); // This prints date DD
  ds = DtTme;
  //Serial.println(ds);
  return DtTme;
}

/*
//************************************************************************************************************************ Date
// Convert time_t to just a Date string without slash in Year Month Day
char * makeWeekDayString(time_t t, char *ds)
{
  tmElements_t tm;
  breakTime(t, tm);
  //sprintf(DtTme, "%04d%02d%02d", (tm.Year + 1970), tm.Month, 
  DtTme = tm.WeekDay;
  //); // This prints date YYYYMMDD
  //ds = DtTme;
  //Serial.println(ds);
  return DtTme;
}*/

//************************************************************************************************************************ Time
// Convert time_t to a Time string
char * makeTimeString(time_t t, char *ds)
{
  tmElements_t tm;
  breakTime(t, tm);
  sprintf(DtTme, "%02d:%02d:%02d", tm.Hour, tm.Minute, tm.Second); // This prints time
  ds = DtTme;
  //Serial.println(ds);
  return DtTme;
}

// Convert time_t to a time string Hours and Minutes
char * makeHrMinTimeString(time_t t, char *ds)
{
  tmElements_t tm;
  breakTime(t, tm);
  sprintf(DtTme, "%02d:%02d", tm.Hour, tm.Minute); // This prints time
  ds = DtTme;
  //Serial.println(ds);
  return DtTme;
}

// Convert time_t to a time string Hours and Minutes
char * makeHrTimeString(time_t t, char *ds)
{
  tmElements_t tm;
  breakTime(t, tm);
  sprintf(DtTme, "%01d", tm.Hour); // This prints time
  ds = DtTme;
  //Serial.println(ds);
  return DtTme;
}
//************************************************************************************************************************ M1 Main GUI
void mainGui() {
  //reset-clear display
  tft.graphicsMode();                 // go back to graphics mode
  tft.fillScreen(RA8875_BLACK);
  tft.graphicsMode();
  bmpDraw("SUNFLSST.BMP", 0, 0);
  //tft.fillScreen(RA8875_MAGENTA);
  //tft.fillScreen(RA8875_BLUE);
  tft.fillScreen(DRKTURQUOISE);
  // display is 800 x 480; 164mm x 100mm x 5mm; 6.5" x 3.9" 0.2"
  // 123 Pixels Per Inch
  // 4 buttons 46 pixels tall about 3/8" and 101 pixels wide about 3/4"
  // 5 buttons 46 pixels tall about 3/8" and 78 pixels wide about 5/8"
  // 15 pixel space between buttons
  // bottom of button about 8 pixels up
  // Example fillRoundRect(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint16_t radius, uint16_t color);
  tft.fillRoundRect(14,  427, 101, 46, 23, 0xFE20);
  tft.fillRoundRect(130, 427, 101, 46, 23, 0xFE20);
  tft.fillRoundRect(246, 427, 101, 46, 23, 0xFE20);
  tft.fillRoundRect(362, 427, 101, 46, 23, 0xFE20);

  tft.fillRoundRect(483, 381, 308, 92, 46, MEDTURQUOISE);

  tft.fillRect(9, 15, 150, 200, MEDTURQUOISE);
  tft.fillRect(167, 15, 150, 200, MEDTURQUOISE);
  tft.fillRect(325, 15, 150, 200, MEDTURQUOISE);
  tft.fillRect(483, 15, 150, 200, MEDTURQUOISE);
  tft.fillRect(641, 15, 150, 200, MEDTURQUOISE);

  tft.fillRect(9, 230, 150, 135, MEDTURQUOISE);
  tft.fillRect(167, 230, 150, 135, MEDTURQUOISE);
  tft.fillRect(325, 230, 150, 135, MEDTURQUOISE);
  tft.fillRect(483, 230, 150, 135, MEDTURQUOISE);
  tft.fillRect(641, 230, 150, 135, MEDTURQUOISE);

  tft.textMode();                 // go to text mode
  //tft.setFont(&FreeSansBold24pt7b);
  //void setCursor(uint16_t x0, uint16_t y0);
  //void setTextColor(uint16_t color);
  tft.textSetCursor(35, 440);
  tft.textTransparent(BROWN);
  //tft.textEnlarge(3);
  tft.textWrite("Weather");
  tft.graphicsMode();
  GuidisplayState[1] = 'M';
  GuidisplayState[2] = '1';
}

//************************************************************************************************************************ Check WiFi
void checkWiFi() {
  if ( WiFi.status() != WL_CONNECTED) {
    while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
      // unsuccessful, retry in 4 seconds
      Serial.print("failed ... ");
      delay(4000);
      Serial.print("retrying ... ");
    }
  }
}


//************************************************************************************************************************ BMP Draw
void bmpDraw(const char *filename, int x, int y) {
  // This function opens a Windows Bitmap (BMP) file and
  // displays it at the given coordinates.  It's sped up
  // by reading many pixels worth of data at a time
  // (rather than pixel by pixel).  Increasing the buffer
  // size takes more of the Arduino's precious RAM but
  // makes loading a little faster.  20 pixels seems a
  // good balance.
  File     bmpFile;
  int      bmpWidth, bmpHeight;   // W+H in pixels
  uint8_t  bmpDepth;              // Bit depth (currently must be 24)
  uint32_t bmpImageoffset;        // Start of image data in file
  uint32_t rowSize;               // Not always = bmpWidth; may have padding
  uint8_t  sdbuffer[3 * BUFFPIXEL]; // pixel in buffer (R+G+B per pixel)
  uint16_t lcdbuffer[BUFFPIXEL];  // pixeindex1l out buffer (16-bit per pixel)
  uint8_t  buffidx = sizeof(sdbuffer); // Current position in sdbuffer
  boolean  goodBmp = false;       // Set to true on valid header parse
  boolean  flip    = true;        // BMP is stored bottom-to-top
  int      w, h, row, col;
  uint8_t  r, g, b;
  uint32_t pos = 0, startTime = millis();
  uint8_t  lcdidx = 0;
  boolean  first = true;

  if ((x >= tft.width()) || (y >= tft.height())) return;

  Serial.println();
  Serial.print(F("Loading image '"));
  Serial.print(filename);
  Serial.println('\'');

  // Open requested file on SD card
  if ((bmpFile = fatfs.open(filename)) == false) {
    Serial.println(F("File not found"));
    return;
  }

  // Parse BMP header
  if (read16(bmpFile) == 0x4D42) { // BMP signature
    Serial.println(F("File size: "));
    Serial.println(read32(bmpFile));
    (void)read32(bmpFile); // Read & ignore creator bytes
    bmpImageoffset = read32(bmpFile); // Start of image data
    Serial.print(F("Image Offset: "));
    Serial.println(bmpImageoffset, DEC);

    // Read DIB header
    Serial.print(F("Header size: "));
    Serial.println(read32(bmpFile));
    bmpWidth  = read32(bmpFile);
    bmpHeight = read32(bmpFile);
    Serial.print(F("width: "));
    Serial.print(bmpWidth, DEC);
    Serial.print(F(" height: "));
    Serial.println(bmpHeight, DEC);

    if (read16(bmpFile) == 1) { // # planes -- must be '1'
      bmpDepth = read16(bmpFile); // bits per pixel
      Serial.print(F("Bit Depth: "));
      Serial.println(bmpDepth);
      if ((bmpDepth == 24) && (read32(bmpFile) == 0)) { // 0 = uncompressed
        goodBmp = true; // Supported BMP format -- proceed!
        Serial.print(F("Image size: "));
        Serial.print(bmpWidth);
        Serial.print('x');
        Serial.println(bmpHeight);

        // BMP rows are padded (if needed) to 4-byte boundary
        rowSize = (bmpWidth * 3 + 3) & ~3;

        // If bmpHeight is negative, image is in top-down order.
        // This is not canon but has been observed in the wild.
        if (bmpHeight < 0) {
          bmpHeight = -bmpHeight;
          flip      = false;
        }

        // Crop area to be loaded
        w = bmpWidth;
        h = bmpHeight;
        if ((x + w - 1) >= tft.width())  w = tft.width()  - x;
        if ((y + h - 1) >= tft.height()) h = tft.height() - y;

        // Set TFT address window to clipped image bounds

        for (row = 0; row < h; row++) { // For each scanline...
          // Seek to start of scan line.  It might seem labor-
          // intensive to be doing this on every line, but this
          // method covers a lot of gritty details like cropping
          // and scanline padding.  Also, the seek only takes
          // place if the file position actually needs to change
          // (avoids a lot of cluster math in SD library).
          if (flip) // Bitmap is stored bottom-to-top order (normal BMP)
            pos = bmpImageoffset + (bmpHeight - 1 - row) * rowSize;
          else     // Bitmap is stored top-to-bottom
            pos = bmpImageoffset + row * rowSize;
          if (bmpFile.position() != pos) { // Need seek?
            bmpFile.seek(pos);
            buffidx = sizeof(sdbuffer); // Force buffer reload
          }

          for (col = 0; col < w; col++) { // For each column...
            // Time to read more pixel data?
            if (buffidx >= sizeof(sdbuffer)) { // Indeed
              // Push LCD buffer to the display first
              if (lcdidx > 0) {
                tft.drawPixel(col + x, row + y, lcdbuffer[lcdidx]);
                lcdidx = 0;
                first  = false;
              }

              bmpFile.read(sdbuffer, sizeof(sdbuffer));
              buffidx = 0; // Set index to beginning
            }

            // Convert pixel from BMP to TFT format
            b = sdbuffer[buffidx++];
            g = sdbuffer[buffidx++];
            r = sdbuffer[buffidx++];
            lcdbuffer[lcdidx] = color565(r, g, b);
            tft.drawPixel(col + x, row + y, lcdbuffer[lcdidx]);
          } // end pixel

        } // end scanline

        // Write any remaining data to LCD
        if (lcdidx > 0) {
          tft.drawPixel(col + x, row + y, lcdbuffer[lcdidx]);
        }

        Serial.print(F("Loaded in "));
        Serial.print(millis() - startTime);
        Serial.println(" ms");

      } // end goodBmp
    }
  }

  bmpFile.close();
  if (!goodBmp) Serial.println(F("BMP format not recognized."));

}

//************************************************************************************************************************ Read 16/32 bit files from SD
// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.

uint16_t read16(File f) {
  uint16_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read(); // MSB
  return result;
}

uint32_t read32(File f) {
  uint32_t result;
  ((uint8_t *)&result)[0] = f.read(); // LSB
  ((uint8_t *)&result)[1] = f.read();
  ((uint8_t *)&result)[2] = f.read();
  ((uint8_t *)&result)[3] = f.read(); // MSB
  return result;
}

uint16_t color565(uint8_t r, uint8_t g, uint8_t b) {
  return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3);
}


byte decToBcd(byte val) {
  // Convert normal decimal numbers to binary coded decimal
  return ( (val / 10 * 16) + (val % 10) );
}

//************************************************************************************************************************ Touch Point Routines
// ***************************************************************************
// Touch point routines
// ***************************************************************************

void SIRtouch() {
  //Serial.print("Touch: ");
  if ((tx >= 10) && (tx <= 131) && (ty >= 917) && (ty <= 992)) {
    GuidisplayState[1] = 'M';
    GuidisplayState[2] = '1';
  }
  else
  {
    if ((tx >= 159) && (tx <= 261) && (ty >= 917) && (ty <= 992)) {
      GuidisplayState[1] = 'M';
      GuidisplayState[2] = '2';
    }
    else
    {
      if ((tx >= 315) && (tx <= 434) && (ty >= 917) && (ty <= 992)) {
        GuidisplayState[1] = 'M';
        GuidisplayState[2] = '3';
      }
      else
      {
        if ((tx >= 457) && (tx <= 588) && (ty >= 917) && (ty <= 992)) {
          GuidisplayState[1] = 'M';
          GuidisplayState[2] = '4';
        }
      }
    }
  }
}


//************************************************************************************************************************ Time Convert - This may not be needed
time_t tmConvert_t(int YYYY, byte MM, byte DD, byte hh, byte mm, byte ss)
{
  tmElements_t tmSet;
  tmSet.Year = YYYY - 1970;
  tmSet.Month = MM;
  tmSet.Day = DD;
  tmSet.Hour = hh;
  tmSet.Minute = mm;
  tmSet.Second = ss;
  return makeTime(tmSet);         //convert to time_t
}

time_t convertToTime(String calTimestamp) {
  struct tm tm;
  //Serial.println("Parsing " + calTimestamp);
  //Format 2021-12-30 03:00:00
  String year = calTimestamp.substring(0, 4);
  String month = calTimestamp.substring(5, 7);
  if (month.startsWith("0")) {
    month = month.substring(1);
  }
  String day = calTimestamp.substring(8, 10);
  if (day.startsWith("0")) {
    month = day.substring(1);
  }
  tm.tm_year = year.toInt() - 1900;
  tm.tm_mon = month.toInt() - 1;
  tm.tm_mday = day.toInt();
  tm.tm_hour = calTimestamp.substring(11, 13).toInt();
  tm.tm_min = calTimestamp.substring(14, 16).toInt();
  tm.tm_sec = calTimestamp.substring(17, 19).toInt();
  return mktime(&tm);
}

time_t stringUtcToLocal(String FCTime) {
  struct tm tm;
  DateTime FCtm = convertToTime(FCTime);
  time_t FCutc = FCtm.unixtime();
  time_t FCloc = myTZ.toLocal(FCutc, &tcr);
  return FCloc;
}

/*
  #############################################################################
  # Get data from The Local InfluxDB
  #
*/
void getLocalWindAvgQuery() {
  Serial.println("\nStarting connection to Docker Container PHP-Apache: InfluxDB WindAvg...");
  // if you get a connection, report back via serial:
  if (client.connect(server1, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.println("GET /WindAvg.php");//http://10.197.1.100/WindAvg.php
  } else {
    Serial.println("************************unable to connect************************");
    while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
      // unsuccessful, retry in 4 seconds
      Serial.print("failed ... ");
      delay(4000);
      Serial.print("retrying ... ");
    }
  }

  delay(1000);
  String line = "";

  while (client.connected()) {
    
    line = client.readStringUntil('\n');
    //Serial.println(line);
    Serial.print("Line : ");  Serial.println(line);
    Serial.println("parsingValues");

    //create a json buffer where to store the json data
    StaticJsonBuffer<1000> jsonBuffer;  //Arduinojson5

       JsonObject& root = jsonBuffer.parseObject(line);    //Arduinojson5

    if (!root.success()) {
      Serial.println("parseObject() failed");
      return;
    }

    //get the data from the json tree
    char windavg[10];
    float wndavg     = root["results"][0]["series"][0]["values"][0][1];
    dtostrf(wndavg, 6, 0, windavg);
  
    Serial.print(" @-Min Wind Average : ");
    Serial.println(windavg); 

    // Display the Values
    tft.textMode();                     // go to text mode
    tft.textTransparent(RA8875_WHITE);  // set text color
    tft.textEnlarge(0);
    tft.textSetCursor(486, 90);
    tft.textWrite("Wind 2-Min Average");
    tft.textSetCursor(595, 108);
    tft.textWrite("MPH");

    tft.textEnlarge(2);
    tft.textSetCursor(450, 108);
    tft.textWrite(windavg);
  }
}

void getLocalWindMaxQuery() {
  Serial.println("\nStarting connection to Docker Container PHP-Apache: InfluxDB WindMax...");
  // if you get a connection, report back via serial:
  if (client.connect(server1, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.println("GET /WindMax.php");//http://10.197.1.100/WindMax.php
  } else {
    Serial.println("************************unable to connect************************");
    while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
      // unsuccessful, retry in 4 seconds
      Serial.print("failed ... ");
      delay(4000);
      Serial.print("retrying ... ");
    }
  }

  delay(1000);
  String line = "";

  while (client.connected()) {
    
    line = client.readStringUntil('\n');
    //Serial.println(line);
    Serial.print("Line : ");  Serial.println(line);
    Serial.println("parsingValues");

    //create a json buffer where to store the json data
    StaticJsonBuffer<1000> jsonBuffer;  //Arduinojson5
    JsonObject& root = jsonBuffer.parseObject(line);    //Arduinojson5

    if (!root.success()) {
      Serial.println("parseObject() failed");
      return;
    }

    //get the data from the json tree
    char windmax[10];
    float wndmax     = root["results"][0]["series"][0]["values"][0][1];
    dtostrf(wndmax, 6, 0, windmax);
  
    Serial.print(" 1 Hour Max Gust : ");
    Serial.println(windmax); 
  
    // Display the Values
    tft.textMode();                     // go to text mode
    tft.textTransparent(RA8875_WHITE);  // set text color
    tft.textEnlarge(0);
    tft.textSetCursor(486, 150);
    tft.textWrite("Wind 1-Hr Max Gust");
    tft.textSetCursor(595, 168);
    tft.textWrite("MPH");

    tft.textEnlarge(2);
    tft.textSetCursor(450, 168);
    tft.textWrite(windmax);  
  }
}

void getLocalDataQuery() {
  Serial.println("\nStarting connection to Docker Container PHP-Apache: InfluxDB index1...");
  // if you get a connection, report back via serial:
  if (client.connect(server1, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.println("GET /index1.php");//http://10.197.1.100/index1.php
  } else {
    Serial.println("************************unable to connect************************");
    while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
      // unsuccessful, retry in 4 seconds
      Serial.print("failed ... ");
      delay(4000);
      Serial.print("retrying ... ");
    }
  }

  delay(1000);
  String line = "";

  while (client.connected()) {
    
    line = client.readStringUntil('\n');
    //Serial.println(line);
    Serial.print("Line : ");  Serial.println(line);
    Serial.println("parsingValues");

    //create a json buffer where to store the json data
    StaticJsonBuffer<1000> jsonBuffer;  //Arduinojson5

    JsonObject& root = jsonBuffer.parseObject(line);    //Arduinojson5

    if (!root.success()) {
      Serial.println("parseObject() failed");
      return;
    }

    Serial.print("Line : ");  Serial.println(line);

    //get the data from the json tree
    char temp[10];
    //String stemp;
    char heatindex[10];
    char dewpoint[10];
    char humidity[10];
    char pressure[10];
    char soiltemp[10];
    char rainfall[10];
    char windspeed[10];
    char winddirection[5];
    char windchill[10];
    char batteryvolt[10];
    int dx;
    int dy;
    int dxOuter, dyOuter, dxinner, dyinner;
    //Setup Wind indicator parameters
    const int windX  = 716;
    const int windY  = 92;
    const int diam  = 55;
    const char* cUtcTime;
    //String cUtcTime;
    //Convert float(s) & int(s) to displayable Strings
    //unsigned long epoch = (((year/4*(365*4+1)+days[year%4][month]+dayOfMonth)*24+hour)*60+minute)*60+second

    int StatementID = root["results"]["statement_id"];
    Serial.print("Statement ID : ");
    Serial.println(StatementID);
    const char* StationNme = root["results"][0]["series"][0]["name"];
    Serial.print("name : ");
    Serial.println(StationNme);
    //Time
    cUtcTime = root["timeStamp"];           //Extracts the timeStamp to a const char*
    String sUtcTime(cUtcTime);              // converts const char* to String  //next step convert from String to time_t
    //time_t utctime = sUtcTime
    //time_t utctime = root["timeStamp"];
    //Temperature
    float tmp     = root["results"][0]["series"][0]["values"][0][8];
    dtostrf(tmp, 5, 0, temp);           // Converts float to char with no decimal
    //Humidity
    float h1     = root["results"][0]["series"][0]["values"][0][2];
    int h2 = h1 * 10;
    float hum  = h2 / 10;
    dtostrf(hum, 5, 0, humidity);
    //Pressure
    float p1     = root["results"][0]["series"][0]["values"][0][4];
    int p2 = p1 * 10;
    float prssure = p2 / 10;
    dtostrf(prssure, 7, 1, pressure);
    //float soilmoisture     = root["results"][0]["series"][0]["values"][0][3];
    //float csoiltemp     = root["results"][0]["series"][0]["values"][0][6];
    //float soiltmp     = (csoiltemp * 1.8) + 32;
    //dtostrf(soiltmp, 5, 0, soiltemp);
    //Rainfall
    float rfall     = root["results"][0]["series"][0]["values"][0][5];
    dtostrf(rfall, 7, 4, rainfall);
    //Wind Speed
    float wndspeed     = root["results"][0]["series"][0]["values"][0][12];
    dtostrf(wndspeed, 6, 0, windspeed);
    //Wind Direction
    float  wnddirect     = root["results"][0]["series"][0]["values"][0][11];
    dtostrf(wnddirect, 4, 0, winddirection);
    // Wind Chill
    //float cwndchll = root["windchill"];
    //T(wc) = 0.0817(3.71V**0.5 + 5.81 -0.25V)(T - 91.4) + 91.4 T(wc); (wind chill old Formula), 
    //T(wc) = 35.74 + 0.6215*T - 35.75(V^0.16) + 0.4275*T(V^0.16);     (wind chill new Formula),
    //V is in the wind speed in statute miles per hour
    //T is the temperature in degrees Fahrenheit.
    float wndchill;
    if (tmp > 50 || wndspeed ==0){
      wndchill = tmp;
    } else {
      float T = tmp;
      float V = wndspeed;
      wndchill  = 35.74 + (0.6215*T) - (35.75*pow(V,0.16)) + (0.4275*T*pow(V,0.16));
    }
    dtostrf(wndchill, 5, 0, windchill);
    Serial.print("Windchill : ");
    Serial.print(windchill);
    // Heatindex (this will need to be calculated)
    
    float chtindx = root["heatindex"];
    //Heat Index
    double htindx;
    double Dtempf = tmp;
    double Dhumid = hum;
    if (tmp < 80 || hum < 40){
      htindx = tmp;
    } else {
      htindx = heatIndex(Dtempf,Dhumid);
    }
    dtostrf(htindx, 5, 0, heatindex);
    Serial.print("Heat Index : ");
    Serial.print(heatindex);
    //Dew Point Calculations
    // DP = T - ((100 - RH)/5)  T= Temperature & RH = Relative Humidity
    double C = ((tmp - 32) * (5/9) );
    double H = hum; 
    double DwPnt = (C - ((100 - H) / 5));    //  dewpoint calculation using Celsius value
    float  DwPoint = (DwPnt * 9 / 5) + 32;   //  converts dewPoint calculation to fahrenheit
    dtostrf(DwPoint, 5, 0, dewpoint);
    Serial.print("Dew Point : ");
    Serial.println(dewpoint);
    //Battery Voltage
    float batv     = root["results"][0]["series"][0]["values"][0][10];
    dtostrf(batv, 7, 3, batteryvolt);
    //
    DateTime tm = rtc.now();
    time_t utc = tm.unixtime();
    time_t local = myTZ.toLocal(utc, &tcr);
    char lo[20];
    char lod[20];
    makeHrMinTimeString(local, lo);
    strcpy(lo, DtTme); //Copy Global DtTime from makeTimeString to lo
    makeJustDateString(local, lo);
    strcpy(lod, DtTme); //Copy Global DtTime from makeTimeString to lod

    // Print values.
    Serial.print("Current Time : ");
//    Serial.print(utctime);
    Serial.print(lo);
    Serial.print(" ");
    Serial.println(tcr -> abbrev);
    Serial.print(" Temperature : ");
    Serial.print(temp);
    Serial.print(" Humidity : ");
    Serial.println(humidity);
    Serial.print("Pressure : ");
    Serial.print(pressure);
    Serial.print(" Rainfall : ");
    Serial.print(rainfall);
    Serial.print(" Battery : ");
    Serial.println(batteryvolt);
    Serial.print(" WindSpeed : ");
    Serial.print(windspeed);
    Serial.print(" Wind Direction : ");
    Serial.println(winddirection);
/**/
    tft.graphicsMode();
    tft.fillRect(167, 15, 150, 200, MEDTURQUOISE); //Temperature Box
    tft.fillRect(325, 15, 150, 200, MEDTURQUOISE); //Humidity Box
    tft.fillRect(483, 15, 150, 200, MEDTURQUOISE); //Pressure Box
    tft.fillRect(641, 15, 150, 200, MEDTURQUOISE); //Wind Box
    tft.fillRoundRect(483, 381, 308, 92, 46, MEDTURQUOISE); //Date Time station Voltage

    // Display the Values
    tft.textMode();                     // go to text mode
    tft.textTransparent(RA8875_WHITE);  // set text color
    tft.textEnlarge(0);
    tft.textSetCursor(170, 20);
    tft.textWrite("Temperature");
    tft.textSetCursor(295, 40);
    tft.textWrite("F");
    tft.textSetCursor(295, 110);
    tft.textWrite("F");
    tft.textSetCursor(295, 170);
    tft.textWrite("F");
    tft.textSetCursor(170, 90);
    tft.textWrite("Wind Chill");
    tft.textSetCursor(170, 150);
    tft.textWrite("Heat Index");
    tft.textSetCursor(328, 20);
    tft.textWrite("Humidity");
    tft.textSetCursor(433, 40);
    tft.textWrite("% RH");
    tft.textSetCursor(453, 110);
    tft.textWrite("F");
    tft.textSetCursor(328, 90);
    tft.textWrite("Dew Point");
    tft.textSetCursor(486, 20);
    tft.textWrite("Pressure");
    tft.textSetCursor(590, 40);
    tft.textWrite("\" Hg");
    tft.textSetCursor(644, 20);
    tft.textWrite("Wind");
    tft.textSetCursor(758, 170);
    tft.textWrite("MPH");
    tft.textSetCursor(580, 402);
    tft.textWrite(tcr -> abbrev); //Current Time Zone
    tft.textSetCursor(650, 440);
    tft.textWrite("Batt : ");
    tft.textWrite(batteryvolt);
    tft.textWrite(" V");
/**/
    tft.textEnlarge(2);
    tft.textSetCursor(160, 35);
    tft.textWrite(temp);

    tft.textSetCursor(160, 100);
    tft.textWrite(windchill);
    tft.textSetCursor(160, 160);
    tft.textWrite(heatindex);
    tft.textSetCursor(318,100);    
    tft.textWrite(dewpoint);
    
    tft.textEnlarge(2);
    tft.textSetCursor(311, 35);
    tft.textWrite(humidity);
    tft.textSetCursor(418, 35);
    tft.textWrite(pressure);
    tft.textSetCursor(540, 155);
    tft.textWrite(windspeed);
/**/
    tft.textEnlarge(1);
    tft.textSetCursor(490, 399);
    tft.textWrite(lo);   //Local Time
    tft.textSetCursor(490, 428); //for date
    tft.textWrite(lod); // Local Date
    //Reset to TextEnlarge 0 and to Graphics mode
    tft.textEnlarge(0);
    tft.graphicsMode();

    //*--------------------------------------------------------------
    // Start WIND COMPASS ROSE and place Wind Direction Indicator
    //
    // Draw Circle center at windX, windY and sized with diam
    tft.drawCircle(windX, windY, diam, RA8875_WHITE);
    // 90 Degree Hash Marks
    tft.drawLine((windX - diam - 5), windY, (windX - diam + 5), windY, RA8875_CYAN);
    tft.drawLine((windX + diam - 5), windY, (windX + diam + 5), windY, RA8875_CYAN);
    tft.drawLine(windX, (windY - diam - 5), windX, (windY - diam + 5), RA8875_CYAN);
    tft.drawLine(windX, (windY + diam - 5), windX, (windY + diam + 5), RA8875_CYAN);
    // add the Four Ordinal points - 45 Degree Hash Marks
    for (float i = 0; i < 360; i = i + 45 )
    {
      dxOuter = (diam * cos((i - 90) * 3.14 / 180));
      dyOuter = (diam * sin((i - 90) * 3.14 / 180));
      dxinner = dxOuter * 0.92;
      dyinner = dyOuter * 0.92;
      tft.drawLine((dxinner + windX), (dyinner + windY), (dxOuter + windX), (dyOuter + windY), RA8875_CYAN);
    }
    // Add the Eight half-winds - 22.5 Degree Hash Marks
    for (float i = 0; i < 360; i = i + 22.5 )
    {
      dxOuter = (diam * cos((i - 90) * 3.14 / 180));
      dyOuter = (diam * sin((i - 90) * 3.14 / 180));
      dxinner = dxOuter * 0.95;
      dyinner = dyOuter * 0.95;
      tft.drawLine((dxOuter + windX), (dyOuter + windY), (dxinner + windX), (dyinner + windY), RA8875_CYAN);
    }
    // Add the Sixteen quarter-winds - 11.25 Degree Hash Marks
    // My current Windirection device does not support quarter winds
    for (float i = 0; i < 360; i = i + 11.25 )
    {
      dxOuter = diam * cos((i - 90) * 3.14 / 180);
      dyOuter = diam * sin((i - 90) * 3.14 / 180);
      dxinner = dxOuter * 0.98;
      dyinner = dyOuter * 0.98;
      tft.drawLine((dxOuter + windX), (dyOuter + windY), (dxinner + windX), (dyinner + windY), RA8875_CYAN);
    }
    //Windirection Indicator
/**/    
    dx = (diam * .9 * cos((wnddirect - 90) * 3.14 / 180)) + windX; // calculate X position
    dy = (diam * .9 * sin((wnddirect - 90) * 3.14 / 180)) + windY; // calculate Y position
    tft.drawLine(dx, dy, windX, windY, RA8875_RED);
/**/
    //Add N,S,E,W near cardinal hash marks
    tft.textMode();
    tft.textTransparent(RED);
    tft.textEnlarge(0);
    tft.textSetCursor((windX - 3), (windY - (diam + 18)));
    tft.textWrite("N");
    tft.textTransparent(YELLOW);
    tft.textSetCursor((windX - 3), (windY + (diam + 4)));
    tft.textWrite("S");
    tft.textSetCursor((windX + (diam + 7)), (windY - 8));
    tft.textWrite("E");
    tft.textSetCursor((windX - (diam + 13)), (windY - 8)); //X was 12 almost no gap from end of dash needs to go left
    tft.textWrite("W");
    //
    tft.graphicsMode();
    // Finished with WIND COMPASS ROSE
  }
}
void ShowMaxMin(int xcnt, float tmax, float tmin) {
  Serial.print("Day ");
  Serial.print(xcnt);
  Serial.print(" Max Temp ");
  Serial.print(tmax);
  Serial.print(" Min Temp ");
  Serial.println(tmin);
}

double heatIndex(double tempF, double Humidity){
//Heat Index from: https://www.weather.gov/ama/heatindex#:~:text=The%20heat%20index%2C%20also%20known,sweat%20to%20cool%20itself%20off
//Heat Index = -42.379 + 2.04901523T + 10.14333127R - 0.22475541TR - 6.83783 x 10-3T2 - 5.481717 x 10-2R2 + 1.22874 x 10-3T2R + 8.5282 x 10-4TR2 - 1.99 x 10-6T2R2
// Where T = Temperature in F
//       R = Relative humidity
//
double T = tempF;
double R = Humidity;
double HI = -42.379 + 2.04901523*T + 10.14333127*R - 0.22475541*T*R - 0.00683783*T*T - 0.05481717*R*R + 0.00122874*T*T*R + 0.00085282*T*R*R - 0.00000199*T*T*R*R;
return HI;
}


void getWeatherforcast() {
  Serial.println("\nStarting connection to server: api.openweathermap.org Weather Forecast...");
  // if you get a connection, report back via serial:
  //https ://api.openweathermap.org/data/2.5/onecall?lat=37.5644615&lon=-97.3522675&units=imperial&exclude=minutely,hourly,alerts&appid=4e8bda75d9c60964
  if (client.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.print("GET /data/2.5/onecall?");
    //client.print("id="+location);
    //lat=37.5644615&lon=-97.3522675
    client.print("lat=37.5644615");
    client.print("&lon=-97.3522675");
    client.print("&units=imperial");  // imperial= Fahrenheit, metric= Celsius,default is Kelvin
    client.print("&exclude=minutely,hourly,alerts");
    client.println("&appid="+apiKey);
    client.println("Host: api.openweathermap.org");
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println("************************unable to connect************************");
    WiFi.disconnect();
    while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
      // unsuccessful, retry in 4 seconds
      Serial.print("failed ... ");
      delay(4000);
      Serial.print("retrying ... ");
    }
  }

  delay(1000);
  String line = "";

  while (client.connected()) {
    line = client.readStringUntil('\n');
    
    Serial.println(line);
    Serial.println("parsingValues");
    //create a json buffer where to store the json data
    StaticJsonBuffer<24000> jsonBuffer;  //Arduinojson5

    JsonObject& root = jsonBuffer.parseObject(line);    //Arduinojson5
    if (!root.success()) {
      Serial.println("parseObject() failed");
      return;
    }

  //get the data from the json tree
  //declare reused time Variables
  char FClo[20];
  char FClod[20];
  String FClodPrev; //Do I need this
  int dow;
  String DayoWeek;


  //Todays Forcast
  String ftimestr0 = root["daily"][0]["dt"];
  time_t fsttm = ftimestr0.toInt();
  time_t FCloc = myTZ.toLocal(fsttm, &tcr);
  dow=(((FCloc / 86400) + 4) % 7);
  DayoWeek = daysOfTheWeek[dow];
  char FCDOW00[10];
  DayoWeek.toCharArray(FCDOW00, 10);
  Serial.print("Todays Forecast ");
  Serial.print(dow);
  Serial.print(" ");
  Serial.println(DayoWeek);
  makeHrMinTimeString(FCloc, FClo);
  strcpy(FClo, DtTme); //Copy Global DtTime from makeTimeString to lo
  makeJustDateString(FCloc, FClod);
  strcpy(FClod, DtTme); //Copy Global DtTime from makeTimeString to lod  
  FClodPrev = FClod; //This is the first date so it is always unique  // Do I need this
  String FCTimeD00 = FClod;
  String FCTime00 = FClo;
  double FCTmp00 = root["daily"][0]["temp"]["max"];
  char FCTemp00[5];
  dtostrf(FCTmp00, 4, 0, FCTemp00);
  double FCTmpL00 = root["daily"][0]["temp"]["min"];
  char FCTempL00[5];
  dtostrf(FCTmpL00, 4, 0, FCTempL00);
  double FCHum00 = root["daily"][0]["humidity"];
  char FCHumid00[5];
  dtostrf(FCHum00, 4, 0, FCHumid00);  
  String FCSky00 = root["daily"][0]["weather"][0]["main"];
  double FCWSpd00 = root["daily"][0]["wind_speed"];
  
  double FCWDir00 = root["daily"][0]["wind_deg"];
  double FCWGst00 = root["daily"][0]["wind_gust"];
  //dtostrf(DwPoint, 5, 0, dewpoint);
  //Test if Rain or Snow is present then set else set to 0
  double FCPo00 = root["daily"][0]["pop"]; // Probability
  int FCPop00 = FCPo00 * 100;
  char FCProb00[5];
  dtostrf(FCPop00, 4, 0, FCProb00);     
  double FCRn00 = root["daily"][0]["rain"];// Rain Amount
  double FCSn00 = root["daily"][0]["snow"];// Snow Amount
  char FCRain00[5];
  if (!FCRn00 && !FCSn00) {
    FCRn00=0;
  } else {  
    if (!FCRn00) {
      FCRn00 = FCSn00;
    }  
  }
  dtostrf(FCRn00, 4, 0, FCRain00); 
  
  //Day 1 Forcast
  String ftimestr1 = root["daily"][1]["dt"];
  fsttm = ftimestr1.toInt();
  FCloc = myTZ.toLocal(fsttm, &tcr);
  //Day of Week
  dow=(((FCloc / 86400) + 4) % 7);
  DayoWeek = daysOfTheWeek[dow];
  char FCDOW01[10];
  DayoWeek.toCharArray(FCDOW01, 10);
  // Day of Week End
  makeHrMinTimeString(FCloc, FClo);
  strcpy(FClo, DtTme); //Copy Global DtTime from makeTimeString to lo
  makeJustDateString(FCloc, FClod);
  strcpy(FClod, DtTme); //Copy Global DtTime from makeTimeString to lod  
  FClodPrev = FClod; //This is the first date so it is always unique  // Do I need this
  String FCTimeD01 = FClod; // We will always need the first date
  String FCTime01 = FClo;
  double FCTmp01 = root["daily"][1]["temp"]["max"];
  char FCTemp01[5];
  dtostrf(FCTmp01, 4, 0, FCTemp01);
  double FCTmpL01 = root["daily"][1]["temp"]["min"];
  char FCTempL01[5];
  dtostrf(FCTmpL01, 4, 0, FCTempL01);
  double FCHum01 = root["daily"][1]["humidity"];
  char FCHumid01[5];
  dtostrf(FCHum01, 4, 0, FCHumid01);  
  String FCSky01 = root["daily"][1]["weather"][0]["main"];
  String FCWSpd01 = root["daily"][1]["wind_speed"];
  String FCWDir01 = root["daily"][1]["wind_deg"];
  String FCWGst01 = root["daily"][1]["wind_gust"];
  //Test if Rain or Snow is present then set else set to 0
  double FCPo01 = root["daily"][1]["pop"]; // Probability
  int FCPop01 = FCPo01 * 100;
  char FCProb01[5];
  dtostrf(FCPop01, 4, 0, FCProb01);   
  double FCRn01 = root["daily"][1]["rain"];// Rain Amount
  double FCSn01 = root["daily"][1]["snow"];// Snow Amount
  char FCRain01[5];
  if (!FCRn01 && !FCSn01) {
    FCRn01=0;
  } else {  
    if (!FCRn01) {
      FCRn01 = FCSn01;
    }  
  }
  dtostrf(FCRn01, 4, 0, FCRain01);

  //Day 2 Forcast
  String ftimestr2 = root["daily"][2]["dt"];
  fsttm = ftimestr2.toInt();
  FCloc = myTZ.toLocal(fsttm, &tcr);
  //Day of Week
  dow=(((FCloc / 86400) + 4) % 7);
  DayoWeek = daysOfTheWeek[dow];
  char FCDOW02[10];
  DayoWeek.toCharArray(FCDOW02, 10);
  // Day of Week End
  makeHrMinTimeString(FCloc, FClo);
  strcpy(FClo, DtTme); //Copy Global DtTime from makeTimeString to lo
  makeJustDateString(FCloc, FClod);
  strcpy(FClod, DtTme); //Copy Global DtTime from makeTimeString to lod  
  FClodPrev = FClod; //This is the first date so it is always unique  // Do I need this
  String FCTimeD02 = FClod; // We will always need the first date
  String FCTime02 = FClo;
  double FCTmp02 = root["daily"][2]["temp"]["max"];
  char FCTemp02[5];
  dtostrf(FCTmp02, 4, 0, FCTemp02);
  double FCTmpL02 = root["daily"][2]["temp"]["min"];
  char FCTempL02[5];
  dtostrf(FCTmpL02, 4, 0, FCTempL02);
  double FCHum02 = root["daily"][2]["humidity"];
  char FCHumid02[5];
  dtostrf(FCHum02, 4, 0, FCHumid02);  
  String FCSky02 = root["daily"][2]["weather"][0]["main"];
  String FCWSpd02 = root["daily"][2]["wind_speed"];
  String FCWDir02 = root["daily"][2]["wind_deg"];
  String FCWGst02 = root["daily"][2]["wind_gust"];
  //Test if Rain or Snow is present then set else set to 0
  double FCPo02 = root["daily"][2]["pop"]; // Probability
  int FCPop02 = FCPo02 * 100;
  char FCProb02[5];
  dtostrf(FCPop02, 4, 0, FCProb02);     
  double FCRn02 = root["daily"][2]["rain"];// Rain Amount
  double FCSn02 = root["daily"][2]["snow"];// Snow Amount
  char FCRain02[5];
  if (!FCRn02 && !FCSn02) {
    FCRn02=0;
  } else {  
    if (!FCRn02) {
      FCRn02 = FCSn02;
    }  
  }
  dtostrf(FCRn02, 4, 0, FCRain02); 

  //Day 3 Forcast
  String ftimestr3 = root["daily"][3]["dt"];
  fsttm = ftimestr3.toInt();
  FCloc = myTZ.toLocal(fsttm, &tcr);
  //Day of Week
  dow=(((FCloc / 86400) + 4) % 7);
  DayoWeek = daysOfTheWeek[dow];
  char FCDOW03[10];
  DayoWeek.toCharArray(FCDOW03, 10);
  // Day of Week End
  makeHrMinTimeString(FCloc, FClo);
  strcpy(FClo, DtTme); //Copy Global DtTime from makeTimeString to lo
  makeJustDateString(FCloc, FClod);
  strcpy(FClod, DtTme); //Copy Global DtTime from makeTimeString to lod  
  FClodPrev = FClod; //This is the first date so it is always unique  // Do I need this
  String FCTimeD03 = FClod; // We will always need the first date
  String FCTime03 = FClo;
  double FCTmp03 = root["daily"][3]["temp"]["max"];
  char FCTemp03[5];
  dtostrf(FCTmp03, 4, 0, FCTemp03);
  double FCTmpL03 = root["daily"][3]["temp"]["min"];
  char FCTempL03[5];
  dtostrf(FCTmpL03, 4, 0, FCTempL03); 
//  String FCHumid03 = root["daily"][3]["humidity"];
  double FCHum03 = root["daily"][3]["humidity"];
  char FCHumid03[5];
  dtostrf(FCHum03, 4, 0, FCHumid03);  
  String FCSky03 = root["daily"][3]["weather"][0]["main"];
  String FCWSpd03 = root["daily"][3]["wind_speed"];
  String FCWDir03 = root["daily"][3]["wind_deg"];
  String FCWGst03 = root["daily"][3]["wind_gust"];
  //Test if Rain or Snow is present then set else set to 0
  double FCPo03 = root["daily"][3]["pop"]; // Probability
  int FCPop03 = FCPo03 * 100;
  char FCProb03[5];
  dtostrf(FCPop03, 4, 0, FCProb03);     
  double FCRn03 = root["daily"][3]["rain"];// Rain Amount
  double FCSn03 = root["daily"][3]["snow"];// Snow Amount
  char FCRain03[5];
  if (!FCRn03 && !FCSn03) {
    FCRn03=0;
  } else {  
    if (!FCRn03) {
      FCRn03 = FCSn03;
    }  
  }
  dtostrf(FCRn03, 4, 0, FCRain03); 
 

  //Day 4 Forcast
  String ftimestr4 = root["daily"][4]["dt"];
  fsttm = ftimestr4.toInt();
  FCloc = myTZ.toLocal(fsttm, &tcr);
  //Day of Week
  dow=(((FCloc / 86400) + 4) % 7);
  DayoWeek = daysOfTheWeek[dow];
  char FCDOW04[10];
  DayoWeek.toCharArray(FCDOW04, 10);
  // Day of Week End
  makeHrMinTimeString(FCloc, FClo);
  strcpy(FClo, DtTme); //Copy Global DtTime from makeTimeString to lo
  makeJustDateString(FCloc, FClod);
  strcpy(FClod, DtTme); //Copy Global DtTime from makeTimeString to lod  
  FClodPrev = FClod; //This is the first date so it is always unique  // Do I need this
  String FCTimeD04 = FClod; // We will always need the first date
  String FCTime04 = FClo;
  double FCTmp04 = root["daily"][4]["temp"]["max"];
  char FCTemp04[5];
  dtostrf(FCTmp04, 4, 0, FCTemp04);
  double FCTmpL04 = root["daily"][4]["temp"]["min"];
  char FCTempL04[5];
  dtostrf(FCTmpL04, 4, 0, FCTempL04);  
//  String FCHumid04 = root["daily"][4]["humidity"];
  double FCHum04 = root["daily"][4]["humidity"];
  char FCHumid04[5];
  dtostrf(FCHum04, 4, 0, FCHumid04);  
  String FCSky04 = root["daily"][4]["weather"][0]["main"];
  String FCWSpd04 = root["daily"][4]["wind_speed"];
  String FCWDir04 = root["daily"][4]["wind_deg"];
  String FCWGst04 = root["daily"][4]["wind_gust"];
  //Test if Rain or Snow is present then set else set to 0
  double FCPo04 = root["daily"][4]["pop"]; // Probability
  int FCPop04 = FCPo04 * 100;
  char FCProb04[5];
  dtostrf(FCPop04, 4, 0, FCProb04);     
  double FCRn04 = root["daily"][4]["rain"];// Rain Amount
  double FCSn04 = root["daily"][4]["snow"];// Snow Amount
  char FCRain04[5];
  if (!FCRn04 && !FCSn04) {
    FCRn04=0;
  } else {  
    if (!FCRn04) {
      FCRn04 = FCSn04;
    }  
  }
  dtostrf(FCRn04, 4, 0, FCRain04); 

  // Print values.  
  Serial.print("Date Time ");
  Serial.print("Max-Temp/F-Min");
  Serial.print("   Humidity   ");
  Serial.print("   Wind Speed/MPH   ");
  Serial.print(" Direction ");
  Serial.print("   Gust/MPH   ");
  Serial.print(" Rain-Snow ");
  Serial.print("   Sky   ");
  Serial.println("");
  //Current
  Serial.print(FCTimeD00);
  Serial.print(" ");
  Serial.print(FCTemp00);
  Serial.print("    ");
  Serial.print(FCTempL00);
  Serial.print("   ");
  Serial.print(FCHumid00);
  Serial.print("            ");
  Serial.print(FCWSpd00);
  Serial.print("             ");
  Serial.print(FCWDir00);
  Serial.print("          ");
  Serial.print(FCWGst00);
  Serial.print("         ");
  Serial.print(FCRain00); 
  Serial.print(" - ");   
  Serial.print(FCProb00); 
  Serial.print("         ");
  Serial.print(FCSky00);
  Serial.println("");
  //Day 1
  Serial.print(FCTimeD01);
  Serial.print(" ");
  Serial.print(FCTemp01);
  Serial.print("    ");
  Serial.print(FCTempL01);
  Serial.print("   ");
  Serial.print(FCHumid01);
  Serial.print("            ");
  Serial.print(FCWSpd01);
  Serial.print("             ");
  Serial.print(FCWDir01);
  Serial.print("          ");
  Serial.print(FCWGst01);
  Serial.print("         ");
  Serial.print(FCRain01); 
  Serial.print(" - ");   
  Serial.print(FCProb01); 
  Serial.print("         ");
  Serial.print(FCSky01);
  Serial.println("");
  //Day 2
  Serial.print(FCTimeD02);
  Serial.print(" ");
  Serial.print(FCTemp02);
  Serial.print("    ");
  Serial.print(FCTempL02);
  Serial.print("   ");
  Serial.print(FCHumid02);
  Serial.print("            ");
  Serial.print(FCWSpd02);
  Serial.print("             ");
  Serial.print(FCWDir02);
  Serial.print("          ");
  Serial.print(FCWGst02);
  Serial.print("         ");
  Serial.print(FCRain02); 
  Serial.print(" - ");   
  Serial.print(FCProb02); 
  Serial.print("         ");
  Serial.print(FCSky02);
  Serial.println("");
  //Day 3
  Serial.print(FCTimeD03);
  Serial.print(" ");
  Serial.print(FCTemp03);
  Serial.print("    ");
  Serial.print(FCTempL03);
  Serial.print("   ");
  Serial.print(FCHumid03);
  Serial.print("            ");
  Serial.print(FCWSpd03);
  Serial.print("             ");
  Serial.print(FCWDir03);
  Serial.print("          ");
  Serial.print(FCWGst03);
  Serial.print("         ");
  Serial.print(FCRain03); 
  Serial.print(" - ");   
  Serial.print(FCProb03); 
  Serial.print("         ");
  Serial.print(FCSky03);
  Serial.println("");
  //Day 4
  Serial.print(FCTimeD04);
  Serial.print(" ");
  Serial.print(FCTemp04);
  Serial.print("    ");
  Serial.print(FCTempL04);
  Serial.print("   ");
  Serial.print(FCHumid04);
  Serial.print("            ");
  Serial.print(FCWSpd04);
  Serial.print("             ");
  Serial.print(FCWDir04);
  Serial.print("          ");
  Serial.print(FCWGst04);
  Serial.print("         ");
  Serial.print(FCRain04); 
  Serial.print(" - ");   
  Serial.print(FCProb04); 
  Serial.print("         ");
  Serial.print(FCSky04);
  Serial.println("");
  // Display the Forecast Values
  DspForecast(9, 230, FCDOW00, FCTemp00, FCTempL00, FCHumid00, FCProb00, FCRain00); //Day 0 Current Days Forecast
  DspForecast(167, 230, FCDOW01, FCTemp01, FCTempL01, FCHumid01, FCProb01, FCRain01); //Day 1 Forecast
  DspForecast(325, 230, FCDOW02, FCTemp02, FCTempL02, FCHumid02, FCProb02, FCRain02); //Day 2 Forecast
  DspForecast(483, 230, FCDOW03, FCTemp03, FCTempL03, FCHumid03, FCProb03, FCRain03); //Day 3 Forecast
  DspForecast(641, 230, FCDOW04, FCTemp04, FCTempL04, FCHumid04, FCProb04, FCRain04); //Day 4 Forecast
  }
}

void getSunriseSunset() {
  Serial.println("\nStarting connection to server: api.openweathermap.org Sunrise/Sunset...");
  // if you get a connection, report back via serial:
  if (client.connect(server, 80)) {
    Serial.println("connected to server");
    // Make a HTTP request:
    client.print("GET /data/2.5/weather?");
    //client.print("q="+location);
    client.print("id="+location);
    client.print("&appid="+apiKey);
    client.print("&cnt=9");
    client.println("&units=imperial");  // imperial= Fahrenheit, metric= Celsius,default is Kelvin
    client.println("Host: api.openweathermap.org");
    client.println("Connection: close");
    client.println();
  } else {
    Serial.println("************************unable to connect************************");
    client.stop();
    while (WiFi.begin(ssid, pass) != WL_CONNECTED) {
      // unsuccessful, retry in 4 seconds
      Serial.print("failed ... ");
      delay(4000);
      Serial.print("retrying ... ");
    }
  }
  delay(1000);
  String line = "";

  while (client.connected()) {
    line = client.readStringUntil('\n');
    
    //Serial.println(line);
    Serial.print("Line : ");  Serial.println(line);
    Serial.println("parsingValues");

    //create a json buffer where to store the json data
    StaticJsonBuffer<8000> jsonBuffer;  //Arduinojson5
    JsonObject& root = jsonBuffer.parseObject(line);    //Arduinojson5
    if (!root.success()) {
      Serial.println("parseObject() failed");
      return;
    }

  char loSrt[20];
  char loSst[20];
  //get the data from the json tree
  //time_t srt = root["sys"]["sunrise"];
  //root["sys"]["sunrise"] is UTC stringUtcToLocal is not working might be missing TZ info.
  //["sys"]["sunrise"] is in UNIX Format
  String Sunrs = root["sys"]["sunrise"];
  time_t srt = Sunrs.toInt();
  time_t locsrt = myTZ.toLocal(srt, &tcr);
  makeHrMinTimeString(locsrt, loSrt);
  strcpy(loSrt, DtTme); //Copy Global DtTime from makeTimeString to lo

  String Sunst = root["sys"]["sunset"];
  time_t sst = Sunst.toInt();
  time_t locsst = myTZ.toLocal(sst, &tcr);
  makeHrMinTimeString(locsst, loSst);
  strcpy(loSst, DtTme);

  // Print values.
  Serial.print("SunRise ");
  Serial.println(loSrt);
  Serial.print("Sunset ");
  Serial.println(loSst);
  
  char curSunrise[32];
  sprintf(curSunrise, "%02d:%02d", hour(locsrt), minute(locsrt));
  char curSunset[32];
  sprintf(curSunset, "%02d:%02d", hour(locsst), minute(locsst));
  // Print values.
  Serial.print("SunRise ");
  Serial.println(curSunrise);
  Serial.print("Sunset ");
  Serial.println(curSunset);

  // Display the Values
  tft.graphicsMode();
  tft.fillRect(9, 15, 150, 200, MEDTURQUOISE);
  tft.textMode();                 // go to text mode
  tft.textSetCursor(20, 170);
  tft.textTransparent(WHITE);
  tft.textEnlarge(0);
  tft.textWrite("Sunrise");
  tft.textSetCursor(100, 170);
  tft.textWrite(curSunrise);
  //tft.setFont(&FreeSansBold24pt7b);
  //void setCursor(uint16_t x0, uint16_t y0);
  //void setTextColor(uint16_t color); 
  tft.textSetCursor(20, 190);
  tft.textTransparent(WHITE);
  tft.textWrite("Sunset");
  tft.textSetCursor(100, 190);
  tft.textWrite(curSunset);
  tft.graphicsMode();

  }
}

void DspForecast(int vstart, int hstart, char dow[10], char htemp[5], char ltemp[5], char hum[5], char prob[5], char moist[5]){
  //Displays the forecast on display panel in five 150x135 turquose boxes with white lettering
  tft.graphicsMode();
  tft.fillRect((vstart), (hstart), 150, 135, MEDTURQUOISE);
  tft.textMode();                 // go to text mode
  tft.textEnlarge(1);
  tft.textTransparent(WHITE);
  //line 227 For Day of the week / date
  tft.textSetCursor((vstart-1),(hstart-3));
  tft.textWrite(dow);
  //line 255 for Hi and Lo Temperature
  tft.textSetCursor((vstart-1),(hstart+25));
  tft.textWrite("T");
  tft.textSetCursor((vstart+3),(hstart+25));
  tft.textWrite(htemp);
  tft.textSetCursor((vstart+73),(hstart+25));
  tft.textWrite("|");
  tft.textSetCursor((vstart+63),(hstart+25));
  tft.textWrite(ltemp);
  //line 280 For Humidity
  tft.textSetCursor((vstart-1),(hstart+50));
  tft.textWrite("H");
  tft.textSetCursor((vstart+3),(hstart+50));
  tft.textWrite(hum);
  tft.textSetCursor((vstart+101),(hstart+50));
  tft.textWrite("%");
  //line 305 Moisture
  tft.textSetCursor((vstart-1),(hstart+75));
  tft.textWrite("RS");
  //tft.textSetCursor((vstart+3),(hstart+75));
  tft.textSetCursor((vstart+13),(hstart+75));
  tft.textWrite(prob);
  //tft.textSetCursor((vstart+73),(hstart+75));
  tft.textSetCursor((vstart+83),(hstart+75));
  tft.textWrite("|");
  //tft.textSetCursor((vstart+63),(hstart+75));
  tft.textSetCursor((vstart+73),(hstart+75));
  tft.textWrite(moist);
  //line 330 For Wind Speed Direction and Gust
  tft.textSetCursor((vstart-1),(hstart+100));
  tft.textWrite("W");
}

// displays at startup the Sketch running in the Arduino
void display_Running_Sketch (void){
  String the_path = __FILE__;
  //int slash_loc = the_path.lastIndexOf('/');
  int slash_loc = the_path.lastIndexOf('\\');
  String the_cpp_name = the_path.substring(slash_loc+1);
  int dot_loc = the_cpp_name.lastIndexOf('.');
  String the_sketchname = the_cpp_name.substring(0, dot_loc);

  Serial.print("\nArduino is running Sketch: ");
  Serial.println(the_sketchname);
  Serial.print("Compiled on: ");
  Serial.print(__DATE__);
  Serial.print(" at ");
  Serial.println(__TIME__);
}

That does NOT actually reset the processor, and can create lots of problems with port direction settings, timer settings, etc. on rebooting, as none of those are set to processor RESET defaults (as often assumed by boot procedures).

Is there a way to perform a true soft reset?

I don't know about a full software reset for the M4, check the processor data sheet.

It is always possible to use a port output pin to toggle the processor reset line.

Thank You, I will look at the Spec sheet for the M4 and if needed add a pin to the reset pin.

I was also looking at possible adding a external watchdog timer. I have had lightning in the area knock Arduinos offline and watchdog timer can reset them after that.

Searching the Web looking for a way to perform a soft reset per the suggestion of @jremington I look at the data sheet which lead to other searches. I found the following on How to Reset an ARM Cortex-M with Software | MCU on Eclipse

I will see if this causes a successful reset or the M4 will just hang again.

void McuArmTools_SoftwareReset(void)
{
  /* Generic way to request a reset from software for ARM Cortex */
  /* See https://community.freescale.com/thread/99740
     To write to this register, you must write 0x5FA to the VECTKEY field, otherwise the processor ignores the write.
     SYSRESETREQ will cause a system reset asynchronously, so need to wait afterwards.
   */
#if McuLib_CONFIG_CPU_IS_ARM_CORTEX_M
#if McuLib_CONFIG_PEX_SDK_USED
  SCB_AIRCR = SCB_AIRCR_VECTKEY(0x5FA) | SCB_AIRCR_SYSRESETREQ_MASK;
#elif McuLib_CONFIG_SDK_VERSION_USED==McuLib_CONFIG_SDK_S32K
  S32_SCB->AIRCR = S32_SCB_AIRCR_VECTKEY(0x5FA) | S32_SCB_AIRCR_SYSRESETREQ_MASK;
#elif McuLib_CONFIG_SDK_VERSION_USED==McuLib_CONFIG_SDK_RPI_PICO
  #define SCB_AIRCR                          (*((uint32_t*)(0xe0000000+0xed0c)))
  #define SCB_AIRCR_VECTKEY_Pos              16U                                            /*!< SCB AIRCR: VECTKEY Position */
  #define SCB_AIRCR_SYSRESETREQ_Pos           2U                                            /*!< SCB AIRCR: SYSRESETREQ Position */
  #define SCB_AIRCR_SYSRESETREQ_Msk          (1UL << SCB_AIRCR_SYSRESETREQ_Pos)             /*!< SCB AIRCR: SYSRESETREQ Mask */

  SCB_AIRCR = (0x5FA<<SCB_AIRCR_VECTKEY_Pos)|SCB_AIRCR_SYSRESETREQ_Msk;
#else
  SCB->AIRCR = (0x5FA<<SCB_AIRCR_VECTKEY_Pos)|SCB_AIRCR_SYSRESETREQ_Msk;
#endif
#endif
  for(;;) {
    /* wait until reset */
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.