Arduino Code on Boot-Up

I have a lengthy Teensy Program and it works fine until it looses power. If the power is lost I have to reupload the program to get it to function properly. I can power it from an external source and push code over USB and it will run fine. Is there any best practices for code that may loose power. I cannot confirm but I believe that it is related to the Teensey RTC. Hard to Prove since it quits communicating to the world.

/*******************************************************************************
 * DESCRIPTION:
 *
 * This is a program written/hacked by Cory Raisbeck with Whispering Hill Farms
 * to control water to a centralized water storage tank, overflow pond, collect
 * the temp of the cattle tire tank, collect the ambient temp and humidity.  There
 * are way better programs out there I would recommend stealing someone elses; it
 * will almost certainly work better!  If you insist on using this one go ahead make both
 * our days.
 *
 * CONNECTIONS:
 * 
 * Teensy D7  - MD13S Driver PWM Input
 * Teensy D8  - MD13S Driver DIR Input
 * Black Orbit Valve Wire  - MA - pushes mag out
 * Red Orbit Valve Wire - MB - pulls mag in
 * Teensy D10 - Temp and Humidity Sensor

 Libraries Used:
 Cytron Motor Driver - Cytron Corp
 Teensy RTC - Paul
 SimpleDHT

 *******************************************************************************/

 #include <CytronMotorDriver.h>
 #include <TimeLib.h>
 #include <Arduino.h>
 #include <SoftwareSerial.h>
 #include <ArduinoJson.h>
 #include <SimpleDHT.h>
 #include <SD.h>
 #include <SPI.h>

#ifndef WHF_H
#define WHF_H
#endif

//DataLogger
const int chipSelect = BUILTIN_SDCARD;
File dataFile;

//Auto-Off Switch
bool switchpin;  //Delete "=HIGH" after testing************************************************************************************
bool priorswitchpin; 

//Temp and Humidity Sensor
int pinDHT22 = 38;
SimpleDHT22 dht22(pinDHT22);
byte temperature = 0; 
byte humidity = 0;
int err = SimpleDHTErrSuccess;

// Cytron Motor Controller
CytronMD motor(PWM_DIR, 7, 8);
int state; //State the solenoid is set to be in
int priorstate = 99; //State the solenoid was in the last loop

//Configuration Loop Time Variables
bool loopbymin = false; //true for min false for hours.  ************************************************************************************
int intMin; 

//Determine what prints
bool createjson = true;   //true writes json to Serial1  ************************************************************************************
bool createSerial = true;  //true writes Serial to Serial Monitor  ***************************************************************************
bool createDataLogger = true; //true writes Data to DataLoggerr    ***************************************************************************


//Time Variables
int hr; //Hour
int mn; //Minutes
int sc; //Seconds
int previoushour;
int remotetime = 0;
String strDate = "";
String strTime = "";

//WHF Message Variables
bool receivedData = false;
const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;
char tempChars[numChars]; // temporary array for use when parsing
int messageID;
int bulletin;
int FieldBoxID = 100;  //Set to unique number from all other Field Boxes
int bulletinID1 = 1;
int bulletinID2 = 2;
int bulletinID3 = 3;
int remotestate = 10;
int i13;
int i4;
int i5;
int  t0 = 0; //12
int  t1 = 0; //1
int  t2 = 1; //2
int  t3 = 1; //3
int  t4 = 1; //4
int  t5 = 0; //5
int  t6 = 0; //6
int  t7 = 0; //7
int  t8 = 0; //8
int  t9 = 0; //9
int t10 = 1; //10
int t11 = 1; //11
int t12 = 0; //12
int t13 = 0; //1
int t14 = 1; //2
int t15 = 1; //3
int t16 = 0; //4
int t17 = 0; //5
int t18 = 0; //6
int t19 = 0; //7
int t20 = 0; //8
int t21 = 0; //9
int t22 = 0; //10
int t23 = 0; //11
float f3 = 0.0;
float f4 = 0.0;
float f5 = 0.0;


/******************************************************************************************************************************************************
***********************************************************The SETUP Fucntion**************************************************************************
******************************************************************************************************************************************************/

