NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Simple LED Light Chaser Souce Code In C

August 09, 2009
by Nerdful_com
Nerdful_com's Avatar

This code will chase a light back and forth with 6 LEDs that came with your nerdkit.

/* 
www.nerdful.com - I get called a nerd now and then,
but I am only a bit nerdful...
*/

#include <avr/io.h>
#include <avr/delay.h>
void sleep(uint8_t millisec)
{
while(millisec)
{
delay_ms(1);
millisec--;
}
}
main()
{
DDRC |=1<<PC5; //enable pin 28 red1
DDRC |=1<<PC4; //enable pin 27 yellow1
DDRC |=1<<PC3; //enable pin 26 green1
DDRC |=1<<PC2; //enable pin 25 red2
DDRC |=1<<PC1; //enable pin 24 yellow2
DDRC |=1<<PC0; //enable pin 23 green2
while(1)
{
PORTC &= ~(1<<PC5); //on red1 pin28
PORTC |=(1<<PC0); //off green2 pin23
PORTC |=(1<<PC4); //off yellow1 pin27
PORTC |=(1<<PC3); //off green1 pin26
PORTC |=(1<<PC2); //off red2 pin32
PORTC |=(1<<PC1); //off yellow2 pin24
sleep(50);
PORTC |=(1<<PC5); //off red1 pin28
PORTC &= ~(1<<PC4); //on yellow1 pin27
sleep(50);
PORTC |=(1<<PC4); //off yellow1 pin27
PORTC &= ~(1<<PC3); //on green1 pin26
sleep(50);
PORTC |=(1<<PC3); //off green1 pin26
PORTC &= ~(1<<PC2); //on red2 pin32
sleep(50);
PORTC |=(1<<PC2); //off red2 pin32
PORTC &= ~(1<<PC1); //on yellow2 pin24
sleep(50);
PORTC |=(1<<PC1); //off yellow2 pin24
PORTC &= ~(1<<PC0); //on green2 pin 23
sleep(50);
PORTC |=(1<<PC0); //off green2 pin23
PORTC &= ~(1<<PC1); //on yellow2 pin24
sleep(50);
PORTC |=(1<<PC1); //off yellow2 pin24
PORTC &= ~(1<<PC2); //on red2 pin32
sleep(50);
PORTC |=(1<<PC2); //off red2 pin32
PORTC &= ~(1<<PC3); //on green1 pin26
sleep(50);
PORTC |=(1<<PC3); //off green1 pin26
PORTC &= ~(1<<PC4); //on yellow1 pin27
sleep(50);
}
}
August 09, 2009
by Nerdful_com
Nerdful_com's Avatar

I have been told I am doing things a hard way (just starting and working my way up). Here is a code of a 3 LED flasher using a much cleaner code (no bit shifting yet, thats next) with help and understanding from mcai8sh4 in the NerdKit IRC chat channel (I will bring more samples soon too that we work out):

#include <avr/io.h>
#include <avr/delay.h>

main()
{
//DDRC = 3;
DDRC = 0b0000111; // enable pins 23-25
while(1)
{
PORTC = 0b001;
delay_ms(100);
PORTC = 0b010;
delay_ms(100);
PORTC = 0b100;
delay_ms(100);
}
}
August 09, 2009
by mcai8sh4
mcai8sh4's Avatar

It's not that you're original method was 'the hard way' that method it excellent for dealing with individual pins, without changing the others. But for this type of example it's useful to see how to make the code, a little simpler (although initially it may look more confusing).

Using binary notation it helpful when learning as you can visualize what you are turning 'on'.

Next we can look at using decimal and hex notation, to make the code shorter and hence less coding for us!!

August 09, 2009
by wayward
wayward's Avatar

Nerdful_com, that's a nice idea for a simple project! I rewrote your code to illustrate a few common programming paradigms; it's shorter now, and if you try to figure out how it works, you'll learn quite a bit.

Cheers, Zoran

#include <avr/io.h>
#include <avr/delay.h>

/* This can go up to 8, but not further! */
#define NUMBER_OF_LEDS  6

