Final Project: Smart Mirror "Connectivity Display and Ambient Lights"

Created: December 5th, 2023

0

Proposal: 

The project that we chose was the Smart Mirror. It merges the functionality of a traditional mirror with modern digital displays. This is for the normal busy person who wants all the information in a quick glance. The main goal behind the creation of smart mirrors is to offer a more interactive and informative experience while maintaining the basic utility of a mirror. Smart mirrors can show real-time information such as weather updates, calendar events, news headlines, and more. In our project the main aspects of the mirror that we will focus on creating a regular mirror into a smart mirror that has a display and led lights. Connectivity will play a pivotal role in our smart mirror project. It will be able to monitor the weather and display it in the mirror. 


0

Our Smart Mirror Preliminary Sketch


0

Here we have the preliminary coding. We were trying to build upon the coding that had the LED lights fading that also implemented the the IFTTT. We wanted to see if we were able to implement the weather app instead of the Google Calendar.

0
void setup() {
    strip.begin ();
    strip.show();  
    
   
    Particle.function("fadeUp", handleFadeUp);
}

void loop() {
    if (timerStarted==true){
        
        long timeNow = millis();
        long timeElapsed = timeNow - timeStart;
        
        if(timeElapsed < durationFade){
            int colorValue = map(timeElapsed, 0, durationFade, 0, 255); 
            
            int r=colorValue;
            int g=0;
            int b=0;
            
            for(int i=0; i<strip.numPixels();i++){
                strip.setPixelColor(i,r,g,b);
                
            }
            strip.show();
        }else{
            timerStarted = false;
             for(int k=256; k>=0; k--){
                 for(int i=0;i<strip.numPixels();i++){
                    strip.setPixelColor(i,0,0,250);
                    strip.show();
        
               delay(10);
                }
             }
        }
    }

    else{
        for(int i=0;i<strip.numPixels();i++){
            strip.setPixelColor(i,10,10,10);
        
        strip.show();
        delay(10);
        }
    }
}

    
int handleFadeUp(String cmd){
    
    timeStart = millis(); 
    timerStarted =true;
    return 1;
}
Click to Expand
0

Here we started to build upon the code adding a web hook so that we could get the temperature. We at first were failing to get the temperature to work. We also added a sketch of how we wanted to implement the LED lights. One of the things that changed was that we didn't have any neopixels 8 LED lights. So we had to be satisfied with the strip LED lights. 

At the end we were happier with the design of the strip LED lights.

0
int lightPin = D2; 
int temperatureThreshold = 35;  

void setup() {
  Particle.subscribe("hook-response/TemperatureWebhook", myHandler, MY_DEVICES);

  pinMode(lightPin, OUTPUT);
}

void loop() {
  
  String data = String(10);

  Particle.publish("TemperatureWebhook", data, PRIVATE);

  delay(60000);
}


void myHandler(const char *event, const char *data) {

  String receivedStr = String(data);
  int loc1 = 0;
  int loc2 = 0;

  loc1 = receivedStr.indexOf("~");

 
  double temperature = receivedStr.substring(0, loc1).toFloat();

 
  adjustLightColor(temperature);
}


void adjustLightColor(double temperature) {
  
  if (temperature < temperatureThreshold) {
    analogWrite(lightPin, 0);  
  } else {
    analogWrite(lightPin, 255);  
  }
}
Click to Expand
0

First, we thought we would use a sensor to detect how hot it is. But instead we decided that an API would be a better route. Here in this code we started to understand how the API works. We ended up using open-meteo Weather Forecast API.

0
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>

#include "neopixel.h"
#define PIXEL_PIN D3
#define PIXEL_COUNT 62
#define PIXEL_TYPE WS2812
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

bool warm = true;

void getData()
{
        // Publish an event to trigger the webhook
  Particle.publish( "get-forecast" );

}

