Donnerstag, 26. Januar 2017

Ein einfaches Thermometer mit PT100



Technische Daten

Betriebsspannung: 5V
Messbereich: -50°C - 100°C
Genauigkeit: ±1K
Maße der Leiterplatte: 25.2mm x 33.5mm
(Alternativ Breadbord)
Projektunterlagen: Github
Dropbox


Einleitung

Ob es warm oder kalt ist, das ist Gefühlssache. Um Temperaturen jedoch konkret zu erfassen, braucht es ein vernünftiges Messinstrument: Das Thermometer. In diesem Artikel erkläre ich den Aufbau und die Funktion eines einfachen elektrischen Thermometers mit einem PT100 Temperatursensor.

Wer nicht so viel lesen und lieber gleich loslegen will, der findet im Abschnitt Technischen Daten einen Link zu den Projektunterlagen. Die Projektunterlagen enthalten Schaltplan, Boardlayout, Breadboardplan und so weiter.

Viel Spaß beim kreativ werden
Hans


Wie arbeitet der Temperatursensor PT100?

Der PT100 ist ein Platinwiderstand, der bei 0°C einen Widerstand von exakt 100Ω besitzt. Sein Widerstand nimmt mit steigender Temperatur zu. Das Verhältnis zwischen Widerstand und Temperatur ist dabei nahezu linear. Daher wird die Kennlinie des PT100 gern mit der folgenden Formel vereinfacht.

RT = R0 • ( 1 + α • T )

RT… Widerstand des PT100 in Abhängigkeit der Temperatur
R0… Widerstand des PT100 bei 0°C (R0 = 100Ω -> konstant)
α… Temperaturkoeffizient des PT100 (α = 3.85 • 10^-3/°C -> konstant)
T… Temperatur in °C

Wie man deutlich in der Formel erkennen kann, ist T, die Temperatur, die einzige Komponente, die sich verändern kann. Dadurch erhält man eine lineare Kennlinie zwischen Temperatur und Widerstand des PT100. Die nachfolgende Grafik zeigt die reale Kennlinie des PT100 gestrichelt und die angenäherte Kennlinie aus der Formel als Vollstrich.


Man kann gut erkennen, dass die Kennlinie im Bereich von -100°C - 200°C fast linear ist, aber spätestens bei 600°C zeigt sich eine deutliche Krümmung. Da wir uns mit unserer Entwicklung in einem Bereich bewegen, in dem die Kennlinie sehr linear verläuft, vernachlässigen wir die Krümmung und arbeiten mit dem idealisierten linearen Modell.


Aufbau des Thermometers

Das Blockschaltbild in Abbildung 4 zeigt schematisch, wie die Temperatur auf der Platine ermittelt und aufbereitet wird. Die Skizze beginnt beim PT100. Mit seiner als linear angenommenen Kennlinie kann er die aktuelle Temperatur detektieren und in eine Widerstandsänderung übertragen. Da durch den PT100 ein Konstantstrom von 1mA fließt, wird seine Widerstandsänderung in eine Spannungsänderung umgesetzt. Allerdings liefert der PT100 mit 100Ω bei 0°C auch einen erheblichen Spannungsoffset, dieser muss später entfernt werden.

An den Klemmen des PT100 sitzt ein Instrumentenverstärker. Dieser stabilisiert die gemessene Spannung und verstärkt sie um den Faktor 10.

Zuletzt wird durch einen Differenzverstärker der bereits erwähnte Spannungsoffset entfernt und das Nutzsignal um den Faktor 8.3 verstärkt. Dadurch ergibt sich eine Kennlinie, die bei einer Temperaturänderung von 150 K einen Spannungsbereich von 0…5V durchläuft.


Schaltplan




Der Schaltplan lässt sich mit dem vorherigen Kapitel Aufbau des Thermometers sehr schnell und einfach verstehen. Im oberen Bereich des Schaltplans befinden sich die drei einzelnen Stufen Konstantstromquelle mit PT100, Instrumentenverstärker und Differenzverstärker. Im unteren Bereich werden zwei Festspannungen eingestellt, welche in der Schaltung als Referenzspannungen benötigt werden.


Symmetrische Spannungsversorgung

Im Schaltplan unten links befindet sich eine Schaltung, welche aus der unsymmetrischen 5V Betriebsspannung eine symmetrische ±2.5V Betriebsspannung erzeugt. Dazu wird mit einem einfachen Spannungsteiler ein künstlicher symmetrischer Nullpunkt bei halber Betriebsspannung definiert. Der dem Spannungsteiler nachgeschaltete OPV ist als Impedanzwandler geschaltet. Seine Aufgabe ist es, den neuen Nullpunkt stabil zuhalten. Die symmetrische Spannungsversorgung ist nötig, um den Instrumentenverstärker zu betreiben und um auf einige OPV Grundschaltungen zurückgreifen zu können. Da symmetrische Spannung und unsymmetrische Spannung direkt übereinander liegen, ist es wichtig die Bezeichnungen beider Netze nicht miteinander zu verwechseln. Die nachfolgende Tabelle zeigt, wie die erzeugte symmetrische Spannung die unsymmetrische Spannung überlagert.


Unsymmetrische Spannung Symmetrisch Spannung
5V +2.5V
2.5V 0V
0V -2.5V



Offsetkorrekturspannung

Die Offsetkorrekturspannung wird auf die gleiche Weise erzeugt, wie der Nullpunkt für die symmetrische Spannungsversorgung. Sie wird benötigt, um den Offset, der durch den Grundwiderstand des PT100 entsteht, zu eliminieren. Mit Potentiometer R12 kann die Offsetkorrekturspannung und damit der Mittelpunkt des Messbereichs eingestellt werden. Wird UREF auf 3.3V eingestellt ergibt sich ein Messbereich von -50°C bis 100°C.


Anschluss des PT100


Der PT100 wird in 4-Leitertechnik angeschlossen, was dafür sorgt, dass man sehr lange Kabel (>10m) verwenden kann, ohne dass das Messergebnis zusätzlich verfälscht wird.


Konstantstromquelle