void setup() 
{
  // set the Time library to use Teensy 3.0's RTC to keep time
  setSyncProvider(getTeensy3Time);
  
  Serial.begin(115200);
  Serial1.begin(115200);
  
  // Wait for Arduino Serial Monitor to open
  while (!Serial);
  delay(100);
  Serial.print("Initializing SD card...");

  // Check if SD card is present and can be initialized:
  if (!SD.begin(chipSelect)) 
    {
      Serial.println("Card failed, or not present");
      createDataLogger = false;
    }
  else 
    {
      Serial.println("SD Card Initialized.");
       if (SD.exists("datalog.txt")) 
        {
          SD.remove("datalog.txt");
        }
      // Open a file on SD Card.
      dataFile = SD.open("datalog.txt", FILE_WRITE);
      // if the file is available, write to it:
      if (dataFile) 
        {
          dataFile.println("WHF SD Card Opening");
          Serial.println("Opening datalog.txt"); // if the file isn't open, pop up an error:
        } 
      else 
        {
          Serial.println("error opening datalog.txt"); // if the file isn't open, pop up an error:
          createDataLogger = false;
        } 
    }
  if ((timeStatus()!= timeSet)) 
  {
    Serial.println("Unable to sync with the RTC");
    //Serial1.println("Unable to sync with the RTC; Time set to Jan 1 2015");
    if (createDataLogger == true)
    {
      dataFile.println("Unable to sync with the RTC; Time set to Jan 1 2015"); 
    }
  } 
  else 
  {
    Serial.println("RTC has set the system time");
    Serial.print(month());
    Serial.print("/");
    Serial.print(day());
    Serial.print("/");
    Serial.print(year());
    Serial.print("  "); 
    Serial.print(hour());
    printDigits(minute());
    printDigits(second());

    //Serial1.println("RTC has set the system time");
    if (createDataLogger == true)
    {
    dataFile.println("RTC has set the system time");
    }
  }

//Close the Valve and set the "state" to closed
  motor.setSpeed(-255);  // Close - Black Wire to Cytron MB
  delay(10);
  motor.setSpeed(0);
  state = 0;
  Serial.println("   Set valve to OFF on startup.");
  if (createDataLogger == true)
    {
    dataFile.println("   Set valve to OFF on startup.");
    }
  pinMode(37, INPUT_PULLUP);
  dataFile.close();
}

/******************************************************************************************************************************************************
***********************************************************The LOOP Fucntion***************************************************************************
******************************************************************************************************************************************************/

void loop()
{
  if (createDataLogger == true)
  {
  dataFile = SD.open("datalog.txt", FILE_WRITE);
  }
  if (Serial.available()) 
  {
    time_t t = processSyncMessage();
    if (t != 0) 
    {
      Teensy3Clock.set(t); // set the RTC
      setTime(t);
    }
  }

  if (remotetime > 1709707305)
  {
    Teensy3Clock.set(remotetime);
    remotetime = 0;
  }

//Gets and sets the time for the loop.
  hr = hour();
  mn = minute();
  sc = second();
//Manually Turn Solenoid ON or OFF with switch
  int switchpin = digitalRead(37);
  if (switchpin == LOW && priorswitchpin != LOW) //and prior was high
    { 
          priorstate = 0; 
          state = 1;
          Statechange();
          priorswitchpin = LOW;
          Serial.println("Switch SET TO ON");
                                                  //Serial.println(switchpin);
          if (createjson == true)
            {
              CreateJSON();
            }
          if (createDataLogger == true)
            {
              dataFile.println("Switch SET TO ON");
            }
    }
  else if (switchpin == HIGH)
    { 
      if (priorswitchpin != HIGH)
      {
        Serial.println ("SWITCH SET TO SCHEDULE");
        if ( createDataLogger == true)
          {
            dataFile.println("SWITCH SET TO SCHEDULE");
          }
        priorswitchpin = HIGH;
        Schedule();
        Statechange();
        if (createjson == true)
          {
            CreateJSON();
          }
          
      }

      if ((loopbymin == true) && (remotestate != 0) && (remotestate != 1))
      {
        //Code to switch every 15 seconds the state to improve testing
        if (sc == 0) //Switch to off at zero seconds
          {
            state = 0;
            intMin = 0;
          }
        else if (sc == 15) //Switch to on at 15 seconds
          {
            state = 1;
            intMin = 0;
          }
        else if (sc == 30) //Switch to off at 30 seconds
          {
            state = 0;
            intMin = 0;
          }
        else if (sc == 45) //Switch to on at 45 seconds
          {
            state = 1;
            intMin = 0;
          }

      }
      //Hourly Schedule Planner
      else if ((loopbymin != true) && (remotestate != 0) && (remotestate  != 1))
        {
          Schedule();
        }
      else if ((remotestate == 0) || (remotestate  == 1))
        {
          //Serial.println("Currently Controlled by Remote State.  Not Running a Schedule;  //TESTING ONLY
        }

      //Hourly check of "Solenoid State" and Temp/Humidity
      if ((hr != previoushour) || ((intMin == 0) && (state != priorstate)))
      {
        PrintMonitor();
        if ((state != priorstate))
        {
         Statechange();
        }
        previoushour = hr;
        intMin = 1;
      }
      
      //Data from Radio
      recvWithStartEndMarkers();
      if (newData == true) 
      {
        strcpy(tempChars, receivedChars);
        // this temporary copy is necessary to protect the original data
        // because strtok() used in parseData() replaces the commas with \0
        Serial.print(tempChars);
        if (createDataLogger == true)
          {
            //dataFile.println(tempChars);
          }
        parseData();
        
        //showParsedData();  //Uncomment to serial print radio messages
        remotecommandandcontrol();
        newData = false;
      }
    }
dataFile.close();
}  //END LOOP

