Go Down

Topic: Turn LED on with RTC (Read 9711 times) previous topic - next topic

Keklja

Halo
I would like to program Arduino so it can switch on relay (relay will switch on light in the room) each day at 18:00 and switch off at 22:00.
I have Arduino UNO and DS3231 RTC. Im not so familiar with RTC but i did find the skech for RTC:

Code: [Select]
#include <TimeLib.h>
#include <Wire.h>
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t

void setup()  {
  Serial.begin(9600);
  while (!Serial) ; // wait until Arduino Serial Monitor opens
  setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if(timeStatus()!= timeSet)
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");     
}

void loop()
{
  if (timeStatus() == timeSet) {
    digitalClockDisplay();
  } else {
    Serial.println("The time has not been set.  Please run the Time");
    Serial.println("TimeRTCSet example, or DS1307RTC SetTime example.");
    Serial.println();
    delay(4000);
  }
  delay(1000);
}

void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year());
  Serial.println();
}

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);
}


How can RTC or Serial command trigger Arduino to set lets say DO3 to HIGH?

Thanx

cattledog

#1
Nov 11, 2019, 09:40 pm Last Edit: Nov 11, 2019, 09:41 pm by cattledog
Quote
I would like to program Arduino so it can switch on relay (relay will switch on light in the room) each day at 18:00 and switch off at 22:00.
Quote
How can RTC or Serial command trigger Arduino to set lets say DO3 to HIGH?
Your sketch is actually using the functions of the Time Library to access the time. The Time Library is referenced to external time with the RTC, and then periodically synchronized with the RTC to improve the timekeeping of the internal oscillator. This is a good approach.

At its's most basic and simple, you could add two conditional tests

Code: [Select]
if(hour() == 18) digitalWrite(3, HIGH);
if(hour() == 22) digitalWrite(3, LOW);


There are several refinements to optimize the code to minimize the time checking and redundant digitalWrite() commands, but the basics can get you going.

Nick_Pyner

There is a TimeAlarms library which is good for all this stuff.

Keklja

Your sketch is actually using the functions of the Time Library to access the time. The Time Library is referenced to external time with the RTC, and then periodically synchronized with the RTC to improve the timekeeping of the internal oscillator. This is a good approach.

At its's most basic and simple, you could add two conditional tests

Code: [Select]
if(hour() == 18) digitalWrite(3, HIGH);
if(hour() == 22) digitalWrite(3, LOW);


There are several refinements to optimize the code to minimize the time checking and redundant digitalWrite() commands, but the basics can get you going.
It work. Thank you.
I didnt know how to save Serial data but it is really easy. Now i can continue with my work

Keklja

So I have different problem now. On 12.Nov evrything was fine and working. Because I need 18 DO I took MEGA and connect RTC on it. I started the program but time is not right. It is showing 11.11.19 and -1hour differance. Last time I only started the skatch (on UNO) and the time was from the start OK. Now it is 4 days and 1 hour in the past...

Keklja

OK. I mannage to set the time again (with DS1307RTC->SetTime sketch). But way did it lose time in the first place?

I'm making a Project that will count how many days is left till Christmas and with the help of RTC it need to turn on specific LED between 18:00 - 22:00 and on LCD show how many days is left.

What can I do to stop RTC from loosing time?

cattledog

I would think that the RTC is not running on battery power, and keeping time when the Arduino is not connected to a power source.

Is the battery new? What voltage is it reading? Is it installed so you can see the +?

When you were on the UNO, could you turn the Arduino off, wait a period of time, and see the correct time?

Do you have a multimeter, and can check if Vbat is present at the chip? You will need to look at a data sheet for the ds3231 to check which pin of the chip that is. Sometimes there have been defective battery holders or traces on the module.


Keklja

The last half a hour arduino was disconneted. I just look at the time. It is OK. Tommorow I will see if the time OK is and test the battery

Keklja

