A spherical glass box that glows in multicolored gradients each morning to remind the user to take their prescription medicine, and turns off and displays the time opened after the user opens the box.

Overall view of the Medicine Remembrall while it is glowing

Close up on OLED display and electronics box after the box has been opened

Close up on opened box, IR monitor, and space for prescription bottle

A short clip of the device in use, including being opened.

A video of the full color spectrum the Remembrall cycles through.

Progress

These were my original sketches of the idea. I experimented with the idea of using a hall sensor or an accelerometer to detect the opening of the box.

This was the cardboard version of the original box design which I used to test the hall sensor with the opening and closing of a box. Unfortunately, the hall sensor kept yielding unreliable results due to the magnetism of the breadboards, Arduino, and my laptop, and I quickly realized that an IR sensor would be easier to use, because unlike if I used an accelerometer, I would not have to attach any electrical components to the lid of the box.

Wiring the LEDs and OLED display when I had considered using the Arduino’s own timing mechanism to set the intervals at which the LEDs reset and have the display show the time since opening

Using the Arduino’s built in timing mechanism didn’t make sense as it meant that the time would be reset every time the device was unplugged, and doing the conversions between milliseconds elapsed since the box was opened to a normal time display of hours, minutes, and seconds, seemed like unnecessary work, so I added in a seperate Real Time Clock component.

A video of the LED strips initializing as the time hits 9:00:00

My electronic components could not fit in the tight space of the initial box design without becoming significantly messier, so I decided to place them in a separate box, allowing for a more creative design for the actual lighted box.

Because my design options for the box were no longer limited by fitting the electronics inside of it, I decided to switch from using frosted acrylic to diffuse the LEDs to wrapping them around the inside of a glass bowl to be reflected and diffused by the central cylinder, which hides the prescription bottle. This was able to create an effect of glowing from the middle similar to a Remembrall in Harry Potter, a sphere which glows if its user has forgotten something, which is where the final project got its name.

Discussion

It’s tough to demo time-based things. Might be advantageous to have a debug mode, just for demo purposes.”

During the critiques, I simply changed the time when the LEDs initialize in the code so that the class could watch the LEDs turn on due to the time. If I had planned this better, I would’ve had this time as a variable at the top of the code so I could edit it easier, or I could simply have set the code to begin the first time it is uploaded as if the box hadn’t been opened yet, by setting the initial value of the variable timeYet to 1.

Soldering your items might be good. Otherwise, the box is well thought of to hide all the wiring.

After receiving my critiques, I cleaned up my wiring and covered the elements outside the two boxes in electrical tape, but if I had had additional time, I think I definitely should’ve soldered the items that I connected through female-to-male jumpers.

While I find the remembrall-inspired glowing effect from the box incredibly beautiful, my primary critique for myself is not leaving enough time to work on the physical design. If I’d had more time, I would’ve soldered all of the wiring and used a more durable material than construction paper as the diffuser inside the remembrall. I’m very happy with the concept behind it, and in the past week of use, it has improved my life by reminding me to take my meds daily, and only once daily. I find myself checking the time on the box to confirm when I took my meds at various times throughout the day because I don’t remember taking them and would otherwise have the urge to take them a second time. Since this is something that I use every day, I do intend to devote more time to improving it in the future, by creating a more durable box for the middle of the remembrall and to hold the electronics, and soldering the wires. Ideally, I would drill a hole in the bottom of the bowl so the wiring didn’t have to stick out of the top, but the current bowl is glass, which would make this difficult. I might eventually go back to the initial idea of laser-cutting an acrylic box that can fit both the electronics and functional part of the device, but I am very attached to the remembrall theme that is created through the round shape and diffusion from the center. The most important lesson to me from working on this project was not the result of a specific component or design choice; through a combination of different ultimately scrapped approaches, I strengthened my ability to realize when an idea like the using the hall sensor or converting the arduino’s found time from milliseconds to hours, minutes, and seconds was not worth the extra level of time that it would require to make right, and to move on to a new approach. My personal impulse is to always finish everything I started exactly how I started it, and if something isn’t working but is theoretically capable of working after I put a lot of time into repairing it, I tend to hyper focus on making that specific idea work, instead of moving on to something that will work more easily, which turns into a massive waste of time that could be better spent on a different part of the project. I also learned a lot about the Arduino’s capabilities to tell time and the existence of time variables and how to operate on them through splitting strings so that I can compare the value of the current time to a set alarm time to determine if it is time yet to initialize the LEDs.

Schematic

Code

/*
 * The Medicine Remembrall
 * Adrien Krupenkin, 2019
 * 
 * Sets an LED strip to start cycling through a rainbow gradient at a set time each morning, 
 * until an infrared detector senses that the box has opened, turning off the LEDs and displaying 
 * when the box was opened.
 */
