Hardware RTC and Widget

I’m looking to send data from my physical RTC connected to my Arduino to my Blynk app. It is important that my program rely on a physical clock to ensure fluid time keeping in the event of network disconnections. Is it possible to send this kind of data to one of the widgets? My thought was to use terminal.println, but after compile failures and research, I’m lead to believe this is just for generic prewritten words and numbers. Any insights?


    #include "SPI.h"
    #include "Ethernet.h"
    #include "BlynkSimpleEthernet.h"
    #include "Wire.h"
    #include "DHT.h"                
    #include "SimpleTimer.h"          
    #include "RTClib.h" // RealTimeClock Library for DS1307 and DS3231

//**********DEFINE PINS****************************
    #define DHTPIN 13    //  DHT22 sensor connected to digital pin 13, there is a 1k pullup resistor from +5V to pin 13                            
    #define Relay_A  30  // relay 1 - Mega Pin 30  //  Lights
    #define Relay_B  31  // relay 2 - Mega Pin 31  //  Feed Pump(s)
    #define Relay_C  32  // relay 3 - Mega Pin 32  //  ------------
    #define Relay_D  33  // relay 4 - Mega Pin 33  //  ------------
    #define Relay_E  34  // relay 5 - Mega Pin 34  //  Exhaust Fan
    #define Relay_F  35  // relay 6 - Mega Pin 35  //  Heater
    #define Relay_G  37  // relay 7 - Mega Pin 36  //  Dehumidifier
    #define Relay_H  36  // relay 8 - Mega Pin 37  //  ------------
    
//*******Sensor Model********************************    
    #define DHTTYPE DHT22
    
//*******Sets Relays to Off Position*****************
    #define TURN_ON 0 // TURN_ON and TURN_OFF are defined to account for Active High relays
    #define TURN_OFF 1 // Used to switch relay states for on/off of AC devices