#8
Nov 16, 2019, 08:40 pm Last Edit: Nov 16, 2019, 08:41 pm by Keklja
So RTC is working but I have same strange problem with the code now. The idea is to make advent wreath that will turn on LED as the day pass. This part is working. But I would like to turn off all LEDs with a button. That part is not working. Here is my code so far:

Code: [Select]

#include <TimeLib.h>
#include <Wire.h>
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t
#define DS3231_I2C_ADDRESS 104

const int ledPins[] = {22, 23, 26, 27, 30, 31, 34, 35, 38, 39, 42, 43, 46, 47, 50, 51, 52, 53};
const int ledOnOff = 2;
int buttonState = 0;

void setup()  {
 for(int x = 0; x < 19; x++){ //set all LEDs als OUTPUT
   pinMode(ledPins[x],OUTPUT);
 }
 pinMode(ledOnOff,INPUT);

Wire.begin();
 Serial.begin(9600);
 while (!Serial) ; // wait until Arduino Serial Monitor opens
 setSyncProvider(RTC.get);   // the function to get the time from the RTC
 if(timeStatus()!= timeSet)
    Serial.println("Unable to sync with the RTC");
 else
    Serial.println("RTC has set the system time");  

void loop() {
 buttonState = digitalRead(ledOnOff);
 Serial.println(buttonState);
 delay(20);
  if (timeStatus() == timeSet) {
   digitalClockDisplay();
 } else {
   Serial.println("The time has not been set.  Please run the Time");
   Serial.println("TimeRTCSet example, or DS1307RTC SetTime example.");
   Serial.println();
   delay(4000);
 }
 
 delay(1000);

 while(buttonState == 0){ //the idea is to turn all LED with a button
 //turning on LEDs for each day in first week
 
  if(day() > 3 && day() < 10){
   for(int x = 0; x<=day()-4; x++){ //because program starts on Monday 4.11. We need to ignore first 3 days. But if i put day()-3 then on the 4.11. we have day() = 4; day()-3 = 1. So it will ignore first pin in array( x[0]) and it will turn one LED more.  
     digitalWrite(ledPins[x],HIGH);
     }
   }
  else if(day() > 10 && day() < 17){
   for(int x = 0; x<=day()-5; x++){ //same as above only we have one more sunday and thats way it is -5  
     digitalWrite(ledPins[x],HIGH);
     }  
  }
 }
}
//Funktion for RTC
void digitalClockDisplay(){
 // digital clock display of the time
 Serial.print(hour());
 printDigits(minute());
 printDigits(second());
 Serial.print(" ");
 Serial.print(day());
 Serial.print(" ");
 Serial.print(month());
 Serial.print(" ");
 Serial.print(year());
 Serial.println();
}

//Funktion for RTC
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);
}


The problem is when I push a button in SerialMonitor I can see the code did only one loop. Strange. It looks like it program make only one run. I changed while with if and the program is looping and I can see that buttonState is 1 but nothing happens. LEDs are on. What Im I doing wrong?

cattledog


How is the button wired? What is the digitalRead() value of the pressed and not pressed state?

It is important that the input signal is not "floating or undefined" when the button is not pressed. To prevent this, there needs to be a pullup or pulldown resistor to tie the unpressed button to a known state.? What is the digitalRead() value of the pressed and not pressed state?

I recommend that you wire the button using the internal pullup resistor which is engaged with pinMode(pin,INPUT_PULLUP). Then wire diagonally across the button between the input pin and ground. The button will read HIGH when not pressed, and LOW when pressed.

Please confirm the hardware situation.

Then we can proceed with reading when the button becomes pressed. That is the state change from unpressed to pressed. When that happens we know to turn on the leds.

To make the program responsive so it is quick to read a button press, there should not be a use of delay in the program. Remove the delay(1000) line in the code. Instead, the digitalClockDisplay() needs to be on a millis() based timer like used in the "Blink without delay" example of the ide. Here's for a one second update, it can be made longer by changing the displayInterval.

