You are here

SD-Karte als Massenspeicher an einem Atmel AVR Microcontroller (SD-Experiment)

Error message

Deprecated function: Array and string offset access syntax with curly braces is deprecated in include_once() (line 20 of /mnt/web216/e3/48/5667948/htdocs/includes/file.phar.inc).

1. Projektziel

Ziel dieses Freizeitprojektes, das ich an verschiedenen anderen Stellen als das SD-Experiment bezeichne, ist es, einerseits physisch eine SD-Karte mit einem Microcontroller zu verbinden und andererseits diesen Massenspeicher dann auch von Programmen, die auf dem Microcontroller laufen, zu nutzen. Dabei sollten vor dem Hintergrund einer möglichst starken Vereinfachung auch Beschränkungen hingenommen werden.

Konkret basiert die Implementierung auf einem ATMEL megaAVR-Controller mit wenigstens 2 kB RAM.

Eine erste Anwendung zielte daraufhin ab, über verhältnismäßig lange Zeiträume (Tage, Wochen, Monate) die Ergebnisse des eingebauten Digital-Analog-Wandlers auf der SD-Karte aufzuzeichnen, um sie später auf einem PC auswerten zu können.

Eine entscheidende Nebenbedingung bleibt immer die Forderung, daß die verwendeten Komponenten für Amateure und engagierte Bastler leicht zu beschaffen sind und daß keine unüberwindliche Hürden durch die Verwendung von SMD-Bauelementen entstehen. Ganz vermeiden lassen sich SMD-Bauelemente aber nicht!

Recherchiert man heute im Web, so findet man eine große Menge von Vorschlägen und Beschreibungen, die in die selbe Richtung abzielen. Selbst als ich die ersten Überlegungen zu diesem Thema anstellte, gab es bereits genügend Material. Es wäre also verhältnismäßig leicht gewesen, die notwendigen Ideen und Anregungen zusammenzutragen, zu untersuchen, zu bewerten und abschließend zusammenzufügen um zu einer ähnlichen, vielleicht sogar leistungsfähigeren Lösung zu gelangen. Das hätte mir nicht so viel Spaß gemacht, denn sonst hätte ich es ja getan. Für mich lag die Herausforderung eher darin, basierend nur auf der Kenntnis des Protokolls der SD-Karte und des File-System (beides natürlich auch im Web recherchiert) sowie natürlich aufgrund der Vertrautheit mit dem gewählten Microcontroller die Anwendung aus eigener Kraft zu realisieren. In gewissem Sinn also from scratch.

2. Die physische Anbindung der SD-Karte

SD-Karten [1],[2],[3] kennen mehrere Betriebsarten im Sinne der Datenübertragung, von denen uns hier nur der SPI-mode weiter interessiert. Er ist in den Spezifikationen offengelegt und speziell für den Einsatz in Microcontroller ausgelegt. Maxim seigt in seiner Application Note 3969 [4] wie eine Firmware in C geschrieben aussehen könnte, um eine SD-Karte zu nutzen. Ohne jetzt an dieser Stelle auf alle Details eingehen zu wollen, möchte ich hier ein paar Bemerkungen zur Pinbelegung anbringen. Im SPI-mode werden von den neun vorhandenen Pins (oder Pads) nur sieben benutzt werden. Masse kommt sogar zweimal vor, sodaß nur sechs unterschiedliche Signale incl. Stromversorgung benötigt werden. Die anderen Pins belegen die Signale data-in, data-out, shift-clock und chip-select. Es liegt auf der Hand daß die Gegenstücke auf der Seite des Controllers MOSI, MISO und SCLK sind, die der SPI-Schnittstelle zugeordnet sind. Zumindest ist das die Bezeichnung, die Atmel gewählt hat. Chip-select liegt dann auf einem freien I/O-Port.