//*******DHT Reference Values - CHANGE THESE TO MANAGE YOUR ROOM'S CLIMATE - //
    byte hiMaxTemp = 90;   // temp that triggers heat removal fan on
    byte lowMaxTemp = 75;  // temp that triggers heat removal fan off 
    byte hiMinTemp = 70;   // temp that triggers heater on
    byte lowMinTemp = 60;  // temp that triggers heater off
    byte hiHum = 75;       // High humidity value that triggers dehumidifier on
    byte lowHum = 70;      // Low humidity value that triggers dehumidifier off

    RTC_DS1307 RTC;
    float UTCOffset = -5.0;    // Your timezone relative to UTC (http://en.wikipedia.org/wiki/UTC_offset)

    char auth[] = "abc123";

    DHT dht(DHTPIN, DHTTYPE);
    byte h;  
    byte f;  

    //WidgetTerminal terminal(V3);
                
    SimpleTimer timer;


    void setup() {
      Serial.begin(9600);  
      //Serial2.begin() // For other baud rates
      //Serial3.begin() // For other baud rates          
      Blynk.begin(auth);
      pinMode(DHTPIN, OUTPUT);           
      dht.begin();
      timer.setInterval(10000L, climateCheck); // 10 seconds between sensor readings

  
//---(Set pins 30-37 as outputs )----
      pinMode(Relay_A, OUTPUT);
      pinMode(Relay_B, OUTPUT);
      pinMode(Relay_C, OUTPUT);
      pinMode(Relay_D, OUTPUT);
      pinMode(Relay_E, OUTPUT);
      pinMode(Relay_F, OUTPUT);
      pinMode(Relay_G, OUTPUT);
      pinMode(Relay_H, OUTPUT);

      digitalWrite(Relay_A, TURN_OFF);  //  This ensures relays do not actuate until called upon
      digitalWrite(Relay_B, TURN_OFF);
      digitalWrite(Relay_C, TURN_OFF);
      digitalWrite(Relay_D, TURN_OFF);
      digitalWrite(Relay_E, TURN_OFF);
      digitalWrite(Relay_F, TURN_OFF);
      digitalWrite(Relay_G, TURN_OFF);
      digitalWrite(Relay_H, TURN_OFF);

      RTC.begin();
      RTC.adjust(DateTime(__DATE__, __TIME__));  /* This captures the time from the computer that is uploading sketch to
                                             //Arduino, so ensure that the uploading computer has the correct time. */
      delay(1000);
    }


    void loop() 
    {
      Blynk.run();
      timer.run();
    }

    void climateCheck()
    {
      h = dht.readHumidity();
      f = dht.readTemperature(true);

      Blynk.virtualWrite(V1, f);    //  Set Virtual Pin 1 frequency to PUSH in Blynk app
      Blynk.virtualWrite(V2, h);      //  Set Virtual Pin 2 frequency to PUSH in Blynk app
    
    }

    void RTCdisplay()
    { 
//**********************************************************************************//
//****** Setting Time and testing to display 24 hour format as 12 hour format ******//
//**********************************************************************************//
      DateTime now = RTC.now();  // reads time at beginning of loop
  
      byte twelveHour = now.hour() - 12; // Variable used to display 13+ hours in 12 hour format
      byte zeroHour = 12;                // Variable use to convert "0" zero hour to display it as 12:00+
  
      if (now.hour() == 0)  // First we test if the hour reads "0"
    { 
      //terminal.println((zeroHour) ":" (now.minute) ":" (now.second) "AM");
      //terminal.flush();             
      Serial.print(zeroHour);  // if yes, serial print a "12" instead
      Serial.print(':');
      Serial.print(now.minute(), DEC);
      Serial.print(':');
      Serial.print(now.second(), DEC);
      Serial.print(' ');
      Serial.println (F("AM"));
    }
      else if (now.hour() >= 13)  // if no, Second we test if the hour reads "13 or more"
    { 
      //terminal.println((twelveHour) ":" (now.minute) ":" (now.second) "PM");
      //terminal.flush();      
      Serial.print(twelveHour);   // if yes, serial print that current hour minus 12
      Serial.print(':');
      Serial.print(now.minute(), DEC);
      Serial.print(':');
      Serial.print(now.second(), DEC);
      Serial.print(' ');
      Serial.println (F("PM"));
    }
      else 
    {
      //terminal.println((now.hour) ":" (now.minute) ":" (now.second) "AM");
      //terminal.flush();
      Serial.print(now.hour(), DEC);    // if no, Third we conclude that the am hours are being displayed correctly.
      Serial.print(':');
      Serial.print(now.minute(), DEC);
      Serial.print(':');
      Serial.print(now.second(), DEC);
      Serial.print(' ');
      Serial.println (F("AM"));
    }
    { 
      //terminal.println((now.month, DEC) "/" (now.day, DEC) "/" (now.year, DEC));
      //terminal.flush();
      Serial.print(now.month(), DEC);
      Serial.print('/');
      Serial.print(now.day(), DEC);
      Serial.print('/');
      Serial.println(now.year(), DEC);
      Serial.println();
    }
  
//******************************************************************************************************//
//***** Alarms for Relays A-D.  Adjust hours and minutes in accordance with 24 hour time format. *******//
//***** Create tests where true is ON time and false is OFF time. **************************************//
//***** 18/6 Light Cycle - RELAY_A *********************************************************************//
  
      boolean relayAstate = false;
      if (now.hour() >= 6) relayAstate = true; //  The test is true from 6-23, and false from 0-5 (18/6)
      if (relayAstate == true)
    { 
      digitalWrite(Relay_A, TURN_ON);
      Serial.print("\t");
      Serial.print(F("Vegetative Lights On"));  //  Text printed to serial monitor
      Serial.print("\t");
      Serial.println();
    }
      else
    {                                              
      digitalWrite(Relay_A, TURN_OFF);
      Serial.print("\t");
      Serial.println(F("Vegitative Lights OFf"));  //  Text printed to serial monitor
      Serial.print("\t");
      Serial.println();
    }
//*********************************** FEED TIMEs - RELAY_B ******************************************//
// By testing hour once and minute twice, we isolate the "on" time and the duration it is "on". *****//
// If the Boolean becomes true, D31 is HIGH until Boolean becomes false again. **********************//
      boolean relayBstate = false;
      if (now.hour() == 9 && now.minute() >= 0 && now.minute() < 10) relayBstate = true;    //9:00 am - 10mins
      if (now.hour() == 15 && now.minute() >= 30 && now.minute() < 40) relayBstate = true;  //3:30 pm - 10mins
      if (now.hour() == 22 && now.minute() >= 30 && now.minute() < 33) relayBstate = true;  //10:30pm - 03mins
      if (relayBstate == true)
    {  
      digitalWrite(Relay_B, TURN_ON);
      Serial.print("\t");
      Serial.println(F("Feeding Plants"));  //  Text printed to serial monitor
      Serial.print("\t");
      Serial.println();  
    }
      else
    {  
      digitalWrite(Relay_B, TURN_OFF);
    }
  }