Code: [Select]
void digitalClockDisplay() {
  // digital clock display of the time
  static unsigned long lastDisplay = 0;
  const unsigned long displayInterval = 1000;
  if (millis() - lastDisplay >= displayInterval)
  {
    lastDisplay = millis();
    Serial.print(hour());
    printDigits(minute());
    printDigits(second());
    Serial.print(" ");
    Serial.print(day());
    Serial.print(" ");
    Serial.print(month());
    Serial.print(" ");
    Serial.print(year());
    Serial.println();
  }
}

Keklja

I found the problem. it was stupid mistake. I wrote ifniite loop. That was the problem. I didnt put exit condition. On the weekend i will have final version of the program. I will post it with explanation what is shoud do. Because my coding skills are limited I would like you look in to it and tell me is there a way to make it shorter...

Keklja

So here is my code. Some stuff work, some not. The idea is to wreath does the following:

1. Turn LEDs on each day between 5 and 10 pm and I shoud be able to turn it on when ever I wont (with Smartphone and Blynk app or with Remote Controler)

2. For each day the wreath needs to turn on 1 LED. I have total 18 LED (for 18 days between first Advent sunday and last Advent sunday). For sundays I dont have a LED because we light on the real candle.

3. The Wreath has also a LCD Display that count down  how many days is left till Christmas. Time recieve from RTC modul.

3. With the help of Blynk and remote control I can switch between LEDs blinking patters. There are 3 patterns.

4. I use Arduino Nano with ESP to connect Blynk app and Arduino Mega where all LEDs are connected. On Arduino Nano I used pin D2 - D4 and programed als Output. Pins D2-D4 on Mega are Inputs.

Here is my 1. Problem. I connected Inputs D2-D4 to pull-down resistors but when Arduino Nano send "1" or 5V, the output on Mega is 1 but if the digital input 0 ist, then Digital Input is not working properly. Althoug I connected input to pull down Resistor, Input is still switching states.

2. Problem is that Remote control dont do anything. It supost to swith patters but it doesnt do that.
I am still troubleshooting but if you have any idea, be free to share it.

Here is my code so far:
Code: [Select]

// ++++Smart Advent Wreath++++
/*After the first Sunday the program will start to work. It will do 2 things: 1. it will count how many days it is left till Christmass and show it on LCD.
  2. for each day it will light up a led starting with 2.Dec (Monday). I dont have a LED for Sundays because on Sundays we light up a real candle.
  For time i connected RTC modul. The RTC is also zaduzen for turning all LED after 18:00 and turning off after 22:00. I dont wont to be on all the time.
  Because I have 18 LEDs (from 2.12 till 21.12, without sundays) I used MEGA (didnt wont to have LED in matrix)
  With the help of Arduino NANO I can turn off LEDs
  The are 4 patterns how LEDs can blink
  Patterns can change with the Blynk app or with the remote control
 */
#include <TimeLib.h>
#include <Wire.h>
#include <DS1307RTC.h>                // a basic DS1307 library that returns time as a time_t
#include <LiquidCrystal_I2C.h>
#include <IRremote.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);

#define DS3231_I2C_ADDRESS 104
#define ON_OFF 2
#define PATTERN_1 3
#define PATTERN_2 4
#define PATTERN_3 5

const int ledPins[] = {22, 23, 26, 27, 30, 31, 34, 35, 38, 39, 42, 43, 46, 47, 50, 51, 52, 53};  //defining on which pins are LEDs
int ledOnOff = 0;
int ledPattern1 = 0;
int ledPattern2 = 0;
int ledPattern3 = 0;


const int recvPin = 7;
IRrecv irrecv(recvPin);
decode_results results;
unsigned long key_value = 0;

int daysTillChristmas = 0;
int pin2State, wreathOnOff, lastPin2State = 0;