Um den PT100 zu betreiben wird er von einem Konstantstrom von 1 mA durchflossen. Um diesen Konstantstrom zu erzeugen, wird eine OPV als Konstantstromquelle geschaltet. Die Parallelschaltung der Widerstände R1 und R11 erzeugt einen Gesamtwiderstand von 2.5kΩ. Da sich der OPV an seinem positiven Eingang auf die symmetrische Masse bezieht, fallen an dem Gesamtwiderstand R1||R11 2.5V ab. So wird ein Konstantstrom von 1mA erzeugt. Dieser Strom fließt kontinuierlich durch den PT100.


Instrumentenverstärker

  

Der Konstantstrom erzeugt am PT100 eine temperaturabhängige Spannung. Diese Spannung wird vom Instrumentenverstärker abgegriffen, stabilisiert und um den Faktor 10 verstärkt. Da der Eingangswiderstand des Instrumentenverstärkers extrem hoch ist, belastet er das Sensorsignal des PT100 nicht. Im Moment liegt noch der volle Offset durch den PT100 (100Ω bei 0°C) auf dem Sensorsignal. Dieser muss in der nächsten Stufe entfernt werden, um das Signal anschließend auf volle Betriebsspannung anheben zu können.


Offsetkorrektur


In der letzten Stufe wird der Offset des PT100 korrigiert. Dazu wird ein OPV als Differenzverstärker geschaltet. In dieser Schaltung wird  die Offsetkorrekturspannung UREF vom aufbereiteten Sensorsignal abgezogen. Anschließend wird das Ergebnis mit dem Faktor 8.3 auf Betriebsspannung verstärkt.


Breadbord

 

Hier sieht man die Schaltung auf einem Steckbrett aufgebaut. Es ist zwar einiges an Kabeln zu verlegen, aber der Aufwand hält sich noch in einem erträglichen Rahmen. Auch die Übersicht über die Schaltung bleibt halbwegs erhalten.


Boardlayout



Wer es etwas schicker und professioneller mag, dem kann ich hier ein schönes kleines SMD Layout anbieten. Ich selbst habe die Platine so im Einsatz und bin sehr zufrieden damit. 





Mehr Informationen und Quellen:

Bücher

  • Bernhard, Frank: Handbuch der Technischen Temperaturmessung. 2. Auflage. Springer Verlag, 2014
  • Reinhold, Wolfgang: Elektronische Schaltungstechnik. 1. Auflage. Carl Hanser Verlag, 2010


Online



Sonntag, 26. Juni 2016

4 Gewinnt auf LED-Matrix mit Raspberry Pi


Was ist schöner als Spiele entwickeln?

Im Zuge einer Studienarbeit habe ich mit meinem Freund Christian ein 4-Gewinnt entwickelt. Es läuft auf Raspberry Pi mit einem selbst gebauten Hardwaremodul auf Lochrasterplatine.

Der Raspberry Pi wird mit Raspbian betrieben und der Quellcode ist in Python geschrieben. Auf dem Hardwaremodul sind eine 7x6 LED-Matrix und 3 Taster zum steuern des Spiels aufgebaut. In den folgenden Kapiteln erkläre ich das Projekt etwas genauer.

Falls ihr jedoch einfach nur schnell loslegen wollt:
Schaltplan, Quellcode und die offizielle Doku findet ihr in den Projektdaten bei den folgenden Hostern:

Dropbox                                                          Github

Schreibt in die Kommentare falls ihr Fragen oder Anregungen habt, ich freu mich auf euer Feedback - Nun viel Spaß beim selber machen!

Hans

1. Hardware


1.1 Teile der Platine

Schauen wir erstmal kurz das Hardwaremodul an.


        1. Schieberegister (74HC595)
        2. High-Side-Treiber (UDN2981)
        3. Low-Side-Treiber (ULN2803)
        4. Vorwiderstände der LEDs
        5. Duo-LEDs (grün-rot)
        6. Taster (Left, Enter, Right)
        7. GPIO-Schnittstelle

1.2 LED-Matrix

Die LED-Matrix besteht aus 7x6 Duo-LEDs mit gemeinsamer Kathode. Sie haben die Farben Rot und Grün. Die Matrix wird durch zwei 8-Bit High-Side-Treiber an den 14 Anoden und einem 8-Bit Low-Side-Treiber an den 6 Kathoden mit Strom versorgt. Die Ansteuerung der Matrix übernehmen drei in Serie geschaltete 8-Bit Schieberegister.

Die folgende Abbildung zeigt den Aufbau und die Ansteuerung der LED-Matrix. Dabei beginnt der Datenvektor stets an der oberen rechten Seite der Matrix und zieht sich durch die Spalten von rechts nach links und anschließend durch die Zeilen von oben nach unten bis zum unteren linken Ende der Matrix.



Um für eine richtige Anzeige zu sorgen, muss der Datenvektor korrekt zusammengesetzt sein. Die Vektorpositionen 0, 1, 16, 17 sind nicht beschaltet. Welche Werte hier eingetragen werden ist grundsätzlich irrelevant. Bei den Positionen 2–15 handelt es sich um die Matrix-Spalten. Dabei sprechen die geraden Zahlen die grüne Anode der jeweiligen LED an, während die ungeraden Zahlen die rote Anode der jeweiligen LED ansprechen. Die Positionen 18–23 entsprechen den Zeilen, hier werden die Kathoden der jeweiligen LEDs angesprochen.

Um eine LED in der Matrix anzusteuern, wird sowohl in den Spalten, als auch in den Zeilen mit High-Pegel adressiert. Das bedeutet, wenn man beispielsweise die LED in der 5. Spalte und der 3. Reihe mit grün ansprechen möchte, müssen an den Datenpositionen 6 und 20 High-Pegel anliegen. Alle anderen Datenpositionen müssten Low-Pegel halten. In diesem Fall würde nur die ausgewählte LED grün leuchten und der Rest der Matrix wäre dunkel. (Datenvektor: ← 00010000 00000000 01000000 ←)

Die Schieberegister beziehen ihre Daten hauptsächlich von der Datenleitung SER und den zwei Taktleitungen SCK und RCK. Des Weiteren existieren die VektorlöschenLeitung SCL und die Freigabeleitung G. Diese 5 Datenleitungen sind mit dem Raspberry Pi verbunden und für die Steuerung der LED-Matrix verantwortlich. Weitere Informationen zu den verschiedenen Steuerleitungen sind in Tabelle 1 zusammengefasst.