main() {
  DDRC |= (1 << NUMBER_OF_LEDS) - 1;  // for 6 LEDs: 00100000-1 = 00011111 (5 lowest bits on)
  PORTC &= ~((1 << NUMBER_OF_LEDS) - 1);  // ditto
  int light_location = 0;    // LED 0 will be lit initially
  int light_direction = +1;  // next LED is the one to the right

  while(1) {
    PORTC |= (1 << light_location);  // LED on
    delay_ms(50);                    // ... sleep
    PORTC &= ~(1 << light_location); // LED off

    light_location += light_direction;  // determine the next LED
    if (light_location < 0) {  // LED hit "left edge" while traveling left?
      light_location = 1;   // bounce LED to 2nd from the left
      light_direction = +1; // and set direction to right
    } else if (light_location == NUMBER_OF_LEDS) {  // hit "right edge"?
      light_location = NUMBER_OF_LEDS - 1;  // bounce LED to 2nd from the right
      light_direction = -1;                 // and set direction to left
    }
  }
}
August 10, 2009
by mcai8sh4
mcai8sh4's Avatar

Ok I'll have a bash - not as elegant as wayward's, but works :

#include <avr/io.h>
#include "../libnerdkits/delay.h"
#define F_CPU 14745600
// 6 led chaser - PC0-5
main()
{
    int i;
    DDRC = 0x3F;
    while(1)
    {
         for (i=0; i <= 5; i++)
         {
                   PORTC = (1 << i); // so PORTC = 0,1,2,4
                   delay_ms(50);
         }
         for (i=5; i >= 0; i--)
         {
                   PORTC = (1 << i); // so PORTC = 0,1,2,4
                   delay_ms(50);
         }

    }

}

August 10, 2009
by Nerdful_com
Nerdful_com's Avatar

Thanks guys, assume codes. I love having various ways to do the same thing. Obviously my way is the hard line by line way and not as small, much less typing with these other codes.

October 17, 2009
by mcai8sh4
mcai8sh4's Avatar

I've been playing around with various code examples, trying to learn other methods, so for completeness heres another example of the same type of program, using a slightly different method.

The idea behind this method originally came from a discussion on the IRC channel about strobing a number of digits on a display, since I didn't understand it, I thought this would be a simple way to help me learn (and I think it worked).

The challenge I set myself was to use a ternary operation. So here it is :

#define F_CPU 14745600  
#include <avr/io.h>
#include "../libnerdkits/delay.h"

#define NUM_OF_LEDS 6
#define SPEED 50

main()
{
    int state=1; // chase state 1=up 0=down
    DDRC |= (1<<NUM_OF_LEDS)-1;
    PORTC = 1;
    while (1) 
    {
        PORTC = (state) ? PORTC<<1 : PORTC>>1;
        state = (PORTC==(1<<NUM_OF_LEDS-1)) ? 0 : state;
        state = (PORTC==1) ? 1 : state;
        delay_ms(SPEED);
    }
    return 0;
}

Any questions/comments, shout out - it is probably not coded in the most elegant fashion, but I guess thats just the nature of this learning curve :)

  • Steve
October 17, 2009
by pbfy0
pbfy0's Avatar

I did it with a bit-shift.

#include <avr/io.h>
#include <avr/delay.h>

uint8_t shift(uint8_t in, uint8_t d){
    if(!d){
        return (in>>1);
    }else {
        return (in<<1);
    }
}

int main(){
    DDRC = 0b00111111;
    PORTC = 0;
    int in = 0;
    PORTC |= (1<<PC5);
    while (1) {
        _delay_ms(50);
        if(PORTC != 1 && PORTC != 0b00100000){
            PORTC = shift(PORTC, in);
        }else {
            in = ~(in);
        }
    }
}

not quite as nice as mcai8sh4's, but works

October 22, 2009
by mcai8sh4
mcai8sh4's Avatar

pbfy0 : Nice code!!

