C LED Matrix 8x8

Janiiix3

Aktives Mitglied
28. Sep. 2013
1.333
10
38
Hannover
Sprachen
  1. ANSI C
  2. C#
Hallo Freunde,


Ich habe vor mir eine LED Matrix zu Basteln... Die Hardware steht schon (siehe Anhang) nun wollte ich mal von euch wissen wie man am besten seinen "C-Code" Aufbaut ?!
Sprich... Wie bekomme ich meine ganzen Einzelnen "LED´s" am besten im Programm verpackt ?! Eine Art Tabelle ?!

Würde mich über die ein oder andere Idee freuen :)
 

Anhänge

  • Maxi Dice.pdf
    77,7 KB · Aufrufe: 21
Hallo Janiiix,
Sprich... Wie bekomme ich meine ganzen Einzelnen "LED´s" am besten im Programm verpackt ?! Eine Art Tabelle ?!

Würde mich über die ein oder andere Idee freuen :)

Ja, das löst du mit einer zweidimensionalen Tabelle, die du am besten im Flash Memory anlegst.

Du hast eine 8x8 Matrix, also 8 Zeilen und 8 Spalten. Es ist jeweils immer nur eine Zeile (Z1..8) aktiv (multiplexen),
Spalten (S1..8) können beliebige aktiv sein. Für Zeilen benötigst du Treiber, für die Spalten eventuell auch, dann
wenn der maximale Strom den zulässigen Portpin-Strom, den maximalen Strom eines Ports oder wenn die Summe aller
Ströme den maximalen Strom des Mikrocontrollers überschreitet.

Ich gehe aber eigentlich davon aus, dass dir die Ansteuerung via Multiplex klar ist, da du dir ja sicher etwas bei dem Design
der Schaltung gedacht hast. Mich wundert es, dass du erst die Hardware (Schaltung) soweit fertig gemacht hast, bevor du weißt, wie du die Software löst. :hmmmm:

Eine Tabelle könnte so aussehen ...

Code:
#include <avr/pgmspace.h>

const uint8_t MeineTabelle[ANZAHL_ZEICHEN][8] PROGMEM =
{
    {0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000}, // Zeichen 1
    {0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000}, // Zeichen 2
    {0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000},
//...
}

Die Werte holst du dir so ...

Code:
uint8_t zeile = pgm_read_byte(&MeineTabelle[zeichen_index][zeilen_index]);
// zeilen_index = 0..7
// zeichen_index = 0..(ANZAHL_ZEICHEN-1)


Ausgeben würde ich es in einem Timerinterrupt (Overflow oder eleganter Compare). Die Periodendauer würde ich möglichst groß wählen, aber noch so klein, dass man multiplexen nicht wahrnimmt.

Vielleicht hilft dir dies schon mal weiter.

Dirk :ciao:
 
Hallo Janiiix,


Ja, das löst du mit einer zweidimensionalen Tabelle, die du am besten im Flash Memory anlegst.

Du hast eine 8x8 Matrix, also 8 Zeilen und 8 Spalten. Es ist jeweils immer nur eine Zeile (Z1..8) aktiv (multiplexen),
Spalten (S1..8) können beliebige aktiv sein. Für Zeilen benötigst du Treiber, für die Spalten eventuell auch, dann
wenn der maximale Strom den zulässigen Portpin-Strom, den maximalen Strom eines Ports oder wenn die Summe aller
Ströme den maximalen Strom des Mikrocontrollers überschreitet.

Ich gehe aber eigentlich davon aus, dass dir die Ansteuerung via Multiplex klar ist, da du dir ja sicher etwas bei dem Design
der Schaltung gedacht hast. Mich wundert es, dass du erst die Hardware (Schaltung) soweit fertig gemacht hast, bevor du weißt, wie du die Software löst. :hmmmm:

Eine Tabelle könnte so aussehen ...

Code:
#include <avr/pgmspace.h>

const uint8_t MeineTabelle[ANZAHL_ZEICHEN][8] PROGMEM =
{
    {0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000}, // Zeichen 1
    {0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000}, // Zeichen 2
    {0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000,0b00000000},
//...
}

Die Werte holst du dir so ...

Code:
uint8_t zeile = pgm_read_byte(&MeineTabelle[zeichen_index][zeilen_index]);
// zeilen_index = 0..7
// zeichen_index = 0..(ANZAHL_ZEICHEN-1)


Ausgeben würde ich es in einem Timerinterrupt (Overflow oder eleganter Compare). Die Periodendauer würde ich möglichst groß wählen, aber noch so klein, dass man multiplexen nicht wahrnimmt.

Vielleicht hilft dir dies schon mal weiter.

Dirk :ciao:


Hallo,

ich klinke mich mal hier ein, da das Thema noch gar nicht so alt ist. Dank dem Post habe ich den LUT schon hinbekommen, auch auslesen klappt. Nur leider landet die komplette Tabelle im EEPROM, Data Memory Usage: 462 bytes 45,1 % Full, vorher war dieser leer. Sollte nicht PROGMEM dafür sorgen, dass es im Programmspeicher landet?
Probiert habe ich:
Code:
const uint8_t MeineTabelle[91][5] PROGMEM =
const uint8_t MeineTabelle[91][5]=

Wobei Progmem eine Warnung "Attribut ignored" kommt.

Die zweite Frage bezieht sich auf das Auslesen eines Wertes. Gibt es andere Möglichkeiten als über den Zeichen- und Zeilenindex? Zum Beispiel direkt Buchstaben auswählen. Auch soll ein LUT eine Switch Case Anweisung ersetzen können, nur wie?
Code:
	switch(x) {
		case 0xAA: irgendwas; break;	
		case 0xFF: irgendwas; break;	
		default: irgendwas; break;
	}