Die Microcontroller der Atmel megaAVR-Familie unterstützen standardmäßig den SPI-mode. Allerdings werden die selben Leitungen auch dazu benützt, den Controller im eingebauten Zustand neu zu programmieren (In System Programming - ISP-mode). Dies erzwingt einen Multiplexer (Umschalter), der im Normalbetrieb die SD-Karte an die SPI-ports (MISO, MOSI, SCLK) legt und im Falle der Neuprogrammierung die SD-Karte abtrennt und die Leitungen des Programmierers (ISP-Header) auf den Controller legt. Eine gängige Lösung benutzt dazu einen 4053. Es geht hauptsächlich darum, zu verhindern, daß zwei Ausgänge, nämlich data-out der SD-Karte und MOSI des Programmers zufällig aufeinandertreffen.

SD-Karten werden typischerweise mit 3,3 V betrieben, während ich mich dazu entschieden habe, den Microcontroller mit 5 V zu betreiben (würde ich heute sicher nicht mehr machen). Das erzwingt eine Pegelanpassung, weil die Eingangsleitungen zur SD-Karte nicht 5 V tolerant sind. Also ist eine weitere Verkomplizierung neben dem Multiplexer notwendig. Zur Pegelanpassung wurde ein 74LVX125 verwendet, der mit 3,3 V betrieben wird. Sein wesentliches Merkmal ist, daß seine Engänge 5 V tolerant sind.

Neben den Leitungen, die zur SD-Karte führen, gibt es noch zwei weitere Leitungen, die auf den SD-Karten-Sockel führen: nämlich die card-detect Leitung und die write-protect Leitung. Sie dienen dazu, wie die Namen schon sagen, das physische Vorhandensein einer Karte im SD-Sockel und die Stellung des Schreibschutzschiebers zu signalisieren.

Abschließend wurde noch eine Steuerleitung vorgesehen, die es ermöglicht, die Betriebsspannung der SD-Karte ein- und auszuschalten. Dies ist notwendig, weil im Zweifelsfall die SD-Karte nur dadurch in einen definierten Anfangszustand zu bringen ist, wenn ihre Betriebsspannung aus- und wieder eingeschaltet wird. Ein klassischer power-on-reset also.

Es ergeben sich einige Verinfachungen, wenn man den Controller mit 3,3 V betreibt. Dann fällt der Pegelwandler weg und man kann sogar auf den Multiplexer verzichten, wenn man dafür sorgt, daß niemals eine SD-Karte und der Programmierer gleichzeitig angeschlossen ist.

3. Die gesamte Schaltung