void setup()  {
  for(int x = 0; x < 19; x++){          //set all LEDs als OUTPUT
    pinMode(ledPins[x],OUTPUT);
  }


  //this Inputs are activated from Arudino NANO and Blynk app
  pinMode(ON_OFF,INPUT);
  pinMode(PATTERN_1,INPUT);   
  pinMode(PATTERN_2,INPUT);
  pinMode(PATTERN_3,INPUT);
 
  //RTC && LCD
  Wire.begin();
  Serial.begin(9600);
  while (!Serial);                    // wait until Arduino Serial Monitor opens
    setSyncProvider(RTC.get);         // the function to get the time from the RTC
    if(timeStatus()!= timeSet)
      Serial.println("Unable to sync with the RTC");
    else
      Serial.println("RTC has set the system time");   
 
  //REMOTE CONTROL
  irrecv.enableIRIn();
  irrecv.blink13(true);
 
  //LCD
  lcd.init();
  lcd.backlight();
}

void loop()
{
  daysTillChristmas = 25 - day(); //for LCD count down

  //i did this because i would like to turn wreath on/off with one single button in the Blynk app
  pin2State = digitalRead(ledOnOff);
  if(pin2State != lastPin2State){
    if(pin2State == 1){
      wreathOnOff = 1;
    }
    else{
      wreathOnOff = 0;
    }
  }
  ledPattern1 = digitalRead(PATTERN_1);
  ledPattern2 = digitalRead(PATTERN_2);
  ledPattern3 = digitalRead(PATTERN_3);
 
 

  //Seting up a LCD
  lcd.setCursor(1,0);
  lcd.print("JOS");
  lcd.setCursor(5,0);
  lcd.print(daysTillChristmas);
  lcd.setCursor(8,0);
  lcd.print("DANA");
  lcd.setCursor(13,0);
  lcd.print("DO");
  lcd.setCursor(0,1);
  lcd.print("*****BOZICA*****");
 
  if (timeStatus() == timeSet) {
    digitalClockDisplay();
  } else {
    Serial.println("The time has not been set.  Please run the Time");
    Serial.println("TimeRTCSet example, or DS1307RTC SetTime example.");
    Serial.println();
    delay(4000);
  }
 
  delay(1000);

  if((hour()>17 && hour()<22) || (wreathOnOff == 1) || (irrecv.decode(&results))){  //turn the wreath on each day beetween 5 and 10 pm OR turn it on with the Blynk App OR with the Remote Control
    if(results.value == 0XFFFFFFFF)
      results.value = key_value;
    if(day() > 3 && day() < 10){                               //turning on LEDs for each day in first week
      for(x = 0; x<=day()-4; x++){                         //because program starts on Monday 4.11. We need to ignore first 3 days. But if i put day()-3 then on the 4.11. we have day() = 4; day()-3 = 1. So it will ignore first pin in array( x[0]) and it will turn one LED more. 
        digitalWrite(ledPins[x],HIGH);
        if((ledPattern1 == 1) || (results.value == 0xFF6897)){
          pattern1(int x);
        }
        else if((ledPattern2 == 1) || (results.value == 0xFF30CF)){
          pattern2(int x);
          pattern3(int x);
        }
        else if((ledPattern3 == 1) || (results.value == 0xFF7A85)) {
          pattern3(int x);
        }
      }
    }
    else if(day() > 10 && day() < 17){
      for(x = 0; x<=day()-5; x++){ //because program starts on Monday 4.11. We need to ignore first 3 days. But if i put day()-3 then on the 4.11. we have day() = 4; day()-3 = 1. So it will ignore first pin in array( x[0]) and it will turn one LED more. 
        digitalWrite(ledPins[x],HIGH);
        if((ledPattern1 == 1) || (results.value == 0xFF6897)){
          pattern1(int x);
        }
        else if((ledPattern2 == 1) || (results.value == 0xFF30CF)){
          pattern2(int x);
          pattern3(int x);
        }
        else if((ledPattern3 == 1) || (results.value == 0xFF7A85)) {
          pattern3(int x);
        }
      }
    }   
    else if(day() >17 && day() < 24){
      for(x = 0; x<=day() - 6;x++){
        digitalWrite(ledPins[x],HIGH);
        if((ledPattern1 == 1) || (results.value == 0xFF6897)){
          pattern1(int x);
        }
        else if((ledPattern2 == 1) || (results.value == 0xFF30CF)){
          pattern2(int x);
          pattern3(int x);
        }
        else if((ledPattern3 == 1) || (results.value == 0xFF7A85)) {
          pattern3(int x);
        }
      }
 
    }
  }
  else{
    for(x = 0; x<19; x++){
      digitalWrite(ledPins[x],LOW);
    }
  }
 
  lastPin2State = pin2State;
}

