0
Offline
Newbie
Karma: 0
Posts: 7
Arduino rocks
|
 |
« on: February 07, 2011, 02:25:15 pm » |
I’m a novice to electronics, but not to programming. I've been trying to build a lamp containing 16 segments of RGB led strip. That makes 48 separate led clusters (3 colors x 16), each ready to go at 12 volts with built-in resistors, and each drawing about 100mA. I twice failed to get things to work using 3 TLC5940s, and then ran across this article: http://www.picano.nl/microcontrollers/arduino/control-many-leds-with-pwm about software PWM. Instead of using shift registers, I decided to try using the Arduino Mega (with ATmega1280). I would use 48 of its 54 digital I/O pins, with interrupt-driven PWM using direct bitSet and bitClear instructions. Since I haven’t seen this “obvious” approach discussed elsewhere, I will provide some details here. I first tested this with only one led connected, but with a program using a timed interrupt to control 48 pins. The board seemed to handle the load well enough, using 30 levels of brightness on a 60Hz basis (hence doing 1800 interrupts per second). That appeared to use about 1/3 of the board’s capacity, since it would saturate and begin to run very slowly if I went to 100 levels of brightness. The interrupt routine is very simple: void iserve(){ static byte counter; for (int i = 0; i <48 ; i++) { if (ledvalue > counter) { bitSet(*ports,portnum); } //see explanation below else bitClear(*ports,portnum); } counter++; if(counter>__maxBrightness) counter=0; }
Here is the rest of the minimum code necessary to the approach I’ve taken:
#include "TimerOne.h"
// A pin on the Arduino board is directly addressed by a command like “bitSet(PORTE,3)”—for pin 5. //I’ll include a complete table of pin and port address associations near the end of this forum message.
volatile uint8_t * ports[48] = {&PORTE, &PORTH, &PORTH, &PORTH, &PORTH, &PORTB, &PORTB, &PORTB, &PORTJ, &PORTJ, &PORTE, &PORTB, &PORTD, &PORTD, &PORTE, &PORTB, &PORTG, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTA, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTC, &PORTD, &PORTG, &PORTG, &PORTG, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTL, &PORTB, &PORTB, &PORTB};
byte portnum[48] ={3, 3, 4, 5, 6, 4, 5, 6, 1, 0, 4, 7, 3, 2, 5, 0, 5, 0, 4, 1, 2, 3, 5, 6, 7, 7, 5, 4, 6, 3, 2, 1, 0, 7, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 3, 2, 1};
byte ledvalue[48]; //holds the brightness level for the leds. Modified by main program, read by interrupt service routine.
int __maxBrightness = 30; long __ledFreq = 60;
void setup(){ Timer1.initialize(round(1000000/(__ledFreq*(__maxBrightness+1)))-1); // initialize timer1 //This sets the interrupt at about every 556 microseconds. Formula from picano article. Timer1.attachInterrupt(iserve); // attaches iserve () as timer overflow interrupt. }
void loop(){ //commands to set led values and make lamp do exciting things. }
It’s that simple.
Now to my difficulties. I set my board up with 7 ULN2003 Darlington arrays, each of which can handle 7 leds. The Arduino pins are connected directly to the ULN2003 inputs, and the led cathodes (with current-limiting resistors) are connected to the ULN2003 outputs. The ULN2003s have only one other connection: ground to Arduino ground, which is also attached to ground for my 12 volt (actually 12.6 volt) power supply. The 12.6 volt (6 amp) positive attaches to all led anodes and to VCC on the Arduino. Again, it’s that simple (if you count 4*48+ solder connections as simple). Twice everything seemed to be working fine—almost. Leds were lighting and dimming as they should. I was tracking down isolated problems with a few leds not lighting when first the board seemed to stop corking, and then suddenly I heard a fizzle—or, last night, I think I saw a little flash and puff of smoke from the Arduino—and the board now seems dead. (Actually, it’s power light still comes on, but I can’t upload programs and it doesn’t function) Last night I determined that the ATmega1280 chip itself had gotten extremely hot, although I had not noticed it getting even warm before then. I had noticed some warmth on a chip very close to the on-board power plug, which I thought might be the voltage regulator. A worry, but it seemed to be just warm, not hot. So any ideas? It is surely possible that my novice wiring and soldering skills led to a problem. That’s what I assumed the first time this happened, because it coincided with me reinserting the 12 volt wire into VCC (maybe I accidently put it into 5V?). But I now worry that maybe I am overloading the board or something like that. There are two possibilities:
I just read something about how I should have resistors between the Arduino pins and the ULN2003 inputs. Could that be the problem? On the other hand, overloading sounds unlikely because I had the system operating for some hours running with most leds lit—except for the few problem ones—and saw neither smoke nor fire. At the time the board failed last night, I was running software that would light only a single led at a time (i.e., only one pin in bitSet mode, although the interrupt routine would have been running, and giving repeated bitClear commands for the other 47 pins). So that hardly seems like an overload condition unless pins in bitClear mode are still placing demands on the board.
Last night, I was working to fix a problem with the led on pin 2 not lighting, and noticed that most of pins showed about 2.4 volts when in bitSet state (but 0 or maybe 0.01 volts with bitClear). Pin 2 was only showing 0.61 volts. I had previously solved a problem with some pins by adding into setup a loop that gave a pinMode(pin, OUTPUT) instruction for those pins. Pin 2 began working right after I put in a loop that gave the pinMode OUTPUT instruction for every pin from 2 through 53. But the board blew not long after the fix to pin2. Is that a hint?
I’m really at a loss about how to proceed. The software PWM seems like such a nice straightforward approach (especially if you don’t need the ULN2003s and just directly connect regular 20mA leds with limiting resistors to the Arduino Mega pins). And I really don’t want to replace the Arduino board only to have another one do a little fireworks display on me. I could revert to trying TLC5940s, but I’d prefer for now to pursue the software PWM approach unless it is just a bad idea.
I’ll be grateful for any help.
As I promised I am including a table of the pin – port address assignments in the Arduino Mega (this is for the ATmega1280, I don’t know if it is the same for the new board). Taken from the schematic at http://arduino.cc/en/uploads/Main/arduino-mega-schematic.pdf
Pin Port,Bit 0 PORTE, 0 1 PORTE, 1 2 PORTE, 4 3 PORTE, 5 4 PORTG, 5 5 PORTE, 3 6 PORTH, 3 7 PORTH, 4 8 PORTH, 5 9 PORTH, 6 10 PORTB, 4 11 PORTB, 5 12 PORTB, 6 13 PORTB, 7 14 PORTJ, 1 15 PORTJ, 0 16 PORTH, 1 17 PORTH, 0 18 PORTD, 3 19 PORTD, 2 20 PORTD, 1 21 PORTD, 0 22 PORTA, 0 23 PORTA, 1 24 PORTA, 2 25 PORTA, 3 26 PORTA, 4 27 PORTA, 5 28 PORTA, 6 29 PORTA, 7 30 PORTC, 7 31 PORTC, 6 32 PORTC, 5 33 PORTC, 4 34 PORTC, 3 35 PORTC, 2 36 PORTC, 1 37 PORTC, 0 38 PORTD, 7 39 PORTG, 2 40 PORTG, 1 41 PORTG, 0 42 PORTL, 7 43 PORTL, 6 44 PORTL, 5 45 PORTL, 4 46 PORTL, 3 47 PORTL, 2 48 PORTL, 1 49 PORTL, 0 50 PORTB, 3 51 PORTB, 2 52 PORTB, 1 53 PORTB, 0
|