Creating a gadget to make my habits stick

If you’re anything like me, there are several things you want to do consistently that you always forget. From exercising, to cleaning, I’m always forgetting.

So I made a device based on an Arduino nano, and it has really helped me stick to those habits that I used to forget.

As I was working on this, I realized, that this is probably the simplest and easiest to do project that is still useful (my bare-essentials version was just adding a single line of code to the blink sample that comes with the Arduino IDE).

Parts List:

And just in case you liked the ‘Clock tower’ design. Here are the components for those:

Books about habits:

  • Atomic Habits by James Clear (probably the most actionable of the bunch)
  • Switch by Chip and Dan Heath (a great read about what makes people change or stick to certain behaviors, not as actionable, but really interesting)
  • The Power of Habit by Charles Duhigg (a lot of theory about how habits work and some actionable content. It is interesting, but I would start with Atomic Habits before moving to this one)
  • The Now Habit by Neil Flore (it’s interesting, but my least favorite among these. It’s strategies to overcome procrastination, but again, I’d start with Atomic Habits and Switch).
Code
int pinLed = 2;

int dip1 = 11,
dip2 = 10,
dip3 = 9,
dip4 = 8,
dip5 = 7,
dip6 = 6;

unsigned long millisPerHour = 3600000;
unsigned long millisPerDay = 24 * millisPerHour;

int previousPeriod = 0;
int millisBetweenBlinks = 0;
int millisBlinkDuration = 1000;

bool useDynamicWarningDuration = true;

unsigned long blinkStart = 0;

// the setup function runs once when you press reset or power the board
void setup() {

pinMode(dip1, INPUT_PULLUP);
pinMode(dip2, INPUT_PULLUP);
pinMode(dip3, INPUT_PULLUP);
pinMode(dip4, INPUT_PULLUP);
pinMode(dip5, INPUT_PULLUP);
pinMode(dip6, INPUT_PULLUP);

Serial.begin(9600);

int d1 = !digitalRead(dip1);
int d2 = !digitalRead(dip2);
int d3 = !digitalRead(dip3);
int d4 = !digitalRead(dip4);
int d5 = !digitalRead(dip5);
int d6 = !digitalRead(dip6);

Serial.print("Pins: ");

Serial.print(d1);
Serial.print(" ");
Serial.print(d2);
Serial.print(" ");
Serial.print(d3);
Serial.print(" ");
Serial.print(d4);
Serial.print(" ");
Serial.print(d5);
Serial.print(" ");
Serial.print(d6);
Serial.println(" ");

int days = d1 + (2 * d2) + (4 * d3) + (8 * d4) + (16 * d5);

useDynamicWarningDuration = d6;

if(days == 0)
{
Serial.println("----- Test Mode ------");
millisPerHour = 1000;
millisPerDay = 30000;
days = 1;
}

blinkStart = (days * millisPerDay) - millisPerHour;

Serial.print("Millis Per Hour: ");
Serial.println(millisPerHour);
Serial.print("millisPerDay: ");
Serial.println(millisPerDay);
Serial.print("Days: ");
Serial.println(days);
Serial.print("Seconds to start blinking: ");
Serial.println(blinkStart / 1000);
Serial.print("Dynamic Warning: ");
Serial.println(useDynamicWarningDuration);

pinMode(pinLed, OUTPUT);

//Greeting Blink
{
int singles = days%10;
int tens = (days - singles) / 10;
int startBlinkDuration = 150;

for(int i = 0; i < tens; i++)
blink(startBlinkDuration, startBlinkDuration);

if(tens > 0)
delay(1000);

for(int i = 0; i < singles; i++)
blink(startBlinkDuration,startBlinkDuration);

}
}

void blink(int millisDelay, int millisDuration)
{
digitalWrite(pinLed, HIGH); // turn the LED on (HIGH is the voltage level)
delay(millisDuration); // wait
digitalWrite(pinLed, LOW); // turn the LED off by making the voltage LOW
delay(millisDelay); // wait
}

// the loop function runs over and over again forever
void loop()
{
int previousPeriod = millisBetweenBlinks;

if(useDynamicWarningDuration && blinkStart > millisPerDay && millis() > (blinkStart - (millisPerDay / 3))) //Warning blink
{
millisBetweenBlinks = 5000;
millisBlinkDuration = 100;
}

if(millis() >= blinkStart) //Regular blink
{
millisBetweenBlinks = 1000;
millisBlinkDuration = millisBetweenBlinks;
}
if(useDynamicWarningDuration)
{
if(millis() >= blinkStart + millisPerDay )
{
millisBetweenBlinks = 500;
millisBlinkDuration = millisBetweenBlinks;
}
if(millis() >= blinkStart + millisPerDay * 2)
{
millisBetweenBlinks = 250;
millisBlinkDuration = millisBetweenBlinks;
}
if(millis() >= blinkStart + millisPerDay * 3)
{
millisBetweenBlinks = 125;
millisBlinkDuration = millisBetweenBlinks;
}
}

if(previousPeriod != millisBetweenBlinks)
{

if(previousPeriod == 0)
Serial.println("Starting blinking");
else
{
Serial.print("Sped up blinking. New period: ");
Serial.println(millisBetweenBlinks);
}
}

if(millisBetweenBlinks > 0)
blink(millisBetweenBlinks, millisBlinkDuration);

}