Anniversary Gift

I'm currently building an anniversary gift for my wife. It's our six-month anniversary on Wednesday the 21. I wanted to build her a wooden box that displays how many days we've been together, so I went and purchased a DS3231 Precision breakout and a 7-segment display w/I2C from Adafruit as well as a servo.

What I'm trying to do is cut a hole in the box at the top where I'll stick out the display to show the days, and on the inside I'll hide the RTC to keep track of the time and the servo will be attached to the latch so it will open on a specific day.

My issue is that I'm new to the world of programming, and thus know nothing about how to make this work. I want the RTC to keep track of how many days have passed since our first date (January 21, 2015) so it can print that to the display. It will all keep working normally until our 12 month anniversary where the servo will move itself and allow the box to be opened.

How can I get the technical know-how within 17 days to make this work?

No hardware/programming experience, 17 days is cutting this close.

Suggest you do this next year.

But, what have you done with the Arduino, if anything.

.

You know what date in the past is interesting. There are Time libraries that can convert that date to an interval since 1/1/2000.

You know what time it is now. At least, the RTC knows, and can tell you. One of the ways that it can tell you is in seconds since 1/1/2000.

The time you have been together is the difference between those two values.

Displaying the interval on the LCD is (nearly) trivial.

What is the servo supposed to do?

"What is the servo supposed to do?"
I think it's to unlock the box revelling the diamond necklace within.

.

Correct. I've figured out most of the parts, but I don't have any clue what code to use to calculate how long since a past date.

I have this:

void loop() {
DateTime now = rtc.now();
Serial.print("Time since First Date 1/21/2017: ");
Serial.print(now.unixtime());
Serial.print("s = ");
Serial.print(now.unixtime() / 86400L);
Serial.println("d");

}

but it's calculating how long since 1970 and not since 2015...

Edit:

Here's the entire thing of code so you can see if I'm doing this right.

#include <Wire.h>
#include "RTClib.h"

#include <Servo.h>

#include <Adafruit_GFX.h>
#include <gfxfont.h>

#include <Adafruit_LEDBackpack.h>

RTC_DS3231 rtc;

void setup() {
Serial.begin(9600);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
if (rtc.begin()) {
rtc.adjust(DateTime(F(DATE), F(TIME)));
//rtc.adjust(DateTime(2017, 1, 21, 0, 0, 0));
Serial.println(F("RTC TIME SET"));
digitalWrite(LED_BUILTIN, HIGH);
}
else {
Serial.println(F("Couldn't find RTC"));
for(boolean b; ; b = !b) {
digitalWrite(LED_BUILTIN, b);
delay(250);
}
}
}

void loop() {
DateTime now = rtc.now();
Serial.print("Time since First Date 1/21/2015: ");
Serial.print(now.unixtime());
Serial.print("s = ");
Serial.print(now.unixtime() / 86400L);
Serial.println("d");

if (now == DateTime(2017, 1, 21, 0, 0, 0)) {
//servo is switched off
}
}

You understand what you are doing...

Raising the bar for every anniversary henceforth.

Perhaps try to give her Blink Without Delay for the sixth month.

:wink:

but it's calculating how long since 1970 and not since 2015...

Well, of course it is.

You need to create another DateTime instance, weJustWhatever, that is your "we just met/got married/whatever" date.

Then, the interval is now - weJustWhatever.

By the way, 17 days is plenty of time to learn enough about coding to make this project work.

Is this to be battery operated?
Is this supposed to be a secret?
What kind of box are you going to make?

Always have a fallback!
.

Yes, all the hardware is worked out. All I need is the software.

This may help for timing:

.

Link to one of Jack's examples:

I've figured most of it out, literally all I need now is help calculating the days passed since 1/21/2015. I know the theory, but I don't know what code to use. Any ideas?

Edit:
I realized that what I should do is calculate the unixtime from 1970 to present date, than the unixtime from the first date than subtract the two and the difference (if i divide each one by 86400) will give me the amount of days from the first date to present. Now all I need to do is program it.

Edit 2:
I can't believe I didn't know anything about programming this morning... I added a variable in setup:

firstDate = DateTime(2015, 1, 21, 0, 0, 0);

and I did the following operation in the loop in order to calculate days since than:

