Amazing, thank you! Photos from earlier in the post are still the latest. The wire going off the PCB connects to the NeoMatrix, which is powered by a separate 5V 4A power supply. When I'm not plugged into the computer, I split the power supply to also power the Feather. Apologies for the crazy on top/down below soldering - this is my first project.
(FWIW, I tried I2C Scan again this morning, and this time made it a little bit before crashing:
Code: Select all
Adafruit I2C Scanner
Default port (Wire) I2C scan: 0x2, 0x3,
The RTC code is the default SetSerial file from JChristensen's DS3232RTC library
https://github.com/JChristensen/DS3232R ... Serial.ino. (Figured easier to post link than increase post length.)
My LED lamp code is here:
Code: Select all
#include <Wire.h>
#include <Adafruit_NeoPixel.h>
#include <DS3232RTC.h> // https://github.com/JChristensen/DS3232RTC
#include <Streaming.h> // https://github.com/janelia-arduino/Streaming
// RTC setup
constexpr uint8_t RTC_INT_PIN{ 5 }; // RTC provides an alarm signal on this pin
DS3232RTC myRTC;
char timestamp[32]; // used later for current time from the RTC in text format
enum alarmPhases { // LED Lamp has three phases
NIGHTLIGHT, // Acts as a nightlight
GETTINGREADY, // Changes color to show time to get ready
DAYTIME // Is not lit during the day
};
enum alarmPhases alarmState;
// Define timing for each alarm
#define DAYOFWEEKCHECK_HOUR 12
#define DAYOFWEEKCHECK_MINUTE 11
#define WEEKDAY_WAKEUP_HOUR 12
#define WEEKDAY_WAKEUP_MINUTE 12 // Add +1 to dayofweekcheck for testing
#define WEEKEND_WAKEUP_HOUR 12
#define WEEKEND_WAKEUP_MINUTE 12 // Add +1 to dayofweekcheck for testing
#define TURN_OFF_MINUTES 1
#define NIGHTLIGHT_ON_HOUR 12 // TODO: Is this doing off?
#define NIGHTLIGHT_ON_MINUTE 14 // Add +3 to dayofweekcheck for testing
// NeoPixel Setup
#define LED_PIN 6 // Which pin on the Arduino is connected to the NeoPixels?
#define LED_COUNT 64 // How many NeoPixels are attached to the Arduino?
#define BRIGHTNESS 200 // Max = 255; Example had it originally set to 50
// Declare our NeoPixel strip object for NeoPixel NeoMatrix https://www.adafruit.com/product/2870
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRBW + NEO_KHZ800); // Adjust to GRBW per forum, but order is RGBW in setting
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
void setup() {
Serial.begin(115200); // TODO: Identify if I remove this when running without computer plugged in
// while the serial stream is not open, do nothing:
while (!Serial)
;
delay(1000);
Serial.println("DEBUG: After serial begin");
pinMode(RTC_INT_PIN, INPUT_PULLUP);
// RTC setup
myRTC.begin();
setSyncProvider(myRTC.get); // the function to get the time from the RTC
if (timeStatus() != BANNED)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
// initialize the alarms to known values, clear the alarm flags, clear the alarm interrupt flags
myRTC.setAlarm(DS3232RTC::ALM1_MATCH_DATE, 0, 0, 0, 1); // Last digit (1) is for a date-based alarm, but I reset to hour-based later
myRTC.setAlarm(DS3232RTC::ALM2_MATCH_DATE, 0, 0, 0, 1);
myRTC.alarm(DS3232RTC::ALARM_1);
myRTC.alarm(DS3232RTC::ALARM_2);
myRTC.alarmInterrupt(DS3232RTC::ALARM_1, false);
myRTC.alarmInterrupt(DS3232RTC::ALARM_2, false);
myRTC.squareWave(DS3232RTC::SQWAVE_NONE);
// print the current time
time_t t = myRTC.get();
formatTime(timestamp, t);
Serial << millis() << F(" Current RTC time ") << timestamp << endl;
// Set the proper status by setting it to the _previous_ status and running changeColor() to advance the status
Serial << millis() << F(" DEBUG: Setting proper status") << endl;
if (weekday() == 1 || weekday() == 7) { // Is a weekend (Day of the week (1-7), Sunday is day 1)
Serial << millis() << F(" DEBUG:Setting weekend or weekday") << endl;
if (hour() >= NIGHTLIGHT_ON_HOUR || hour() < WEEKEND_WAKEUP_HOUR) { // Want this to end up at NIGHTLIGHT, so set to DAYTIME
alarmState = DAYTIME;
} else { // It's not nighttime, so figure out which other state it is
if (hour() == WEEKEND_WAKEUP_HOUR) { // Shortcutting by not worrying about getting ready timer.
alarmState = NIGHTLIGHT; // Setting to NIGHTLIGHT means it will end up at GETTINGREADY
} else {
alarmState = GETTINGREADY; // Setting to GETTINGREADY means it will end up at DAYTIME
}
}
} else { // Is a weekday
if (hour() >= NIGHTLIGHT_ON_HOUR || hour() < WEEKDAY_WAKEUP_HOUR) {
alarmState = DAYTIME;
} else {
if (hour() == WEEKDAY_WAKEUP_HOUR) { // Shortcutting by not worrying about getting ready timer.
alarmState = NIGHTLIGHT;
} else {
alarmState = GETTINGREADY;
}
}
}
changeColor();
Serial.print("Current status during setup is: ");
Serial.print(alarmState);
Serial.println();
// Set alarm 1, which will check for day of week and then set alarm 2 appropriately
Serial << millis() << F(" DEBUG:Setting alarm 1 for day of week check") << endl;
myRTC.setAlarm(DS3232RTC::ALM1_MATCH_HOURS, DAYOFWEEKCHECK_MINUTE, DAYOFWEEKCHECK_HOUR, 0); // Alarm will match hour and minute every day
myRTC.alarm(DS3232RTC::ALARM_1); // Ensure RTC interrupt flag is cleared
myRTC.alarmInterrupt(DS3232RTC::ALARM_1, true);
// Set alarm 2 to a default weekday alarm
Serial << millis() << F(" DEBUG:Setting alarm 2") << endl;
myRTC.setAlarm(DS3232RTC::ALM2_MATCH_HOURS, WEEKDAY_WAKEUP_MINUTE, WEEKDAY_WAKEUP_HOUR, 0);
myRTC.alarm(DS3232RTC::ALARM_2);
myRTC.alarmInterrupt(DS3232RTC::ALARM_2, true);
// Initialize NeoPixel
Serial << millis() << F(" DEBUG:Neopixel initializing") << endl;
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(BRIGHTNESS);
}
void loop() {
digitalClockDisplay(); // Display the current time
Serial.print("Current status: ");
Serial.print(alarmState);
Serial.println();
delay(1000);
// check to see if the INT/SQW pin is low, i.e. an alarm has occurred
if (!digitalRead(RTC_INT_PIN)) {
Serial << millis() << F(" DEBUG:Some alarm went off; checking which") << endl;
formatTime(timestamp, myRTC.get()); // get current RTC time
if (myRTC.alarm(DS3232RTC::ALARM_1)) { // If Alarm 1 has gone off, call SetAlarm2 to set the appropriate daily alarm
Serial << millis() << F(" Alarm 1 went off at ") << timestamp << endl;
setAlarm2();
} else if (myRTC.alarm(DS3232RTC::ALARM_2)) { // Must be the daily alarm
// Set the new alarm, then call changeColor to change the LED color and advance the state
Serial << millis() << F(" Alarm 2 went off at ") << timestamp << endl;
Serial.print("The alarmState currently is: ");
Serial.print(alarmState);
Serial.println();
if (alarmState == NIGHTLIGHT) { // Since state = NIGHTLIGHT, move to state = GETTINGREADY
// Set the next alarm to TURN_OFF_MINUTES from now
time_t t2 = myRTC.get();
tmElements_t tm;
breakTime(t2 + (60 * TURN_OFF_MINUTES), tm);
tm.Second = 0;
time_t a1 = makeTime(tm);
myRTC.setAlarm(DS3232RTC::ALM2_MATCH_HOURS, minute(a1), hour(a1), 1);
myRTC.alarm(DS3232RTC::ALARM_2);
myRTC.alarmInterrupt(DS3232RTC::ALARM_2, true);
Serial.print("Now moving to GETTING READY state; Alarm 2 RESET to ");
Serial.print(hour(a1));
Serial.print(":");
Serial.print(minute(a1));
Serial.println();
} else if (alarmState == GETTINGREADY) { // Since state = GETTINGREADY, move to state = DAYTIME
// Set the next alarm to NIGHTLIGHT_ON_HOUR and NIGHTLIGHT_ON_MINUTE
myRTC.setAlarm(DS3232RTC::ALM2_MATCH_HOURS, NIGHTLIGHT_ON_MINUTE, NIGHTLIGHT_ON_HOUR, 1);
myRTC.alarm(DS3232RTC::ALARM_2);
myRTC.alarmInterrupt(DS3232RTC::ALARM_2, true);
Serial.print("Now moving to DAYTIME state; Alarm 2 RESET to ");
Serial.print(NIGHTLIGHT_ON_HOUR);
Serial.print(":");
Serial.print(NIGHTLIGHT_ON_MINUTE);
Serial.println();
} else if (alarmState == DAYTIME) { // Since state = DAYTIME, move to state = NIGHTLIGHT
// As a default (since setAlarm2() will adjust, set alarm1 to weekday alarm time
myRTC.setAlarm(DS3232RTC::ALM2_MATCH_HOURS, WEEKDAY_WAKEUP_MINUTE, WEEKDAY_WAKEUP_HOUR, 0);
myRTC.alarm(DS3232RTC::ALARM_2);
myRTC.alarmInterrupt(DS3232RTC::ALARM_2, true);
Serial.print("Now moving to NIGHTLIGHT state; Alarm 2 RESET to weekday default of ");
Serial.print(WEEKDAY_WAKEUP_HOUR);
Serial.print(":");
Serial.print(WEEKDAY_WAKEUP_MINUTE);
Serial.println();
}
changeColor(); // Change the LED color and advance the state
}
}
}
void setAlarm2() {
// Set Alarm2 appropriately based on whether it is a weekend or weekday
if (weekday() == 1 || weekday() == 7) { // Is a weekend (Day of the week (1-7), Sunday is day 1)
myRTC.setAlarm(DS3232RTC::ALM2_MATCH_HOURS, WEEKEND_WAKEUP_MINUTE, WEEKEND_WAKEUP_HOUR, 1); // Set alarm 2 to weekend wakeup time
myRTC.alarm(DS3232RTC::ALARM_2);
myRTC.alarmInterrupt(DS3232RTC::ALARM_2, true);
Serial.print("Alarm 2 SET to ");
Serial.print(WEEKEND_WAKEUP_HOUR);
Serial.print(":");
Serial.print(WEEKEND_WAKEUP_MINUTE);
Serial.println();
} else { // Is a weekday
myRTC.setAlarm(DS3232RTC::ALM2_MATCH_HOURS, WEEKDAY_WAKEUP_MINUTE, WEEKDAY_WAKEUP_HOUR, 1);
myRTC.alarm(DS3232RTC::ALARM_2);
myRTC.alarmInterrupt(DS3232RTC::ALARM_2, true);
Serial.print("Alarm 2 SET to ");
Serial.print(WEEKDAY_WAKEUP_HOUR);
Serial.print(":");
Serial.print(WEEKDAY_WAKEUP_MINUTE);
Serial.println();
}
}
void changeColor() {
// Change the color and advance the state
Serial.println("DEBUG: Changing color and advancing state");
if (alarmState == NIGHTLIGHT) { // NIGHTLIGHT --> GETTINGREADY
Serial.println("In NIGHTLIGHT");
strip.fill(strip.Color(0, 0, 0, 0)); // Fill entire strip with nothing
strip.show();
strip.fill(strip.Color(0, 35, 0, 0)); // Fill entire strip with green
strip.show();
alarmState = GETTINGREADY; // Advance the state
return;
} else if (alarmState == GETTINGREADY) { // GETTINGREADY --> DAYTIME
Serial.println("In GETTINGREADY");
strip.fill(strip.Color(0, 0, 0, 0)); // No color for daytime
// TODO: Should I "turn it off" instead of settting to 0?
strip.show();
alarmState = DAYTIME;
return;
} else if (alarmState == DAYTIME) { // DAYTIME --> NIGHTLIGHT
Serial.println("In DAYTIME");
strip.fill(strip.Color(0, 0, 0, 0));
strip.show();
strip.fill(strip.Color(7, 0, 13, 0)); // Fill entire strip with purple
strip.show();
alarmState = NIGHTLIGHT;
return;
}
}
// UTILITY FUNCTIONS follow
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);
}
void formatTime(char *buf, time_t t) {
// format a time_t value, return the formatted string in buf (must be at least 25 bytes)
char m[4]; // temporary storage for month string (DateStrings.cpp uses shared buffer)
strcpy(m, monthShortStr(month(t)));
sprintf(buf, "%.2d:%.2d:%.2d %s %.2d %s %d",
hour(t), minute(t), second(t), dayShortStr(weekday(t)), day(t), m, year(t));
}
Thank you again for any insights/ideas