Introduction: Arduino Controlled Sunrise Alarm Clock

About: Eric J. Wilhelm is the founder of Instructables. He has a Ph.D. from MIT in Mechanical Engineering. Eric believes in making technology accessible through understanding, and strives to inspire others to learn …
This is an update to the microcontroller for my Blue LED Dawn Simulator Alarm Clock.  Previously, it used an Atmel ATMEGA8-16PI which required an Atmel programer.  Here, I've updated it to use an Arduino Uno.  Since the Uno is based on a similar chip, I was able to reuse code to access interrupts to drive a 16-bit PWM controller.  Even if you're not interested in building a sunrise simulator, you might find the 16-bit PWM code useful.  

Running on just the Atmetl, the sunrise simulator started getting intermittent errors, which resulted in bright flashes of light during the sunrise cycle instead of a gradual increase.  Presumably this was from additional noise from the Soleil alarm clock.  I no longer had easy access to an Atmel programmer, so decided to update to an Arduino for easier future changes.  

The wiring is largely the same as before, except the signal from the Soleil is read by an analog input rather than a digital input.  I decided using the analog input would make the controller more resistant to noise than the my previous solution using interrupts.   Arduino code is below :

long previousMillis = 0;        // will store last time LED was updated
long interval = 1000;           // interval at which to update (milliseconds)

void setup() {               
  // initialize the digital pin as an output.
  pinMode(9, OUTPUT);

  // turn off the LED on the Arduino board
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);

  // Timer1 does ~16-bit PWM
  TCCR1A = _BV (COM1B1) | _BV (WGM11) | _BV (COM1A1);
  TCCR1B = _BV (WGM13) | _BV (WGM12) | _BV (CS10);

  ICR1 = 65535;
  // Start the PWM duty cycle at 100%
  OCR1A = 65535;

  // turn this on for debugging
  //Serial.begin(9600);

}

void loop() {
  unsigned long currentMillis = millis();
  long y=0;
  long output[100], u;
  int i;

  //take 1000 readings on the analog input
  for (i=0; i<1000 ; i++) {
    y = y + analogRead(A0);
  }

  output[0] = 65535 / (1 + exp(-1*0.00002275*(y-500000)));

  //average the output so it doesn't jump around
  for(i=9;i>0;i--) {
    output[i] = output[i-1];
  }
  u=0;
  for(i=0;i<10;i++) {
    u=u+output[i];
  }

  //make sure the output value doesn't go above 65535
  if (u/10 > 65535) u = 655350;
  //set the PWM duty cycle
  OCR1A = u/10;

  if(currentMillis - previousMillis > interval) {
    // save the last time the output was printed
    previousMillis = currentMillis;  
    //output what's going on for debugging
    //Serial.println(OCR1A);
    //Serial.println(y);
  }
}

I determined the exponential function that matched the output of the LEDs to the incandescent lights by eye and trial and error.  A graph showing the exponential rise compared to a linear rise is attached.  
Hack It! Contest

Participated in the
Hack It! Contest