3x daily ringing of church bells

Hello,

i am new to the arduino world, i have already browsed quite a few forums in search of a suitable codo for my project, bell management on a small bell tower. I am contacting you if anyone can help me create useful code.

I would use an adruino uno, ds3231, 4 digit relay and 20x4- I2C
I would manage 2 bells
in the morning at 7.00 - 1 bell rings ---- 2min
at 12.00 - ring 1 bell ---- 2min
in the evening after sunset --- 2 bells ring ---- 2min
Lcd displays information about the date of the hour and the sunset
rtc should support DST (EU)

the ringing mode is performed by a blink system between 2 relays
relay1-relay2-relay1-relay2 .....

I’ve come across a few examples that should come together in my project but I fail to do so.

Please help advice or anything that will guide me in the right direction. Thanks

What have you come up with so far? if you post code we can help you figure out where you are going wrong.

The only special wrinkle is the sunset sunrise thing, but there is at least one good library that does a good job of that.

So you could leave that as a refinement and just aim for 6 AM and 6 PM first.

You could start even earlier, just the relays and see if you can really "ring the bell".

This should be very similar to dozens of projects… using exactly the same basic parts.

Divide and conquer. Find example code for each component and get to know how it works and what code for it looks like.

a7

Totally agree with that. Your "mistake" if I may call it that, was here (my emphasis):

It's almost impossible to find existing code that will meet the need of some other project. That means you pretty much have to do what was already suggested: take the project to pieces and get each part sorted in isolation of the others.

hello
I am attaching a code that works after rtc time in which I cannot determine the operation as a blink between relay 1 and 2

//////////////////////////////////////////////////////////////
// Real Time Clock with Displayed on I2C 20x4 LCD
// Parts
// 1 x Arduino UNO
// 1 x 2004 I2C LCD 
// 1 x DS3231 RTC Module
// RTC and LCD both use Pins A4 & A5
//***************************************************************


#include <Wire.h>  //WireLibrary comes with arduino
#include <LiquidCrystal_I2C.h> //i2c LCD Library 
#include <DS3231.h>

int Relay1 = 4;
int Relay2 = 5;




DS3231  rtc(SDA, SCL);
Time t;

const int OnHour = 19; //SET TIME TO ON RELAY (24 HOUR FORMAT)
const int OnMin = 23;
const int OffHour = 19; //SET TIME TO OFF RELAY
const int OffMin = 24;







#define DS3231_I2C_ADDRESS 0x68 //RTC Address


LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address


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


void setup()
{
  Wire.begin(); //initialise the TWI
  lcd.begin(20, 4);  //20 x 4 LCD (Change if required)

  for (int i = 0; i < 0; i++) //Flash LCD backlight 2 times on startup
  {
    lcd.backlight();
    delay(250);
    lcd.noBacklight();
    delay(250);
  }
  lcd.backlight(); // finish with backlight on
  lcd.setCursor(0, 0); //Start at character 0 on line 0
  lcd.print("URA:     DATUM:");

   Serial.begin(115200);
  rtc.begin();
  pinMode(Relay1, OUTPUT);
  pinMode(Relay2, OUTPUT);
  digitalWrite(Relay1, HIGH);
  digitalWrite(Relay2, HIGH);
 

}
//***********************************************************

void loop()
{
  displayTime(); //calls the display time function

  

t = rtc.getTime();
  Serial.print(t.hour);
  Serial.print(" hour(s), ");
  Serial.print(t.min);
  Serial.print(" minute(s)");
  Serial.println(" ");
  delay (1000);
  
  
  if(t.hour == OnHour && t.min == OnMin){
    digitalWrite(Relay1,LOW);
    Serial.println("LIGHT ON");
    digitalWrite(Relay1,LOW);
    Serial.println("LIGHT ON");
   

    }

  


    
    
    else if(t.hour == OffHour && t.min == OffMin){
      digitalWrite(Relay1,HIGH);
      Serial.println("LIGHT OFF");
      digitalWrite(Relay1,HIGH);
      Serial.println("LIGHT OFF");


      }

      


  
}
//*******************************************************************