void setup() {

    strip.begin();
    strip.show();
    Particle.subscribe("hook-response/get-forecast", handleForecastReceived );
    getData();

}

int light_strip(String command)
{
    if (warm){
        warmer_fade();
        return 1;
    }
  else return -1;
}

//Webhook functions



// This function will handle data received back from the webhook
void handleForecastReceived(const char *event, const char *data) {
  // Handle the integration response

  String receivedStr =  String( data );
  int loc1 = 0;

  loc1 = receivedStr.indexOf("~");

  String temperature_str = receivedStr.substring(0,loc1);
  double temperature = (double) String(temperature_str).toFloat();
  double humidity = (double) String(receivedStr.substring(loc1+1)).toFloat();
  Particle.publish(receivedStr);

}


void cooler_fade(){

    for( int i = 0; i < strip.numPixels(); i++ ){
      strip.setPixelColor(i, 0, 100, 100); // set a color
      strip.show();
      delay( 100 );
     }
     for (int j = 0; j < 3; j++){
         for( int k = 0; k <256; k++ ){
            for( int i = 0; i < strip.numPixels(); i++ ){
                strip.setPixelColor(i, 0, k/3, k/2); // set a color
            }
            strip.show();
            delay( 10 );
        }   

    for( int k = 255; k >=0; k-- ){
        for( int i = 0; i < strip.numPixels(); i++ ){
            strip.setPixelColor(i, 0, k/3, k/2 ); // set a color
        }
            strip.show();
            delay( 10 );
            }
    }



    for( int i = 0; i < strip.numPixels(); i++ ){
        if (i>0){
             strip.setPixelColor(i-1, 0, 0, 0); // set a color
        }
      strip.setPixelColor(i, 0, 100, 100); // set a color
      strip.show();
      delay( 100 );
     }



}

void warmer_fade(){
    for( int i = 0; i < strip.numPixels(); i++ ){
      strip.setPixelColor(i, 235, 52, 100); // set a color
      strip.show();
      delay( 100 );
     }

     for (int j = 0; j < 3; j++){
         for( int k = 0; k <256; k++ ){
            for( int i = 0; i < strip.numPixels(); i++ ){
                strip.setPixelColor(i, k/2, 0, k/3); // set a color
            }
            strip.show();
            delay( 10 );
        }   

    for( int k = 255; k >=0; k-- ){
        for( int i = 0; i < strip.numPixels(); i++ ){
            strip.setPixelColor(i, k/2, 0, k/3); // set a color
        }
            strip.show();
            delay( 10 );
            }
    }



    for( int i = 0; i < strip.numPixels(); i++ ){
        if (i>0){
             strip.setPixelColor(i-1, 0, 0, 0); // set a color
        }
     strip.setPixelColor(i, 235, 52, 155); // set a color
      strip.show();
      delay( 100 );
     }

}

void loop() {

//   uint16_t blue = 0;
//   uint16_t red = 0;
//   uint16_t green = 0;

 // This makes it go brighter and then dim back down
    // warmer_fade();
    cooler_fade();


}
Click to Expand
0

Here we decided to add a function. We talked amongst ourselves and realized that temperature is different and varies person to person. So we implemented a function that allows the user to decide at what temperature is hot or cold for them.

0
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>

#include "neopixel.h"
#define PIXEL_PIN D3
#define PIXEL_COUNT 16
#define PIXEL_TYPE WS2812B
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

bool warm;
float limit =72;
float temperature;

void getData()
{
        // Publish an event to trigger the webhook
  Particle.publish( "get-forecast" );
}

int get_compare(String args){
    float set_tmp = String(args).toFloat();
    limit = set_tmp;
    return 1;
}


void setup() {

    strip.begin();
    strip.show();
    Particle.function("get_compare", get_compare);
    Particle.subscribe("hook-response/get-forecast", handleForecastReceived );
    getData();

}


//Webhook functions


