Menu:

Arduino AVR assignment 2

Original by B.J.D. Vermulst for AVR Studio with WinAVR. April 2010.

A walking light is a bar of lights of which the lights are lit one after another. It looks like the light is ‘walking’ along the bar. In this assignment, we make a walking light with 8 LEDs. With the same program in the microcontroller, and suitable devices (optocouplers and triacs), we could drive 8 normal light bulbs.

loop1_en.c
Connect 8 LEDs with resistors (you have learned to calculate the resistance in the previous assignment) to the 6 upper pins of port D and two first pins of port B. The code to make a light walking in one direction is not very complicated:
int main (void){
    char x = 0b1;
    DDRD = 0xFF;
    DDRB = (1 << PB0)|(1 << PB1);

    while (1)
{
        PORTD = x << 2;
        PORTB = x >> 6;
        _delay_ms(200);
        x = x << 1;

        if(x == 0)
            x = 0b1;
    }

    return 1;
}

First, we define a variable (a char type, which is an 8 bit variable) x. x is initialized to 0b00000001, which is the binary value for the decimal value 1. After that, we set up port D and B: all port D pins are defined as output and port B pin 0 and 1 are output. 0x00 is the hexadecimal value for the decimal value 0 and 0xFF is the decimal value for 255.

After the initialization, we make a while loop that runs forever. In this while loop, the 8 bits of x are written to the 6 upper pins of port D and the last two bits are written to port B. Now we wait for 200mS. Then we move the bits of x one position to the left (this is the same as multiplying with 2 in the decimal system, check this!). If we shift the bits again and again, the bit that is 1 is shifted out of the variable x. If this is the case (x has become 0b00000000), we reset x to 0b00000001.

loop2_en.c
Instead of lighting a single LED, we also can make other patterns. Change the code in such a way that there are 2 LEDs on simultaneously. Not only the starting value x has to be changed, but also the condition of the IF statement has to be changed (otherwise sometimes only one LED is lit).
loop3_en.c
Instead of only shifting, you can choose to increase the number of LEDs that are lit. For instance, at first only the most left LED, then 2, etc. This can be done with:
x = (x << 1) | 0b00000001;

The | (pipe) means OR: every bit of x is shifted one to position to the left, and the bit that is most right becomes 1. The effect is a ‘growing’ light (each time an extra LED is lit). If you write the bits down, it is more obvious what happens:
x = 0b00001111
x << 1 = 0b00011110
(x << 1) | 0b00000001 =
00011110
00000001 OR
------------
00011111

The OR operation is bitwise. If at least 1 of the 2 bits has the value 1, the result is also 1.

Edit the program. Pay also attention to the condition of the IF statement. To have the wanted effect, you should move the recalculation of x to the ELSE part of the IF statement.

loop4_en.c
The car of Nightrider and the eyes of StarWars robots have lights that go from the left to the right and back. To make this happen, besides remembering the new value of x, you also have to know in which way your light is walking. If your light hits the left or right border, you have to change the direction.

#define LEFT 0
#define RIGHT 1
...

char direction = LEFT;
...

if (x == 0b00000001){
direction = LEFT;
}else if (x == 0b10000000){
direction = RIGHT;
}
...

if (direction == RIGHT){
x = x << 1;
}
else if (direction == RIGHT){
x = x >> 1;
}

Try to understand what happens, and edit your code.

loop5_en.c
Adapt the code in such a way that 2 LEDs are on simultaneously and create a function ‘display(int x)’ which writes the bits of x to the proper pins.

loop6_en.c
Symmetrical patterns often look nice. A simple symmetrical pattern consists of 2 lights moving from both sides towards the middle. This pattern only has 5 states (including the ‘all off’ state), so it is easy to write down every single state:
void main(void)
{
...

while(1)
{
Display(....);
Delay100mS(....);
Display(....);
Delay100mS(....);
Display(....);
Delay100mS(....);
Display(....);
Delay100mS(....);
Display(....);
Delay100mS(....);
}
}

Make the new program, almost everything is different regarding the previous program.

Fill in the gaps yourself.

loop7_en.c
The previous program is not very well programmed. If you should write your programs always in this way, it certainly would become a mess. You can reprogram it in a better way: the writing to the ports and the delay should be placed together in a function. Try it!
loop8_en.c
Adapt the code in such a way that when the 2 lights meet in the middle, they are starting to move away from each other. It is maybe more nice to delete the ‘all off’ state now. This pattern has 6 states.