byte decToBcd(byte val)//used when sending time
{
  return ( (val / 10 * 16) + (val % 10) );
}
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
  return ( (val / 16 * 10) + (val % 16) );
}
//**********************************************************************
void readDS3231time(byte *second, byte *minute, byte *hour, byte *dayOfWeek, byte *dayOfMonth, byte *month, byte *year)
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0); // set DS3231 register pointer to 00h
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  // request seven bytes of data from DS3231 starting from register 00h
  *second = bcdToDec(Wire.read() & 0x7f);
  *minute = bcdToDec(Wire.read());
  *hour = bcdToDec(Wire.read() & 0x3f);
  *dayOfWeek = bcdToDec(Wire.read());
  *dayOfMonth = bcdToDec(Wire.read());
  *month = bcdToDec(Wire.read());
  *year = bcdToDec(Wire.read());
}
//****************************************************************************
void displayTime()
{
  byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;

  readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
                 &year);
  if (hour < 10)
  {
    lcd.setCursor(0, 1);
    lcd.print("0");
    lcd.setCursor(1, 1);
    lcd.print(hour , DEC);
  }
  if (hour > 9)
  {
    lcd.setCursor(0, 1);
    lcd.print(hour , DEC);
  }
  lcd.setCursor(2, 1);
  lcd.print(":");
  if (minute < 10)
  {
    lcd.setCursor(3, 1);
    lcd.print("0");
    lcd.setCursor(4, 1);
    lcd.print(minute , DEC);
  }
  if (minute > 9)
  {
    lcd.setCursor(3, 1);
    lcd.print(minute , DEC);
  }
  lcd.setCursor(5, 1);
  lcd.print(":");
  if (second < 10)
  {
    lcd.setCursor(6, 1);
    lcd.print("0");
    lcd.setCursor(7, 1);
    lcd.print(second, DEC);
  }
  if (second > 9)
  {
    lcd.setCursor(6, 1);
    lcd.print(second, DEC);
  }
  if (dayOfMonth < 10)
  {
    lcd.setCursor(9, 1);
    lcd.print("0");
    lcd.setCursor(10, 1);
    lcd.print(dayOfMonth, DEC);
    lcd.setCursor(11, 1);
    lcd.print("/");
  }
  if (dayOfMonth > 9)
  {
    lcd.setCursor(9, 1);
    lcd.print(dayOfMonth, DEC);
    lcd.setCursor(11, 1);
    lcd.print("/");
  }
  if (month < 10)
  {
    lcd.setCursor(12, 1);
    lcd.print("0");
    lcd.setCursor(13, 1);
    lcd.print(month, DEC);
    lcd.setCursor(14, 1);
    lcd.print("/");
  }
  if (month > 9)
  {
    lcd.setCursor(12, 1);
    lcd.print(month, DEC);
    lcd.setCursor(14, 1);
    lcd.print("/");
  }
  lcd.setCursor(15, 1);
  lcd.print(year, DEC);

  switch (dayOfWeek) {
    case 1:
      lcd.setCursor(0, 2);
      lcd.print("Today is Sunday");
      break;
    case 2:
      lcd.setCursor(0, 2);
      lcd.print("Today is Monday");
      break;
    case 3:
      lcd.setCursor(0, 2);
      lcd.print("Today is Tuesday");
      break;
    case 4:
      lcd.setCursor(0, 2);
      lcd.print("Today is Wednesday");
      break;
    case 5:
      lcd.setCursor(0, 2);
      lcd.print("Today is Thursday");
      break;
    case 6:
      lcd.setCursor(0, 2);
      lcd.print("Today is Friday");
      break;
    case 7:
      lcd.setCursor(0, 2);
      lcd.print("Today is Saturday");
      break;
  }


}

What does your serial output show?

Haha, no.

Rather than a complete does-exactly existing program, use examples for each of the pieces of hardware.

Post the sketches you are using to test and become familiar with the pieces.

Post any effort you have made to combine the features, or anything where you are having trouble understanding an examples or making the example code work.

a7

Please post your code between code tags, as explained in the forum guide and we will review it for you. Many forum members browse the forum on phones & tablets and cannot open a .ino attachment.

In English it is called "code" not "codo" and we do not say "a code", we say "some code". (It is similar to water or air or distance. We would not say "I am thirsty so I will drink a water". We would say "drink some water" :slightly_smiling_face:)

There's more than a few of us who tots missed that the OP did post an attached *.ino!

a7

I apologize for the poor English, I corrected the addition of the code in the post.

Take a look at the IDE example "blink without delay". That should let you operate your relay(s). Add that to your existing code.

Then use your existing time logic to set a boolean variable that tells you whether the bells should be ringing or not.

If they should, use the BWOD stuff you copied to operate them.

