Entdecken Sie eBooks
Kategorien
Entdecken Sie Hörbücher
Kategorien
Entdecken Sie Zeitschriften
Kategorien
Entdecken Sie Dokumente
Kategorien
zum Thema
Bastian Holtermann
geboren am 29.09.1979
(Matr.- Nr.: 7051425)
Betreuung: Prof. Dr. Engels
Dortmund, 27. Mrz 2008
Markenrechtlicher Hinweis
Die in dieser Arbeit wiedergegebenen Gebrauchsnamen, Handelsnamen, Warenzeichen usw. knnen auch ohne besondere Kennzeichnung geschtzte
Marken sein und als solche den gesetzlichen Bestimmungen unterliegen.
Smtliche in dieser Arbeit abgedruckten Bildschirmabzge unterliegen
dem Urheberrecht () des jeweiligen Herstellers.
Das Wort Brockhaus ist fr den Verlag Bibliographisches Institut & F.A.
Brockhaus AG als Marke geschtzt.
Atmel ist eine eingetragene Marke der Atmel Corporation
II
Kurzfassung
In dieser Diplomarbeit wird das Modular-EEG-Gert aus dem OpenEEGProjekt von 6 auf 16 Kanle erweitert. Diese Erweiterung wird durch die
Verwendung eines ATmega1280 Mikrocontrollers mglich. Die ntigen nderungen werden in dieser Arbeit beschrieben. Dazu zhlen die nderungen
des Schaltplans, des Platinenlayouts und der Firmware.
III
Abstract
In this diploma thesis the Modular-EEG device from the OpenEEG project
will be expanded from 6 channel to 16 channel support. This is possible by
using an ATmega1280 microcontroller. The changes made to the schematic
diagram, the board layout and the firmware will be described in this work.
IV
Inhaltsverzeichnis
1. Einleitung
4
5
6
2.1. Machbarkeitsstudie . . . . . . . . . . . . . . . . . . .
2.1.1. Einfhrung in die Timing-Problematik . . . . .
2.1.2. Berechnung des Timings mit 6 Kanlen . . . .
2.1.3. Berechnung des Timings mit 16 Kanlen . . .
2.1.4. Lsungsmglichkeiten fr das Timing-Problem
2.1.5. Berechnung eines realisierbaren Timings . . .
2.2. Analyse der Firmware fr den ATmega8 . . . . . . . .
2.2.1. Programmiersprache C . . . . . . . . . . . . .
2.2.2. Verwendete Anweisungen . . . . . . . . . . .
2.2.3. Analyse . . . . . . . . . . . . . . . . . . . . .
2.3. Schaltplannderungen . . . . . . . . . . . . . . . . . .
2.4. Platinenlayout . . . . . . . . . . . . . . . . . . . . . .
2.5. Bauteile . . . . . . . . . . . . . . . . . . . . . . . . .
2.6. Firmware . . . . . . . . . . . . . . . . . . . . . . . .
2.6.1. Firmware fr 6-Kanal-EEG mit ATmega1280 .
2.6.2. Firmware fr 16-Kanal-EEG mit ATmega1280
2.7. Software . . . . . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
6
7
8
12
13
14
17
18
18
21
35
37
40
45
45
60
68
2.8. Tests . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3. Abschluss
3.1. Fazit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
3.2. Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . .
70
74
74
74
Literaturverzeichnis
76
79
88
99
Abbildungsverzeichnis
2.1. Ausschnitt einer Tabelle aller Atmel-Mikrocontroller nach
A/D-Kanlen sortiert . . . . . . . . . . . . . . . . . . . . .
7
2.2. Original-Schaltplan der Digital-Platine des Modular-EEG (Quelle: [Pro]) . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
2.3. Schaltplan mit ATmega1280 . . . . . . . . . . . . . . . . . 39
2.4. Pin-Konfigurartion des ATmega8 (Quelle: [Atm07b]) . . . . 40
2.5. Pin-Konfigurartion des ATmega1280 (Quelle: [Atm07a]) . . 41
2.6. Oberseite des Original-Layout (Quelle: [Pro]) . . . . . . . . 42
2.7. Oberseite des Layout fr ATmega1280 . . . . . . . . . . . . 42
2.8. Unterseite des Original-Layout (Quelle: [Pro]) . . . . . . . . 43
2.9. Unterseite des Layout fr ATmega1280 . . . . . . . . . . . 43
2.10. Oberseite der leeren Platine . . . . . . . . . . . . . . . . . . 44
2.11. Unterseite der leeren Platine . . . . . . . . . . . . . . . . . 45
2.12. Oberseite der bestckten Platine . . . . . . . . . . . . . . . 46
2.13. Unterseite der bestckten Platine . . . . . . . . . . . . . . . 46
2.14. Screenshot aus Brainbay mit 16 Kanlen . . . . . . . . . . . 73
VII
Tabellenverzeichnis
2.1. Bestimmung des optimalen Quarz . . . . . . . . . . . . . .
2.2. Bitmuster fr die A/D-Wandler Kanalauswahl mit den Bits
MUX0-MUX5 [Atm07a] . . . . . . . . . . . . . . . . . . .
2.3. Anordnung der Daten im Textpuffer ohne Komprimierung .
2.4. Anordnung der Daten im Textpuffer mit Komprimierung . .
VIII
15
58
65
66
Kapitel 1.
Einleitung
Computer werden in vielen Gebieten und fr viele Zwecke eingesetzt. Fr
den sinnvollen Einsatz von Computern sind Schnittstellen unbedingt erforderlich. Computer knnen ohne Schnittstellen weder programmiert noch bedient werden und knnen auch keine Ergebnisse prsentieren. Je mehr Schnittstellen ein Computer hat, desto mehr Mglichkeiten gibt es, ihn einzusetzen.
Gngige Schnittstellen, die jedem Computerbenutzer bekannt sein drften,
sind Tastatur, Maus und Monitor.
Eine spezielle Gruppe von Schnittstellen sind die BCI.1 Diese Schnittstellen basieren darauf, Signale vom Gehirn zu erfassen und auf einem Computer zu verarbeiten. Ein Verfahren, mit dem man Signale vom Gehirn gewinnen kann, ist das EEG.
EEG ist die Abkrzung fr das Elektroenzephalogramm2 , das Hirnstrombild. Die Gehirnttigkeit verursacht schwache elektrische Strme, die fr die
Erstellung eines EEGs an verschiedenen Punkten der Kopfhaut mit Hilfe von
Elektroden abgeleitet werden. Die Spannungsdifferenz und die Spannungsschwankungen werden verstrkt und entweder von einem Mehrkanalschreiber aufgezeichnet oder von einem Computer oder Mikrocontroller verarbei1 BCI
steht fr Brain-Computer-Interface
egkphalon = was im Kopf ist, Gehirn
2 griechisch
Kapitel 1. Einleitung
tet.3
Ein EEG-Signal kann nach sechs abgrenzbaren Kurvenformen untersucht
werden, die in unterschiedlichen Frequenzbereichen auftreten und den Zustand der Gehirnaktivitt zeigen.
Deltawellen treten im Schlaf auf und haben eine Frequenz von 1 bis
4 Hz.
Thetawellen sind mit Kreativitt, Spontanitt, Ablenkbarkeit, Tagtrumen, Depressionen und Angstzustnden verknpft. Die Frequenz betrgt 48 Hz.
Alphawellen haben eine Frequenz von 812 Hz und treten bei Meditation, innerer Ruhe und Friedlichkeit auf.
Betawellen treten bei aktivem, aufmerksamem wachsein auf und haben eine Frequenz von 13 bis 21 Hertz.
Hohe Betawellen werden mit Zustnden wie Hchstleistung, Sorge,
Angst und Grbeln in Verbindung gebracht und treten bei einer Frequenz von 2032 Hz auf.
Gammawellen haben eine Frequenz von 3840 Hz und sind mit ProblemLsungs Aufgaben verknpft.4
Man kann also mit dem EEG den Aktivittsgrad von verschiedenen Hirnregionen5 feststellen und auch Gehirnerkrankungen erkennen. Mit einem
EEG knnen keine Gedanken gelesen werden.6
Da professionelle medizinische Gerte fr den Hausgebrauch zu teuer sind
um damit herum zu experimentieren wurde das OpenEEG-Projekt ins Leben
3 vgl.
Kapitel 1. Einleitung
gerufen. Das Projekt beschftigt sich mit der Entwicklung von do-it-yourself
EEG-Gerten und richtet sich an jeden der sich Amateurhaft mit EEG beschftigen mchte.7
Der erste Teil von OpenEEG, also Open, sagt aus, dass die Entwickler, die an diesem Projekt arbeiten, ihre Erfahrungen und ihr Wissen teilen.
Dies erfolgt in diesem Fall auf der Internetseite des OpenEEG-Projekts8 , in
dem dort Berichte, Anleitungen und vor allem die Quelltexte fr Software und Schaltplne fr Hardware verffentlicht werden. Die Inhalte dieser
Internetseiten sind, soweit auf einzelnen Seiten nichts anderes vermerkt ist,
unter der creative commons Attribution-Sharealike 2.0 Lizenz verffentlicht.9
Die Lizenz legt fest, dass man das Werk vervielfltigen, verbreiten, ffentlich zugnglich machen und Bearbeitungen des Werkes anfertigen darf. Jedoch nur unter folgenden Bedingungen. Der Autor oder Rechteinhaber muss
in der von ihm festgelegten Weise genannt werden und das neu entstandene
Werk darf nur unter Verwendung von identischen oder vergleichbaren Lizenzbedingungen weitergegeben werden.10
Die Hardware des Projekts beschrnkt sich bisher auf zwei EEG-Gerte.
Zum einen das Modular-EEG, das schon fertig entwickelt ist, whrend meiner Projektarbeit11 in Betrieb genommen und in dieser Diplomarbeit erweitert wird. Zum anderen das Soundcard-EEG, das wie der Name schon sagt,
die Soundkarte als Schnittstelle zum Computer benutzt und dessen Entwicklung bisher nicht abgeschlossen ist.12
Das Modular-EEG verdankt seinen Namen dem modularen Aufbau. Es
setzt sich aus einer Digital-Platine und bis zu drei Analog-Platinen zusam7 vgl.
[Pro]
8 http://openeeg.sourceforge.net/
9 vgl.
Kapitel 1. Einleitung
men. Die Analog-Platinen haben die Aufgabe, die empfindlichen EEG-Signale
zu verstrken und durch mehrere Filterstufen von Strungen zu befreien. Eine Analog-Platine ist mit zwei Kanlen ausgestattet. Auf der Digital-Platine
befindet sich der Mikrocontroller, der die analogen Signale von den AnalogPlatinen Digital-Signale umwandelt und per serieller Datenbertragung zu
einem Computer sendet. Auf der Digital-Platine befindet sich ein Netzteilbereich, der durch Optokoppler vom Mikrocontroller-Teil galvanisch getrennt
ist. Dieses Netzteil versorgt auch die Analog-Platinen mit Strom.13
13 vgl.
[GNP+ 03]
Kapitel 1. Einleitung
Kapitel 2.
Hauptteil
2.1. Machbarkeitsstudie
Vor Beginn der eigentlichen Arbeiten wird an dieser Stelle berprft, ob das
gesetzte Ziel theoretisch erreichbar ist.
Ein wichtiger Punkt fr die berprfung der Machbarkeit ist die Berechnung, wie viel Zeit der Mikrocontroller braucht, um 16 Kanle zu verarbeiten. In den nchsten Abschnitten folgen eine Einfhrung in die TimingProblematik und Berechnungen der Timings fr Sechs- und 16-Kanal-Betrieb.
Neben den theoretischen Voraussetzungen wird jedoch auch ein Mikrocontroller bentigt, der die entsprechende Anzahl an Analog/Digital-WandlerKanlen hat. Die bisher eingesetzten Mikrocontroller im Modular-EEG stammen von der Firma Atmel. Auf der Internetseite von Atmel lieen sich am
12.09.2007 noch alle Atmel-Mikrocontroller in einer Tabelle1 auflisten und
nach bestimmten Kriterien sortieren. In der Fassung vom 27.02.2008 ist die
Anzahl der A/D-Kanle fr viele Mikrocontroller in der Tabelle nicht mehr
eingetragen und daher an dieser Stelle nicht mehr fr die Recherche nach
dem geeigneten Mikrocontroller verwendbar. Ein Ausschnitt der nach A/DKanlen sortierten Tabelle vom 12.09.2007 ist in Abbildung 2.1 zu sehen.
1 Parametric
Product Table
Kapitel 2. Hauptteil
Die Typen ATmega640, ATmega1280 und ATmega2560 eignen sich fr diese Arbeit. Diese drei sind bis auf den Flash Speicher baugleich und werden
im selben Datenblatt beschrieben.2 Von den drei Typen sind bei Conrad oder
Reichelt nur der ATmega1280 oder der ATmega2560 kuflich zu erwerben.
Fr den ATmega128RZBV und den ATmega256RZBV lieen sich keine Bezugsquellen finden. Um nicht alle drei Typen aufzuzhlen, wird im weiteren
Verlauf der Arbeit nur noch der ATmega1280 verwendet.
[Atm07a]
[HPR03]
Kapitel 2. Hauptteil
3,90625 ms4 dauern. Ansonsten wre der erste Zyklus noch nicht vollstndig abgearbeitet, bevor der nchste begonnen wird. Die Deadline wre dann
berschritten und das bedeutet, dass der Mikrocontroller nicht genug Zeit
hat, das Programm ordnungsgem auszufhren.
Der Analog/Digital-Wandler wird beim Modular-EEG mit 10-Bit-Auflsung
betrieben.5 Die Geschwindigkeit des A/D-Wandlers wird durch den Systemtakt festgelegt. Der Systemtakt wird dafr durch einen fr den A/D-Wandler
separat vorhandenen Prescaler entsprechend skaliert. Die Frequenz des A/DWandlers darf bei 10-Bit Auflsung nicht mehr als 200 kHz betragen, um die
maximale Auflsung zu erreichen. Die Umwandlungszeiten betragen fr die
erste Umwandlung 25 A/D-Takte und fr die folgenden Umwandlungen jeweils 13 A/D-Takte.6
Die Datenbertragung erfolgt seriell ber einen USART7 . Die Datenbertragungsrate fr den USART wird wie der A/D-Wandler Takt ebenfalls vom
Systemtakt festgelegt und ber einen Prescaler eingestellt.8 Fr die Datenbertragung wird pro Byte noch ein Start-Bit und ein Stop-Bit mit bertragen, dadurch werden pro Byte 10 Bit bertragen.9
Gleichung 2.1
[HPR03]
6 vgl. [Atm07b]
7 Universal Synchronous and Asynchronous serial Receiver and Transmitter
8 vgl. [Atm07b]
9 vgl. [HPR03]
10 [Hol07]
5 vgl.
Kapitel 2. Hauptteil
es auch eine Paket-Version 3 gibt. Diese wird jedoch nicht von allen Programmen untersttzt und hier nicht thematisiert.
Wie oben beschrieben, betrgt die Abtastrate 256 Hz. Daraus resultiert
nach Gleichung 2.1 eine Zeit von 3,90625 ms, in der ein Zyklus abgearbeitet
sein muss.
Zeit t =
1
1
=
= 0,00390625 s = 3,90625 ms
Frequenz f
256 1s
(2.1)
Die Frequenz des A/D-Wandlers darf nicht mehr als 200 kHz betragen.
Der Wert fr den Prescaler ergibt sich somit aus der Ungleichung 2.2. Der
Prescaler fr den A/D-Wandler kann aber nur die Werte 2, 4, 8, 16, 32, 64 und
128 annehmen. Hier wird der Wert fr den Prescaler also auf 64 festgelegt.
Systemtakt-Frequenz
Max. Frequenz des A/D-Wandlers
7,3728 MHz
>
200 kHz
> 36,864
A/D-Prescaler >
(2.2)
Die Taktfrequenz des A/D-Wandlers betrgt 115,2 kHz und resultiert aus
der Gleichung 2.3. Ein Taktzyklus des A/D-Wandlers bentigt nach Gleichung 2.4 8,68 s.
System-Taktfrequenz
A/D-Prescaler
7,3728 MHz
=
64
= 0,1152 MHz
= 115,2 kHz
(2.3)
Kapitel 2. Hauptteil
Zeit t =
1
1
=
= 8,68 s
Frequenz f
115200 1s
(2.4)
Bei der Berechnung der Zeiten fr die A/D-Wandlung werden in der Firmware fr die jeweils erste von sechs Umwandlungen 26 A/D-Taktzyklen und
fr die folgenden 14 A/D-Taktzyklen zugrunde gelegt.11 Nach Gleichung 2.5
betrgt die Zeit fr die erste A/D-Wandlung 225,68 s und nach Gleichung
2.6 die Zeit fr jede folgende A/D-Wandlung 121,52 s.Um die sechs Kanle umzuwandeln, bentigt der A/D-Wandler nach Gleichung 2.7 insgesamt
0,83328 ms.
(2.5)
= 225,68 s
(2.6)
= 121,52 s
(2.7)
= 0,83328 ms
Pro Zyklus der Abtastrate wird ein Datenpaket gesendet. Dieses Paket enthlt vier Byte fr den Paketheader, zwei Byte fr die Daten pro Kanal und
ein Byte fr den Paketfooter. Bei sechs Kanlen ist das Paket also 17 Byte
gro. Bei der Datenbertragung werden pro Byte noch ein Start- und ein
Stop-Bit mitgesendet. Die Gesamtgre eines Paketes betrgt somit 170 Bit.
11 vgl.
[HPR03]
10
Kapitel 2. Hauptteil
Bei der hier verwendeten bertragungsrate von 57600 Bit
s dauert die bertragung nach Gleichung 2.8 2,95139 ms.
Datenmenge
bertragungsrate
170 Bit
=
57600 Bit
s
Gesamtzeit Datenbertragung =
(2.8)
= 0,00295139 s
= 2,95139 ms
Zieht man nun die Zeiten fr die A/D-Wandlung und die Datenbertragung von der, fr einen Abtast-Zyklus, zur Verfgung stehenden Zeit ab, so
bleiben noch 0,12158 ms brig.
(2.9)
In dieser Restzeit sind die Zeiten fr die restlichen Anweisungen enthalten. Hier wird jedoch nicht die Dauer jeder einzelnen Anweisung analysiert,
sondern die Anzahl der Single-Cycle Anweisungen berechnet, die in der
Restzeit ausgefhrt werden knnten. Single-Cycle bedeutet, dass die Anweisung mit einem Taktzyklus des Mikrocontrollers ausgefhrt werden kann. Es
gibt auch Anweisungen, die mehr als einen Taktzyklus fr die Ausfhrung
bentigen.
Bei einer Taktfrequenz von 7,3728 MHz dauert ein Taktzyklus 0,1356 s.
Es bleibt also noch Zeit fr 896 Sigle-Cycle Anweisungen.
Zeit t =
1
1
=
= 0,1356 s
Frequenz f
7372800 1s
11
(2.10)
Kapitel 2. Hauptteil
(2.11)
= 2,04848 ms
Die Paketgre steigt von 17 Byte auf 37 Byte, da pro Kanal zwei Byte
bertragen und nun zehn Kanle mehr verwendet werden. Durch die Startund Stop-Bits entspricht ein Paket 370 Bit. Die Datenbertragung bentigt
bei einer bertragungsrate von 57600 Bit
s eine Zeit von 6,42361 ms.
Datenmenge
bertragungsrate
370 Bit
=
57600 Bit
s
Gesamtzeit Datenbertragung =
(2.12)
= 0,00642361 s
= 6,42361 ms
Die Datenbertragung braucht schon mehr Zeit als zur Verfgung steht.
Mit den bisherigen Einstellungen kann das Programm nicht ordnungsgem
ausgefhrt werden, wenn 16 Kanle verarbeitet werden. Im folgenden Abschnitt werden Lsungsmglichkeiten fr dieses Problem aufgezhlt.
12
Kapitel 2. Hauptteil
[Stu04]
[Dem05]
14 siehe Tabelle 2.4 auf Seite 66
13 vgl.
13
Kapitel 2. Hauptteil
fr die Paketversion weggelassen wird.
Die maximale Frequenz des A/D-Wandlers von 200 kHz ist mit 115,2 kHz
noch nicht voll ausgeschpft. Fr eine Erhhung der Frequenz muss die Systemtaktfrequenz erhht werden. Diese Frequenz wird durch ein Quarz auf
der Platine festgelegt. Die Tabelle 2.1 dient der Bestimmung der optimalen
Taktfrequenz. In ihr werden fr die Frequenzen der handelsblichen Quarze
die zugehrigen Datenbertragungsraten und Frequenzen des A/D-Wandlers
dargestellt. Die Tabelle enthlt nur Quarzfrequenzen zwischen 1000 und
16000 kHz und davon nur diejenigen, mit der sich Anhand des Prescalers eine Datenbertragungsrate von 115200 Bit
s einstellen lsst. Die optimale Frequenz betrgt 11059,2 kHz, da bei dieser Frequenz die hchste A/D-Frequenz
, bei gleichzeitig eingestellter bertragunsgrate von 115200 Bit
s , erzielt werden kann.
System-Taktfrequenz
A/D-Prescaler
11,0592 MHz
=
64
= 0,1728 MHz
= 172,8 kHz
Die Zeit fr einen A/D-Taktzyklus vermindert sich auf 5,787 s.
14
(2.13)
1843,2
3686,4
7372,8
9216,0
11059,2
14745,6
Frequenz
Quarz
115,2
230,4
460,8
576,0
691,2
921,6
16
64
80
96
128
32
32
64
128
115,2 57,6
28,8
14,4
115,2 57,6
28,8
115,2 57,6
144
72
172,8 86,4
115,2
16
15
Kapitel 2. Hauptteil
Zeit t =
1
1
=
= 5,787 s
Frequenz f
172800 1s
(2.14)
Damit ndert sich auch die Gesamtzeit fr die A/D-Wandlung von 2,04848 ms
auf 1,365732 ms.
(2.15)
= 150,462 s
(2.16)
= 81,018 s
(2.17)
= 1,365732 ms
Die Paketgre wird durch Komprimierung nach dem Schema in Tabelle
2.4 auf Seite 66 von 37 Byte auf 29 Byte verringert und das Byte fr die
Paketversion im Header wird ebenfalls eingespart. Insgesamt ist ein Paket
dann 28 Byte gro. Die Datenbertragungsrate wird auf 115200 Bit
s erhht.
Diese Manahmen krzen die Zeit fr die Datenbertragung von 6,42361 ms
auf 2,43056 ms.
16
Kapitel 2. Hauptteil
Datenmenge
bertragungsrate
280 Bit
=
115200 Bit
s
Gesamtzeit Datenbertragung =
(2.18)
= 0,00243056 s
= 2,43056 ms
Es bleibt noch eine restliche Zeit von 0,109958 ms. Bei 11,0592 MHz dauert ein Taktzyklus 0,0904 s. Die restliche Zeit reicht demnach fr 1216
Single-Cycle Anweisungen.
Zeit t =
1
1
=
= 0,0904 s
Frequenz f
11059200 1s
(2.20)
Dieses Timing ermglicht die Verarbeitung von 16 Kanlen mit einer Abtastrate von 256 Hz.
17
Kapitel 2. Hauptteil
2.2.1. Programmiersprache C
Die Firmware ist in der Programmiersprache C geschrieben. Die Sprache C
wurde von Dennis Ritchie und Brian Kernighan aus der Programmiersprache B weitermodifiziert, die von Ken Thompson entwickelt wurde. Verffentlicht wurde C das erste Mal im Jahr 1978. Der erste Standard namens
ANSI-C wurde 1989 vom American Nationals Standards Institute festgelegt. Ein paar Elemente aus der Weiterentwicklung von C zu C++ sind in
den ISO-Standard C99 von C aus dem Jahre 1999 aufgenommen worden.15
C ist eine maschinennahe und eine hhere Programmiersprache. Auf der
einen Seite kann mit C hardwareorientiert programmiert und somit die Eigenschaften einer speziellen Hardware optimal ausgenutzt werden. Und auf
der anderen Seite kann ein C Programm, welches nicht so maschinennah
programmiert ist, auf einer anderen Computerarchitektur oder einem anderen Betriebssystem verwendet werden. Dafr muss es aber von einem Compiler neu bersetzt werden. Der Sprachumfang von C umfasst 31 reservierte
Worte und beinhaltet dennoch Elemente aus hheren Programmiersprachen.
Weiterhin stehen 40 verschiedene Operatoren fr die Verknpfung von Variablen und Zahlen zur Verfgung.16
Das Hauptprogramm ist wie alle Unterprogramme und Programmmodule
als Funktion realisiert. Wobei das Hauptprogramm die einzige Funktion ist,
die sich selbst aufruft. Dieser Selbstaufruf der Funktion main() erfolgt beim
Programmstart.17
[Bro07b]
[Bro07b]
17 vgl. [Bro07b]
16 vgl.
18
Kapitel 2. Hauptteil
Erklrung der Funktionsweise verzichtet werden.
Die #include-Anweisung gefolgt von einem Dateinamen bewirkt, dass der
Inhalt der angegebenen Datei an Stelle der #include-Anweisung in das Programm geschrieben wird.18
Mit #define werden symbolische Konstanten definiert. Mit der Anweisung
# d e f i n e NUMCHANNELS 6
wird der symbolischen Konstanten NUMCHANNELS der Wert 6 zugewiesen. NUMCHANNELS steht hier fr die Anzahl der verwendeten A/D-Kanle.
Im Programm wird an allen Stellen, an denen die Anzahl der Kanle angegeben wird, statt der Zahl die symbolische Konstante eingetragen. Der Vorteil
von symbolischen Konstanten ist, dass, bei einer ntigen nderung des Wertes, nur an einer zentralen Stelle und nicht im ganzen Programm verstreut
der Wert angepasst werden muss. Auerdem wird das Programm dadurch
besser lesbar.19
Die Funktion outb(ZIEL, WERT) dient der Ausgabe des Wertes WERT in
ZIEL.20 Diese Funktion wird in der Firmware fr das Schreiben in Register
verwendet.
Mit inp(PORT) werden Daten vom angegebenen Port gelesen.21
Die Anweisung BV(BIT) wird durch die eingebundene Datei avr/sfr_defs
in (1 (BIT)) umgewandelt.22 Es wird also eine 1 um BIT stellen nach links
verschoben. Die 1 steht dann an genau der Stelle, an der sich das Bit im
jeweiligen Register befindet.
sbi(REGISTER, BIT) ist eine Funktion, die im angegebenen Register das
18 vgl.
[Wol06]
[Wol06]
20 vgl. [AVR07]
21 vgl. [AVR07]
22 vgl. [AVR07]
19 vgl.
19
Kapitel 2. Hauptteil
angegebene Bit auf den Wert 1 setzt.23
Das gegenteilige wird mit der Funktion cbi(REGISTER, BIT) bewirkt. Das
Bit wird im Register gelscht, also mit dem Wert 0 versehen.24
Die folgenden Anweisungen werden bei der bersetzung des Quellprogramms in ein ausfhrbares Programm ausgewertet. Anweisungen, die zwischen #if defined (__AVR_ATmega8__) und #else stehen werden nur dann
bersetzt, wenn das Programm fr einen AVR ATmega8 Mikrocontroller
bersetzt wird. In allen anderen Fllen werden die Anweisungen zwischen
#else und #endif bersetzt und somit in das ausfhrbare Programm bernommen.
# i f d e f i n e d ( __AVR_ATmega8__ )
/ / Anweisungen
#else
/ / Anweisungen
# endif
hnliches gilt bei dieser Verzweigung, die jedoch bei der Ausfhrung des
Programms und nicht bei der bersetzung des Programms ausgewertet wird.
Diesmal mssen die jeweiligen Anweisungen, die ausgefhrt werden sollen,
in geschweifte Klammern gefasst werden. Ist die BEDINGUNG erfllt25 ,
dann werden die Anweisungen zwischen den Klammern nach if(BEDINGUNG)
ausgefhrt.
i f (BEDINGUNG)
{
/ / Anweisungen
}
else
{
/ / Anweisungen
23 vgl.
[AVR07]
[AVR07]
25 wahr oder 1
24 vgl.
20
Kapitel 2. Hauptteil
}
Das waren die Anweisungen, die am hufigsten in der Firmware verwendet werden. Die restlichen werden in der nun folgenden Analyse der Firmware beschrieben.
2.2.3. Analyse
Die Analyse der Original-Firmware findet in der Reihenfolge des Programmablaufs statt. Die Anweisungen, die im Abschnitt Definitionen dargestellt
sind, werden sogar schon vor dem eigentlichen Programmstart beim bersetzen des Quelltextes in ein ausfhrbares Programm abgearbeitet. Die Anweisungen, die bei jeder Ausfhrung eines Programms als erstes ausgefhrt
werden, stehen in der Hauptfunktion main(), welche sich beim Programmstart selbst aufruft.
In dieser Analyse wird nur erlutert, was durch welche Anweisung bewirkt
wird. Auf die Darstellung von weiteren Optionen, welche mit den Registern
noch konfiguriert werden knnen, wird hier verzichtet, da dies im Rahmen
dieser Arbeit nicht zu leisten ist. Die Konzentration liegt auf der Funktionsweise der Firmware.
Definitionen
Der Inhalt der folgenden Dateien wird bei der bersetzung in das Programm
eingebunden. Da diese Dateien zum Teil auch #inlude-Anweisungen mit
weiteren Dateien enthalten und nicht alle Dateien fr das Verstndnis des
Programms erwhnt werden mssen, werden hier nicht alle Dateien behandelt.
# i n c l u d e < a v r / i o . h>
# i n c l u d e < i n t t y p e s . h>
# i n c l u d e < a v r / i n t e r r u p t . h>
21
Kapitel 2. Hauptteil
# i n c l u d e < a v r / s i g n a l . h>
Die Datei avr/io.h bindet die fr den Mikrocontroller entsprechenden IODefinitionen in das Programm ein. Dazu gehren die folgenden weiteren
Dateien. Die Datei avr/iom8.h wird nur eingebunden, wenn das Programm
fr einen AVR ATmega8-Mikrocontroller bersetzt wird. Mit einer ganzen
Reihe von solchen Bedingungen in der Datei avr/io.h wird fr jeden Mikrocontroller die richtige IO-Definitions Datei gefunden.26
# i n c l u d e < a v r / s f r _ d e f s . h>
# e l i f d e f i n e d ( __AVR_ATmega8__ )
# i n c l u d e < a v r / iom8 . h>
# endif
# i n c l u d e < a v r / p o r t p i n s . h>
# i n c l u d e < a v r / common . h>
# i n c l u d e < a v r / v e r s i o n . h>
# i n c l u d e < a v r / f u s e . h>
# i n c l u d e < a v r / l o c k . h>
_SFR_IO8 ( 0 x02 )
In der Datei avr/iom8.h wird unter anderem zu jedem Registernamen die zugehrige Speicheradresse und zu jedem Bitnamen die zugehrige Bitposition
im Register definiert.27
26 vgl.
27 vgl.
[MWW07]
[Mic02]
22
Kapitel 2. Hauptteil
Als nchstes folgt die Definition der symbolischen Konstanten. NUMCHANNELS steht fr die Anzahl der A/D-Kanle, HEADERLEN fr die
Lnge des Paket-Headers in Byte und PACKETLEN fr die Lnge des Datenpaketes insgesamt. Die Paketlnge setzt sich aus zwei Byte fr jeden Kanal plus der Lnge des Paketheaders plus einem Byte fr den Paket-Footer
zusammen. SAMPFREQ steht fr die Abtastrate und TIMER0VAL fr den
Wert, den der Timer 0 erhlt, um die Abtastrate zu realisieren. Die Zahl
7372800 in TIMER0VAL ist die Frequenz des Quarzes, der die Taktfrequenz
des Mikrocontrollers bestimmt. Die detaillierte Beschreibung der Berechnung von TIMER0VAL findet sich weiter unten auf Seite 31.
# define
# define
# define
# define
# define
NUMCHANNELS 6
HEADERLEN 4
PACKETLEN (NUMCHANNELS * 2 + HEADERLEN + 1 )
SAMPFREQ 256
TIMER0VAL 256 ( ( 7 3 7 2 8 0 0 / 2 5 6 ) / SAMPFREQ)
Nun folgen einige Variablen, die fr das ganze Programm gltig sind.
channel_order[] ist eine konstante28 Liste aus Werten vom Datentyp char.
Die Liste legt fest, in welcher Reihenfolge die A/D-Kanle bearbeitet werden. Die Reihenfolge entspricht der Zuordnung der Kanle zu den AnalogPlatinen. Kanal 0 und 3 sind auf der ersten Platine, 1 und 4 auf der zweiten
und 2 und 5 auf der dritten Analog-Platine.
Der Datentyp char ist ein Byte gro und kann fr einzelne Zeichen oder
fr Ganzzahlen zwischen -128 und +127 verwendet werden.29
TXBuf ist ebenfalls eine Liste. Diese Liste dient als Puffer fr die Paketdaten, die diesmal vom Datentyp uint8_t sind. Die Lnge, also die Gre des
Puffers, wird durch PACKETLEN festgelegt.
28 const
29 vgl.
[Wol06]
23
Kapitel 2. Hauptteil
Das Schlsselwort volatile bewirkt, dass der Wert einer Variablen bei jedem Zugriff neu aus dem Speicher gelesen wird und der Compiler beim
bersetzen des Programms keine Optimierungen an diesem Variablenzugriff
vornimmt.30
Weiterhin bewirkt volatile, dass die Variable im Speicher und nicht in
einem Register gespeichert wird. Dies ist notwendig, wenn mit, in einem
C-Programm eingebetteten, Assembler-Anweisungen auf die Variable zugegriffen werden soll.31
uint8_t steht fr unsigned integer 8 bit type und kann fr vorzeichenlose,
also nur positive, Ganzzahlen von 0255 verwendet werden.32
Die Variable TXIndex wird zur Indizierung des Paketpuffers und CurrentCh wird zur Indizierung der Kanalliste verwendet.
char const channel_order []= { 0 , 3 , 1 , 4 , 2 , 5 };
/ * * The t r a n s m i s s i o n p a c k e t * /
v o l a t i l e u i n t 8 _ t TXBuf [PACKETLEN ] ;
/ * * Next b y t e t o r e a d o r w r i t e i n t h e t r a n s m i s s i o n p a c k e t . * /
v o l a t i l e u i n t 8 _ t TXIndex ;
/ * * C u r r e n t channel being sampled . * /
v o l a t i l e u i n t 8 _ t CurrentCh ;
In diesem Abschnitt werden die Anweisungen analysiert, die beim Programmstart einmalig ausgefhrt werden.
Zuerst werden die ersten vier Byte des Textpuffers geschrieben. In die ersten zwei Byte kommen Werte fr die Synchronisierung mit der Software. Die
30 vgl.
[Wol06]
[Fli01]
32 vgl. [AVR07]
31 vgl.
24
Kapitel 2. Hauptteil
Software kann anhand dieser aufeinanderfolgenden und festgelegten Werte
den Anfang eines Datenpaketes erkennen. Im dritten Byte des Puffers wird
die Nummer der Paketversion untergebracht. Dies zeigt der Software an, in
welcher Reihenfolge die Daten in einem Datenpaket gespeichert sind. Und
das vierte Byte enthlt einen Zhler fr die Pakete von 0255, der bei jedem
Paket um eins hochgezhlt wird. Hier wird der Paketzhler mit 0 initialisiert.
/ / W r i t e p a c k e t h e a d e r and f o o t e r
TXBuf [ 0 ] = 0 xa5 ;
/ / Sync 0
TXBuf [ 1 ] = 0 x5a ;
/ / Sync 1
TXBuf [ 2 ] = 2 ;
/ / Protocol version
TXBuf [ 3 ] = 0 ;
/ / Packet counter
PORTD steht fr das Port D Data Register. Durch die folgenden Anweisungen werden fr alle Pins an Port D und Port B, die als Eingang konfiguriert sind, interne Pull-up Widerstnde aktiviert.34
o u t b (PORTD, 0 x f f ) ;
33 vgl.
34 vgl.
[Atm07b]
[Atm07b]
25
Kapitel 2. Hauptteil
o u t b ( PORTB , 0 x f f ) ;
[Atm07b]
[Atm07b]
26
Kapitel 2. Hauptteil
Bits auf 1 wird der Prescaler fr den A/D-Wandler auf 64 eingestellt. Das
ADIF Bit zeigt einen bestehenden Interrupt des A/D-Wandlers an, wenn es
0 ist. Wird es auf 1 gesetzt, werden die Interrupts zurck gesetzt. Mit ADEN
wird der A/D-Wandler eingeschaltet.37
o u t b (ADMUX, 0 ) ;
/ / Select channel 0
/ / P r e s c a l e r = 6 4 , f r e e r u n n i n g mode = o f f , i n t e r r u p t s o f f .
o u t b (ADCSR, BV( ADPS2 ) | BV( ADPS1 ) ) ;
s b i (ADCSR, ADIF ) ;
/ / R e s e t any p e n d i n g ADC i n t e r r u p t s
s b i (ADCSR, ADEN ) ;
/ / E n a b l e t h e ADC
Systemtakt f requenz
1
16 bertragunsrate
7372800 1s
=
1
16 57600 Bit
s
UBRR =
(2.21)
=7
Im UCSRA Register wird nur ein Bit bei der Systemstart mit 1 initialisiert. Das ist das USART Data Register Empty Bit, welches anzeigt, ob der
Sendepuffer leer ist. Ist das Bit 1, kann ein Interrupt ausgelst werden. Das
wird durch lschen des Bits verhindert.
Das Register UCSRC teilt sich eine Speicheradresse mit dem UBRRH
Register. Durch wenn das USART Register Select Bit URSEL in der Anwei37 vgl.
38 vgl.
[Atm07b]
[Atm07b]
27
Kapitel 2. Hauptteil
sung 1 ist, wird in das UCSRC geschrieben. Die USART Character Size Bits
UCSZ2UCSZ0 legen durch setzten von UCSZ1 und UCSZ0 auf 1 fest, dass
acht Datenbits pro Frame bertragen werden. Ein Frame beginnt mit einem
Start-Bit und endet mit einem Stop-Bit.
TXEN heit Transmitter Enable und aktiviert den USART Sender.39
# i f d e f i n e d ( __AVR_ATmega8__ )
o u t b (UBRRH, 0 ) ;
/ / S e t s p e e d t o 57600 b p s
o u t b (UBRRL , 7 ) ;
o u t b (UCSRA, 0 ) ;
o u t b (UCSRC, BV( URSEL ) | BV( UCSZ1 ) | BV( UCSZ0 ) ) ;
o u t b (UCSRB, BV(TXEN ) ) ;
39 vgl.
40 vgl.
/ / Clear i t .
/ / S t a r t i t . F r e q u e n c y = c l k / 256
/ / Enable the i n t e r r u p t s .
[Atm07b]
[Atm07b]
28
Kapitel 2. Hauptteil
Danach folgt optional die Initialisierung des PWM Signals durch den Aufruf der Funktion pwm_init():
/ / I n i t i a l i z e PWM ( o p t i o n a l )
pwm_init ( ) ;
PWM-Testsignal
29
Kapitel 2. Hauptteil
OCR1A bedeutet Output Compare Register A fr Timer 1. Der Wert in
den Registern OCR1AH und OCR1AL wird stndig mit dem Zhlerwert des
Timers 1 verglichen. Durch die Timer/Counter 1 Control Register TCCR1A
und TCCR1B wird die Funktion des Timers konfiguriert. WGM steht fr Waveform Generation Mode. Die Bits WGM13 bis WGM10 legen den Funktionsmodus des Timer 1 fest. Durch setzten der Bits WGM11 und WGM10 auf
1 wird der phasenkorrekte 10-Bit PWM Modus ausgewhlt. Durch die Bitkombination der Compare Output Mode Bits COM1A1 und COM1A0 mit
COM1A1 = 1 und COM1A0 = 0 wird festgelegt, dass der Pin OC1A, bei
bereinstimmung von OCR1A mit dem Zhlerwert, beim Hochzhlen des
Timers auf 0 und beim Runterzhlen auf 1 gesetzt wird. Der Zhler 1 zhlt
in dieser Konfiguration von 0 bis 1023 hoch und dann wieder bis 0 runter.
Wenn er den Wert 512 erreicht, wird beim hochzhlen OC1A auf 0 und beim
runterzhlen auf 1 gesetzt. CS steht fr Clock Select. Durch setzen von CS12
auf 1 wird als Quelle fr den Timer 1 der Prescaler mit einer Einstellung von
256 gewhlt. Nach Gleichung 2.22 betrgt die Frequenz des Signals, durch
Festlegen des Vergleichswertes auf die Mitte des Wertebereiches, 14,076 Hz.
Der Wert 2046 kommt dadurch zustande, dass der Pin nur bei jeder zweiten
bereinstimmung umgeschaltet wird.41
PWM-Frequenz =
=
Systemtakt f requenz
Prescaler
2046
7372800 1s
256
2046
= 14,076
1
s
# i f d e f i n e d ( __AVR_ATmega8__ )
o u t b (OCR1AH , 2 ) ;
/ / S e t OCR1A = 512
41 vgl.
[Atm07b]
30
(2.22)
Kapitel 2. Hauptteil
o u t b (OCR1AL , 0 ) ;
/ / S e t 10 b i t PWM mode
o u t b ( TCCR1A , BV(COM1A1) + BV(WGM11) + BV(WGM10 ) ) ;
/ / S t a r t and l e t r u n a t c l k / 256 Hz .
o u t b ( TCCR1B , ( 1 << CS12 ) ) ;
Systemtakt f requenz
Prescaler
7372800 1s
=
256
1
= 28800
s
Timer 0 Frequenz =
42 vgl.
[Atm07b]
31
(2.23)
Kapitel 2. Hauptteil
Timer 0 Frequenz
Zhlerschritte bis berlauf
28800 1s
=
256
1
= 112,5
s
Abtastrate =
Timer 0 Frequenz
Abtastrate
28800 1s
=
256
1
= 112,5
s
(2.24)
(2.25)
Die folgenden Anweisungen setzen den Index fr die Kanalliste auf 0 zurck, erhhen den Paketzhler im Datenpuffer um 1 und schreiben in das
letzte Byte des Puffers die digitalen Werte von Port D. Diese Werte werden um zwei Stellen nach rechts verschoben um die Werte von PD5 bis
PD2 rechtsbndig zu haben. Anschlieend wird noch mit 0x0F maskiert.
Das heit, dass alle bis auf die rechten vier Bits gelscht werden.
CurrentCh = 0;
/ / W r i t e h e a d e r and f o o t e r :
/ / Increase packet counter ( fourth byte in header )
TXBuf [ 3 ] + + ;
/ / Get s t a t e o f s w i t c h e s on PD2 . . 5 ,
/ / i f any ( l a s t b y t e i n p a c k e t ) .
TXBuf [ 2 * NUMCHANNELS + HEADERLEN] = ( i n p ( PIND ) >> 2 ) &0x0F ;
32
Kapitel 2. Hauptteil
Als letztes wird in dieser Interruptroutine, durch lschen und setzen von
verschiedenen Interupts, sichergestellt, welche Interruptroutine als nchstes ausgefhrt wird. UDRIE ist das USART Data Register Empty Interrupt
Enable Bit, welches hier gelscht wird, um einen USART Interrupt zu verhindern. Durch Setzen des ADIF auf 1 werden bestehende A/D-WandlerInterrupts gelscht und mit dem ADC Interrupt Enable Bit ADIE wird ein
A/D-Interrupt ausgelst, der als Anzeige fr eine abgeschlossene A/D-Wandlung
dient.43
c b i (UCSRB, UDRIE ) ;
s b i (ADCSR, ADIF ) ;
s b i (ADCSR, ADIE ) ;
/ / E n s u r e UART IRQ s a r e d i s a b l e d .
/ / R e s e t any p e n d i n g ADC i n t e r r u p t s
/ / E n a b l e ADC i n t e r r u p t s .
A/D-Wandlung
[Atm07b]
[AVR07]
33
Kapitel 2. Hauptteil
C u r r e n t C h ++;
Wenn der Index fr die Kanalliste kleiner ist als die Anzahl der Kanle,
wurden noch nicht alle Kanle verarbeitet. In diesem Fall wird der Wert fr
den nchsten Kanal in den A/D-Wandler-Multiplexer gespeichert und somit
ausgewhlt. Sind alle Kanle verarbeitet worden, so wird wieder der Kanal
0 als erster Kanal ausgewhlt und der A/D-Wandler-Interrupt deaktiviert.
Dann wird das erste Byte des Puffers in das USART Daten Register UDR
geschrieben, der USART-Interrupt aktiviert und der Index fr den Puffer auf
1 gesetzt. Durch das schreiben der Daten in den das UDR Register werden
die Daten gesendet.
i f ( C u r r e n t C h < NUMCHANNELS)
{
/ / Select the next channel .
o u t b (ADMUX, c h a n n e l _ o r d e r [ C u r r e n t C h ] ) ;
/ / The n e x t s a m p l i n g i s s t a r t e d a u t o m a t i c a l l y .
}
else
{
/ / P r e p a r e n e x t c o n v e r s i o n , on c h a n n e l 0 .
o u t b (ADMUX, c h a n n e l _ o r d e r [ 0 ] ) ;
/ / D i s a b l e ADC i n t e r r u p t s t o p r e v e n t
/ / f u r t h e r c a l l s t o SIG_ADC .
c b i (ADCSR, ADIE ) ;
/ / Hand o v e r t o SIG_UART_DATA , by s t a r t i n g
/ / t h e UART t r a n s f e r and e n a b l i n g UDR IRQ s .
o u t b (UDR, TXBuf [ 0 ] ) ;
s b i (UCSRB, UDRIE ) ;
TXIndex = 1 ;
}
34
Kapitel 2. Hauptteil
Datenbertragung
2.3. Schaltplannderungen
Neben der Original-Firmware stehen auch die Schaltplne der Platinen im
Internet zum Download zur Verfgung. Die Schaltplne wurden mit Eagle
45 siehe
46 vgl.
Seite 31
[Atm07b]
35
Kapitel 2. Hauptteil
gezeichnet. Dieses Programm ist in einer eingeschrnkten Version kostenlos
im Internet erhltlich. Fr die Herstellung einer Platine wird das PlatinenLayout bentigt. Eagle verknpft den Schaltplan mit dem Layout und sieht
vor, dass zuerst der Schaltplan und dann das Layout fertiggestellt wird.
Die Abbildung 2.2 zeigt den Original-Schaltplan, in dem noch der Mikrocontroller AT90S4433P verwendet wird. Dieser Mikrocontroller wurde von
Atmel durch den ATmega8 ersetzt. Diese beiden Mikrocontroller haben die
gleiche Pin-Konfiguration. In Abbildung 2.3 ist der genderte Schaltplan mit
dem ATmega1280 Mikrocontroller dargestellt. Um Platz fr den Mikrocontroller zu schaffen werden die umliegenden Schaltungsteile verschoben.
Die Belegung von J102 wird nicht grundlegend gendert, um die Kompatibilitt zum Original-Modular-EEG zu erhalten. Die Zuordnung der Pins
in J102 wird an die Pin-Konfiguration des ATmega1280, unter Bercksichtigung der Lage jedes Pin am Gehuse, angepasst. Die Funktionsweise bleibt
aufgrund der folgenden Anpassungen in der Firmware die gleiche. So werden die A/D-Kanle 1015 anstelle der Kanle 05 an J102 angeschlossen.
Die Digital-Eingnge PD2PD5 werden durch PA3PA6 ersetzt. Bei den
digitalen Ausgngen wird die alternative Port-Funktion bei der Auswahl
der Pins teilweise mit bercksichtigt. Dies ist besonders wichtig bei PB1,
der die alternative Port-Funktion fr den Output Compare Pin von Timer
1 hat und das PWM-Signal hier ausgegeben wird. Die alternativen PortFunktionen werden in der Pin-Konfiguration in Klammern dargestellt. Die
Pin-Konfiguration des ATmega8 ist in Abbildung 2.4, die des ATmega1280
in Abbildung 2.5 zu sehen. PB0 und PB2 werden aufgrund der alternativen
Port-Funktionen ICP1 und OC1B anderen Ports zugewiesen, die die selbe alternative Funktion haben. PB0 wird PD4, PB1 wird PB5 und PB2 wird PB6.
Bei den anderen Digital-Ausgngen, die mit J102 verbunden sind, kann irgend ein Port verwendet werden. PD7 wird PD5.
Die Programmier-Schnittstelle J101 wird entsprechend der alternativen
Port-Funktionen von MISO, MOSI, SCK und /RESET mit PB1PB3 und dem
36
Kapitel 2. Hauptteil
Reset-Pin verbunden.
Eine weitere Schnittstelle J103 wird eingefgt um die erweiterten A/DKanle anschlieen zu knnen. Dabei ist bercksichtigt, dass die Kanle
05 ber ein Flachbandkabel mit drei Analog-Platinen verbunden werden
kann und dabei auch die Versorgungsspannungen fr die Analog-Platinen
mit gefhrt werden. Es bleiben noch vier Kanle brig, die auf zwei AnalogPlatinen verteilt werden knnen. Dabei ist darauf zu achten, dass bei dem
Verbindungskabel, auf der Seite der Analog-Platinen eine Reihe zwischen
ADC7 und ADC8 frei bleiben muss, um die Zuordnung der Kanle zu den
Analog-Platinen nach dem bisherigen Schema beizubehalten.
Fr jeden A/D-Kanal ist ein RC-Tiefpass vorhanden.
2.4. Platinenlayout
Da die kostenlose Eagle-Version nur Platinengren bis 10 cm x 8 cm erlaubt, werden die Mae hier nicht berschritten. Dadurch wird Sichergestellt, dass andere Entwicklern im OpenEEG-Projekt die Mglichkeit haben das Platinen-Layout zu ndern. Die Original-Platine erfllt bereits diese
Maximal-Mae.
Aus Platzgrnden wurden einige Widerstnde und Kondensatoren durch
SMD-Bauteile ersetzt. Dies sind alle 470 Vorwiderstnde an J102, alle
7,5 k Widerstnde fr den RC-Tiefpass an den A/D-Kanlen und ein 10 k
Widerstand. Die ersetzten Kondensatoren, mit 220 nF sind diejenigen, welche zum RC-Tiefpass gehren.
Die folgenden Abbildungen zeigen die Vernderung des Platinenlayouts.
Abbildung 2.6 zeigt das Original-Layout von der Oberseite. Entsprechend
ist in Abbildung 2.7 das neue Layout zu sehen.
Die selbe Reihenfolge fr die Unterseite, erst das Original in Abbildung
2.8, dann das neue Layout in Abbildung 2.9.
37
Kapitel 2. Hauptteil
Kapitel 2. Hauptteil
Kapitel 2. Hauptteil
2.5. Bauteile
Da der ATmega1280 mit einem Abstand von 5 mil zwischen den Pins sehr
filigran ist, hat sich bei der Bestellung der Platine herausgestellt, das nicht jede Firma eine solche Platine fertigen kann. Die meisten Firmen geben einen
Mindestabstand von 6 mil fr die Fertigung an. Ein mil entspricht einem tausendstel inch, also 0,0254 mm.
Die leere Platine ist in den Abbildungen 2.10 und 2.11 zu sehen.
Im Internet 47 kann ein Archiv heruntergeladen werden, in dem neben den
Schaltplnen auch Bauteilelisten enthalten sind. In den Listen sind auch die
Bestellnummern von mehreren Lieferanten hinterlegt.
Die Bauteile, die nicht in den Listen aus dem Projekt stehen sind die
SMD-Bauteile. Nach Rcksprache mit Joerg Hansmann48 werden fr die
SMD-Widerstnde 0,125 Watt-Typen in der Bauform 0805 verwendet. Die
47 http://sourceforge.net/project/showfiles.php?group_id=35817
48 einem
40
Kapitel 2. Hauptteil
41
Kapitel 2. Hauptteil
42
Kapitel 2. Hauptteil
43
Kapitel 2. Hauptteil
Kondensatoren sind in der Bauform 1206. Fr den Mikrocontroller kann ein
ATmega1280, ein ATmega640 oder ein ATmega2560 verwendet werden.
Die Abbildungen 2.12 und 2.13 zeigen die bestckte Platine.
44
Kapitel 2. Hauptteil
2.6. Firmware
Zunchst wird die Firmware fr das 6-Kanal-EEG fr den ATmega1280 gendert. Dies hat den Vorteil, dass die Platine mit der bisherigen Software aus
dem OpenEEG-Projekt getestet werden kann. Anschlieend wird die Firmware fr 16-Kanal Betrieb angepasst.
45
Kapitel 2. Hauptteil
46
Kapitel 2. Hauptteil
nicht mehr verwendet werden sollen.
Die Anweisungen, die der Compiler bemngelt, sind:
sbi ( Register , Bit ) ;
cbi ( Register , Bit ) ;
inp ( Register ) ;
o u t b ( Z i e l , Wert ) ;
Um die nderungen am Code deutlich sichtbar zu machen, wird pro nderung zuerst der Code aus der Original Firmware fr den ATmega8 und
darunter der Code fr die Firmware fr den ATmega1280 abgebildet. Fr
den ATmega1280 sind jeweils zwei Zeilen Code angegeben, wobei die obere, auskommentierte Zeile, aus der nderung im ersten Schritt stammt und
die zweite Zeile den endgltigen Code beinhaltet. Die Reihenfolge der nderungen entspricht, wie bei der Analyse der Firmware, der Reihenfolge des
Programmablaufs. Eine detaillierte Beschreibung der Firmware befindet sich
im Abschnitt Analyse der Firmware. Die komplette 6-Kanal-EEG-Firmware
fr den ATmega1280 befindet sich im Anhang. Die Zeilen fr die Kompatibilitt mit dem AT90S4434 werden hier nicht bercksichtigt.
Definitionen
Die Headerdatei avr/signal.h soll laut Compiler nicht mehr verwendet werden. Statt dessen soll avr/interrupt.h eingebunden werden. Da diese schon
eingebunden ist, reicht es, die Anweisung
# i n c l u d e < a v r / s i g n a l . h>
auszukommentieren.
/ / # i n c l u d e < a v r / s i g n a l . h>
47
Kapitel 2. Hauptteil
wie der ATmega8 mit 7,372800 MHz getaktet wird, muss der Wert 7372800
in
# d e f i n e TIMER0VAL 256 ( ( 7 3 7 2 8 0 0 / 2 5 6 ) / SAMPFREQ)
auf 11059200 gendert werden. TIMER0VAL ist der Wert, der fr den Timer
0 eingestellt wird, um eine Abtastrate von 256 Hz zu generieren.
# d e f i n e TIMER0VAL 256 ( ( 1 1 0 5 9 2 0 0 / 2 5 6 ) / SAMPFREQ)
Die Reihenfolge der Kanle wird dahingehend angepasst, dass nun die
A/D-Kanle 1015 an J102 angeschlossen sind und nicht mehr die Kanle
05. Diese nderung hat sich durch das Platinenlayout ergeben.
Alt:
char const channel_order []= { 0 , 3 , 1 , 4 , 2 , 5 };
Neu:
c h a r c o n s t c h a n n e l _ o r d e r [ ] = { 1 0 , 1 3 , 1 1 , 1 4 , 1 2 , 15 } ;
Da der ATmega8 nur drei Ports und der ATmega1280 elf Ports hat, muss die
Konfiguration der Ports in der Firmware erweitert werden. Die Ports haben
bei den beiden Mikrocontrollern nicht die gleichen Funktionen, so dass bei
der Konfiguration auf den jeweiligen Schaltplan zurckzugreifen ist.
Atmel empfiehlt fr nicht angeschlossene Pins den internen Pull-up-Widerstand zu aktivieren, damit der Pin einen definierten Zustand erhlt. Durch
das Setzen aller Bits auf 1 im Port Register des Ports wird fr alle Pins,
die durch das Data Direction Register als Eingang gekennzeichnet sind, der
48
Kapitel 2. Hauptteil
interne Pull-up-Widerstand aktiviert.49
Port A existiert beim ATmega8 nicht und hat hier die Funktion fr die
vier digitalen Eingnge von J102. Es knnen somit alle Pins von Port A
als Eingang konfiguriert werden. Die Data Direction Register werden mit 0
initialisiert. Aus Grnden der bersicht erfolgt hier dennoch die explizite
Anweisung, das Data Direction Register auf 0 zu setzen.
/ / o u t b (DDRA,
DDRA = 0 x00 ;
0 x00 ) ;
An Port B werden PB5 und PB6 als Ausgnge verwendet. PB5 dient hierbei als Ausgang fr das PWM-Kalibrierungssignal. Weiterhin sind die Signale fr die Programmierung (SCK, MOSI, MISO) an Port B Pins 13 angeschlossen. Diese werden hier, analog zu der Firmware des ATmega8, als
Eingang konfiguriert.
/ / o u t b (DDRB,
DDRB = 0 x60 ;
0 x60 ) ;
Die Ports C, G, H, J und L sind gar nicht mit der Schaltung verbunden
und sollten als Eingnge konfiguriert werden, damit die Pull-up-Widerstnde
aktivierbar sind.
/ / o u t b (DDRC,
DDRC = 0 x00 ;
/ / o u t b (DDRG,
DDRG = 0 x00 ;
/ / o u t b (DDRH,
DDRH = 0 x00 ;
/ / o u t b ( DDRJ ,
DDRJ = 0 x00 ;
/ / o u t b (DDRL,
DDRL = 0 x00 ;
49 vgl.
0 x00 ) ;
0 x00 ) ;
0 x00 ) ;
0 x00 ) ;
0 x00 ) ;
[Atm07a]
49
Kapitel 2. Hauptteil
Die Pins PD4 bis PD6 sind als weitere digitale Ausgnge vorgesehen. Die
anderen Pins von Port D sind nicht angeschlossen.
/ / o u t b (DDRD,
DDRD = 0 x70 ;
0 x70 ) ;
0 x02 ) ;
0 xff );
0 xff );
0 xff );
0 xff );
0 xff );
0 xff );
0 xff );
50
Kapitel 2. Hauptteil
/ / o u t b ( PORTJ , 0 x f f ) ;
PORTJ = 0 x f f ;
/ / o u t b ( PORTL , 0 x f f ) ;
PORTL = 0 x f f ;
Die Auswahl und die Aktivierung der Sleep-Modi erfolgt beim ATmega1280 ber das Sleep Mode Control Register (SMCR) und nicht ber das
MCU Control Register (MCUCR). Die Anweisung
o u t b (MCUCR, ( i n p (MCUCR) | BV( SE ) ) &
( ~BV(SM0) | ~BV(SM1) | ~BV(SM2 ) ) ) ;
.
Die Anweisung
o u t b (ADMUX, 0 ) ;
/ / Select channel 0
whlt Kanal 0 als aktuellen Eingang fr den A/D-Wandler aus. Da in dieser Arbeit die ersten Kanle, die jedoch die Kanle 1015 sind, und der
ATmega1280 die Kanle mit 5 Bits anstelle von 3 Bits adressiert, wird die
Anweisung durch folgende ersetzt.
/ / S e l e c t c h a n n e l 10
/ / o u t b (ADMUX, ( i n p (ADMUX) | BV(MUX1) ) &
/ / ( ~BV(MUX0) | ~BV(MUX2) | ~BV(MUX3) | ~BV(MUX4 ) ) ;
ADMUX | = ( 1 << MUX1 ) ;
ADMUX &=
~ ( ( 1 << MUX0) | ( 1 << MUX2) | ( 1 << MUX3) | ( 1 << MUX4 ) ) ;
/ / o u t b (ADCSRB , ( i n p (ADCSRB) | BV(MUX5 ) ) ) ;
51
Kapitel 2. Hauptteil
ADCSRB | = ( 1 << MUX5 ) ;
Der ATmega8 verfgt nur ber das ADC Control and Status Register A
(ADCSRA), welches mit ADCSR angesprochen werden kann. Die folgenden Anweisungen
o u t b (ADCSR, BV( ADPS2 ) | BV( ADPS1 ) ) ;
s b i (ADCSR, ADIF ) ;
/ / R e s e t any p e n d i n g ADC i n t e r r u p t s
s b i (ADCSR, ADEN ) ;
/ / E n a b l e t h e ADC
werden hier jeweils durch ein A ergnzt. Der Prescaler bleibt gleich.
/ / o u t b (ADCSRA, BV( ADPS2 )
ADCSRA | = ( 1 << ADPS2 ) |
/ / s b i (ADCSRA, ADIF ) ;
ADCSRA | = ( 1 << ADIF ) ;
/ / s b i (ADCSRA, ADEN ) ;
ADCSRA | = ( 1 << ADEN ) ;
| BV( ADPS1 ) ) ;
( 1 << ADPS1 ) ;
/ / R e s e t any p e n d i n g ADC i n t e r r u p t s
/ / R e s e t any p e n d i n g ADC i n t e r r u p t s
/ / E n a b l e t h e ADC
/ / E n a b l e t h e ADC
Da der ATmega1280 ber vier USARTs und der ATmega8 nur ber einen
verfgt mssen die Registernamen fr den USART mit seiner Nummer ergnzt werden. In dieser Arbeit wird der USART 0 verwendet. Durch die
Anweisungen
o u t b (UBRRH, 0 ) ;
o u t b (UBRRL , 7 ) ;
/ / S e t s p e e d t o 57600 b p s
wird bei einer Frequenz von 7,372800 MHz die Datenbertragungsrate auf
57600 bps festgelegt. Bei der hier verwendeten Frequenz von 11,0592 MHz
wrde die Datenbertragungsrate bei gleicher Prescaler-Einstellung 86400 bps
betragen. Mit folgenden Anweisungen wird der USART-Prescaler wieder
auf 57600 bps eingestellt.
/ / o u t b (UBRR0H, 0 x00 ) ;
UBRR0H = 0 x00 ;
/ / o u t b ( UBRR0L, 0 x0b ) ;
/ / S e t s p e e d t o 57600 b p s
/ / S e t s p e e d t o 57600 b p s
52
Kapitel 2. Hauptteil
UBRR0L = 0 x0b ;
/ / Clear i t .
/ / Clear i t .
// Start
53
i t . F r e q u e n c y = c l k / 256
Kapitel 2. Hauptteil
/ / o u t b ( TCCR0B , 4 ) ;
TCCR0B = ( 1 << CS02 ) ;
/ / S t a r t i t . F r e q u e n c y = c l k / 256
/ / S t a r t i t . F r e q u e n c y = c l k / 256
Das Timer/Counter Interrupt Mask Register (TIMSK) heit beim ATmega1280 TIMSK0.
o u t b ( TIMSK , BV( TOIE0 ) ) ;
/ / Enable the i n t e r r u p t s .
/ / Enable the i n t e r r u p t s .
/ / Enable the i n t e r r u p t s .
PWM Initialisierung
In der pwm_init Funktion mssen alle Anweisungen ersetzt werden, da diese veraltet sind. Die veralteten Zeilen sind hier auskommentiert dargestellt.
Zustzlich sei hier kurz erwhnt, dass sich die Frequenz des Kalibrierungssignals durch die Erhhung der Taktfrequenz des Mikrocontrollers von ca.
14 Hz auf 21,11 Hz erhht.
/ / o u t b (OCR1AH , 2 ) ;
/ / S e t OCR1A = 512
OCR1AH = 0 x02 ;
/ / S e t OCR1A = 512
/ / o u t b (OCR1AL , 0 ) ;
OCR1AL = 0 x00 ;
/ / S e t 10 b i t PWM mode
/ / o u t b ( TCCR1A , BV(COM1A1) + BV(WGM11) + BV(WGM10 ) ) ;
/ / S e t 10 b i t PWM mode
TCCR1A | = ( 1 << COM1A1) | ( 1 << WGM11) | ( 1 << WGM10 ) ;
/ / S t a r t and l e t r u n a t c l k / 256 Hz .
/ / o u t b ( TCCR1B , ( 1 << CS12 ) ) ;
/ / S t a r t and l e t r u n a t c l k / 256 Hz .
TCCR1B | = ( 1 << CS12 ) ;
54
Kapitel 2. Hauptteil
Interruptroutine fr die Abtastrate
Diese Funktion wird durch den Timer 0 ausgelst, der fr die Abtastrate von
256 Hz zustndig ist.
Hier wieder eine veraltete Anweisung:
/ / Reset timer to get c o r r e c t sampling frequency .
/ / o u t b ( TCNT0 , TIMER0VAL ) ;
/ / Reset timer to get c o r r e c t sampling frequency .
TCNT0 = TIMER0VAL ;
Die Auswahl des aktuellen Kanals wird wieder auf den ersten Kanal zurckgesetzt. Die Zeile
CurrentCh = 0;
muss nicht gendert werden, da CurrentCh zur Indizierung der Kanalnummer in channel_order[] verwendet wird.
Die vier digitalen Eingnge, deren Zustand mit zum PC bertragen wird,
befinden sich nicht mehr an Port D 25, sondern an Port A 36. Die Verschiebung der Bits muss auch angepasst werden, um die Werte ganz nach
rechts zu verschieben und korrekt zu maskieren.
/ / Get s t a t e o f s w i t c h e s on PD2 . . 5 ,
/ / i f any ( l a s t b y t e i n p a c k e t ) .
TXBuf [ 2 * NUMCHANNELS + HEADERLEN] = ( i n p ( PIND ) >> 2 ) &0x0F ;
55
Kapitel 2. Hauptteil
/ / Get s t a t e o f s w i t c h e s on PA3 . . 6 ,
/ / i f any ( l a s t b y t e i n p a c k e t ) .
/ / TXBuf [ 2 * NUMCHANNELS + HEADERLEN] = ( i n p ( PINA ) >> 3 ) &0x0F ;
TXBuf [ 2 * NUMCHANNELS + HEADERLEN] = ( PINA >> 3 ) &0x0F ;
Die Adresse des USART-Interrupts ist nun in Register UCSR0B und heit
UDRIE0.
c b i (UCSRB, UDRIE ) ;
/ / E n s u r e UART IRQ s a r e d i s a b l e d .
/ / c b i ( UCSR0B , UDRIE0 ) ;
UCSR0B &= ~ ( 1 << UDRIE0 ) ;
/ / E n s u r e UART IRQ s a r e d i s a b l e d .
/ / E n s u r e UART IRQ s a r e d i s a b l e d .
Das ADC Control and Status Register (ADCSR) heit nun ADCSRA.
s b i (ADCSR, ADIF ) ;
s b i (ADCSR, ADIE ) ;
/ / R e s e t any p e n d i n g ADC i n t e r r u p t s
/ / E n a b l e ADC i n t e r r u p t s .
/ / s b i (ADCSRA, ADIF ) ;
ADCSRA | = ( 1 << ADIF ) ;
/ / s b i (ADCSRA, ADIE ) ;
ADCSRA | = ( 1 << ADIE ) ;
//
//
//
//
R e s e t any p e n d i n g ADC i n t e r r u p t s
R e s e t any p e n d i n g ADC i n t e r r u p t s
E n a b l e ADC i n t e r r u p t s .
E n a b l e ADC i n t e r r u p t s .
Hier ein paar Anweisungen, deren Adressen zwar stimmen, aber die aufgrund der Compiler-Fehlermeldungen ersetzt werden.
56
Kapitel 2. Hauptteil
/ / TXBuf [ i + 1 ] = i n p (ADCL ) ;
TXBuf [ i + 1 ] = ADCL;
/ / TXBuf [ i ] = i n p (ADCH ) ;
TXBuf [ i ] = ADCH;
Das Bit MUX5 im Register ADCSRB wird in der Main-Funktion auf 1 gesetzt und braucht hier nicht gendert zu werden. Fr eine korrekte Auswahl
der Kanle wird von der Kanalnummer, die in channel_order[] steht, acht
subtrahiert.
/ / Select the next channel .
/ / The r i g h t v a l u e f o r ADMUX e . g . f o r C h a n n e l 10 i s 2
/ / and n o t 1 0 , s o 8 n e e d t o be s u t r a c t e d
ADMUX = ( c h a n n e l _ o r d e r [ C u r r e n t C h ] 8 ) ;
57
MUX5
0
0
0
0
0
0
0
0
1
1
1
1
1
1
1
1
Kanal
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
MUX4
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
MUX3
0
0
0
0
1
1
1
1
0
0
0
0
1
1
1
1
MUX2
0
0
1
1
0
0
1
1
0
0
1
1
0
0
1
1
MUX1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
0
1
MUX0
0
1
2
3
4
5
6
7
0
1
2
3
4
5
6
7
ADMUX Dezimal
Tabelle 2.2.: Bitmuster fr die A/D-Wandler Kanalauswahl mit den Bits MUX0-MUX5 [Atm07a]
Kapitel 2. Hauptteil
58
Kapitel 2. Hauptteil
/ / P r e p a r e n e x t c o n v e r s i o n , on c h a n n e l 0 .
/ / o u t b (ADMUX, c h a n n e l _ o r d e r [ 0 ] ) ;
Da hier wie in der Main-Funktion der Kanal 10 ausgewhlt wird, kann die
Anweisung aus der Main-Funktion verwendet werden.
/ / P r e p a r e n e x t c o n v e r s i o n , on c h a n n e l 1 0 .
ADMUX | = ( 1 << MUX1 ) ;
ADMUX &=
~ ( ( 1 << MUX0) | ( 1 << MUX2) | ( 1 << MUX3) | ( 1 << MUX4 ) ) ;
ADCSRB | = ( 1 << MUX5 ) ;
Auch hier muss die Adresse des ADC Control and Status Registers von
ADCSR auf ADCSRA gendert werden:
c b i (ADCSR, ADIE ) ;
/ / c b i (ADCSRA, ADIE ) ;
ADCSRA &= ~ ( 1 << ADIE ) ;
Die Adressen der USART Register und Bits mssen wieder mit der Nummer des USART vervollstndigt werden.
o u t b (UDR, TXBuf [ 0 ] ) ;
s b i (UCSRB, UDRIE ) ;
/ / o u t b (UDR0 , TXBuf [ 0 ] ) ;
UDR0 = TXBuf [ 0 ] ;
/ / s b i ( UCSR0B , UDRIE0 ) ;
UCSR0B | = ( 1 << UDRIE0 ) ;
Der Name der dritten Interruptroutine wird analog zu den anderen gendert.
59
Kapitel 2. Hauptteil
SIGNAL ( SIG_UART_DATA )
/ / SIGNAL ( SIG_UART_DATA )
ISR ( USART0_UDRE_vect )
Hier sind die Adressen der USART Register und Bits anzupassen sowie
die Anweisungen zu ersetzen.
Alt:
o u t b (UDR, TXBuf [ TXIndex ] ) ;
/ / Send n e x t b y t e
/ / D i s a b l e SIG_UART_DATA i n t e r r u p t s .
c b i (UCSRB, UDRIE ) ;
Neu:
/ / o u t b (UDR0 , TXBuf [ TXIndex ] ) ;
/ / Send n e x t b y t e
UDR0 = TXBuf [ TXIndex ] ;
/ / Send n e x t b y t e
/ / D i s a b l e SIG_UART_DATA i n t e r r u p t s .
/ / c b i ( UCSR0B , UDRIE0 ) ;
/ / D i s a b l e SIG_UART_DATA i n t e r r u p t s .
UCSR0B &= ~ ( 1 << UDRIE0 ) ;
60
Kapitel 2. Hauptteil
# d e f i n e NUMCHANNELS 6
# d e f i n e HEADERLEN 4
# d e f i n e PACKETLEN (NUMCHANNELS * 2 + HEADERLEN + 1 )
c h a r c o n s t c h a n n e l _ o r d e r [ ] = { 1 0 , 1 3 , 1 1 , 1 4 , 1 2 , 15 } ;
Die Anzahl der zu verarbeitenden Kanle wird der Konstanten NUMCHANNELS zugewiesen. Die sechs muss also durch eine 16 ersetzt werden.
Die Lnge des Paketheaders HEADERLEN krzt sich durch das Weglassen der Angabe der Paketversion um ein Byte von vier auf drei.
Die Paketlnge PACKETLEN hat sich durch die Komprimierung der Daten verkrzt. In der Original-Firmware werden pro Kanal zwei Byte bertragen.50 Das entsprche bei 16 Kanlen mit Header und Footer einer Paketlnge von 36 Byte. In dieser Version teilen sich zwei Kanle drei Byte. Dadurch
wird die Paketlnge auf 28 Byte gekrzt.
Die Liste mit der Kanalreihenfolge channel_order[] muss um weitere
Kanle ergnzt werden. Die Reihenfolge entspricht diesmal nicht der Zuordnung zu den Analog-Platinen, da in der Testphase so die Kanle besser
identifiziert werden knnen.
# d e f i n e NUMCHANNELS 16
# d e f i n e HEADERLEN 3
# d e f i n e PACKETLEN ( ( ( NUMCHANNELS/ 2 ) * 3 ) + HEADERLEN + 1 )
char const channel_order []=
{ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 1 0 , 1 1 , 1 2 , 1 3 , 1 4 , 15 } ;
Main-Funktion
Die Anweisung, der die Paketversion oder Protokollnummer in den Textpuffer schreibt, wird gelscht. Um Zeit bei der Datenbertragung zu sparen,
wird dieses Byte nicht mehr verwendet. Dadurch verschiebt sich der Inhalt
50 vgl.
[HPR03]
61
Kapitel 2. Hauptteil
des Textpuffers um ein Byte nach vorne. Entsprechend mssen die Anweisungen, die TXBuf[] verwenden, angepasst werden.
6-Kanal:
TXBuf [ 2 ] = 2 ;
TXBuf [ 3 ] = 0 ;
/ / Protocol version
/ / Packet counter
16-Kanal:
TXBuf [ 2 ] = 0 x00 ;
/ / Packet counter
In der Main-Funktion muss als erster Kanal fr den A/D-Wandler der Kanal 0 ausgewhlt werden.
6-Kanal:
/ / S e l e c t c h a n n e l 10
ADMUX | = ( 1 << MUX1 ) ;
ADMUX &=
~ ( ( 1 << MUX0) | ( 1 << MUX2) | ( 1 << MUX3) | ( 1 << MUX4 ) ) ;
ADCSRB | = ( 1 << MUX5 ) ;
16-Kanal:
/ / Select channel 0
ADMUX &= ~ ( ( 1 << MUX0) | ( 1 << MUX1) | ( 1 << MUX2) |
( 1 << MUX3) | ( 1 << MUX4 ) ) ;
ADCSRB &= ~ ( 1 << MUX5 ) ;
/ / S e t s p e e d t o 57600 b p s
16-Kanal:
UBRR0H = 0 x00 ;
/ / S e t s p e e d t o 115200 b p s
62
Kapitel 2. Hauptteil
UBRR0L = 0 x05 ;
In SIGNAL(TIMER0_OVF_vect) mssen folgende Anweisungen fr die Anpassung an das neue Paketformat gendert werden.
6-Kanal:
/ / Increase packet counter ( fourth byte in header )
TXBuf [ 3 ] + + ;
/ / Get s t a t e o f s w i t c h e s on PA3 . . 6 ,
/ / i f any ( l a s t b y t e i n p a c k e t ) .
TXBuf [ 2 * NUMCHANNELS + HEADERLEN] = ( PINA >> 3 ) &0x0F ;
16-Kanal:
/ / Increase packet counter ( t h i r d byte in header )
TXBuf [ 2 ] + + ;
/ / Get s t a t e o f s w i t c h e s on PA3 . . 6 ,
/ / i f any ( l a s t b y t e i n p a c k e t ) .
TXBuf [ ( ( NUMCHANNELS/ 2 ) * 3 ) + HEADERLEN] = ( PINA >> 3 ) &0x0F ;
Die Anweisungen fr das Fllen des Textpuffers aus dem Speicher des A/DWandlers mssen fr die Komprimierung gendert werden. Die Tabelle 2.3
zeigt den Inhalt des Textpuffers ohne Komprimierung. Dort ist deutlich zu
sehen, dass pro Kanal sechs Bit frei bleiben. In Tabelle 2.4 ist der Inhalt
des Textpuffers mit Komprimierung dargestellt. Die niedrigsten acht Bit des
ersten Kanals, hier Kanal 0, werden in das vierte Byte des Textpuffers gespeichert. Danach werden die Bits acht und neun des ersten Kanals in Byte
fnf gespeichert. Fr den zweiten Kanal, hier Kanal 3, werden zuerst die
niedrigsten acht Bit in das sechste Byte des Puffers geschrieben. Die Bits
63
Kapitel 2. Hauptteil
acht und neun des zweiten Kanals werden um sechs Stellen nach links verschoben, mit dem Inhalt des fnften Byte Oder-Verknpft und in das fnfte
Byte des Puffers gespeichert. Die Kanalnummer ergibt sich aus der Kanalreihenfolge channel_order[] (siehe oben auf Seite 61).
6-Kanal ohne Komprimierung:
i = 2 * C u r r e n t C h + HEADERLEN ;
TXBuf [ i + 1 ] = ADCL;
TXBuf [ i ] = ADCH;
Bei der Auswahl des nchsten Kanals muss gegenber der 6-Kanal Version nun auch das MUX5 Bit bercksichtigt werden.
6-Kanal:
/ / Select the next channel .
/ / The r i g h t v a l u e f o r ADMUX
/ / e . g . f o r C h a n n e l 10 i s 2 and n o t 1 0 ,
/ / s o 8 n e e d t o be s u b t r a c t e d
ADMUX = ( c h a n n e l _ o r d e r [ C u r r e n t C h ] 8 ) ;
64
65
..
.
0
1
2
Byte
Bit 6
Bit 5
Bit 3
Synchronisation (0xa5)
Synchronisation (0x5a)
Paketzhler
Bit 4
Bit 2
Bit 1
Kanal 0
Bit 9
Kanal 0 Kanal 0 Kanal 0 Kanal 0 Kanal 0 Kanal 0 Kanal 0
Bit 7
Bit 6
Bit 5
Bit 4
Bit 3
Bit 2
Bit 1
Kanal 3
Bit 9
Kanal 3 Kanal 3 Kanal 3 Kanal 3 Kanal 3 Kanal 3 Kanal 3
Bit 7
Bit 6
Bit 5
Bit 4
Bit 3
Bit 2
Bit 1
Kanal 1
Bit 9
Kanal 1 Kanal 1 Kanal 1 Kanal 1 Kanal 1 Kanal 1 Kanal 1
Bit 7
Bit 6
Bit 5
Bit 4
Bit 3
Bit 2
Bit 1
Kanal 4
Bit 9
..
..
..
..
..
..
..
.
.
.
.
.
.
.
-
Bit 7
Kanal 0
Bit 8
Kanal 0
Bit 0
Kanal 3
Bit 8
Kanal 3
Bit 0
Kanal 1
Bit 8
Kanal 1
Bit 0
Kanal 4
Bit 8
..
.
Bit 0
Kapitel 2. Hauptteil
66
..
.
0
1
2
Byte
Kanal 0
Bit 7
Kanal 3
Bit 9
Kanal 3
Bit 7
Kanal 1
Bit 7
Kanal 4
Bit 9
Kanal 4
Bit 7
Kanal 2
Bit 7
..
.
Bit 7
Kanal 0
Bit 6
Kanal 3
Bit 8
Kanal 3
Bit 6
Kanal 1
Bit 6
Kanal 4
Bit 8
Kanal 4
Bit 6
Kanal 2
Bit 6
..
.
Bit 6
Bit 4
Bit 3
Bit 2
Kanal 4
Bit 4
Kanal 2
Bit 4
..
.
Kanal 4
Bit 5
Kanal 2
Bit 5
..
.
Kanal 3
Bit 4
Kanal 1
Bit 4
Kanal 3
Bit 5
Kanal 1
Bit 5
Kanal 4
Bit 3
Kanal 2
Bit 3
..
.
Kanal 3
Bit 3
Kanal 1
Bit 3
Kanal 4
Bit 2
Kanal 2
Bit 2
..
.
Kanal 3
Bit 2
Kanal 1
Bit 2
Synchronisation (0xa5)
Synchronisation (0x5a)
Paketzhler
Kanal 0 Kanal 0 Kanal 0 Kanal 0
Bit 5
Bit 4
Bit 3
Bit 2
Bit 5
Kanal 0
Bit 1
Kanal 0
Bit 9
Kanal 3
Bit 1
Kanal 1
Bit 1
Kanal 1
Bit 9
Kanal 4
Bit 1
Kanal 2
Bit 1
..
.
Bit 1
Kanal 0
Bit 0
Kanal 0
Bit 8
Kanal 3
Bit 0
Kanal 1
Bit 0
Kanal 1
Bit 8
Kanal 4
Bit 0
Kanal 2
Bit 0
..
.
Bit 0
Kapitel 2. Hauptteil
Kapitel 2. Hauptteil
Es muss eine Unterscheidung zwischen den Kanlen 07 und 815 erfolgen.
Wenn die Kanalnummer aus channel_order[] an der Stelle CurrentCh kleiner als acht ist, dann muss das MUX5 Bit in ADCSRB auf 0 gesetzt werden.
Die anderen Bits, die in ADMUX stehen, knnen dann mit der Kanalnummer belegt werden. Ist das nicht der Fall, dann ist die Kanalnummer grer
als sieben und das MUX5 Bit muss auf 1 gesetzt werden. Die Bits MUX0MUX2 erhalten dann die Kanalnummer abzglich acht. Das Bitmuster fr
die Kanaladressierung ist in Tabelle 2.2 auf Seite 58 dargestellt.
16-Kanal:
/ / Select the next channel .
i f ( channel_order [ CurrentCh ] < 8)
{
ADCSRB &= ~ ( 1 << MUX5 ) ;
ADMUX = c h a n n e l _ o r d e r [ C u r r e n t C h ] ;
}
else
{
ADCSRB | = ( 1 << MUX5 ) ;
ADMUX = ( c h a n n e l _ o r d e r [ C u r r e n t C h ] 8 ) ;
}
Die Auswahl des ersten Kanals muss von Kanal zehn auf Kanal null gendert werden.
6-Kanal:
/ / P r e p a r e n e x t c o n v e r s i o n , on c h a n n e l 1 0 .
ADMUX | = ( 1 << MUX1 ) ;
ADMUX &=
~ ( ( 1 << MUX0) | ( 1 << MUX2) | ( 1 << MUX3) | ( 1 << MUX4 ) ) ;
ADCSRB | = ( 1 << MUX5 ) ;
16-Kanal:
/ / P r e p a r e n e x t c o n v e r s i o n , on c h a n n e l 0 .
67
Kapitel 2. Hauptteil
ADMUX &= ~ ( ( 1 << MUX0) | ( 1 << MUX1) | ( 1 << MUX2)
| ( 1 << MUX3) | ( 1 << MUX4 ) ) ;
ADCSRB &= ~ ( 1 << MUX5 ) ;
2.7. Software
Als Software wird das Brainbay Programm verwendet, da es ein Open Source Programm ist. Das Programm, der Quellcode, eine ausfhrliche Anleitung
fr nderungen am Programm und die notwendigen Bibliotheken knnen
kostenlos auf der Brainbay-Internetseite51 heruntergeladen werden.
Fr die ersten Tests mit der 6-Kanal-Firmware braucht das Programm
nicht gendert zu werden, da die Daten in der Paketversion 2 bertragen
werden.
Die Funktion fr die Paketversion 2 in der Datei ob_eeg.cpp dient als Vorlage fr die 16-Kanal Version einer solchen Funktion. Die Implementierung
der Dekomprimierung der Daten ist die wesentlichste nderung an dem Programm. Auf die nderungen wird nicht weiter eingegangen. Hier noch die
Quellcodes fr die Original-Funktion und fr die 16-Kanal Version.
6-Kanal-Modular-EEG Paketversion 2:
void parse_byte_P2 ( unsigned char a c t b y t e )
{
s w i t c h (PACKET . r e a d s t a t e )
{
c a s e 0 : i f ( a c t b y t e ==165) PACKET . r e a d s t a t e ++;
break ;
c a s e 1 : i f ( a c t b y t e ==90) PACKET . r e a d s t a t e ++;
e l s e PACKET . r e a d s t a t e = 0 ;
break ;
51 http://www.shifz.org/brainbay/
68
Kapitel 2. Hauptteil
c a s e 2 : PACKET . r e a d s t a t e ++;
break ;
c a s e 3 : PACKET . number = a c t b y t e ;
/ / i f (++PACKET . o l d _ n u m b e r ! = a c t b y t e )
/ / GLOBAL . temp ++;
/ / PACKET . o l d _ n u m b e r = a c t b y t e ;
PACKET . e x t r a c t _ p o s = 0 ;PACKET . r e a d s t a t e ++;
break ;
c a s e 4 : i f (PACKET . e x t r a c t _ p o s < 1 2 )
{
i f ( ( PACKET . e x t r a c t _ p o s & 1 ) == 0 )
PACKET . b u f f e r [PACKET . e x t r a c t _ p o s > >1]
= a c t b y t e *256;
else
PACKET . b u f f e r [PACKET . e x t r a c t _ p o s > >1]
+= a c t b y t e ;
PACKET . e x t r a c t _ p o s ++;
}
else
{ PACKET . s w i t c h e s = a c t b y t e ;
PACKET . r e a d s t a t e = 0 ;
process_packets ( ) ;
}
break ;
d e f a u l t : PACKET . r e a d s t a t e = 0 ;
}
}
69
Kapitel 2. Hauptteil
c a s e 1 : i f ( a c t b y t e ==90) PACKET . r e a d s t a t e ++;
e l s e PACKET . r e a d s t a t e = 0 ;
break ;
c a s e 2 : PACKET . number = a c t b y t e ;
/ / i f (++PACKET . o l d _ n u m b e r ! = a c t b y t e )
/ / GLOBAL . temp ++;
/ / PACKET . o l d _ n u m b e r = a c t b y t e ;
PACKET . e x t r a c t _ p o s = 0 ;PACKET . r e a d s t a t e ++;
break ;
c a s e 3 : t m p _ b u f f e r [PACKET . e x t r a c t _ p o s ] = a c t b y t e ;
PACKET . e x t r a c t _ p o s ++;
i f (PACKET . e x t r a c t _ p o s ==25)
{
f o r ( i =0 , j = 0 ; j < 2 4 ; i +=2 , j +=3)
{
PACKET . b u f f e r [ i ] = ( ( u n s i g n e d s h o r t ) t m p _ b u f f e r [ j ] )
| ( ( ( u n s i g n e d s h o r t ) t m p _ b u f f e r [ j + 1 ] ) & 0 x03 ) << 8 ;
PACKET . b u f f e r [ i + 1 ] =
( ( ( u n s i g n e d s h o r t ) t m p _ b u f f e r [ j + 1 ] ) & 0xC0 ) << 2
| ( ( unsigned short ) tmp_buffer [ j +2]);
}
PACKET . s w i t c h e s = t m p _ b u f f e r [ 2 4 ] ;
PACKET . r e a d s t a t e = 0 ;
process_packets ( ) ;
}
break ;
d e f a u l t : PACKET . r e a d s t a t e = 0 ;
}
}
2.8. Tests
Folgende Tests wurden mit der neuen Hardware durchgefhrt. Whrend der
Ltarbeiten wurde der ordnungsgeme Kontakt der Mikrocontroller-Pins
70
Kapitel 2. Hauptteil
geprft. Benachbarte Pins wurden auf Kurzschlsse getestet.
Zum Testen der Funktionstchtigkeit der Platine wurden diese Tests durchgefhrt. In Brainbay wurden die Signale der Kanle auf einem Oszilloskop
ausgegeben. Als Quelle der Signale wurde der PWM-Ausgang mit jeweils
einem Kanal verbunden und der Signalverlauf beobachtet.
Test 1: 6-Kanal-Firmware mit Original Brainbay Kanle 1015
Ergebnis: Normale Funktion
Test 2: 6-Kanal-Firmware mit gendertem Brainbay Kanle 1015
Ergebnis: Normale Funktion
Test 3: 6-Kanal-Firmware mit gendertem Brainbay Kanle 05
Ergebnis: Fehler
Test 4: 6-Kanal-Firmware mit Original Brainbay Kanle 05
Ergebnis: Gleiche Fehler
Kanal 0 normale Funktion
Kanal 1 normale Funktion
Ein Signal auf Kanal 2 wird in der Software auch auf Kanal 3 angezeigt.
Wird das Signal auf Kanal 3 angeschlossen, ist in der Software nichts zu sehen.
Kanal 4 verringerte Amplitude
Kanal 5 verringerte Amplitude
Test 5: 6-Kanal-Firmware mit Original Brainbay Kanle 0, 6, 7, 3, 4, 5 Ergebnis: Fehler
Kanal 6 verringerte Amplitude
Kanal 7 verringerte Amplitude und Signal auch auf Kanal 3.
71
Kapitel 2. Hauptteil
Test 6: 6-Kanal-Firmware mit Original Brainbay Kanle 8-13
Ergebnis: Normale Funktion
Vermutlich liegt ein Problem mit den Kondensatoren im Tiefpass der A/DEingnge vor.
Test 7: 16-Kanal-Firmware mit gendertem Brainbay Kanle 016
Ergebnis: Gleiche Fehler bei den Kanlen wie bei den 6-Kanal Tests.
Test 8: 16-Kanal-Firmware mit gendertem Brainbay Kanle 016, alle
Kanle angeschlossen
Ergebnis: Der Signalverlauf ist bei 16-Kanlen gleichmig.
Abbildung 2.14 zeigt einen Screenshot aus dem Brainbay-Programm bei
gleichzeitiger Verwendung von 16 Kanlen.
72
Kapitel 2. Hauptteil
73
Kapitel 3.
Abschluss
3.1. Fazit
In dieser Diplomarbeit ist eine Platine entstanden, mit der sich zeigen lsst,
dass die Zielsetzung und die theoretischen berlegungen umsetzbar sind.
Die Platine enthlt noch kleine Fehler, fr deren Beseitigung die Zeit nicht
mehr ausgereicht hat.
3.2. Ausblick
Es gibt noch einige interessante Aufgaben, die sich an diese Arbeit anschlieen lassen. So knnten weitere EEG-Programme fr die Verwendung von
16-Kanlen erweitert werden. Im OpenEEG-Projekt wurde auf die Verwendung eines Programmierprogrammes zum Einspielen der Firmware auf den
Mikrocontroller hingewiesen. Dieses Programm heit SP12 und hat keine
Konfiguration um damit einen ATmega1280 zu programmieren. Der Vorteil
von so einem Programm ist, dass mit ein paar Bauteilen ein eigenes Programmierkabel hergestellt werden kann. Eine Konfiguration fr SP12 fr
den ATmega1280 herzustellen wrde die Verwendbarkeit dieser Arbeit im
OpenEEG-Projekt vergrern.
74
Eidesstattliche Erklrung
Ich versichere an Eides statt, dass ich die vorliegende Arbeit selbstndig angefertigt und mich keiner fremden Hilfe bedient sowie keine anderen als die
angegebenen Quellen und Hilfsmittel benutzt habe. Alle Stellen, die wrtlich
oder sinngem verffentlichten oder nicht verffentlichten Schriften und
anderen Quellen entnommen sind, habe ich als solche kenntlich gemacht.
Diese Arbeit hat in gleicher oder hnlicher Form noch keiner Prfungsbehrde vorgelegen.
Dortmund, den 27.03.2008
Erklrung
Mir ist bekannt, dass nach 156 StGB bzw. 163 StGB eine falsche Versicherung an Eides Statt bzw. eine fahrlssige falsche Versicherung an Eides
Statt mit Freiheitsstrafe bis zu drei Jahren bzw. bis zu einem Jahr oder mit
Geldstrafe bestraft werden kann.
Dortmund, den 27.03.2008
75
Literaturverzeichnis
[Atm05]
[Bro07a]
Der Brockhaus multimedial 2007 premium, 2007, ISBN 3-41106548-6. Artikel: Elektroenzephalogramm.
[Bro07b]
Der Brockhaus multimedial 2007 premium, 2007, ISBN 3-41106548-6. Artikel: C, Programmierung.
[Cre]
76
Literaturverzeichnis
[Dem05]
[Fli01]
[GNP+ 03] Dan Griffiths, Nelo, Jim Peters, Andreas Robinson, Jack
Spaar und Yaniv Vilnai: The ModularEEG Design, 2002,2003.
http://openeeg.sourceforge.net/doc/modeeg/
modeeg_design.html, besucht: 26.03.2008.
[Hol07]
[HPR03]
Joerg Hansmann, Jim Peters und Andreas Robinson: ModularEEG firmware for one-way transmission, v0.5.4-p2, 2002,2003.
http://downloads.sourceforge.net/openeeg/
ModularEEG-firmware-v1.0.0.zip?modtime=
1061769600&big_mirror=0, besucht: 10.03.2008.
[Lic]
[Mic02]
77
Literaturverzeichnis
[Stu04]
[Wol06]
78
Anhang A.
Original Firmware fr ATmega8
Hier folgt die Firmware Version 0.5.4-p2 aus dem OpenEEG-Projekt. (Quelle: [HPR03]) Zur besseren Lesbarkeit wurden lediglich ein paar Zeilenumbrche eingefgt. Der Code an sich wurde nicht verndert.
/*
* ModularEEG f i r m w a r e f o r oneway t r a n s m i s s i o n , v0 . 5 . 4 p2
* C o p y r i g h t ( c ) 2002 2003 ,
* J o e r g Hansmann , Jim P e t e r s , A n d r e a s R o b i n s o n
* L i c e n s e : GNU G e n e r a l P u b l i c L i c e n s e ( GPL ) v2
* C o m p i l e s w i t h AVRGCC v3 . 3 .
*
* Note : p2 i n t h e v e r s i o n number means t h i s f i r m w a r e i s f o r
* packet version 2.
*/
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/*
//////////
P a c k e t Format Version 2 / / / / / / / / / / / /
/ / 17 b y t e p a c k e t s a r e t r a n s m i t t e d from t h e ModularEEG
/ / a t 256Hz , u s i n g 1 s t a r t b i t , 8 d a t a b i t s , 1 s t o p b i t ,
/ / no p a r i t y , 57600 b i t s p e r s e c o n d .
79
/ / Minimial t r a n s m i s s i o n speed i s
/ / 256Hz * s i z e o f ( m o d e e g _ p a c k e t ) * 10 = 43520 b p s .
s t r u c t modeeg_packet
{
uint8_t
sync0 ;
/ / = 0 xa5
uint8_t
sync1 ;
/ / = 0 x5a
uint8_t
version ;
// = 2
/ / p a c k e t c o u n t e r . I n c r e a s e s by 1 e a c h p a c k e t .
uint8_t
count ;
/ / 10 b i t s a m p l e ( = 0 1 0 2 3 ) i n b i g e n d i a n
/ / ( Motorola ) format .
uint16_t
data [ 6 ] ;
/ / S t a t e o f PD5 t o PD2 , i n b i t s 3 t o 0 .
uint8_t
switches ;
};
//
//
//
//
Note t h a t d a t a i s t r a n s m i t t e d i n b i g e n d i a n f o r m a t .
By t h i s m e a s u r e t o g e t h e r w i t h t h e u n i q u e p a t t e r n i n s y n c 0
and s y n c 1 i t i s g u a r a n t e e d , t h a t r e s y n c
( i . e a f t e r d i s c o n n e c t i n g the data l i n e ) i s always s a f e .
//
//
//
//
*/
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/*
* Program f l o w :
*
80
< a v r / i o . h>
< i n t t y p e s . h>
< a v r / i n t e r r u p t . h>
< a v r / s i g n a l . h>
# d e f i n e NUMCHANNELS 6
# d e f i n e HEADERLEN 4
# d e f i n e PACKETLEN (NUMCHANNELS * 2 + HEADERLEN + 1 )
# d e f i n e SAMPFREQ 256
# d e f i n e TIMER0VAL 256 ( ( 7 3 7 2 8 0 0 / 2 5 6 ) / SAMPFREQ)
char const channel_order []= { 0 , 3 , 1 , 4 , 2 , 5 };
/ * * The t r a n s m i s s i o n p a c k e t * /
v o l a t i l e u i n t 8 _ t TXBuf [PACKETLEN ] ;
81
CurrentCh = 0;
/ / W r i t e h e a d e r and f o o t e r :
/ / Increase packet counter ( fourth byte in header )
TXBuf [ 3 ] + + ;
/ / Get s t a t e o f s w i t c h e s on PD2 . . 5 ,
/ / i f any ( l a s t b y t e i n p a c k e t ) .
TXBuf [ 2 * NUMCHANNELS + HEADERLEN] =
( i n p ( PIND ) >> 2 ) &0x0F ;
c b i (UCSRB, UDRIE ) ;
s b i (ADCSR, ADIF ) ;
s b i (ADCSR, ADIE ) ;
/ / E n s u r e UART IRQ s a r e d i s a b l e d .
/ / R e s e t any p e n d i n g ADC i n t e r r u p t s
/ / E n a b l e ADC i n t e r r u p t s .
/ / The ADC w i l l s t a r t s a m p l i n g a u t o m a t i c a l l y a s s o o n
/ / a s s l e e p i s e x e c u t e d i n t h e mainl o o p .
}
82
83
pwm_init ( void )
S e t t i m e r / c o u n t e r 1 t o u s e 10 b i t PWM mode .
The c o u n t e r c o u n t s from z e r o t o 1023 and t h e n b a c k down
a g a i n . Each t i m e t h e c o u n t e r v a l u e e q u a l s t h e v a l u e
o f OCR1 (A) , t h e o u t p u t p i n i s t o g g l e d .
The c o u n t e r s p e e d i s s e t i n TCCR1B ,
t o c l k / 256 = 28800Hz .
E f f e c t i v e f r e q u e n c y i s t h e n c l k / 256 / 2046 = 14 Hz
# i f d e f i n e d ( __AVR_ATmega8__ )
o u t b (OCR1AH , 2 ) ;
/ / S e t OCR1A = 512
o u t b (OCR1AL , 0 ) ;
/ / S e t 10 b i t PWM mode
o u t b ( TCCR1A , BV(COM1A1) + BV(WGM11) + BV(WGM10 ) ) ;
/ / S t a r t and l e t r u n a t c l k / 256 Hz .
o u t b ( TCCR1B , ( 1 << CS12 ) ) ;
84
=
=
=
=
0 xa5 ;
0 x5a ;
2;
0;
/ / Sync 0
/ / Sync 1
/ / Protocol version
/ / Packet counter
/ / S e t up t h e p o r t s .
o u t b (DDRD,
o u t b (DDRB,
o u t b (PORTD,
o u t b ( PORTB ,
0 xc2 ) ;
0 x07 ) ;
0 xff );
0 xff );
/ / S e l e c t s l e e p mode = i d l e .
# i f d e f i n e d ( __AVR_ATmega8__ )
o u t b (MCUCR, ( i n p (MCUCR) | BV( SE ) ) &
( ~BV(SM0) | ~BV(SM1) | ~BV(SM2 ) ) ) ;
85
T i m i n g s f o r s a m p l i n g o f one 10 b i t ADv a l u e :
/ / Select channel 0
/ / P r e s c a l e r = 6 4 , f r e e r u n n i n g mode = o f f , i n t e r r u p t s o f f .
o u t b (ADCSR, BV( ADPS2 ) | BV( ADPS1 ) ) ;
s b i (ADCSR, ADIF ) ;
/ / R e s e t any p e n d i n g ADC i n t e r r u p t s
s b i (ADCSR, ADEN ) ;
/ / E n a b l e t h e ADC
/ / I n i t i a l i z e t h e UART
# i f d e f i n e d ( __AVR_ATmega8__ )
o u t b (UBRRH, 0 ) ;
/ / S e t s p e e d t o 57600 b p s
o u t b (UBRRL , 7 ) ;
o u t b (UCSRA, 0 ) ;
o u t b (UCSRC, BV( URSEL ) | BV( UCSZ1 ) | BV( UCSZ0 ) ) ;
o u t b (UCSRB, BV(TXEN ) ) ;
86
/ / S e t s p e e d t o 57600 b p s
# endif
/ / I n i t i a l i z e timer 0
o u t b ( TCNT0 ,
// Start it .
o u t b ( TCCR0 ,
o u t b ( TIMSK ,
0);
/ / Clear i t .
F r e q u e n c y = c l k / 256
4);
BV( TOIE0 ) ) ;
/ / Enable the i n t e r r u p t s .
/ / I n i t i a l i z e PWM ( o p t i o n a l )
pwm_init ( ) ;
sei ();
/ / Now , we w a i t . T h i s i s an e v e n t d r i v e n program ,
/ / s o n o t h i n g much h a p p e n s h e r e .
while (1)
{
__asm__ _ _ v o l a t i l e _ _ ( "sleep" ) ;
}
}
87
Anhang B.
6-Kanal-EEG Firmware fr
ATmega1280
Dies ist die Firmware fr den ATmega1280 fr den ersten Test der Platine mit 6-Kanal A/D-Wandlung und der unvernderten Software, auf die im
OpenEEG-Projekt verlinkt wird.
/*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
6C h a n n e l ModularEEG f i r m w a r e f o r oneway t r a n s m i s s i o n ,
v0 .1 p2 f o r ATmega1280 (6Ch EEG) a t 1 1 0 5 9 , 2 kHz
M o d i f i e d by : B a s t i a n H o l t e r m a n n
D a t e : March 2008
L i c e n s e : GNU G e n e r a l P u b l i c L i c e n s e ( GPL ) v3
C o m p i l e s w i t h AVRGCC v4 . 2 . 2
This i s a modified Version of :
* * * * * * * * * * * * * * * * * * * * * * * * * * * *
ModularEEG f i r m w a r e f o r oneway t r a n s m i s s i o n , v0 . 5 . 4 p2
C o p y r i g h t ( c ) 2002 2003 ,
J o e r g Hansmann , Jim P e t e r s , A n d r e a s R o b i n s o n
L i c e n s e : GNU G e n e r a l P u b l i c L i c e n s e ( GPL ) v2
C o m p i l e s w i t h AVRGCC v3 . 3 .
Note : p2 i n t h e v e r s i o n number means t h i s f i r m w a r e
is for packet version 2.
88
* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/*
//////////
P a c k e t Format Version 2 / / / / / / / / / / / /
/ / 17 b y t e p a c k e t s a r e t r a n s m i t t e d from t h e ModularEEG a t
/ / 256Hz , u s i n g 1 s t a r t b i t , 8 d a t a b i t s , 1 s t o p b i t ,
/ / no p a r i t y , 57600 b i t s p e r s e c o n d .
/ / Minimial t r a n s m i s s i o n speed i s
/ / 256Hz * s i z e o f ( m o d e e g _ p a c k e t ) * 10 = 43520 b p s .
s t r u c t modeeg_packet
{
uint8_t
sync0 ;
//
uint8_t
sync1 ;
//
uint8_t
version ; / /
/ / p a c k e t c o u n t e r . I n c r e a s e s by
uint8_t
count ;
/ / 10 b i t s a m p l e ( = 0 1 0 2 3 )
/ / in big endian ( Motorola )
uint16_t
data [ 6 ] ;
/ / S t a t e o f PA6 t o PA3 , i n b i t s
uint8_t
switches ;
};
//
//
//
//
=
=
=
1
0 xa5
0 x5a
2
each packet .
format .
3 to 0.
Note t h a t d a t a i s t r a n s m i t t e d i n b i g e n d i a n f o r m a t .
By t h i s m e a s u r e t o g e t h e r w i t h t h e u n i q u e p a t t e r n i n
s y n c 0 and s y n c 1 i t i s g u a r a n t e e d , t h a t r e s y n c
( i . e a f t e r d i s c o n n e c t i n g the data l i n e ) i s always s a f e .
/ / At t h e moment c o m m u n i c a t i o n d i r e c t i o n i s o n l y from
89
90
91
92
i f ( C u r r e n t C h < NUMCHANNELS)
{
/ / Select the next channel .
/ / The r i g h t v a l u e f o r ADMUX
/ / e . g . f o r C h a n n e l 10 i s 2 and n o t 1 0 ,
/ / s o 8 n e e d t o be s u b t r a c t e d
ADMUX = ( c h a n n e l _ o r d e r [ C u r r e n t C h ] 8 ) ;
/ / The n e x t s a m p l i n g i s s t a r t e d a u t o m a t i c a l l y .
}
else
{
/ / P r e p a r e n e x t c o n v e r s i o n , on c h a n n e l 1 0 .
/ / o u t b (ADMUX, c h a n n e l _ o r d e r [ 0 ] ) ;
ADMUX | = ( 1 << MUX1 ) ;
ADMUX &= ~ ( ( 1 << MUX0) | ( 1 << MUX2)
| ( 1 << MUX3) | ( 1 << MUX4 ) ) ;
ADCSRB | = ( 1 << MUX5 ) ;
/ / D i s a b l e ADC i n t e r r u p t s t o p r e v e n t
/ / f u r t h e r c a l l s t o SIG_ADC .
/ / c b i (ADCSRA, ADIE ) ;
ADCSRA &= ~ ( 1 << ADIE ) ;
/ / Hand o v e r t o SIG_UART_DATA , by s t a r t i n g
/ / t h e UART t r a n s f e r and e n a b l i n g UDR IRQ s .
/ / o u t b (UDR0 , TXBuf [ 0 ] ) ;
UDR0 = TXBuf [ 0 ] ;
/ / s b i ( UCSR0B , UDRIE0 ) ;
UCSR0B | = ( 1 << UDRIE0 ) ;
TXIndex = 1 ;
}
}
93
94
=
=
=
=
0 xa5 ;
0 x5a ;
2;
0;
/ / Sync 0
/ / Sync 1
/ / Protocol version
/ / Packet counter
/ / S e t up t h e p o r t s .
/ / o u t b (DDRA,
DDRA = 0 x00 ;
/ / o u t b (DDRB,
DDRB = 0 x60 ;
/ / o u t b (DDRC,
DDRC = 0 x00 ;
/ / o u t b (DDRD,
DDRD = 0 x70 ;
/ / o u t b (DDRE,
DDRE = 0 x02 ;
/ / o u t b (DDRG,
DDRG = 0 x00 ;
/ / o u t b (DDRH,
DDRH = 0 x00 ;
0 x00 ) ;
0 x60 ) ;
0 x00 ) ;
0 x70 ) ;
0 x02 ) ;
0 x00 ) ;
0 x00 ) ;
95
0 x00 ) ;
0 x00 ) ;
0 xff );
0 xff );
0 xff );
0 xff );
0 xff );
0 xff );
0 xff );
0 xff );
0 xff );
/ / S e l e c t s l e e p mode = i d l e .
/ / o u t b (SMCR, ( i n p (SMCR) | BV( SE ) ) & ( ~BV(SM0)
/ / | ~BV(SM1) | ~BV(SM2 ) ) ) ;
SMCR | = ( 1 << SE ) ;
SMCR &= ~ ( ( 1 << SM0) | ( 1 << SM1) | ( 1 << SM2 ) ) ;
/ / I n i t i a l i z e t h e ADC
/ / T i m i n g s f o r s a m p l i n g o f one 10 b i t ADv a l u e :
//
/ / p r e s c a l e r > ( ( XTAL / 200 kHz ) = 5 5 . 2 9 6 =>
96
/ / S e l e c t c h a n n e l 10
/ / o u t b (ADMUX, ( i n p (ADMUX) | BV(MUX1) )
/ / & ( ~BV(MUX0) | ~BV(MUX2) | ~BV(MUX3) | ~BV(MUX4 ) ) ;
ADMUX | = ( 1 << MUX1 ) ;
ADMUX &= ~ ( ( 1 << MUX0) | ( 1 << MUX2) | ( 1 << MUX3)
| ( 1 << MUX4 ) ) ;
/ / o u t b (ADCSRB , ( i n p (ADCSRB) | BV(MUX5 ) ) ) ;
ADCSRB | = ( 1 << MUX5 ) ;
/ / P r e s c a l e r = 6 4 , f r e e r u n n i n g mode = o f f , i n t e r r u p t s o f f .
/ / o u t b (ADCSRA, BV( ADPS2 ) | BV( ADPS1 ) ) ;
ADCSRA | = ( 1 << ADPS2 ) | ( 1 << ADPS1 ) ;
/ / R e s e t any p e n d i n g ADC i n t e r r u p t s
/ / s b i (ADCSRA, ADIF ) ;
ADCSRA | = ( 1 << ADIF ) ;
/ / E n a b l e t h e ADC
/ / s b i (ADCSRA, ADEN ) ;
ADCSRA | = ( 1 << ADEN ) ;
/ / I n i t i a l i z e t h e UART
/ / S e t s p e e d t o 57600 b p s
/ / o u t b (UBRR0H, 0 x00 ) ;
UBRR0H = 0 x00 ;
/ / o u t b ( UBRR0L, 0 x0b ) ;
UBRR0L = 0 x0b ;
/ / o u t b ( UCSR0A , 0 ) ;
UCSR0A = 0 x00 ;
97
/ / I n i t i a l i z e timer 0
/ / Clear i t .
/ / o u t b ( TCNT0 , 0 ) ;
TCNT0 = 0 x00 ;
/ / S t a r t i t . F r e q u e n c y = c l k / 256
/ / o u t b ( TCCR0B , 4 ) ;
TCCR0B = ( 1 << CS02 ) ;
/ / Enable the i n t e r r u p t s .
/ / o u t b ( TIMSK0 , BV( TOIE0 ) ) ;
TIMSK0 | = ( 1 << TOIE0 ) ;
/ / I n i t i a l i z e PWM ( o p t i o n a l )
pwm_init ( ) ;
sei ();
/ / Now , we w a i t . T h i s i s an e v e n t d r i v e n program ,
/ / s o n o t h i n g much h a p p e n s h e r e .
while (1)
{
__asm__ _ _ v o l a t i l e _ _ ( "sleep" ) ;
}
}
98
Anhang C.
16-Kanal Firmware fr
ATmega1280
Hier ist die Firmware fr 16-Kanal A/D-Wandlung mit dem ATmega1280.
/*
* 16 C h a n n e l ModularEEG f i r m w a r e f o r oneway t r a n s m i s s i o n ,
* v0 .1 p2 f o r ATmega1280 (16Ch EEG) a t 1 1 0 5 9 , 2 kHz
* M o d i f i e d by : B a s t i a n H o l t e r m a n n
* D a t e : March 2008
* L i c e n s e : GNU G e n e r a l P u b l i c L i c e n s e ( GPL ) v3
* C o m p i l e s w i t h AVRGCC v4 . 2 . 2
* This i s a modified Version of :
* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* ModularEEG f i r m w a r e f o r oneway t r a n s m i s s i o n , v0 . 5 . 4 p2
* C o p y r i g h t ( c ) 2002 2003 ,
* J o e r g Hansmann , Jim P e t e r s , A n d r e a s R o b i n s o n
* L i c e n s e : GNU G e n e r a l P u b l i c L i c e n s e ( GPL ) v2
* C o m p i l e s w i t h AVRGCC v3 . 3 .
*
* Note : p2 i n t h e v e r s i o n number means t h i s f i r m w a r e i s
* for packet version 2.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
99
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/*
//////////
P a c k e t Format
////////////
/ / 28 b y t e p a c k e t s a r e t r a n s m i t t e d from t h e ModularEEG
/ / a t 256Hz , u s i n g 1 s t a r t b i t , 8 d a t a b i t s , 1 s t o p b i t ,
/ / no p a r i t y , 115200 b i t s p e r s e c o n d .
/ / Minimial t r a n s m i s s i o n speed i s
/ / 256Hz * s i z e o f ( m o d e e g _ p a c k e t ) * 10 = 71680 b p s .
s t r u c t modeeg_packet
{
uint8_t
sync0 ;
/ / = 0 xa5
uint8_t
sync1 ;
/ / = 0 x5a
/ / p a c k e t c o u n t e r . I n c r e a s e s by 1 e a c h p a c k e t .
uint8_t
count ;
/ / 10 b i t s a m p l e ( = 0 1 0 2 3 )
uint16_t
data [16];
/ / S t a t e o f PA6 t o PA3 , i n b i t s 3 t o 0 .
uint8_t
switches ;
};
/ / By t h i s m e a s u r e t o g e t h e r w i t h t h e u n i q u e p a t t e r n i n s y n c 0
/ / and s y n c 1 i t i s g u a r a n t e e d , t h a t r e s y n c
/ / ( i . e a f t e r d i s c o n n e c t i n g the data l i n e ) i s always s a f e .
//
//
//
//
//
At t h e moment c o m m u n i c a t i o n d i r e c t i o n i s o n l y from
Atmelp r o c e s s o r t o PC . The h a r d w a r e however s u p p o r t s f u l l
d u p l e x c o m m u n i c a t i o n . T h i s f e a t u r e w i l l be u s e d i n l a t e r
f i r m w a r e r e l e a s e s t o s u p p o r t t h e PWMo u t p u t and
LEDG o g g l e s .
100
*/
// / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
/*
* Program f l o w :
*
* When 256Hz t i m e r e x p i r e s : g o t o ISR ( TIMER0_OVF_vect )
* ISR ( TIMER0_OVF_vect ) e n a b l e s t h e ADC
*
* R e p e a t f o r e a c h c h a n n e l i n t h e ADC:
* S a m p l i n g s t a r t s . When i t c o m p l e t e s : g o t o ISR ( ADC_vect )
* ISR ( ADC_vect ) r e a d s t h e s a m p l e and r e s t a r t s t h e ADC.
*
* ISR ( ADC_vect ) w r i t e s f i r s t b y t e t o UART 0 d a t a r e g i s t e r
* (UDR0) which s t a r t s t h e t r a n s m i s s i o n o v e r t h e s e r i a l p o r t .
*
* Repeat f o r each byte in packet :
* When t r a n s m i s s i o n b e g i n s and UDR e m p t i e s :
* g o t o ISR ( USART0_UDRE_vect )
*
* S t a r t o v e r from b e g i n n i n g .
*/
# i n c l u d e < a v r / i o . h>
# i n c l u d e < i n t t y p e s . h>
# i n c l u d e < a v r / i n t e r r u p t . h>
# d e f i n e NUMCHANNELS 16
# d e f i n e HEADERLEN 3
/ / 2 C h a n n e l s s h a r e 3 B y t e s i n P a c k e t + 3 B y t e s HEADERLEN
/ / + 1 Byte f o r t h e f o o t e r
# d e f i n e PACKETLEN ( ( ( NUMCHANNELS/ 2 ) * 3 ) + HEADERLEN + 1 )
# d e f i n e SAMPFREQ 256
101
/ * * Sampling t i m e r ( t i m e r 0) i n t e r r u p t h a n d l e r * /
ISR ( TIMER0_OVF_vect )
{
/ / Reset timer to get c o r r e c t sampling frequency .
TCNT0 = TIMER0VAL ;
/ / Reset channelcounter
CurrentCh = 0;
i = 4;
/ / Increase packet counter ( t h i r d byte in header )
TXBuf [ 2 ] + + ;
/ / Get s t a t e o f s w i t c h e s on PA3 . . 6 ,
/ / i f any ( l a s t b y t e i n p a c k e t ) .
TXBuf [ ( ( NUMCHANNELS/ 2 ) * 3 ) + HEADERLEN] =
( PINA >> 3 ) &0x0F ;
/ / E n s u r e UART IRQ s a r e d i s a b l e d .
102
/ * * ADc o n v e r s i o n c o m p l e t e i n t e r r u p t h a n d l e r . * /
ISR ( ADC_vect )
{
i f ( ( C u r r e n t C h % 2 ) == 0 )
{
TXBuf [ i 1] = ADCL;
TXBuf [ i ] = ADCH;
}
else
{
TXBuf [ i + 1 ] = ADCL;
TXBuf [ i ] | = (ADCH << 6 ) ;
i += 3 ;
}
/ / Increase channel counter
C u r r e n t C h ++;
i f ( C u r r e n t C h < NUMCHANNELS)
{
/ / Select the next channel .
/ / I f t h e c h a n n e l number ( n o t t h e c o u n t e r )
/ / i s l o w e r t h a n 8 , t h e MUX5 b i t h a s t o be c l e a r e d
i f ( channel_order [ CurrentCh ] < 8)
103
104
105
}
i n t main ( v o i d )
{
/ / Write packet header
TXBuf [ 0 ] = 0 xa5 ;
TXBuf [ 1 ] = 0 x5a ;
TXBuf [ 2 ] = 0 x00 ;
/ / Sync 0
/ / Sync 1
/ / Packet counter
/ / S e t up t h e p o r t s .
/ / Write a 1 f o r pin i s output , 0 f o r pin i s i n p u t
DDRA = 0 x00 ;
DDRB = 0 x60 ;
DDRC = 0 x00 ;
DDRD = 0 x70 ;
DDRE = 0 x02 ;
DDRG = 0 x00 ;
DDRH = 0 x00 ;
DDRJ = 0 x00 ;
DDRL = 0 x00 ;
/ / A c t i v a t e p u l l up r e s i s t o r f o r a l l p i n s t h a t a r e i n p u t s
PORTA = 0 x f f ;
PORTB = 0 x f f ;
PORTC = 0 x f f ;
PORTD = 0 x f f ;
PORTE = 0 x f f ;
PORTG = 0 x f f ;
PORTH = 0 x f f ;
PORTJ = 0 x f f ;
PORTL = 0 x f f ;
/ / S e l e c t s l e e p mode = i d l e .
SMCR | = ( 1 << SE ) ;
SMCR &= ~ ( ( 1 << SM0) | ( 1 << SM1) | ( 1 << SM2 ) ) ;
106
/ / I n i t i a l i z e t h e ADC
//
//
//
//
//
//
//
//
//
T i m i n g s f o r s a m p l i n g o f one 10 b i t ADv a l u e :
p r e s c a l e r > ( ( XTAL / 200 kHz ) = 5 5 . 2 9 6 =>
p r e s c a l e r = 64 ( ADPS2 = 1 , ADPS1 = 1 , ADPS0 = 0 )
ADCYCLE = XTAL / p r e s c a l e r =
172800Hz o r 5 . 7 8 7 u s / c y c l e
14 ( s i n g l e c o n v e r s i o n ) c y c l e s =
81 ,01 us (12344 samples / sec )
26 ( 1 s t c o n v e r s i o n ) c y c l e s = 1 5 0 . 4 6 u s
/ / Select channel 0
ADMUX &= ~ ( ( 1 << MUX0) | ( 1 << MUX1) | ( 1 << MUX2)
| ( 1 << MUX3) | ( 1 << MUX4 ) ) ;
ADCSRB &= ~ ( 1 << MUX5 ) ;
/ / P r e s c a l e r = 6 4 , f r e e r u n n i n g mode = o f f , i n t e r r u p t s o f f .
ADCSRA | = ( 1 << ADPS2 ) | ( 1 << ADPS1 ) ;
/ / R e s e t any p e n d i n g ADC i n t e r r u p t s
ADCSRA | = ( 1 << ADIF ) ;
/ / E n a b l e t h e ADC
ADCSRA | = ( 1 << ADEN ) ;
/ / I n i t i a l i z e t h e USART
UBRR0H = 0 x00 ;
/ / S e t s p e e d t o 115200 b p s
UBRR0L = 0 x05 ;
UCSR0A = 0 x00 ;
UCSR0C | = ( 1 << UCSZ01 ) | ( 1 << UCSZ00 ) ;
UCSR0B | = ( 1 << TXEN0 ) ;
/ / I n i t i a l i z e timer 0
TCNT0 = 0 x00 ;
/ / Clear i t .
107
108