// This function will handle data received back from the webhook
void handleForecastReceived(const char *event, const char *data) {
  // Handle the integration response

  String receivedStr =  String( data );
  int loc1 = 0;

  loc1 = receivedStr.indexOf("~");

  String temperature_str = receivedStr.substring(0,loc1);
  float tmp = String(temperature_str).toFloat();
  double humidity = (double) String(receivedStr.substring(loc1+1)).toFloat();
  //debugging string-- displays the temperature
  Particle.publish(receivedStr);
  temperature = tmp;
//   if (temperature > (double)72){
//       warm = true;
//   }
//   else{
//       warm = false;
//   }
}


void cooler_fade(){

    for( int i = 0; i < strip.numPixels(); i++ ){
      strip.setPixelColor(i, 0, 100, 100); // set a color
      strip.show();
      delay( 100 );
     }
     for (int j = 0; j < 3; j++){
         for( int k = 0; k <256; k++ ){
            for( int i = 0; i < strip.numPixels(); i++ ){
                strip.setPixelColor(i, 0, k/3, k/2); // set a color
            }
            strip.show();
            delay( 10 );
        }   

    for( int k = 255; k >=0; k-- ){
        for( int i = 0; i < strip.numPixels(); i++ ){
            strip.setPixelColor(i, 0, k/3, k/2 ); // set a color
        }
            strip.show();
            delay( 10 );
            }
    }



    for( int i = 0; i < strip.numPixels(); i++ ){
        if (i>0){
             strip.setPixelColor(i-1, 0, 0, 0); // set a color
        }
      strip.setPixelColor(i, 0, 100, 100); // set a color
      strip.show();
      delay( 100 );
     }



}

void warmer_fade(){
    for( int i = 0; i < strip.numPixels(); i++ ){
      strip.setPixelColor(i, 235, 52, 100); // set a color
      strip.show();
      delay( 100 );
     }

     for (int j = 0; j < 3; j++){
         for( int k = 0; k <256; k++ ){
            for( int i = 0; i < strip.numPixels(); i++ ){
                strip.setPixelColor(i, k/2, 0, k/3); // set a color
            }
            strip.show();
            delay( 10 );
        }   

    for( int k = 255; k >=0; k-- ){
        for( int i = 0; i < strip.numPixels(); i++ ){
            strip.setPixelColor(i, k/2, 0, k/3); // set a color
        }
            strip.show();
            delay( 10 );
            }
    }



    for( int i = 0; i < strip.numPixels(); i++ ){
        if (i>0){
             strip.setPixelColor(i-1, 0, 0, 0); // set a color
        }
     strip.setPixelColor(i, 235, 52, 155); // set a color
      strip.show();
      delay( 100 );
     }

}

void loop() {

 // This makes it go brighter and then dim back down
 if (temperature > limit){
      warmer_fade();
 }
 else{
     cooler_fade();
 }
    // if(warm){
    //     warmer_fade();
    // }
    // else{
    //     cooler_fade();
    // }
}
Click to Expand
0

