Digital Hourglass logic

Hello,

I have just bought the arduino uno starter kit and, to be honest, I was hoping to be further along than this before resorting to the forums. However I have spent all afternoon searching this forum and racking my brains and so I think I need some guidance. Below is the original sketch for Tutorial 8 the Digital Hourglass which is a set of 6 LEDs set to light up sequentially until the switch state is changed and they are reset.

// named constant for the switch pin
const int switchPin = 8;

unsigned long previousTime = 0; // store the last time an LED was updated
int switchState = 0; // the current switch state
int prevSwitchState = 0; // the previous switch state
int led = 2; // a variable to refer to the LEDs

// 600000 = 10 minutes in milliseconds
long interval = 600000; // interval at which to light the next LED

void setup() {
  // set the LED pins as outputs
  for (int x = 2; x < 8; x++) {
    pinMode(x, OUTPUT);
  }
  // set the tilt switch pin as input
  pinMode(switchPin, INPUT);
}

void loop() {
  // store the time since the Arduino started running in a variable
  unsigned long currentTime = millis();

  // compare the current time to the previous time an LED turned on
  // if it is greater than your interval, run the if statement
  if (currentTime - previousTime > interval) {
    // save the current time as the last time you changed an LED
    previousTime = currentTime;
    // Turn the LED on
    digitalWrite(led, HIGH);
    // increment the led variable
    // in 10 minutes the next LED will light up
    led++;

    if (led == 7) {
      // the hour is up
    }
  }

  // read the switch value
  switchState = digitalRead(switchPin);

  // if the switch has changed
  if (switchState != prevSwitchState) {
    // turn all the LEDs low
    for (int x = 2; x < 8; x++) {
      digitalWrite(x, LOW);
    }

    // reset the LED variable to the first one
    led = 2;

    //reset the timer
    previousTime = currentTime;
  }
  // set the previous switch state to the current state
  prevSwitchState = switchState;
}

The sketch works fine (more or less - it seems to freeze if I make the interval small and leave it alone for a while, but I need to understand the logic before I start de-bugging!). There are a few things that, for some reason, I cannot get my head around:

A) Interval variable - we set this as a long integer variable at the beginning. Later we tell the LEDs to light up and stay on sequentially using:

digitalWrite(led, HIGH);
led++

But how is it reading the interval variable? We could change the name and location of this variable yet it still knows that this is the time period between leds lighting up - how?

C) Current time = Previous time

When running the serial monitor Previous Time is always equal to Current Time regardless of any switch change or time passed. In the comments it says "save the current time as the last time you changed an LED" - but this isn't the case. Furthermore we initially set the Previous Time as 0 so if we want to overwrite the Current Time with Previous Time how is it measuring the time between LED changes?

When you have statement like "xTime = yTime" is it important for the syntax to be the correct order? ie for xTime to overwrite yTime and vice versa.

I really don't understand what's at play here and I know it's fairly elementary so sorry if I am being thick! :confused: It would be so helpful if someone could explain it simply.

Many thanks

WestyTea,

You're entering the loop multiple times, each time it is setting 'currentTime' to the current time ...
Then you are comparing 'currentTime' against previousTime. If the difference is > 600000 (10 mins) then you're doing the next LED.
If the difference is not > 600000 then you are just doing nothing and re-entering the loop (and setting 'currentTime' again etc.

xTime = yTime Yes, very important to get these the right way around. In this example xTime will be overwritten with the value that yTime currently has.

How does it now what LED to light - well, it is using the led variable. This starts with a value of 2, each time a further 'interval passes' it lights the LED to connected to the pin number held in the 'pin' variable and then increments the 'pin' variable (pin++;)

So at the start pin is 2 - after 1 interval (10 mins) it sets pin(2) to HIGH (lighting the LED) and sets pin variable to 3, next time it sets pin(3) HIGH (lighting the LED) and increments it again.

When it gets to the last one there is a check whether the 'led' variable is 7 (i.e. the hour is complete) and if so, it resets all pins to LOW (turning off the LEDs)

Hope this makes sense...

.. Ken

Hello Ken,

Thank you for your response. Yes this makes perfect sense - it is the difference! I couldn't see the forest for the trees! For some reason I thought the led++ would need to address the interval value directly. Also, it didn't help that on my serial monitor I was showing the currentTime value under previousTime column - what a noob!

Properly enjoying this though, last time I tried microcontroller programming was 10 years ago - onwards and upwards!

Cheers

Hello, i had the same problem with the sample sketch "DigitalHourglass" I have set the interval to 1000. After about an half minute without pressing the switch button the board doesnt read the switch anymore and writes the DigitalOuts itsself in intervals. I wondering why. But i found the problem.
This is because its forgotten to stop the led++ when hourglass is full. led++ and digitalwrite is still executed every second. And led takes values that are no digitalouts on the board.
I put the led++ inside the modified if case, then the behavior is correct.

if (led < 7) {
led++;
// the hour is up
}