//********************** Unassigned - RELAY_C *******************************//
  
//********************** Unassigned - RELAY_D *******************************//

    
  
//******************************** RELAYS E^F^G^H ****************************************//
//******* Testing the DHT22 sensor temperature in Fahrenheit and humidity in Percent and *// 
//******* actuating Relays based upon those values ***************************************//
//****************************************************************************************//
  void climaticEvents()
  {    
      h = dht.readHumidity();  
      f = dht.readTemperature(true);  
      if (isnan(f) || isnan(h)) 

    {
      Serial.println("Failed to read from DHT");
    }
      else
    {
      float hi = dht.computeHeatIndex(f, h);
      Serial.print(F("Fahrenheit: "));
      Serial.print(f);
      Serial.println("*\t");
      Serial.print(F("Humidity: "));
      Serial.print(h);
      Serial.println("%\t");

    }
//********************************************************************************//
//   Tests temp & humidity to see if preset values are exceed.
//   If exceeded, a relay is trigger high to power an exhaust fan or heater.
//**************************** REMOVING HEAT *************************************//
      if (f >= hiMaxTemp)  //if "f" is greater than or equal to hiMaxTemp,
    {
      digitalWrite(Relay_E, TURN_ON);  // TURN_ON relayE (fan).
      Serial.print("\t");
      Serial.println(F("Exhausting the heat!")); //  Text printed to serial monitor
      Serial.print("\t");
      Serial.println();
    }
      else if (f <= lowMaxTemp)  //  or else if "f" is less than or equal to lowMaxTemp
    {
      digitalWrite(Relay_E, TURN_OFF); //  TURN_OFF relay E.
    }
//****************************** ADDING HEAT *******************************//
      if (f <= lowMinTemp)   
    {
      digitalWrite(Relay_F, TURN_ON);  // (heater)
      Serial.print("\t");
      Serial.println(F("Warming the room!"));  
      Serial.print("\t");
      Serial.println();
    }
      else if(f >= hiMinTemp);
    {
      digitalWrite(Relay_F, TURN_OFF); 
    }
//**************************** REMOVING HUMIDITY *******************//
      if (h >= hiHum) 
    {
      digitalWrite(Relay_G, TURN_ON);  // (dehumidifier)
      Serial.print("\t");
      Serial.println(F("Drying the air!"));  
      Serial.print("\t");
      Serial.println();
    }
      else if (h <= lowHum)
    {
      digitalWrite(Relay_G, TURN_OFF);  
    }
}

I’m confused- you have a physical RTC attached to your arduino, and you want to be able to send the RTC data to a widget, but also retrieve it in the event of a network failure? :unamused:

I feel like you should take a look at the timeAlarms library.

https://www.pjrc.com/teensy/td_libs_TimeAlarms.html

Secondly, if you know your system will eventually recover and have internet access again/ be able to recover those stored RTC values, you should just use (or just incorporate) the actual Blynk RTC widget. It’s awesome.

If for instance, the network is disconnected for days, it will be as long before the Arduino can execute a time based command. Also, when first researching how time is kept with an Arduino, I was lead to believe that counting off days weeks and months in milliseconds is relatively inaccurate and the register that keeps track of those numbers will eventually max out and reset. An RTC is a battery powered component that will keep ticking even if I lose both networking and electricity. What’s more, I went to the extent of cutting the RESET-EN trace on my Arduino to ensure that even if power is lost for any period, the Arduino does not reset upon regaining power and the sketch will simply look at the clock, see what time it is, and execute any commands if needed.

