Okay, so all six leds are wired up. They all work. Let's say you like 100 the most as a PWM output (approximately 2V).
Let's consider the process.
First, we need to get the time from the arduino. The time can be obtained in milliseconds or microseconds* from the time the arduino was last powered up / reset. In fact we only need seconds, so we're going to want the measurement that's equally or slightly more precise; clearly milliseconds will be easier to deal with.
Ok, 1000 ms per sec. Here's how we get elapsed seconds:
seconds = millis() / 1000;
We see that millis() returns elapsed milliseconds.
Now, we have seconds, but they go from 0 to very large. We'll want to limit them to be from 0 to 59. For this, we want the modulus operator. (Basically the modulus takes the remainder of a division: Let's say you divide 7 by 3, you get 2 remainder 1, therefore 7 % 3 == 1. Also, a very quick way to tell if something is even is to do number % 2 == 0; if it's even this will return true.) Obviously we want to do modulus 60
seconds = (millis() / 1000) % 60;
So now we have seconds, 0-59 inclusive. We can store this as a byte. Now, you remember how we think of this as bit representations, right? We're going to have two leading zeros and six bits, like so
00000000 to 00111011 = 0 to 59
And now we have to extract the six bits individually to determine if the corresponding light should be powered.
Let's think about this using an example.
00101010 is 42
0th bit off
1st bit on
2nd bit off
3rd bit on
4th bit off
5th bit on
ignore 6th and 7th bits
Here's where we have to dig into bitwise operators. You really, really want to google bitwise operators to get a better understanding than I can impart.
These are the important ones:
| is OR, this returns true if the first bit is 1 or the second bit is 1.
EXAMPLE
11111111 |
00000000 =
11111111
10101010 |
11001010 =
11101010
& is AND, this returns true if the first bit is 1 and the second bit is 1.
EXAMPLE
11111111 &
00000000 =
00000000
10100101 &
01010110 =
00000100
^ is XOR or exclusive OR, this returns true if the first bit is not equal to the second bit.
EXAMPLE
01011001 ^
10010101 =
11001100
10101010 ^
01010101 =
11111111
~ is NOT, this is applied to only one operand and just switches the bits.
EXAMPLE
~11111111 = 00000000
~00000000 = 11111111
~01100101 = 10011010
~~1111111 = 11111111 (two NOTs cancel.)
Confused yet? Well, here's two more. These are bit shifting functions.
We have two bit-shifting functions: >> and <<. Great.
Consider the number 42: 00101010.
What happens if we just shift all the bits over one spot to the right?
00101010 >> 1 becomes 00010101 = 21.
What happens if we just shift all the bits over two spots to the right?
00101010 >> 2 becomes 00001010 = 10.
And three spots to the right?
00101010 >> 3 becomes 00000101 = 5.
Now let's shift it the other way.
00101010 << 1 becomes 01010100 = 84
00101010 << 2 becomes 10101000 = 168
See a pattern here? Yeah, basically bit shifting is multiplying by 2 raised to a certain power. Shift right x and it's 2^-x, shift left x and it's 2^x. (This is ^ as raising to the power, mister nitpicker.)
http://arduino.cc/en/Reference/Bitshift for more info on how ints will change and how leading 1s replicate when shifted right and how to change that.
Oh boy! Now we need to know how to get the 0-5th bits from the end of our seconds, which is currently a byte with values 0-59.
Consider again our number 42, or 00101010.
There are a few ways to get the correct bits out.
One way is to actually shift the bits an appropriate amount and then see if we're left with an even or odd number. For example
byte sec = 42; // 00101010
(sec >> 0) % 2 == 0
(sec >> 1) % 2 == 1
(sec >> 2) % 2 == 0
(sec >> 3) % 2 == 1
(sec >> 4) % 2 == 0
(sec >> 5) % 2 == 1
Or we can do an AND comparison, like so
byte sec = 42; // 00101010
sec & 1 == 0 // 00101010 & 00000001 == 00000000
sec & 2 == 2 // 00101010 & 00000010 == 00000010
sec & 4 == 0 // 00101010 & 00000100 == 00000000
sec & 8 == 8 // 00101010 & 00001000 == 00001000
sec & 16 == 0 // 00101010 & 00010000 == 00000000
sec & 32 == 32 // 00101010 & 00100000 == 00100000
Or we could do an OR comparison
byte sec = 42; // 00101010
sec | 1 == sec + 1 == 43 // 00101010 | 00000001 == 00101011
sec | 2 == sec == 42 // 00101010 | 00000010 == 00101010
sec | 4 == sec + 4 == 46 // 00101010 | 00000100 == 00101110
sec | 8 == sec == 42 // 00101010 | 00001000 == 00101010
sec | 16 == sec + 16 == 58 // 00101010 | 00010000 == 00111010
sec | 32 == sec == 42 // 00101010 | 00100000 == 00101010
So now you know how to read time, extract seconds from time, extract seconds between 0-59 from seconds, and extract individual bits to power the LEDs!
In case you're confused, the three patterns I listed are
1) Power LED x if (sec >> x) % 2 == 1
2) Power LED x if sec & 2^x == 2^x
3) Power LED if sec | 2^x == sec
(^ here is 2 to the power of x, not 2 XOR x. You know that, mister wiseguy.)
A pro can weigh in on which method, if any, is superior in terms of runtime. (Chances are that you'll never see any difference in runtime but if the optimization is switching one line for another, it can't hurt!)
*I'll cover a bug with microseconds in a separate thread.