/******************************************************************************************************************************************************
***********************************************************Loop Fucntions******************************************************************************
******************************************************************************************************************************************************/

void Schedule()
{
    //Military times from 0001-1159 are am 
    //Military times from 1200-2359 are pm    
    if      (hr == 0 && mn <=59) //12:00 AM
    {
    state = t0;
    }
    else if (hr == 1 && mn <=59) //1:00 AM
    {
    state = t1;
    }   
    else if (hr == 2 && mn <=59) //2:00 AM
    {
    state = t2;
    }    
    else if (hr == 3 && mn <=59) //3:00 AM
    {
    state = t3;
    }   
    else if (hr == 4 && mn <=59) //4:00 AM
    {
    state = t4;
    }    
    else if (hr == 5 && mn <=59) //5:00 AM
    {
    state = t5;
    }  
    else if (hr == 6 && mn <=59) //6:00 AM
    {
    state = t6;
    }   
    else if (hr == 7 && mn <=59) //7:00 AM
    {
    state = t7;
    }    
    else if (hr == 8 && mn <=59) //8:00 AM
    {
    state = t8;
    }   
    else if (hr == 9 && mn <=59) //9:00 AM
    {
    state = t9;
    }    
    else if (hr == 10 && mn <=59) //10:00 AM
    {
    state = t10;
    }
    else if (hr == 11 && mn <=59) //11:00 AM
    {
    state = t11;
    }   
    else if (hr == 12 && mn <=59) //12:00 AM
    {
    state = t12;
    }    
    else if (hr == 13 && mn <=59) //1:00 PM
    {
    state = t13;
    }   
    else if (hr == 14 && mn <=59) //2:00 PM
    {
    state = t14;
    }    
    else if (hr == 15 && mn <=59) //3:00 PM
    {
    state = t15;
    }
    else if (hr == 16 && mn <=59) //4:00 PM
    {
    state = t16;
    }   
    else if (hr == 17 && mn <=59) //5:00 PM
    {
    state = t17;
    }    
    else if (hr == 18 && mn <=59) //6:00 PM
    {
    state = t18;
    }   
    else if (hr == 19 && mn <=59) //7:00 PM
    {
    state = t19;
    }    
    else if (hr == 20 && mn <=59) //8:00 PM
    {
    state = t20;
    }
    else if (hr == 21 && mn <=59) //9:00 PM
    {
    state = t21;
    }   
    else if (hr == 22 && mn <=59) //10:00 PM
    {
    state = t22;
    }    
    else if (hr == 23 && mn <=59) //11:00 PM
    {
    state = t23;
    }
}