Does anyone know if I can send this time through the Blynk server to be displayed on my app?

It’s very simple. Just combine your physycal RTC values into one string and send it to Virtual Pin of LCD or Terminal widget every second or minute

Or use a couple of Value Display widgets with Virtual Pins as well. Check PushData example sketch to see how it’s done.

Thank you Pavel. I will search for the method of collecting my RTC readings into a string. Once I get that knowledge, would I then use Blynk.virtualWrite() to send the string?

Surely, just remember not to use Blynk.virtualWrite() in the main loop. It should be a timed event. Check the example on how to use timer:

I set the timer to get RTC readings every 10 seconds,

` SimpleTimer timer;

void setup() {
  Serial.begin(9600);  
  //Serial2.begin() // For other baud rates
  //Serial3.begin() // For other baud rates          
  Blynk.begin(auth);
  pinMode(DHTPIN, OUTPUT);           
  dht.begin();
  timer.setInterval(10000L, climateCheck); // 10 seconds between sensor readings
  timer.setInterval(10000L, RTCdisplay); // 10 seconds between sensor readings

`
and channeled all RTC data to fit into strings,

` DateTime now = RTC.now(); // reads time at beginning of loop

  byte twelveHour = now.hour() - 12; // Variable used to display 13+ hours in 12 hour format
  byte zeroHour = 12;                // Variable use to convert "0" zero hour to display it as 12:00+
  byte displayHour;
  //char* meridian[]{"AM", "PM"};

  if (now.hour() == 0)  // First we test if the hour reads "0"
{ 
  displayHour = zeroHour;
  //meridian[] = "AM";         
}
  else if (now.hour() >= 13)  // if no, Second we test if the hour reads "13 or more"
{ 
  displayHour = twelveHour;
  //meridian[] = "PM";      
}
  else 
{ 
  displayHour = now.hour();
  //meridian[] = "AM"; 
}
{ 
  char timeStamp[6] = {displayHour, ':', now.minute(), ':', now.second()};
  char dateStamp[6] = {now.month(), '/', now.day(), '/', now.year()};
  Blynk.virtualWrite(V3, timeStamp);
  Blynk.virtualWrite(V4, dateStamp);`

and though it all compiles and uploads to the board, the RTC data is still not pushing anything into a graph or terminal widget. I can’t fathom why as the DHT22 data is still being sent every 10 seconds and the relays trigger when called to do so, which means the Blynk side is working properly.

Can you spot any defects in the code?

I have worked out all the bugs that were in my code regarding collecting the RTC outputs and appending them into a string. I’ve verified the strings with Serial.print. I am now trying to print these strings to the LCD widget, but still no display. The DHT readings go to the app just fine, and also the relays can be toggled, but still no display of time from my arduino’s RTC. Any suggestions?


    #include <SPI.h>
    #include <Ethernet.h>
    #include <BlynkSimpleEthernet.h>
    #include <Wire.h>                 
    #include "DHT.h"                
    #include <SimpleTimer.h>          
    #include "RTClib.h" // RTC Library for DS1307 and DS3231
    #define BLYNK_PRINT Serial
    #include <SPI.h>

//**********DEFINE PINS****************************
    #define DHTPIN 13    //  DHT22 sensor connected to digital pin 13, there is a 1k pullup resistor from +5V to pin 13                            
    