Here we have the top and side view of the particle device and the wire connections. I also added a video of the device showing us that it is cold outside (temperature is less than 75 Degrees Fahrenheit. 

0
Top view of connection
Img 9412.thumb (2023)
0
Side View of device
Img 9413.thumb (2023)
0
Smart mirror prototype
Brian Hernandez - https://youtu.be/QnMgXd6vw7I?feature=shared
0

Here we started the early implementation of the display, this has been the hardest part. No one in the group had used a display or even knew where to start. We were having some connectivity issues with the particle. Below are the top and side view of the connections. 

0
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>

#include "neopixel.h"
#define PIXEL_PIN D3
#define PIXEL_COUNT 16
#define PIXEL_TYPE WS2812B
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

bool warm;
float limit =72;
float temperature;

void getData()
{
	// Publish an event to trigger the webhook
  Particle.publish( "get-forecast" );
  // triggers response to send GET request to api
}

int get_compare(String args){
    //function that gets user input for the dividing temperature
    float set_tmp = String(args).toFloat();
    limit = set_tmp;
    return 1;
}


void setup() {
    strip.begin();
    strip.show();
    Particle.function("get_compare", get_compare);
    Particle.subscribe("hook-response/get-forecast", handleForecastReceived );
    getData();
    
}


//Webhook functions


// This function will handle data received back from the webhook
void handleForecastReceived(const char *event, const char *data) {
  // Handle the integration response

  String receivedStr =  String( data );
  int loc1 = 0;

  loc1 = receivedStr.indexOf("~");

  String temperature_str = receivedStr.substring(0,loc1);
  //a float of temerpature is stored to tmp
  float tmp = String(temperature_str).toFloat();
  //humidity is stored to a double
  double humidity = (double) String(receivedStr.substring(loc1+1)).toFloat();
  //DISPLAY TO SCREEN HERE?
  //debugging string-- displays the temperature and humidity to console
  Particle.publish(receivedStr);
  temperature = tmp;
}


void cooler_fade(){

    for( int i = 0; i < strip.numPixels(); i++ ){
      strip.setPixelColor(i, 0, 100, 100); // set a color
      strip.show();
      delay( 100 );
     }
     for (int j = 0; j < 3; j++){
         for( int k = 0; k <256; k++ ){
            for( int i = 0; i < strip.numPixels(); i++ ){
                strip.setPixelColor(i, 0, k/3, k/2); // set a color 
            }
            strip.show();
            delay( 10 );
        }   
    
    for( int k = 255; k >=0; k-- ){
        for( int i = 0; i < strip.numPixels(); i++ ){
            strip.setPixelColor(i, 0, k/3, k/2 ); // set a color
        }
            strip.show();
            delay( 10 );
            }
    }
     

    
    for( int i = 0; i < strip.numPixels(); i++ ){
        if (i>0){
             strip.setPixelColor(i-1, 0, 0, 0); // set a color
        }
      strip.setPixelColor(i, 0, 100, 100); // set a color
      strip.show();
      delay( 100 );
     }
}

void warmer_fade(){
    for( int i = 0; i < strip.numPixels(); i++ ){
      strip.setPixelColor(i, 235, 52, 100); // set a color
      strip.show();
      delay( 100 );
     }
     
     for (int j = 0; j < 3; j++){
         for( int k = 0; k <256; k++ ){
            for( int i = 0; i < strip.numPixels(); i++ ){
                strip.setPixelColor(i, k/2, 0, k/3); // set a color 
            }
            strip.show();
            delay( 10 );
        }   
    
    for( int k = 255; k >=0; k-- ){
        for( int i = 0; i < strip.numPixels(); i++ ){
            strip.setPixelColor(i, k/2, 0, k/3); // set a color 
        }
            strip.show();
            delay( 10 );
            }
    }
     

    
    for( int i = 0; i < strip.numPixels(); i++ ){
        if (i>0){
             strip.setPixelColor(i-1, 0, 0, 0); // set a color
        }
     strip.setPixelColor(i, 235, 52, 155); // set a color 
      strip.show();
      delay( 100 );
     }

}

void loop() {

 // This makes it go brighter and then dim back down
 if (temperature > limit){
      warmer_fade();
 }
 else{
     cooler_fade();
 }

}
Click to Expand
0

The code of this project is fairly straight forward, as illustrated by this diagram. The code started with just the normal code to light up the neopixels, then we added a function that obtains data from the api. After that, we created two functions, a fade cool and fade warm that would display on repeat. In order to obtain the user data of at what temperature they would like the display to change color, we setup a function to be published to the particle platform, and we do this in the function setup(). After that, we parse the information from the api using a template and the particle integration. (Key component shown in pictures below).

 Lastly, we make sure to call the correct neopixel function to display the light as well as write to the display appropriately. 

0
Top view of display connection
Img 9435.thumb (2023)
0
Side View of device
Img 9434.thumb (2023)
0

We finally had the code to work for the display. We then connected the ambient lights and taped it all on the back of the mirror so we could have a clean presentation.

0

Here we have a final presentation of our project. We have the lights displaying the temperature (42.4 deg F) and the percentage of precipitation (0%).  We then typed in our function the number 10. Meaning that if the person believes anything above 10 degrees F is hot then the mirror will turn to the warmer color.

0
Final project “Smart Mirror”
Brian Hernandez - https://youtube.com/shorts/Jr2OkCFmoos?feature=shared
0

Here is our final code.

0
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>

#include "Adafruit_ST7789.h"
#include "SPI.h"
#include "Adafruit_GFX.h"

#include "neopixel.h"
#define PIXEL_PIN D3
#define PIXEL_COUNT 62
#define PIXEL_TYPE WS2812B

// You can't really have two of these on the same pins, but this is just to make sure it compiles
// It's not a working example.
// I've removed the examples because it's not possible to have dependencies for individual examples
// and the necessary libraries won't be included and the build will fail. Since other boards like
// the miniTFTWing have their own examples, you should just test this library with those examples.

//Adafruit_ST7789 st7789(&SPI, D2, D3, D4);



#if defined(ARDUINO_FEATHER_ESP32) // Feather Huzzah32
  #define TFT_CS         14
  #define TFT_RST        15
  #define TFT_DC         32

#elif defined(ESP8266)
  #define TFT_CS         4
  #define TFT_RST        16
  #define TFT_DC         5

#else
  // For the breakout board, you can use any 2 or 3 pins.
  // These pins will also work for the 1.8" TFT shield.
  #define TFT_CS         D10
  #define TFT_RST        -1 // Or set to -1 and connect to Arduino RESET pin
  #define TFT_DC         D8
#endif

// OPTION 1 (recommended) is to use the HARDWARE SPI pins, which are unique
// to each board and not reassignable. For Arduino Uno: MOSI = pin 11 and
// SCLK = pin 13. This is the fastest mode of operation and is required if
// using the breakout board's microSD card.

//Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_RST);

// OPTION 2 lets you interface the display using ANY TWO or THREE PINS,
// tradeoff being that performance is not as fast as hardware SPI above.
#define TFT_MOSI 12  // Data out
#define TFT_SCLK 13  // Clock out

Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);