1.3 Taster

Die Taster sind unterhalb der LED-Matrix angeordnet. Mit ihnen wird das Spiel gesteuert. Dabei gibt es zwei Taster, um den Coin nach rechts(Right) und links(Left) zu bewegen und einen Taster um den Coin fallen zu lassen(Enter). Der Enter-Taster hat eine Zusatzfunktion. Hält man ihn für längere Zeit gedrückt, so wird ein Reset ausgeführt und das Spiel neu gestartet.

Jeder Taster ist durch eine kleine Schaltung Hardware-Entprellt und führt eine eigene Datenleitung zum Raspberry Pi. Allerdings ist in der Software noch ein Algorithmus zum Entprellen der Taster vorhanden. Dies ist vorangegangen Entwicklungsphasen geschuldet und völlig unkritisch. In einer späteren Entwicklungsstufe sollte dieser Programmabschnitt angepasst und optimiert werden.

1.4 GPIO-Schnittstelle

An der GPIO-Schnittstelle werden alle Ein- und Ausgänge sowie die Betriebsspannung der Platine in einem Sockel zusammengefasst. An dieser Stelle muss der Raspberry Pi angeschlossen werden. Tabelle 1 gibt eine detaillierte Übersicht über alle Pins und zeigt, wie das Board mit dem Raspberry Pi zu verbinden ist.

1.5 Schaltplan

 

1.6 Board


2 Software

Die Software zur Ansteuerung des 4-Gewinnt-Spiels wurde für Raspberry Pi auf dem Betriebssystem Raspian geschrieben. Die dazu verwendete Programmiersprache ist Python. Da Python eine Interpretersprache ist, besteht keine Notwendigkeit, den Quellcode zu kompilieren, er wird direkt im Betriebssystem interpretiert.

Die gesamte entwickelte Software des 4-Gewinnt Spiels befindet sich in der Python-Datei VierGewinnt v1.4.py. Nachfolgend werden die einzelnen Komponenten dieser Software und der Ablauf des Hauptprogramms näher beschrieben.

2.1 Softwaremodule

Die Software ist in 3 Abschnitte aufgeteilt. Dabei handelt es sich um die Definition der Variablen, die Definition der Funktionen und den Ablauf des Hauptprogramms. Nachfolgend werden die Definition der Variablen und die Definition der Funktionen näher betrachtet und erläutert.

2.1.1 Definition der Variablen

Die Software beginnt mit der Definition der GPIO-Pins. Dazu wird für jeden Pin eine globale Variable definiert. Die Pin-Variablen enthalten dabei eine Zahl entsprechend des zugewiesenen Pins. Beim Aufrufen von Funktionen mit diesen Variablen wird die enthaltene Zahl verwendet, um auf den entsprechenden GPIO-Pin zu verlinken. Eine genaue Übersicht zu den GPIO-Pin-Variablen liefert Tabelle 2.

Im zweiten Programmschritt werden einige Programm-Variablen definiert. Sie werden vielfältig in den einzelnen Funktionen und im Hauptprogramm verwendet. Tabelle 3 zeigt die Programm-Variablen übersichtlich dargestellt und erklärt.


2.1.2 Definiton der Funktionen

Um ein Programm schlank und übersichtlich zu programmieren, wurden wiederkehrende Programmbestandteile in Funktionen integriert. Nachfolgend werden alle im Programm definierten Funktionen aufgelistet und beschrieben. In Abbildung 6 werden unter den Funktionen bestehende Abhängigkeiten veranschaulicht.




Button(button nr)
Eingabevariable:
button nr . . . kann eine der 3 Button-Variablen enthalten (2/3/4)Beschreibung:
Gibt an, ob ein Taster gedrückt wurde. Welcher Taster geprüft werden soll, wird
durch die Eingabevariable ausgewählt.
Rückgabewert:
0. . . Taster ist nicht gedrückt, 1. . . Taster ist gedrückt
global button state. . . gibt an, ob Taster gedrückt wurde
global button old . . . speichert, welcher Taster gedrückt wurde. Erst wenn dieser los-
gelassen wird, kann er erneut betätigt werden.

Output Enable()
Eingabevariable:

Beschreibung:
Aktiviert die Tri-State-Ausgänge der Schieberegister und erlaubt das Durchschalten
der Speicherregister auf die Ausgänge. Damit können die Daten der Speicherregister
auf der LED-Matrix angezeigt werden. Siehe hierzu auch Anhang D Datenblatt
Schieberegister 74HC595 (Auszug).
Rückgabewert:


Output Disable()
Eingabevariable:

Beschreibung:
Schaltet die Tri-State-Ausgänge der Schieberegister hochohmig. Dadurch können die Speicherregister keinen Wert auf die Ausgänge schreiben.
D Datenblatt Schieberegister 74HC595 (Auszug)
Rückgabewert:


Clear Shift Register()
Eingabevariable:

Beschreibung:
Löscht den gesamten in den Schieberegistern gespeicherten Datenvektor. Der neue
Vektor enthält ausschließlich Nullen.
Rückgabewert:


Set Shift Register(data)
Eingabevariablen:
data. . . zu schreibender LED-Matrix Datenvektor
Beschreibung:
Schiebt einen Datenvektor beliebiger Länge in die Schieberegister.
Rückgabewert:


Set Storage Register()
Eingabevariable:

Beschreibung:
Übergibt den aktuellen Datenvektor der Schieberegister an die Speicherregister.
Dort wird der aktuelle Datenvektor auf die LED-Matrix ausgegeben.
Rückgabewert:


Sample(sample nr)
Eingabevariable:
sample nr . . . wählbarer Standarddatensatz (0. . . 7)
Beschreibung:
Gibt einen Standarddatensatz für die LED-Matrix entsprechend der eingegebenen
Datensatznummer zurück. (Startbildschirm, ’HI’, ’DU’, ’P1’, ’P2’, Unentschieden-
Bildschirm, ’Player 2 Win’, ’4 Gewinnt’)
Rückgabewert:
Datenvektor für LED-Matrix (84 Bit / mehr bei Lauftext - Sample 6 + 7)

Send Data(data)
Eingabevariable:
data. . . Datenvektor für LED-Matrix
Beschreibung:
Schreibt einen Datenvektor auf die LED-Matrix. Der Vektor enthält ein vollständiges
Bild.
Rückgabewert:


