Forum: Mikrocontroller und Digitale Elektronik Arduino 8x8 Matrix


von Patrick (Gast)


Lesenswert?

Hallo,
Ich plane zur zeit eine 16x16 Matrix und tastete mich deshalb mit Hilfe 
eines Tutorials (http://arduino.cc/en/Tutorial/ShiftOut) erstmal an das 
shiften mit dem arduino.
Das funktionierte Super und nun möchte ich daraus eine 8x8 Matrix 
erstellen, welche mit 2xudn2981 an den Anoden laufen soll (udn2981 in 
Reihe zum 595).
Leider habe ich aber das Problem, dass sobald ich die udn dazubaue 
nichts mehr durchkommt. Muss ich bei diesen Bausteinen noch etwas in der 
Programmierung beachten?
Zum testen verwende ich das Letzte Programm aus dem tut.

Vcc und gnd habe ich verbunden


Vielen dank für eure Hilfe
Patrick

von Hubert G. (hubertg)


Lesenswert?

Wieso 2x UDN2981 ?
Wie wäre es mit einem Schaltplan?

von Patrick (Gast)


Lesenswert?

Weil ich ja irgendwann auf eine 16x16 Matrix mit angehängtem Schaltplan 
kommen will. ( es sind viele Bauteile drauf die ich erstmal nicht 
benötige.)

http://wyolum.com/docs/Nachbau/Nb_v2_SCH.pdf

Momentan reicht mir natürlich ein udn für die Anoden.

von Hubert G. (hubertg)


Lesenswert?

Einen Fehler sehe ich auf die Schnelle nicht. Das die UDN mit +5V aktiv 
sind ist ja klar.
Die 595 an den Kathoden müssen dann bei 0V aktiv sein.
Warum meinst du das du an den Anoden UDN brauchst und bei den Kathoden 
keine? Da sollten es dann aber ULN sein.

von Patrick (Gast)


Lesenswert?

Die Platine habe ich noch Zuhause von einem qlocktwo Projekt. Und der 
Ersteller hat den obigen Schaltplan verwendet. Dort funktioniert es auch 
aber in meinem Probeaufbau leider nicht.

Kann es sein, dass es nicht reicht die Platine über USB zu Speisen? 
Sondern muss über Netzteil versorgt werden.

von Hubert G. (hubertg)


Lesenswert?

Passt aber auch deine Software dazu?

von Patrick (Gast)


Lesenswert?

Bisher noch nicht :(.

Wenn ich die LEDs aber direkt am 595 Ausgang betreibe funktionierts.
Wenn ich aber dazwischen noch den udn habe funktioniert nix.

Auf was muss ich Inder Programmierung achten? Habe das Programm aus dem 
arduino Tutorial verwendet

von Hubert G. (hubertg)


Lesenswert?

Du musst bedenken das du etwa 2V im UDN verlierst.
Was ist wenn du den UDN direkt ansteuerst? Also 5V an den Eingang legen.

von Patrick (Gast)


Lesenswert?

Ok, ich habe jetzt nochmal alles neu aufgebaut auf meinem Steckbrett und 
jetzt funktioniert es.

Habe sodann eine 4x4 Matrix aufgebaut, um sie dann an einem 595 zu 
betreiben.

Angehängtes Programm habe ich draufgeladen, aber es macht noch nicht das 
was es soll (1/1 soll leuchten).

Was ist falsch an meinem Programm? Ich will, dass ich mit TurnOn(1,1), 
die erste LED anschalten kann...und so weiter
1
//Pin connected to ST_CP of 74HC595
2
int latchPin = 8;
3
//Pin connected to SH_CP of 74HC595
4
int clockPin = 12;
5
////Pin connected to DS of 74HC595
6
int dataPin = 11;
7
8
int data[4];
9
10
int COLUMN=1;
11
12
void shiftOut(int myDataPin, int myClockPin, byte myDataOut) 
13
{
14
  int i=0;
15
  int pinState;
16
  pinMode(myClockPin, OUTPUT);
17
  pinMode(myDataPin, OUTPUT);
18
19
  digitalWrite(myDataPin, 0);
20
  digitalWrite(myClockPin, 0);
21
22
  for (i=4; i>=0; i--)  
23
  {
24
    digitalWrite(myClockPin, 0);
25
26
    if ( myDataOut & (1<<i) ) 
27
    {
28
      pinState= 1;
29
    }
30
    else 
31
    {  
32
      pinState= 0;
33
    }
34
    
35
    digitalWrite(myDataPin, pinState);
36
    digitalWrite(myClockPin, 1);
37
    digitalWrite(myDataPin, 0);
38
  }
39
  
40
  digitalWrite(myClockPin, 0);
41
}
42
43
void TurnOn(int x, int y)      //TurnOn(1,1)=0b00010111
44
{
45
 data[y] |= 1 << x-1; 
46
 
47
 delay(100);
48
}
49
50
51
void TurnOff(int x, int y)
52
{
53
 data[y] &= 0 << x-1; 
54
}
55
56
void setup() 
57
{
58
  pinMode(latchPin, OUTPUT);
59
  Serial.begin(9600);
60
}
61
62
void loop() 
63
{
64
    
65
    
66
    
67
    digitalWrite(latchPin, 0);
68
    TurnOn(1,1);
69
    shiftOut(dataPin, clockPin, (data[COLUMN]<<4) | ~(1<<(4-COLUMN)));   
70
    digitalWrite(latchPin, 1);
71
    COLUMN ++;
72
    delay(100);
73
   
74
  }

von Patrick (Gast)


Lesenswert?

Ok, das war nicht gut was ich da geschrieben habe.

Hier mein neuer Code (Allerdings würde ich gerne wissen, wie ich es 
jetzt richtig schreiben muss, dass ich erst die erste LED leuchten 
lassen kann und dann die zweite?
Denn wenn ich es mit Delay schreibe, flackern beide LED´s):
1
int latchPin = 8;
2
int clockPin = 12;
3
int dataPin = 11;
4
5
byte i;
6
byte j;
7
8
byte dataToSend;
9
byte ledData[4];
10
11
void TurnOn(int x, int y) 
12
{
13
 ledData[x-1] |= 1 << y-1; 
14
}
15
16
void setup() {
17
  pinMode(latchPin, OUTPUT);
18
  pinMode(clockPin, OUTPUT);
19
  pinMode(dataPin, OUTPUT);
20
}
21
22
void loop() {
23
 
24
  TurnOn(1,1);
25
  
26
  for (i=0;i<4;i++)
27
  {   
28
    byte dataToSend = (1 << (i+4)) | (15 & ~ledData[i]);
29
      
30
    // setlatch pin low so the LEDs don't change while sending in bits
31
    digitalWrite(latchPin, LOW);
32
33
    for (j=0;j<8;j++)
34
    {
35
      digitalWrite(clockPin,LOW);
36
      digitalWrite(dataPin,((dataToSend>>j)&1));
37
      digitalWrite(clockPin,HIGH);
38
    }
39
    
40
    digitalWrite(latchPin, HIGH);
41
      
42
  }  
43
}

von AVR (Gast)


Lesenswert?

Cool wäre natürlich SPI auch zu benutzen, wenn man schon MOSI, MISO, SCK 
verwendet.

von Patrick (Gast)


Lesenswert?

Was muss ich in meinem Code ändern, dass ich mehrere "Bilder" 
nacheinander anzeigen kann und nicht nur ein Bild auf einmal?

von Patrick (Gast)


Lesenswert?

Versteht jemand mein Problem und kann mir bitte helfen

von Karl H. (kbuchegg)


Lesenswert?

Dein ganzer Denkansatz ist falsch.

Bei einer LED-Matrix geht es nicht im Einzelfall darum, welche LED 
konkret zu leuchten hat, sondern um ein allgemeines Schema.

Du hast im Speicher eine Speicherfläche (ein Array), welches deine LED 
repräsentiert. WEnn du eine LED leuchten lassen willst, dann setzt du 
dort das zugehörige Bit auf 1 bzw. umgekehrt.

Und dann gibt es noch einen allgemeinen Mechanismus, den man am besten 
an einen Timer koppelt, der die ganze Zeit nichts anderes tut, als 
reihum aus diesen Daten heraus Zeile für Zeile laufend an die Matrix 
rauszuschaufeln. D.h. der ganze Ausgabekram hat in der loop eigentlich 
nichts verloren, sondern wird Timer-gesteuert in regelmässigen 
Zeitabständen aufgerufen.
Und der Ausgabekram gibt auch nicht alle Zeilen auf einmal aus, sondern 
immer nur eine. Und beim nächsten Aufruf dann die nächste Zeile.


ALso:
rann an die Bulleten und gelernt, wie man Hardware Timer samt Interrupts 
auf einem Arduino benutzt. Geht genau so, wie auch auf nicht Arduino 
Systemen. Lediglich die Codeaufteilung ist ein wenig anders, weil du ja 
spezielle Funktionen hast, die aufgerufen werden (setup(), loop()) 
anstatt nur einer einzigen main()
FAQ: Timer

von Patrick (Gast)


Lesenswert?

Ok, jetzt bin ich ein bisschen überfordert.
Was muss ich durch den Timer tauschen?

Und wenn ich das erledigt habe, kann ich die "Bilder" wechseln?


Hättest du einen konkreten Änderungsvorschlag für mich?

von Karl H. (kbuchegg)


Lesenswert?

Patrick schrieb:
> Ok, jetzt bin ich ein bisschen überfordert.

Das hab ich mir schon gedacht :-)
D.h. eine LED Matrix fachgerecht aufzubauen ist noch zu schwierig für 
dich :-)