Why have a function to read the DS3231 yourself when you included a library for handling the low-level communications with the RTC?

This is true because I don't have wifi or other options I would only use ds3231 to which I would add DST. But since I'm really a beginner, I don't know how to add this to the code.

thanks

hello found the code with a 2 pin switch to enter a pause between them

const int ledAPin = 5;               // the number of the LED pin
const int ledBPin = 4;                // another LED
char ledState = 'A';                  // ledState used to set the LED
unsigned long previousMillis = 0;     // will store last time LED was updated
const long interval = 500;           // interval at which to blink (milliseconds)

void setup() {
  pinMode(ledAPin, OUTPUT);
  pinMode(ledBPin, OUTPUT);
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    // if the LED A is on turn it off and vice-versa:
    if (ledState == 'A') {
      ledState = 'B'; // switch to state B for the next iteration
      digitalWrite(ledAPin, LOW);
      digitalWrite(ledBPin, HIGH);
    } else {
      ledState = 'A';
      digitalWrite(ledAPin, HIGH);
      digitalWrite(ledBPin, LOW);
    }
  }
}

What do you mean by "1 bell rings ---- 2min"?

Is the "after sunset" a fixed amount after sunset?

bell number 1, ringing lasts 2 minutes

7am, 12 and at sunset

the sunset changes the calculation based on the astronomical clock

What type of error are you getting?

Around line 164 the for statement is incorrect, an int is 2 bytes, so sizeof(periodSetZvon1) will be 12 (array of int with 6 elements). You likely do not want the "- 1" unless you want to exclude the last element of the array. You probably do not want to subtract 1 either, unless you specifically want to exclude the last element of the array.

        //for (int i = 0; i < sizeof(periodSetZvon1) - 1; i++) {
        for (int i = 0; i < sizeof(periodSetZvon1)/sizeof(periodSetZvon1[0]) - 1; i++) {

I had to change the following line because my computer operating system is case-sensitive. The same change had to be made to the sunMoon.h file in the library.

//#include <Time.h>
#include <time.h>

hello

I'm still dealing with the problem of how to determine in a program that is activated when the sunset condition is met and takes an interval that it switches between pin 4 -5.
i want it to work pin4 200ms - pause500ms - pin5 200ms-pause 500ms ....

I will be grateful for any help

Using delay for timing is usually a bad idea - it makes the program unresponsive. In this case, you can get away with it because all the code does is ring bells. It will probably turn out to be a problem eventually as requirements are clarified or change, but here is a version to try out:

#include <Time.h>
#include <TimeLib.h>
#include <DS3232RTC.h>
#include <sunMoon.h>
#include <LiquidCrystal_I2C.h>

#define DS3231_I2C_ADDRESS 0x68 //RTC Address

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);  // Set the LCD I2C address

#define OUR_latitude    46.056946           // Ljubljana
#define OUR_longtitude  14.505752
#define OUR_timezone    60                     // localtime with UTC difference in minutes

sunMoon  sm;

//definiraj pine za zvonove
int zvon11 = 4; //priklopi na arduino pin xx
int zvon12 = 5; //priklopi na arduino pin xy

//definicija timerja
int period = 10000;  //spremeni na ÄŤas zvonenja (1000ms = 1s)
unsigned long time_now = 0; //pusti na miru, temp variable za preteÄŤen ÄŤas


void printDate(time_t date)
{
  char buff[20];
  sprintf(buff, "%2d-%02d-%4d %02d:%02d:%02d",
          day(date), month(date), year(date), hour(date), minute(date), second(date));
  Serial.print(buff);
}

void Time(time_t date)
{
  char buff[20];
  sprintf(buff, "%02d:%02d:%02d",
          hour(date), minute(date), second(date));
  Serial.print(buff);
  (buff);
}

//additional function
void printLcdDate(time_t date)
{
  char buff[20];
  sprintf(buff, "%02d:%02d:%02d",
          hour(date), minute(date), second(date));
  lcd.print(buff);
}
//additional function
void printLcdDate1(time_t date)
{
  char buff[20];
  sprintf(buff, "%2d-%02d-%4d",
          day(date), month(date), year(date));
  lcd.print(buff);
}