Position Check(level)
Eingabevariable:
level . . . zum Prüfen des Bitzustands (0. . . Low, 1. . . High)
global pos. . . aktuelle Position im Matrix-Datenvektor
global player nr . . . zeigt an, welcher Spieler an der Reihe ist (Matrixnavigation)
Beschreibung:
Prüft, ob die LED an der aktuellen Position des Matrix-Datenvektors ein- oder
ausgeschaltet ist. Es wird immer nur rot oder grün eingeschaltet, niemals beide LED-
Farben gemeinsam. Ist eine Farbe eingeschaltet, so gilt die LED als eingeschaltet.
Rückgabewert:
0. . . Bit6 = level, 1. . . Bit=level

Win Check(r)Eingabevariablen:
r . . . Reihe der aktuellen Matrix-Position
global pos. . . aktuelle Position im Matrix-Datenvektor
global data. . . Matrix-Datenvektor
Beschreibung:
Überprüft ausgehend von der übergebenen Position, ob das Spiel gewonnen wurde.
Es wird in alle Richtungen geprüft. (4 Coins in Reihe/Spalte/Diagonal)
Rückgabewert:
0. . . Spiel nicht gewonnen, 1. . . Spiel gewonnen
global win row . . . Vektor mit 4 Daten, gibt die Position des Gewinns an

Win Screen()
Eingabevariable:

Beschreibung:
Zeigt den Gewinn eines Spielers an. Die Anzeige dauert 4s.
Rückgabewert:


Draw Screen()
Eingabevariable:

Beschreibung:
Zeigt an, dass das Spiel unentschieden ausgegangen ist. Die Anzeige dauert 4s.
Rückgabewert:



2.2 Programmablauf

An dieser Stelle wird der Ablauf des Hauptprogramms beschrieben. Um die Übersichtlichkeit zu wahren, wird der Programmablauf in kleinen Absätzen nachvollzogen.

Definiton der Variablen

Das Programm beginnt mit der Definition der Variablen. Dabei wird zwischen GPIO-Variablen und Programm-Variablen unterschieden. Die GPIO-Variablen werden verwendet, um den verschiedenen Signalleitungen je einen GPIO zuzuordnen. Tabelle 2 zeigt eine detaillierte Zuordnung der einzelnen GPIO-Pins. Die Programm-Variablen werden im Hauptprogramm und den Funktionen verwendet. Eine detaillierte Zuordnung zeigt Tabelle 3.

Definiton der Funktionen

Nach den Variablen werden die Funktionen definiert. Dazu ist jede für das Programm geschriebene Funktion mit ihrem jeweiligen Quellcode nacheinander angeordnet. Um dem Interpreter deutlich zu machen, dass es sich um eine Definition handelt, bekommt jede Funktion das Präfix def.

Interrupt Event: Reset()

Die Funktion Reset() wird in einem parallelen Prozess geladen. Sie prüft, ob der Spieler einen Abbruchwunsch äußert. Auf diese Weise kann das Spiel jederzeit neu gestartet werden.

Begrüßung der Spieler

Zur Begrüßung der Spieler wird ein Lauftext "4 Gewinnt" auf der LED-Matrix ausgegeben.

Hauptschleife und Initialisierung

An dieser Stelle beginnt die Hauptschleife des Programms. Während der Initialisierung werden die Grundeinstellungen zum Starten des Spiels getroffen. Dabei wird das Reset-Flag gelöscht, die Grundposition der Matrix eingestellt, Spieler 1 als aktiv gewählt, der Tri-State-Ausgang der Schieberegister aktiviert und der aktuelle Datenvektor in den Schieberegistern gelöscht und an die Ausgänge übernommen.

Spielschleife

Die Spielschleife wiederholt sich so lang, bis das Reset-Flag gesetzt wird. Dies kann durch den parallelen Prozess Reset() oder durch das Ende des Spiels geschehen. Das Spiel wird beendet, wenn ein Spieler gewonnen hat oder keine Züge mehr möglich sind, weil die Matrix zu 100% gefüllt ist.

In der Spielschleife laufen immer die folgenden Schritte nacheinander ab: Sende Daten an LED-Matrix, prüfe Left-Taster, prüfe Enter-Taster, prüfe Right-Taster. Je nachdem, ob und, wenn ja, welcher Taster betätigt wurde, arbeitet die Spielschleife eine andere Aktion ab.

Left-Taster

Der Coin wird auf der LED-Matrix um eine Position weiter nach links verschoben. Sollte der Rand der LED-Matrix erreicht worden sein, so verharrt der Coin auf seiner aktuellen Position am linken Rand der Matrix.

Enter-Taster

Der Coin wird in der aktuellen Spalte fallen gelassen. Er gleitet bis zur untersten noch von keinem Coin besetzten Stelle und verharrt an dieser. Anschließend wird überprüft, ob durch den Wurf ein Gewinn erzielt wurde. Ist das der Fall, wird eine Gewinnmeldung ausgegeben und das Spiel beendet. Falls kein Gewinn festgestellt wurde, wird nun überprüft, ob noch gültige Züge vorgenommen werden können. Sollte die LED-Matrix bereits vollständig ausgefüllt sein, ist dies nicht mehr möglich und ein Unentschiedenbildschirm wird ausgegeben und das Spiel beendet. Falls noch weitere gültige Spielzüge möglich sind, wird der Spieler gewechselt und regulär in die Spielschleife zurück gesprungen.

Right-Taster

Der Coin wird auf der LED-Matrix um eine Position weiter nach rechts verschoben. Sollte der Rand der LED-Matrix erreicht worden sein, so verharrt der Coin auf seiner aktuellen Position am rechten Rand der Matrix.


3. Diskussion


3.1 Bekannte Probleme und Fehler


Flackerndes Display

Die LED-Matrix kann gelegentlich etwas flackern. Das liegt daran, dass die LED-Matrix vom Hauptprogramm beschrieben wird. Da je nach gewählter Aktion ein kürzeres oder längeres Hauptprogramm ausgeführt wird, ist kein gleichmäßiges Beschreiben der LED-Matrix möglich. Dieser Effekt ist jedoch sehr gering und fällt kaum ins Gewicht.