bool warm;

Adafruit_ST7789 tft = Adafruit_ST7789(TFT_CS, TFT_DC, TFT_MOSI, TFT_SCLK, TFT_RST);


float p = 3.1415926;
float limit =72;
float temperature;

void getData()
{
	// Publish an event to trigger the webhook
  Particle.publish( "get-forecast" );
  // triggers response to send GET request to api
}

int get_compare(String args){
    //function that gets user input for the dividing temperature
    float set_tmp = String(args).toFloat();
    limit = set_tmp;
    return 1;
}

void setup(void) {
  strip.begin();
  strip.show();
  Serial.begin(9600);
  Serial.print(F("Hello! ST77xx TFT Test"));

  // Use this initializer (uncomment) if using a 1.3" or 1.54" 240x240 TFT:
  // tft.init(240, 240);           // Init ST7789 240x240

  // OR use this initializer (uncomment) if using a 1.69" 280x240 TFT:
  //tft.init(280, 280);           // Init ST7789 280x240

  // OR use this initializer (uncomment) if using a 2.0" 320x240 TFT:
  //tft.init(240, 320);           // Init ST7789 320x240

  // OR use this initialhttps://build.particle.io/build/6571ed7b2ae6f2018fb9b700#verifyizer (uncomment) if using a 1.14" 240x135 TFT:
  //tft.init(135, 240);           // Init ST7789 240x135
  
  // OR use this initializer (uncomment) if using a 1.47" 172x320 TFT:
  tft.init(172, 320);           // Init ST7789 172x320

  // OR use this initializer (uncomment) if using a 1.9" 170x320 TFT:
  //tft.init(170, 320);           // Init ST7789 170x320

  // SPI speed defaults to SPI_DEFAULT_FREQ defined in the library, you can override it here
  // Note that speed allowable depends on chip and quality of wiring, if you go too fast, you
  // may end up with a black screen some times, or all the time.
  //tft.setSPISpeed(40000000);
  
  
  Serial.println(F("Initialized"));

  uint16_t time = millis();
  tft.fillScreen(ST77XX_BLACK);
  time = millis() - time;

  Serial.println(time, DEC);

  
  // tft.drawLine(0, 0, 150, 150, ST77XX_YELLOW);
  
  Particle.function("get_compare", get_compare);
  Particle.subscribe("hook-response/get-forecast", handleForecastReceived );
  getData();
  // testdrawtext("hello", ST77XX_YELLOW);
}

