NEU
http://sites.schaltungen.at/arduino-kochbuch/kapitel-17-deutschWels, am 2015-04-26BITTE nützen Sie doch rechts OBEN das Suchfeld [ ] [ Diese Site durchsuchen]DIN A3 oder DIN A4 quer ausdrucken ********************************************************************************** DIN A4 ausdrucken ********************************************************* Englischsprachige ORIGINAL-Seiten 715_d_O'REILLY-x_Arduino Kochbuch - Kapitel 17 engl. (16 Seiten )_1a.pdf Auf dieser Seite die schlechte (nicht korrigierte) Maschinen-Übesetzung ins Deutsche Draht = Wire Stift = Pin Rezept = Sketch KAPITEL 17 Erweiterte Codierung und Speicher Handhabung 17.0 Einführung Wie Sie mit Ihrem Arduino mehr tun, müssen Sie Ihre Skizzen effizienter zu werden. Die Techniken, die in diesem Kapitel können Ihnen helfen, die Leistung zu verbessern und den Code zu reduzieren Größe Ihrer Skizzen. Wenn Sie brauchen, um Ihre Zeichnung schneller laufen oder benutzen Sie weniger RAM, die hier Rezepte helfen können. Die Rezepte sind hier eher technische als die meisten anderen Rezepten in diesem Buch, weil sie Dinge, die in der Regel von der freundlichen Arduino verborgen sind decken Wrapper. Das Arduino Build-Prozess wurde entwickelt, um komplexe Aspekte der C und C ++ zu verbergen, wie sowie die verwendeten Werkzeuge, um eine Skizze in die Bytes, die hochgeladen werden, und führen Sie auf konvertieren ein Arduino Board. Aber wenn Ihr Projekt Performance und Ressourcenbedarf über die Fähigkeit der Standard-Arduino-Umgebung, sollten Sie die Rezepte finden hier sinnvoll. Das Arduino-Board verwendet den Speicher zur Speicherung von Informationen. Es verfügt über drei Arten von Speicher: Programmspeicher, einen Direktzugriffsspeicher (RAM) und EEPROM. Jeder hat andere Eigenschaften und Verwendungen. Viele der Techniken in diesem Kapitel behandeln, was zu tun, wenn Sie haben nicht genug von einer Art von Speicher. Programmspeicher (auch als Flash bekannt) ist in dem die ausführbare Skizze Code gespeichert ist. Der Inhalt des Programmspeichers kann nur durch den Bootloader im Upload geändert werden Prozess von der Arduino-Software auf Ihrem Computer ausgeführt eingeleitet. Nach dem Upload Prozess abgeschlossen ist, kann der Speicher nicht bis zur nächsten Upload geändert werden. Es gibt weit mehr Programmspeicher auf einem Arduino-Board als RAM, so dass es von Vorteil sein können Speichern von Werten, die sich nicht ändern, während der Code ausgeführt wird (zB Konstanten) im Programmspeicher. Der Bootloader nimmt etwas Platz im Programmspeicher. Wenn alle anderen Versuche zur Minimierung der Code, um im Programmspeicher passen gescheitert sind, der Bootloader kann entfernt werden um Platz zu schaffen, sondern eine zusätzliche Hardware-Programmierer wird dann benötigt, um Code zu bekommen auf die Platine. Wenn Ihr Code ist größer als der Programmspeicher auf dem Chip, die Upload- wird nicht funktionieren und die IDE wird Sie warnen, dass die Skizze ist zu groß, wenn Sie kompilieren. RAM wird durch den Code verwendet, wie es läuft, um die Werte für die Variablen durch verwendet speichern Sie Ihre skizzieren (einschließlich Variablen in den durch die Skizze verwendet Bibliotheken). RAM ist flüchtig, die bedeutet, dass es durch den Code in Ihre Skizze geändert werden. Es bedeutet auch, nichts in dieser gespeicherte Speicher verloren geht, wenn der Strom abgeschaltet wird. Arduino hat viel weniger RAM als Programm Speicher. Wenn Sie aus dem RAM ausgeführt werden, während die Skizze läuft auf dem Board (wie Variablen erstellt und zerstört, während der Code ausgeführt wird) das Board schlecht benehmen (Absturz). EEPROM (elektrisch löschbarer programmierbarer Nur-Lese-Speicher) ist ein Speicher, Code auf Arduino laufen kann lesen und schreiben, aber es ist nicht-flüchtigen Speicher, die Werte bewahrt auch wenn das Gerät ausgeschaltet ist. EEPROM-Zugriff ist deutlich langsamer als für RAM, so EEPROM ist in der Regel zum Speichern von Konfigurations oder andere Daten, die beim Start gelesen wird verwendet, Informationen aus der vorherigen Sitzung wiederherzustellen. Um diese Probleme zu verstehen, ist es hilfreich zu verstehen, wie die Arduino IDE bereitet Ihr Code auf den Chip zu gehen und wie Sie die Ergebnisse es produziert zu inspizieren. Preprocessor Einige der Rezepte verwenden hier den Präprozessor, um das gewünschte Ergebnis zu erzielen. Vorverarbeitung ist ein Schritt in der ersten Stufe des Build-Prozesses, in dem der Quellcode (Skizze) ist für die Zusammenstellung vorbereitet. Verschiedene Suchen und Ersetzen-Funktionen durchgeführt werden. Preprocessor Befehle werden von Zeilen, die mit # beginnen identifiziert. Sie haben bereits gesehen in Skizzen, die eine Bibliotheks- # verwenden gehören teilt dem Präprozessor, um den Code von einfügen die Namen Bibliotheksdatei. Manchmal ist der Präprozessor ist der einzige Weg, um zu erreichen, was ist benötigt, aber die Syntax ist anders als C und C ++ Code, und es können Fehler einführen, dass sind subtil und schwer aufzuspüren, so verwenden Sie es mit Sorgfalt. Siehe auch Avrfreaks ist eine Website für Software-Ingenieure, die eine gute Quelle für technische Detail ist auf den Controller-Chips von Arduino verwendet: http://www.avrfreaks.net Technische Details auf der C-Präprozessor finden Sie unter http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html Die Speicherspezifikationen für alle offiziellen Karten können auf der Arduino-Website gefunden werden. http://www.arduino.cc/en/Main/Products?from=Main.Hardware . 17.1 Verständnis der Arduino Build-Prozess Problem Sie wollen sehen, was sich unter der Decke passiert, wenn Sie kompilieren und laden ein Skizze. Seite 584 | Kapitel 17: Erweiterte Codierung und Speicher Handhabung Lösung Sie können wählen, um alle Befehlszeilen Aktivität, die bei der Zusammenstellung stattfindet anzuzeigen oder Hochladen einer Skizze über den Dialog Einstellungen im Arduino 1.0 aufgenommen. Wählen Datei → Einstellungen, um das Dialogfeld anzuzeigen, um aktivieren oder deaktivieren Sie die Kontrollkästchen aktivieren ausführliche Ausgabe zu kompilieren oder Upload-Nachrichten. In Versionen vor 1.0 können Sie bei gedrückter Shift-Taste gedrückt, wenn Sie auf Kompilieren klicken oder Laden. Die Konsolenbereich im unteren Teil des IDE wird Details der Kompilierung angezeigt Prozess. In Versionen vor 1.0, um einen Wert in der Arduino Preferences.txt ändern müssen Sie Datei dieses Detail immer sichtbar zu machen. Diese Datei sollte in den folgenden Standorten: Windows XP C:\Documents and Settings\<USERNAME>\Application Data\Arduino\preferences.txt Sicherstellen, dass der Arduino IDE nicht läuft (Änderungen vorgenommen, um Preferences.txt somit nicht gespeichert, wenn die IDE läuft). Öffnen Sie die Datei, und suchen Sie die Zeile build.verbose = false (es ist nahe dem Ende der Datei). Ändern Sie false auf true und die Datei speichern. Diskussion Wenn Sie auf Kompilieren und Hochladen klicken, eine Menge von Aktivitäten vor, dass in der Regel nicht auf dem Bildschirm angezeigt. Die Kommandozeilen-Tools, die die Arduino IDE wurde gebaut, um zu verbergen werden dazu verwendet, kompilieren, linken und laden Sie Ihren Code auf dem Brett. Erste Skizze Datei (en) in eine geeignete für den Compiler-Datei umgewandelt (avrgcc) herstellen. Alle Quelldateien in der Skizze Ordner, die keine Dateierweiterung sind zusammen, um eine Datei zu machen. Alle Dateien, die in .c oder .cpp enden werden separat erstellt. Header-Dateien (mit der Erweiterung von H) werden ignoriert, sofern sie nicht ausdrücklich in die mitgelieferte Dateien, die miteinander verbunden sind. #include <Arduino.h> (WProgram.h in früheren Versionen) am Anfang der Datei hinzu die Header-Datei mit allen Arduino spezifische Codedefinitionen wie gehören digitalWrite () und analogRead (). Wenn Sie, um den Inhalt zu untersuchen möchten, können Sie die Datei finden kann Windows unter dem Verzeichnis, in dem Arduino installiert wurde; von dort aus können Sie Navigieren Sie Hardware → Arduino → Kerne → Arduino. 17.1 Das Verständnis der Arduino Build-Prozess | Seite 585 Das Arduino-Verzeichnis-Struktur kann in neue Versionen geändert, so überprüfen die Dokumentation der von Ihnen verwendeten Version. Um den Code gültig C ++ zu machen, die Prototypen von Aufgaben in Ihrem Code, angegeben werden, erzeugt nächsten und eingefügt. Schließlich ist die Einstellung der Pensionsmenü wird verwendet, um Werte einfügen (aus der erhaltene boards.txt Datei), die verschiedenen Konstanten für die Controller-Chips auf dem ausgewählten verwendet definieren Bord. Diese Datei wird dann von AVR-GCC, die innerhalb des Arduino Haupt enthalten kompiliert Download (im Ordner Tools ist). Der Compiler produziert eine Reihe von Objektdateien (Dateien mit der Erweiterung .o das wird durch den Link-Tool kombiniert werden). Diese Dateien befinden sich im Verzeichnis / tmp auf Mac und Linux gespeichert. Auf Fenster, sie sind in der Applet-Verzeichnis (ein Ordner unter dem Arduino-Installationsverzeichnis). Die Objektdateien werden dann zusammen, um einen Hex-Datei zu machen, um auch direkt hochladen verbunden. Avrdude, ein Dienstprogramm für die Übertragung von Dateien auf das Arduino-Controller, wird verwendet, um den Upload die tafel. Die zur Herstellung des Build-Prozess zu implementieren Werkzeuge können in der Hardware \ Tools gefunden werden Verzeichnis. Ein weiteres nützliches Tool für erfahrene Programmierer ist avr-objdump, auch im Ordner Tools. Damit können Sie sehen, wie der Compiler macht die Skizze in Code, den der Controller-Chip läuft. Dieses Tool erzeugt eine Demontage Auflistung Ihrer Skizze, die den Objekt-Code zeigt, mit dem Quellcode vermischt. Es kann auch ein Speicherabbild aller Variablen angezeigt werden in Ihrer Skizze verwendet. Um das Tool zu verwenden, kompilieren Sie die Skizze, und navigieren Sie zu dem Ordner, mit dem Arduino Verteilung. Dann navigieren Sie zum Ordner mit allen Zwischen Dateien in den Build-Prozess verwendet werden (wie bereits erläutert). Die von verwendeten Datei avr-objdump ist der mit der Verlängerung .elf. Zum Beispiel, wenn Sie die Blink kompilieren skizzieren Sie könnten die kompilierte Ausgabe (der Maschinencode) angezeigt werden durch Ausführen der folgenden in der Befehlszeile: ..\hardware\tools\avr\bin\avr-objdump.exe -S blink.cpp.elf Es ist bequem, die Ausgabe in eine Datei, die in einem Texteditor gelesen werden kann lenken. Sie können tun dies wie folgt: ..\hardware\tools\avr\bin\avr-objdump.exe -S blink.cpp.elf > blink.txt Seite 586 | Kapitel 17: Erweiterte Codierung und Speicher Handhabung Diese Version bringt eine Liste der Abschnittsüberschriften (hilfreich für die Bestimmung der Speichernutzung): ..\hardware\tools\avr\bin\avr-objdump.exe -S -h blink.cpp.elf > blink.txt Sie können eine Batch-Datei, um die Liste in eine Datei auszug erstellen. Fügen Sie den Pfad Ihrer Arduino-Installation auf die folgende Zeile und speichern Sie sie auf einem Stapel Datei: hardware\tools\avr\bin\avr-objdump.exe -S -h -Tdata %1 > %1%.txt Siehe Auch Für Informationen über die Arduino Build-Prozess finden http://code.google.com/p/arduino/wiki/BuildProcess http://www.avrfreaks.net/wiki/index.php/Documentation:AVR_GCC 17.2 Bestimmung der Höhe der freien und belegten RAM Problem Sie wollen sicher sein, dass Sie nicht von RAM. Eine Skizze wird nicht korrekt ausgeführt werden, wenn nicht genügend Speicherplatz, und das kann schwer zu erkennen sein. Lösung Dieses Rezept zeigt Ihnen, wie Sie die Menge des freien Speichers zur Verfügung, um zu bestimmen Ihre Skizze. Diese Skizze enthält eine Funktion namens memoryFree, die die Menge Berichte verfügbarer RAM: void setup() { Serial.begin(9600); } void loop() { Serial.print(memoryFree()); // print the free memory Serial.print(' '); // print a space delay(1000); } // variables created by the build process when compiling the sketch extern int __bss_end; extern void *__brkval; // function to return the amount of free RAM int memoryFree() { int freeValue; if((int)__brkval == 0) freeValue = ((int)&freeValue) - ((int)&__bss_end); else freeValue = ((int)&freeValue) - ((int)__brkval); return freeValue; } 17.2 Bestimmung der Höhe der freien und belegten RAM | Seite 587 Diskussion Die memoryFree Funktion verwendet die Systemvariablen, die Menge an RAM berechnen. System Variablen sind normalerweise nicht sichtbar (sie vom Compiler erstellt werden, um zu verwalten interne Ressourcen). Es ist nicht notwendig, zu verstehen, wie die Funktion arbeitet, um seine Ausgabe zu verwenden. Die Funktion gibt die Anzahl der Bytes des freien Speichers. Die Anzahl der Bytes Ihr Code ändert sich der Code ausgeführt wird. Das Wichtigste ist, um sicherzustellen, dass Sie mehr Speicher, als Sie nicht verbrauchen. Hier sind die wichtigsten Möglichkeiten, RAM-Speicher verbraucht wird: • Wenn Sie Konstanten initialisieren: #define ERROR_MESSAGE "an error has occurred" • Wenn Sie erklären, globale Variablen: char myMessage[] = "Hello World"; • Wenn Sie einen Funktionsaufruf: void myFunction(int value) { int result; result = value * 2; return result; } • Wenn Sie dynamisch Speicher zuweisen: String stringOne = "Arduino String"; Das Arduino String-Klasse verwendet dynamische Speicher, um Platz für Zeichenfolgen zuweisen. Sie können finden Sie dies, indem Sie die folgende Zeile an die Spitze des Codes in der Lösung: String s = "\n"; und die folgenden Zeilen direkt vor der Verzögerung in der Schleife Code: s = s + "Hello I am Arduino \n"; Serial.println(s); // print the string value Sie werden sehen, der Speicherwert als die Größe des Strings zu reduzieren wird jedes Mal erhöht durch die Schleife. Wenn Sie die Skizze lange genug ausführen, wird der Speicher aus-nicht laufen endlos versuchen, die Größe einer Zeichenkette in einer anderen als einer Testanwendung zu erhöhen. Seite 588 | Kapitel 17: Erweiterte Codierung und Speicher Handhabung Schreiben von Code, wie diese, die ein ständig wachsWert schafft, ist ein sicherer Weg zu laufen aus dem Speicher. Sie sollten auch darauf achten, nicht-Code, der dynamisch erzeugt erstellen eine unterschiedliche Anzahl von Variablen basierend auf einige Parameter, während der Code ausgeführt wird, da es sehr schwierig sein, sicher sein, Sie werden die Speichermöglichkeiten des Boards nicht überschreiten wenn der Code ausgeführt wird. Konstanten und globale Variablen werden oft in Bibliotheken erklärt als gut, so können Sie nicht sich bewusst sein, aber sie benutzen immer noch RAM. Der serielle Bibliothek hat zum Beispiel einen 128 Byte-Array, das globale es für eingehende serielle Daten verwendet. Dies allein verbraucht ein Achtel des Gesamtspeichers eines alten Arduino 168 Chip. Siehe auch Eine technische Übersicht über die Speichernutzung ist auf verfügbar http://www.gnu.org/savannah-checkouts/non-gnu/avr-libc/user-manual/malloc.html 17.3 Speichern und Abrufen von numerischen Werten in Programmspeicher Problem Sie haben eine Menge von konstanten numerischen Daten und wollen nicht, dies zu RAM zuweisen. Lösung Lagern Sie numerische Variablen im Programmspeicher (Flash-Speicher verwendet werden, um Arduino speichern Programme). Diese Skizze stellt einen Fading-LED für die nichtlineare Empfindlichkeit des menschlichen Sehens. Es speichert die Werte, die in einer Tabelle von 256 Werten in dem Programmspeicher nicht im Arbeitsspeicher zu verwenden. Die Skizze ist auf Rezept 7.2 Auf der Grundlage; siehe Kapitel 7 für einen Schaltplan und Diskussion auf der Fahrt LEDs. Ausführen dieser Skizze zu einer glatten Änderung der Helligkeit mit der LED an Pin 5 im Vergleich zur LED an Pin 3: /* * ProgmemCurve sketch * uses table in program memory to convert linear to exponential output * See Recipe 7.2 and Figure 7-2 */ #include <avr/pgmspace.h> // needed for PROGMEM // table of exponential values // generated for values of i from 0 to 255 -> x=round( pow( 2.0, i/32.0) - 1); const byte table[]PROGMEM = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 14, 14, 14, 15, 15, 15, 16, 16, 16, 17, 17, 18, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26, 27, 28, 28, 29, 30, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37, 38, 39, 40, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 54, 55, 56, 58, 59, 60, 62, 63, 64, 66, 67, 69, 70, 72, 73, 75, 77, 78, 80, 82, 84, 86, 88, 90, 91, 94, 96, 98, 100, 102, 104, 107, 109, 111, 114, 116, 119, 122, 124, 127, 130, 133, 136, 139, 142, 145, 148, 151, 155, 158, 161, 165, 169, 172, 176, 180, 184, 188, 192, 196, 201, 205, 210, 214, 219, 224, 229, 234, 239, 244, 250 }; const int rawLedPin = 3; // this LED is fed with raw values const int adjustedLedPin = 5; // this LED is driven from table int brightness = 0; int increment = 1; void setup() { // pins driven by analogWrite do not need to be declared as outputs } void loop() { if (brightness > 254) { increment = -1; // count down after reaching 255 } else if (brightness < 1) { increment = 1; // count up after dropping back down to 0 } brightness = brightness + increment; // increment (or decrement sign is minus) // write the brightness value to the LEDs analogWrite(rawLedPin, brightness); // this is the raw value int adjustedBrightness = pgm_read_byte(&table[brightness]); // adjusted value analogWrite(adjustedLedPin, adjustedBrightness); delay(10); // 10ms for each step change means 2.55 secs to fade up or down } Diskussion Wenn Sie brauchen, um einen komplexen Ausdruck zu verwenden, um eine Reihe von Werten, die regelmäßig berechnen zu wiederholen, ist es oft besser, die Werte vorzuberechnen und sie in einer Tabelle von Werten, (Üblicherweise als ein Array) im Code. Dies spart Zeit für die Berechnung der Werte wiederholt, wenn der Code ausgeführt wird. Der Nachteil betrifft den Speicherbedarf zu Ort diese Werte im RAM. RAM auf Arduino und der viel größeren Programmspeicher begrenzt Seite 590 | Kapitel 17: Erweiterte Codierung und Speicher Handhabung Raum kann verwendet werden, um konstante Werte zu speichern. Dies ist besonders hilfreich für Skizzen, haben große Anordnungen von Zahlen. An der Spitze der Skizze ist die Tabelle mit den folgenden Ausdruck definiert: const byte table[]PROGMEM = { 0, . . . PROGMEM teilt dem Compiler mit, dass die Werte, die im Programmspeicher nicht gespeichert werden als RAM. Der Rest der Expression ist ähnlich zu der Definition eines herkömmlichen Array (Siehe Kapitel 2). Die Low-Level-Definitionen erforderlich, um PROGMEM verwenden werden in einer Datei mit dem Namen enthalten pgmspace.h und die Skizze enthält diese wie folgt: #include <avr/pgmspace.h> Um die Helligkeit um die Fade-Look zu vereinheitlichen, fügt dieses Rezept die folgende Zeilen in die LED-Ausgangscode in Rezept 7.2 verwendet: int adjustedBrightness = pgm_read_byte(&table[brightness]); analogWrite(adjustedLedPin, adjustedBrightness); Die Variable adjustedBrightness von einem Wert aus dem Programmspeicher gelesen gesetzt. Die Ausdruck pgm_read_byte(&table[brightness]); Mittel, um die Adresse der Rückkehr Eintrag in der Tabelle Anordnung an der Indexposition von brightness angegeben. Jeder Eintrag in der Tabelle ist ein Byte, also eine weitere Möglichkeit, diesen Ausdruck zu schreiben ist: pgm_read_byte(table + brightness); Ist es nicht klar, warum und Tabelle [Helligkeit] entspricht Tisch + Helligkeit, nicht Sorgen; Verwendung je nachdem, was Ausdruck macht mehr Sinn für Sie. Ein weiteres Beispiel ist von Rezept 6.5, die eine Tabelle zum Konvertieren eines Infrarot verwendet Sensors, der in Abstand. Hier ist die Skizze von diesem Rezept umgewandelt, um eine Tabelle zu verwenden im Programmspeicher anstatt RAM: /* ir-distance_Progmem sketch * prints distance & changes LED flash rate depending on distance from IR sensor * uses progmem for table */ #include <avr/pgmspace.h> // needed when using Progmem // table entries are distances in steps of 250 millivolts const int TABLE_ENTRIES = 12; const int firstElement = 250; // first entry is 250 mV const int interval = 250; // millivolts between each element // the following is the definition of the table in Program Memory const int distanceP[TABLE_ENTRIES] PROGMEM = { 150,140,130,100,60,50, 40,35,30,25,20,15 }; // This function reads from Program Memory at the given index int getTableEntry(int index) { int value = pgm_read_word(&distanceP[index]); return value; } 17,3 speichern und abrufen Numerische Werte im Programmspeicher | Seite 591 Der verbleibende Code ähnelt Rezept 6.5, mit der Ausnahme, dass die getTableEntry Funktion verwendet, um den Wert aus dem Programmspeicher, anstatt Zugriff auf eine Tabelle in dem RAM zu erhalten. Hier ist die überarbeitete getDistance Funktion von diesem Rezept: int getDistance(int mV) { if( mV > interval * TABLE_ENTRIES ) return getTableEntry(TABLE_ENTRIES-1); // the minimum distance else { int index = mV / interval; float frac = (mV % 250) / (float)interval; return getTableEntry(index) - ((getTableEntry(index) - getTableEntry(index+1)) * frac); } } Siehe auch In Rezept 17.4 für die Technik in Arduino 1.0 eingeführt, um Strings in Flash speichern Speicher. 17.4 Speichern und Abrufen von Strings im Programmspeicher Problem Sie haben viele Strings und sie verbrauchen zu viel RAM. Sie wollen sich zu bewegen String-Konstanten, wie zum Beispiel Menüführung oder Debugging-Anweisungen, aus dem RAM und in Programmspeicher. Lösung Diese Skizze erzeugt einen String im Programmspeicher an und gibt deren Wert an den Serial Monitor mit dem F ("text") in Arduino 1.0 eingeführt Ausdruck. Die Technik für das Drucken die Menge des freien RAM wird in Rezept 17.2 beschrieben: /* * Write strings using Program memory (Flash) */ void setup() { Serial.begin(9600); } void loop() { Serial.print(memoryFree()); // print the free memory Serial.print(' '); // print a space Serial.print(F("arduino duemilanove ")); // print the string delay(1000); } // variables created by the build process when compiling the sketch extern int __bss_end; extern void *__brkval; // function to return the amount of free RAM int memoryFree() { int freeValue; if ((int)__brkval == 0) freeValue = ((int)&freeValue) - ((int)&__bss_end); else freeValue = ((int)&freeValue) - ((int)__brkval); return freeValue; } Seite 592 | Kapitel 17: Erweiterte Codierung und Speicher Handhabung Diskussion Strings sind besonders hungrig, wenn sie in den Arbeitsspeicher kommt. Jedes Zeichen wird ein Byte, so es ist leicht, große Teile der RAM verbrauchen, wenn Sie viele Wörter in Zeichenfolgen in Ihrem Skizze. Einfügen von Text in das F ("text") Ausdruck speichert den Text in der viel größeren Flash-Speicher anstelle von RAM. Wenn Sie eine frühere Arduino Mitteilung sind können Sie Text im Programmspeicher noch zu speichern, aber Sie brauchen, um ein wenig mehr Code in Ihre Skizze hinzuzufügen. Hier ist die gleiche Funktionalität für Versionen vor 1.0 implementiert: #include <avr/pgmspace.h> // for progmem //create a string of 20 characters in progmem const prog_uchar myText[] PROGMEM = "arduino duemilanove "; void setup() { Serial.begin(9600); } void loop() { Serial.print(memoryFree()); // print the free memory Serial.print(' '); // print a space printP(myText); // print the string delay(1000); } // function to print a PROGMEM string void printP(const prog_uchar *str) { char c; while((c = pgm_read_byte(str++))) Serial.write(c); } // variables created by the build process when compiling the sketch extern int __bss_end; extern void *__brkval; // function to return the amount of free RAM int memoryFree(){ int freeValue; if((int)__brkval == 0) freeValue = ((int)&freeValue) - ((int)&__bss_end); else freeValue = ((int)&freeValue) - ((int)__brkval); return freeValue; } 17.4 Speichern und Abrufen von Strings im Programm-Speicher | Seite 593 Siehe auch In Rezept 15.11 ein Beispiel für Flash-Speicher zum Speichern von Web-Seite Strings verwendet. 17.5 Using #define and const Instead of Integers Problem Sie wollen RAM-Auslastung, indem Sie dem Compiler mit, dass der Wert konstant ist zu minimieren und optimiert werden. Lösung Verwenden Sie const auf Werte, die in der gesamten Skizze konstant zu deklarieren. Beispielsweise können anstelle von: int ledPin=13; use: const int ledPin=13; Diskussion Wir wollen oft einen konstanten Wert in verschiedenen Bereichen der Code zu verwenden. Nur das Schreiben der Anzahl ist eine sehr schlechte Idee. Wenn Sie später die verwendete Wert ändern möchten, ist es schwierig, herauszufinden, welche Zahlen in der ganzen Code verstreut müssen auch geändert werden. Es ist am besten zu nutzen Nennung von Namen. Seite 594 | Kapitel 17: Erweiterte Codierung und Speicher Handhabung Hier sind drei Möglichkeiten, einen Wert, der eine Konstante zu definieren: int ledPin = 13; // a variable, but this wastes RAM const int ledPin = 13; // a const does not use RAM #define ledPin 13 // using a #define // the preprocessor replaces ledPin with 13 pinMode(ledPin, OUTPUT); Obwohl die ersten zwei Ausdrücke ähnlich aussehen, erzählt der Begriff const den Compiler nicht um ledPin als gewöhnliche Variable behandeln. Im Gegensatz zu den normalen int ist keine RAM reserviert Halten Sie den Wert für die const, da sichergestellt ist, nicht zu ändern. Der Compiler erzeugen genau das gleiche Code, als hätten Sie geschrieben: pinMode(13, OUTPUT); Sie werden manchmal sehen # define-Konstanten verwendet werden, um bei älteren Arduino-Code definieren, aber const ist eine bessere Wahl als #define. Dies liegt daran, eine const-Variable hat eine Art, die ermöglicht dem Compiler zu überprüfen und zu melden, wenn die Variable, die in einer Weise nicht angemessen verwendet für diesen Typ. Der Compiler wird auch C-Regeln zu respektieren für den Geltungsbereich eines const variabel. Ein #define Wert den gesamten Code in der Skizze zu beeinflussen, das ist mehr als sein kann, Sie bestimmt. Ein weiterer Vorteil der const ist, dass es vertraut Syntax- # definieren nicht verwenden das Gleichheitszeichen und kein Semikolon am Ende verwendet. Siehe auch Siehe Einleitung Abschnitt in diesem Kapitel, um mehr über den Präprozessor. 17.6 Verwenden von Conditional Compilation Problem Sie möchten verschiedene Versionen des Codes, die selektiv zusammengestellt werden können. Für Beispiel-Code müssen Sie möglicherweise anders zu arbeiten bei der Fehlersuche oder bei der Ausführung mit verschiedensten Boards. Lösung Sie können die bedingte Anweisungen auf dem Präprozessor Ziel verwenden, um zu steuern, wie Ihre Skizze wird gebaut. Dieses Beispiel von Skizzen in Kapitel 15 umfasst die SPI.h Bibliotheksdatei, die nur ist zur Verfügung und mit Arduino Versionen nach 0018 veröffentlicht benötigt: #if ARDUINO > 18 #include <SPI.h> // needed for Arduino versions later than 0018 #endif 17.6 Verwenden von Conditional Compilation Übersicht | Seite 595 Das Beispiel mit dem Sketch von Rezept 5.6 zeigt nur einige Debug-Anweisungen wenn DEBUG definiert ist: /* Pot_Debug sketch blink an LED at a rate set by the position of a potentiometer Uses Serial port for debug if DEBUG is defined */ const int potPin = 0; // select the input pin for the potentiometer const int ledPin = 13; // select the pin for the LED int val = 0; // variable to store the value coming from the sensor #define DEBUG void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); // declare the ledPin as an OUTPUT } void loop() { val = analogRead(potPin); // read the voltage on the pot digitalWrite(ledPin, HIGH); // turn the ledPin on delay(val); // blink rate set by pot value digitalWrite(ledPin, LOW); // turn the ledPin off delay(val); // turn LED off for same period as it was turned on #if defined DEBUG Serial.println(val); #endif } Diskussion Dieses Rezept benutzt den Präprozessor zu Beginn der Kompilierung verwendet werden, um zu ändern welche Code kompiliert. Die ersten Beispiel prüft, ob der Wert des konstanten ARDUINO ist größer als 18, und wenn ja, wird die Datei SPI.h enthalten. Der Wert des konstanten ARDUINO wird in den Build-Prozess festgelegt und entspricht dem Arduino-Release-Version. Die Syntax dieser Ausdruck nicht die gleiche wie die für das Schreiben einer Skizze verwendet. Expressions dass mit dem Symbol # beginnen, werden verarbeitet, bevor der Code kompiliert, sehen die in diesem Kapitel Einführungsabschnitt, um mehr über den Präprozessor. Sie haben bereits in # include kommen: #include <library.h> Die <> Klammern sagen dem Compiler, um die Datei in den Speicherort für Standard suchen Bibliotheken: #include "header.h" Der Compiler wird auch in der Skizze Verzeichnis. Seite 596 | Kapitel 17: Erweiterte Codierung und Speicher Handhabung Sie können ein bedingtes Kompilieren, basierend auf dem Steuerchip in der IDE ausgewählt ist. Beispielsweise wird der folgende Code anderen Code als für einen Mega zusammengestellt produzieren Brett, das die zusätzliche analoge Stifte, die es lautet: /* * ConditionalCompile sketch * This sketch recognizes the controller chip using conditional defines */ int numberOfSensors; int val = 0; // variable to store the value coming from the sensor void setup() { Serial.begin(9600); #if defined(__AVR_ATmega1280__) // defined when selecting Mega in the IDE numberOfSensors = 16; // the number of analog inputs on the Mega #else // if not Mega then assume a standard board numberOfSensors = 6; // analog inputs on a standard Arduino board #endif Serial.print("The number of sensors is "); Serial.println(numberOfSensors); } void loop() { for(int sensor = 0; sensor < numberOfSensors; sensor++) { val = analogRead(sensor); // read the sensor value Serial.println(val); // display the value } Serial.println(); delay(1000); // delay a second between readings } Siehe auch Technische Details auf der C-Präprozessor finden Sie unter http://gcc.gnu.org/onlinedocs/gcc-2.95.3/cpp_1.html Siehe die Diskussion Abschnitt Rezept 16.4 zum Beispiel für die bedingte Kompilierung verwendet werden, um Unterschiede zwischen Arduino 1.0 und früheren Versionen zu behandeln. 17.6 Verwenden von Conditional Compilation Übersicht | ENDE Seite 597 DIN A4 ausdrucken ********************************************************* Impressum: Fritz Prenninger, Haidestr. 11A, A-4600 Wels, Ober-Österreich, mailto:[email protected] ENDE |
ARDUINO Kochbuch >