
Arduino LED matrix ethernet upgrade
Lang geleden, eind 2012, bouwde ik een LED matrix display met een Arduino Uno. Aangezien standaard 8x8 matrixen, Neopixels en adresseerbare LED-strips toen nog niet bestonden (of niet te verkrijgen waren voor consumenten) bouwde ik de matrix from scratch. Nu, in 2015, is de tijd gekomen om dit project weer eens uit de kast te trekken en van een fraaie upgrade te voorzien.
Bouwen van de 8 x 24 LED matrix
Meer informatie over de hardware van het LED-display vind je in het originele artikel, onder andere over de aansturing van de LED’s met 74HC595 shiftregisters en een ULN2803 driverarray om multiplexen mogelijk te maken.

De Arduino draait standalone zijn programma af bestaande uit klok, datum en temperatuur, maar zoals ik destijds ook al schreef was het me niet gelukt om vanaf de computer teksten in te schieten. Met de upgrade die ik hier beschrijf wordt dit wel mogelijk, de gehele matrix kan dan via ethernet worden bediend!
Ombouwen naar Ethernet Display
Omdat ik de Arduino matrix alleen standalone gebruikte had ik een eigen printplaat gebouwd zodat ik mijn ‘kostbare’ Arduino weer voor andere projecten kon gebruiken. Nu Arduino’s niet zo veel meer kosten door het enorme aanbod aan kloon-Arduino’s en ik liever niet een Ethernet-chip met de hand ga zitten solderen heb ik er voor gekozen om mijn printplaat te transformeren tot shield. Vandaar dat je op de printplaat nog wat loze componenten aantreft en het een redelijke dradenboel is geworden.