3.2 Ausblick


Parallele Prozesse und Interrupts

In der aktuellen Entwicklung könnten viele Funktionen des Hauptprogramms in Interrupts oder parallele Prozesse ausgelagert werden. So könnte beispielsweise das Beschreiben des Displays wesentlich gleichmäßiger ablaufen, wenn es in einen parallelen Prozessausgelagert wird. Auch das Abfragen der Taster könnte durch die Verwendung von Interrupts effizienter gestaltet werden.

Computergegner

Eine schöne Erweiterung des Projekts wäre ein optionaler Computergegner. So könnte man das Spiel auch allein spielen. Des weiteren wäre auch das Implementieren eines Demonstrationsmodus interessant. Dabei können zwei Computergegner in immer neuen Variationen gegeneinander spielen.

Integration weiterer Spiele

Für spätere Entwicklungen ist es vorstellbar, weitere Spiele auf der bereits vorhandenen Hardware zu programmieren. Gut geeignete Spiele wären beispielsweise Varianten von Tetris, Pong oder Snake.

Mittwoch, 23. März 2016

Entwicklungsumgebung: Eclipse für STM32 unter Ubuntu



Bild EvalBoard
Evaluation Board: STM32-P152
Nachfolgend wird erläutert, wie eine freie Programmierumgebung für STM32 unter Ubuntu eingerichtet werden kann. In diesem Beispiel baut die Entwicklungsumgebung auf Eclipse mit diversen Erweiterungen auf.
In diesem Tutorial beziehen ich mich auf das Olimex STM32-P152 Evaluation-Board, welches einen STM32L152VBT6 Mikrocontroller enthält. An einigen Stellen gibt es allerdings auch Verweise für die Familien F0, F1, F2, F3 und F4.

1. Verwendete Komponenten

  •  Evaluation Board: Olimex STM32-P152
  • JTAG-Debugger: Olimex ARM-USB-TINY-H

2. Verwendete Programme

  • Ubuntu 14.10
  • Eclipse Kepler 4.3 (Service Release 2)
  • OpenOCD 0.9.0
  • ARM GCC Toolchain 5.0
  • ARM GCC Plugin 2.8.1 (Eclipse Plugin)
  • Zylin 4.16 (Eclipse Plugin)

3. Vorgehensweise

  1. installiere „OpenOCD“
  2. installiere „GCC ARM Embedded Toolchain”
  3. installiere Eclipse für C/C++ (Kepler)
  4. Eclipse add-ons hinzufügen
  5. ein neues Projekt in Eclipse beginnen
  6. Einrichten von OpenOCD in Eclipse
  7. Einrichten des Debuggers in Eclipse

4. Installiere OpenOCD

OpenOCD steht für Open On-Chip Debugger. Dieses Tool stellt die Verbindung zwischen Board, Debugger und PC her.

Installation

Terminal: ~$ sudo apt-get install openocd

Mehr Informationen

http://openocd.org/



Bild JTAG-Debugger
JTAG-Debugger: ARM-USB-TINY-H

5. Installiere GCC ARM Embedded Toolchain

Die GCC ARM Toolchain wird benötigt, um den C-Quellcode in maschinenlesbaren Code zu übersetzen. Sie übernimmt in Eclipse das Builden und einen Teil des Debuggens.

Installation

Terminal:
~$ sudo apt-get install dh-autoreconf libusb-1.0-0-dev libftdi-dev
~$ sudo add-apt-repository ppa:terry.guo/gcc-arm-embedded
~$ sudo apt-get update
~$ sudo apt-get install gcc-arm-none-eabi



Mehr Informationen

https://launchpad.net/~terry.guo/+archive/ubuntu/gcc-arm-embedded
http://wiki.ubuntuusers.de/Archiv/GNU_ARM-Toolchain
http://fab.cba.mit.edu/classes/4.140/tutorials/EmbeddedProgramming/stm32.html


Logo Eclipse

6. Installiere Eclipse für C/C++

Eclipse wird von uns als Entwicklungsumgebung für C/C++ verwendet. Eine Entwicklungsumgebung ist ein Programm, in dem der Quellcode geschrieben, gebuildet und debuggt wird. Es ist damit die Hauptoberfläche mit der sich ein Programmierer beschäftigt.

Automatische Installation

Terminal: ~$ sudo apt-get install eclipse

Falls keine aktuelle Version von Eclipse installiert werden sollte, (Eclipse 4.3 Kepler oder höher) muss Eclipse manuell installiert werden.

Manuelle Installation

  • gehe auf die Eclipse Homepage: www.eclipse.de
  • lade Eclipse Kepler oder eine höhere Version für Linux herunter (achte dabei auf 32 Bit / 64 Bit)
  • installiere ROOT-Befehl für graphische Anwendungen:
    ~$ sudo apt-get install gksu
  • starte Nautilus mit ROOT-Rechten:
    ~$ gksudo nautilus
  • navigiere zum Verzeichnis /opt/
  • Extrahieren des Eclipse-Archivs hier in einen Ordner (eine eindeutige Namenswahl ist immer gut, z.B. eclipse_kepler)
  • Nach dem Entpacken muss der Datenpfad, in dem Eclipse abgelegt wurde, für den Benutzer freigegeben werden.
  • Im folgenden Terminal-Befehl muss $USER durch den Benutzernamen des Kontos ersetzt werden, welcher für die Verwendung von Eclipse freigegeben werden soll (z.B. jochen). Der Ordner „eclipse_kepler“ muss durch den gerade erstellten Ordnernamen ersetzt werden.
    ~$ sudo chown -R $USER:$USER /opt/eclipse_kepler

Mehr Informationen

https://eclipse.org/
http://wiki.ubuntuusers.de/eclipse
http://ubuntuhandbook.org/index.php/2014/06/install-latest-eclipse-ubuntu-14-04/
https://wiki.ubuntuusers.de/chown/


7. Eclipse Plugins

Um Eclipse für die geplante Aufgabe tauglich zu machen, ist es notwendig einige Plugins zu installieren. Plugins können meistens auf mehreren Wegen installiert werden. In diesem Dokument wurde versucht, die jeweils einfachste und schnellste Variante zu wählen.



7.1. CDT