> Hättest du einen konkreten Änderungsvorschlag für mich?

Schau dir erst mal in der FAQ: Timer den Timer Abschnitt an!
Dann lass eine LED Timergesteuert blinken.

Wenn du dann das Zusammenspiel von Hardware-Timer und ISR durchschaut 
hast, dann kann es mit der Matrix weiter gehen.

von Patrick (Gast)


Lesenswert?

Den Abschnitt habe ich mir schon durchgelesen und es auch verstanden.

Mein Problem ist, dass ich nicht verstehe:

- warum ich den Timer verwenden soll, da ich ja jede led bereits so 
ansteuern kann wie ich will
- wie mir der Timer bei meinem jetzigen Problem helfen kann.

Kannst du mir mit meinem Programm helfen?

von Karl H. (kbuchegg)


Lesenswert?

Patrick schrieb:
> Den Abschnitt habe ich mir schon durchgelesen und es auch verstanden.
>
> Mein Problem ist, dass ich nicht verstehe:
>
> - warum ich den Timer verwenden soll, da ich ja jede led bereits so
> ansteuern kann wie ich will
> - wie mir der Timer bei meinem jetzigen Problem helfen kann.
>
> Kannst du mir mit meinem Programm helfen?
1
byte aktuelleZeile;
2
byte ledData[4];
3
4
ISR( ... )
5
{
6
  die aktuelle Zeile der Matrix abschalten
7
8
  aktuelleZeile++;
9
  if( aktuelleZeile == 4)
10
    aktuelleZeile = 0;
11
12
  die LED der aktuellen Zeile auf das Schieberegister ausgeben
13
  (auf Deutsch: ledData[aktuelleZeile] aufs Schieberegister rausgeben)
14
  Schieberegister aktivieren
15
  die aktuelle Zeile der Matrix freischalten
16
}
17
18
setup()
19
{
20
  Timer konfigurieren
21
  und so einstellen, dass die ISR ca 400 bis 500 mal
22
  in der Sekunde aufgerufen wird. Kann auch öfter sein
23
  aber weniger sollte es nicht mehr sein, sonst flackerts.
24
}
25
26
loop()
27
{
28
  mach was immer du willst mit den Bits in ledData
29
  Du kannst hier Änderungen an ledData vornehmen
30
  wie es dir beliebt.
31
  'magisch' (durch die Timer ISR) werden die phsikalischen LED
32
  in der Matrix deinen Änderungen in ledData folgen. Setzt du
33
  1 Bit, dann leuchtet die LED auf. Löscht du 1 Bit dann verlischt
34
  auch die LED wieder.
35
}

