top of page
Writer's pictureElvin Shoolbraid

Challenge 9 - Sunrise Lamp

For this challenge, I chose to design an alarm clock that simulated a sunrise by fading through different colours and brightness's of light. I also wanted to be able to set the time and the alarm time, and have the current time output to an lcd display.


Schematic:


Photo of circuit:


Code:

/*
   Sunrise Lamp Sketch
   by Elvin Shoolbraid, created June 2, 2022
   This program will fade an array of RGB Leds on in a
   sunrise-like fashion every 24 hours, with an LCD
   to display time and a potentiometer/button combo
   to set time and alarm time.
*/


//libraries
#include <LiquidCrystal.h>
#include <Adafruit_NeoPixel.h>
const int neoPin = 6;                                          //neopixel pin
Adafruit_NeoPixel ring = Adafruit_NeoPixel(24, neoPin);        //define a neopixel ring with 24 leds
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);                        //lcd data pin locations

const int enterButtonPin = 7;   //button pins
const int plusButtonPin = 8;
int enterButtonState = 0;       //variable to hold button press states
int plusButtonState = 0;
int currentTime[2] = {0, 0};    //variable for the current time
int alarmTime[2] = {0, 0};      //variable to remember when the sunrise happens

void setup() {
  lcd.begin(16, 2); // Set up the number of columns and rows on the LCD.

  ring.begin();     //initialize the ring
  ring.show();

  Serial.begin(9600); //start serial for debug

  pinMode(enterButtonPin, INPUT);    //set button pins to input
  pinMode(plusButtonPin, INPUT);
}

void loop()
{

  currentTime[0] = setTime(0, 0);    //The current time hours variable is set to the output of the setTime function
  //with input variable 0 for current time and 0 for hours
  delay(200);
  lcd.clear();
  currentTime[1] = setTime(1, 0);    //The rest of the user-defined variables are set; current time minutes,
  //alarm time hours, and alarm time minutes
  delay(200);
  lcd.clear();
  alarmTime[0] = setTime(0, 1);
  delay(200);
  lcd.clear();
  alarmTime[1] = setTime(1, 1);
  while (1)                        //forever
  {
    for (int i = 0; i < 1420; i++)   //This loop increments the current time minutes by one,
                                     //if the time is 60 minutes it sets minutes to 0 and 
                                     //increments hours, and if the current time is 
                                     //the same as the alarm time, it runs sunrise.
    {
      currentTime[1] += 1;
      if (currentTime[1] == 60)
      {
        currentTime[1] = 0;
        currentTime[0] += 1;
      }
      if (currentTime[0] == 24)
      {
        currentTime[0] = 0;
      }
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print(currentTime[0]);
      lcd.print(" : ");
      lcd.print(currentTime[1]);

      Serial.print(currentTime[0]);
      Serial.print(" : ");
      Serial.println(currentTime[1]);

      if (currentTime[0] == alarmTime[0] && currentTime[1] == alarmTime[1])
      {
        currentTime[1] += 20;
        Sunrise();
        Serial.print("sunrise");
      }

      delay(60000);
    }
  }
}

int setTime (int unit, int parameter)   //starts a user interface for setting a variable.
                                        //int unit: if = 0, the unit is hours. If 1, the
                                        //unit is minutes.
                                        //int parameter: if 0, the parameter to be edited
                                        //is the current time. if 1, alarm time is edited.
                                        //these parameters change what is displayed on the
                                        //screen, and what variable is set.
{
  if (parameter == 1)
  {
    lcd.setCursor(0, 0);
    lcd.print ("Set Alarm ");
    //delay(1000);
  } else if (parameter == 0)
  {
    lcd.setCursor(0, 0);
    lcd.print ("Set Current ");
    //delay(1000);
  }
  if (unit == 1)
  {
    lcd.print("mins:");
    //delay(1000);
  } else if (unit == 0)
  {
    lcd.print("hrs:");
    //delay(1000);
  }

  int setValue = 0;                                     //variable for the value to edit
  int awaitingPlusButtonRelease = plusButtonState;
  while (enterButtonState != 1)
  {
    enterButtonState = digitalRead(enterButtonPin);
    plusButtonState = digitalRead(plusButtonPin);
    if ((plusButtonState == 1) && !(awaitingPlusButtonRelease == 1))
    {
      setValue ++;
      if (setValue > 59 && unit == 1)          //if you're editing minutes and you reach 60, it wraps to 0
      {
        setValue = 0;
      } else if (setValue > 23 && unit == 0)  //same with hours and 24
      {
        setValue = 0;
      }
    }
    lcd.setCursor(0, 1);
    lcd.print(setValue);
    awaitingPlusButtonRelease = plusButtonState;
  }
  enterButtonState = 0;
  return setValue;
}


void colorWipe(int redVal, int grnVal, int bluVal) //sets all the ring pixels to one rgb colour
{
  for (int i = 0; i < 24; i++)
  {
    ring.setPixelColor(i, redVal, grnVal, bluVal);
    ring.show();
  }
}

void Sunrise ()                        //sunrise light fade sequence
{
  Serial.print("sunrise activated");
  for (int i = 0; i < 600; i++)                //600 seconds is 10 minutes
  {
    int redLightValue = map(i, 0, 599, 0, 255); //as i goes from 1 to 600, red light value
                                                //goes from 0 to 255
    int greenLightValue = 0;
    int blueLightValue = 0;

    if (redLightValue > 15)                    //a few seconds in, fade in green to make orange/yellow
    {
      greenLightValue = (redLightValue - 16) / 2.5;
    }
    if (redLightValue < 9)                     //right at the beggining, fade in blue and fade it out again
    {
      blueLightValue = redLightValue;
    } else if (redLightValue > 8 && redLightValue < 17)
    {
      blueLightValue = abs((redLightValue - 16));
    } else if (redLightValue > 150)                //near the end, fade in a little blue to lighten the yellow
    {
      blueLightValue = (redLightValue - 150) / 15;
    }
    Serial.print("r");
    Serial.print(redLightValue);
    Serial.print(" g");
    Serial.print(greenLightValue);
    Serial.print(" b");
    Serial.println(blueLightValue);
    colorWipe(redLightValue, greenLightValue, blueLightValue);
    ring.show();
    delay(1000);
  }
  delay(600000);                         //the sun stays on for another 10 minutes, for a total 20
  colorWipe(0, 0, 0);
  ring.show();
}

Video of the project working:


Reflection:

What was the easiest part of this challenge?

I think the easiest part of this challenge was wiring the circuit. I designed the form factor to be easy to work on, and this was the case.


What was the hardest?

Coding for a user-settable clock is hard. Perhaps not super hard logically, but there is so much logic involved that the code gets quite large, as you've noticed. The physical assembly was easy on this one, though. Perhaps I'm learning.


What did you learn?

I learned more about advanced logic structures and code flow, and also learned how great it is to work with coroplast. It's easy to cut, durable, looks nice, and is easy to glue.


What feedback did you get from other people in the class?

People liked it, but many noticed the slight flicker of the sunrise. I anticipated this; There are only 255 gradations of brightness, and when you spread that over 10 minutes, it's easy to see a jump.

Recent Posts

See All

Comentarios


bottom of page