I wrote the following code to do PWM modulation, but I've found that I get a lot of flicker with the dimmer settings:
int array[8] = {3, 7, 15, 31, 63, 127, 191, 255};
void setup() {
for (int x = 2; x < 10; x++)
{
pinMode(x, OUTPUT);
}
}
// the loop() method runs over and over again,
// as long as the Arduino has power
void loop()
{
updatearray();
}
void updatearray() {
int firstpin = 2;
//int dutycycle = 1785; // Dutycycle = 1000000 microseconds / 70hz update / groups. 1785 = 8 groups of 8 at 70hz. 490hz update of 8 groups of leds = 256 microsecond duty cycle.
unsigned long delaystart;
int timeelapsed;
for (int x = 0; x < 64; x+=8) { // Simulate updating 64 leds.
if (x < 8) {
delaystart = micros();
timeelapsed = 0;
while (timeelapsed < 255) { // Regardless of whether all LED's are off, wait for duty cycle to complete.
for (int y = 0; y < 8; y++) {
// Using a 490hz update greatly simplifies duty cycle calculations. This page mentions that the Arduino uses that rate on its PWM pins -> http://www.arduino.cc/en/Reference/AnalogWrite
// Note that the 16mhz Arduino has a resolution of four microseconds, so only 64 brightness levels are possible. -> http://arduino.cc/en/Reference/Micros
if (array[x+y] > 0) {
if (timeelapsed >= (255-array[x+y])) {
digitalWrite(firstpin + x + y, HIGH);
array[x+y] = -array[x+y]; // Toggle array value negative to keep track of current pin state.
}
}
}
timeelapsed = micros()-delaystart;
}
for (int y = 0; y < 8; y++) {
if (array[x+y] < 0) {
digitalWrite(firstpin + x + y, LOW);
array[x+y] = -array[x+y];
}
}
}
else {
delayMicroseconds(255); // Removing this delay would make the leds brighter when fewer are lit, and could burn them out if we are pulsing them at higher than their rated current.
}
}
}
The code above requires 8 leds connected to pins 2 thru 10 with resistors on the cathodes going to ground. And it looks a bit funny because it's simulating how the leds will look when I expand the array out to an 8x8. So the 8 leds will be run on a 1/8th duty cycle.
Anyway, the code should be updating the entire array at 490hz, so I wouldn't think I should be seeing any flicker, but nothing I do makes it go away. It WAS much worse when I was setting the pin state every update, but now that I toggle the array to keep track of the current state of the pin, it's much better, but still not perfect.
I've thought about setting all the pins at once, but in this case that doesn't make a lot of sense because multiple pins generally won't need to be set at the same time.
So, any ideas how I can improve upon this? Or am I just stuck with it because the Arduino isn't fast enough?
Oh, and one more thing about how the code works. Unlike standard PWM where the pins would be in an on state initially and then shut off for a period of time, my code starts the pins in an off state and turns them on for a period of time. I did this because I found that when I was turning them on at the beginning of the loop, I could not get them to be very dim. I'm not sure why that is, but perhaps it was simply due to how long the loop took to step through all the pins to turn them on.