- LiTime Speicher und Akkus         
Seite 1 von 3 123 LetzteLetzte
Ergebnis 1 bis 10 von 23

Thema: Tutorial: Erstellen einer Arduino-Bibliothek

  1. #1
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    13.01.2014
    Beiträge
    454
    Blog-Einträge
    3

    Tutorial: Erstellen einer Arduino-Bibliothek

    Anzeige

    Powerstation Test
    Dieses Tutorial beschäftigt sich mit dem Erstellen einer Arduino-Bibliothek


    1. Vorwort


    Bibliotheken sind ja für viele etwas, was man reinladen muß, damit irgendein Sensor, Motor, Display etc angesprochen werden kann. Bibliotheken sind aber kein Hexenwerk. Im Gegenteil, sie sind sehr nützlich, um Programme übersichtlicher zu machen. Außerdem kann man sie leicht mit anderen teilen, sodass nicht jeder Programierer ein bestimmtes Problem neu enträtseln muss. Darum werden wir hier mal ein bischen genauer hinschauen.

    Dazu nehmen wir ein einfaches Arduino-Programm und lagern die Funktion in mehreren Schritten in eine Bibliothek aus. Diese sind nicht unbedingt alle nötig, dienen aber der Verauschaulichung, was zu tun ist und warum.

    Wer die Programmbeispiele am eigenen Rechner nachvollziehen will, benötigt eine installierte Arduino-IDE ab Version 1.




    2. Das Programm


    Programmbeschreibung:
    Das Programm steuert eine RGB-Led. Diese Led kann man sich vorstellen wie 3 verschiedenfarige Leds in einem Gehäuse. Sie besitzt 4 Anschlüsse: Masse und 3 Anschlüsse für die einzelnen Steuerspannungen, mit denen die Helligkeit der jeweiligen Farbe (Rot, Grün, Blau) gesteuert wird.

    RGB_LED.ino:
    Code:
    #define RED_PIN 4
    #define GRN_PIN 3
    #define BLU_PIN 2
    
    void setRGB(byte r, byte g, byte b) {
      analogWrite(RED_PIN, r);
      analogWrite(GRN_PIN, g);
      analogWrite(BLU_PIN, b);
    }
    
    void blink(char color, byte times, unsigned int ms) {
      byte r=0, g=0, b=0;
      if(color == 'r')      r = 255;
      else if(color == 'g') g = 255;
      else if(color == 'b') b = 255;
      else return ;
      
      for (byte i = 0; i < times; i++) {
        setRGB(r, g, b);
        delay(ms);
        setRGB(0, 0, 0);
        delay(ms);
      }
    }
    
    void setup() {}
    
    void loop() {
      blink('r',   5, 500);  // rot, 5 Widerholungen, jeweils 500 Millisekunden an
      blink('b', 10, 250);  
      blink('g', 15, 167);
    }
    'setRGB' setzt die einzelnen Steuerspannungen, und damit Farbe und Helligkeit der RGB-Led. Sie nimmt je Farbe Werte zwischen 0 (aus) und 255 (volle Helligkeit) entgegen.

    'blink' lässt die Led naja blinken. Farbe der Led, Anzahl der Blinkwiderholungen und Dauer eines An-Aus-Intervalls sind der Funktion zu übergeben.

    'loop' lässt die RGB-Led nun in erst rot und langsam, dann blau und schneller, dann grün und schnell blinken. Dann beginnt es von vorn.





    3. Auslagern der Funktionalität in ein Modul


    Motivation:
    - Die Übersichtlichkeit wird verbessert. Im Hauptprogramm sind nur noch die Funtionsaufrufe sichtbar.
    - Die Funktionalität kann so sehr einfach in andere Programme integriert werden. Dazu muss nur das Modul geladen werden.

    Dazu wird im Sketch-Ordner eine zusätzliche Datei erstellt. Wir nennen sie 'RGBLed.h'.
    '.h' identifiziert die Datei als Header-Datei. Hier werden nun die Funtionen eingefügt. Dem vorangestellt steht die Zeile: #include <Arduino.h>. Die ist erforderlich, weil dem Linker die Arduino-Befehlsumgebung zu diesem Zeitpunkt noch nicht bekannt ist. (Der Linker ist Programm, dass die einzelnen Programmteile zu eine einem Gesamtprogramm zusammensetzt, damit es vom Compiler in einen vom Arduino verständlichen Maschinencode übersetzt werden kann).

    RGBLed.h
    Code:
    #include <Arduino.h>
    
    void setRGB(byte r, byte g, byte b)  {
      analogWrite(RED_PIN, r);
      analogWrite(GRN_PIN, g);
      analogWrite(BLU_PIN, b);
    }
    
    void blink(char color, byte times, unsigned int ms) {
      byte r=0, g=0, b=0;
      if(color == 'r')      r = 255;
      else if(color == 'g') g = 255;
      else if(color == 'b') b = 255;
      else return ;
      
      for (byte i = 0; i < times; i++) {
        setRGB(r, g, b);
        delay(ms);
        setRGB(0, 0, 0);
        delay(ms);
      }
    }
    Im Hauptprogramm muß dann dem Kompiler angezeigt werden, dass wir die frisch erzeugte Datei verwenden wollen. Dies macht die Anweisung #include "RGBLed.h".

    RGB_LED.ino
    Code:
    #define RED_PIN 4
    #define GRN_PIN 3
    #define BLU_PIN 2
    
    #include "RGBLed.h"
    
    void setup() {}
    
    void loop() {
      blink('r', 5 , 500);
      blink('b', 10, 250);
      blink('g', 15, 167);
    }




    4. Objekt bauen


    Motivation:
    - Objekte fassen Funtionalität und Daten unter einem Dach zusammen
    - bessere Lesbarkeit des Codes
    - Kapselung, Sicherheit

    Bis hierhin haben wir reinen C-Code verwendet. Es ist jetzt an der Zeit einen der Vorzüge von C++ zu verwenden: Objekt-Orientierung. Objekte werden nach einem Bauplan erstellt. Dieser Bauplan wird allgemein als Klasse bezeichnet. Die Beschreibung einer Klasse geschieht in einem class-Block. Unsere bekommt den Namen RGBLed.
    Das Schlüsselwort public gibt an, dass die Funktionen (die in der Objekt -Orientierung auch Methoden genannt werden) ausserhalb der Klasse ansprechbar sind. Dies wollen wir, da ja später aus dem Hauptprogramm diese Methoden aufrufen werden sollen.

    RGBLed.h
    Code:
    #include <Arduino.h>
    
    class RGBLed {
    public:
    	void setRGB(byte r, byte g, byte b) {
    		analogWrite(RED_PIN,   r);
    		analogWrite(GRN_PIN, g);
    		analogWrite(BLU_PIN,  b);
    	}
    
    	void blink(char color, byte times, unsigned int ms) {
    		byte r=0, g=0, b=0;
    		if(color == 'r')      r = 255;
    		else if(color == 'g') g = 255;
    		else if(color == 'b') b = 255;
    		else return ;
    
    		for (byte i = 0; i < times; i++) {
    			setRGB(r, g, b);
    			delay(ms);
    			setRGB(0, 0, 0);
    			delay(ms);
    	}
    
    };
    Im Hauptprogramm erzeugen wir zuerst ein RGBLed-Objekt mit dem Namen 'rgb'. Die Methoden des Objekts werden über den '.'-Operator angesprochen.

    RGB_LED.ino
    Code:
    #define RED_PIN 4
    #define GRN_PIN 3
    #define BLU_PIN 2
    #include "RGBLed.h"
    RGBLed rgb;
    
    void setup() {}
    
    void loop() {
      rgb.blink('r', 5 , 500);
      rgb.blink('b', 10, 250);
      rgb.blink('g', 15, 167);
    }




    5. Weitere Bearbeitung


    - verhindern, dass die Bibliothek mehrfach geladen werden kann (und so zu Compiler-Fehlermeldungen führt)
    Dies wird mit folgendem Code erreicht:
    Code:
    #ifndef __RGB_LED__
    #define __RGB_LED__
    //...
    #endif
    - Daten im Objekt speichern
    Dazu benutzen wir einen Konstruktor: RGBLed (byte redPin, byte greenPin, byte bluePin)
    Dieser soll die PIN-Nummern, an denen die RGB-Led angeschlossen wird, beim sofort beim Erstellen des Objekts speichern.
    Das Schlüsselwort 'private' gibt an, dass die Variablen nur innerhalb des Objekts angesprochen werden können.

    RGBLed.h:

    Code:
    #ifndef __RGB_LED__
    #define __RGB_LED__
    
    #include <Arduino.h>
    
    class RGBLed {
    private:
    	byte redPin;
    	byte greenPin;
    	byte bluePin;
    
    public:
    	RGBLed (byte redPin, byte greenPin, byte bluePin){
    		this->redPin   = redPin;
    		this->greenPin = greenPin;
    		this->bluePin  = bluePin;
    	}
    	void setRGB(byte r, byte g, byte b) {
    		analogWrite(redPin,   r);
    		analogWrite(greenPin, g);
    		analogWrite(bluePin,  b);
    	}
    	void blink(char color, byte times, unsigned int ms) {
    		byte r=0, g=0, b=0;
    		if(color == 'r')      r = 255;
    		else if(color == 'g') g = 255;
    		else if(color == 'b') b = 255;
    		else return ;
    
    		for (byte i = 0; i < times; i++) {
    			setRGB(r, g, b);
    			delay(ms);
    			setRGB(0, 0, 0);
    			delay(ms);
    		}
    	}
    };
    
    #endif
    Im Hauptprogramm benutzen wir nun den neuen Konstruktor.

    RGB_LED.ino
    Code:
    #include "RGBLed.h"
    RGBLed rgb(4, 3, 2);  //Pins: red =4, green =3, blue =2
    
    void setup() {}
    
    void loop() {
      rgb.blink('r', 5 , 500);
      rgb.blink('b', 10, 250);
      rgb.blink('g', 15, 167);
    }




    6. Finale Bearbeitung


    Jetzt werden wir eine weitere Datei hinzufügen: RGBLed.cpp
    Diese cpp-Datei wird die gesamte Funktionalität beinhalten, während wir diese aus der h-Datei verbannen. Dort werden nur noch Deklarationen stehen. Dies dient wiederum der Übersichtlichkeit. Falls ein fremder Programmieren sich den Code anschaut, kann er in der h-Datei sehen, was die Bibliothek kann. In der cpp-Datei kann er sehen, wie die Bibliothek das umsetzt.

    Außdem werden wir nun einen neuen Ordner im Ordner '..Arduino/libraries' erstellen. Diesen nennen wir 'RGBLed' und packen unsere h-Datei und cpp-Datei dort hinein.

    RGBLed.h:
    Code:
    #ifndef __RGB_LED__
    #define __RGB_LED__
    
    #include <Arduino.h>
    
    class RGBLed {
    private:
    	byte redPin;
    	byte greenPin;
    	byte bluePin;
    
    public:
    	RGBLed (byte redPin, byte greenPin, byte bluePin);
    
    	void setRGB(byte r, byte g, byte b) ;
    	void blink(char color, byte times, unsigned int ms);
    };
    
    #endif
    'RGBLed::' ordnet die in der cpp-Datei definierten Funktionen der Klasse 'RGBLed' zu.

    RGBLed.cpp:
    Code:
    #include "RGBLed.h"
    
    RGBLed::RGBLed (byte redPin, byte greenPin, byte bluePin) {
    	this->redPin   = redPin;
    	this->greenPin = greenPin;
    	this->bluePin  = bluePin;
    }
    
    void RGBLed::setRGB(int r, int g, int b) {
    	analogWrite(redPin,   r);
    	analogWrite(greenPin, g);
    	analogWrite(bluePin,  b);
    }
    
    void  RGBLed::blink(char color, byte times, unsigned int ms) {
    	byte r=0, g=0, b=0;
    	if(color == 'r')      r = 255;
    	else if(color == 'g') g = 255;
    	else if(color == 'b') b = 255;
    	else return ;
    
    	for (byte i = 0; i < times; i++) {
    		setRGB(r, g, b);
    		delay(ms);
    		setRGB(0, 0, 0);
    		delay(ms);
    	}
    }
    Das Hauptprogramm hat nur eine Änderung:
    #include <RGBLed.h> statt #include "RGBLed.h"
    Diese Änderung trägt der Migration in den Ordner '..Arduino/libraries' Rechnung. Dort sucht die Arduino-IDE beim Programmstart automatisch nach Bibliotheken.

    RGB_LED.ino
    Code:
    #include <RGBLed.h>
    RGBLed rgb(4, 3, 2);  //Pins: red =4, green =3, blue =2
    
    void setup() {}
    
    void loop() {
      rgb.blink('r', 5 , 500);
      rgb.blink('b', 10, 250);
      rgb.blink('g', 15, 167);
    }
    Als letztes fügen wir in unseren Ordner eine weitere Datei:

    keywords.txt
    Code:
    RGBLed	KEYWORD1
    setRGB	KEYWORD1
    blink	KEYWORD1
    Diese sorgt für ein buntes Hervorheben unserer Schlüsselwörter und dient somit der nocheinmal der besseren Lesbarkeit.

    --
    Viel Spass beim Schreiben (und Veröffentlichen) eurer eigenen Arduino-Bibliotheken!!!

    Sisor
    Geändert von Sisor (06.07.2014 um 13:59 Uhr) Grund: Korrektur nach Hinweis

  2. #2
    Erfahrener Benutzer Begeisterter Techniker Avatar von Chypsylon
    Registriert seit
    02.02.2011
    Ort
    Graz/Österreich
    Beiträge
    256
    Zitat Zitat von Sisor Beitrag anzeigen
    Die Methoden des Objekts werden über den '.'-Operator angesprochen, wie man es von z.B. Java oder C# kennt. (Dies ist eine Besonderheit der Arduino-IDE. C++-Programierer wundern sich: Normalerweise ist hier doch ein Pfeiloperator?)
    C++ verwendet genauso den '.'-Operator. Der '->'-Pfeil ist nur eine Abkürzung um sich das derefernzieren eines Pointers zu ersparen.

    Code:
    Foo *myFoo = new Foo();
    
    (*myFoo).foobar();
    //ist das gleiche wie
    myFoo->foobar();

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    13.01.2014
    Beiträge
    454
    Blog-Einträge
    3
    Danke für den Hinweis, da hatte ich im Kopf mächtig was verdreht.
    In meinem Beispiel wird eben nicht mit 'new' und Referenz gearbeitet. Daher fällt natürlich auch das Dereferenzieren weg.
    Code:
    Foo myFoo();
    myFoo.foobar();
    
    // ohne Anwendung, nur zur Veranschaulichung:
    Foo* myFooPtr = &myFoo;  // Referenz erzeugen
    myFooPtr->foobar();      // indirekter Zugriff
    Habs korrigiert.

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    16.02.2014
    Beiträge
    80
    Hey Sisor, und wieder herzlichen Dank für das Tutorial! Ich werde es nutzen um meine rudimentären C-Kenntnisse endlich auf rudimentäre C++-Kenntnisse aufzustocken wenn ich mal wieder Zeit für den Arduino hab'...

  5. #5
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    13.01.2014
    Beiträge
    454
    Blog-Einträge
    3
    Kein Problem, ich hatte mich mit dem Thema gerade beschäftigt und dachte, ich fass das Gelernte mal für mich und andere zusammen. Interessant ist, dass jedes der 5 Programme (Schritt 2 - 6) die gleiche Funktionalität aufweist. Je komplexer ein Programm wird, desto mehr macht eine modulare, objektorientierte Herangehensweise Sinn.

  6. #6
    Unregistriert
    Gast

    Compiler-Fehler / INT vs Byte

    D:\Eigene Dateien\Arduino\libraries\RGBLed\RGBLed.cpp:9:6: error: prototype for 'void RGBLed::setRGB(int, int, int)' does not match any in class 'RGBLed'
    void RGBLed::setRGB(int r, int g, int b) {
    ^
    In file included from D:\Eigene Dateien\Arduino\libraries\RGBLed\RGBLed.cpp:1:0:
    D:\Eigene Dateien\Arduino\libraries\RGBLed\RGBLed.h:15:7: error: candidate is: void RGBLed::setRGB(byte, byte, byte)
    void setRGB(byte r, byte g, byte b) ;
    ^
    Fehler beim Kompilieren.

  7. #7
    Erfahrener Benutzer Begeisterter Techniker Avatar von Chypsylon
    Registriert seit
    02.02.2011
    Ort
    Graz/Österreich
    Beiträge
    256
    Der Compiler sagt dir doch eh schon wo das Problem liegt

    Im header File (.h) ist setRGB(byte r, byte g, byte b); mit bytes definiert. Im .cpp ist gibts die Funktion aber nur mit ints als Parameter ausprogrammiert. Das ist vermutlcih einfach ein Copy&Paste Fehler des Autors, ändere die ints zu bytes und es sollte funktionieren.

  8. #8
    Unregistriert
    Gast

    Cool Ist behoben -> weitere Frage dazu

    Vielen Dank für die Rückantwort.0
    Habe das bereits geändert so ´dass der Funktionsrumpf und die Implementierung über Byte arbeiten.
    Wollte gerne noch bei meinem Projekt in die CPP-Datei die IRremote.h einbinden.
    Wo kann man dazu noch was finden?

    Derzeit kommt das dabei raus:
    --------------
    IRControl.cpp:1:22: fatal error: IRremote.h: No such file or directory
    #include <IRremote.h>
    ^
    compilation terminated.
    Fehler beim Kompilieren.
    --------------

    Meine Klasse soll IRControl heißen und Steuercodes auf den Seriellen Monitor bzw. einen INT-Wert zurückgeben.
    Hatte da schon ein Programm fertig, welches ich jetzt mit diesen Tutoriell in eine Klasse stecken möchte.

  9. #9
    Erfahrener Benutzer Begeisterter Techniker Avatar von Chypsylon
    Registriert seit
    02.02.2011
    Ort
    Graz/Österreich
    Beiträge
    256
    IRControl.cpp:1:22: fatal error: IRremote.h: No such file or directory
    Der Compiler meckert hier das er diese Datei nicht finden kann, bist du dir sicher das du die Library richtig installiert hast? Funktioniert das einbinden bei anderen Programmen?

  10. #10
    Unregistriert
    Gast

    Rotes Gesicht Einbinden weiterer Header gelöst

    Danke nochmal für die Rückantwort.

    Das Einbinden über <IRremote.h> hat nicht geklappt.

    Habe die IRremote.h und die CPP sowie die zugehörigen Dateien in mein Library-Verzeichnis "IRControl" kopiert.
    In der IRControl.cpp habe ich dann oben gleich diese direkt so eingebunden:

    #include "IRControl.h"
    #include "IRremote.h"
    #include<Arduino.h>

    Dann war es noch wichtig alle weiteren Dateien über Drag&Drop auf die Arduino-IDE zu ziehen damit die gefunden werden.
    Jetzt läuft es soweit.

    Das Einzige was mich noch etwas nervt, ist das im Hauptprogramm das Objekt sofort
    instanziiert wird. In Java kann man es immer erst deklarieren und danach mit 'new' instanziieren.
    Habe es jetzt mit static in den Loop() gesetzt. Da sollte es nur einmal erzeugt werden und ist verfügbar.
    Vorerst ist es aber mal soweit ok. Hatte gegen 2009 aufgehört C++ zu programmieren.

Seite 1 von 3 123 LetzteLetzte

Ähnliche Themen

  1. problem bei der verwendung einer twi bibliothek (avr-gcc)
    Von avrrobot im Forum Software, Algorithmen und KI
    Antworten: 18
    Letzter Beitrag: 17.01.2011, 21:13
  2. NIBObee: beelib - noch einer andere Bibliothek...
    Von bantyy im Forum Sonstige Roboter- und artverwandte Modelle
    Antworten: 4
    Letzter Beitrag: 01.06.2010, 23:18
  3. Einbinden einer Bibliothek in ein Assembler Programm
    Von EGS-3 im Forum PIC Controller
    Antworten: 2
    Letzter Beitrag: 12.07.2006, 22:55
  4. Gibt es eine Bibliothek für das Erstellen von Bildern ?
    Von terny im Forum C - Programmierung (GCC u.a.)
    Antworten: 0
    Letzter Beitrag: 12.09.2005, 09:15
  5. Fragen zur Erstellung einer Eagle Bibliothek
    Von Arme Sau im Forum Konstruktion/CAD/3D-Druck/Sketchup und Platinenlayout Eagle & Fritzing u.a.
    Antworten: 3
    Letzter Beitrag: 18.12.2004, 09:56

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

LiTime Speicher und Akkus