void cooler_fade(){

    for( int i = 0; i < strip.numPixels(); i++ ){
      strip.setPixelColor(i, 0, 100, 100); // set a color
      strip.show();
      delay( 100 );
     }
     for (int j = 0; j < 3; j++){
         for( int k = 0; k <256; k++ ){
            for( int i = 0; i < strip.numPixels(); i++ ){
                strip.setPixelColor(i, 0, k/3, k/2); // set a color 
            }
            strip.show();
            delay( 10 );
        }   
    
    for( int k = 255; k >=0; k-- ){
        for( int i = 0; i < strip.numPixels(); i++ ){
            strip.setPixelColor(i, 0, k/3, k/2 ); // set a color
        }
            strip.show();
            delay( 10 );
            }
    }
     

    
    for( int i = 0; i < strip.numPixels(); i++ ){
        if (i>0){
             strip.setPixelColor(i-1, 0, 0, 0); // set a color
        }
      strip.setPixelColor(i, 0, 100, 100); // set a color
      strip.show();
      delay( 100 );
     }
}

void warmer_fade(){
    for( int i = 0; i < strip.numPixels(); i++ ){
      strip.setPixelColor(i, 235, 52, 100); // set a color
      strip.show();
      delay( 100 );
     }
     
     for (int j = 0; j < 3; j++){
         for( int k = 0; k <256; k++ ){
            for( int i = 0; i < strip.numPixels(); i++ ){
                strip.setPixelColor(i, k/2, 0, k/3); // set a color 
            }
            strip.show();
            delay( 10 );
        }   
    
    for( int k = 255; k >=0; k-- ){
        for( int i = 0; i < strip.numPixels(); i++ ){
            strip.setPixelColor(i, k/2, 0, k/3); // set a color 
        }
            strip.show();
            delay( 10 );
            }
    }
     

    
    for( int i = 0; i < strip.numPixels(); i++ ){
        if (i>0){
             strip.setPixelColor(i-1, 0, 0, 0); // set a color
        }
     strip.setPixelColor(i, 235, 52, 155); // set a color 
      strip.show();
      delay( 100 );
     }

}

void loop() {
   // This makes it go brighter and then dim back down
  if (temperature > limit){
    warmer_fade();
     }
     else{
         cooler_fade();
     }
}



//Webhook functions


// This function will handle data received back from the webhook
void handleForecastReceived(const char *event, const char *data) {
  // Handle the integration response

  String receivedStr =  String( data );
    Particle.publish(receivedStr);

  int loc1 = 0;

  loc1 = receivedStr.indexOf("~");

  String temperature_str = receivedStr.substring(0,loc1);
  String humidity_str = receivedStr.substring(loc1+1);
  //a float of temerpature is stored to tmp
  float tmp = String(temperature_str).toFloat();
  //humidity is stored to a double
  double humidity = (double) String(receivedStr.substring(loc1+1)).toFloat();
  
  char temperature_chars[5];
  char humidity_chars[5];
  
  temperature_str.toCharArray(temperature_chars, 5);
  humidity_str.toCharArray(humidity_chars, 5);
  //DISPLAY TO SCREEN HERE?
  testdrawtext(0, 0, 7, temperature_chars, ST77XX_WHITE);
  tft.print("F\n\n");
  tft.print(humidity_chars);
  tft.print("%");
//debugging string-- displays the temperature and humidity to console
  temperature = tmp;
}