von Karl H. (kbuchegg)


Lesenswert?

gilt das
> Habe sodann eine 4x4 Matrix aufgebaut, um sie dann an einem 595 zu
betreiben.

eigentlich noch und stimmt die Annahme, dass du sowohl Zeilen als auch 
Spalten an einem 595 liegen hast?

Denn dann muss die Ausgabe ein bischen abgeändert werden, damit es nicht 
zu Ghosting kommt.
1
ISR( ... )
2
{
3
  eine 0 auf das SR ausgeben und aktivieren (schaltet alle LED ab)
4
5
  aktuelleZeile++;
6
  if( aktuelleZeile == 4)
7
    aktuelleZeile = 0;
8
9
  die LED der aktuellen Zeile auf das Schieberegister ausgeben
10
  (auf Deutsch: ledData[aktuelleZeile] aufs Schieberegister rausgeben)
11
12
  die Zeileninformation da noch mit dazugeben
13
14
  Schieberegister aktivieren
15
}

von Patrick (Gast)


Lesenswert?

Vielen dank für deine Hilfe,
Ich werde mein Programm ändern sobald ich zu Hause bin.

Dann Berichte ich wieder ;)

von Patrick (Gast)


Lesenswert?

Aktuell habe ich eine 4x4 Matrix an einem 595 (Anoden und Kathoden an 
einem)