Een belangrijk en nog wel functioneel onderdeel is de 5 Volt voeding, 192 LED’s kun je nu eenmaal niet uit de Arduino voeden, dan brand deze waarschijnlijk door dus voorziet de matrix in zijn eigen voeding.
Nu de hardware gekoppeld is kunnen we aan de software beginnen.
Arduino LED matrix software
Het hart van de software is natuurlijk nog steeds de interrupt routine die de pixels op het scherm aanstuurt. Door voortschrijdend inzicht kon ik deze writeScreen routine als volgt herschrijven om hem efficiënter te maken.
void writeScreen() {
digitalWrite(rowpins[row], LOW); // switch current row off
row++; // goto next row if exist
if (row == 8) {
row = 0;
}
bitClear(PORTC, 3); // latch low to hide output
for (col = 0; col < 24; col++) {
bitClear(PORTC, 4); // clock low
digitalWrite(A2, buffer[row][col]); // set databit
bitSet(PORTC, 4); // clock high to shift output
}
bitSet(PORTC, 3); // latch high to show output
digitalWrite(rowpins[row], HIGH); // row on to light leds on row
}
De routine schrijft nu één rij per keer in plaats van het hele display, hierdoor ontstaat er meer tijd tussen de cycles om communicatie en andere taken af te handelen. Bovendien blijft een rij nu langer (millisecondes) ingeschakeld waardoor de helderheid van het display toeneemt. Voor het gemak gebruik ik de TimerOne-library om het timer-interrupt in te stellen, dat kan dan met twee eenvoudige regels:
Timer1.initialize(2000); // overflow at 2000 Microseconds
Timer1.attachInterrupt(writeScreen); // execute writeScreen() at overflow
Arduino matrix klok
De LED matrix had al de mogelijkheid om een klok weer te geven, maar het instellen hiervan met twee drukknopjes was een drama. Aangezien er nu een ethernet connectie is kan ik de tijd mooi via NTP ophalen, zo is de tijd en datum altijd in sync met de atoomklok. Meer over het opzetten van een via NTP gesynchroniseerde klok.
Natuurlijk willen we ook graag wat zien op ons matrix display, alleen weet de Arduino nog niet hoe hij zijn interne kennis kan omzetten in iets zinnigs op het scherm. Daar hebben we letters en cijfers voor nodig, net als op de computer noem ik dit het lettertype of font. Voor het weergeven van de gewone klok met seconden heb ik twee fonts gemaakt bestaande uit grote en kleine cijfers. Daarnaast heb ik ook een uberklok gemaakt bestaande uit extra grote, dikke cijfers. De fonts zijn als volgt opgeslagen.
const PROGMEM prog_uchar cijfers[10][3] = {{127,65,127},
{0,0,127},
{121,73,79},
{73,73,127},
{15,8,127},
{79,73,121},
{127,73,121},
{1,1,127},
{127,73,127},
{79,73,127}};
const PROGMEM prog_uchar cijfers_klein[10][3] = {{124,68,124},
{0,0,124},
{116,84,92},
{84,84,124},
{28,16,124},
{92,84,116},
{124,84,116},
{4,4,124},
{124,84,124},
{92,84,124}};
const PROGMEM prog_uchar cijfers_uber[10][5] = {{255,255,195,255,255},
{0,0,0,255,255},
{251,251,219,223,223},
{219,219,219,255,255},
{31,31,24,255,255},
{223,223,219,251,251},
{255,255,219,251,251},
{3,3,3,255,255},
{255,255,219,255,255},
{223,223,219,255,255}};
Allereerst zie je hier de cijfers van 0 tot en met 9 in een formaat van 3x7 pixels, vervolgens de kleine cijfers in 3x5 pixels. De laatste array bevat de ubercijfers 0 tot en met 9 in het formaat 5x7 pixels. De cijfers zijn opgeslagen in tweedimensionale arrays. Als ik het cijfer 0 wil ophalen kijk ik dus in cijfers[0][0] voor kolom 1, cijfers[0][1] voor kolom 2, en cijfers[0[2] voor kolom 3. Als je het decimale getal in de array binair uitschrijft krijg je een 1 als de LED aan staat, en een 0 als deze uit staat. Dus voor het getal 0 krijg je in kolom 1: 1111111, kolom 2: 1000001, kolom 3: 1111111.
Hoe dat de juiste cijfers uit het font via de klok in de buffer van het display worden gezet liet ik in het oude LED matrix artikel al zien.
Teksten naar de LED matrix sturen
Dan het sluitstuk van de LED matrix ethernet upgrade: het realtime doorsturen van teksten. Om tekst weer te geven heb je uiteraard ook weer een font nodig, maar nu met de letters en speciale tekens. Dit matrixfont kun je hier downloaden.
Teksten die via het ethernet-shield binnenkomen worden opgeslagen als String en vervolgens door de functie DecodeText met behulp van het font in de display buffer geladen.
void DecodeText(String text) {
for (i = 0; i < text.length(); i++) {
text[i] -= 32; // map ASCII font
for (x = 0; x <= 7; x++) {
for (y = 0; y <= 4; y++) {
buffer[x][i * 6 + y] = bitRead(pgm_read_byte_near(&font[text[i]][y]), 7 - x);
}
buffer[x][i * 6 + 5] = 0;
}
}
}
Omdat de display buffer niet oneindig groot is kan vaak niet alle tekst in een keer ingeladen worden. Daarom splits ik de tekst op in blokken van 5 karakters, scroll vervolgens een karakter naar links, en laad dan weer een blok van 5 karakters. Dit gaat zo snel dat er voor het oog nog steeds een vloeiend scrollende tekst zichtbaar is.
if (k < (var1.length() - 4)) {
DecodeText(var1.substring(k,k+5));
for (byte z = 0; z <= 5; z++) {
ScrLeft(30);
delay(150);
}
k++;
}
else {
k = 0;
}
void ScrLeft(byte length) {
for (x = 0; x <= 7; x++) {
temp[x] = buffer[x][0];
for (y = 0; y <= (length - 2); y++) {
buffer[x][y] = buffer[x][y + 1];
}
buffer[x][length - 1] = temp[x];
}
}
Klik hier voor de complete supermatrix code.