Jan
30
2009
0

Project: LED Firefly Lights – Post #5 Real Firefly Test

Click here to see the entire LED FireFly Lights Project.

Now that I’ve got my firefly test LEDs to fade in and out randomly (Project: LED Firefly Lights – Post #4 Random Fade Test) I’ve decided to try to replicate what real fireflies look like when they flash.  I’ve found this video on youtube that shows how they flash and it also shows a some LED firefly lights a company in California has made called FireFly Magic.

Get the Flash Player to see the wordTube Media Player.

For the code I mostly just inverted the DelayOn and DelayOff. I did add an extra #define to take the place of the direction 1 or -1 so I could easily change the speed at which I change the LED brightness. I also changed the name of the fade variable in the LED structure to FadeDelay. To see the old version of the code check out Post #4.

Here is what the test fireflies look like now; they don’t blink as fast as real fireflies my wife prefers them to go a bit slower. The speed can easily be changed by changing the #define constants.

Get the Flash Player to see the wordTube Media Player.

Here is the new code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
 
volatile unsigned int vCount = 0;
volatile unsigned char vPORTA = 0;
volatile unsigned char vPORTB = 0;
volatile unsigned char vPORTC = 0;
volatile unsigned char vPORTD = 0;
volatile unsigned char vPORTE = 0;
 
#define cLED_CNT 16
#define cFADEDELAY 3
#define cDELAYOFFMAX 1500
#define cDELAYON 1
#define cBRIGHTMAX 100
#define cFADESPEED 5
 
struct LED
{
  char Port;
  char Bit;
  int Brightness;
  int Direction;
  int DelayOn;
  int DelayOff;
  int FadeDelay;
};
 
volatile struct LED LEDArray[cLED_CNT];
 
 
/* Main Function */
int main(void)
{
  int vI;
 
  /* Initialize Timer0 */
 
    // Enable timer0 compare interrupt
  TIMSK0 = (1<<OCIE0A);
 
    // Sets the compare value
  OCR0A = 12;
 
  // Set Clear on Timer Compare (CTC) mode, prescaler
  TCCR0A = (1<<WGM01)|(0<<WGM00)|(3<<CS00);
 
  /* Initialize Ports for output */
  DDRA = 0xFF;
  DDRB = 0xFF;
  DDRC = 0xFF;
  DDRD = 0xFF;
  DDRE = 0xFF;
 
  /* Initialize LED Array */
  for(vI = 0; vI < cLED_CNT; vI++)
  {
    if (vI < 8)
    {
      LEDArray[vI].Port = 'B';
      LEDArray[vI].Bit = vI;
    }
    else
    {
      LEDArray[vI].Port = 'D';
      LEDArray[vI].Bit = vI - 8;
    }
    LEDArray[vI].Brightness = 0;
    LEDArray[vI].Direction = cFADESPEED;
    LEDArray[vI].DelayOff = (rand() % cDELAYOFFMAX) + 1;
    LEDArray[vI].DelayOn = cDELAYON;
    LEDArray[vI].FadeDelay = cFADEDELAY;
  }   
 
  // Enable Interrupts
  sei();
 
   // Main program loop
   while(1) {   }
 
   return 0;
}
 
/* Handle Timer Interrupt */
ISR (TIMER0_COMP_vect)
{
  int vI = 0;
 
  vCount++;
  if (vCount >= 100) vCount = 0;
  if (vCount == 0) 
  {
    //vPORTA = 0xFF;
    vPORTB = 0xFF;
    //vPORTC = 0xFF;
    vPORTD = 0xFF;
    //vPORTE = 0xFF;
  }
 
  for (vI = 0; vI < cLED_CNT; vI++)
  {
    if ((LEDArray[vI].Brightness <= 0) | (LEDArray[vI].Brightness == vCount))
    {
      switch (LEDArray[vI].Port)
      {
        case 'A': vPORTA &= ~(1 << LEDArray[vI].Bit);break;
        case 'B': vPORTB &= ~(1 << LEDArray[vI].Bit);break;
        case 'C': vPORTC &= ~(1 << LEDArray[vI].Bit);break;
        case 'D': vPORTD &= ~(1 << LEDArray[vI].Bit);break;
        case 'E': vPORTE &= ~(1 << LEDArray[vI].Bit);break;
      }
    }
    if (vCount == 0) 
    {
      LEDArray[vI].DelayOff--;
      if (LEDArray[vI].DelayOff == 0)
      {
        LEDArray[vI].DelayOff = 1;
        LEDArray[vI].FadeDelay--;
        if (LEDArray[vI].FadeDelay == 0)
        {
          LEDArray[vI].FadeDelay = cFADEDELAY;
          LEDArray[vI].Brightness += LEDArray[vI].Direction;
          if (LEDArray[vI].Brightness >= cBRIGHTMAX) 
          {
            LEDArray[vI].Brightness = cBRIGHTMAX-1;
            LEDArray[vI].DelayOn--;
            if (LEDArray[vI].DelayOn == 0)
            {
              LEDArray[vI].Direction = -1 * cFADESPEED;
              LEDArray[vI].DelayOn = cDELAYON;
            }
          }
          if (LEDArray[vI].Brightness <= 0) 
          {
            LEDArray[vI].Direction = cFADESPEED;
            LEDArray[vI].DelayOff = (rand() % cDELAYOFFMAX) + 1;
          }  
        }
      }
    }
  }
  //PORTA = vPORTA;
  PORTB = vPORTB;
  //PORTC = vPORTC;
  PORTD = vPORTD;
  //PORTE = vPORTE;
}
Jan
29
2009
0

Project: LED Firefly Lights – Post #4 Random Fade Test

Click here to see the entire LED FireFly Lights Project.

In the previous post I showed how I faded an entire bank of LED lights. Since then I’ve added another bank of LEDs to make sure my code works with multiple banks. So the total LED count is 16. I connected the LEDs through a resistor to Ports B & D on the AVR Butterfly as shown in the picture below. I had to disconnect the piezo speaker on the back of the Butterfly since it is also connected to pin 5 of Port B.

fireflytestbutterflyportsbd-thumb fireflytestledbanksbd-thumb


I’ve been playing around with randomizing the LEDs so they don’t all turn on and off at the same time.

To create a random number in C you can use the rand( ) function declared in the stdlib.h library. In my code I use the following statement to generate a random delay for each LED.

LEDArray[vI].DelayOn = (rand() % cDELAYONMAX) + 1;

LEDArray[vI].DelayOn is an integer variable that is part of my LED structure used to store the random number in.

rand( ) function returns a pseudo-random integral number in the range 0 to RAND_MAX where RAND_MAX = 0x7FFF which is declared in the stdlib.h library.

% Modulus computes the remainder that results from performing integer division.

cDELAYONMAX is a constant I declare to give me the maximum random number I want to generate. Currently I’ve set this to 1500.

I’ve created an LED structure to group the variable I need to control the LEDs.

struct LED
{
  char Port;
  char Bit;
  int Brightness;
  int Direction;
  int DelayOn; 
  int DelayOff;
  int FadeSpeed;
};

Port variable sets the Port the LED is located on.
Bit variable sets which pin the LED is located on.
Brightness variable controls the current brightness of the LED in percent 0 to 100.
Direction variable controls whether the LED is fading in or out. 1 is in and -1 is out.
DelayOn contains a random number that sets how long the LED will stay on.
DelayOff contains how long the LED will stay off.
FadeSpeed controls how fast the LED will fade on and off.

Here is a video that shows the LEDs randomly fading in and out:

Get the Flash Player to see the wordTube Media Player.

Here is my code, it may not be the best way to do it but it works:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
 
volatile unsigned int vCount = 0;
volatile unsigned char vPORTA = 0;
volatile unsigned char vPORTB = 0;
volatile unsigned char vPORTC = 0;
volatile unsigned char vPORTD = 0;
volatile unsigned char vPORTE = 0;
 
#define cLED_CNT 16
#define cFADESPEED 5
#define cDELAYONMAX 1500
#define cDELAYOFF 5
#define cBRIGHTMAX 100
 
struct LED
{
  char Port;
  char Bit;
  int Brightness;
  int Direction;
  int DelayOn; 
  int DelayOff;
  int FadeSpeed;
};
 
volatile struct LED LEDArray[cLED_CNT];
 
/* Main Function */
int main(void)
{
  int vI;
 
  /* Initialize Timer0 */
 
  // Enable timer0 compare interrupt
  TIMSK0 = (1 << OCIE0A);
 
  // Sets the compare value
  OCR0A = 12;
 
  // Set Clear on Timer Compare (CTC) mode, prescaler
  TCCR0A = (1 << WGM01) | (0 << WGM00) | (3 << CS00);
 
  /* Initialize Ports for output */
  DDRA = 0xFF;
  DDRB = 0xFF;
  DDRC = 0xFF;
  DDRD = 0xFF;
  DDRE = 0xFF;
 
  /* Initialize LED Array */
  for(vI = 0; vI < cLED_CNT; vI++)
  {
    if (vI < 8)
    {
      LEDArray[vI].Port = 'B';
      LEDArray[vI].Bit = vI;
    }
    else
    {
      LEDArray[vI].Port = 'D';
      LEDArray[vI].Bit = vI - 8;
    }
      LEDArray[vI].Brightness = cBRIGHTMAX;
      LEDArray[vI].Direction = -1;
      LEDArray[vI].DelayOn = (rand() % cDELAYONMAX) + 1;
      LEDArray[vI].DelayOff = cDELAYOFF;
      LEDArray[vI].FadeSpeed = cFADESPEED;
  }
 
  // Enable Interrupts
  sei();
 
  // Main program loop
  while(1) {   }
 
  return 0;
}
 
/* Handle Timer Interrupt */
ISR (TIMER0_COMP_vect)
{
  int vI = 0;
 
  vCount++;
  if (vCount >= 100) vCount = 0;
  if (vCount == 0)
  {
    //vPORTA = 0xFF;
    vPORTB = 0xFF;
    //vPORTC = 0xFF;
    vPORTD = 0xFF;
    //vPORTE = 0xFF;
  }
 
  for (vI = 0; vI < cLED_CNT; vI++)
  {
    if ((LEDArray[vI].Brightness <= 0) | (LEDArray[vI].Brightness == vCount))
    {
      switch (LEDArray[vI].Port)
      {
        case 'A': vPORTA &= ~(1 << LEDArray[vI].Bit);break;
        case 'B': vPORTB &= ~(1 << LEDArray[vI].Bit);break;
        case 'C': vPORTC &= ~(1 << LEDArray[vI].Bit);break;
        case 'D': vPORTD &= ~(1 << LEDArray[vI].Bit);break;
        case 'E': vPORTE &= ~(1 << LEDArray[vI].Bit);break;
      }
    }
    if (vCount == 0)
    {
      LEDArray[vI].DelayOn--;
      if (LEDArray[vI].DelayOn == 0)
      {
        LEDArray[vI].DelayOn = 1;
        LEDArray[vI].FadeSpeed--;
        if (LEDArray[vI].FadeSpeed == 0)
        {
          LEDArray[vI].FadeSpeed = cFADESPEED;
          LEDArray[vI].Brightness += LEDArray[vI].Direction;
          if (LEDArray[vI].Brightness <= 0)
          {
            LEDArray[vI].Brightness = 0;
            LEDArray[vI].DelayOff--;
            if (LEDArray[vI].DelayOff == 0)
            {
              LEDArray[vI].Direction = 1;
              LEDArray[vI].DelayOff = cDELAYOFF;
            }
          }
          if (LEDArray[vI].Brightness == cBRIGHTMAX)
          {
            LEDArray[vI].Direction = -1;
            LEDArray[vI].DelayOn = (rand() % cDELAYONMAX) + 1;
          }
        }
      }
    }
  }
  //PORTA = vPORTA;
  PORTB = vPORTB;
  //PORTC = vPORTC;
  PORTD = vPORTD;
  //PORTE = vPORTE;
}
Jan
24
2009
0

AVR JTAGICE mkII clone – Review

This is a followup review post from this one:  AVR JTAGICE mkII clone

I finally tried out the AVR JTAGICE mkII clone.  AVRSTudio connected to it just like it should.  It downloaded the latest firmware.  I connected to my AVR Butterfly and it read the device signature.  Everything was looking good until I tried to debug my code.  Whenever I entered debug mode the JTAGICE mkII clone would time out and disconnect from AVRStudio.

I was a bit discouraged and I had to figure out if I was doing something wrong or if I got a bad programmer.  One of my friends had a JTAGICE mkII from atmel that was not a clone so I borrowed it and tried it.  It didn’t have any problems in debug mode.  So I did get a bad programmer.

I contacted the vendor where I purchased the programmer and he said to ship it back and they will test it.  So I shipped it back to them and a few days later I got this response:

Hi, I tested your mkii clone and as you said, the debugging mode doesn’t work.  I will have to ship it to the manufacturer for a repair.  The whole process can take 3-4 weeks, as they are closed right now because of Chinese New Year celebration.

So the good news is they had the same problem I was having with it.  The bad news is they will not be sending me a new one, instead they are sending it back to China for repair.  So far I’m not all that impressed with the clone.  I think if you receive a device that does not work they should replace it with a new one instead of sending it back for repair.  Maybe in a month (hopefully) when I get the clone back it will work as it should.

To see a list of other AVR programmer/debuggers check out my AVR Programmer/Debugger post.

EDIT:  I finally got it back see here AVR JTAGICE mkII clone – Review (Final)

Written by KludgeGuru in: AVR |
Jan
21
2009
0

Project: LED Firefly Lights – Post #3 LED Fade Test

Well I’ve finally made some progress on my LED FireFly Lights Project.

First I’m using the AVR Butterfly to prototype it, which has the ATmega169 AVR. It doesn’t come with any connectors so I got some samples from Samtec (their sudden service is great for fast overnight free samples!)

I then setup a bank of LEDs on my solderless bread board.

I connected each LED to a pin on Port D of the AVR Butterfly plus power & ground:

I then struggled a bit trying to figure out how to get the timer on the ATmega169 to work. After figuring out the timer I wrote a quick little program that fades the bank of LEDs on and off. I’m using pulse width modulation (PWM) to vary the brightness of the LEDs by changing the duty cycle. I decided to start with 100Hz for the PWM frequency which I may change later.

Here is what is looks like…sorry so dark:

Get the Flash Player to see the wordTube Media Player.

Here is what the output signal looks like on an oscilloscope:

Get the Flash Player to see the wordTube Media Player.

And here is my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
#include <avr/io.h>
#include <avr/interrupt.h>
 
volatile unsigned char vDuty = 1;
volatile unsigned char vCount = 0;
volatile unsigned int vDimm = 0;
volatile unsigned int vSpeed = 400;
volatile char vDir = 1;
 
/* Main Function */
int main(void)
{
  /* Initialize Timer0 */
  // Enable timer0 compare interrupt
  TIMSK0 = (1 << OCIE0A);
  OCR0A = 12;  // Sets the compare value
  // Set clear on timer compare (CTC) mode, prescaler
  TCCR0A = (1 << WGM01) | (0 << WGM00) | (3 << CS00);
 
  /* Initialize PortD */
  DDRD = 0xFF;  // Set PortD for all Outputs
  PORTD = 0x00;  // Clear PortD Pins
  sei();  // Enable Interrupts
 
  /* Main Program Loop */
  while(1) { /* Do Nothing */}
 
  return 0;
}
 
/* Handle Timer Interrupt */
ISR (TIMER0_COMP_vect)
{
  vCount++;
  if (vCount >= 100) vCount = 0;
  if (vCount == 0) PORTD = 0xFF;
  if (vCount == vDuty) PORTD = 0x00;
  vDimm++;
  if (vDimm == vSpeed)
  {
    vDimm = 0;
    vDuty += vDir;
    if (vDuty == 75) vDir = -1;
    if (vDuty == 1) vDir = 1;
  }
}

Click here to see the rest of my Project: LED Firefly Lights.

Jan
21
2009
0

WINAVR Development Tools

I decided to use the WINAVR development suite which includes the AVR-GCC compiler for C and C++.  The great thing about these development tools is that they are free and they integrate into AVRStudio.

The hard thing about switching from the PIC C18 compiler to the AVR-GCC compiler so far has been setting and clearing a single port pin.

With the PIC compiler I was able to do this to set & clear pins:

PORTBbits.RB5 = 1;  // Sets Port B Pin 5
PORTBbits.PB5 = 0;  // Clears Port B Pin 5

With the AVR-GCC compiler you use bit shifting:

PORTB |=  (1 << 5)  // Sets Port B Pin 5
PORTB &= ~(1 << 5)  // Clears Port B Pin 5

I’m not saying it is hard to use bit shifting, it’s just a little more cryptic and will take a little getting used to.  Another option is to define macros which might make it more readable:

#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))

Here is how you would use the macros in the code:

bit_set(PORTD,  BIT(5));  // Sets Port B Pin 5
bit_clear(PORTB, BIT(5));  // Clears Port B Pin 5

Here are some other useful macro definitions for bit shifting:

#define bit_get(p,m) ((p) & (m))
#define bit_flip(p,m) ((p) ^= (m))
#define bit_write(c,p,m) (c ? bit_set(p,m) : bit_clear(p,m))
#define BIT(x) (0×01 << (x))
#define LONGBIT(x) ((unsigned long)0×00000001 << (x))

Written by KludgeGuru in: AVR |

Powered by WordPress. Theme: Aeros 2.0 by TheBuckmaker.com.