Nächster Schritt sind zwei 595 für 8x8 Matrix( Anoden und Kathoden 
getrennt)

Letztlich wird's so sein, dass eine 16x16 Matrix an 4x 595 betrieben 
werden

von Karl H. (kbuchegg)


Lesenswert?

Hmm. Eigentlich ist der Teil, den du hattest ja gar nicht so schlecht 
(Na ja). Daraus kann man schon was machen.
1
byte aktuelleZeile;
2
3
void SendByte( byte data )
4
{
5
  for (j=0;j<8;j++)
6
  {
7
    digitalWrite(dataPin,data & 0x01));
8
    digitalWrite(clockPin,HIGH);
9
    digitalWrite(clockPin,LOW);
10
11
    data >>= 1;
12
  }
13
    
14
  digitalWrite(latchPin, HIGH);
15
  digitalWrite(latchPin, LOW);
16
}
17
18
ISR( ... )
19
{
20
  SendByte( 0 );
21
22
  aktuelleZeile++;
23
  if( aktuelleZeile == 4 )
24
    aktuelleZeile = 0;
25
26
  byte dataToSend = (1 << (aktuelleZeile+4)) | (0x0F & ~ledData[aktuelleZeile]);
27
      
28
  SendByte( dataToSend );
29
}

Die Shift Operationen mit variablen Bitzahlen sind mir natürlich noch 
ein Dorn im Auge, aber ich lass das mal so, damit du es wiedererkennst.

von Eumel (Gast)


Lesenswert?

Patrick schrieb:
> Letztlich wird's so sein, dass eine 16x16 Matrix an 4x 595 betrieben
> werden

Ob 1 zu 16 Multiplexen so clever ist?

von Patrick (Gast)


Lesenswert?

Das mit 16x16 ist dann nur der theoretische maximalaufbau.
Es werden dann davon nur 10x11 LEDs verwendet.

Aber wie multiplext man eine 16x16 Matrix stattdessen?

von Karl H. (kbuchegg)


Lesenswert?

Patrick schrieb:
> Das mit 16x16 ist dann nur der theoretische maximalaufbau.
> Es werden dann davon nur 10x11 LEDs verwendet.
>
> Aber wie multiplext man eine 16x16 Matrix stattdessen?

