Hey all
So, a friend and I are making a mini clock tower, and I'm handling the sound signals with an Arduino Uno R3, DS3231, SRD-05VDC-SL-C Relay, and a KK-0630B Strike Magnet.
The relay and strike magnet are powered through the Arduino. The current never exceeds the arduino limit, so I think it should be fine.
Every hour, I activate the strike magnet to strike the bell so you can hear what time it is. I also do this once every half hour so you know it's halfway through the hour.
Now, here's the issue: Not every hour does the bell strike the correct number of times. For example, if it's 10 AM, sometimes it will only strike 4 times, but other days it will strike all 10 times.
I don't know what the problem is. The only thing I can think of is that the millis are moving too fast, and it might cause an error in the loop?
Has anyone got any ideas?
Thank you!
#include <Wire.h>
#include "RTClib.h"
RTC_DS3231 rtc;
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long hammerMoveTime = 1000; // This value is in milliseconds
const int relayPin = 8;
int totalStrikes = 0;
int strikeCount = 0;
bool isStriking = false;
bool halfHourStrike = false;
bool hammerRetracted = false;
bool hammerReleased = true;
void setup() {
pinMode(relayPin, OUTPUT);
digitalWrite(relayPin, LOW);
Serial.begin(9600);
startMillis = millis(); // Start the internal timer
if (!rtc.begin()) { // Check if the external clock is found
Serial.println("RTC not found!");
while (1);
}
if (rtc.lostPower()) { // Check if the external clock has lost its time, otherwise set it
rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
}
}
bool isDaylightSaving(DateTime now) { // Check if it is summer or winter time
int month = now.month();
int day = now.day();
// Simple check: Daylight saving time from April 1st to October 31st
return (month > 4 && month < 10) ||
(month == 4 && day >= 1) ||
(month == 10 && day <= 31);
}
void loop() {
currentMillis = millis(); // Get the current milliseconds since the start of the program or last loop
DateTime now = rtc.now(); // Get the current time from the RTC
int hour = now.hour();
int minute = now.minute();
int second = now.second();
//Serial.print(hour);
//Serial.print(":");
//Serial.print(minute);
//Serial.print(":");
//Serial.print(second);
//Serial.println();
bool isSummer = isDaylightSaving(now); // Check if it is summer or winter time
// Strike window according to season
int startHour = 7; // Time to start striking
int endHour = isSummer ? 22 : 20; // Time to stop striking
if (hour >= startHour && hour <= endHour && minute == 0 && second == 0 || isStriking) { // Strikes on every full hour
if (hour > 12 && !isStriking) { // When a new hour starts, check if it's above or below 12
totalStrikes = hour - 12; // If it's, for example, 13:00, subtract 12 to get 1 hour; otherwise, too many strikes will occur
// Serial.print("totalStrikes: ");
// Serial.print(totalStrikes);
// Serial.println();
}
else if (hour <= 12 && !isStriking){
totalStrikes = hour;
// Serial.print("totalStrikes: ");
// Serial.print(totalStrikes);
// Serial.println();
}
if ((currentMillis - startMillis >= hammerMoveTime) && hammerRetracted == false && hammerReleased == true) // Check if the time period has passed, check if the hammer is released
{
digitalWrite(relayPin, HIGH);
// Serial.print("Retracting");
// Serial.println();
isStriking = true; // We have started a series of strikes
hammerRetracted = true; // The hammer is retracted
hammerReleased = false; // The hammer is not released
startMillis = currentMillis; // IMPORTANT to keep track of the time
}
else if ((currentMillis - startMillis >= hammerMoveTime) && hammerRetracted == true && hammerReleased == false) // Check if the time period has passed, check if the hammer is retracted
{
digitalWrite(relayPin, LOW);
// Serial.print("Releasing");
// Serial.println();
hammerRetracted = false; // The hammer is no longer retracted
hammerReleased = true; // The hammer is released
strikeCount++; // We count how many strikes we have done
// Serial.print("strikeCount: ");
// Serial.print(strikeCount);
// Serial.println();
startMillis = currentMillis; // IMPORTANT to keep track of the time
}
} else if (hour >= startHour && hour < endHour && minute == 30 && second == 0 || halfHourStrike) { // Strikes on every half hour
if ((currentMillis - startMillis >= hammerMoveTime) && hammerRetracted == false && hammerReleased == true) // Check if the time period has passed
{
digitalWrite(relayPin, HIGH);
// Serial.print("Retracting");
// Serial.println();
halfHourStrike = true; // This is for 1 strike that we do every half hour
hammerRetracted = true; // The hammer is retracted
hammerReleased = false; // The hammer is not released
startMillis = currentMillis; // IMPORTANT to save the start time of the current LED state
}
else if ((currentMillis - startMillis >= hammerMoveTime) && hammerRetracted == true && hammerReleased == false) // Check if the time period has passed
{
digitalWrite(relayPin, LOW);
// Serial.print("Releasing");
// Serial.println();
hammerRetracted = false; // The hammer is no longer retracted
hammerReleased = true; // The hammer is released
halfHourStrike = false; // The 1 strike of the half hour has been completed
startMillis = currentMillis; // IMPORTANT to save the start time of the current LED state
}
}
if (strikeCount >= totalStrikes && totalStrikes != 0) { // Check if all the necessary strikes have been completed
strikeCount = 0; // Reset the current number of strikes done
isStriking = false; // All necessary strikes have been completed, this will be set to false
// Serial.print("isStriking = false ");
// Serial.println();
}
}
