In der Welt der Arduino-Programmierung spielen Datentypen eine zentrale Rolle, da sie den Grundstein für die Speicherung und Verarbeitung von Daten legen. Jeder Datentyp definiert einen spezifischen Wertebereich und bestimmt, wie viel Speicherplatz für die Speicherung einer Variable oder eines Funktionswertes reserviert wird. Die Auswahl des richtigen Datentyps ist entscheidend, um Effizienz, Präzision und eine optimale Nutzung der begrenzten Ressourcen eines Mikrocontrollers zu gewährleisten.
Die Arduino-IDE stellt eine Vielfalt an Datentypen zur Verfügung, von einfachen booleschen Werten, die nur true
oder false
sein können, bis hin zu komplexeren Fließkommazahlen und benutzerdefinierten Strukturen. Ein interessantes Beispiel ist der bool
-Datentyp: Obwohl er konzeptionell nur ein Bit für die Darstellung benötigt, reserviert die Arduino-Plattform standardmäßig 8 Bit im Arbeitsspeicher für eine boolesche Variable, um die Speicherverwaltung zu vereinfachen und die Kompatibilität mit der Hardware zu gewährleisten.
Produktempfehlungen und -suche in Verbindung mit dem Amazon Partnerprogramm:
¹ Angaben ohne Gewähr. Bei einem Kauf über den Link erhalten wir eine Provision.
Dieser Beitrag bietet eine umfassende Übersicht über die verschiedenen Datentypen, die in der Arduino-IDE verfügbar sind, und erklärt ihre Eigenschaften, Anwendungen und die damit verbundenen Besonderheiten. Ziel ist es, Ihnen ein tiefes Verständnis dafür zu vermitteln, wie Sie diese Datentypen effektiv in Ihren Projekten einsetzen können, um kreative und technisch solide Lösungen zu entwickeln.
Produktempfehlungen und -suche in Verbindung mit dem Amazon Partnerprogramm:
¹ Angaben ohne Gewähr. Bei einem Kauf über den Link erhalten wir eine Provision.
Zum Kapitel springen Grundlegende Datentypen
Zum Kapitel springen void
Der Ausdruck void
wird in der Programmierung genutzt, um zu spezifizieren, dass eine Funktion keinen Rückgabewert liefert. Im engeren Sinne handelt es sich bei void
nicht um einen traditionellen Datentyp, da er keinen Wertebereich definiert. Stattdessen signalisiert er das Fehlen eines Datentyps. Zusätzlich findet void
Anwendung in der Deklaration von Zeigern, die auf eine Adresse ohne spezifizierten Datentyp verweisen, was ihre Flexibilität in verschiedenen Kontexten erhöht.
void myFunction(){
// do some stuff here an return nothing
}
Zum Kapitel springen bool - 1 bit
Variablen des Typs bool
, auch bekannt als boolean
, sind darauf ausgelegt, einen von zwei möglichen Werten zu speichern: true
oder false
. Obwohl für eine bool
-Variable 8 Bit an Speicherplatz reserviert werden, repräsentiert sie konzeptionell einen binären Zustand, der effektiv nur 1 Bit an Information benötigt. Dies macht den bool
-Datentyp ideal für die Darstellung von binären Zuständen, wie dem Ein- oder Auszustand eines Schalters.
bool switch_is_on = true;
bool switch_is_on = false;
Zum Kapitel springen byte - 8 bit
Ein Byte, welches aus 8 Bit besteht, ist in der Lage Werte im Bereich von 0 bis 255 zu speichern. Diese Eigenschaft wird häufig bei PWM (Pulsweitenmodulation) Registern genutzt, die ebenfalls eine Auflösung von 8 Bit besitzen. Aufgrund dieser Übereinstimmung ergibt sich der maximale Wert von 255 für die Intensität von PWM-Signalen.
byte value = 33;
Zum Kapitel springen char - 8 bit
Der Datentyp char
dient zur Speicherung einzelner Zeichen, kann aber auch numerische Werte im Bereich von -128 bis 127 aufnehmen. Jedes char
belegt 1 Byte Speicherplatz, wobei die Interpretation des gespeicherten Werts oft anhand der ASCII-Tabelle erfolgt. Diese Tabelle ordnet jedem Zeichen einen eindeutigen Dezimalwert (Dez) zu, wodurch char
variabel für Buchstaben, Ziffern oder Steuerzeichen verwendet werden kann. Ein Blick in die ASCII-Tabelle ist hilfreich, um die Zuordnung zwischen Zeichen und ihren numerischen Äquivalenten zu verstehen.
// Bei beiden Definitionen wird der Buchstabe a gespeichert.
char buchstabe_a = ‘a’;
char number_a = 97;
Zum Kapitel springen unsigned char - 8 bit
Der Datentyp unsigned char
ist vorzeichenlos, das heißt, er kann keine negativen Werte abbilden. Stattdessen erstreckt sich sein Wertebereich über 1 Byte von 0 bis 255, was ausschließlich positive Werte umfasst. Dies entspricht dem Wertebereich des byte
-Datentyps. Um Verwechslungen zu vermeiden, empfiehlt es sich, bei Bedarf direkt den byte
-Datentyp zu verwenden.
// Dies speichert das ASCII-Zeichen für das Copyright-Symbol ©
unsigned char myChar = 169;
Zum Kapitel springen word - 16 bit
Der Datentyp word
ist implizit vorzeichenlos, auch wenn das Schlüsselwort unsigned
nicht explizit angegeben wird. Dies bedeutet, dass word
nur positive Werte speichern kann, mit einem Wertebereich von 0 bis 65'535. Der Name word
kann irreführend sein, da er suggeriert, es könnten Wörter gespeichert werden, tatsächlich aber werden Ganzzahlen in diesem Bereich abgebildet. Für Klarheit und Konsistenz kann es sinnvoll sein, stattdessen den Datentyp unsigned int
zu verwenden, der denselben Wertebereich bietet.
word gramms = 45231;
Zum Kapitel springen int - 16 bit
Der Datentyp int
steht für "Integer" und bezeichnet Ganzzahlen, also Zahlen ohne Nachkommastellen. Mit einer Größe von 16 Bit ermöglicht dieser Datentyp die Speicherung von Werten im Bereich von -32'768 bis 32'767, einschließlich sowohl negativer als auch positiver Zahlen. Diese Spanne macht int
besonders vielseitig für Anwendungen, bei denen eine breite Palette von Ganzzahlen benötigt wird.
int year = 2021;
Zum Kapitel springen unsigned int - 16 bit
Der unsigned int
Datentyp ist äquivalent zum word
Datentyp, mit der Fähigkeit, positive Ganzzahlen ohne Vorzeichen zu speichern. Beide Datentypen nutzen 16 Bit Speicherplatz, was einen Wertebereich von 0 bis 65'535 ermöglicht. Dieser Umfang erlaubt die Darstellung einer breiten Palette von Zahlen, ideal für Fälle, in denen negative Werte nicht erforderlich sind.
unsigned int gramms = 45231;
Zum Kapitel springen long - 32 bit
Der Datentyp long
nutzt 32 Bit Speicherplatz, um sowohl positive als auch negative Ganzzahlen zu speichern. Dies ermöglicht einen breiten Wertebereich von -2'147'483'648 bis 2'147'483'647. Diese Kapazität macht den long
Datentyp ideal für Anwendungen, die einen umfangreichen Zahlenbereich benötigen, wie beispielsweise bei der Verarbeitung großer Zählvariablen oder bei der Arbeit mit Zeitdifferenzen in größeren Dimensionen.
long time_remaining = -12372876;
Zum Kapitel springen unsigned long - 32 bit
Der unsigned long
Datentyp reserviert 32 Bit im Speicher für die Speicherung ausschließlich positiver Zahlen. Dieser erweiterte Speicherplatz ermöglicht es, einen großen Wertebereich von 0 bis 4'294'967'295 abzudecken. Aufgrund seiner Fähigkeit, umfangreiche Zahlenwerte zu handhaben, findet unsigned long
häufig Verwendung bei der Zeitmessung, insbesondere in Verbindung mit der millis()
Funktion der Arduino IDE, die die Millisekunden seit dem Programmstart zurückgibt.
unsigned long last_millis = 3124591539;
Zum Kapitel springen float - 32 bit
Der float
Datentyp ist einzigartig, da er speziell für die Speicherung von Fließkommazahlen konzipiert wurde. Mit einem Speicherbedarf von 32 Bit ermöglicht float
die Darstellung von Zahlen mit Dezimalstellen, wobei der Wertebereich von etwa -3,4E+38 bis 3,4E+38 reicht. Aufgrund ihrer Fähigkeit, komplexe Berechnungen mit Bruchteilen auszuführen, sind float
Variablen besonders wertvoll in mathematischen und wissenschaftlichen Anwendungen. Jedoch sollte ihre Verwendung wohlüberlegt sein, da sie sowohl rechen- als auch speicherintensiver im Vergleich zu Ganzzahl-Datentypen sind. Dies gilt besonders in Umgebungen mit begrenzten Ressourcen, wie Mikrocontrollern.
float height = 1.75;
Zum Kapitel springen Erweiterte Datentypen
Zum Kapitel springen short - 16 bit
Ein short
ist ein Ganzzahl-Datentyp, der mindestens 16 Bit Speicherplatz belegt und Werte im Bereich von -32768 bis 32767 speichern kann. Es bietet eine kompakte Form zur Speicherung von Ganzzahlen, wenn der breitere Wertebereich von int
nicht benötigt wird.
short smallNumber = -12345;
Zum Kapitel springen double - 64 bit
Der Datentyp double
bietet eine höhere Präzision für Fließkommazahlen im Vergleich zu float
, mit einem Speicherbedarf von 64 Bit auf Plattformen wie dem Arduino Due. Auf den meisten 8-bit Mikrocontrollern (z.B. Arduino Uno) ist double
allerdings gleichbedeutend mit float
und beschränkt sich auf 32-Bit Präzision. double
ist ideal für Anwendungen, die eine hohe numerische Genauigkeit erfordern.
double precisionValue = 3.1415926535897932384626433832795;
Zum Kapitel springen long long - 64 bit
Der Datentyp long long erweitert den Wertebereich für Ganzzahlen deutlich, indem er 64 Bit (8 Byte) des Speicherplatzes nutzt. Er ist in der Lage, Werte zwischen -9'223'372'036'854'775'808 und 9'223'372'036'854'775'807 zu speichern. Diese erweiterte Kapazität macht long long besonders wertvoll für Anwendungen, die mit extrem großen Ganzzahlen arbeiten müssen, welche die Kapazität herkömmlicher Datentypen wie int und long überschreiten.
// Nutzt 'LL' zur Kennzeichnung als 'long long'
long long veryLargeNumber = -9223372036854775807LL;
Zum Kapitel springen unsigned long long - 64 bit
Parallel zum long long Datentyp gibt es den unsigned long long, der ebenfalls 64 Bit des Speichers belegt, jedoch ausschließlich positive Werte speichern kann. Der Wertebereich erstreckt sich von 0 bis 18'446'744'073'709'551'615. Die Nutzung von unsigned long long ist ideal, wenn Sie mit Zahlenwerten arbeiten, die über die Grenzen positiver Werte von long hinausgehen, ohne die Notwendigkeit, negative Zahlen zu berücksichtigen.
// Nutzt 'ULL' zur Kennzeichnung als 'unsigned long long'
unsigned long long veryLargePositiveNumber = 18446744073709551615ULL;
Zum Kapitel springen Höhere Datentypen und Konzepte
Zum Kapitel springen String
Im Gegensatz zu char
-Arrays, die für die Speicherung von Zeichenfolgen verwendet werden können, bieten String
-Objekte dynamische Speicherverwaltung und eine Vielzahl von Methoden für Operationen wie das Hinzufügen, Entfernen oder Suchen innerhalb von Strings. Die Verwendung von String
kann jedoch zu Fragmentierung des Speichers führen, weshalb sie mit Vorsicht eingesetzt werden sollte.
String greeting = "Hallo Welt!";
Zum Kapitel springen Array
Arrays sind Sammlungen von Elementen desselben Datentyps, die unter einem gemeinsamen Namen gespeichert werden. Sie ermöglichen die effiziente Verwaltung von Datensätzen und können mit jedem grundlegenden Datentyp wie int
, float
, char
etc. genutzt werden. Arrays spielen eine zentrale Rolle bei der Organisation und Verarbeitung von Daten in Arduino-Projekten.
// Array von Temperaturmesswerten für eine Woche
int temperatureReadings[7] = {22, 24, 23, 22, 25, 26, 23};
Zum Kapitel springen Structs
Mit Structs können benutzerdefinierte Datentypen erstellt werden, die Gruppen von Variablen unterschiedlicher Datentypen unter einem Namen zusammenfassen. Sie eignen sich hervorragend zur Darstellung von komplexeren Datenstrukturen, wie z.B. Sensordaten, die mehrere Attribute umfassen.
struct SensorData {
float temperature;
float humidity;
};
SensorData indoorClimate = {22.5, 48.7};
Serial.print("Temperatur: ");
Serial.print(indoorClimate.temperature);
Serial.print(", Feuchtigkeit: ");
Serial.println(indoorClimate.humidity);
Zum Kapitel springen Enums
Enums (Enumerationen) definieren einen Datentyp, der eine Menge von benannten Konstanten repräsentiert. Sie sind nützlich, um Code lesbarer und wartbarer zu machen, indem sie eine klare Bezeichnung für die Werte von Variablen bieten.
enum Days {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY};
Days today = WEDNESDAY;
// Gibt den numerischen Wert von 'WEDNESDAY' aus, typischerweise '2' in dieser Enumeration
Serial.println(today);
Zum Kapitel springen Zeigertypen und Speichermanagement
Zum Kapitel springen Pointer
Zeiger sind Variablen, die Speicheradressen speichern. Sie ermöglichen die direkte Interaktion mit dem Speicher und bieten leistungsfähige Mechanismen für die dynamische Speicherverwaltung und die Manipulation von Array-Daten. Zeiger können mit jedem Datentyp verwendet werden und sind ein fortgeschrittenes Werkzeug, das mit Vorsicht angewendet werden sollte.
int value = 30;
// 'ptr' enthält die Adresse von 'value'
int* ptr = &value;
// Dereferenzierung des Zeigers gibt den Wert von 'value' aus
Serial.print("Wert von 'value' über Zeiger: ");
Serial.println(*ptr);