Zu Beginn erweitert man Eclipse um die Plugins „CDT“ (C/C++ Development Tools) und „G++“ (GNU-C/C++ Compiler). Dabei handelt es sich um die C/C++Software Development-Funktion und einen C/C++ Compiler von GNU. Diese Plugins machen ein Programmieren in C/C++ möglich.

Installation

Terminal: ~$ sudo apt-get install eclipse eclipse-cdt g++

Mehr Informationen

https://eclipse.org/cdt/
https://de.wikipedia.org/wiki/GNU_Compiler_Collection

7.2. GNU ARM Eclipse Plugins

Das „GNU ARM Eclipse Plugin“ erweitert Eclipse um einige Bibliotheken und bietet für die STM32-Familien F0xx, F10x, F2xx, F3xx und F4xx vorgefertigte Template-Projekte an. Des Weiteren werden für diese Familien auch die Standard Peripherie Bibliotheken geladen. Die von mir Verwendete Familie L1 gibt es leider nicht in den fertigen Templates, für sie werden auch keine Standard Peripherie Bibliotheken geladen. Diese Templates und Bibliotheken müssen selbst geschrieben (bzw. als fertiges Template von dieser Seite eingebunden) werden.

Installation aus dem Internet

  • starte Eclipse ⇒ Menüleiste > Help > Install New Software ...
  • Work with: klicke „Add...“
    • Name: GNU ARM Eclipse Plug-ins
    • Location: http://gnuarmeclipse.sourceforge.net/updates
  • setze einen Haken bei „GNU ARM C/C++ Cross Development Tools“
  • klicke 2x Next, bestätige die Lizenzvereinbarung und beende die Installation mit einem Klick auf Finish

Mehr Informationen

http://gnuarmeclipse.livius.net/blog/plugins-install/
http://sourceforge.net/projects/gnuarmeclipse/
http://community.arm.com/groups/tools/blog/2014/07/17/gnu-arm-eclipse-open-source-tools-with-experimental-cmsis-pack-support



http://opensource.zylin.com/embeddedcdt.html

7.3. Zylin

Das Zylin-Plugin ist ein GDB-Server. Es ist dafür verantwortlich, dass das Debuggen auf dem Entwicklungsboard vonstattengehen kann. Dazu verwendet es teile der GCC ARM Toolchain und OpenOCD.

Installation

  • starte Eclipse ⇒ Menüleiste > Help > Install New Software ...
  • work with: klicke „Add...“
    • Name: (leer lassen)
    • Location: http://opensource.zylin.com/zylincdt
  • setze einen Haken bei „Zylin Embedded CDT“
  • klicke 2x Next, bestätige die Lizenzvereinbarung und beende die Installation mit einem Klick auf Finish

Mehr Informationen

http://opensource.zylin.com/embeddedcdt.html
http://vedder.se/2012/12/debugging-the-stm32f4-using-openocd-gdb-and-eclipse/
http://repo.or.cz/w/zylincdt.git


8. Ein neues Projekt beginnen

Nachdem wir nun viele Programme und Programmbestandteile installiert haben, bekommen wir erstmals das eigentliche C-Projekt zu Gesicht. Für das Erstellen eines neuen Projekts gibt es je nach Mikrocontroller-Familie verschiedene Möglichkeiten. Hier wird eine Möglichkeit für die Familie L1 und eine zweite Möglichkeit für die Familien F0, F1,F2, F3 und F4 vorgestellt.




8.1. STM32-Familie L1

  • zuerst muss das folgende STM32L1-Template herunter geladen werden
    https://www.dropbox.com/s/1l40vgzjdt5i876/TempEclipseSTM32L1-MH.zip?dl=0
  • kopiere das Template an einen beliebigen Ort (z.B. ~/Schreibtisch/)
  • öffne Eclipse ⇒ Menüleiste > File > Import...
  • wähle: General > Existing Projects into Workspace, klicke Next
  • navigiere zum Template und klick anschließend Finish:
    • Select arcive file: (Ort des Templates, z.B. /home/(benutzer)/Schreibtisch/TempEclipseSTM32L1-MH-LaBP.zip)
    • Projects: ✔ TempEclipseSTM32L1-MH (TempEclipseSTM32L1-MH)

Nun wird das Projekt noch umbenannt und der Postprocessor des Builders an den neuen Namen angepasst:

  • Menüleiste >File >Rename...
  • wähle den Namen für den Projekt und Klicke OK
  • jetzt muss der Postprocessor an den neuen Namen angepasst werden
  • Menüleiste >Project >Properties
  • Navigiere zu: C/C++ Build >Settings
  • wähle den Tab „Build Steps“
  • ändere im Abschnitt „Post-build steps“ die Zeile „Command:“, der alte Projektname muss durch den neu gewählten ersetzt werden, Klicke Apply und anschließend OK
    • Alt: arm-none-eabi-objcopy -S -O binary TempEclipseSTM32L1-MH-LaBP.elf TempEclipseSTM32L1-MH-LaBP.bin
    • Neu: arm-none-eabi-objcopy -S -O binary (Projektname).elf (Projektname).bin




8.2. STM32-Familie F0, F1, F2, F3 und F4

  • öffne Eclipse ⇒ Menüleiste > File > New > C Project und klick Next
  • benenne dein Projekt und benutze „Cross ARM GCC“ als Toolchain, klick Next
    • Project name: (Der Name deines Projektes)
    • Project type: (je nach Chip)
      • STM32F0xx C/C++ Project
      • STM32F1xx C/C++ Project
      • STM32F2xx C/C++ Project
      • STM32F3xx C/C++ Project
      • STM32F4xx C/C++ Project
    • Toolchain: Cross ARM GCC
  • Nun werden die Target processor settings eingestellt, diese Daten müssen mit den Daten des Boards und des Mikrocontrollers abgeglichen werden. Eclipse trifft zwar meist die richtigen Einstellungen automatisch, darauf sollte man sich jedoch nicht verlassen.
    • Processor core: (Datenblatt Chip)
    • Flash size (kB): (Datenblatt Chip)
    • RAM size (kB): (Datenblatt Chip)
    • clock(Hz): (Datenblatt Board)
    • content: Blinky (blink a led)
    • use system calls: Freestanding (no POSIX system calls)
    • trace output: Semihosting DEBUG channel
    • enable Boxes: ✔Check some warnings, ✔Use newlib nano
  • Als nächstes wird die Ordnerstruktur festgelegt
    • include folder: inc
    • source folder: src
    • system folder: system
    • CMSIS library folder: cmsis
    • C library folder: newlib
    • linker script folder: ldscripts
    • vendor CMSIS name: DEVICE
  • bei Set Configurations wird ✔Debug und ✔Relase ausgewählt, klick Next
  • wähle die vorher installierte GNU ARM Toolchain, klick Finish
    • toolchain name: GNU Tools for ARM Embedded Processors (arm-none-eabi-gcc)
    • toolchain path: (Der Pfad zu den Ausführbaren Dateien der Toolchain, er sollte in folgendem Verzeichnis zu finden sein: /usr/bin/arm-none-eabi-gcc)