void testlines(uint16_t color) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, 0, x, tft.height()-1, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, 0, tft.width()-1, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, 0, x, tft.height()-1, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, 0, 0, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(0, tft.height()-1, x, 0, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(0, tft.height()-1, tft.width()-1, y, color);
    delay(0);
  }

  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, x, 0, color);
    delay(0);
  }
  for (int16_t y=0; y < tft.height(); y+=6) {
    tft.drawLine(tft.width()-1, tft.height()-1, 0, y, color);
    delay(0);
  }
}

void testdrawtext(uint16_t x, uint16_t y, uint16_t size, char *text, uint16_t color) {
  tft.setCursor(x, y);
  tft.setTextColor(color);
  tft.setTextWrap(true);
  tft.setTextSize(size);
  tft.print(text);
}

void testfastlines(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t y=0; y < tft.height(); y+=5) {
    tft.drawFastHLine(0, y, tft.width(), color1);
  }
  for (int16_t x=0; x < tft.width(); x+=5) {
    tft.drawFastVLine(x, 0, tft.height(), color2);
  }
}

void testdrawrects(uint16_t color) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=0; x < tft.width(); x+=6) {
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color);
  }
}

void testfillrects(uint16_t color1, uint16_t color2) {
  tft.fillScreen(ST77XX_BLACK);
  for (int16_t x=tft.width()-1; x > 6; x-=6) {
    tft.fillRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color1);
    tft.drawRect(tft.width()/2 -x/2, tft.height()/2 -x/2 , x, x, color2);
  }
}

void testfillcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=radius; x < tft.width(); x+=radius*2) {
    for (int16_t y=radius; y < tft.height(); y+=radius*2) {
      tft.fillCircle(x, y, radius, color);
    }
  }
}

void testdrawcircles(uint8_t radius, uint16_t color) {
  for (int16_t x=0; x < tft.width()+radius; x+=radius*2) {
    for (int16_t y=0; y < tft.height()+radius; y+=radius*2) {
      tft.drawCircle(x, y, radius, color);
    }
  }
}

void testtriangles() {
  tft.fillScreen(ST77XX_BLACK);
  uint16_t color = 0xF800;
  int t;
  int w = tft.width()/2;
  int x = tft.height()-1;
  int y = 0;
  int z = tft.width();
  for(t = 0 ; t <= 15; t++) {
    tft.drawTriangle(w, y, y, x, z, x, color);
    x-=4;
    y+=4;
    z-=4;
    color+=100;
  }
}

void testroundrects() {
  tft.fillScreen(ST77XX_BLACK);
  uint16_t color = 100;
  int i;
  int t;
  for(t = 0 ; t <= 4; t+=1) {
    int x = 0;
    int y = 0;
    int w = tft.width()-2;
    int h = tft.height()-2;
    for(i = 0 ; i <= 16; i+=1) {
      tft.drawRoundRect(x, y, w, h, 5, color);
      x+=2;
      y+=3;
      w-=4;
      h-=6;
      color+=1100;
    }
    color+=100;
  }
}