void setup()
{
  lcd.begin(20, 4);
  tmElements_t  tm;                             // specific time
  tm.Second = 0;
  tm.Minute = 12;
  tm.Hour   = 12;
  tm.Day    = 3;
  tm.Month  = 8;
  tm.Year   = 2016 - 1970;
  time_t s_date = makeTime(tm);
  Serial.begin(9600);
  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");
  sm.init(OUR_timezone, OUR_latitude, OUR_longtitude);
  Serial.print("Today is ");
  printDate(RTC.get()); Serial.println("");
  uint32_t jDay = sm.julianDay();               // Optional call
  byte mDay = sm.moonDay();
  time_t sRise = sm.sunRise();
  time_t sSet  = sm.sunSet();
  Serial.print("Today is "); Serial.print(jDay); Serial.println(" Julian day");
  Serial.print("Moon age is "); Serial.print(mDay); Serial.println("day(s)");
  Serial.print("Today sunrise and sunset: ");
  printDate(sRise); Serial.print("; ");
  printDate(sSet);  Serial.println("\t");
  Time(sRise); Serial.print("; ");
  Time(sSet);  Serial.println("");
  lcd.setCursor(0, 0);
  printLcdDate1(RTC.get());
  lcd.setCursor(12, 0);
  printLcdDate(RTC.get());
  lcd.setCursor(0, 3);
  printLcdDate(sRise);
  lcd.setCursor(12, 3);
  printLcdDate(sSet);
  Serial.print("Specific date was ");
  printDate(s_date); Serial.println("");
  jDay = sm.julianDay(s_date);
  mDay = sm.moonDay(s_date);
  sRise = sm.sunRise(s_date);
  sSet  = sm.sunSet(s_date);
  Serial.print("Specific date sunrise and sunset was: ");
  Serial.print("Julian day of specific date was "); Serial.println(jDay);
  Serial.print("Moon age was "); Serial.print(mDay); Serial.println("day(s)");
  printDate(sRise); Serial.print("; ");
  printDate(sSet);  Serial.println("");
  //definiraj outpute za relaye
  pinMode(zvon11, OUTPUT);    // sets the digital pin to output
  digitalWrite(zvon11, HIGH); // sets the digital pin LOW
  pinMode(zvon12, OUTPUT);    // sets the digital pin to output
  digitalWrite(zvon12, HIGH); // sets the digital pin LOW
}

void loop()
{
  time_t sRise = sm.sunRise();
  time_t sSet  = sm.sunSet();
  time_t sunRise(time_t date = 0);
  time_t sunSet(time_t date = 0);
  printDate(RTC.get()); Serial.print("\t");
  Time(sRise); Serial.print("\t ");
  Time(sSet);  Serial.println("");
  if (RTC.get() >= sRise && RTC.get() <= sSet )
  {
    Serial.println("Day");
    lcd.setCursor(10, 1);
    lcd.print("Day");
  }
  else if (RTC.get() >= sSet && RTC.get() <= sRise )
  {
    Serial.print("Night ");
    lcd.setCursor(10, 1);
    lcd.print("Night");
  }
  else
  {
  }
  lcd.setCursor(0, 0);
  printLcdDate1(RTC.get());
  lcd.setCursor(12, 0);
  printLcdDate(RTC.get());
  lcd.setCursor(0, 3);
  printLcdDate(sRise);
  lcd.setCursor(12, 3);
  printLcdDate(sSet);
  if (sRise == RTC.get())
  {
    time_now = millis();
    while (millis() < time_now + period)
    {
      digitalWrite(zvon11, LOW); //let's magic begin
      digitalWrite(zvon12, LOW); //let's magic begin
    }
  }
  else
  {
    digitalWrite(zvon11, HIGH); //let's magic begin
    digitalWrite(zvon12, HIGH); //let's magic begin
  }
  if(sSet == RTC.get())
    {
    RingSunsetBells();  
    }
  delay(1000);
}

void RingSunsetBells()
{
for(int lp=0;lp<20;lp++)
  {
  digitalWrite(zvon11, LOW);
  delay(200);
  digitalWrite(zvon11, HIGH);
  delay(500);
  digitalWrite(zvon12, LOW);
  delay(200);
  digitalWrite(zvon12, HIGH);
  delay(500);
  }
}

I can't compile it because I don't have the libraries, so I obviously didn't test it either.

hello

Modified code does not work. you mentioned that this method is not so suitable, what do you suggest? But it would be better to count down the overlaps. Thanks

Blink without delay is the usual choice. What does that code do? Nothing?

Can you put a serial print in the bell ringing function to see whether it is ever called? I have my doubts because of the delay(1000) meaning that the sunset time is missed.

You might also call the new function from setup to check that it actually operates the bells.