9. Einrichten von OpenOCD in Eclipse

OpenOCD steht für „Open On Chip Debugger“ und ist für die Verbindung zwischen Mikrocontroller, JTAG-Debugger und PC verantwortlich. Um dieser Aufgabe nachzugehen muss das Programm auf die vom Nutzer verwendeten Hardware eingestellt werden.

  • lade die Config-Datei des Boards vom Hersteller runter (stm32l.cfg)
  • kopiere die Datei ins Verzeichnis: /usr/share/openocd/scripts/target/
  • falls die Datei schon vorhanden ist, wird die alte Datei ersetzt
  • öffne Eclipse und navigiere dich zu
    Menüleiste > Run > External Tools > External Tools Configuration
  • Rechtsklick auf Programm > New
  • gehe auf den neu entstandenen Unterpunkt und gib ihm einen aussagekräftigen Namen (z.B. connect-ARM-USB-TINY-H)
  • Einstellungen für den Main-Tab:
    • Location: /usr/bin/openocd
    • Working Directory: ${workspace_loc}
    • Arguments:
      -f /usr/share/openocd/scripts/interface/ftdi/olimex-arm-usb-tiny-h.cfg -f /usr/share/openocd/scripts/target/stm32l.cfg -00
      • In Arguments gibt es keinen Zeilenumbruch!
      • Achte darauf, dass die Dateien in Location und Arguments auch wirklich da sind, die Pfade müssen ggf. an die vorgenommene Installation angepasst werden!
  • Einstellung für den Common-Tab:
    • save as: Local file
    • Display in Favorites menu: ✔External Tools
    • Die Restlichen Einstellungen können in Standardposition bleiben
  • Einstellung der anderen Tabs ist nicht nötig, klick Apply und danach Close
  • Im Favoriten-Menü (Button-Leiste) gibt es einen Button für die External Tools, in seiner Auswahl ist jetzt das von uns definierte OpenOCD-Makro „connect-ARM-USB-TINY-H“ enthalten.
  • Mit einem Klick darauf kann nun die Verbindung zum Board per OpenOCD hergestellt werden. Die Console sollte folgende Meldung ausgeben:
Open On-Chip Debugger 0.8.0 (2014-05-10-23:20)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.sourceforge.net/doc/doxygen/bugs.html
/usr/bin/openocd: invalid option -- ’0’
/usr/bin/openocd: invalid option -- ’0’
Info : only one transport option; autoselect ’jtag’
adapter speed: 100 kHz
adapter_nsrst_delay: 100
jtag_ntrst_delay: 100
cortex_m reset_config sysresetreq
Info : clock speed 100 kHz
Info : JTAG tap: stm32l.cpu tap/device found: 0x4ba00477
(mfg: 0x23b, part: 0xba00, ver: 0x4)
Info : JTAG tap: stm32l.bs tap/device found: 0x06416041
(mfg: 0x020, part: 0x6416, ver: 0x0)
Info : stm32l.cpu: hardware has 6 breakpoints, 4 watchpoints
  • Während einer Eclipsesitzung brauch die Verbindung per OpenOCD nur ein Mal hergestellt werden, sie bleibt erhalten, bis man sie manuell trennt


10. Einrichten des Debuggers in Eclipse

  • öffne Eclipse und navigiere dich zu:
    Menüleiste > Run > Debug Configurations...
  • Rechtsklick auf Zylin Embedded debug(Nativ) > New
  • gehe auf den neu entstandenen Punkt und gib ihm einen aussagekräftigen Namen z.B. (Projekt)-Debug-Zylin
  • Einstellungen im Main-Tab
    • Project (optional): (Projektname, z.B. HelloWorld)
    • C/C++Application: Debug/(Projektbinary, z.B. HelloWorld.elf)
  • Einstellungen im Debugger-Tab
    • Debugger: Embedded GDB
    • ✔Stop on startup at: main
    • GDB debugger: arm-elf-gdb
    • GDB command file: .gdbinit
    • GDB command set: Standard
    • Protocol: mi
  • Einstellungen im Commands-Tab
    • ’Initialize’ commands:

      01 target remote localhost:3333

      02 monitor reset

      03 monitor halt

      04 monitor flash protect 0 0 11 off

      05 monitor flash write_image erase /home/benutzer/Dokumente
      /Eclipse/Workspace/(Dein Projekt)/Debug/(Binary 06 Name (z.B. Projekt.bin)) 0x08000000
      07 disconnect

      08 target remote localhost:3333

      09 monitor reset

      10 monitor halt
      • Der Pfad in Zeile 5 muss angepasst werden und zum Projekt-Binary (z.B. HelloWorld.bin) führen
    • ’Run’ commands: (leer)
  • Einstellungen im Common-Tab
    • ✘Local file
    • Display in favorites menu: ✔Debug
  • Einstellung der anderen Tabs ist nicht nötig, klick Apply und danach Close
  • Im Favoriten-Menü (Button-Leiste) gibt es einen Button für Debug, er kann nun jeder Zeit verwendet werden um das Projekt zu debuggen.
    • vor dem Debuggen (!) ist es wichtig ein OpenOCD-Verbindung herzustellen


11. Sie haben Ihr Ziel erreicht!

Wenn alle vorangegangenen Schritte richtig ausgeführt worden sind, sollte es jetzt möglich sein, das Projekt fehlerfrei zu builden und zu debuggen. Dabei ist der Ablauf immer wie folgt:
  • Code schreiben (.c und .h Dateien)
  • builden (Menü-Button „Hammer“)
  • mit OpenOCD die Verbindung zum Board herstellen (Menü-Button „Koffer“)
  • mit Zylin debuggen (Menü-Button „Käfer“)