void tftPrintTest() {
  tft.setTextWrap(false);
  tft.fillScreen(ST77XX_BLACK);
  tft.setCursor(0, 30);
  tft.setTextColor(ST77XX_RED);
  tft.setTextSize(1);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_YELLOW);
  tft.setTextSize(2);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_GREEN);
  tft.setTextSize(3);
  tft.println("Hello World!");
  tft.setTextColor(ST77XX_BLUE);
  tft.setTextSize(4);
  tft.print(1234.567);
  delay(1500);
  tft.setCursor(0, 0);
  tft.fillScreen(ST77XX_BLACK);
  tft.setTextColor(ST77XX_WHITE);
  tft.setTextSize(0);
  tft.println("Hello World!");
  tft.setTextSize(1);
  tft.setTextColor(ST77XX_GREEN);
  tft.print(p, 6);
  tft.println(" Want pi?");
  tft.println(" ");
  tft.print(8675309, HEX); // print 8,675,309 out in HEX!
  tft.println(" Print HEX!");
  tft.println(" ");
  tft.setTextColor(ST77XX_WHITE);
  tft.println("Sketch has been");
  tft.println("running for: ");
  tft.setTextColor(ST77XX_MAGENTA);
  tft.print(millis() / 1000);
  tft.setTextColor(ST77XX_WHITE);
  tft.print(" seconds.");
}

void mediabuttons() {
  // play
  tft.fillScreen(ST77XX_BLACK);
  tft.fillRoundRect(25, 10, 78, 60, 8, ST77XX_WHITE);
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_RED);
  delay(500);
  // pause
  tft.fillRoundRect(25, 90, 78, 60, 8, ST77XX_WHITE);
  tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_GREEN);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_GREEN);
  delay(500);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_BLUE);
  delay(50);
  // pause color
  tft.fillRoundRect(39, 98, 20, 45, 5, ST77XX_RED);
  tft.fillRoundRect(69, 98, 20, 45, 5, ST77XX_RED);
  // play color
  tft.fillTriangle(42, 20, 42, 60, 90, 40, ST77XX_GREEN);
}
Click to Expand
0

Feedback/ What to improve 

After presenting we were given great feedback. Some of the feedback was on including a voice activation system that would include Siri or Amazon Alexa and allow the mirror to be voice activated. That would allow for anything ranging from asking questions to putting music. The next crucial feedback was the aesthetic. We could improve the frame and the way we have the ambient lights surrounding the mirror. One example that was given was putting a milky white sheet so you can't see the individual lights. The last and favorite piece of advice was  adding a display that would allow for notes or affirmations. Moving forward those are some pieces that we would like to add to our prototype.

0

Bill of Materials

Particle controller, Temperature API, LCD screen (for display), Ambient Light (LED Light Strip), mirror

0

References:

- Engmann, Nick. “Magic Mirror Module for Particle.Io Data.” Particle Projects, 11 May 2020, particle.hackster.io/nick-engmann/magic-mirror-module-for-particle-io-data-bbc5c0.

- josh_kilinc, and Instructables. “Smart Mirror.” Instructables, Instructables, 13 June 2022, www.instructables.com/Smart-Mirror-8/. 

-Braun, Max. “Smarter Mirrors and How They’re Made.” Medium, OneZero, 27 July 2020, onezero.medium.com/smarter-mirrors-and-how-theyre-made-327997b9eff7. 

-https://diotlabs.daraghbyrne.me/docs/working-with-data/webhooks/openmeteo_weather

0
Max Braun
Prototype example2.thumb (2018)
0
Max Braun
Prototype example.thumb Max Braun (2018)
0

Upon receiving some feedback from our demon, we realized that in order to make our design more interactive and user centered, we should try to display more information that is customizable. Because some people told us they would like to know more weather information, while others said that they wish to put a To Do list that they can review in the morning. I think having a function where users can text the particle to display the information on a second display screen would be really cool. 

x
Share this Project

Courses

48-675 Designing for the Internet of Things 24

· 11 members

A hands-on introductory course exploring the Internet of Things and connected product experiences.


Focused on
About

Final Project: Smart Mirror "Connectivity Display and Ambient Lights"