After working through your example I saw an opportunity to modify mine again (it's like 'c-golf' : keep trying to get less lines)! And yes, to all out there, that is a challenge :)

When I tried using ~state.... it didn't work, don't know why, if anyone can shed some light on that, please do. (my guess it's inverting the bits, so i=0000000001; ~i=1111111110... but that should still work, no?) Instead I used 'not' (!state) to flip the direction flag.

But anyway, following pbfy0s code, here is (what I think is) my shortest version of the chase example :

#define F_CPU 14745600  
#include <avr/io.h>
#include "../libnerdkits/delay.h"

#define NUM_OF_LEDS 6
#define SPEED 50

main()
{
    int state=1;
    DDRC |= (1<<NUM_OF_LEDS)-1;
    PORTC = 1;
    while (1) 
    {
        PORTC = (state) ? PORTC<<1 : PORTC>>1;
        state = (PORTC==(1<<NUM_OF_LEDS-1) || (PORTC==1)) ? !state : state;
        delay_ms(SPEED);
    }

    return 0;
}

Thanks for code pbfy0!

December 27, 2009
by jastermerrel
jastermerrel's Avatar

Hey everyone, I'm very much a beginner, so please bare with me.

I've started at the beginning of this thread with the intention of working through each example of code for an LED chaser. So I started with Nerd_ful's code here is what I did:

#define F_CPU 14745600

#include <avr/io.h>
#include <avr/delay.h>
void sleep(uint8_t millisec)
{
    while(millisec)
    {
        delay_ms(1);
        millisec--;
    }
}

main()
{
    DDRC |=1<<PC5; //enable pin 28 red1
    DDRC |=1<<PC4; //enable pin 27 red2
    DDRC |=1<<PC3; //enable pin 26 yellow1
    DDRC |=1<<PC2; //enable pin 25 yellow2
    DDRC |=1<<PC1; //enable pin 24 green1
    DDRC |=1<<PC0; //enable pin 23 green2
    while (1)
    {
        PORTC &= ~(1<<PC5); //on red1 pin28
        PORTC |=(1<<PC0); //off green2 pin23
        PORTC |=(1<<PC4); //off red2 pin27
        PORTC |=(1<<PC3); //off yellow1 pin26
        PORTC |=(1<<PC2); //off yellow2 pin25
        PORTC |=(1<<PC1); //off green1 pin24
        sleep(50);
        PORTC |=(1<<PC5); //off red1 pin28
        PORTC &= ~(1<<PC4); //on red2 pin27
        sleep(50);
        PORTC |=(1<<PC4); //off red2 pin27
        PORTC &= ~(1<<PC3); //on yellow1 pin26
        sleep(50);
        PORTC |=(1<<PC3); //off yellow1 pin26
        PORTC &= ~(1<<PC2); //on yellow2 pin25
        sleep(50);
        PORTC |=(1<<PC2); //off yeloow2 pin25
        PORTC &= ~(1<<PC1); //on green1 pin24
        sleep(50);
        PORTC |=(1<<PC1); //off green1 pin24
        PORTC &= ~(1<<PC0); //on green2 pin23
        sleep(50);
        PORTC |=(1<<PC0); //off green2 pin23
        PORTC &= ~(1<<PC1); //on green1 pin 24
    sleep(50);
        PORTC |=(1<<PC1); //off green1 pin24
        PORTC &= ~(1<<PC2); //on yellow2 pin25
        sleep(50);
        PORTC |=(1<<PC2); //off yellow2 pin25
        PORTC &= ~(1<<PC3); //on yellow1 pin26
        sleep(50);
        PORTC |=(1<<PC3); //off yellow1 pin26
        PORTC &= ~(1<<PC4); //on red2 pin27
        sleep(50);
    }
}

I then copied the "make" file from the tempsensor directory and edited it by changing any "tempsensor" to "led_chase" which is the name of the file I created and also changed to COM5. When I run make from the command prompt I get:

C:\Users\Jeramy\Desktop\nerdkits\Code\Code\led_chase>make
make -C ../libnerdkits
make[1]: Entering directory `C:/Users/Jeramy/Desktop/nerdkits/Code/Code/libnerdkits'
make[1]: Nothing to be done for `all'.
make[1]: Leaving directory `C:/Users/Jeramy/Desktop/nerdkits/Code/Code/libnerdkits'
avr-gcc -g -Os -Wall -mmcu=atmega168  -Wl,-u,vfprintf -lprintf_flt -Wl,-u,vfscan
f -lscanf_flt -lm -o led_chase.o led_chase.c ../libnerdkits/delay.o ../libnerdki
ts/lcd.o ../libnerdkits/uart.o
In file included from led_chase.c:4:
c:/winavr-20090313/lib/gcc/../../avr/include/avr/delay.h:36:2: warning: #warning
 "This file has been moved to <util/delay.h>."
led_chase.c: In function 'sleep':
led_chase.c:9: warning: implicit declaration of function 'delay_ms'
led_chase.c: At top level:
led_chase.c:15: warning: return type defaults to 'int'
led_chase.c:35:14: error: invalid suffix "PC3" on integer constant
make: *** [led_chase.hex] Error 1

And then it stops. Any help will be appreciated. THANKS!

December 27, 2009
by Rick_S
Rick_S's Avatar

Looks like you moved your code 1 level too low in your folder structure. The Nerdikits folder libnerdkits needs to be one level above where your program code resides to find the nerdkits libraries.

Rick

December 27, 2009
by jastermerrel
jastermerrel's Avatar

Thank you! Fixed and works

Post a Reply

Please log in to post a reply.

Did you know that microcontrollers have two different kinds of memory, program space (flash) and SRAM? Learn more...