Als 2 Matrizen 8*16 gleichzeitig parallel.
Sonst wirds höchst wahrscheinlich zu dunkel.
Aber das wirst du schon noch sehen.

von Patrick (Gast)


Lesenswert?

Ok, ich danke dir, dass du dich in mein falsches Programm gedacht hast 
und versuche das Programm zu Hause zu ändern.

Ich berichte, wenns was Neues gibt

von Patrick (Gast)


Lesenswert?

So, jetzt habe ich es endlich geschafft einen halbwegs funktionierenden 
Code zu schreiben.
Was müsste ich noch verbessern?
Was muss geändert werden, dass die gewünschte LED dauerhaft abgeschaltet 
werden kann?

Danke
Patrick
1
#define ISR_FREQ 249          //249 = 500Hz
2
3
int latchPin = 8;
4
int clockPin = 12;
5
int dataPin = 11;
6
7
byte i;
8
byte j;
9
10
byte dataToSend;
11
byte ledData[4];
12
byte aktuelleZeile;
13
14
ISR(TIMER2_COMPA_vect)
15
{
16
  SendByte(0);                                                                     
17
18
  aktuelleZeile++;
19
  if( aktuelleZeile == 4 )
20
    aktuelleZeile = 0;
21
22
  byte dataToSend = (1 << (aktuelleZeile+4)) | (0x0F & ~ledData[aktuelleZeile]);  
23
      
24
  SendByte(dataToSend);                                                          
25
}
26
27
28
void SendByte(byte data)
29
{
30
  for (j=0;j<8;j++)
31
  {
32
    digitalWrite(dataPin,data & 0x01);
33
    digitalWrite(clockPin,HIGH);
34
    digitalWrite(clockPin,LOW);
35
36
    data >>= 1;
37
  }
38
    
39
  digitalWrite(latchPin, HIGH);
40
  digitalWrite(latchPin, LOW);
41
}
42
43
void setISRtimer()
44
{                                        
45
  TCCR2A = 0x02;                                                
46
  TCNT2 = 0;                            
47
  OCR2A = ISR_FREQ;                     
48
}
49
 
50
void startISR()
51
{                                     
52
  TCNT2 = 0;                           
53
  TIMSK2|=(1<<OCIE2A);                 
54
}
55
 
56
void stopISR()
57
{                                             
58
  TIMSK2&=~(1<<OCIE2A);                 
59
}
60
61
void turnOn(int x, int y)
62
{
63
  stopISR();
64
  ledData[x-1] |= 1 << y-1;
65
  startISR();
66
}
67
68
void turnOff(int x, int y)
69
{
70
  stopISR();
71
  ledData[x-1] &= 0 << y-1; 
72
  startISR();
73
}
74
75
76
void setup()
77
{
78
  pinMode(latchPin, OUTPUT);
79
  pinMode(clockPin, OUTPUT);
80
  pinMode(dataPin, OUTPUT);
81
  setISRtimer();
82
  startISR();
83
}
84
85
void loop()
86
{
87
  turnOn(1,1);
88
  delay(500);
89
  turnOn(2,1);
90
  turnOff(1,1);
91
  delay(500);
92
93
}

von Karl H. (kbuchegg)


Lesenswert?

1
void turnOn(int x, int y)
2
{
3
  stopISR();
4
  ledData[x-1] |= 1 << y-1;
5
  startISR();
6
}

Das stopISR bzw. StartISR kannst du dir sparen. Brauchst du nicht. Du 
darfst jederzeit auf ledData etwas schreiben. In der ISR wird ledISR nur 
lesend verwendet. Daher ist das kein Problem, wenn hier geschrieben 
wird.
Starte den Timer in setup() und dann lässt du ihn einfach laufen.


1
void turnOff(int x, int y)
2
{
3
  stopISR();
4
  ledData[x-1] &= 0 << y-1; 
5
  startISR();
6
}

so löscht man aber kein Bit.

Bit auf 1 sezten     variable |= ( 1 << Bitnummer );
Bit auf 0 setzen     variable &= ~( 1 << Bitnummer );