#include <DS3231.h>
#include <Wire.h>

#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <gfxfont.h>
#include <DS3231.h>
#ifdef __AVR__
#include <Adafruit_NeoPixel.h>

  #include <avr/power.h>
#endif

#include "Arduino.h"
#include "SPI.h"


#define LEDPIN 2
#define IRPIN A0
#define OLED_RESET 4
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels

Adafruit_SSD1306 disp(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
DS3231  rtc(SDA, SCL);
Adafruit_NeoPixel strip = Adafruit_NeoPixel(30, LEDPIN, NEO_GRB + NEO_KHZ800);  //setup of LED strip

int x = 123;
int val;    // variable to read the value from the analog pin
int nLEDs = 30;   //value for number of LEDs used
int timeYet = 0;
Time t;
Time opened;
int displayTime;
int irVal = 100;
int Hor;
int Min;
int Sec;
int hourOpened = 0;
int minOpened = 0;
int secOpened = 0;
String openedTime;

void setup() {
  rtc.begin();
  
  // The following lines were uncommented in one upload to set date and time and recommented
 // rtc.setDOW(SUNDAY);     
 // rtc.setTime(11, 36, 00);     // Set the time
 // rtc.setDate(3, 3, 2019);   // Set the date
  Wire.begin();
  disp.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  pinMode(LEDPIN, OUTPUT);  
  pinMode(IRPIN, INPUT);
  Serial.begin(9600);
    disp.display();

  // Clear the buffer
  disp.clearDisplay();
   disp.display();
    strip.begin(); 
    strip.show();

}

void loop() {
  //Check time
   t = rtc.getTime();
   Hor = t.hour;
   Min = t.min;
   Sec = t.sec;
   if( Hor == 8 &&  (Min == 00 || Min == 01)){
        timeYet = 1; 
   }
   Serial.println(timeYet);
  uint16_t i, j;
  if (timeYet == 0) //if it's not time, turn off LEDs and display the time when the box was last opened
  {
    strip.setBrightness(0);
    strip.show();
    disp.clearDisplay();
    disp.setTextSize(1); // Draw 2X-scale text
    disp.setTextColor(WHITE);
    disp.setCursor(10, 0);
    disp.println("Time Opened:");
    disp.setTextSize(2); // Draw 2X-scale text
    disp.setTextColor(WHITE);
    disp.setCursor(10, 10);
    disp.println(openedTime);
    disp.display();
  }
  if (timeYet == 1) //if it's past the set morning light time, turn on LEDs and display time
  {
    strip.setBrightness(50);
    strip.show();   // write all the pixels out
  //loop to write LEDs based on color from wheel 
  for(j=0; j<256; j++) {  
    for(i=0; i<strip.numPixels(); i++) {
      if(timeYet == 1)
      {
      strip.setPixelColor(i, Wheel((i+j) & 255));
    strip.show();
      }
    }
    //Display Time (do in this loop so it doesn't get delayed)
    disp.clearDisplay();
    disp.setTextSize(1); // Draw 2X-scale text
    disp.setTextColor(WHITE);
    disp.setCursor(10, 0);
    disp.println("Current Time:");
    disp.setTextSize(2); // Draw 2X-scale text
    disp.setTextColor(WHITE);
    disp.setCursor(10, 10);
    disp.println(rtc.getTimeStr());
    disp.display(); 
    irVal = analogRead(IRPIN); //check if the box has been opened
    Serial.println(irVal);
     if (irVal<100){
    openedTime = rtc.getTimeStr();
    timeYet = 0; //if the box has been opened, set the time setting to be not time yet for LEDs
  }
    }
    }
    irVal = analogRead(IRPIN);
    Serial.println(irVal);
     if (irVal<100){
    openedTime = rtc.getTimeStr();
    timeYet = 0;
    strip.setBrightness(0);
    strip.show();
    disp.clearDisplay();
    disp.setTextSize(1); // Draw 2X-scale text
    disp.setTextColor(WHITE);
    disp.setCursor(10, 0);
    disp.println("Time Opened:");
    disp.setTextSize(2); // Draw 2X-scale text
    disp.setTextColor(WHITE);
    disp.setCursor(10, 10);
    disp.println(openedTime);
    disp.display();
  }
}

//code to cycle through different LED colors
uint32_t Wheel(byte WheelPos) {
  WheelPos = 255 - WheelPos;
  if(WheelPos < 85) {
    return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  }
  if(WheelPos < 170) {
    WheelPos -= 85;
    return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
  WheelPos -= 170;
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
}