// 2-dimensional array of row pin numbers:
const int row[8] = {
2, 7, 19, 5, 13, 18, 12, 16
};
// 2-dimensional array of column pin numbers:
const int col[8] = {
6, 11, 10, 3, 17, 4, 8, 9
};
// 2-dimensional array of pixels:
int pixels[8][8];
int posX = 7;
int posY = 7;
int count = 30;
bool bg = false;
unsigned int timer1_counter;
int scanningRow = 0;
void setup() {
Serial.begin(9600);
// initialize the I/O pins as outputs
// iterate over the pins:
for (int thisPin = 0; thisPin < 8; thisPin++) {
// initialize the output pins:
pinMode(col[thisPin], OUTPUT);
pinMode(row[thisPin], OUTPUT);
// take the col pins (i.e. the cathodes) high to ensure that
// the LEDS are off:
digitalWrite(col[thisPin], HIGH);
}
// initialize timer1
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
//timer1_counter for 1 sec, with prescaler=256
//65536 - 16000000/256
//timer1_counter = 3036;
//timer1_counter for 0.5 sec, with prescaler=256
//65536 - 16000000/(256*2)
//timer1_counter = 34286;
//timer1_counter for 0.1 sec, with prescaler=256
//65536 - 16000000/(256*10)
//timer1_counter = 59286;
//timer1_counter for 0.001 sec, with prescaler=256
//65536 - 16000000/(256*100)
//timer1_counter = 64911;
//timer1_counter for 0.0002 sec, with prescaler=256
//65536 - 16000000/(256*500)
timer1_counter = 65411;
TCNT1 = timer1_counter; // preload timer
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt
interrupts(); // enable all interrupts
//init pixels
for (int x = 0; x < 4; x++) {
for (int y = 0; y < 8; y++) {
pixels[x][y] = HIGH;
}
}
for (int x = 4; x < 8; x++) {
for (int y = 0; y < 8; y++) {
pixels[x][y] = LOW;
}
}
pixels[1][3] = LOW;
}
ISR(TIMER1_OVF_vect) // interrupt service routine
{
TCNT1 = timer1_counter; // preload timer
//scan LED Matrix in ISR
digitalWrite(row[scanningRow], LOW);
if(++scanningRow>=8){
scanningRow = 0;
}
for (int thisCol = 0; thisCol < 8; thisCol++) {
int thisPixel = pixels[scanningRow][thisCol];
digitalWrite(col[thisCol], thisPixel);
}
digitalWrite(row[scanningRow], HIGH);
}
void loop() {
//refreshScreen();
//Do something, block the loop
Serial.println("Hello!");
//Serial.println("Hello! again");
}
void refreshScreen() {
// iterate over the rows (anodes):
for (int thisRow = 0; thisRow < 8; thisRow++) {
// take the row pin (anode) high:
digitalWrite(row[thisRow], HIGH);
// iterate over the cols (cathodes):
for (int thisCol = 0; thisCol < 8; thisCol++) {
// get the state of the current pixel;
int thisPixel = pixels[thisRow][thisCol];
// when the row is HIGH and the col is LOW,
// the LED where they meet turns on:
digitalWrite(col[thisCol], thisPixel);
// turn the pixel off:
if (thisPixel == LOW) {
digitalWrite(col[thisCol], HIGH);
}
}
// take the row pin low to turn off the whole row:
digitalWrite(row[thisRow], LOW);
}
}
Tuesday, September 9, 2014
Arduino Uno: scan LED Matrix in Timer Interrupt
The original tutorial "Row-columm Scanning to control an 8x8 LED Matrix" call refreshScreen() to draw the screen repeatly in main loop(). If anything in loop() have to do something for times, will block the program, and make the duty cycle (and the brightness) will become unstable. This example show how to scan LED Matrix in Timer Interrupt ISR, such that it will not be affect by the jobs in loop(). But the timing of Timer Interrupt will affect the performance. This video show how:
Subscribe to:
Post Comments (Atom)
Hello Eric,
ReplyDeleteI am trying out your code. Is it true, that the individual LEDs brightness will depend on the amount of other LED on in the row (colum)? I am using two bitmaps with different layout and am noticing the effect. Any way to remedy that, mybe increasing duty time somehow? I can send you the code block I modified. Thank you.