In der von ST bereitgestellten STM32L1xx_StdPeriph_Lib gibt es viele nützliche Programmierbeispiele, die einem das Arbeiten wesentlich leichter machen. Ein Streifzug durch die unter dem nachfolgenden Link geführte Bibliothek ist daher sehr zu empfehlen.

http://www.st.com/web/catalog/tools/FM147/CL1794/SC961/SS1743/LN1939/PF257913

Herzlichen Glückwunsch zur eingerichteten Entwicklungsumgebung und viel Spaß beim Programmieren!


12. Anmerkungen

Das Tutorial wurde verschiedenen Quellen entnommen und komprimiert aufgearbeitet.

Buch

Ralf Jesse, ARM Cortex-M3 Mikrocontroller, mitp Verlag München

Online

https://balau82.wordpress.com/2014/02/23/stm32-p152-development-with-eclipse-on-linux/
http://vedder.se/2012/12/debugging-the-stm32f4-using-openocd-gdb-and-eclipse/
http://nyatekniken.blogspot.de/2012/09/setting-up-olimex-arm-usb-tiny-h-with.html
http://elk.informatik.fh-augsburg.de/pub/stm32lab/Hauffe-Fischer-Eclipse/bericht.html

Mittwoch, 16. März 2016

Wecker Projekt mit MSP430

Heute stelle ich ein Projekt zur Realisierung eines Weckers mit MSP430 vor. Dieses Projekt wurde von meinem Freund Christian und mir während des 4. Semesters im Fach Mikrorechnerarchitekturen" bearbeitet. Dazu wird ein Evaluation Board, welches zum Buch "Mikrocontrollertechnik" von M.Sturm, angeboten wird verwendet.

Buch und Board können unter der folgenden Adresse erworben werden:
http://www.msp430-buch.de/


Das Evaluation Board:


Eingabe
4x Taster
1x Potentiometer
1x Inkrementaldrehgeber

Ausgabe
8x LED
4x4 LED-Matrix an I2C
2 Zeiliges LC-Display




Anforderungen an den Wecker

  • Weckuhr mit Anzeige der Uhrzeit, Datum, Wochentag und Alarmzeit über das LC Display
  • Eingabe und Justage von Uhrzeit, Datum, und Alarmzeit per Inkrementaldrehgeber
  • Der Wochentag ist automatisch für das jeweilige Datum zu berechnen
  • Akustischer Weckalarm bestehend aus unterschiedlichen Tönen
  • Nutzung der 4x4 LED Matrix zur Anzeige des Alarmzustandes (An / Aus / Aktiv)

Lösung

Den Programmcode, die Dokumentation des Codes und eine  Bedienungsanleitung für den Wecker findet ihr unter folgendem Link in einem RAR-Archiv.

https://www.dropbox.com/s/gir0w7qerdjssqx/WeckerMitMSP430.rar?dl=0




Viel Spaß beim ansehen, ausprobieren und inspirieren lassen!

Samstag, 5. September 2015

Lichtorgel - SumoLight


Es werde Licht!

Für eine Waldparty brauchten wir noch ein bisschen Licht. Daher habe ich eine Lichtorgel mit 6 Kanälen entwickelt. Besonders beachtenswert ist, dass an jedem Kanal bis zu 5A Leistung entnommen werden kann. Das sind 1100 Watt oder 11 super helle Glühbirnen an einem Kanal!

Es gibt zwar noch einiges zu verbessern, aber für einen ersten Prototypen haben wir hier ein echt fettes Teil.


Funktionen

  • Mikrocontroller: PIC16F84A
  • Programmiersprache: Assembler-Programmcode (ohne Interrupts)
  • Eingabe: 
    • Taster 1 -> Programmauswahl (10 Programme)
    • Taster 2 -> Geschwindigkeitsauswahl (4 Stufen)
  • Ausgabe: 
    • 6 Outputs
      • 6 Solid-State-Relais an 230VAC
      • 6 Kontroll-LEDs auf dem Bedienpanel
  • Leistung: 
    • max. 5A pro Kanal
    • max. 16A alle Kanäle zusammen


Schaltplan

 


Leiterplattenlayout


Ein Blick unter die Motorhaube

Wichtig!!

Die Solid-State-Relais vertragen laut Hersteller keine induktiven und kapazitiven Lasten.

Das bedeutet, es ist sinnvoll nur Glühbirnen dran zu hängen. Ich hab zwar auch schon LEDs (Netzteil) und Halogenleuchten daran betrieben, aber wegen den hohen Spannungsspitzen beim ausschalten einer induktiven Last, sollte man sowas nicht übertreiben, sonst ist so ein Solid-State-Relais schnell hinüber... ;-)

Technische Daten

Funktion: Lichtorgel
Kanäle (Outputs): 6
Programme: 10
Geschwindigkeiten: 4
Versorgungsspannung: 230V
Leistung: max. 3,5 KW


Verbesserungen

Problem

Die Lichtorgel läuft im Moment noch autark und vollig ohne Kopplung an die Musik. Leider wird man verrückt wenn sechs Lichter unabhängig von der Musik blinken. Daher soll sich das ändern.

Lösung

Sinnvoll wäre das einbauen eines Basstrigger oder Geschwindigkeitseinstellung mit Poti


Problem:

Die angeschlossenen Lichter steuern beim Einschalten immer voll durch. Der Scheinwerfer geht also nicht langsam an, sondern knallt einem sofort ins Gesicht. Dafür wäre eine geschmeidigere Lösung angebracht.

Lösung:

Wahrscheinlich muss man für diesen Wunsch das Konzept mit den Solid-State-Relais grundsätzlich überdenken...


Problem:

Die Steuerung ist sehr mühselig und wenig komfortabel, mehr Bedienelemente und ein besseres Programmfeedback wären sehr wünschenswert.

Lösung:

Der Programmcode muss überarbeitet werden. Dabei sollten Interrupts eingebunden und Kontroll sowie Bedienelemente erweitert werden.


Anhang 


Downloads

AB SumoLight v1.0 - Stückliste.zip
AB SumoLight v1.0 - Programmcode.zip