logisch überlegen:
eine 0 kannst du nach links bzw. rechts schieben solange und so oft du 
willst. Da kommt immer wieder nur 0 raus. Oder: was mathematisch 
äquivalent ist: 0 multipliziert mit irgendeiner anderen Zahl ergibt 
wieder 0.

D.h. du hast hier nur möglichst kompliziert geschrieben

   ledData[x-1] = 0;

und das ist wohl kaum das, was du willst, denn wenn man egal was mit 0 
verundet, dann kommt da auf jeden Fall 0 raus und diese 0 weist du an 
ledData zu.

von Karl H. (kbuchegg)


Lesenswert?

Und PS:

In C bzw. C++ fangen wir bei 0 zu zählen an.
Gewöhn dich daran!

von Patrick (Gast)


Lesenswert?

Ok, vielen Dank für deine Hilfe.
Jetzt funktioniert das Ding endlich und ich werde morgen auf 8x8 
ausbauen.

von Patrick (Gast)


Lesenswert?

Hallo,
mein Projekt erweist sich leider immer noch als sehr schwierig.
Wollte das Programm jetzt so aufspielen, dass 4x 74hc595 verwendet 
werden.

2x 74hc595 + 2x UDN2981 --> Anoden der Matrix
2x 74hc595                         --> Kathoden der Matrix

Leider funktioniert nichts. Wo übersehe ich einen Fehler?
1
#define ISR_FREQ 249          //249 = 500Hz
2
3
int latchPin = 11;    //11;8
4
int clockPin = 12;    //12;12
5
int dataPin = 10;      //10;11
6
7
int i;
8
int j;
9
10
long dataToSend;
11
long ledData[16];
12
long aktuelleZeile;
13
14
15
ISR(TIMER2_COMPA_vect)
16
{
17
  SendByte(0);                                                                     
18
19
  aktuelleZeile++;
20
  if( aktuelleZeile == 16 )
21
    aktuelleZeile = 0;
22
23
  long dataToSend = (1 << (aktuelleZeile+16)) | (0x0FFFF & ~ledData[aktuelleZeile]);
24
      
25
  SendByte(dataToSend);  
26
27
}
28
29
30
void SendByte(long data)
31
{
32
  for (j=0;j<32;j++)
33
  {
34
    digitalWrite(dataPin,data & 0x01);
35
    digitalWrite(clockPin,HIGH);
36
    digitalWrite(clockPin,LOW);
37
38
    data >>= 1;
39
  }
40
    
41
  digitalWrite(latchPin, HIGH);
42
  digitalWrite(latchPin, LOW);
43
}
44
45
void setISRtimer()
46
{                                        
47
  TCCR2A = 0x02;                                                
48
  TCNT2 = 0;                            
49
  OCR2A = ISR_FREQ;                     
50
}
51
 
52
void startISR()
53
{                                     
54
  TCNT2 = 0;                           
55
  TIMSK2|=(1<<OCIE2A);                 
56
}
57
58
void turnOn(int x, int y)
59
{
60
  ledData[x-1] |= 1 << y-1;
61
}
62
63
void turnOff(int x, int y)
64
{
65
  ledData[x-1] &= ~(1 << y-1); 
66
}
67
68
void Random()
69
{
70
  if ((random(7)==1))
71
  {
72
      turnOn(random(7), random(7));
73
  }
74
  else
75
  {
76
      turnOff(random(7), random(7));
77
  }
78
}
79
80
void Random2()
81
{
82
    int x, y;
83
  x=random(1,6);
84
  y=random(1,6);
85
  
86
  if(random(0,3) ==1)
87
  {
88
    turnOn(x,y); 
89
  }
90
}
91
  
92
void setup()
93
{
94
  pinMode(latchPin, OUTPUT);
95
  pinMode(clockPin, OUTPUT);
96
  pinMode(dataPin, OUTPUT);
97
  setISRtimer();
98
  startISR();
99
}
100
101
void loop()
102
{
103
  turnOn(1,1);
104
  delay(200);
105
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.