//PATTERNS
void pattern1(x){
  digitalWrite(ledPins[x],LOW);
  delay(300);
  digitalWrite(ledPins[x],HIGH);
  delay(300);
}

void pattern2(x){
  digitalWrite(ledPins[x],LOW);
  delay(300);
}
void pattern3(x){
  digitalWrite(ledPins[x],HIGH);
  delay(300);
}

void pattern4(x){
  int random_led = random(ledPins[x]);
  digitalWrite(random_led,LOW);
  delay(500);
  digitalWrite(random_led,HIGH);
  delay(500);
}


//Fuktion for RTC
void digitalClockDisplay(){
  // digital clock display of the time
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.print(" ");
  Serial.print(day());
  Serial.print(" ");
  Serial.print(month());
  Serial.print(" ");
  Serial.print(year());
  Serial.println();
}
//Funktion for RTC
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);
}

cattledog

#12
Nov 24, 2019, 07:47 pm Last Edit: Nov 24, 2019, 08:02 pm by cattledog Reason: Add information about array indexes
Quote
So here is my code. Some stuff work, some not.
Your code does not compile, and once it is corrected to compile successfully, there appear to be many other significant errors.  

You are not obviously not writing code in a disciplined fashion. You need to start from something that works properly, and then make small changes, testing as you go. Do you have working code which uses an on/off button and the rtc? No nano, no blynk, no patterns.
If so, post it and lets go from there.

Regarding the ir remote. Forget about that entirely until you have the blynk and rtc controlled lights working.

Quote
Here is my 1. Problem. I connected Inputs D2-D4 to pull-down resistors but when Arduino Nano send "1" or 5V, the output on Mega is 1 but if the digital input 0 ist, then Digital Input is not working properly. Although I connected input to pull down Resistor, Input is still switching states.
I suggest, that to start you separate the nano and blynk from the operation on the mega.

Control the lighting output of the mega with 4 buttons and the rtc. Start with the on/off button and then add patterns one at a time.

Can you attach a hand drawn sketch of how you have wired the buttons and the pulldowns?

Once you get that working properly you can add the nano with blynk to replace the buttons.
The nano with serial input can be used in place of the buttons before you ever get to blynk.

Adding in the ir remote on the mega can be final step.

EDIT: There is a fundamental problem in how you are handling the arrays which I did not notice before. Arrays are zero indexed. That is the first element is element[0].

You have 18 elements in the array. They are indexed 0 through 17. You need to modify the for loops to stay within bounds of your array.

Code: [Select]
const int ledPins[] = {22, 23, 26, 27, 30, 31, 34, 35, 38, 39, 42, 43, 46, 47, 50, 51, 52, 53};

void setup()  {
 //for(int x = 0; x < 19; x++){ //set all LEDs als OUTPUT
    for(int x = 0; x < 18; x++){ //set all LEDs als OUTPUT //indexes are 0 thru 17
   pinMode(ledPins[x],OUTPUT);

Keklja

About arrays you got that right. It forgot to change that. The RTC and LEDs are working correctly. On Tuesday i can post that. Tommorow i will have the drawings in the Frizing dann so I can post that as well. I will try like you sad. Install 4 buttons that will "simulate" NANO and Blynk.

cattledog

Code: [Select]
#define ON_OFF 2
int ledOnOff = 0;
pinMode(ON_OFF,INPUT);

pin2State = digitalRead(ledOnOff);


You are not reading the ON_OFF button input, instead you are reading pin 0. You need to use this to read the the input on pin 2.

Code: [Select]
pin2State = digitalRead(ON_OFF);

Go Up