I've build a 10x10 RGB LED Matrix. The LEDs are connected in rows and columns. That's 40 pins (30 for RGB, 10 for GND). I got myself five 74CH595 ICs and soldered everything together. I also added a 1A BJT in front of each row/column to protect the ICs + Arduino and to be able to use an external power supply. The 3 pins (Data, Clock, latch) from the ICs are connected to my Arduino micro.
It's all working very well (even with multiplexing) when I don't use Bit Angle Modulation.
Words you prob. don't know:
BAM = Bit Angle Modulation
In the comments "...(Data) an" means the ...(Data) pin is on. "...(Data) aus" means the Data pin is off.
Why I use the FastLED Library code:
I use it because they're some very good animation software for that Library/Type of LED.
The Code uses 10% of program memory and 21% dynamic memory.
Here is my code (Arduino IDE 1.6.7, no Lib)
class FLED {
private:
bool b;
public:
FLED();
void show();
};
FLED::FLED() : b(false) {
}
void FLED::show() {
}
class LED {
private:
uint8_t LEDname;
uint8_t R;
uint8_t G;
uint8_t B;
public:
LED();
uint8_t getR();
uint8_t getG();
uint8_t getB();
void setR(uint8_t _R);
void setG(uint8_t _G);
void setB(uint8_t _B);
};
LED::LED() : R(0), G(0), B(0) {
}
uint8_t LED::getR() {
return R;
}
uint8_t LED::getG() {
return G;
}
uint8_t LED::getB() {
return B;
}
void LED::setR(uint8_t _R) {
R = _R;
}
void LED::setG(uint8_t _G) {
G = _G;
}
void LED::setB(uint8_t _B) {
B = _B;
}
LED leds[100];
FLED FastLED;
void setup() {
//set pins to output so you can control the shift register
pinMode(2, OUTPUT);
pinMode(4, OUTPUT);
pinMode(3, OUTPUT);
//Serial.begin(1000000);
}
uint8_t BitMapR1[10] = {
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000
};
uint8_t BitMapR2[10] = {
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000
};
uint8_t BitMapR3[10] = {
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000
};
uint8_t BitMapR4[10] = {
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000,
B00000000
};
LED CRGB(byte _R, byte _G, byte _B) {
LED _LED = LED();
_LED.setR(constrain(_R / 16, 0, 15));
_LED.setG(constrain(_G / 16, 0, 15));
_LED.setB(constrain(_B / 16, 0, 15));
return _LED;
}
void loop() {
//Serial.print(micros()); Serial.println(" Start");
leds[0] = CRGB(0, 0, 0);
leds[1] = CRGB(0, 0, 0);
leds[2] = CRGB(0, 0, 0);
leds[3] = CRGB(0, 0, 0);
leds[4] = CRGB(0, 0, 0);
leds[5] = CRGB(0, 0, 0);
leds[6] = CRGB(0, 0, 0);
leds[7] = CRGB(0, 0, 0);
leds[8] = CRGB(0, 0, 0);
leds[9] = CRGB(0, 0, 0);
leds[10] = CRGB(0, 0, 0);
leds[11] = CRGB(0, 0, 0);
leds[12] = CRGB(0, 0, 0);
leds[13] = CRGB(0, 0, 0);
leds[14] = CRGB(0, 0, 0);
leds[15] = CRGB(0, 0, 0);
leds[16] = CRGB(0, 0, 0);
leds[17] = CRGB(0, 0, 0);
leds[18] = CRGB(0, 0, 0);
leds[19] = CRGB(0, 0, 0);
leds[20] = CRGB(0, 0, 0);
leds[21] = CRGB(0, 0, 0);
leds[22] = CRGB(0, 0, 0);
leds[23] = CRGB(0, 0, 0);
leds[24] = CRGB(0, 0, 0);
leds[25] = CRGB(0, 0, 0);
leds[26] = CRGB(0, 0, 0);
leds[27] = CRGB(0, 0, 0);
leds[28] = CRGB(0, 0, 0);
leds[29] = CRGB(0, 0, 0);
leds[30] = CRGB(16, 0, 0);
leds[31] = CRGB(32, 0, 0);
leds[32] = CRGB(48, 0, 0);
leds[33] = CRGB(64, 0, 0);
leds[34] = CRGB(96, 0, 0);
leds[35] = CRGB(128, 0, 0);
leds[36] = CRGB(180, 0, 0);
leds[37] = CRGB(200, 0, 0);
leds[38] = CRGB(255, 0, 0);
leds[39] = CRGB(0, 0, 0);
leds[40] = CRGB(0, 0, 0);
leds[41] = CRGB(0, 0, 0);
leds[42] = CRGB(0, 0, 0);
leds[43] = CRGB(0, 0, 0);
leds[44] = CRGB(0, 0, 0);
leds[45] = CRGB(0, 0, 0);
leds[46] = CRGB(0, 0, 0);
leds[47] = CRGB(0, 0, 0);
leds[48] = CRGB(0, 0, 0);
leds[49] = CRGB(0, 0, 0);
leds[50] = CRGB(16, 0, 0);
leds[51] = CRGB(32, 0, 0);
leds[52] = CRGB(48, 0, 0);
leds[53] = CRGB(64, 0, 0);
leds[54] = CRGB(96, 0, 0);
leds[55] = CRGB(128, 0, 0);
leds[56] = CRGB(180, 0, 0);
leds[57] = CRGB(200, 0, 0);
leds[58] = CRGB(255, 0, 0);
leds[59] = CRGB(0, 0, 0);
leds[60] = CRGB(0, 0, 0);
leds[61] = CRGB(0, 0, 0);
leds[62] = CRGB(0, 0, 0);
leds[63] = CRGB(0, 0, 0);
leds[64] = CRGB(0, 0, 0);
leds[65] = CRGB(0, 0, 0);
leds[66] = CRGB(0, 0, 0);
leds[67] = CRGB(0, 0, 0);
leds[68] = CRGB(0, 0, 0);
leds[69] = CRGB(0, 0, 0);
leds[70] = CRGB(0, 0, 0);
leds[71] = CRGB(0, 0, 0);
leds[72] = CRGB(0, 0, 0);
leds[73] = CRGB(0, 0, 0);
leds[74] = CRGB(0, 0, 0);
leds[75] = CRGB(0, 0, 0);
leds[76] = CRGB(0, 0, 0);
leds[77] = CRGB(0, 0, 0);
leds[78] = CRGB(0, 0, 0);
leds[79] = CRGB(0, 0, 0);
leds[80] = CRGB(0, 0, 0);
leds[81] = CRGB(0, 0, 0);
leds[82] = CRGB(0, 0, 0);
leds[83] = CRGB(0, 0, 0);
leds[84] = CRGB(0, 0, 0);
leds[85] = CRGB(0, 0, 0);
leds[86] = CRGB(0, 0, 0);
leds[87] = CRGB(0, 0, 0);
leds[88] = CRGB(0, 0, 0);
leds[89] = CRGB(0, 0, 0);
leds[90] = CRGB(0, 0, 0);
leds[91] = CRGB(0, 0, 0);
leds[92] = CRGB(0, 0, 0);
leds[93] = CRGB(0, 0, 0);
leds[94] = CRGB(0, 0, 0);
leds[95] = CRGB(0, 0, 0);
leds[96] = CRGB(0, 0, 0);
leds[97] = CRGB(0, 0, 0);
leds[98] = CRGB(0, 0, 0);
leds[99] = CRGB(0, 0, 0);
//Serial.print(micros()); Serial.println(" Objekte");
FastLED.show();
//setBitMaps();
//myloop();
while(true) {
BAM();
}
//Serial.print(micros()); Serial.println(" BAM");
}
void BAM() {
for (int cycle = 1; cycle <= 15; cycle++) {
setBitMaps(cycle, 1);
myloop();
}
}
void setBitMaps(int cycle, int pos) {
//Register 1
for (byte intLayerSel = 0; intLayerSel < 100; intLayerSel += 10) {
byte _byte = 0;
for (byte i = intLayerSel; i < intLayerSel + 8; i++) {
if (cycle == 1 && (leds[i].getR() & (1 << pos - 1)) != 0) {
_byte = _byte << 1;
_byte = _byte + B00000001;
}
else if ((cycle == 2 || cycle == 3) && (leds[i].getR() & (1 << pos)) != 0) {
_byte = _byte << 1;
_byte = _byte + B00000001;
}
else if (cycle >= 4 && cycle <= 7 && (leds[i].getR() & (1 << pos + 1 )) != 0) {
_byte = _byte << 1;
_byte = _byte + B00000001;
}
else if (cycle >= 8 && cycle <= 15 && (leds[i].getR() & (1 << pos + 2)) != 0) {
_byte = _byte << 1;
_byte = _byte + B00000001;
}
else {
_byte = _byte << 1;
_byte = _byte + B00000000;
}
}
BitMapR1[intLayerSel / 10] = _byte;
}
}
void myloop() {
byte bLayerA;
byte bLayerB;
for (byte bLayerTop = 1; bLayerTop <= 10; bLayerTop++) {
bLayerA = B00000000;
bLayerB = B00000000;
if (bLayerTop == 1) {
bLayerA = B10000000;
} else if (bLayerTop == 2) {
bLayerA = B01000000;
} else if (bLayerTop == 3) {
bLayerA = B00100000;
} else if (bLayerTop == 4) {
bLayerA = B00010000;
} else if (bLayerTop == 5) {
bLayerA = B00001000;
} else if (bLayerTop == 6) {
bLayerA = B00000100;
} else if (bLayerTop == 7) {
bLayerA = B00000010;
} else if (bLayerTop == 8) {
bLayerA = B00000001;
} else if (bLayerTop == 9) {
bLayerB = B00000010;
} else if (bLayerTop == 10) {
bLayerB = B00000001;
}
// take the latchPin low so
// the LEDs don't change while you're sending in bits:
// shift out the bits:
/*
shiftOut(dataPin, clockPin, MSBFIRST, bLayerA);
shiftOut(dataPin, clockPin, MSBFIRST, bLayerB + B00111111);
shiftOut(dataPin, clockPin, MSBFIRST, B11111111);
shiftOut(dataPin, clockPin, MSBFIRST, B11111111);
shiftOut(dataPin, clockPin, MSBFIRST, B11111111);
PORTD &= ~_BV(PORTD2);
delayMicroseconds(35);//delay < 35 flackert
PORTD |= _BV(PORTD2);
*/
PORTD &= ~_BV(PORTD2);
byte bLayer = bLayerTop - 1;
ShiftOut(bLayerA);
ShiftOut(bLayerB + BitMapR4[bLayer]);
ShiftOut(BitMapR3[bLayer]);
ShiftOut(BitMapR2[bLayer]);
//ShiftOut(B11111111);
ShiftOut(BitMapR1[bLayer]);
//take the latch pin high so the LEDs will light up:
PORTD |= _BV(PORTD2);//LatchPin
// pause before next value:
//delay(1);
delayMicroseconds(100);
}
}
void ShiftOut(byte myDataOut) {
// This shifts 8 bits out MSB first,
//on the rising edge of the clock,
//clock idles low
//internal function setup
byte i = 0;
//clear everything out just in case to
//prepare shift register for bit shifting
PORTD &= ~_BV(PORTD3);//Data aus
PORTD &= ~_BV(PORTD4);//Clock aus
//for each bit in the byte myDataOutï
//NOTICE THAT WE ARE COUNTING DOWN in our for loop
//This means that %00000001 or "1" will go through such
//that it will be pin Q0 that lights.
for (i = 0; i <= 7; i++) {
PORTD &= ~_BV(PORTD4);//Clock aus
//if the value passed to myDataOut and a bitmask result
// true then... so if we are at i=6 and our value is
// %11010100 it would the code compares it to %01000000
// and proceeds to set pinState to 1.
if ( myDataOut & (1 << i) ) {
PORTD |= _BV(PORTD3);//Data an
} else {
PORTD &= ~_BV(PORTD3);//Data aus
}
//register shifts bits on upstroke of clock pin
PORTD |= _BV(PORTD4);//Clock an
//zero the data pin after shift to prevent bleed through
PORTD &= ~_BV(PORTD3);//Data aus
}
}
So my first problem is that the last row (2 or 10) is brighter than the other rows. I think this is the time while the loop is restarting and refilling the Objects (led in leds) with new Data.
- I think my code is to slow because I still get some flicker when doing BAM. If anyone has a tip for me how to get the code faster it would be very nice if you tell me :)
If you need I can upload a schematic but my Internet is very slow so I don't do it right now.
Here is a Simulation made myself to test code. It's only 1 color and 8x8 but it works the same way: https://circuits.io/circuits/2422863-led-matrix-8x8-controler