DateTime now = rtc.now()
Serial.print("Days: ")
Serial.println((now.unixtime() / 86400L) - (firstDate.unixtime() / 86400L));

Now what?

Use the Time library. You can use makeTime() to create the Unix time for 1/21/2015. Subtracting then from now in Unix time gives you the number of seconds. Then just divide by 606024.

Andromeda_:
Now what?

The library you are using has a cool Class called TimeSpan.

You can use that and its methods to get what you want, quite simply...

Something like this (compiles but not tested) using the example from Adafruit's GitHub:

// Date and time functions using a DS3231 RTC connected via I2C and Wire lib
#include <Wire.h>
#include "RTClib.h"

RTC_DS3231 rtc;

char daysOfTheWeek[7][12] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};

DateTime weddingDay(2015, 1, 21);  //EDITED to correct actual wedding date ;)

void setup ()
{
#ifndef ESP8266
  while (!Serial); // for Leonardo/Micro/Zero
#endif
  Serial.begin(9600);
  delay(3000); // wait for console opening
  
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

  if (rtc.lostPower()) {
    Serial.println("RTC lost power, lets set the time!");
    // following line sets the RTC to the date & time this sketch was compiled
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    // This line sets the RTC with an explicit date & time, for example to set
    // January 21, 2014 at 3am you would call:
    // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0));
  }
}

void loop ()
{
  DateTime now = rtc.now();
  TimeSpan marriageDuration = now - weddingDay;
  char timeNow[64] = "";
  sprintf(timeNow, "%s\t%2d/%02d/%d\t%2d:%2d:%2d\n", daysOfTheWeek[now.dayOfTheWeek()], now.month(), now.day(), now.year(), now.hour(), now.minute(), now.second());
  Serial.print(timeNow);
  sprintf(timeNow, "Enjoying %d days of wedded bliss...\n", marriageDuration.days());
  Serial.print(timeNow);
  delay(1000);
}

I've finally finished the coding, but I have one problem. When I hook everything up I get the following warning:

Category 'Real-time clock' in library DS3231 is not valid. Setting to 'Uncategorized'

Will this affect my project?
Also, for some reason the date is 20 days behind, why is this?

#include <Wire.h>
#include "RTClib.h"

#include <Servo.h>

#include <Adafruit_GFX.h>
#include <gfxfont.h>

#include "Adafruit_LEDBackpack.h"


RTC_DS3231 rtc;
Adafruit_7segment matrix = Adafruit_7segment();

DateTime firstDate = DateTime(2017, 1, 21, 0, 0, 0);

void setup() {
  #ifndef __AVR_ATtiny85__
      Serial.begin(9600);
      Serial.println("Display test");
  #endif
      matrix.begin(0x70);

  matrix.setBrightness(8);
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);
  
  //DateTime firstDate = DateTime(2017, 1, 21, 0, 0, 0);
  
  if (rtc.begin()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    //rtc.adjust(DateTime(2017, 1, 21, 0, 0, 0));
    Serial.println(F("RTC TIME SET"));
    digitalWrite(LED_BUILTIN, HIGH);
  }
  else {
    Serial.println(F("Couldn't find RTC"));
    for(boolean b;  ; b = !b) {
      digitalWrite(LED_BUILTIN, b);
      delay(250);
    }
  }
}

void loop() {
  DateTime now = rtc.now();
  Serial.print("Days: ");
  int daysSince = floor((now.unixtime() / 86400L) - (firstDate.unixtime() / 86400L));
  Serial.print(daysSince);
  matrix.print(daysSince, DEC);
  matrix.writeDisplay();
  delay(3600000);
}

Just a comment about right side of this equation:

int daysSince = floor((now.unixtime() / 86400L) - (firstDate.unixtime() / 86400L));

because unixtime() returns an integer, and your are dividing by an integer, you are performing Integer Division... there is no fractional remainder. So, floor will not affect the result and does nothing.

Alright, I've got most of the software up and ready now. I think this will be my final problem, but I don't know how to make the servo work with the rest of the design. When I plug the servo in to the arduino power the entire thing just ends up failing, how can I power it efficiently? (Hopefully without a transistor...)

Recommend you use a P channel MOS FET to enable power to the servo.
However, you could use a 5 volt relay picked by a transistor and the Arduino.

There are sensitive 5 volt relays available with 130 Ω coil ~30ma
.