void Statechange()
{
     //Turn the Tank ON or OFF
    if (state == 1)
    {
        motor.setSpeed(255);  // Open - Red Wire To Cytron MA
        delay(10);
        motor.setSpeed(0);
    }
    if (state == 0) 
    {
        motor.setSpeed(-255);  // Close - Black Wire to Cytron MB
        delay(10);
        motor.setSpeed(0);
    }
    priorstate = state;
    //Measuretemperatureandhumidity();
}

void Measuretemperatureandhumidity()
{  
    if ((err = dht22.read(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) 
      {
        Serial.print(","); Serial.print(SimpleDHTErrDuration(err));
        return;
      } 
    else
      {     
        Serial.print("   Ambient Tempature = ");
        Serial.print((temperature * 9/5) + 32, 1);
        Serial.print(" deg. F, Humidity = ");
        Serial.print(humidity, 1);
        Serial.print("%");
      }
}

void PrintMonitor()
{
  //SERIAL PRINTING
    if (createSerial == true)
    {
      Serial.print(month());
      Serial.print("/");
      Serial.print(day());
      Serial.print("/");
      Serial.print(year());
      Serial.print("  ");
      if (hr < 10) { Serial.print ("0");}
      Serial.print(hr);
      printDigits(mn);
      printDigits(sc);

      
      if (switchpin == LOW)
      {
          Serial.print("   Mode: Always ON ");
      }
      if (switchpin == HIGH) 
      {
          Serial.print("   Mode: Schedule ");
      }
    
      if (state == 1)
      {
          Serial.print("   Solenoid State: ");
          Serial.print("ON "); 
      }
      if (state == 0) 
      {
          Serial.print("   Solenoid State: ");
          Serial.print("OFF");
      }   

      //Measure temperature and humidity.  
      Measuretemperatureandhumidity();
  
      Serial.print(" Remote State: ");
      Serial.print(remotestate);

      //One Record Per Row on Serial Output
      Serial.println("") ;
    }

    //RADIO PRINTING
    if (createjson == true)
    {
      CreateJSON();
    }

    //SD CARD PRINTING
    if (createDataLogger == true)
    {
      DTtoStr();
      dataFile.print("FieldBoxID: ");
      dataFile.print(FieldBoxID);
      dataFile.print("  ");
      dataFile.print(strDate);
      dataFile.print("  ");
      dataFile.print(strTime);
     
    if (switchpin == LOW)
    {
        dataFile.print("   Mode: Always ON");
    }
    if (switchpin == HIGH) 
    {
        dataFile.print("   Mode: Schedule ");
    }
  
    if (state == 1)
    {
        dataFile.print("   Solenoid State: ");
        dataFile.print("ON "); 
    }
    if (state == 0) 
    {
        dataFile.print("   Solenoid State: ");
        dataFile.print("OFF");
    }   

    //Print temperature and humidity.
    dataFile.print("  Temperature: ");  
    dataFile.print((temperature * 9/5) + 32);
    dataFile.print ("  Humidity: ");
    dataFile.print(humidity);

    //Print RemoteState
    dataFile.print("  Remotestate:  ");
    dataFile.print(remotestate);
    //One Record Per Row on Serial Output
    dataFile.println("") ;
    strDate = "";
    strTime = "";

  }
}

/******************************************************************************************************************************************************
******************************************************OUTGOING MESSAGING FUNCTIONS*********************************************************************
******************************************************************************************************************************************************/

void FB2WHF()
{
  //something
}

//void PringmsgFB2WHF

void       CreateJSON()
{
DTtoStr();
//Create a Json String to send over radio
  JsonDocument doc;
  JsonArray array = doc.to<JsonArray>();

  array.add("^");
  array.add(FieldBoxID);
  array.add(strDate);
  array.add(strTime);
  array.add(state);
  array.add((temperature * 9/5) + 32);
  array.add(humidity);
  array.add(switchpin);
  array.add(remotestate);
  array.add("^");

  Serial1.write("<0x02>");
  Serial1.write(serializeJson(doc, Serial1));
  //Serial1.write(0x0A);
  Serial1.write("<0x03>");

  //Serial.write(serializeJson(doc, Serial));
  //Serial.write(0x0A);
  
  strDate = "";
  strTime = "";

}

/******************************************************************************************************************************************************
******************************************************INCOMING MESSAGING FUNCTIONS*********************************************************************
******************************************************************************************************************************************************/

void recvWithStartEndMarkers() 
{
    static boolean recvInProgress = false;
    static byte ndx = 0;
    char startMarker = '<stx>^';
    char endMarker = '^<etx>';
    char rc;
 
    while (Serial1.available() > 0 && newData == false) 
      {
        rc = Serial1.read();
        //Serial.print(rc);
        if (recvInProgress == true) {
            if (rc != endMarker) {
                receivedChars[ndx] = rc;
                ndx++;
                if (ndx >= numChars) {
                    ndx = numChars - 1;
                }
            }
            else {
                receivedChars[ndx] = '\0'; // terminate the string
                recvInProgress = false;
                ndx = 0;
                newData = true;
            }
      }

        else if (rc == startMarker) {
            recvInProgress = true;
        }
    }
}

void WHF2FB()
{
  /*20 Fields with the 1st being a MessageID# and the secoond the bulletin enlose in ^^
  *MessageID is equal to the FieldBoxID and will always be an integer
  *Bulletin is a message identification to allow multiple messages to be sent to the same Field Box and will always be an integer.
  *The first letter in the variable name will determine if it is a int or float. The sample message shows 9 and 19 being floats.
  *Sample Message: <MessageID, Bulletin, i3,i4,i5,i6,i7,i8,f9,i10,i11,i12,i13,i14,i15,i16,i17,i18,f19,i20>
  */

  //Serial.print("Remote Message (tempChars):  ");
 // Serial.println( tempChars );

  // char * strtokIndx; // this is used by strtok() as an index
  
  // //MessageID
  // strtokIndx = strtok(tempChars,",");        // get the first part - Expects an integer that matches "FieldBoxID" convert this part to an integer
  // if ( strtokIndx == NULL ) return; 
  // messageID = atoi(strtokIndx); 
  // if (messageID != FieldBoxID)
  //   {
  //      messageID = 0;
  //      return;
  //   }

  // //Bulletin
  // strtokIndx = strtok(NULL, ",");         // this continues where the previous call left off
  // if ( strtokIndx == NULL ) return;       // Expects an integer that matches "FieldBoxID" convert this part to an integer
  // bulletin = atoi(strtokIndx);           // Expects an integer that matches "bulletin" convert this part to an integer

  // //Belletin 1 message
  // if ((messageID == FieldBoxID) && (bulletin = bulletinID1)) //This might need a else return.
  //   {  
  //       //Bulletin 1 Field 3
  //       strtokIndx = strtok(NULL, ",");         // this continues where the previous call left off
  //       if ( strtokIndx == NULL ) return;       // Expects an integer that matches "FieldBoxID" convert this part to an integer
  //       remotestate = atoi(strtokIndx);           // Expects an integer that matches "FieldBoxID" convert this part to an integer   
        
  //       //Bulletin 1 Field 4
  //       strtokIndx = strtok(NULL, ",");           // this continues where the previous call left off and is calling an integer
  //       if ( strtokIndx == NULL ) return; 
  //       loopbymin = atoi(strtokIndx);           // USE THIS IF converting to an integer

  //       //Bulletin 1 Field 5
  //       strtokIndx = strtok(NULL, ",");
  //       if ( strtokIndx == NULL ) return; 
  //       i5 = atoi(strtokIndx);        // USE THIS IF converting to a float
  //   }
  // else if ((messageID == FieldBoxID) && (bulletin = bulletinID2))  //Bulletin 2 message parse  Floats
  //   {
  //       //Bulletin 2 Field 3 
  //       strtokIndx = strtok(NULL, ",");
  //       if ( strtokIndx == NULL ) return; 
  //       f3 = atof(strtokIndx);     
  //   }
  // else if (((messageID == FieldBoxID) && (bulletin = bulletinID2)))
  //   {
  //       //Bulletin 3 message parse
  //   }

  // if (messageID != FieldBoxID)
  //   {
  //       Serial.print("INVALID MESSAGE ID:  Expecting: ");
  //       Serial.println(FieldBoxID);
  //   }

  // else
  //   {
  //       if (createSerial == true)
  //       {
  //       PrintmsgWHF2FB();
  //       }
  //   }
}

void parseData() //WILL BE CHANGED TO WHF2FB FUNCTION/LIBRARY
{ 
 // Serial.print("Remote Message (tempChars):  ");
 // Serial.println( tempChars );

  char * strtokIndx; // this is used by strtok() as an index
  //Serial.print(tempChars);
  //MessageID
  strtokIndx = strtok(tempChars,",");      // get the first part - Expects an integer that matches "FieldBoxID" convert this part to an integer
  if ( strtokIndx == NULL ) return; 
  messageID = atoi(strtokIndx); 
  if (messageID != FieldBoxID)
    {
       return;
    }

  //Bulletin
  strtokIndx = strtok(NULL, ",");         // this continues where the previous call left off
  if ( strtokIndx == NULL ) return;      
  bulletin = atoi(strtokIndx);           // Expects an integer that matches "bulletin"

  //Belletin 1 message
  if ((messageID == FieldBoxID) && (bulletin = bulletinID1)) //This might need a else return.
    {  
        //Bulletin 1 Field 3
        strtokIndx = strtok(NULL, ",");         // this continues where the previous call left off
        if ( strtokIndx == NULL ) return;       // Expects an integer that matches "FieldBoxID" convert this part to an integer
        remotestate = atoi(strtokIndx);         // Expects an integer that matches "FieldBoxID" convert this part to an integer
            
        //Bulletin 1 Field 4
        strtokIndx = strtok(NULL, ",");         // this continues where the previous call left off and is calling an integer
        if ( strtokIndx == NULL ) return; 
        loopbymin = atoi(strtokIndx);           // Send 1 or true for Looping by Minutes

        //Bulletin 1 Field 5
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        remotetime = atoi(strtokIndx);          //Send a UNIX timestamp to set the time

                //Bulletin 1 Field 6
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        createSerial = atoi(strtokIndx);          //Send a UNIX timestamp to set the time
    }
  else if ((messageID == FieldBoxID) && (bulletin = bulletinID2))  //Bulletin 2 message parse integers
    {
        //Bulletin 2 Field 3 
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t0 = atoi(strtokIndx);

        //Bulletin 2 Field 4 
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t1 = atoi(strtokIndx);

        //Bulletin 2 Field 5 
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t2 = atoi(strtokIndx);  

        //Bulletin 2 Field 6 
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t3 = atoi(strtokIndx);  

        //Bulletin 2 Field 7 
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t4 = atoi(strtokIndx);  

        //Bulletin 2 Field 8
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t5 = atoi(strtokIndx);  

        //Bulletin 2 Field 9
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t6 = atoi(strtokIndx);  

        //Bulletin 2 Field 10
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t7 = atoi(strtokIndx);  

        //Bulletin 2 Field 11
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t8 = atoi(strtokIndx);  

        //Bulletin 2 Field 12
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t9 = atoi(strtokIndx);  

        //Bulletin 2 Field 13
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t10 = atoi(strtokIndx);  

        //Bulletin 2 Field 14
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t11 = atoi(strtokIndx);  

        //Bulletin 2 Field 15
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t12 = atoi(strtokIndx);  

        //Bulletin 2 Field 16
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t13 = atoi(strtokIndx);  

        //Bulletin 2 Field 17
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t14 = atoi(strtokIndx);  

        //Bulletin 2 Field 18
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t15 = atoi(strtokIndx);  

        //Bulletin 2 Field 19
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t16 = atoi(strtokIndx);  

        //Bulletin 2 Field 20
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t17 = atoi(strtokIndx);  

    }
  else if ((messageID == FieldBoxID) && (bulletin = bulletinID3))
    {
        //Bulletin 3 Field 3 
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t18 = atoi(strtokIndx);

        //Bulletin 3 Field 4 
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t19 = atoi(strtokIndx);

        //Bulletin 3 Field 5 
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t20 = atoi(strtokIndx);  

        //Bulletin 3 Field 6 
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t21 = atoi(strtokIndx);  

        //Bulletin 3 Field 7 
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t22 = atoi(strtokIndx);  

        //Bulletin 3 Field 8
        strtokIndx = strtok(NULL, ",");
        if ( strtokIndx == NULL ) return; 
        t23 = atoi(strtokIndx);  
    }
}

void PrintMsg_WHF2FB ()
{
     
}

void showParsedData() //WILL BE CHANGED TO WHF2FB FUNCTION/LIBRARY//Needs a bunch of work with the new message layout 
{
    if (messageID != FieldBoxID)
    {
       Serial.print("INVALID MESSAGE ID:  Expecting: ");
       Serial.println(FieldBoxID);
    }

    else
    {
        Serial.print("MessageID: ");
        Serial.println(messageID);
        Serial.print("Bulletin: ");
        Serial.println(bulletin);
        Serial.print("Field3 (remotestate): ");
        Serial.println(remotestate);
        Serial.print("i4: (intMin) ");
        Serial.println(intMin);
        Serial.print("Field5: ");
        Serial.println(i5);
     }
    

}

void remotecommandandcontrol()
{
 if (messageID == FieldBoxID)
    {
        if (remotestate > 1)
        {
          priorstate = 9; //Set to 9 so the schedule runs
          Schedule();
        }
        if (remotestate == 0)
        {
          priorstate = 1; 
          state = 0;
        }
        if (remotestate == 1)
        {
          priorstate = 0;
          state = 1;
        }
        Statechange();
        //Serial.println("Message ID let me into the Remote Command and Control function");
        if (createjson == true)
          {
            //Serial.println("Message ID let me create the JSON");
            CreateJSON();
          }

          

    }
}


/******************************************************************************************************************************************************
*************************************************TEENSY RTC FUNCTIONS**********************************************************************************
******************************************************************************************************************************************************/

time_t getTeensy3Time()
{
  return Teensy3Clock.get();
}

/*  code to process time sync messages from the serial port   */
#define TIME_HEADER  "T"   // Header tag for serial time sync message

unsigned long processSyncMessage() 
{
  unsigned long pctime = 0L;
  const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013 

  if(Serial.find(TIME_HEADER)) {
     Serial.println("PCNate is Great");
     pctime = Serial.parseInt();
     return pctime;
     if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
       pctime = 0L; // return 0 to indicate that the time is not valid
     }
  }
  return pctime;
}

void printDigits(int digits)
{
  // utility function for digital clock display: prints preceding colon and leading 0
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

void DTtoStr()
{
    strDate = strDate.concat(month()); //Create a String for DATE  
  strDate.concat("/");
  strDate.concat(day());
  strDate.concat("/");
  strDate.concat(year());

  //Create a String for Time  
  strTime = strTime.concat(hr);
  strTime.concat(":");
  if (mn < 10)
  {
    strTime.concat("0");
    strTime.concat(mn);
    strTime.concat(":");
    if (sc <10)
    {
        strTime.concat("0");
        strTime.concat(sc);
    }
    else 
    {
        strTime.concat(sc);
    }
  }
  else
  {
    strTime.concat(mn);
    strTime.concat(":");
    if (sc <10)
    {
        strTime.concat("0");
        strTime.concat(sc);
    }
    else 
    {
        strTime.concat(sc);
    }
  }
}



I was typing two and three. With the long code I made 3 seperate post.

The code controls a water setup for cattle. Next to a water trough (TireTank) is a large tank that fills from the well and has an overflow to a pond. We pump water from the tank to a mobile water cart during the summer months and in the winter months the cattle drink directly from the TireTank.

A MDS13 contols a latching valve that turns the water on an off to the storage tank. The valve is 12 volts and the MDS13 motor driver acts like a relay only allows me to switch the state and then stop powering the solenoid after a few milliseconds. The valve latches using a small magnet.

I also read the temp and humity of the air and record those readings.

This data is sent over a XBEE radio back to a central PI that collects the radio messages and using python uploads them to a google sheet that acts like a dashboard, reporting the different status of the different tanks. Each tank is identifed with a unique FieldBox.

We use the Teensy onboard RTC however do not have a seperate backup power battery for it. The Teensy itself is powered by a 7AH battery that is charged by solar power. Up untill last nite the panel (no charge controller) was directly connected to the battery for charging. After three or four days the battery would end up dead. The total amp draw of a Teesny is almost zero so i was concerned that the panel was draining the battery at night. I installed a diode to insure this isnt happening any longer.

Besides the fact that the battery would go dead in the morning when the sun came out the Teensy rebooted but never again acted correctly. If I went out to it with my PC in the field and uploaded the program again while on good battery and then unplugged the USB cable everything would work normally.

I added a SD card to try to get addtional logging but still havent closed the loop on the issue. I belive it is related to not getting a PC_TIME in the code to properly set the Teensy time.

Looking for advice.

I will try and post another post with the diagram. It all is moutned on a custom PCB.

I have to confirm what board version I have installed at this particular fieldbox so this may be a revision newer or older but should get us close.

What kind of Teensy?

Why no battery on Vbat? I have a Teensy 4.x with a CR2032 on Vbat and it keeps time just fine even when the main power has been off for days. And the battery itself has lasted between 17 and 23 months so far.

I understand that but when I look at the code if it cant get pctime it should use a default time as I read it, but the board never seems to act right. Things just dont work as expected. Other idea is if it maybe insist it connect to the internet for a library or something to update but I just do not know. Im asking open ended questions trying to "Jog an Idea". Im sorry in advance.

Because...................:slight_smile:

I didnt think of it untill I have the PCB built. I honestly can do that if that is my problem.

Teensy 4.1 We use it almost exlcusively because of speed and pins. I am told there is a SMT board now that I would consider for the PCB but I like to be able to pull the teensy in the field and swwap it with another one I updated some code on in my shop so I am not sure about switching at this time. I buy them from PROTO SUPPLIES pre soldered and use the same ones we use for AGOPENGPS.

It calls a function in the setup to get Teensy time. The function is the third from the bottom. Although when I just looked again it might not be setting a default time if not connected to the PC.

Its not. That makes better sense now.

If I default to time if the RTC cant set a pctime, I could potentially get a time over the radio. Not sure exactly how to do this automatically but I do have a remote time in my radio message that I tested that I may be able to send it a message, although it seems like I could broadcast a time message "T" and it would sync????????

if ((timeStatus()!= timeSet)) 
  {

SET A DEFAULT TIME HERE    

   Serial.println("Unable to sync with the RTC");
    //Serial1.println("Unable to sync with the RTC; Time set to Jan 1 2015");
    if (createDataLogger == true)
    {
      dataFile.println("Unable to sync with the RTC; Time set to Jan 1 2015"); 
    }
  } 
  else 

Thank you very much. I will try this out tonight when I get to the field box and update you. Appreciate it sometimes you just need to be able to talk it through.

Can I ask one more question related to my code that I havent been able to locate an answer on how to properly fix?

I get a warning:
warning: unsigned conversion from 'int' to 'char' changes value from '1954037342' to ''^'' [-Woverflow] 643 | char startMarker = '<stx>^';
I understand it wants 1 single character in the startMarker. Is there syntax that allows it to handle more than 1 character. It works as programed but gives error messages that make debugging a PIA every time looking through the errors.

As I see it, you've got 2 problems. The first is why are you losing power. The second is why your program is misbehaving when it powers up and the RTC isn't set. If I recall correctly (and it's been a while since I dug into the T4 RTC code), if the SRTC isn't running on startup, it gets initialized with a default date of Jan 1, 2019.

The very last thing that the Teensy Loader program does when it's uploaded your sketch is to pass the current time to the loader, which then sets the RTC before running your sketch. Since the RTC has been set by the loader, timeStatus() will return timeSet.

When your board looses power, without a battery on Vbat, the RTC loses its time. So when power is reapplied and your sketch runs, timeStatus() will not return timeSet.

I see you have a processSyncMessage function that will try and set the RTC from a time string on the Serial port, but there's not going to be anything connected to the Serial port to send the current time.

I wasI was able to do some testing this weekend and found several issues that you folks ideas spurred. This code specifically:

  // Wait for Arduino Serial Monitor to open
  while (!Serial);
  delay(100);

was my main problem. If the Teensy wasnt plugged into the computer the program would never load past this DoWhile Loop. Once I got that part addressed it would boot with the default time. The RTC has a default time if the clock fails to get one. You then can udate the time sending it a "T"UTC message. Remember to adjust your UTC to accomidate your timezone or you will be at GMT.

Thanks again.

I did but not the way I had wanted. I simply went to one character. I found an example of how Teensy uses "T" for a header and was going to dig in and see how they did it. It is on my list. I have it in another program also where the ending string is /n/n/r and if I try to change it to an array or index it doesnt work but if I program it with the warning it works.

I agree. I will figure it out.

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