/*
Gray Mack
11/5/2024
A simple clock display with up/down buttons as every clock should have
License: MIT license https://choosealicense.com/licenses/mit/ (AI wrote the code but I wrote the prompt)
Code by GitHub Copilot AI chat Chat. Prompt:
Can you write arduino code. Utilize millis instead of delay.
Have 5 section for the code with section comments for "Includes" "Pins" "Constants" "Globals" "Code" and organize the code under those sections.
I have a DS3231 RTC module which should be read frequently.
I have a tm1637 seven segment display with data on pin 10 named DisplayData and clock on pin 8 named DisplayClock. Use the TM1637Display.h library
I have a piezo buzzer on pin 9.
I have 8 ws2812 pixels on pin 7. Use the FastLED library to make a larson scanner.
There are 5 buttons: HourUp, HourDown, MinuteUP, MinuteDown, SecondReset on pins 0, 1, 2, 3, 6 respectively.
Use Button2 library with these buttons.
Use INPUT_PULLUP mode with these buttons.
initialize the serial port at 9600 band and print "Setup complete" at the end of setup.
The button HourUp will increase the hour, rolling over after 12 to 1 and toggle between am and pm and change the RTC modules time and print "Hr+" to console.
The button HourDown will decrease the hour, rolling under from 1 back to 12 and toggle between am and pm and change the RTC modules time and print "Hr-" to console.
The button MinuteUp will increase the minute, rolling over after 59 to 0 and change the RTC modules time and print "Min+" to console.
The button MinuteDown will decrease the minute, rolling under after 0 to 59 and change the RTC modules time and print "Min-" to console.
The button SecondReset will set the RTC modules seconds to 0 and print Sec0 to console.
The button routines also immediately update the display.
The day/month year is not important and can be ignored.
The clock should display in 12 hour mode on the tm1637 seven segment display. The hour should not include leading zero but the minute should for example showing " 3:09"
Update the ClockInterval every 1000ms.
Create a function called TimeToColor that returns a CRGB based on the time. When Hours times 60 + Minutes is closer to (9*60) it returns blue, when closer to (22*60) it returns red and the color blends between these wrapping the percentage over.
Create a function UpdateLarsonScanner function has a static variable tracking the lightOn and a static variable tracking the direction of +1 or -1
Update the LarsonScannerInterval every 1/(NUM_LEDS-1) second calling a function called UpdateLarsonScanner.
{
"type": "wokwi-arduino-nano",
"id": "esp",
"top": -81.4,
"left": -25.5,
"rotate": 180,
"attrs": {}
},
*/
//TEST:
// Includes
#include <FastLED.h>
// Pins
#define LED_PIN 7
// Constants
#define NUM_LEDS 8
#define BRIGHTNESS 64
#define LED_TYPE WS2812
#define COLOR_ORDER GRB
const long larsonInterval = 1000 / (NUM_LEDS - 1); // Update interval for Larson scanner
// Globals
CRGB leds[NUM_LEDS];
unsigned long previousLarsonMillis = 0;
// Code
void setup() {
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setBrightness(BRIGHTNESS);
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousLarsonMillis >= larsonInterval) {
previousLarsonMillis = currentMillis;
updateLarsonScanner();
}
}
void updateLarsonScanner() {
static int lightOn = 0;
static int direction = 1;
fill_solid(leds, NUM_LEDS, CRGB::Black);
leds[lightOn] = CRGB::Red;
FastLED.show();
lightOn += direction;
if (lightOn == NUM_LEDS - 1 || lightOn == 0) {
direction = -direction;
}
}
/*
// Includes
#include <Wire.h>
#include <RTClib.h>
#include <TM1637Display.h>
#include <FastLED.h>
#include <Button2.h>
// Pins
#define DisplayData 10
#define DisplayClock 8
#define BUZZER_PIN 9
#define LED_PIN 7
#define HOUR_UP_PIN 0
#define HOUR_DOWN_PIN 1
#define MINUTE_UP_PIN 2
#define MINUTE_DOWN_PIN 3
#define SECOND_RESET_PIN 6
// Constants
#define NUM_LEDS 8
const long clockInterval = 1000; // Update interval for display and RTC read
const long larsonInterval = 1000 / (NUM_LEDS - 1); // Update interval for Larson scanner
// Globals
RTC_DS3231 rtc;
TM1637Display display(DisplayClock, DisplayData);
CRGB leds[NUM_LEDS];
Button2 btnHourUp(HOUR_UP_PIN);
Button2 btnHourDown(HOUR_DOWN_PIN);
Button2 btnMinuteUp(MINUTE_UP_PIN);
Button2 btnMinuteDown(MINUTE_DOWN_PIN);
Button2 btnSecondReset(SECOND_RESET_PIN);
unsigned long previousClockMillis = 0;
unsigned long previousLarsonMillis = 0;
// Code
void setup() {
Wire.begin();
rtc.begin();
display.setBrightness(0x0f);
FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS);
btnHourUp.setClickHandler([](Button2 &btn) { adjustHour(1); });
btnHourDown.setClickHandler([](Button2 &btn) { adjustHour(-1); });
btnMinuteUp.setClickHandler([](Button2 &btn) { adjustMinute(1); });
btnMinuteDown.setClickHandler([](Button2 &btn) { adjustMinute(-1); });
btnSecondReset.setClickHandler([](Button2 &btn) { resetSeconds(); });
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousClockMillis >= clockInterval) {
previousClockMillis = currentMillis;
updateDisplay();
}
if (currentMillis - previousLarsonMillis >= larsonInterval) {
previousLarsonMillis = currentMillis;
updateLarsonScanner();
}
btnHourUp.loop();
btnHourDown.loop();
btnMinuteUp.loop();
btnMinuteDown.loop();
btnSecondReset.loop();
}
void updateDisplay() {
DateTime now = rtc.now();
int hour = now.hour() % 12;
if (hour == 0) hour = 12;
int minute = now.minute();
display.showNumberDecEx(hour * 100 + minute, 0x40, true, 4, 0);
}
CRGB TimeToColor(int hour, int minute) {
int totalMinutes = hour * 60 + minute;
int startMinutes = 9 * 60; // 9:00 AM
int endMinutes = 21 * 60; // 9:00 PM
float progress = (float)(totalMinutes - startMinutes) / (endMinutes - startMinutes);
if (progress < 0) progress += 1.0;
if (progress > 1) progress -= 1.0;
return blend(CRGB::Blue, CRGB::Red, progress * 255);
}
void updateLarsonScanner() {
static int lightOn = 0;
static int direction = 1;
DateTime now = rtc.now();
CRGB color = TimeToColor(now.hour(), now.minute());
fill_solid(leds, NUM_LEDS, CRGB::Black);
leds[lightOn] = color;
FastLED.show();
lightOn += direction;
if (lightOn == NUM_LEDS - 1 || lightOn == 0) {
direction = -direction;
}
}
void adjustHour(int delta) {
DateTime now = rtc.now();
int hour = now.hour() + delta;
if (hour > 23) hour = 0;
if (hour < 0) hour = 23;
rtc.adjust(DateTime(now.year(), now.month(), now.day(), hour, now.minute(), now.second()));
updateDisplay();
}
void adjustMinute(int delta) {
DateTime now = rtc.now();
int minute = now.minute() + delta;
if (minute > 59) minute = 0;
if (minute < 0) minute = 59;
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), minute, now.second()));
updateDisplay();
}
void resetSeconds() {
DateTime now = rtc.now();
rtc.adjust(DateTime(now.year(), now.month(), now.day(), now.hour(), now.minute(), 0));
updateDisplay();
}
*/