Dergesamte Schaltplan (siehe auch [10]) erstreckt sich über zwei Seiten (Seite 1, Seite 2) und umfaßt die folgenden Komponenten:

  1. Microcontroller (ATMEL ATmega32L [7])
  2. ISP/SPI-Multiplexer (74HC4053)
  3. Pegelwandler von 5 nach 3,3 V (74LVX125)
  4. Ein I2C-parallel-Port zur Überwachung und Steuerung diverser Signale (u.a. card detct, write protect und Stromversorgung der SD-Karte (PCF8574A)
  5. Ein I2C-parallel-Port zum Anschluß von bis zu 8 Leuchtdioden oder bis zu 4 Tastern (PCF8574A)
  6. Ein LCD-Interface zu Anschluß eine LC-Displays
  7. Ein USB nach Seriell Umsetzer (FT232BL)
  8. Eine I2C-Echtzeituhr mit Batteriepufferung (PCF8583)
  9. Ein Spannungsregler für 3,3 V und 5,0 V (TDA8139)
  10. Zwei Analogverstärker mit nachfolgenden Tiefpassfiltern, die auf ADC6 und ADC7 führen (LT1490 [5], MAX7400 [6])
  11. Ein Funkuhrenmodul
  12. Ein Piezo-Signalgeber
  13. Eine Reihe von Pfostenleisten, die auf die Ports des Controllers und andere periphere Komponenten führen

Einige der genannten Komponenten sind optional (etwa USB); andere werden Stand heute auch noch nicht von der Firmware unterstützt (etwa das LC-Display). Es hängt letztlich von der konkreten Anwendung ab, was von den vorhandenen peripheren Komponenten benutzt werden soll.

Im folgenden sind neben den beiden Seiten des Schaltplanes einige Bilder der Platine im bestückten Zustand zu sehen:

Schaltplan - Teil 1 Schaltplan - Teil 2 Die bestückte Platine von oben Die Platine von schräg oben
Die Platine von schräg vorne Die Platine von der Lötseite Schaltplan - Teil 1 Schaltplan - Teil 2

Der Analogteil: Er setzt sich aus zwei Komponenten zusammen: nämlich aus einem OP-Verstärker (LT1490, [5]), der auf eine Verstärkung von 100 eingestellt ist und einem Tiefpaßfilter (MAX7400, [6]), dessen Grenzfrequenz etwas weniger als die halbe Abtastrate eines ADC-Kanals sein soll. Die Abtastrate sollte so bemessen sein, daß bei Nutzung aller acht Analog-Digital-Kanäle eine 1 GB SD-Karte nach etwas mehr als einer Woche voll ist. Dabei sollten keine Komprimierungsverfahren zur Anwendung gelangen. Die Größenordnung ist dann 100 Messungen pro Sekunde und pro ADC-Kanal. Die Grenzfrequenz des Tiefpasses ist dann etwas unter 50 Hz. Das ist sehr praktisch, weil dann auch die Netzfrequenz gut unterdrückt wird. ADC6 und ADC7 wurden mit Vorverstärker und Tiefpaß ausgestattet; die anderen Kanäle des Analog-Digital-Wandlers nicht.

Die Eingangssignale auf den OP-Verstärker sind sowohl positiv als auch negativ und sie reichen herab bis zu 0 Hz. Die Betriebsspannung ist aber nicht symmetrisch. Negative Eingangsspannungen bezogen auf 0 V würden sich also garnicht verarbeiten lassen. Daher wurde eine 'virtuelle' Null realisiert (R19, R20), die auf halber Betriebsspannung (2,5 V) liegt. Liegt kein Signal an, so liefert der OP-Verstärker an seinem Ausgang ebenfalls 2,5 V, die ihrerseits den Tiefpaß unverändert passieren und dann auf einen ADC-Kanal gelangen. Der ADC des Controllers hat 10 bit Auflösung; 0 V entspricht dann auch dem Wert 0 des ADC, 5 V ist dann 1024 oder 0x0400 (gerade eins zu viel und somit gerade nicht mehr darstellbar) und 2,5 V ist dann genau 512 (0x0200). Das heiß 0 bis 511 repräsentiern negative Werte und 513 bis 1023 stehen für positive Werte. Die 'Mitte' ist allerdings nur im Idealfall bei 512. Wo sie wirklich liegt hängt von der Genaugkeit der beiden Widerstände R19 und R20 ab sowie vom Offset-Fehler des verwendeten OP-Verstärkers. Dieser steigt mit zunehmender Verstärkung. Da keine Offset-Kompensation vorgesehen ist, sind Verstärkungen von deutlich über 100 nicht mehr praktikabel. Die Null liegt dann schnell bei 1 V oder 4 V und der Aussteuerungsbereich wird massiv unsymmetrisch beschnitten. Ansonsten ist die gewählte Verstärkung von 100 ein recht willkürlicher Wert.

Der Tiefpaß ist ein 'switched capacitor'-Filter, dessen Grenzfrequenz sich ausschließlich aus der Taktfrequenz ergibt, die dem Filter zugeführt wird. Das Verhältnis aus Taktfrequenz und Grenzfrequenz ist 100 - d.h. wenn die Grenzfrequenz 40 Hz sein soll, so muß der Takt eine Frequenz von 4 kHz haben. Der Takt wird im Controller erzeugt und dem Pin OC0, der zum Timer/Counter 0 gehört, entnommen. Damit ist der Takt programmierbar und kann leicht auf die benötigten Verhältnisse eingestellt werden.

4. Die Firmware

Die notwendige Firmware (die jeweils aktuelle Verion ist in [9] zu finden) wurde in C (WinAVR zusammen mit AVRStudio 4) entwickelt. Im wesentlichen wurde versucht, sie in Software-Layern zu organisieren und dadurch klare Zuständigkeiten zu definieren. Beispielweise wird der unterste Layer die Kommunikation mit der konkreten Hardware durchführen. Im einzelmen gibt es folgende Layer:

  1. die Anwendung
  2. Die öffentlichen Funktionen des Filesystems
  3. Die privaten internen Funktionen eines einfaches FAT16 Filesystems
  4. Die internen C-Funktionen, die die Funktionen auf der SD-Karte repräsentieren (Proxy)
  5. Primitive Kommunikation mit der SD-Karte und ihrem Umfeld (Adapter - hardwareabhängig)

Es liegt auf der Hand, daß die drei 'inneren' Layer in einer hardwareunabhängigen Bibliothek veröffentlicht werden können. Gedanklich wurde auch hier so verfahren. Die hardwareabhängigen Anteile wurden mittels callback-Funktionen realisiert, die vor der ersten Verwendung beim zweituntersten Layer registriert werden. Die folgenden Unterkapiltel behandeln die einzelnen Layer bzw. Funktionsblöcke.

Neben dem Coding für die Anwendung, die hier ein Datenlogger ist, werden die in der folgenden Tabelle aufgeführten Quellfiles benötigt und hier behandelt.

C-FileH-FileBeschreibung
SD_api.cSD_api.hVerschalung der SD-Karten-Funktionen als C-Funktionen
SD_interface.cSD_interface.hIm wesentlichen die Funktionen, die die SPI-Schnittstelle bedienen
FAT16.cFAT16.hEine Untermenge des FAT16-Filesystems
.c.hFortsetzung folgt ...

4.1 Die elementaren Funktionen der SD-Karte (SD_api.c/SD_api.h)

Im folgenden möchte ich nochmal darauf hinweisen, daß wesentliche Teile dieser Funktionen aus [4] entnommen wurden. Ich habe sie nicht selbst erfunden. Einiges wurde jedoch den speziellen Bedürnissen dieses Projektes angepaßt, aber der Kern der Routinen blieb erhalten.

Der folgende Auszug zeigt die wichtigsten Elemente des Header-Files. Die Definition von Konstanten wurde weggelassen.

  1. #include <stdint.h>
  2.  
  3. #define BLOCK_BUFFER_LEN 515
  4. uint8_t rxbuf[BLOCK_BUFFER_LEN];
  5.  
  6. /* here the public functions */
  7. int SD_init(int retries);
  8. int SD_get_cid(void);
  9. int SD_get_csd(void);
  10. int SD_readblock(uint32_t blocknr);
  11. int SD_writeblock(uint32_t blocknr);
  12.  
  13. /* and here the registration of hardware dependent callback functions */
  14. void SD_set_callbacks(uint8_t (*exchange_data)(uint8_t data),
  15. void (*exchange_data1)(uint8_t data),
  16. uint8_t (*exchange_data2)(void),
  17. void (*set_fast_mode)(void),
  18. void (*set_normal_mode)(void),
  19. int (*get_card_insertion_status)(void) );

Der Datenaustasuch mit den Funktionen erfolgt im wesentlichen über den global verfügbaren Puffer rxbuf. Die ersten 512 byte stehen für die Daten eines Blocks während die drei verbleibenden bytes sowohl eine CRC16-Prüfsumme als auch eine CRC7-Prüfsumme aufnehmen. Der Rückgabewert der Funktion repräsentiert den Erfolg oder im Fehlerfall eine Information über den Grund des Miserfolgs. Die ersten fünf Funktionen dienen im einzelnen folgenden Zwecken:

  • Initialisierung der SD-Karte
  • Lesen des card identification register (CID) - Das Ergebnis belegt die ersten 15 bytes von rxbuf
  • Lesen des card specific data register (CSD) - Das Ergebnis belegt die ersten 15 bytes von rxbuf
  • Lesen eines Blocks mit der angegebenen Blocknummer - Das Ergebnis belegt die ersten 512 bytes von rxbuf
  • Schreiben eines Blocks mit der angegebenen Blocknummer - Die zu schreibenden Daten sind die ersten 512 bytes von rxbuf

Besondere Erwähnung verdient die letzte Funktion. Sie dient dazu, der SD_api die hardwarespezifischen Funktionen zur Verfügung zustellen, die der Kommunikation mit der SD-Karte dienen. Beispielsweise kann die konkrete Implementierung des SPI von Prozessortyp zu Prozessortyp variieren. Siehe auch 4.2. SD_api soll keinerlei Annahmen darüber treffen müssen, wie nun genau auf dem aktuellen Prozessor die SPI-Kommunikation funktioniert. Es genügt vollkommen, wenn zur Laufzeit SD_api eine Referenz auf die konkrete Implementierung erhält. Das ermöglichst es, die SD_api sogar in eine Bibliothek zu verlagern. Im einzelnen müssen, bevor zur Laufzeit eine Funktion der SD_api das erste mal benutzt wird, folgende callback-Funktionen registriert werden:

  • exchange_data: Kompletter Austausch eines bytes über das SPI. Ein byte wird gesendet und gleichzeitig wird eines empfangen. Es wird so lange gewartet, bis der Vorgang abgeschlossen ist.
  • exchange_data1: Sendet ein byte über das SPI
  • exchange_data2: Wartet, bis ein byte über das SPI empfangen wurde und gibt dies zurück
  • set_fast_mode: erlaubt es, die Geschwindigkeit des SPI zu erhöhen
  • set_normal_mode: setzt die Übertragungsgeschwindigkeit des SPI auf den normalen Wert zurück
  • get_card_insertion_status: ermittelt, ob eine SD-Karte überhaupt im SD-Slot vorhanden ist, und wenn ja, in welcher Stellung der Schreibschutzschieber ist

Die ersten drei Funktionen behandeln die SPI-Kommunikation. Vereinfacht kann man sagen, daß die zweite und dritte zusammen der ersten entspricht. Die Aufspaltung wurde deswegen durchgeführt, um während der Wartezeit auf den Eingang eines bytes andere sinnvollere Operationen ausführen zu können als immer nur das Statusbit des Empfangsregisters abzufragen. Intern wird also zuerst exchange_data1 aufgerufen, dann werden ein paar weitere Zeilen code abgearbeitet bevor dann auf jeden Fall exchange_data2 aufgerufen wird. Das fördert die Performance.

Während der Initialisierungsphase erwartet die SD-Karte eine gemäßigte Übertragungsgeschwindigkeit auf dem SPI. Wurde diese erfolgreich beendet, so kann man die Datenrate erhöhen. Die letzte Funktion ist offensichtlich.

Der Puffer rxbuf ist für eine Blockgröße von bis zu 512 bytes ausgelegt. Das stellt damit zur Zeit auch die Obergrenze dar, die von SD_api unterstützt wird. Experimente mit abweichenden Größen wurden nicht durchgeführt. Es ist allerdings davon auszugehen, daß SD-Karten mit 2 GB oder mehr nicht verwendet werden können, weil sie eine größere Blockgröße erfordern. 1 GB-Karten werden regelmäßig ohne Probleme verwendet.

4.2 Die callback-Funktionen für die SPI-Schnittstelle (SD_interface.c/SD_interface.h)

Um die SP_api überhaupt nutzen zu können, müssen einige Funktionen dort registriert werden, die der Kommunikation mit dem SPI dienen. Diese Funktionen sind hardwareabhängig und ihre Implementierung kann von Prozessortyp zu Prozessortyp variieren. Zunächst das Header-File:

  1. #include <stdint.h>
  2.  
  3. uint8_t xferSPI(uint8_t in);
  4. void xferSPI1(uint8_t in);
  5. uint8_t xferSPI2(void);
  6. void SD_set_fast_mode(void);
  7. void SD_set_normal_mode(void);
  8. int SD_card_insertion_status(void);
  9.  
  10. void SD_init_ports(void);
  11. void SD_SPI_off(void);

Die ersten sechs Funktionen entsprechen genau denjenigen, die die Funktion SD_set_callbacks erwartet. Darüber hinaus gibt es noch eine Funktion, die die benötigten Ports und das SPI initialisieren sowie eine letzte, die das SPI einfach abschaltet.

Die hardwareunabhängigen Funktionen in SD_api zusammen mit den hardwareabhängigen Funktionen in SD_interface ermöglichen es bereits, mit einer SD-Karte zu kommunizieren und Daten auszutauschen. An dieser Stelle bleibt es jedoch dem Anwender überlassen, nach welcher Strategie er die Blöcke auf der Karte befüllt. Um die Daten später auch auf einem PC auslesen zu können, wäre es wünschenswert, wenn die Strategie sich einem der gebräuchlichen Filesysteme anlehnen würde. Genau das wird im nächsten Unterkapitel behandelt.

4.3 Das FAT16-Filesystem für die SD-Karte (FAT16.c/FAT16.h)

Um nicht darauf angewiesen zu sein, die Blöcke der SD-Karte direkt zu beschreiben und um die Möglichkeit zu haben, die aufgezeichneten Daten einigermaßen komfortabel auf einen PC zu übertragen, wurde eine Implementierung des FAT16-Filesystems [8] geschaffen. Der folgende Auszug führt die realisierten Funktionen auf.

  1. struct ty_fat16_filename {
  2. unsigned char name[8];
  3. unsigned char extension[3];
  4. };
  5.  
  6. int fat16_init(void);
  7. int fat16_new_file(struct ty_fat16_filename *filename);
  8. int fat16_put(unsigned char c);
  9. int fat16_file_close(void);
  10. int fat16_open_file(struct ty_fat16_filename *filename);

Nicht aufgeführt sind hier alle Konstantendefinitionen (zumeist Fehlercodes) und einige Strukturdefinitionen sowie einige Funktionen für spezielle Zwecke. Die Bedeutung der aufgeführten Funktionen ist selbsterklärend:

  • fat16_init: Initialisierung
  • fat16_new_file: Anlegen eines neuen Files
  • fat16_put: Schreiben eines Bytes in das zuvor angelegte neue File
  • fat16_file_close: Schließen des zuvor angelegten Files (FAT schreiben und Directory aktualisieren)
  • fat16_open_file: Öffnen eines existierenden Files zum lesen - eine fat16_get-Funktion zum lesen von Daten aus dem geöffneten File fehlt noch.

Es ist - Stand heute - nicht vorgesehen, den Inhalt eines existierenden Files zu überschreiben oder Daten an ein existierendes File anzuhängen. Löschen wird ebenfalls nicht unterstützt. Diese Einschränkungen spielen aber für eine Datenrecorderanwendung keine allzugroße Rolle.

Eine wichtige Einschränkung ist, daß nur das Wurzelverzeichnis des Datenträgers, also der SD-Karte, genutzt werden kann. Unterverzeichnisse und die Dateien darin werden nicht berücksichtigt; sie sollten aber, falls vorhanden, zumindest nicht stören. Auch lange Dateinamen werden nicht unterstützt. Wird ein File neu angelegt, so wird als Datum und Uhrzeit fest der 25.05.2007 20:30 eingetragen. Die Echtzeituhr auf dem Board wird (noch) nicht verwendet. Außerdem kann nur maximal ein File gleichzeitig geöffnet sein.

5. Einschränkungen

Beschränkt man sich auf 2 kByte RAM im Controller, so muß man in Kauf nehmen, daß die Blockgröße der verwendeten SD-Karte 512 Byte sein muß. Nicht größer und nicht kleiner. Daraus ergibt sich, daß die SD-Karte nicht größer als 1 GByte sein darf (Das hängt allerdings hier von der Anwendung ab. Sie belegt einen großen Teil des RAM mit einem FIFO, der dazu dient, Meßdaten während der Zeit aufzunehmen, während der das File-System den aktuellen Block schreibt und ggf. den nächsten freien Cluster sucht). Die SD-Karte muß gemäß FAT-16 formatiert sein. Andere Filesysteme werden vom System abgelehnt. Benutzt wird nur das Hauptverzeichnis. Dateinamen werden nur im 8.3-Format verarbeitet. Unterverzeinisse werden nicht benutzt. Vermutlich werden sie aber nicht stören. Das Hauptverzeichnis muß noch wenigstens Platz für einen Eintrag haben. Sollen größere Datenmengen kontinuierlich über einen längeren Zeitraum geschrieben werden, dann sollte die FAT, außer beim suchen des ersten freien Clusters, nicht in größerem Umfang auf belegte Cluster treffen. Ideal ist es, eine leere, frisch formatierte SD-Karte zu verwenden. Die Firmware unterstützt nur das schreiben von Files. Lesen ist vorbereitet, aber mangels Eigenbedarf nicht implementiert. Das Hauptverzeichnis kann jedoch gelesen werden. Die Anwendung kann höchstens ein File gleichzeitig offen haben, welches Stand heute nur geschrieben werden kann. Die Informationen über Datum und Uhrzeit der letzten Änderung eines Files (hier des anlegens) ist momentan etwas statisch. Die RTC wird dazu noch nicht herangezogen. Die DCF77-Daten werden zwar aufgezeichnet, aber vom Controller nicht ausgewertet.

6. Ausblick

Die Erfahrungen, die mit den ersten Versuchen gesammelt worden sind zusammen mit einigen Bemerkungen, die weiter oben schon gefallen sind, könnte ich mir vorstellen, die Schaltung vor allem unter dem Aspekt der Betriebsspannung (alles mit 3,3 V betrieben) zu vereinfachen. Das geht sicher einher mit einer Verkleinerung der Platine ohne Verlust an Funktionalität. Weniger Komponenten und weniger Betriebsspannung sind eine gute Voraussetzung für den Versuch, die Schaltung aus einem Akku zu betreiben. Ziel wäre es, eine Woche mit einem NiMH-Akku mit vier Zellen (4,8 V) und 3000 mAh pro Zelle auszukommen. Im Umkehrschluß bedeutet das aber, daß 20 mA kontinuierliche Stromaufnahme bereits zu viel sind!

Was ich momentan eher nicht weiter verfolge, ist der Versuch, die Platine mit (weiteren) Bedienelementen auszustatten. Das soll alles recht spartanisch bleiben. Für ein neues Layout würde ich sogar auf den Anschluß eiens LC-displays verzichten. Damit werden Pins frei, die dann zur Steuerung des Umfeldes der SD-Karte genutzt werden können. Ob eine RTC in Anwesenheit eines DCF77-Moduls sinnvoll ist, wäre ebenfalls zu überprüfen.

Weiterentwicklungen in der Software bzw. der Firmware sind zum Glück eher unabhängig davon, wie die Hardware realisiert ist. Hier wäre sicher noch eine Funktion zum lesen von Files praktisch. Beispielsweise könnte ein File dazu dienen, Parameter zur Datenaufnahme in einer Logger-Anwendung aufzunehmen. Bevor die Messung startet, würde das File gesucht und gefunden werden und die Messung gemäß den Parametern durchgeführt. Etwa welche ADC-Kanäle sollen benutzt werden, wieviele Messungen pro Sekunde, welche Grenzfrequenz soll der Tiefpaß haben etc.

Es ist nicht gelant, mehrere Files gleichzeitig offen zu haben. Es ist auch nicht vorgesehen, an ein bereits geschlossenes File weitere Daten anzuhängen. Das zusammenführen von Meßdaten soll dann auf dem PC geschehen.

7. Referenzen und Links

Undefined