Viele Grüße
Daniel
 
Hallo Daniel,

bei dir landen die Daten im Moment nicht im Eeprom, sondern im SRAM des Mikrocontrollers.

Dies liegt sicherlich an dem Warning "Attribut ignored". Definiere die Tabelle einmal global und nicht innerhalb einer Funktion (also auch nicht in main), vielleicht liegts daran.

Dirk :ciao:

Hallo,

ich klinke mich mal hier ein, da das Thema noch gar nicht so alt ist. Dank dem Post habe ich den LUT schon hinbekommen, auch auslesen klappt. Nur leider landet die komplette Tabelle im EEPROM, Data Memory Usage: 462 bytes 45,1 % Full, vorher war dieser leer. Sollte nicht PROGMEM dafür sorgen, dass es im Programmspeicher landet?
Probiert habe ich:
Code:
const uint8_t MeineTabelle[91][5] PROGMEM =
const uint8_t MeineTabelle[91][5]=

Wobei Progmem eine Warnung "Attribut ignored" kommt.

Die zweite Frage bezieht sich auf das Auslesen eines Wertes. Gibt es andere Möglichkeiten als über den Zeichen- und Zeilenindex? Zum Beispiel direkt Buchstaben auswählen. Auch soll ein LUT eine Switch Case Anweisung ersetzen können, nur wie?
Code:
    switch(x) {
        case 0xAA: irgendwas; break;    
        case 0xFF: irgendwas; break;    
        default: irgendwas; break;
    }

Viele Grüße
Daniel
 
Hallo,

nun landen die Daten immerhin dort, wo sie landen sollen. Über die Uart + RS232 bekam ich die Werte ordnungsgemäß wieder ausgegeben. (Anderer Code, finde ihn nicht wieder :C)
Wenn ich aber die Zeichen auf der LED-Matrix ausgeben will, bleibt diese schwarz. Wenn ich im Hautprogramm
Code:
PORTD = 255;
nehme, leuchtet die Matrix in voller Pracht, die Timer-Interrups funkionieren also, und kommen mit 625 Hz. Woran kann es liegen? Am Zahlenformat?

Viele Grüße



Code:
#define F_CPU 8000000UL
#include <avr/io.h>
#include <inttypes.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <util/delay.h>
#include <avr/pgmspace.h>


volatile uint8_t Symbole=108, Ledspalten=6, zeichen, spalte;

volatile const uint8_t MeineTabelle[108][6] PROGMEM=
{
	{0x7F, 0x88, 0x88, 0x88, 0x7F, 0x00}, //  A
..... 107 weitere Zeichen
}


ISR (TIMER0_COMPA_vect)
{
	uint8_t wert;
	if (spalte==Ledspalten)
	{
		spalte=0;
		
	}
	

	
	switch(spalte) {
		
		case 0x00: PORTB = 0xBF; break;							//Reihe 1 PB6
		case 0x01: PORTB = 0xDF; break;							//Reihe 2 PB5
		case 0x02: PORTB = 0xEF; break;							//Reihe 3 PB4
		case 0x03: PORTB = 0xFB; break;							//Reihe 4 PB2
		case 0x04: PORTB = 0xFD; break;							//Reihe 5 PB1
		case 0x05: PORTB = 0xFE; break;							//Reihe 6 PB0
	}



	wert = pgm_read_byte (MeineTabelle[zeichen][spalte]);

	PORTD = wert;
	spalte++;
	
}

int main(void)
{
	spalte=0;
	
	DDRB = 0xFF;
	DDRD = 0xFF;
	
	while(1)
	{
		for (zeichen=0;zeichen<=Symbole;zeichen++)
		{
			_delay_ms(1000);
		}	
	}
}
 
Hallo.

Wenn dies dein komplettes Programm ist, kann es eigentlich nicht funktionieren. Es fehlt die Initialisierung des Timers und die Freigabe des COMPA Interrupts. Die ISR wird nie aufgerufen.

Nach der Aktivierung aller Zeilentreiber im Hauptprogramm solltest du keine Frequenz messen, da die Treiber einfach statisch aktiv sind.

Dirk :ciao:
 
Hallo.

Wenn dies dein komplettes Programm ist, kann es eigentlich nicht funktionieren. Es fehlt die Initialisierung des Timers und die Freigabe des COMPA Interrupts. Die ISR wird nie aufgerufen.

Nach der Aktivierung aller Zeilentreiber im Hauptprogramm solltest du keine Frequenz messen, da die Treiber einfach statisch aktiv sind.

Dirk :ciao:

Die Timer-Initialisierung habe ich nicht gepostet. Ist aber vorhanden.
Ich setze ja nur PortD auf 255, hätte dazu sagen sollen, das ich eine 8*6 Matrix habe und die 8 Zeilen an PortD sind. Die 6 Spalten sind über PNP Transistoren an PortB verstreut.
Ich setzte heute abend mal die Timer Interrupts in den sichtbaren, nachvollziehbaren Bereich, um zu sehen ob er die Spalten durchgeht. Aber Meiner Meinung nach klappt der Interrupt, da ich ja in meinem Versuch statisch PortD (Zeilen) komplett auf high lege, jedoch nicht die Spalten.

Edit: Glaube ich habe meinen Fehler gefunden. Schaue nachher nach und melde mich danach.
Edit2: Nun klappt es einigermaßen, aber warum weiß ich auch nicht, habe nichts relevantes verändert :D

Viele Grüße.
Daniel
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)