Projekt 43: LED-Würfel 2.0: Unterschied zwischen den Versionen
Keine Bearbeitungszusammenfassung |
|||
(24 dazwischenliegende Versionen von einem anderen Benutzer werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
[[Kategorie:ProjekteET_MTR_BSE_WS2017]] | |||
[[Kategorie:Projekte]] | [[Kategorie:Projekte]] | ||
Autoren: Valentina Merkel, Julia Müller<br/> | Autoren: Valentina Merkel, Julia Müller<br/> | ||
Zeile 32: | Zeile 33: | ||
===Aufgabenstellung=== | ===Aufgabenstellung=== | ||
In diesem Projekt ist die Komplexität bereits bestimmt. Der LED-Würfel ist bereits elektrotechnisch aufgebaut. Es handelt sich um einen LED-Würfel aus 512 einfarbigen LEDs. Herzstück der Steuerungsschaltung ist der Mikrocontroller ATmega32 von der Firma Atmel. | In diesem Projekt ist die Komplexität bereits bestimmt. Der LED-Würfel ist bereits elektrotechnisch aufgebaut. Es handelt sich um einen LED-Würfel aus 512 einfarbigen LEDs. Herzstück der Steuerungsschaltung ist der Mikrocontroller ATmega32 von der Firma Atmel. | ||
Das Ziel dieses Projekts "LED-Würfel" 2.0 besteht darin eine Steuerungssoftware für den vorhandenen LED-Würfel zu erstellen, um beliebige Lichtmuster realisieren zu können. Die Muster sollen in die Software | Das Ziel dieses Projekts "LED-Würfel" 2.0 besteht darin eine Steuerungssoftware für den vorhandenen LED-Würfel zu erstellen, um beliebige Lichtmuster realisieren zu können. Die Muster sollen in die Software Matlab der Firma The MathWorks generiert und an den Mikrocontroller übergeben werden. Der Mikrocontroller soll die empfangenen Befehle interpretieren können und die entsprechenden Muster mittels der LEDs erzeugen. | ||
===Benötigte Komponenten=== | ===Benötigte Komponenten=== | ||
Zeile 53: | Zeile 53: | ||
===Der LED-Würfel=== | ===Der LED-Würfel=== | ||
[[Bild:Kathoden_Anode.jpg|thumb|400px|Kathodenebenen und Anodenreihen]] | [[Bild:Kathoden_Anode.jpg|thumb|400px|Kathodenebenen und Anodenreihen]] | ||
Der LED-Würfel besteht wie bereits erwähnt aus 512 grünen LEDs, die um eine dreidimensionale Matrix zu erhalten miteinander verbunden werden mussten. Jede LED besitzt zwei | Der LED-Würfel besteht wie bereits erwähnt aus 512 grünen LEDs, die um eine dreidimensionale Matrix zu erhalten miteinander verbunden werden mussten. Jede LED besitzt zwei Anschlusspins, eine Anode und eine Kathode. Die erste grundlegende Entscheidung, die die Vorgängergruppe getroffen hat, war zu bestimmen, wo die Anode, bzw. die Kathode anschlossen werden. Sie entschieden sich dazu alle Kathoden einer Ebene miteinander zu verbinden. Um nun jede LED einer Ebene einzeln ansteuern zu können, darf zwischen den Anoden keine Verbindung entstehen. Es gibt daher 64 Anodenanschlüsse. Um nun nicht jede Anode einzeln anschließen zu müssen, wurden die 8 übereinanderliegenden LEDs zu einer Reihe zusammengefasst. Die 512 Leuchtdioden unterteilen sich somit in acht Kathoden-Ebenen und 64 Anoden-Reihen. Zur Verdeutlichung siehe Bild [[:Bild:Kathoden_Anode.jpg|Kathodenebenen und Anodenreihen]]. Durch dieses Konzept ist es nun möglich jede LED einzeln anzusteuern. Man muss für die entsprechende LED dann die passende Anodenreihe bestromen und die Kathodenebene auf Ground setzen. Wie dies schaltungstechnisch geregelt wird, wird im Anschnitt [[Projekt 43: LED-Würfel 2.0#Die Platine]]. | ||
[[Bild:LED_Beinchen.jpg|thumb|left|100px|Vorbereitung einer LED]] | [[Bild:LED_Beinchen.jpg|thumb|left|100px|Vorbereitung einer LED]] | ||
[[Bild:Schablone.jpg|thumb|right|100px|Schablone für LED-Ebene]] | [[Bild:Schablone.jpg|thumb|right|100px|Schablone für LED-Ebene]] | ||
Der Aufbau der Ebenen wurde wie folgt realisiert. Zunächst wurde | Der Aufbau der Ebenen wurde wie folgt realisiert. Zunächst wurde die Kathode, wie in Bild [[:Bild:LED_Beinchen.jpg|Vorbereitung einer LED]] zu sehen, um 90° abgewinkelt. Grundsätzlich sollte man sich überlegen die Dichte der LEDs, d.h. die Anzahl der LEDs in einem LED-Würfel, auf die Größe des Würfels abzustimmen. Daraus ergibt sich ein bestimmter Abstand zwischen den LEDs, der eine günstige Darstellung der 3D-Muster ermöglicht. Wird der Abstand zu klein gewählt, werden die hinteren Lichtquellen nicht wahrgenommen. Andererseits wird bei zu großem Abstand die Darstellung zu sehr gedehnt und kann somit schwierig als ein Muster erkannt werden. | ||
Bei dem vorliegenden Projekt wurde eine Schablone aus Holz angefertigt, sodass die | Bei dem vorliegenden Projekt wurde eine Schablone aus Holz angefertigt, sodass die LEDs sowohl in der Ebene als auch in der Höhe in gleichmäßigem Abstand zueinander angeordnet werden konnten. Die Schablone wurde mit 64 Sacklochbohrungen (Durchmesser: 3,2 mm) versehen, wobei die Länge der Kathoden, die etwa 23 mm beträgt, den Abstand zwischen den Bohrlöchern und damit auch zwischen den einzelnen Leuchtdioden, vorgegeben hat (Bild [[:Bild:Schablone.jpg|Schablone für LED-Ebene]]). | ||
[[Bild:eineEbene.jpg|thumb|left|100px|eine verlötete Ebene]] | [[Bild:eineEbene.jpg|thumb|left|100px|eine verlötete Ebene]] | ||
[[Bild:Wuerfel.jpg|thumb|right|100px|fertiger LED-Würfel]] | [[Bild:Wuerfel.jpg|thumb|right|100px|fertiger LED-Würfel]] | ||
Die | Die LEDs wurden mit dem Kopf in die Löcher gesteckt und jeweils an der Kathode miteinander verlötet. Beim Verlöten der Kathoden entstehen acht Reihen. Um den Kontakt zwischen den acht Reihen herzustellen, wurde ein Silberdraht mit dem Durchmesser von 8 mm an drei Stellen der Ebene angebracht. Dieser Draht trägt zusätzlich zur Stabilität der Konstruktion bei. Eine Ebene sieht dabei wie auf Bild [[:Bild:eineEbene.jpg|eine verlötete Ebene]] zu sehen aus. Dieser Vorgang wurde für alle acht Ebenen wiederholt. | ||
Im Anschluss wurden die Anoden der Leuchtdioden miteinander verlötet. Es wurde eine Schicht nach der anderen auf den Würfel aufgesetzt und die 64 Anoden jeweils mit der Reihe verbunden. Das Bild [[:Bild:Wuerfel.jpg|fertiger LED-Würfel]] zeigt den vollständig aufgebauten Würfel. | Im Anschluss wurden die Anoden der Leuchtdioden miteinander verlötet. Es wurde eine Schicht nach der anderen auf den Würfel aufgesetzt und die 64 Anoden jeweils mit der Reihe verbunden. Das Bild [[:Bild:Wuerfel.jpg|fertiger LED-Würfel]] zeigt den vollständig aufgebauten Würfel. | ||
Zeile 70: | Zeile 72: | ||
=== Die Platine=== | === Die Platine=== | ||
Das Herzstück der Platine ist der 8-Bit-Mikrocontroller der Firma Atmel (ATMEGA 32-16 DIP). Über den Mikrocontroller werden die 8 Kathodenebenen und 64 Anodenreihen gesteuert. Der Mikrocontroller verfügt über 40 Pins. Es ist somit nicht möglich gewesen | Das Herzstück der Platine ist der 8-Bit-Mikrocontroller der Firma Atmel (ATMEGA 32-16 DIP). Über den Mikrocontroller werden die 8 Kathodenebenen und 64 Anodenreihen gesteuert. Der Mikrocontroller verfügt über 40 Pins. Es ist somit nicht möglich gewesen alle Ebenen und Reihen direkt an den Mikrocontroller anzuschließen. Die Anschlüsse der Ebenen und der Reihen werden durch das Gehäuse zur Platine geführt. | ||
[[Datei: MOSFET N.png|thumb|100px|N-Kanal MOSFET, normal sperrend]] | [[Datei: MOSFET N.png|thumb|100px|N-Kanal MOSFET, normal sperrend]] | ||
Die 8 Kathodenebenen sollen die Verbindung | Die 8 Kathodenebenen sollen die Verbindung zum Ground realisieren, um den Stromkreis zu schließen und die LED zum Leuchten zu bringen. Die 8 Ebenen können nicht direkt mit Ground verbunden werden, da ansonsten beim Bestromen einer LED-Reihe die ganze Reihe leuchten würde. Es muss somit geregelt werden, dass man die Verbindungen der Ebenen zum Ground einzeln schließen oder öffnen kann. Dies wird durch acht MOSFETs (IRF 630) realisiert. Bei den MOSFETS handelt es sich um N-Kanal, normal sperrende MOSFETs (siehe Bild [[:Bild:MOSFET N.png| Schaltzeichen N-Kanal MOSFET, normal sperrend]] ), d.h. im Ausgangszustand ist keine Verbindung / kein Stromfluss zwischen Drain und Source. An Drain wird jeweils das Kabel der Ebene angeschlossen und Source wird auf Ground gelegt. An 8 Pins (PD0 - PD7) des Mikrocontrollers werden die jeweilige Steuerleitung, d.h. das Gate, des MOSFETs gelegt. Liegt an dem jeweiligen Pin, also am Gate, eine 1 an, so wird ein Stromfluss von Drain nach Source freigegeben. Der Stromkreis wird geschlossen und die LED kann leuchten. | ||
[[Datei:Schieberegister.png|thumb|200px|left|Schaltbild Schieberegister]] | [[Datei:Schieberegister.png|thumb|200px|left|Schaltbild Schieberegister]] | ||
Die 64 Kabel der Reihen werden über acht Schieberegister (74HC 595) mit dem Mikrocontroller verbunden. Das Schaltbild eines Schieberegisters sieht wie in Abbildung [[:Bild:Schieberegister.png|Schaltbild Schieberegister]] dargestellt aus. Die Ansteuerung der Schieberegister erfolgt über den Mikrocontroller. Die Ausgänge QA bis QH sind mit den Kabeln der Reihen verbunden. Jeweils 8 Reihen hängen somit an einem Schieberegister. Ein Schieberegister bildet somit eine Spalte der Matrix ab. Jedes Schieberegister besitzt 5 Eingangspins, einen | Die 64 Kabel der Reihen werden über acht Schieberegister (74HC 595) mit dem Mikrocontroller verbunden. Das Schaltbild eines Schieberegisters sieht wie in Abbildung [[:Bild:Schieberegister.png|Schaltbild Schieberegister]] dargestellt aus. Die Ansteuerung der Schieberegister erfolgt über den Mikrocontroller. Die Ausgänge QA bis QH sind mit den Kabeln der Reihen verbunden. Jeweils 8 Reihen hängen somit an einem Schieberegister. Ein Schieberegister bildet somit eine Spalte der Matrix ab. Jedes Schieberegister besitzt 5 Eingangspins, einen seriellen Eingang (SER, Pin 14), einen Schiebetakt (SCK, Pin 11), ein Reset für das Schieberegister (SCL, Pin 10), einen Speichertakt (RCK, Pin 12) und eine Ausgangssteuerung (G, Pin 13). Die Schiebetakte der 8 Schieberegister sind miteinander verbunden und auf den Pin 23 ((SDA)PC1) des Mikrocontrollers gelegt worden. Das Gleiche gilt für die Speichertakte. Sie liegen auf Pin 24 ((TCK)PC2) des Mikrocontrollers. Der Reset wurde auf die 5V-Versorgung gelegt und kann somit nicht ausgelöst werden. Die Ausgangssteuerung G ist auf Ground gelegt. Dies bedeutet, dass an den Ausgängen der entsprechend über den seriellen Dateneingang eingegebene Pegel anliegt. Die Eingangspegel werden durch den Mikrocontroller bestimmt. Die seriellen Dateneingänge liegen nicht auf demselben Pin und sind nicht miteinander verbunden. Jeder serielle Dateneingang liegt an einem Pin des Mikrocontrollers. Details zur Pinbelegung sind unter [[Projekt 43: LED-Würfel 2.0#Pinbelegung des Mikrocontrollers]] zu finden. Die Funktionsweise eines Schieberegisters wird im Zusammenhang mit der Programmierung des Schieberegisters im Kapitel [[Projekt 43: LED-Würfel 2.0#Schieberegister]]. | ||
Des Weiteren sind an den Mikrocontroller ein externer Quarz zur Takterzeugung und eine ISP-Schnittstelle zum Flashen des Mikrocontrollers angeschlossen. Zu den wesentlichen Komponenten, die für die Ansteuerung der LEDs verantwortlich sind, kommen Vorwiderstände, Dioden und Kondensatoren, die zum Schutz der anderen Bauteile benötigt werden. | Des Weiteren sind an den Mikrocontroller ein externer Quarz zur Takterzeugung und eine ISP-Schnittstelle zum Flashen des Mikrocontrollers angeschlossen. Zu den wesentlichen Komponenten, die für die Ansteuerung der LEDs verantwortlich sind, kommen Vorwiderstände, Dioden und Kondensatoren, die zum Schutz der anderen Bauteile benötigt werden. | ||
Von uns wurde eine UART-Schnittstelle zur seriellen Kommunikation ergänzt. Die Datenleitungen mussten an die entsprechenden Pins des Mikrocontrollers angeschlossen werden. Da die Pins bereits durch zwei Ebenen belegt werden, mussten die Anschlüsse der Ebenen auf zwei andere Pins umgelegt werden. Die aktuelle Pinbelegung befindet sich unter [[Projekt 43: LED-Würfel 2.0#Pinbelegung des Mikrocontrollers]] . | Von uns wurde eine UART-Schnittstelle zur seriellen Kommunikation ergänzt. Die Datenleitungen mussten an die entsprechenden Pins des Mikrocontrollers angeschlossen werden. Da die Pins bereits durch zwei Ebenen belegt werden, mussten die Anschlüsse der Ebenen auf zwei andere Pins umgelegt werden. Die aktuelle Pinbelegung befindet sich unter [[Projekt 43: LED-Würfel 2.0#Pinbelegung des Mikrocontrollers]] . | ||
Zeile 83: | Zeile 85: | ||
{|border="1" | {|border="1" | ||
| Komponente | ! width="200px" | Komponente | ||
| Bezeichnung/Größe | ! width="200px" | Bezeichnung/Größe | ||
| Datenblatt | ! width="200px" | Datenblatt | ||
|- | |- | ||
| LED | | LED | ||
Zeile 149: | Zeile 151: | ||
==== Pinbelegung des Mikrocontrollers ==== | ==== Pinbelegung des Mikrocontrollers ==== | ||
Die Pins des Mikrocontrollers sind jeweils für | Die Pins des Mikrocontrollers sind jeweils für bestimmte Aufgaben vorgesehen. Die Bestimmung findet sich in der Bezeichnung wieder. Bei mehreren Pins liegt eine Doppelbelegung für mehrere Funktionen vor. Außerdem kann man die Pins zwischen Eingang und Ausgang umschalten. Die Konfiguration der Pins erfolgt über die Software, die auf den Mikrocontroller geflasht wird. | ||
In der nachfolgenden Tabelle ist die aktuelle Pinbelegung des Mikrocontrollers dargestellt: | In der nachfolgenden Tabelle ist die aktuelle Pinbelegung des Mikrocontrollers dargestellt: | ||
{|border="1" | {|border="1" | ||
! width="100px"| Pin | |||
! width="200px"| Pin-Bezeichnung | |||
! width="400px"| angeschlossen an | |||
|- | |- | ||
| 1 | | 1 | ||
Zeile 320: | Zeile 322: | ||
====Schaltplan==== | ====Schaltplan==== | ||
Der | Der Schaltplan wurde im Programm Control Panel - EAGLE 7.1.0 Light erstellt. Zugehörige *.sch-Datei liegt im SVN-Ordner. | ||
Aktuell sieht der Schaltplan wie in Bild [[:Bild:Aktueller Schaltplan.png|Aktueller Schaltplan]] zu sehen ist aus. | |||
[[Bild:Aktueller Schaltplan.png|600px|Aktueller Schaltplan]] | |||
== Software == | == Software == | ||
Zeile 333: | Zeile 338: | ||
Sollte mit dem vorhandenen Programm weiter gearbeitet werden, so müssen die grundlegenden Einstellungen nicht mehr vorgenommen werden. Möchte man ein neues Projekt erstellen, so muss man wie folgt vorgehen: | Sollte mit dem vorhandenen Programm weiter gearbeitet werden, so müssen die grundlegenden Einstellungen nicht mehr vorgenommen werden. Möchte man ein neues Projekt erstellen, so muss man wie folgt vorgehen: | ||
# Atmel Studio starten und "New Project" wählen | # Atmel Studio starten und "New Project" wählen. | ||
# Man wird nach der Verwendung | # Man wird nach der Verwendung eines Templates gefragt und wählt "GCC C++ Executable Project". Etwas weiter unten muss man noch den Namen für das Projekt angeben. | ||
# Im nächsten Schritt "Device Selection" muss man angeben, welchen Mikrocontroller man verwendet. | # Im nächsten Schritt "Device Selection" muss man angeben, welchen Mikrocontroller man verwendet. | ||
# Das Projekt wird erstellt. Es wird zusätzlich das erste C-File erstellt in dem bereits die Bibliothek "avr/io.h" eingebunden und die main-Funktion angelegt ist. | # Das Projekt wird erstellt. Es wird zusätzlich das erste C-File erstellt in dem bereits die Bibliothek "avr/io.h" eingebunden und die main-Funktion angelegt ist. | ||
Bevor man beginnt | Bevor man mit dem Programmieren beginnt, sollte man noch die Frequenz, mit der die CPU des Mikrocontrollers arbeitet, einstellen. Die Einstellung erfolgt unter dem Projekt in "Toolchaian", dort unter "AVR/GNU C Compiler" weiter zu Symbols. Dort kann man Symbols definieren und fügt als neuen item "F_CPU=14745600UL" ein. Der Wert hinter dem Gleichheitszeichen entspricht der gewählten Frequenz. Wichtig dabei ist es den Ausdruck ohne Leerzeichen zu schreiben. | ||
==== Mikrocontroller ATmega32 - Einstellungen ==== | ==== Mikrocontroller ATmega32 - Einstellungen ==== | ||
Zeile 355: | Zeile 360: | ||
<code> DDRA = 0xFF; </code> | <code> DDRA = 0xFF; </code> | ||
Hier | Hier werden alle Pins des Port A als Ausgänge gesetzt. | ||
Einen einzelnen Pin setzt man als Ausgang indem man | Einen einzelnen Pin setzt man als Ausgang indem man | ||
Zeile 365: | Zeile 370: | ||
Mehrere zu setzenden Pins programmiert man durch: | Mehrere zu setzenden Pins programmiert man durch: | ||
<code> DDRB |=(1<<DDB2) | (1<<DDB4) | <code> DDRB |=(1<<DDB2) | (1<<DDB4) | (1<<DDB7); </code> | ||
( Pin 2,4 und 7 des Port B werden als Ausgang gesetzt) | ( Pin 2,4 und 7 des Port B werden als Ausgang gesetzt) | ||
===== Aktivierung Funktionen ===== | ===== Aktivierung Funktionen ===== | ||
Funktionen wie Interrupts, serielle Kommunikation, Timer und vieles mehr (siehe dafür in das Datenblatt) verfügen über spezielle Funktionsregister in denen die Einstellungen getroffen werden. Die Namen der Funktionsregisters und die Namen ihrer einzelnen Bits sind als Bezeichner hinterlegt und können bei der Programmierung verwendet werden. | Funktionen wie Interrupts, serielle Kommunikation, Timer und vieles mehr (siehe dafür in das Datenblatt) verfügen über spezielle Funktionsregister in denen die Einstellungen getroffen werden. Die Namen der Funktionsregisters und die Namen ihrer einzelnen Bits sind als Bezeichner hinterlegt und können bei der Programmierung verwendet werden. | ||
Möchte man eine Funktion aktivieren | Möchte man eine Funktion aktivieren, liest man am besten im Datenblatt des Mikrocontrollers nach, wie dies funktioniert und welche Einstellungen getroffen werden müssen. | ||
Die Bits in den Registers setzt man, indem man den | Die Bits in den Registers setzt man, indem man den | ||
Zeile 380: | Zeile 384: | ||
setzt. | setzt. | ||
Möchte man beispielsweise die serielle Kommunikation einrichten und das Senden und Empfangen freischalten, so muss man im Register ''UCSRB'' die Bits ''RXEN'' und ''TXEN'' auf 1 | Möchte man beispielsweise die serielle Kommunikation einrichten und das Senden und Empfangen freischalten, so muss man im Register ''UCSRB'' die Bits ''RXEN'' und ''TXEN'' auf 1 setzen. Der Quellcode sieht wie folgt aus: | ||
<code> UCSRB = (1<<RXEN)|(1<<TXEN); </code> | <code> UCSRB = (1<<RXEN)|(1<<TXEN); </code> | ||
Zeile 400: | Zeile 404: | ||
==== Einbinden von Funktionen ==== | ==== Einbinden von Funktionen ==== | ||
Um Funktionen verwenden zu können, muss zu Beginn des Programms die Bibliotheken einbinden, in denen | Um Funktionen verwenden zu können, muss man zu Beginn des Programms die Bibliotheken einbinden, in denen diese bekannt gemacht werden. Man muss dabei zwischen vorgefertigten und selbstgeschriebenen Funktionen unterscheiden. | ||
Für vorgefertigte Funktion bindet man die Bibliothek über den Quellcode | Für vorgefertigte Funktion bindet man die Bibliothek über den Quellcode | ||
Zeile 410: | Zeile 414: | ||
<code> #include "Bibliothek.h" </code> | <code> #include "Bibliothek.h" </code> | ||
Durch die Bekanntmachung der Funktionen in Bibliotheken, kann man die Funktion auch aus anderen Programmcodes aufrufen. | |||
Die Funktion wird im Hauptprogramm vor der main-Funktion programmiert. Man muss dabei die benötigten Eingabewert und ihren Datentyp, ebenso wie den Datentyp der Ausgabe definieren. Nach der Definition folgt die Programmierung der Funktion in geschweiften Klammern. Die im Funktionsaufruf definierten Eingabewerte können in der Funktion verwendet werden. Der Ausgabewert muss über ''return'' zurückgegeben werden. | |||
<code> | |||
DatentypAusgang Funktionsname ( DatentypEingang1 NameEingang1, DatentypEingang2 NameEingang2,...) <br> | |||
{ <br> | |||
// Hier steht Ihre Funktion und hier verwenden Sie ihre Eingabeparameter <br> | |||
// Ausgabewert setzen, z.B. in Variable Ergebnis <br> | |||
return Ergebnis <br> | |||
} <br> | |||
</code> | |||
==== Mikrocontroller ATmega32 flashen ==== | ==== Mikrocontroller ATmega32 flashen ==== | ||
Zeile 418: | Zeile 435: | ||
{|border="1" | {|border="1" | ||
|JTAGICE3 Pin | ! width="100px"|JTAGICE3 Pin | ||
|ISP 10 Pin | ! width="100px"|ISP 10 Pin | ||
|Bezeichnung | ! width="100px" |Bezeichnung | ||
|Bemerkung | ! width="100px" |Bemerkung | ||
|- | |- | ||
|1 | |1 | ||
Zeile 480: | Zeile 497: | ||
Um die 8 Ausgangspins des Schieberegisters (QA bis QH zu beschreiben muss man wie folgt vorgehen: | Um die 8 Ausgangspins des Schieberegisters (QA bis QH zu beschreiben muss man wie folgt vorgehen: | ||
# Auf serielle Eingangsdatenleitung SER Wert anlegen | # Auf serielle Eingangsdatenleitung SER Wert anlegen. | ||
# Auf Schiebetakt SCK eine steigende Flanke geben. Dies führt dazu, dass alle Werte des internen Schieberegister um eine Stelle verschoben werden. Der Wert am seriellen Dateneingang wird auf die Stelle 0 des internen Registers verschoben, der Wert der Stelle 1 auf Stelle 2,..., der Wert der Stelle 6 auf Stelle 7 und der Wert der Stelle 7 fällt raus | # Auf Schiebetakt SCK eine steigende Flanke geben. Dies führt dazu, dass alle Werte des internen Schieberegister um eine Stelle verschoben werden. Der Wert am seriellen Dateneingang wird auf die Stelle 0 des internen Registers verschoben, der Wert der Stelle 1 auf Stelle 2,..., der Wert der Stelle 6 auf Stelle 7 und der Wert der Stelle 7 fällt raus. | ||
# Solange noch nicht alle Stellen beschrieben sind, gehe wieder zu Schritt 1 und setzt nächsten Wert | # Solange noch nicht alle Stellen beschrieben sind, gehe wieder zu Schritt 1 und setzt nächsten Wert. | ||
# Sind im internen Schieberegister alle Bits nach Wunsch gesetzt, muss man eine steigende Flanke auf den Speichertakt RCK geben. Dies führt dazu, dass die Werte aus dem internen Schieberegister in das Ausgangsregister übertragen werden und somit auf den Ausgängen die Werte anliegen. | # Sind im internen Schieberegister alle Bits nach Wunsch gesetzt, muss man eine steigende Flanke auf den Speichertakt RCK geben. Dies führt dazu, dass die Werte aus dem internen Schieberegister in das Ausgangsregister übertragen werden und somit auf den Ausgängen die Werte anliegen. | ||
Zeile 502: | Zeile 519: | ||
Möchte man den Wert im Datenblatt nachlesen, muss man im Kapitel "''USART''" unter "''Examples of Baud Rate Setting''" suchen. Dort findet man eine Tabelle aus der man den Wert ablesen kann, der in die Funktion eingetragen wird. Zuerst muss man die Spalte mit der passenden Taktfrequenz, d.h. Oszillatorfrequenz suchen. In unserem Fall muss man in der Spalte "f<sub>OSC</sub>=14.7456MHz" schauen. Die Spalte teilt sich nochmals auf in "U2X=0" und "U2X=1". U2X ist die Bezeichnung für ein Bit im Register UCSRA (= UART Control and Status Register A). Ist dieses Bit gesetzt, bedeutet dies, dass die Transferrate verdoppelt ist. In unserem Fall ist U2X gleich 0 gesetzt. | Möchte man den Wert im Datenblatt nachlesen, muss man im Kapitel "''USART''" unter "''Examples of Baud Rate Setting''" suchen. Dort findet man eine Tabelle aus der man den Wert ablesen kann, der in die Funktion eingetragen wird. Zuerst muss man die Spalte mit der passenden Taktfrequenz, d.h. Oszillatorfrequenz suchen. In unserem Fall muss man in der Spalte "f<sub>OSC</sub>=14.7456MHz" schauen. Die Spalte teilt sich nochmals auf in "U2X=0" und "U2X=1". U2X ist die Bezeichnung für ein Bit im Register UCSRA (= UART Control and Status Register A). Ist dieses Bit gesetzt, bedeutet dies, dass die Transferrate verdoppelt ist. In unserem Fall ist U2X gleich 0 gesetzt. | ||
Anschließend kann man die gewünschte Baudrate aus der ersten Spalte wählen. In der Tabelle kann man den Sendefehler bei der Baudrate in der Spalte Error ablesen. Dies kann die Wahl der Baudrate beeinflussen, da man einen möglichst geringen Sendefehler wählen sollte. Der Wert den man aus der Spalte UBRR ablesen kann muss man in der Initialisierungsfunktion <code> UART_Init(baud)</code> als Wert für Baud eintragen. Für den LED-Würfel haben wir eine Übertragungsrate von 9600bps gewählt. Der Error liegt dort bei 0% und in die Funktion wird der Wert 95 eingetragen. | Anschließend kann man die gewünschte Baudrate aus der ersten Spalte wählen. In der Tabelle kann man den Sendefehler bei der Baudrate in der Spalte Error ablesen. Dies kann die Wahl der Baudrate beeinflussen, da man einen möglichst geringen Sendefehler wählen sollte. Der Wert, den man aus der Spalte UBRR ablesen kann, muss man in der Initialisierungsfunktion <code> UART_Init(baud)</code> als Wert für Baud eintragen. Für den LED-Würfel haben wir eine Übertragungsrate von 9600bps gewählt. Der Error liegt dort bei 0% und in die Funktion wird der Wert 95 eingetragen. | ||
Der Wert kann | Der Wert kann alternativ auch über die Formel | ||
UBRR = ((Taktfrequenz in Herz)/(Baudrate*16))-0.5 | UBRR = ((Taktfrequenz in Herz)/(Baudrate*16))-0.5 | ||
berechnet. Der Wert sollte mit dem Wert aus der Tabelle nahezu übereinstimmen. Berechnet man den Wert, so erhält man einen Wert von 95.5 und muss diesen dann auf oder abrunden auf den nächsten ganzzahligen Wert. | berechnet werden. Der Wert sollte mit dem Wert aus der Tabelle nahezu übereinstimmen. Berechnet man den Wert, so erhält man einen Wert von 95.5 und muss diesen dann auf oder abrunden auf den nächsten ganzzahligen Wert. | ||
Nach der Initialisierung der UART-Schnittstelle werden im main-Programm die Funktionen <code> LEDaus()</code> und <code> Ebeneaus()</code> einmalig aufgerufen. Beim Start des Mikrocontrollers werden dadurch alle LEDs am LED-Würfel ausgeschaltet und es sind immer dieselbe Startbedingungen (alles Aus) gegeben. | Nach der Initialisierung der UART-Schnittstelle werden im main-Programm die Funktionen <code> LEDaus()</code> und <code> Ebeneaus()</code> einmalig aufgerufen. Beim Start des Mikrocontrollers werden dadurch alle LEDs am LED-Würfel ausgeschaltet und es sind immer dieselbe Startbedingungen (alles Aus) gegeben. | ||
Zeile 575: | Zeile 592: | ||
<code> LEDaus()</code> | <code> LEDaus()</code> | ||
Ruft man diese Funktion auf, so werden alle Ausgänge aller 8 Schieberegister auf 0 gesetzt | Ruft man diese Funktion auf, so werden alle Ausgänge aller 8 Schieberegister auf 0 gesetzt, d.h. alle LEDs werden ausgeschaltet. | ||
Will man nur einzelne LEDs ausschalten so muss man dies über die Funktion <code> LEDan</code> lösen. | Will man nur einzelne LEDs ausschalten, so muss man dies über die Funktion <code> LEDan</code> lösen. | ||
Die Funktion wird über die <code> LEDControlStateMachine </code> aufgerufen, wenn man über Matlab ein kleines "b" sendet. | Die Funktion wird über die <code> LEDControlStateMachine </code> aufgerufen, wenn man über Matlab ein kleines "b" sendet. | ||
Zeile 586: | Zeile 603: | ||
<code> Ebenean(Ebene)</code> | <code> Ebenean(Ebene)</code> | ||
Die Funktion benötigt einen Eingabewert mit der Information, welche Ebene anschaltet werden soll. Erst wenn diese Funktion aufgerufen, dann ist der Stromkreis geschlossen. Es kann allerdings der Fall sein, | Die Funktion benötigt einen Eingabewert mit der Information, welche Ebene anschaltet werden soll. Erst wenn diese Funktion aufgerufen, dann ist der Stromkreis geschlossen. Es kann allerdings der Fall sein, dass noch keine LEDs gesetzt wurde. In dem Fall ist noch der Funktionsaufruf der Funktion <code> LEDan_Matlab</code> notwendig, damit die LEDs leuchten. | ||
In Matlab muss das Datenbyte für den Wert ''Ebene'' als ASCII-Zeichen ''1'' - ''8'' für die Ebene 1 - 8 versendet werden. Matlab muss zuerst das Befehlsbyte senden und anschließend das Datenbyte. | In Matlab muss das Datenbyte für den Wert ''Ebene'' als ASCII-Zeichen ''1'' - ''8'' für die Ebene 1 - 8 versendet werden. Matlab muss zuerst das Befehlsbyte senden und anschließend das Datenbyte. | ||
Zeile 643: | Zeile 660: | ||
Die Funktion <code> UART_gets(*Buffer,MaxLen)</code> kann eine Zeichenkette empfangen. Sie wird aktuell nicht verwendet. Dennoch haben wir sie im Programm behalten, da die Funktion bei der Weiterentwicklung nützlich sein kann. | Die Funktion <code> UART_gets(*Buffer,MaxLen)</code> kann eine Zeichenkette empfangen. Sie wird aktuell nicht verwendet. Dennoch haben wir sie im Programm behalten, da die Funktion bei der Weiterentwicklung nützlich sein kann. | ||
Über die Funktion <code> UART_Transmit(data)</code> kann ein Datenbyte verschickt werden. Diese Funktion ist hilfreich, um zu | Über die Funktion <code> UART_Transmit(data)</code> kann ein Datenbyte verschickt werden. Diese Funktion ist hilfreich, um zu testen, ob die Kommunikation über die UART-Schnittstelle funktioniert. | ||
=== Matlab-Programm LED-Würfel === | === Matlab-Programm LED-Würfel === |
Aktuelle Version vom 12. Oktober 2017, 16:51 Uhr
Autoren: Valentina Merkel, Julia Müller
Betreuer: Prof. Göbel
Aufgabe
Erstellen Sie eine Steuerungssoftware für den bestehenden LED-Würfel. Lesen Sie die Daten in einem geeigneten Format (erstellt in Matlab) ein und erzeugen Sie damit beliebige Lichtmuster.
Erwartungen an Ihre Projektlösung
- Darstellung der Theorie
- Entwurf einer Steuerung.
- Recherche zu bestehenden Lösungen
- Programmierung in Matlab und C
- Erstellung eines Benutzerleitfadens für die Anwendung der Software
- Test und wiss. Dokumentation
- Live Vorführung während der Abschlusspräsentation
Schwierigkeitsgrad
Anspruchsvoll (***)
→ zurück zum Hauptartikel: Angewandte Elektrotechnik (WS 14/15)
Einleitung
Ein LED-Würfel (engl.: LED-Cube) ist aktuell ein beliebtes Projekt. Dieses Projekt wurde bereits öfters realisiert und so findet man im Internet auch einige Beispiele für LED-Würfel. Die Komplexität des LED-Würfels kann dabei stark variieren. Sie hängt hauptsächlich von der Anzahl der LEDs und der Wahl der LED (einfarbig oder RGB) ab. Ein Beispiel für ein sehr komplexen LED-Würfel ist in dem Bild Beispiel für ein LED-Würfel zu sehen.
Ziel aller LED-Würfel ist es dreidimensionale Symbole, Figuren und Texte darzustellen. Dies sollen sich dann im dreidimensionalen LED-Würfel bewegen, d.h. durchlaufen oder drehen. Durch die Komplexität der Muster und Bewegungen wird die Komplexität des Projektes weiter beeinflusst. Für die Realisierung eines LED-Würfels benötigt man Erfahrungen, bzw. Interesse im Bereich Elektrotechnik und Informatik. Die elektrotechnische Komponente befasst sich mit dem Aufbau des LED-Würfels und der Realisierung der Steuerungsschaltung. Man muss sich Gedanken darüber machen, wie die LEDs miteinander verbunden werden und wie man sie anschließend elektrisch ansteuern will. Die elektrische Ansteuerung erfolgt dann über die Steuerungsschaltung. Diese muss programmiert werden, dies führt einen zu dem Bereich der Informatik. Man benötigt je nach gewähltem Mikrocontroller entsprechende Programmierkenntisse. Weiterer Faktor für die Komplexität ist somit die Wahl der Programmierung (Sprache, Oberfläche, etc.). Dieses Projekt lässt sich in der Komplexität durch viele Komponenten steuern. Es ist somit ein Projekt, das sowohl für Einsteiger als auch für Erfahrene geeignet ist. Jeder kann dieses Projekt so gestalten, dass es seinem Können entspricht.
Aufgabenstellung
In diesem Projekt ist die Komplexität bereits bestimmt. Der LED-Würfel ist bereits elektrotechnisch aufgebaut. Es handelt sich um einen LED-Würfel aus 512 einfarbigen LEDs. Herzstück der Steuerungsschaltung ist der Mikrocontroller ATmega32 von der Firma Atmel. Das Ziel dieses Projekts "LED-Würfel" 2.0 besteht darin eine Steuerungssoftware für den vorhandenen LED-Würfel zu erstellen, um beliebige Lichtmuster realisieren zu können. Die Muster sollen in die Software Matlab der Firma The MathWorks generiert und an den Mikrocontroller übergeben werden. Der Mikrocontroller soll die empfangenen Befehle interpretieren können und die entsprechenden Muster mittels der LEDs erzeugen.
Benötigte Komponenten
Die Hauptkomponente ist der LED-Würfel. Er besteht aus einem Gehäuse, in dem die Platine mit der benötigten Hardware verbaut ist, und dem eigentlichen LED-Würfel, der aus 512 grünen Leuchtdioden aufgebaut ist (siehe Bild Unser LED-Würfel). Der LED-Würfel besteht aus einer Matrix von 8 x 8 x 8 grünen 3mm-Leuchtdioden. Er besitzt somit 8 Ebenen und eine Ebene besteht aus 64 LEDs. Diese lassen sich unabhängig voneinander steuern. Der LED-Würfel ist auf dem Gehäuse der Schaltung aufgebaut worden. Das Gehäuse besteht aus vier Holzplatten mit einer Dicke von 1,5 cm, die mit weißer Klebefolie überzogen wurden. Die Maße betragen 30 cm x 13 cm x 30 cm (B x H x T). Das Gehäuse für die Schaltung dient somit gleichzeitig als Sockel für den Würfel. Die Kabel des LED-Würfels werden direkt ins Gehäuse geführt und mit der Schaltung verkabelt. Weitere benötigte Komponenten sind ein Computer mit der Software Atmel-Studio 6.2 zur Programmierung des Mikrocontrollers und der Software Matlab zur Generierung der Muster. Das Programm für den Mikrocontroller muss auf den Mikrocontroller geflasht werden. Daher wird zusätzlich ein Flash-Gerät benötigt. Die Kommunikation von Matlab zum Mikrocontroller muss noch festgelegt werden, dafür wird dann eine zusätzliche Kommunikationsschnittstelle aufgebaut werden müssen.
Vorgehensweise
Zu Beginn wird die Funktionsweise des LED-Würfels analysiert. Hierzu werden der Aufbau des Würfels, d.h. die Schaltung,die verwendete Hardware und das vorhandene Beispielprogramm näher betrachtet. Es folgt die Planung des weiteren Vorgehens und die Beschreibung des angestrebten Lösungsweges. Auf Basis des Lösungskonzeptes wird eine Steuerung entworfen, wobei bestehende Lösungen analysiert und eingebunden werden. Die Programmierung erfolgt dabei in Atmel-Studio 6.2 und Matlab. Nach der erfolgreichen Programmierung wird ein Benutzerleitfaden für die Anwendung der Software erstellt. Anschließend wird die Vorgehensweise zur Ansteuerung des LED-Würfels dokumentiert und das Ergebnis im Rahmen der Abschlusspräsentation vorgeführt.
Aufbau
Dieser Abschnitt beschreibt den vorgefundenen Aufbau der gesamten Hardware und wie das Funktionsprinzip der Schaltung konzipiert wurde. Die Informationen über den Aufbau des LED-Würfels stammen aus der Dokumentation der Vorgängergruppe. Die Beschreibung der Hardware und des Schaltungsaufbaus sind notwendig, um den Würfel korrekt programmieren zu können.
Der LED-Würfel
Der LED-Würfel besteht wie bereits erwähnt aus 512 grünen LEDs, die um eine dreidimensionale Matrix zu erhalten miteinander verbunden werden mussten. Jede LED besitzt zwei Anschlusspins, eine Anode und eine Kathode. Die erste grundlegende Entscheidung, die die Vorgängergruppe getroffen hat, war zu bestimmen, wo die Anode, bzw. die Kathode anschlossen werden. Sie entschieden sich dazu alle Kathoden einer Ebene miteinander zu verbinden. Um nun jede LED einer Ebene einzeln ansteuern zu können, darf zwischen den Anoden keine Verbindung entstehen. Es gibt daher 64 Anodenanschlüsse. Um nun nicht jede Anode einzeln anschließen zu müssen, wurden die 8 übereinanderliegenden LEDs zu einer Reihe zusammengefasst. Die 512 Leuchtdioden unterteilen sich somit in acht Kathoden-Ebenen und 64 Anoden-Reihen. Zur Verdeutlichung siehe Bild Kathodenebenen und Anodenreihen. Durch dieses Konzept ist es nun möglich jede LED einzeln anzusteuern. Man muss für die entsprechende LED dann die passende Anodenreihe bestromen und die Kathodenebene auf Ground setzen. Wie dies schaltungstechnisch geregelt wird, wird im Anschnitt Projekt 43: LED-Würfel 2.0#Die Platine.
Der Aufbau der Ebenen wurde wie folgt realisiert. Zunächst wurde die Kathode, wie in Bild Vorbereitung einer LED zu sehen, um 90° abgewinkelt. Grundsätzlich sollte man sich überlegen die Dichte der LEDs, d.h. die Anzahl der LEDs in einem LED-Würfel, auf die Größe des Würfels abzustimmen. Daraus ergibt sich ein bestimmter Abstand zwischen den LEDs, der eine günstige Darstellung der 3D-Muster ermöglicht. Wird der Abstand zu klein gewählt, werden die hinteren Lichtquellen nicht wahrgenommen. Andererseits wird bei zu großem Abstand die Darstellung zu sehr gedehnt und kann somit schwierig als ein Muster erkannt werden. Bei dem vorliegenden Projekt wurde eine Schablone aus Holz angefertigt, sodass die LEDs sowohl in der Ebene als auch in der Höhe in gleichmäßigem Abstand zueinander angeordnet werden konnten. Die Schablone wurde mit 64 Sacklochbohrungen (Durchmesser: 3,2 mm) versehen, wobei die Länge der Kathoden, die etwa 23 mm beträgt, den Abstand zwischen den Bohrlöchern und damit auch zwischen den einzelnen Leuchtdioden, vorgegeben hat (Bild Schablone für LED-Ebene).
Die LEDs wurden mit dem Kopf in die Löcher gesteckt und jeweils an der Kathode miteinander verlötet. Beim Verlöten der Kathoden entstehen acht Reihen. Um den Kontakt zwischen den acht Reihen herzustellen, wurde ein Silberdraht mit dem Durchmesser von 8 mm an drei Stellen der Ebene angebracht. Dieser Draht trägt zusätzlich zur Stabilität der Konstruktion bei. Eine Ebene sieht dabei wie auf Bild eine verlötete Ebene zu sehen aus. Dieser Vorgang wurde für alle acht Ebenen wiederholt. Im Anschluss wurden die Anoden der Leuchtdioden miteinander verlötet. Es wurde eine Schicht nach der anderen auf den Würfel aufgesetzt und die 64 Anoden jeweils mit der Reihe verbunden. Das Bild fertiger LED-Würfel zeigt den vollständig aufgebauten Würfel.
Die Platine
Das Herzstück der Platine ist der 8-Bit-Mikrocontroller der Firma Atmel (ATMEGA 32-16 DIP). Über den Mikrocontroller werden die 8 Kathodenebenen und 64 Anodenreihen gesteuert. Der Mikrocontroller verfügt über 40 Pins. Es ist somit nicht möglich gewesen alle Ebenen und Reihen direkt an den Mikrocontroller anzuschließen. Die Anschlüsse der Ebenen und der Reihen werden durch das Gehäuse zur Platine geführt.
Die 8 Kathodenebenen sollen die Verbindung zum Ground realisieren, um den Stromkreis zu schließen und die LED zum Leuchten zu bringen. Die 8 Ebenen können nicht direkt mit Ground verbunden werden, da ansonsten beim Bestromen einer LED-Reihe die ganze Reihe leuchten würde. Es muss somit geregelt werden, dass man die Verbindungen der Ebenen zum Ground einzeln schließen oder öffnen kann. Dies wird durch acht MOSFETs (IRF 630) realisiert. Bei den MOSFETS handelt es sich um N-Kanal, normal sperrende MOSFETs (siehe Bild Schaltzeichen N-Kanal MOSFET, normal sperrend ), d.h. im Ausgangszustand ist keine Verbindung / kein Stromfluss zwischen Drain und Source. An Drain wird jeweils das Kabel der Ebene angeschlossen und Source wird auf Ground gelegt. An 8 Pins (PD0 - PD7) des Mikrocontrollers werden die jeweilige Steuerleitung, d.h. das Gate, des MOSFETs gelegt. Liegt an dem jeweiligen Pin, also am Gate, eine 1 an, so wird ein Stromfluss von Drain nach Source freigegeben. Der Stromkreis wird geschlossen und die LED kann leuchten.
Die 64 Kabel der Reihen werden über acht Schieberegister (74HC 595) mit dem Mikrocontroller verbunden. Das Schaltbild eines Schieberegisters sieht wie in Abbildung Schaltbild Schieberegister dargestellt aus. Die Ansteuerung der Schieberegister erfolgt über den Mikrocontroller. Die Ausgänge QA bis QH sind mit den Kabeln der Reihen verbunden. Jeweils 8 Reihen hängen somit an einem Schieberegister. Ein Schieberegister bildet somit eine Spalte der Matrix ab. Jedes Schieberegister besitzt 5 Eingangspins, einen seriellen Eingang (SER, Pin 14), einen Schiebetakt (SCK, Pin 11), ein Reset für das Schieberegister (SCL, Pin 10), einen Speichertakt (RCK, Pin 12) und eine Ausgangssteuerung (G, Pin 13). Die Schiebetakte der 8 Schieberegister sind miteinander verbunden und auf den Pin 23 ((SDA)PC1) des Mikrocontrollers gelegt worden. Das Gleiche gilt für die Speichertakte. Sie liegen auf Pin 24 ((TCK)PC2) des Mikrocontrollers. Der Reset wurde auf die 5V-Versorgung gelegt und kann somit nicht ausgelöst werden. Die Ausgangssteuerung G ist auf Ground gelegt. Dies bedeutet, dass an den Ausgängen der entsprechend über den seriellen Dateneingang eingegebene Pegel anliegt. Die Eingangspegel werden durch den Mikrocontroller bestimmt. Die seriellen Dateneingänge liegen nicht auf demselben Pin und sind nicht miteinander verbunden. Jeder serielle Dateneingang liegt an einem Pin des Mikrocontrollers. Details zur Pinbelegung sind unter Projekt 43: LED-Würfel 2.0#Pinbelegung des Mikrocontrollers zu finden. Die Funktionsweise eines Schieberegisters wird im Zusammenhang mit der Programmierung des Schieberegisters im Kapitel Projekt 43: LED-Würfel 2.0#Schieberegister. Des Weiteren sind an den Mikrocontroller ein externer Quarz zur Takterzeugung und eine ISP-Schnittstelle zum Flashen des Mikrocontrollers angeschlossen. Zu den wesentlichen Komponenten, die für die Ansteuerung der LEDs verantwortlich sind, kommen Vorwiderstände, Dioden und Kondensatoren, die zum Schutz der anderen Bauteile benötigt werden. Von uns wurde eine UART-Schnittstelle zur seriellen Kommunikation ergänzt. Die Datenleitungen mussten an die entsprechenden Pins des Mikrocontrollers angeschlossen werden. Da die Pins bereits durch zwei Ebenen belegt werden, mussten die Anschlüsse der Ebenen auf zwei andere Pins umgelegt werden. Die aktuelle Pinbelegung befindet sich unter Projekt 43: LED-Würfel 2.0#Pinbelegung des Mikrocontrollers .
Auflistung der Komponenten für die Platine
Eine detaillierte Auflistung aller Komponenten ist in den folgenden Tabellen enthalten.
Komponente | Bezeichnung/Größe | Datenblatt |
---|---|---|
LED | LED 3mm ST GN | Datenblatt |
Silberdraht | Silber 0,8mm | Datenblatt |
ATMEGA32 | ATMEGA 32-16 DIP | [1] |
N-MOSFET | IRF 630 | Datenblatt |
Kondensator | 22 pF | Datenblatt |
Tantal-Chip-Kondensator | 10uF | Datenblatt |
Kondensator | 1nF | Datenblatt |
Vorwiderstände | 150 Ohm | Datenblatt |
Spannungsregler, Low Drop, TO-220 | LM 1085 IT5,0 | Datenblatt |
8-Bit Schieberegister | 74HC 595 | Datenblatt |
IC-Sockel 20-polig | GS 20 | |
IC-Sockel 40-polig | GS 40 | |
Treiber/Empfänger | MAX 232 CPE | Datenblatt |
Standardquarz | 14,7456-HC49U-S | Datenblatt |
Rippen-Kühlkörper | V 4330N |
Pinbelegung des Mikrocontrollers
Die Pins des Mikrocontrollers sind jeweils für bestimmte Aufgaben vorgesehen. Die Bestimmung findet sich in der Bezeichnung wieder. Bei mehreren Pins liegt eine Doppelbelegung für mehrere Funktionen vor. Außerdem kann man die Pins zwischen Eingang und Ausgang umschalten. Die Konfiguration der Pins erfolgt über die Software, die auf den Mikrocontroller geflasht wird.
In der nachfolgenden Tabelle ist die aktuelle Pinbelegung des Mikrocontrollers dargestellt:
Pin | Pin-Bezeichnung | angeschlossen an |
---|---|---|
1 | PB0 (XCK/T0) | frei |
2 | PB1 (T1) | frei |
3 | PB2 (INT2/AIN0) | Gain MOSFET für Ebene 2 |
4 | PB3 (OC0/AIN1) | Gain MOSFET für Ebene 1 |
5 | PB4 (SS) | frei |
6 | PB5 (MOSI) | ISP-Schnittstelle zum Flashen |
7 | PB6 (MISO) | ISP-Schnittstelle zum Flashen |
8 | PB7 (SCK) | ISP-Schnittstelle zum Flashen |
9 | RESET | +5V Versorgung, d.h. kein Reset möglich |
10 | VCC | +5V Versorgung |
11 | GND | Ground |
12 | XTAL2 | externer Quarz |
13 | XTAL1 | externer Quarz |
14 | PD0 (RXD) | UART-Schnittstelle für Kommunikation |
15 | PD1 (TXD) | UART-Schnittstelle für Kommunikation |
16 | PD2 (INT0) | Gain MOSFET für Ebene 3 |
17 | PD3 (INT1) | Gain MOSFET für Ebene 4 |
18 | PD4 (OC1B) | Gain MOSFET für Ebene 5 |
19 | PD5 (OC1A) | Gain MOSFET für Ebene 6 |
20 | PD6 (ICP1) | Gain MOSFET für Ebene 7 |
21 | PD7 (OC2) | Gain MOSFET für Ebene 8 |
22 | PC0 (SCL) | frei |
23 | PC1 (SDA) | Schiebetakt SCK aller Schieberegister |
24 | PC2 (TCK) | Speichertakt RCK aller Schieberegister |
25 | PC3 (TMS) | frei |
26 | PC4 (TDO) | frei |
27 | PC5 (TDI) | frei |
28 | PC6 (TOSC1) | frei |
29 | PC7 (TOSC2) | frei |
30 | AVCC | +5V-Versorgung |
31 | GND | Ground |
32 | AREF | frei |
33 | PA7 (ADC7) | Serieller Dateneingang Schieberegister 8 für LED 57 - 64 |
34 | PA6 (ADC6) | Serieller Dateneingang Schieberegister 7 für LED 49 - 56 |
35 | PA5 (ADC5) | Serieller Dateneingang Schieberegister 6 für LED 41 - 48 |
36 | PA4 (ADC4) | Serieller Dateneingang Schieberegister 5 für LED 33 - 40 |
37 | PA3 (ADC3) | Serieller Dateneingang Schieberegister 4 für LED 25 - 32 |
38 | PA2 (ADC2) | Serieller Dateneingang Schieberegister 3 für LED 17 - 24 |
39 | PA1 (ADC1) | Serieller Dateneingang Schieberegister 2 für LED 9 - 16 |
40 | PA0 (ADC0) | Serieller Dateneingang Schieberegister 1 für LED 1 - 8 |
Schaltplan
Der Schaltplan wurde im Programm Control Panel - EAGLE 7.1.0 Light erstellt. Zugehörige *.sch-Datei liegt im SVN-Ordner. Aktuell sieht der Schaltplan wie in Bild Aktueller Schaltplan zu sehen ist aus.
Software
Grundlagen Programmierung
In diesem Abschnitt wird zunächst grundlegend erklärt, wie man einen Mikrocontroller und die für uns relevanten Komponenten programmieren kann. Es werden nur die Teile erklärt, die für die Programmierung unseres LED-Würfels interessant sind. So soll der Einstieg in das entstandene Programm erleichtert werden. Dadurch soll ein schnelleres Arbeiten an der Software ermöglicht werden.
Grundlegende Einstellungen Atmel Studio 6.2
Das Programm für den ATmega32 wird über die Software Atmel Studio 6.2 programmiert. Es handelt sich dabei um eine spezielle Oberfläche für die Atmel Mikrocontroller. Sollte mit dem vorhandenen Programm weiter gearbeitet werden, so müssen die grundlegenden Einstellungen nicht mehr vorgenommen werden. Möchte man ein neues Projekt erstellen, so muss man wie folgt vorgehen:
- Atmel Studio starten und "New Project" wählen.
- Man wird nach der Verwendung eines Templates gefragt und wählt "GCC C++ Executable Project". Etwas weiter unten muss man noch den Namen für das Projekt angeben.
- Im nächsten Schritt "Device Selection" muss man angeben, welchen Mikrocontroller man verwendet.
- Das Projekt wird erstellt. Es wird zusätzlich das erste C-File erstellt in dem bereits die Bibliothek "avr/io.h" eingebunden und die main-Funktion angelegt ist.
Bevor man mit dem Programmieren beginnt, sollte man noch die Frequenz, mit der die CPU des Mikrocontrollers arbeitet, einstellen. Die Einstellung erfolgt unter dem Projekt in "Toolchaian", dort unter "AVR/GNU C Compiler" weiter zu Symbols. Dort kann man Symbols definieren und fügt als neuen item "F_CPU=14745600UL" ein. Der Wert hinter dem Gleichheitszeichen entspricht der gewählten Frequenz. Wichtig dabei ist es den Ausdruck ohne Leerzeichen zu schreiben.
Mikrocontroller ATmega32 - Einstellungen
Bei einem Mikrocontroller können sehr viele Einstellungen vorgenommen werden. Diese beziehen sich auf die Verwendung der Pins, auf die Aktivierung und Deaktivierung von Funktionen, etc. Wie die Einstellungen der einzelnen Funktionen vorzunehmen sind, findet man im Datenblatt des ATmega32. Ebenso findet man dort die Informationen über die Standardeinstellungen. Der Vorteil bei der Verwendung des Atmel Studios ist, dass für die einzustellenden Parameter bereits vorgefertige Bezeichner, um die Einstellungen zu erleichtern. Die Einstellungen, die wir vorgenommen haben, sollen im Folgenden beschrieben werden.
Die Einstellung der Pins
Der Mikrocontroller besitzt 4 Ports (A, B, C, D)mit jeweils 8 Pins. Für die Ports kann bestimmen, welcher Pin als Ausgang und welcher Pin als Eingang verwendet werden soll. Die Festlegung der Pins muss zu Beginn der main-Funktion erfolgen. Für das Setzen der Ports gibt es ebenfalls vorgefertigte Bezeichner. Die Ports werden mit DDRA, DDRB, DDRC und DDRD bezeichnet. Möchte man einen einzelnen Pin als Ausgang setzten, wo muss man DD+Port+Pinnummer aufrufen.
Sollen alle Pins des Ports als Ausgänge verwendet werden, so kann man dies definieren durch
DDRA = 0xFF;
Hier werden alle Pins des Port A als Ausgänge gesetzt.
Einen einzelnen Pin setzt man als Ausgang indem man
DDRA |=(1<<DDA2);
programmiert. In diesem Fall würde nur Pin 2 des Port A als Ausgang gesetzt werden.
Mehrere zu setzenden Pins programmiert man durch:
DDRB |=(1<<DDB2) | (1<<DDB4) | (1<<DDB7);
( Pin 2,4 und 7 des Port B werden als Ausgang gesetzt)
Aktivierung Funktionen
Funktionen wie Interrupts, serielle Kommunikation, Timer und vieles mehr (siehe dafür in das Datenblatt) verfügen über spezielle Funktionsregister in denen die Einstellungen getroffen werden. Die Namen der Funktionsregisters und die Namen ihrer einzelnen Bits sind als Bezeichner hinterlegt und können bei der Programmierung verwendet werden. Möchte man eine Funktion aktivieren, liest man am besten im Datenblatt des Mikrocontrollers nach, wie dies funktioniert und welche Einstellungen getroffen werden müssen. Die Bits in den Registers setzt man, indem man den
Bezeichner Register = (Wert für das Bit << Bezeichner Bit)
setzt.
Möchte man beispielsweise die serielle Kommunikation einrichten und das Senden und Empfangen freischalten, so muss man im Register UCSRB die Bits RXEN und TXEN auf 1 setzen. Der Quellcode sieht wie folgt aus:
UCSRB = (1<<RXEN)|(1<<TXEN);
Mikrocontroller ATmega32 - Pins setzen
Nachdem man die Pins der Ports als Ausgang eingestellt hat, kann man den Ausgang auf High (=1) oder auf Low (=0) setzen. Die Ports werden als PORTA, PORTB, PORTC und PORTD bezeichnet. Die Bezeichnung der einzelnen Pins entspricht der Bezeichnung im Datenblatt, z.B. für Pin 3 des Ports C PC3. Möchte man alle Pins eines Ports gleichzeitig setzen, so ist dies möglich, indem man den Port gleich dem Hexadezimal-Wert der gesetzten Pins setzt. Möchte man beispielsweise alle Pins von Port A setzen, so lautet die Programmcodezeile:
PORTA = 0xFF;
Entsprechend setzt man eine 0x00, wenn man alle Pins auf 0 setzen will.
Einzelne Pins kann man über folgende Befehle beeinflussen:
- Setzen:
PORTA |= (1<<PA3);
(Setzt Pin 3 von Port A auf 1) - Zurücksetzen:
PORTA &= ~(1<<PA3);
(Setzt Pin 3 von Port A auf 0)
Einbinden von Funktionen
Um Funktionen verwenden zu können, muss man zu Beginn des Programms die Bibliotheken einbinden, in denen diese bekannt gemacht werden. Man muss dabei zwischen vorgefertigten und selbstgeschriebenen Funktionen unterscheiden. Für vorgefertigte Funktion bindet man die Bibliothek über den Quellcode
#include <Bibliothek.h>
ein.
Für die selbstgeschriebenen Funktionen sollte man eine *.h-Datei erstellen, in der man die Funktionen bekannt macht. Die Einbindung dieser Bibliothek erfolgt über
#include "Bibliothek.h"
Durch die Bekanntmachung der Funktionen in Bibliotheken, kann man die Funktion auch aus anderen Programmcodes aufrufen.
Die Funktion wird im Hauptprogramm vor der main-Funktion programmiert. Man muss dabei die benötigten Eingabewert und ihren Datentyp, ebenso wie den Datentyp der Ausgabe definieren. Nach der Definition folgt die Programmierung der Funktion in geschweiften Klammern. Die im Funktionsaufruf definierten Eingabewerte können in der Funktion verwendet werden. Der Ausgabewert muss über return zurückgegeben werden.
DatentypAusgang Funktionsname ( DatentypEingang1 NameEingang1, DatentypEingang2 NameEingang2,...)
{
// Hier steht Ihre Funktion und hier verwenden Sie ihre Eingabeparameter
// Ausgabewert setzen, z.B. in Variable Ergebnis
return Ergebnis
}
Mikrocontroller ATmega32 flashen
Es gibt mehrere Möglichkeiten den Mikrocontroller zu flashen. Dafür muss man beim Aufbau der Schaltung darauf achten, dass eine Schnittstelle zum Flashen an den entsprechenden Pins angeschlossen wird. Für den korrekten Aufbau der Schnittstelle hält man sich am besten an das Datenblatt. In der Software muss man dann in dem Projekt unter Tool wählen, welche Schnittstelle und welches Flash-Gerät vorhanden sind. Zusätzlich muss man dort die Frequenz einstellen. Zwischen den Schnittstellen gibt es dabei Unterschiede. Verwendet man eine ISP-Schnittstelle (=In-System-Programmierung) so kann man das geschriebenen Programm auf den Mikrocontroller flashen, aber nicht debuggen. Bei der Verbindung einer JTAG-Schnittstelle (JTAG = Joint Test Action Group, Name der Gruppe, die das Protokoll entwickelte) kann man dagegen das Programm auf den Mikrocontroller flashen und dann das Programm auf dem Mikrocontroller debuggen.
JTAGICE3 Pin | ISP 10 Pin | Bezeichnung | Bemerkung |
---|---|---|---|
1 | 7 | SCK | |
2 | 4, 6, 8, 10 | GND | |
3 | 9 | MISO | |
4 | 2 | VCC | Extern |
5 | frei | ||
6 | 5 | RESET | |
7 | frei | ||
8 | frei | ||
9 | 1 | MOSI | |
10 | siehe PIN 2 |
Schieberegister
Das Schieberegister besteht intern aus zwei Registern, einem internen Register und einem Ausgangsregister. Um die 8 Ausgangspins des Schieberegisters (QA bis QH zu beschreiben muss man wie folgt vorgehen:
- Auf serielle Eingangsdatenleitung SER Wert anlegen.
- Auf Schiebetakt SCK eine steigende Flanke geben. Dies führt dazu, dass alle Werte des internen Schieberegister um eine Stelle verschoben werden. Der Wert am seriellen Dateneingang wird auf die Stelle 0 des internen Registers verschoben, der Wert der Stelle 1 auf Stelle 2,..., der Wert der Stelle 6 auf Stelle 7 und der Wert der Stelle 7 fällt raus.
- Solange noch nicht alle Stellen beschrieben sind, gehe wieder zu Schritt 1 und setzt nächsten Wert.
- Sind im internen Schieberegister alle Bits nach Wunsch gesetzt, muss man eine steigende Flanke auf den Speichertakt RCK geben. Dies führt dazu, dass die Werte aus dem internen Schieberegister in das Ausgangsregister übertragen werden und somit auf den Ausgängen die Werte anliegen.
Eine detaillierte Beschreibung der Funktionsweise eines Schieberegisters findet man unter auf Mikrocontroller.net [[2]].
C-Programm LED-Würfel
In diesem Kapitel wird das erstellte C-Programm für den Würfel vorgestellt. Der Quellcode wird nicht schrittweise erklärt werden. Die Einzelschritte sind im Quellcode mittels Kommentaren detailliert beschrieben worden. Der gesamte Quellcode wurde im entsprechenden SVN-Projekt-Ordner hinterlegt. Im Folgenden wird grundsätzlich erklärt, welche Aufgabe die Funktion erfüllen soll und wie sie grob funktioniert.
Gewählte Einstellungen ATmega32
Beim Anlegen des Projektes wurde als verwendeter Mikrocontroller der ATmega32 gewählt. Als nächsten Schritt haben wir die Taktfrequenz wie unter Projekt 43: LED-Würfel 2.0#Grundlegende Einstellungen Atmel Studio 6.2 beschreiben, eingefügt. In unserem Fall ist ein externer Quarz mit 14,7456MHz zur Generierung der Taktfrequenz angeschlossen. Der gesamte Programmcode befindet sich in led_cube.c und unsere Funktionen sind in der Bibliothek led_cube.h bekannt gemacht. Im Quellcode led_cube.c haben wir vor Beginn der main-Funktion die Bibliotheken eingebunden, die Konstanten und Variablen definiert und die Funktionen implementiert. Zu den verwendeten Bibliotheken gehören neben der eigenen Bibliothek, die AVR-Studio Basis Bibliothek, die die Nutzung der Bezeichner ermöglicht und die Bibliothek, die die Nutzung der delay-Funktion ermöglicht. Für welche Funktion die Konstanten und Variablen benötigt werden, wird im Quelltext in den Kommentaren erklärt. Die Erklärung der Funktionen folgt in den nächsten Abschnitten.
main-Funktion
Zu Beginn der main-Funktion wird die Einstellung der Pins als Ausgänge, wie in Projekt 43: LED-Würfel 2.0#Die Einstellung der Pins beschrieben, vorgenommen. Für den LED-Würfel müssen alle Pins des Port A, Pin 3 und Pin 4 des Port B, Pin 1 und Pin 2 des Port C und Pin 2 bis Pin 7 von Port D als Ausgang festgelegt werden. An diesen Pins hängen die Schieberegister und die MOSFETS der Ebenen.
Nach der Einstellung muss des Weiteren die UART-Schnittstelle initialisiert werden. Für die Initialisierung gibt es eine spezielle Funktion UART_Init(baud)
die in der main-Funktion aufgerufen wird. Diese Initialisierungsfunktion benötigt als Eingabewert die zu verwendende Baudrate. Welcher Wert dabei einzusetzen ist, kann man im Datenblatt des ATmega32 nachlesen oder selber ausrechnen.
Möchte man den Wert im Datenblatt nachlesen, muss man im Kapitel "USART" unter "Examples of Baud Rate Setting" suchen. Dort findet man eine Tabelle aus der man den Wert ablesen kann, der in die Funktion eingetragen wird. Zuerst muss man die Spalte mit der passenden Taktfrequenz, d.h. Oszillatorfrequenz suchen. In unserem Fall muss man in der Spalte "fOSC=14.7456MHz" schauen. Die Spalte teilt sich nochmals auf in "U2X=0" und "U2X=1". U2X ist die Bezeichnung für ein Bit im Register UCSRA (= UART Control and Status Register A). Ist dieses Bit gesetzt, bedeutet dies, dass die Transferrate verdoppelt ist. In unserem Fall ist U2X gleich 0 gesetzt.
Anschließend kann man die gewünschte Baudrate aus der ersten Spalte wählen. In der Tabelle kann man den Sendefehler bei der Baudrate in der Spalte Error ablesen. Dies kann die Wahl der Baudrate beeinflussen, da man einen möglichst geringen Sendefehler wählen sollte. Der Wert, den man aus der Spalte UBRR ablesen kann, muss man in der Initialisierungsfunktion UART_Init(baud)
als Wert für Baud eintragen. Für den LED-Würfel haben wir eine Übertragungsrate von 9600bps gewählt. Der Error liegt dort bei 0% und in die Funktion wird der Wert 95 eingetragen.
Der Wert kann alternativ auch über die Formel
UBRR = ((Taktfrequenz in Herz)/(Baudrate*16))-0.5
berechnet werden. Der Wert sollte mit dem Wert aus der Tabelle nahezu übereinstimmen. Berechnet man den Wert, so erhält man einen Wert von 95.5 und muss diesen dann auf oder abrunden auf den nächsten ganzzahligen Wert.
Nach der Initialisierung der UART-Schnittstelle werden im main-Programm die Funktionen LEDaus()
und Ebeneaus()
einmalig aufgerufen. Beim Start des Mikrocontrollers werden dadurch alle LEDs am LED-Würfel ausgeschaltet und es sind immer dieselbe Startbedingungen (alles Aus) gegeben.
In der main-Funktion wird als Nächstes eine while-Schleife programmiert. Die while-Schleife ist gleich 1 gesetzt und wird somit niemals beendet, sie wirkt somit als Endlosschleife. Das eigentliche Programm muss nun in der Schleife programmiert werden. In unserem Fall besteht das Programm aus einer if-Bedingung, die abfragt, ob über UART ein Wert empfangen wurde. Ist dies der Fall, wird über die Funktion UART_get()
das empfangene Datenbyte abgeholt und in einer Variable zwischengespeichert. Anschließend erfolgt der Aufruf der Funktion LEDControlStateMachine(Datenbyte)
, welche als Eingabewert das aktuell empfangene Datenbyte erhält.
Mehr Programm enthält die main-Funktion nicht. Alle anderen Funktionen werden über die LEDControlStateMachine
-Funktion aufgrufen.
Funktionen
In diesem Abschnitt wird die Funktionsweise der einzelnen Funktionen beschrieben. Der Quellcode wird dabei nicht schrittweise durchgegangen. Die schrittweise Erklärung des Quellcodes ist direkt im Quellcode durch Kommentare erfolgt. Neben der Erklärung der Funktionen wird auch immer ein Hinweis gegeben, was in Matlab eingegeben werden muss.
Es muss darauf geachtet werden, das man bei den verwendeten Eingabewerten zwischen Zeichen der ASCII-Tabelle, Hexdezimal- und Dezimalzahlen unterscheiden muss. Über Matlab werden die Befehls- und Datenbytes versendet. Die Eingabe in Matlab erfolgt über die Tastatur, d.h. man gibt ein Zeichen ein. Versendet wird die zugehörige Bitfolge. Der versendete Wert und die entsprechende Bitfolge können über die ASCII-Tabelle in Dezimal- oder Hexadezimal-Zahlen umgesetzt werden. Erhält man nun über die UART-Schnittstelle ein Byte, so muss für die Interpretation im C-Programm der Dezimal oder Hexadezimal-Wert verwendet werden. Will man beispielsweise die Funktion Test starten. So gibt man in Matlab ein kleines e ein und versendet dies. Der C-Code empfängt den Dezimalwert 101, bzw. den Hexadezimalwert 65. Die Interpretation des empfangenen Byte, d.h. Funktionsaufruf oder Wert als Datenbyte verwenden, muss auf Grundlage der Dezimal-/Hexadezimalwerte erfolgen.
Funktion "LEDan"
Die Funktion LEDan
erhält als Eingabewerte insgesamt neun Werte und ihr Aufruf sieht wie folgt aus
LEDan(Schieberegister, QA, QB, QC, QD, QE, QF, QG, QH)
Mithilfe dieser Funktion kann man die 64 LEDs einer Ebene, d.h. die 64 LED-Reihen ansteuern. Man muss dafür zunächst bestimmen, welches Register für die 8 anzusteuernden LEDs zu verwenden ist. Für den Eingabewert Schieberegister setzt man in Matlab das ASCII-Zeichen 1 - 8 ein. Das Schieberegister, welches hinter dem Eingabewert 1 steckt, steuert die ersten 8 LEDs an. Durch den Eingabewert 2 werden die LEDs 9 - 16 ansteuert, usw.
Die folgenden 8 Eingabewerte werden über die Funktion LEDan_Matlab
ermittelt. Die Eingabewerte QA - QH stehen für die 8 Ausgänge des Schieberegisters, welche die einzelnen LEDs ansteuern. QA - QH sind entweder 0 oder 1, also AN oder AUS.
In der Funktion LEDan
werden im gewählte Schieberegister die Ausgänge nach entsprechender Auswahl gesetzt.
Beispiel: Es soll die LED 22 und 23 angesteuert werden.
Die LEDs werden durch das dritte Schieberegister angesteuert und Pin 22 ist mit dem Ausgangspin QF, Pin 23 mit QG verbunden. Man kann die Werte einfach direkt in die Funktion eingeben:
LEDan(0x33, 0, 0, 0, 0, 0, 1, 1, 0)
Ausführlicher kann man die Variablen vorher beschreiben und den Funktionsaufruf unverändert lassen.
Schieberegister = 0x33 // entspricht dem ASCII-Zeichen 3
QA = 0;
QB = 0;
QC = 0;
QD = 0;
QE = 0;
QF = 1;
QG = 1;
QH = 0;
LEDan(Schieberegister, QA, QB, QC, QD, QE, QF, QG, QH)
In unserem Fall erfolgt der Aufruf in der Funktion LEDan_Matlab
und dort werden die Eingabewerte gesetzt.
Funktion "LEDan_Matlab"
Über Matlab erhält man zunächst das Byte, welches die Funktion aufruft. Anschließend müssen zwei Byte, das Erste mit der Information welches Schieberegister verwendet werden soll und das Zweite mit der Information welche LEDs angeschaltet werden sollen, gesendet werden. Der Funktionsaufruf sieht dabei wie folgt aus:
LEDan_Matlab (Reg, ledByte)
Den Eingabewert Reg, welcher für das zu wählende Register benötigt wird, gibt man in Matlab durch das ASCII-Zeichen 1 - 8 ein.
Der Eingabewert ledByte wird in der Funktion in die 8 Eingabewerte QA - QH für die Funktion LEDan
umgewandelt. Es wird dabei betrachtet, welche Bits des empfangenen Zeichens gesetzt sind. Ist das nullte Bit gesetzt, so wird QA gleich AN gesetzt. Ansonsten wird QA gleich AUS gesetzt. Dieselbe Bestimmung erfolgt für Bit 1 bis Bit 7. Anschließend wird die Funktion LEDan
durch die Funktion LEDan_Matlab
aufgerufen.
In Matlab muss man das Byte entsprechend zunächst, je nachdem welche LEDs gesetzt werden sollen, berechnen. Anschließend muss man den zu der Bitfolge, bzw. zu dem Dezimal-/Hexadezimalwert, gehörende ASCII-Zeichen versenden.
Matlab muss dementsprechend zuerst das Befehlsbyte zum Aufruf der Funktion senden, anschließend das Datenbyte mit der Information über das Register und abschließend das Datenbyte mit den Informationen welche LEDs angeschaltet werden sollen.
Die Funktion wird über die LEDControlStateMachine
aufgerufen, wenn man über Matlab ein kleines "a" sendet.
Funktion "LEDaus"
Der Funktionsaufruf dieser Funktion benötigt keine Eingabewerte.
LEDaus()
Ruft man diese Funktion auf, so werden alle Ausgänge aller 8 Schieberegister auf 0 gesetzt, d.h. alle LEDs werden ausgeschaltet.
Will man nur einzelne LEDs ausschalten, so muss man dies über die Funktion LEDan
lösen.
Die Funktion wird über die LEDControlStateMachine
aufgerufen, wenn man über Matlab ein kleines "b" sendet.
Funktion "Ebenean"
Der Funktionsaufruf dieser Funktion sieht wie folgt aus:
Ebenean(Ebene)
Die Funktion benötigt einen Eingabewert mit der Information, welche Ebene anschaltet werden soll. Erst wenn diese Funktion aufgerufen, dann ist der Stromkreis geschlossen. Es kann allerdings der Fall sein, dass noch keine LEDs gesetzt wurde. In dem Fall ist noch der Funktionsaufruf der Funktion LEDan_Matlab
notwendig, damit die LEDs leuchten.
In Matlab muss das Datenbyte für den Wert Ebene als ASCII-Zeichen 1 - 8 für die Ebene 1 - 8 versendet werden. Matlab muss zuerst das Befehlsbyte senden und anschließend das Datenbyte.
Die Funktion wird über die LEDControlStateMachine
aufgerufen, wenn man über Matlab ein kleines "c" sendet.
Funktion "Ebeneaus"
Die Funktion benötigt ebenso wie die Funktion LEDaus()
keinen Eingabewert.
Ebeneaus()
Mithilfe dieser Funktion werden alle Ebenen ausgeschaltet.
ACHTUNG:
Bei der Programmierung ist darauf zu achten, dass immer nur eine Ebene leuchten darf. Dies muss beachtet werden, da die maximale Stromaufnahme des LED-Würfels, bei der die Schaltung nicht beschädigt wird, 1,3 A betragen darf. Die maximale Stromaufnahme wird erreicht, wenn alle LEDs der Ebene leuchten. Um der Gefahr der zu hohen Stromaufnahme zu entgehen, sollte man die Ebenen mit einer Frequenz von größer 25Hz an und ausschalten. Ab dieser Frequenz kann das menschliche Auge das Flackern des An- und Ausschaltens nicht mehr erkennen. Es wirkt für das Auge so, als wäre die Ebene, bzw. mehrere Ebenen gleichzeitig an.
Die Funktion wird über die LEDControlStateMachine
aufgerufen, wenn man über Matlab ein kleines "d" sendet.
Funktion "Test"
Ruft man die Funktion Test()
auf, so wird eine Funktion aufgerufen, mit der sich die Funktionsfähigkeit jeder LED überprüfen lässt. In der Funktion werden nacheinander die Ebenen überprüft. Es wird immer eine LED eingeschaltet. Wenn alle 8 LEDs eines Schieberegisters aufgerufen worden sind, dann leuchten nochmals alle 8 LEDs des Schieberegisters auf. Anschließend wird mit dem nächsten Schieberegister fortgefahren. Die Ebenen werden dabei der Reihe nach getestet.
Die Funktion wird über die LEDControlStateMachine
aufgerufen, wenn man über Matlab ein kleines "e" sendet.
Funktion "LEDControlStateMachine"
Der Funktionsaufruf dieser Funktion erfolgt automatisch in der main-Funktion, wenn über die UART-Schnittstelle ein Byte empfangen wurde. Das Byte wird durch die Funktion UART_get
empfangen und in einer Variable zwischengespeichert. Es folgt der Funktionsaufruf
LEDControlStateMachine (controlByte)
.
Bei dem Eingabewert controlByte handelt es sich um das enpfangene Byte. In der Funktion LEDControlStateMachine
wird entschieden, wie das empfangene Byte interpretiert werden soll. Es kann sich um ein Befehlsbyte oder um ein Datenbyte handeln. Im Initialzustand wartet die Funktion auf ein Befehlsbyte. Wird ein Byte von Matlab empfangen, prüft die LEDControlStateMachine
welche der anderen Funktionen aufgerufen werden soll. Benötigt die aufzurufende Funktion noch Eingabedaten, so wechselt der Zustand der LEDControlStateMachine
und sie wartet auf das nächste empfangene Byte. Die Funktion wird dafür verlassen. Wird ein neues Byte empfangen und die Funktion wieder aufgerufen, wird das empfangene Byte als Datenbyte für die aufzurufende Funktion interpretiert. Dies ist der Fall bei den Funktionen LEDan_Matlab
(2 Eingabewerte) und Ebenean
(1 Eingabewert). Sind alle Eingabewerte empfangen worden, so ruft die LEDControlStateMachine
die Funktion mit den Eingabewerten auf und kehrt in den Initialzustand zurück. Bei Funktionen ohne Eingabewert, wird die aufzurufende Funktion direkt aufgerufen und die LEDControlStateMachine
bleibt im Initialzustand und erwartet das nächste Befehlsbyte.
Funktion "UART_init"
Diese Funktion wird einmalig zu Beginn der main-Funktion aufgerufen und richtet die UART-Schnittstelle ein. Der Funktionsaufruf sieht dabei wie folgt aus:
UART_Init (baud)
Wie der einzusetzende Wert baud bestimmt wird, ist unter Projekt 43: LED-Würfel 2.0#main-Funktion beschrieben.
Neben der Baudrate, werden weitere Bits in den speziellen Registern für die UART-Schnittstelle gesetzt. In unserem Fall ist die UART-Schnittstelle wie folgt eingerichtet:
- Senden und Empfangen über RXD und TXD wird aktiviert
- Sendeformat: 8N1 --> 8 Datenbits, kein Parity-Bit und 1 Stop-Bit
Funktionen "UART_get", "UART_gets" & "UART_Transmit"
Die Funktionen stammen aus dem Artikel "AVR-GCC-Tutorial/Der UART" von der Website mikrocontroller.net [[3]].
Die Funktion UART_get()
empfängt ein Byte. Diese Funktion wird aktuell in der main-Funktion verwendet, um das Byte zu empfangen und den Wert anschließend in einer Variable zu speichern.
Die Funktion UART_gets(*Buffer,MaxLen)
kann eine Zeichenkette empfangen. Sie wird aktuell nicht verwendet. Dennoch haben wir sie im Programm behalten, da die Funktion bei der Weiterentwicklung nützlich sein kann.
Über die Funktion UART_Transmit(data)
kann ein Datenbyte verschickt werden. Diese Funktion ist hilfreich, um zu testen, ob die Kommunikation über die UART-Schnittstelle funktioniert.
Matlab-Programm LED-Würfel
In dem Matlab -Programm werden zu Beginn grundsätzlich das Command Window und der Workspace geleert und alle offenen Figuren geschlossen. Anschließend wird die Schnittstelle, über die kommuniziert werden soll eingerichtet. Zunächst muss man dafür feststellen, an welchem RS232-Anschluss (COM) die Kommunikationsleitung angeschlossen ist. Dies kann man am besten über den Gerätemanager feststellen. Sollte man nicht genügend RS232-Anschlüsse besitzen, kann man einen RS232-USB-Converter verwenden. Neben dem Anschluss muss man noch das Sendeformat einstellen. In Matlab müssen somit für die Schnittstelle folgenden Parameter eingestellt werden:
- Anschluss COM
- Baudrate = 9600
- 8 Datenbits
- kein Parity-Bit
- 1 Stop-Bit
Anschließend kann man über den Befehl fopen(Schnittstelle)
die Kommunikation eröffnet werden.
Im weiteren Programm müssen die Muster generiert werden und nach den Vorgaben des C-Programms die Befehls- und Datenbytes übertragen werden.
Aktueller Stand des Projektes
Im Verlauf des Projektes sind einige Probleme aufgetreten. Das Hauptproblem des Projektes ist die Schaltung. Die Schaltung ist durch den direkten Anschluss der Leitungen an die Platine sehr unübersichtlich. Bei der Erstellung der Platine wurde nicht sauber gearbeitet und einige Punkte wurden nicht bedacht. So kann der Mikrocontroller nur über eine ISP-Schnittstelle geflasht werden. Dadurch ist es nicht möglich das Programm auf dem Mikrocontroller zu debuggen. Dies erschwerte die Programmierung sehr, da sich die Fehlersuche dadurch kompliziert gestaltete. Der Mikrocontroller unterstützt aber eine JTAG-Schnittstelle, mittels der man auf dem Mikrocontroller debuggen kann. Bei der ISP-Schnittstelle liegt des Weiteren ein Kurzschluss zwischen der Versorgungsleitung und GND vor. Damit man überhaupt flashen kann, muss man die Versorgungsspannung direkt vom Netzteil abgreifen und am Flasher anlegen. Das wesentliche Problem lag jedoch darin, dass die serielle Kommunikation nicht funktionierte. Da ein Debuggen nicht möglich war, war die Fehlersuche sehr kompliziert und dauerte unnötig lange. Nach langem Suchen fanden wir heraus, dass der Fehler nicht in der Software zu liegen scheint. Wir untersuchten die Schaltung genauer, dabei fiel auf, dass
- ... zwischen Masse und Versorgung ein Kurzschluss vorlag.
- ... falsche Kondensatoren am Quarz verwendet wurden.
- ... der externe Quarz gar nicht schwingt.
Eine serielle Kommunikation ist mit der aktuellen Schaltung nicht möglich. Es gelang uns in der verbleibenden Zeit nicht die Schaltung zu reparieren. Durch die langwierige Fehlersuche und die Reparaturversuche konnte blieb am Ende des Projektes leider keine Zeit mehr für die Generierung der Muster in Matlab.
Aktuell verfügt das Projekt somit über alle benötigten Funktionen in C, um eine Ansteuerung über Matlab zu realisieren.
Ausblick
Wir würden empfehlen die Platine vollständig neu aufzubauen. Hierzu sollten folgende Punkte beachtet werden:
- Pinbelegung im Vorfeld genau überlegen und logisch anlegen
- JTAG-Schnittstelle vorsehen (Flashen mit Debuggen)
- über die Auswahl des Quarzes Gedanken machen
- Anschlusskabel der Ebenen und Reihen über einen Stecker mit der Platine verbinden (ermöglicht Herausnehmen der Platine für Lötarbeiten und verringert das Risiko von Kabelbruch)
Im weiteren Projektverlauf sollte dann wie folgt vorgegangen werden:
- Neuaufbau der Platine
- Test der vorhandenen Software, insbesondere Test der seriellen Kommunikation
- Erstellung einer Matlab-Oberfläche zur Generierung komplexer Muster
Quellen
- Klingen, Martin; Schulz, Juri: LED-CUBE Dokumentation.pdf, 25.01.2013
- Artikel "AVR-Tutorial: Schieberegister" auf mikrocontroller.net, Abruf: 02.02.2015[[4]]
- Artikel "AVR-Tutorial:UART" auf mikrocontroller.net, Abbruf: 02.02.2015 [[5]]
- Artikel "AVR-GCC-Tutorial/Der UART" von der Website mikrocontroller.net, Abruf: 02.02.2015[[6]]
- Horn, Thorsten: ASCII-Tabelle,1998, Aachen, Abruf: 02.02.2015[[7]]
- www.reichelt.de[8]