TrashTimer  

This is a simple project that has a simple purpose - to remind my wife or I to put our rubbish bins out for the council pickup the next morning. It's sad how many times we've been awoken by the sound of the truck and raced out in our pj's! TrashTimer now sits beside our bed and flashes a very bright blue LED that can only be stopped by pressing the button on the front of the project box. Simple, but effective!

Step one involves designing the circuit. As always I used Fritzing and it really only took a few minutes to have it skethed up. This is the first time I've used an ATtiny85 and am quite impressed with the possibilities they open up.


As you can see Fritzing supports placing logos on the silkscreen, and as you'll see below the end result is very professional looking (well, in my opinion).

The schematic doesn't show it but there are 2 buttons used in the circuit. The first, connected to pin 6 is used to reset the timer (ie the timer will expire 7 days after the button is pressed). The second button is connected to pin 5 and is used to acknowledge that the timer has gone off, and thereby turning off the LED.

Next I etched my own board using the same technique previously described and then soldered it up, programmed the ATtiny and powered it up. I had fun chasing down a bug caused by inadequate toner in the laser printer, which resulted in some very small gaps in a few key copper trces. However the intent was always to checkout what Fritzing Fab could produce, and boy am I impressed with their boards!!
The code for TrashTimer is very simple and counts milliseconds to determine when a week is up and the responds appropriately to the two button presses. To program the ATtiny I used the Arduino IDE, a USBtinyISP in-system programmer and the ATtiny85 dev board.
#define MILLISECS_IN_A_WEEK 604800000UL
#define ACK_WEEK_ELAPSED_PIN 0
#define RESET_WEEK_PIN 1
#define WEEK_ELAPSED_LED_PIN 4

boolean debounceButton( int pin, int bounceDelay = 750 );

unsigned long weekStart;
boolean weekElapsed = false;

void flashLED( int numTimes, int flashDuration, int flashDelay )
{
  int x;
  
  for ( x = 0; x < numTimes; x++ )
  {
    digitalWrite( WEEK_ELAPSED_LED_PIN, HIGH );
    delay( flashDuration );
    digitalWrite( WEEK_ELAPSED_LED_PIN, LOW );
    delay( flashDelay );
  }
}

boolean debounceButton( int pin, int bounceDelay )
{
  if ( digitalRead( pin ) == LOW )
  {
    long press = millis();
    
    // spin whilst the buton is down
    while ( digitalRead( pin ) == LOW )
      ;
    
    // was it down long enough to indicate a real press
    if ( millis() > press + bounceDelay )
      return true;
  }
  return false;
}

void setup()
{
  pinMode( WEEK_ELAPSED_LED_PIN, OUTPUT );     
  flashLED( 3, 500, 500 );

  pinMode( RESET_WEEK_PIN, INPUT );
  digitalWrite( RESET_WEEK_PIN, HIGH );  // internal pull-up - switch will pull low to indicate reset

  pinMode( ACK_WEEK_ELAPSED_PIN, INPUT );
  digitalWrite( ACK_WEEK_ELAPSED_PIN, HIGH );  // internal pull-up - switch will pull low to indicate reset

  weekStart = millis();
}

void loop()
{
  if ( weekStart + MILLISECS_IN_A_WEEK <= millis() && !weekElapsed )
  {
    weekElapsed = true;
    weekStart = millis();
  }
  
  if ( weekElapsed )
    flashLED( 1, 1000, 1000 );
  
  if ( debounceButton( ACK_WEEK_ELAPSED_PIN ) )
    weekElapsed = false;

  if ( debounceButton( RESET_WEEK_PIN ) )
  {
    weekStart = millis();
    flashLED( 2, 250, 250 );
  }
}

Now you also have no excuse for forgetting to take out your trash! Here's the code and here's the board design.