//*******Sensor Model********************************    
    #define DHTTYPE DHT22


    RTC_DS1307 RTC;
    float UTCOffset = -5.0;    // Your timezone relative to UTC (http://en.wikipedia.org/wiki/UTC_offset)

    char auth[] = "YourAuth";

    DHT dht(DHTPIN, DHTTYPE);
    byte h;  
    byte f;  
                
    SimpleTimer timer;


    void setup() {
      Serial.begin(9600);  
      //Serial2.begin() // For other baud rates
      //Serial3.begin() // For other baud rates          
      Blynk.begin(auth);
      pinMode(DHTPIN, OUTPUT);           
      dht.begin();
      timer.setInterval(10000L, climateCheck); // 10 seconds between sensor readings
      timer.setInterval(10000L, RTCdisplay); // 10 seconds between sensor readings

      RTC.adjust(DateTime(__DATE__, __TIME__));  // This captures the time from the computer that is uploading sketch to
      RTC.begin();                                        //Arduino, so ensure that the uploading computer has the correct time. */
      //delay(1000);
    }


    void loop() 
    {
      Blynk.run();
      timer.run();
    }

    void climateCheck()
    {
      h = dht.readHumidity();
      f = dht.readTemperature(true);

      Blynk.virtualWrite(V1, f);    //  Set Virtual Pin 1 frequency to PUSH in Blynk app
      Blynk.virtualWrite(V2, h);      //  Set Virtual Pin 2 frequency to PUSH in Blynk app
      //Serial.print(f);
      //Serial.print(h);
    
    }

    void RTCdisplay()
    { 

      DateTime now = RTC.now();  // reads time at beginning of loop
  
      byte twelveHour = now.hour() - 12; // Variable used to display 13+ hours in 12 hour format
      byte zeroHour = 12;                // Variable use to convert "0" zero hour to display it as 12:00+
      byte displayHour;
      byte MIN = now.minute();
      byte SEC = now.second();
      char* meridian;
  
      if (now.hour() == 0)  // First we test if the hour reads "0"
    { 
      displayHour = zeroHour;
      meridian = "AM";         
    }
      else if (now.hour() >= 13)  // if no, Second we test if the hour reads "13 or more"
    { 
      displayHour = twelveHour;
      meridian = "PM";      
    }
      else 
    { 
      displayHour = now.hour();
      meridian = "AM"; 
    }
     
      char timeStamp[11];
      char dateStamp[11];
      sprintf(timeStamp, "%02d:%02d:%02d-%02s", displayHour, MIN, SEC, meridian);
      sprintf(dateStamp, "%02d/%02d/%04d", now.month(), now.day(), now.year());
    {
            
      WidgetLCD timeStampLCD(V3);
      WidgetLCD dateStampLCD(V4);
      timeStampLCD.clear(); //Use it to clear the LCD Widget
      dateStampLCD.clear();
      timeStampLCD.print(4, 0, timeStamp); // use: (position X: 0-15, position Y: 0-1, "Message you want to print")
      dateStampLCD.print(4, 1, dateStamp);
      //Serial.println(timeStamp);
      //Serial.println(dateStamp);
    }

    }

Code snippet should be formatted. Edit your post!

Wrap the code by adding 3 Backtick: ``` symbols:

Example:

 ``` cpp <--put 3 backticks BEFORE your code starts  (cpp means C++ language) 

   //Put your code here
   //..................
   //..................

 ``` <--insert 3 backticks AFTER your code

**This makes your code readable and with highlighted syntax, like this:**
//comment goes here 
void helloWorld() { 
   String message =  "hello" + "world"; 
}

@myggle your sketch is so badly formatted in this thread it is hard to follow but it looks like you have not defined the widgets in the correct place. Shouldn’t they be defined at the start of the sketch rather than in some random place?

  WidgetLCD timeStampLCD(V3);
  WidgetLCD dateStampLCD(V4); 

If this is not the problem format the sketch and we will try to find the problem.

Thank you guys for getting me right with the formatting on the site. My sketch is now formatted, unnecessarily code has been removed and the rest is now readable.

The reason I moved all of the code from void setup() into a function is because this is not an operation that I wanted to run just once. That aside however, I am finding that I am unsuccessful with the LCD example linked from your “DOCs” page, so maybe that would be a better place for me to start debugging my problems. I confirmed that I still have a valid network connection and power as I am able to power cycle the attached relays without any added code, but the LCD with V1 assigned into the first of the 2 fields returns no value or text when I tick the play button in the app. Aside from changing my auth key, I made no other edits to the example sketch.

Once again, sorry about the poor formatting of my previous sketch.

Edit - I’ve tried reading frequency set to both PUSH and 1 sec