Arduino-Befehle: Liste mit Syntax, Beispielen und Fehlern
Arduino-Befehle erklärt: pinMode, digitalWrite, analogRead, analogWrite, millis, Serial, map, tone, pulseIn und attachInterrupt mit Beispielen und Fehlern.
Arduino-Befehle sind fertige Funktionen, die dem Board sagen, was es tun soll: pinMode() macht einen Pin zum Ausgang, digitalWrite() schaltet eine LED ein, analogRead() liest einen Sensor und Serial.println() schickt eine Nachricht an den Computer. Die meisten Arduino-Sketches bestehen eigentlich nur aus rund zwanzig Grundbefehlen, die unterschiedlich kombiniert werden. Wenn du diese Befehle und ihre Bedeutung einmal richtig verstanden hast, kannst du jeden Code lesen, vom Blinken einer LED bis zum Roboterauto, und dein eigenes Projekt von Grund auf schreiben.
In dieser Anleitung haben wir die meistgenutzten Arduino-Befehle in vier Gruppen eingeteilt: Ein- und Ausgabe, Zeit, Mathematik und Kommunikation. Zu jedem Befehl findest du die Syntax, die Bedeutung der Parameter, ein kurzes Beispiel, das auf einem Arduino Uno kompiliert und läuft, und den Fehler, den Einsteiger am häufigsten machen. In den letzten Abschnitten sehen wir uns außerdem an, wie sich dieselben Befehle auf dem ESP32 anders verhalten und wie ihre MicroPython-Entsprechungen auf dem Raspberry Pi Pico aussehen.

Was ist ein Arduino-Befehl und wie läuft ein Sketch ab?
Arduino-Code basiert auf C/C++; das meiste, was wir „Befehle“ nennen, sind eigentlich Funktionen, die dir der Arduino-Core fertig bereitstellt. Eine Funktion bekommt Parameter in Klammern (zum Beispiel eine Pinnummer und einen Wert), und manche liefern ein Ergebnis zurück: digitalRead() den Zustand eines Pins, millis() die vergangene Zeit. Jeder Arduino-Sketch hat zwei Pflichtfunktionen: setup() läuft nur einmal, wenn das Board eingeschaltet oder zurückgesetzt wird, und loop() wiederholt sich danach endlos. Vorbereitungen wie Pin-Einstellungen und Serial.begin() gehören in setup(), alles, was ständig passieren soll, in loop().
1// Her Arduino programı bu iki fonksiyondan oluşur / Every Arduino sketch has these two functions
2void setup() {
3 // Açılışta ya da resetten sonra bir kez çalışır / Runs once at power-up or after reset
4 pinMode(13, OUTPUT); // dahili LED pini çıkış / built-in LED pin as output
5}
6
7void loop() {
8 // Sonsuza kadar tekrar eder / Repeats forever
9 digitalWrite(13, HIGH); // LED'i yak / turn the LED on
10 delay(500); // 500 ms bekle / wait 500 ms
11 digitalWrite(13, LOW); // LED'i söndür / turn the LED off
12 delay(500);
13}Wenn du drei Regeln von Anfang an beachtest, ersparst du dir viele Kompilierfehler: Befehle unterscheiden Groß- und Kleinschreibung (schreibst du digitalwrite, bekommst du den Fehler „'digitalwrite' was not declared in this scope“), jede Anweisung endet mit einem Semikolon, und Text steht in doppelten, einzelne Zeichen in einfachen Anführungszeichen. Zu Variablentypen und Strukturen wie if und for schau dir die Grundlagen der Arduino-Programmierung an.
Liste der Arduino-Befehle: Tabellen nach Kategorien
Die vier Tabellen unten fassen fast alle Befehle zusammen, die du in alltäglichen Projekten brauchst. Die erste Gruppe sind die Ein- und Ausgabebefehle; sie legen die Aufgabe eines Pins fest, geben eine Spannung aus oder lesen einen Wert ein. Die Pinnummern deines Boards findest du im Werkzeug Pinout.
| Befehl | Syntax | Was er macht | Beispiel |
|---|---|---|---|
| pinMode | pinMode(pin, modus) | Macht einen Pin zum Ein- oder Ausgang | pinMode(13, OUTPUT); |
| digitalWrite | digitalWrite(pin, wert) | Setzt einen Pin auf HIGH (5 V) oder LOW (0 V) | digitalWrite(13, HIGH); |
| digitalRead | digitalRead(pin) | Liest, ob ein Pin HIGH oder LOW ist | int b = digitalRead(2); |
| analogRead | analogRead(pin) | Wandelt 0–5 V in eine Zahl von 0 bis 1023 um | int v = analogRead(A0); |
| analogWrite | analogWrite(pin, wert) | Erzeugt ein PWM-Signal von 0 bis 255 | analogWrite(9, 128); |
| analogReference | analogReference(typ) | Wählt die Referenzspannung für analogRead | analogReference(INTERNAL); |
| tone / noTone | tone(pin, frequenz, dauer) | Erzeugt einen Ton per Rechtecksignal, noTone stoppt ihn | tone(8, 440, 500); |
| pulseIn | pulseIn(pin, wert, timeout) | Misst die Länge eines Impulses in µs | pulseIn(10, HIGH, 30000); |
| shiftOut | shiftOut(datenPin, taktPin, reihenfolge, byte) | Schiebt ein Byte Bit für Bit hinaus (z. B. an einen 74HC595) | shiftOut(11, 12, MSBFIRST, 255); |
| attachInterrupt | attachInterrupt(interrupt, funktion, modus) | Ruft sofort eine Funktion auf, wenn sich ein Pin ändert | attachInterrupt(digitalPinToInterrupt(2), say, FALLING); |
Die zweite Gruppe sind die Zeitbefehle. Den Unterschied zwischen delay(), das wartet, und millis() sowie micros(), die Zeit messen, zu verstehen, ist der Schlüssel zu einem flüssig laufenden Sketch.
| Befehl | Syntax | Was er macht | Achtung |
|---|---|---|---|
| delay | delay(ms) | Wartet die angegebenen Millisekunden | Das Programm steht in dieser Zeit still |
| delayMicroseconds | delayMicroseconds(us) | Wartet einige Mikrosekunden | Genau zwischen 3 und 16383 µs |
| millis | millis() | Liefert die Millisekunden seit dem Start | unsigned long; läuft nach etwa 49,7 Tagen über |
| micros | micros() | Liefert die Mikrosekunden seit dem Start | Auf dem Uno in 4-µs-Schritten, Überlauf nach etwa 70 Minuten |
Die dritte Gruppe sind die Mathematikbefehle; mit ihnen rechnest du einen Sensorwert in einen anderen Bereich um, begrenzt ihn oder erzeugst eine Zufallszahl. Die vierte Gruppe, die Kommunikationsbefehle, sorgt dafür, dass das Board Daten mit dem Computer und anderen Geräten austauschen kann.
| Befehl | Syntax | Was er macht | Beispielergebnis |
|---|---|---|---|
| map | map(x, vonMin, vonMax, nachMin, nachMax) | Rechnet einen Bereich in einen anderen um | map(512, 0, 1023, 0, 255) → 127 |
| constrain | constrain(x, unten, oben) | Hält einen Wert zwischen zwei Grenzen | constrain(300, 0, 255) → 255 |
| min / max | min(a, b) / max(a, b) | Liefert den kleineren oder größeren Wert | min(7, 3) → 3 |
| abs | abs(x) | Betrag (Absolutwert) | abs(-12) → 12 |
| pow / sqrt / sq | pow(basis, exponent), sqrt(x), sq(x) | Potenz, Quadratwurzel, Quadrat | pow(2, 10) → 1024.0 |
| random | random(min, max) | Zufällige Ganzzahl (max nicht enthalten) | random(1, 7) → 1 bis 6 |
| randomSeed | randomSeed(startwert) | Ändert den Startpunkt der Zufallsfolge | randomSeed(analogRead(A3)); |
| Befehl | Was er macht | Beispiel |
|---|---|---|
| Serial.begin(geschwindigkeit) | Öffnet die serielle Schnittstelle mit der angegebenen Baudrate | Serial.begin(9600); |
| Serial.print(daten) | Gibt Daten aus und bleibt in derselben Zeile | Serial.print(temperatur); |
| Serial.println(daten) | Gibt Daten aus und springt in die nächste Zeile | Serial.println("Hallo"); |
| Serial.available() | Liefert die Anzahl der Bytes, die auf das Lesen warten | if (Serial.available() > 0) |
| Serial.read() | Liest ein Byte, liefert -1, wenn keine Daten da sind | char c = Serial.read(); |
| Serial.readStringUntil(z) | Liest Text bis zu einem bestimmten Zeichen | String s = Serial.readStringUntil('\n'); |
| Serial.parseInt() | Holt eine Ganzzahl aus dem empfangenen Text | int n = Serial.parseInt(); |
| Serial.write(byte) | Sendet ein rohes Byte | Serial.write(65); // 'A' |
| Wire.begin() | Startet den I2C-Bus (Wire.h) | Wire.begin(); |
| SPI.begin() | Startet den SPI-Bus (SPI.h) | SPI.begin(); |
pinMode(): die Aufgabe eines Pins festlegen
pinMode(pin, modus) legt fest, ob ein digitaler Pin Ein- oder Ausgang ist, und steht meist einmal in setup(). Es gibt drei Modi: OUTPUT macht den Pin zum Ausgang (für LED, Summer oder Relais), INPUT zu einem hochohmigen Eingang (für Schaltungen mit externem Pull-up- oder Pull-down-Widerstand), und INPUT_PULLUP macht ihn zum Eingang und verbindet einen internen Widerstand von etwa 20–50 kΩ mit 5 V. Auch die analogen Pins (A0–A5) lassen sich mit pinMode als Digitalpins nutzen; pinMode(A0, OUTPUT) ist zum Beispiel ein gültiger Befehl.
digitalWrite() und digitalRead(): digitale Aus- und Eingabe
digitalWrite(pin, HIGH) legt einen Ausgang auf dem Uno auf 5 V, digitalWrite(pin, LOW) auf 0 V. Bis zu 20 mA pro Pin sind unbedenklich (der absolute Grenzwert liegt bei 40 mA); schließe eine LED immer mit Vorwiderstand an, den passenden Wert findest du mit dem LED-Vorwiderstandsrechner. digitalRead(pin) prüft die Spannung am Pin und liefert HIGH oder LOW; auf dem Uno gilt grob alles über 3 V als HIGH und alles unter 1,5 V als LOW. Im folgenden Beispiel leuchtet die eingebaute LED, wenn du den Taster an D2 drückst:
1const int BUTON_PIN = 2; // buton: bir ucu D2, diğer ucu GND / button: one leg to D2, the other to GND
2const int LED_PIN = 13; // dahili LED / built-in LED
3
4void setup() {
5 pinMode(BUTON_PIN, INPUT_PULLUP); // dahili pull-up direnci açık / internal pull-up resistor enabled
6 pinMode(LED_PIN, OUTPUT);
7}
8
9void loop() {
10 int durum = digitalRead(BUTON_PIN); // HIGH ya da LOW döner / returns HIGH or LOW
11 if (durum == LOW) { // pull-up ile basılı = LOW / with pull-up, pressed = LOW
12 digitalWrite(LED_PIN, HIGH);
13 } else {
14 digitalWrite(LED_PIN, LOW);
15 }
16}Mit INPUT_PULLUP ist die Logik umgekehrt: Ist der Taster losgelassen, liest der Pin dank des internen Widerstands HIGH, wird er gedrückt, liest er LOW, weil er mit GND verbunden ist. Schließt du den Taster ohne Widerstand im Modus INPUT an, hängt der Pin in der Luft und digitalRead() liefert zufällige Werte; schon wenn du die Hand näherst, kann sich das Ergebnis ändern. Zum Prellen und zur richtigen Beschaltung lies Taster am Arduino anschließen.
analogRead() und analogWrite(): analoge Eingabe und PWM
analogRead(pin) wandelt mit einem 10-Bit-Wandler (ADC) eine Spannung zwischen 0 und 5 V an den Pins A0–A5 in eine Zahl von 0 bis 1023 um. Eine Messung dauert etwa 100 µs, du schaffst also rund 10.000 Messungen pro Sekunde. Um die Zahl in eine Spannung umzurechnen, nimmst du Wert × 5,0 / 1023; ein Messwert von 512 bedeutet zum Beispiel etwa 2,5 V. Die Referenzspannung lässt sich mit analogReference() ändern: Die Option INTERNAL nutzt beim Uno die interne 1,1-V-Referenz und verbessert die Auflösung bei kleinen Spannungen. Mehr zu Auflösung und Referenz findest du unter ADC und Analog-Digital-Wandlung.
Trotz seines Namens erzeugt analogWrite(pin, wert) keine echte analoge Spannung. Es schaltet den Pin sehr schnell ein und aus und erzeugt so ein PWM-Signal: 0 heißt immer aus, 255 immer an und 127 etwa zur Hälfte an. Aus diesem Mittelwert ergibt sich, dass eine LED für unser Auge halb hell wirkt und ein Motor langsam dreht. Auf dem Uno liefern nur die mit ~ markierten Pins 3, 5, 6, 9, 10 und 11 PWM; die Frequenz beträgt an den meisten Pins 490 Hz, an den Pins 5 und 6 980 Hz. analogWrite() schaltet den Pin selbst auf Ausgang, pinMode ist also nicht nötig. Der folgende Code stellt die Helligkeit einer LED mit einem Potentiometer ein und schreibt den Messwert samt Spannung in den seriellen Monitor; Details zu Tastgrad und Frequenz findest du unter Was ist PWM?.
1const int POT_PIN = A0; // potansiyometrenin orta bacağı / potentiometer wiper
2const int LED_PIN = 9; // ~9 PWM pini + 220 ohm direnç / ~9 PWM pin + 220 ohm resistor
3
4void setup() {
5 Serial.begin(9600);
6}
7
8void loop() {
9 int ham = analogRead(POT_PIN); // 0-1023 arası / between 0 and 1023
10 float volt = ham * (5.0 / 1023.0); // sayıyı gerilime çevir / convert the reading to volts
11 analogWrite(LED_PIN, ham / 4); // 0-1023 -> 0-255 PWM parlaklığı / 0-1023 -> 0-255 PWM brightness
12
13 Serial.print(F("Ham / raw: "));
14 Serial.print(ham);
15 Serial.print(F(" Gerilim / voltage: "));
16 Serial.print(volt, 2); // 2 ondalık basamak / 2 decimal places
17 Serial.println(F(" V"));
18 delay(200);
19}delay(), millis() und micros(): Zeitbefehle
delay(ms) wartet die angegebenen Millisekunden, und in dieser Zeit läuft keine andere Zeile in loop(); delay(1000) ist eine volle Sekunde Pause. Für kurze Wartezeiten im Mikrosekundenbereich gibt es delayMicroseconds(), das zwischen 3 und 16383 µs genau ist. millis() dagegen wartet nicht, sondern liefert die Zeit seit dem Start des Boards in Millisekunden. Speichere das Ergebnis immer in einer Variable vom Typ unsigned long: Nimmst du int, läuft der Wert auf dem Uno über, sobald er 32.767 übersteigt, also nach etwa 33 Sekunden, und deine Zeitsteuerung gerät durcheinander. millis() springt etwa alle 49,7 Tage auf null zurück; die Subtraktionsmethode unten funktioniert auch über diesen Überlauf hinweg korrekt.
1const int LED_PIN = 13;
2const unsigned long ARALIK = 500; // yanıp sönme aralığı (ms) / blink interval (ms)
3unsigned long oncekiZaman = 0; // son değişim anı / time of the last toggle
4
5void setup() {
6 pinMode(LED_PIN, OUTPUT);
7}
8
9void loop() {
10 unsigned long simdi = millis();
11 if (simdi - oncekiZaman >= ARALIK) { // taşmada da doğru çalışır / safe across overflow
12 oncekiZaman = simdi;
13 digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // LED'i tersine çevir / toggle the LED
14 }
15 // Burada buton, sensör ve ekran işleri de yapılabilir / button, sensor and display tasks can run here
16}Bei diesem Muster bleibt loop() nie stehen; während die LED weiter blinkt, kannst du in derselben Schleife einen Taster lesen, einen Sensor messen und ein Display aktualisieren. micros() funktioniert genauso in Mikrosekunden; auf dem Uno zählt es in 4-µs-Schritten und läuft nach etwa 70 Minuten über. Wie du mehrere Aufgaben gleichzeitig erledigst, erklären wir ausführlich in Arduino millis() statt delay().
Serial.begin(), Serial.print() und Serial.read(): serielle Kommunikation
Mit den Serial-Befehlen spricht der Arduino über das USB-Kabel mit deinem Computer, und sie sind dein wichtigstes Werkzeug zur Fehlersuche. Serial.begin(9600) öffnet die serielle Schnittstelle mit 9600 Bit pro Sekunde; stimmt die Geschwindigkeit im seriellen Monitor nicht überein, siehst du nur wirre Zeichen. Serial.print() gibt Daten aus und bleibt in derselben Zeile, Serial.println() springt nach der Ausgabe in die nächste Zeile. Mit einem zweiten Parameter wählst du das Format: Serial.print(78, HEX) gibt „4E“ aus, Serial.print(78, BIN) „1001110“, und Serial.print(3.14159, 3) zeigt „3.142“ (bei Kommazahlen sind standardmäßig 2 Nachkommastellen eingestellt). Feste Texte in F("...") zu schreiben spart Platz in den 2 KB RAM des Uno.
Zum Lesen prüfst du zuerst mit Serial.available(), ob Bytes im Puffer warten; der Empfangspuffer des Uno ist 64 Byte groß. Serial.read() holt ein einzelnes Byte aus diesem Puffer und liefert -1, wenn nichts zu lesen ist. Der folgende Code schaltet die LED mit den Zeichen 1 und 0 ein und aus, die du über den seriellen Monitor sendest:
1const int LED_PIN = 13;
2
3void setup() {
4 Serial.begin(9600); // Seri Monitör de 9600 olmalı / Serial Monitor must be 9600 too
5 pinMode(LED_PIN, OUTPUT);
6 Serial.println(F("1: LED açık / on, 0: LED kapalı / off"));
7}
8
9void loop() {
10 if (Serial.available() > 0) { // tamponda bayt var mı? / any bytes waiting?
11 char c = Serial.read(); // ilk baytı al / read the first byte
12 if (c == '1') { // '1' karakteri, 1 sayısı değil / the character '1', not the number 1
13 digitalWrite(LED_PIN, HIGH);
14 Serial.println(F("LED açık / on"));
15 } else if (c == '0') {
16 digitalWrite(LED_PIN, LOW);
17 Serial.println(F("LED kapalı / off"));
18 }
19 // '\n' ve '\r' gibi diğer karakterler atlanır / other characters such as '\n' and '\r' are ignored
20 }
21}Beachte, dass mit '1' verglichen wird (einfache Anführungszeichen, also ein Zeichen): Die 1, die du auf der Tastatur eingibst, entspricht in der ASCII-Tabelle der Zahl 49, deshalb ist die Bedingung c == 1 nie wahr. Für mehrstellige Zahlen kannst du Serial.parseInt() verwenden, für eine ganze Zeile Serial.readStringUntil('\n'). Zu Zeilenende-Einstellungen, Baudrate und seriellem Plotter lies Seriellen Monitor des Arduino benutzen.
map() und constrain(): Werte umrechnen und begrenzen
map(wert, vonMin, vonMax, nachMin, nachMax) überträgt eine Zahl proportional von einem Bereich in einen anderen. Dahinter steckt diese Formel: (x − vonMin) × (nachMax − nachMin) / (vonMax − vonMin) + nachMin. map(512, 0, 1023, 0, 255) ergibt zum Beispiel 127 und nicht 127,6, weil map() nur mit Ganzzahlen rechnet und den Nachkommaanteil abschneidet. Indem du den Zielbereich umdrehst, erhältst du einen umgekehrten Zusammenhang: map(x, 0, 1023, 255, 0). map() begrenzt das Ergebnis nicht; liegt der Eingang außerhalb des angegebenen Bereichs, liegt auch der Ausgang außerhalb. Deshalb kombiniert man es meist mit constrain(x, unten, oben).
1const int LDR_PIN = A0; // LDR + 10k gerilim bölücü / LDR + 10k voltage divider
2const int LED_PIN = 9; // ~9 PWM pini / ~9 PWM pin
3
4void setup() {
5 pinMode(LED_PIN, OUTPUT);
6}
7
8void loop() {
9 int isik = analogRead(LDR_PIN); // odada ölçülen aralık ~200-800 / measured range in the room ~200-800
10 int pwm = map(isik, 200, 800, 255, 0); // karanlıkta parlak, aydınlıkta sönük / bright in the dark, dim in the light
11 pwm = constrain(pwm, 0, 255); // aralık dışı değerleri kes / clip out-of-range values
12 analogWrite(LED_PIN, pwm);
13 delay(20);
14}In diesem Beispiel liefert der LDR im Zimmer Werte zwischen 200 und 800. Fällt der Wert nachts auf 100, berechnet map() 297; ohne constrain() bekäme analogWrite() diesen Wert außerhalb des Bereichs 0–255. Auf dem Uno führt so ein Wert je nach Pin zu unterschiedlichen, unerwarteten Ergebnissen: An den Pins 3, 5, 6 und 11, die 8-Bit-Timer nutzen, läuft 297 über und verhält sich wie 41, sodass die LED bei völliger Dunkelheit fast ausgeht, statt hell zu leuchten. Weil constrain(), min(), max() und abs() auf dem Uno als Makros definiert sind, schreib kein x++ und keinen anderen Funktionsaufruf in die Klammern; der Ausdruck kann mehrfach ausgewertet werden und unerwartete Ergebnisse liefern. Die Beschaltung des LDR findest du unter LDR-Lichtsensor.
tone() und noTone(): Töne mit dem Summer erzeugen
tone(pin, frequenz, dauer) erzeugt an einem Pin ein Rechtecksignal mit 50 % Tastgrad und bringt einen passiven Summer oder einen kleinen Lautsprecher in dieser Frequenz zum Klingen. Die Dauer wird in Millisekunden angegeben und ist optional; ohne sie klingt der Ton, bis du noTone(pin) aufrufst. Ein wichtiges Detail: tone() wartet nicht, sondern startet den Ton und springt sofort zur nächsten Zeile. Spielst du mehrere Noten nacheinander, brauchst du deshalb nach jedem tone()-Aufruf ein delay(), das mindestens so lang ist wie die Note, sonst hörst du nur die letzte.
1const int BUZZER_PIN = 8; // pasif buzzer'ın + ucu / passive buzzer + leg
2
3void setup() {
4 int notalar[] = {262, 294, 330, 349, 392}; // Do Re Mi Fa Sol (Hz) / C D E F G (Hz)
5 for (int i = 0; i < 5; i++) {
6 tone(BUZZER_PIN, notalar[i], 200); // 200 ms çal / play for 200 ms
7 delay(250); // tone() beklemez, sen bekle / tone() does not wait, so you do
8 }
9 noTone(BUZZER_PIN); // sesi kapat / stop the sound
10}
11
12void loop() {
13}- Frequenzgrenzen: Auf dem Uno lassen sich keine Töne unter 31 Hz erzeugen, die Obergrenze liegt bei 65.535 Hz; mit einem Summer ist der sinnvolle Bereich etwa 100–5000 Hz.
- Nur ein Ton: Es kann immer nur ein Pin gleichzeitig einen Ton spielen; für einen Ton an einem anderen Pin musst du den vorherigen erst mit noTone() stoppen.
- PWM-Konflikt: Auf dem Uno nutzt tone() den Timer2, deshalb funktioniert analogWrite() an den Pins 3 und 11 nicht richtig, solange ein Ton läuft.
- Aktiver Summer: Weil er einen eigenen Oszillator hat, lässt sich seine Frequenz nicht mit tone() ändern; einen aktiven Summer schaltest du einfach mit digitalWrite() ein und aus. Die Unterschiede erklärt Was ist ein Buzzer?.
pulseIn(): Impulslängen messen
pulseIn(pin, HIGH) wartet, bis der Pin HIGH wird, misst, wie lange er HIGH bleibt, und liefert das Ergebnis in Mikrosekunden; es kann Impulse von 10 µs bis 3 Minuten Länge messen. Die bekannteste Anwendung ist der Ultraschall-Abstandssensor HC-SR04: Der Sensor gibt einen Impuls aus, der so lang ist wie die Laufzeit des Schalls hin und zurück. Schall breitet sich in Luft mit etwa 343 m/s aus, also 0,0343 cm/µs; da der Weg hin und zurück führt, gilt Abstand = Dauer × 0,0343 / 2.
1const int TRIG_PIN = 9;
2const int ECHO_PIN = 10;
3
4void setup() {
5 Serial.begin(9600);
6 pinMode(TRIG_PIN, OUTPUT);
7 pinMode(ECHO_PIN, INPUT);
8}
9
10void loop() {
11 digitalWrite(TRIG_PIN, LOW);
12 delayMicroseconds(2);
13 digitalWrite(TRIG_PIN, HIGH); // 10 µs tetik darbesi / 10 µs trigger pulse
14 delayMicroseconds(10);
15 digitalWrite(TRIG_PIN, LOW);
16
17 unsigned long sure = pulseIn(ECHO_PIN, HIGH, 30000UL); // en fazla 30 ms bekle / wait at most 30 ms
18 if (sure == 0) {
19 Serial.println(F("Menzil dışı / out of range"));
20 } else {
21 float mesafe = sure * 0.0343 / 2.0; // ses hızı 343 m/s, gidiş-dönüş / speed of sound 343 m/s, round trip
22 Serial.print(mesafe, 1);
23 Serial.println(F(" cm"));
24 }
25 delay(100);
26}Der dritte Parameter, das Timeout, ist sehr wichtig. Fehlt er, wartet pulseIn() bei ausbleibendem Impuls 1 Sekunde und liefert 0; löst sich das Sensorkabel, friert das ganze Programm in jedem Durchlauf eine Sekunde ein. Ein Timeout von 30000 µs entspricht etwa 5 Metern und reicht für die 4 Meter Reichweite des HC-SR04. Anschluss und Genauigkeit des Sensors erklärt HC-SR04 Ultraschallsensor.
attachInterrupt(): sofort reagieren mit Interrupts
attachInterrupt(digitalPinToInterrupt(pin), funktion, modus) führt die angegebene Funktion in dem Moment aus, in dem sich ein Pin ändert, ganz egal, was loop() gerade tut. Diese Funktion heißt Interrupt-Service-Routine (ISR). Der Modus kann vier Werte haben: RISING löst beim Wechsel von LOW nach HIGH aus, FALLING beim Wechsel von HIGH nach LOW, CHANGE bei jeder Änderung und LOW, solange der Pin LOW bleibt. Auf dem Uno und Nano können nur die Pins D2 und D3 so einen Interrupt auslösen; beim Mega sind es die Pins 2, 3, 18, 19, 20 und 21. Das ist ideal, um einen schnell drehenden Drehgeber, die Impulse eines Windmessers oder einen sehr kurzen Tastendruck nicht zu verpassen.
1const int BUTON_PIN = 2; // Uno'da kesme pinleri: 2 ve 3 / interrupt pins on the Uno: 2 and 3
2volatile unsigned long sayac = 0; // ISR'de değişen değişken volatile olmalı / variables changed in an ISR must be volatile
3
4void say() { // kesme fonksiyonu (ISR): kısa tut / interrupt service routine: keep it short
5 sayac++;
6}
7
8void setup() {
9 Serial.begin(9600);
10 pinMode(BUTON_PIN, INPUT_PULLUP);
11 attachInterrupt(digitalPinToInterrupt(BUTON_PIN), say, FALLING); // HIGH'dan LOW'a geçişte / on a HIGH-to-LOW edge
12}
13
14void loop() {
15 noInterrupts(); // 4 baytlık değeri güvenle kopyala / copy the 4-byte value safely
16 unsigned long kopya = sayac;
17 interrupts();
18
19 Serial.print(F("Basma sayısı / presses: "));
20 Serial.println(kopya);
21 delay(500);
22}random() und randomSeed(): Zufallszahlen erzeugen
random(max) liefert eine zufällige Ganzzahl zwischen 0 und max−1, random(min, max) eine zwischen min und max−1; die Obergrenze ist im Ergebnis nicht enthalten. Für einen Würfel von 1 bis 6 schreibst du deshalb random(1, 7). Der Arduino erzeugt keinen echten Zufall, sondern berechnet eine Zahlenfolge mit einer festen Formel; rufst du randomSeed() nicht auf, siehst du nach jedem Start dieselben Zahlen in derselben Reihenfolge. Das Rauschen eines unbeschalteten Analogpins als Startwert zu nutzen, löst das in der Praxis:
1void setup() {
2 Serial.begin(9600);
3 randomSeed(analogRead(A3)); // boştaki A3 pininin gürültüsü / noise from the unconnected A3 pin
4}
5
6void loop() {
7 int zar = random(1, 7); // 1-6 arası; üst sınır dahil değil / 1 to 6; the upper bound is exclusive
8 Serial.print(F("Zar / dice: "));
9 Serial.println(zar);
10 delay(1000);
11}Arduino-Befehle auf dem ESP32: worauf du achten musst
Der ESP32 wird in der Arduino IDE mit denselben Befehlen programmiert, und der meiste Code in diesem Artikel läuft direkt, sobald du die Pinnummern anpasst. Weil die Hardware anders ist, verhalten sich manche Befehle aber anders. Der wichtigste Unterschied ist die Spannung: Die Pins des ESP32 arbeiten mit 3,3 V, digitalWrite(pin, HIGH) gibt 3,3 V aus, und 5-V-Signale dürfen nicht direkt an die Pins. Mehr über das Board erfährst du unter Was ist der ESP32?.
| Befehl | Arduino Uno | ESP32 |
|---|---|---|
| digitalWrite(pin, HIGH) | 5 V | 3,3 V |
| analogRead() | 10 Bit, 0–1023, A0–A5 | 12 Bit, 0–4095; bei aktivem WLAN nur die ADC1-Pins (GPIO 32–39) |
| analogWrite() | Nur die ~-Pins (3, 5, 6, 9, 10, 11), 490/980 Hz | Fast jeder ausgangsfähige GPIO; Frequenz über ledcAttach(pin, frequenz, aufloesung) |
| attachInterrupt() | Nur D2 und D3 | Alle GPIOs; die ISR bekommt IRAM_ATTR |
| tone() | Nutzt Timer2, stört PWM an 3 und 11 | Läuft über die LEDC-Hardware |
| Serial.begin() | Meist 9600 | Meist 115200 (auch die Bootmeldungen kommen mit dieser Geschwindigkeit) |
| delay() | Hält den Prozessor komplett im Warten | Gibt die Zeit an FreeRTOS ab; WLAN läuft im Hintergrund weiter |
1const int POT_PIN = 34; // ADC1 pini, Wi-Fi açıkken de okur / ADC1 pin, works with Wi-Fi on
2const int LED_PIN = 2; // çoğu DevKit'te dahili LED / onboard LED on most DevKits
3const int BUTON_PIN = 4; // butonun diğer ucu GND / other button leg to GND
4
5volatile bool basildi = false;
6
7void IRAM_ATTR butonISR() { // ESP32'de ISR IRAM'e yerleşmeli / on the ESP32 the ISR should live in IRAM
8 basildi = true;
9}
10
11void setup() {
12 Serial.begin(115200);
13 pinMode(BUTON_PIN, INPUT_PULLUP);
14 attachInterrupt(digitalPinToInterrupt(BUTON_PIN), butonISR, FALLING); // her GPIO kesme destekler / every GPIO supports interrupts
15}
16
17void loop() {
18 int ham = analogRead(POT_PIN); // 0-4095 (12 bit)
19 analogWrite(LED_PIN, map(ham, 0, 4095, 0, 255)); // 8 bit PWM / 8-bit PWM
20 if (basildi) {
21 basildi = false;
22 Serial.println("Butona basıldı / button pressed");
23 }
24 Serial.println(ham);
25 delay(200);
26}Da analogRead() auf dem ESP32 Werte von 0 bis 4095 liefert, ändert sich auch der map()-Bereich entsprechend. Das IRAM_ATTR vor der ISR legt den Code in den schnellen internen Speicher; fehlt es, kann das Board in manchen Situationen mit einem „Guru Meditation Error“ neu starten. Die Analogmessungen des ESP32 sind an den Rändern des Bereichs (um 0 V und 3,3 V) nicht linear; brauchst du eine genauere Messung, liefert die Funktion analogReadMilliVolts() einen kalibrierten Wert in Millivolt.
Raspberry Pi Pico: MicroPython-Entsprechungen der Arduino-Befehle
Programmierst du den Raspberry Pi Pico mit der Arduino IDE (Core arduino-pico), funktionieren alle Befehle aus diesem Artikel unter demselben Namen; analogRead() liefert standardmäßig 10 Bit und analogWrite() erzeugt 1 kHz PWM. Meist wird der Pico jedoch mit MicroPython genutzt. Dort schreibst du die Befehle mit Objekten aus den Modulen machine und time; die Logik ist dieselbe, nur die Syntax ändert sich. Auch die Pins des Pico arbeiten mit 3,3 V, die analogen Eingänge sind GP26, GP27 und GP28. Für den Einstieg lies Was ist der Raspberry Pi Pico?.
| Arduino-Befehl | MicroPython-Entsprechung | Hinweis |
|---|---|---|
| pinMode(15, OUTPUT) | led = Pin(15, Pin.OUT) | Das Pin-Objekt wird einmal angelegt |
| pinMode(14, INPUT_PULLUP) | btn = Pin(14, Pin.IN, Pin.PULL_UP) | Interner Pull-up-Widerstand |
| digitalWrite(15, HIGH) | led.value(1) | led.on() geht auch |
| digitalRead(14) | btn.value() | Liefert 0 oder 1 |
| analogRead(A0) | ADC(26).read_u16() | Liefert 0–65535 |
| analogWrite(15, 128) | PWM(Pin(15)).duty_u16(32768) | Tastgrad von 0 bis 65535 |
| delay(500) | time.sleep_ms(500) | time.sleep(0.5) geht auch |
| millis() | time.ticks_ms() | Differenzen mit time.ticks_diff() |
| Serial.println(x) | print(x) | Erscheint in der Thonny-Shell |
| tone(pin, 440) | pwm.freq(440) und pwm.duty_u16(32768) | Stumm schalten mit duty_u16(0) |
| pulseIn(pin, HIGH, 30000) | machine.time_pulse_us(pin, 1, 30000) | Liefert bei Timeout einen negativen Wert |
| attachInterrupt(...) | btn.irq(trigger=Pin.IRQ_FALLING, handler=f) | f bekommt das Pin-Objekt als Parameter |
| random(1, 7) | random.randint(1, 6) | Obergrenze ist enthalten |
| map() / constrain() | Nicht eingebaut, du schreibst sie selbst | Für constrain: min(max(x, 0), 255) |
1from machine import Pin, ADC, PWM
2import time
3
4led = PWM(Pin(15)) # pinMode + analogWrite karşılığı / pinMode + analogWrite equivalent
5led.freq(1000) # 1 kHz PWM
6buton = Pin(14, Pin.IN, Pin.PULL_UP) # INPUT_PULLUP karşılığı / INPUT_PULLUP equivalent
7pot = ADC(26) # GP26 = ADC0
8
9def map_deger(x, giris_min, giris_max, cikis_min, cikis_max): # Arduino map() karşılığı / Arduino map() equivalent
10 return (x - giris_min) * (cikis_max - cikis_min) // (giris_max - giris_min) + cikis_min
11
12onceki = time.ticks_ms() # millis() karşılığı / millis() equivalent
13while True:
14 ham = pot.read_u16() # 0-65535 (analogRead)
15 led.duty_u16(ham) # parlaklık / brightness (analogWrite)
16 if buton.value() == 0: # digitalRead; basılı = 0 / pressed = 0
17 print("Butona basıldı / button pressed")
18 if time.ticks_diff(time.ticks_ms(), onceki) >= 1000: # saniyede bir / once a second
19 onceki = time.ticks_ms()
20 print("Yüzde / percent:", map_deger(ham, 0, 65535, 0, 100))
21 time.sleep_ms(50) # delay(50)Wie die Tabelle zeigt, schließt random.randint(1, 6) in MicroPython die Obergrenze ein und liefert dasselbe Ergebnis wie random(1, 7) beim Arduino; time.ticks_diff() bietet dieselbe Überlaufsicherheit wie die millis()-Subtraktion. Genau diese kleinen Unterschiede sorgen beim Wechsel zwischen den beiden Plattformen am häufigsten für Verwirrung. Weitere Grundbefehle von MicroPython findest du unter MicroPython-Grundlagen.
Projektideen mit diesen Befehlen
- Ampel: Schalte mit pinMode(), digitalWrite() und delay() drei LEDs nacheinander; Schritt für Schritt erklären wir das in Arduino-Ampel.
- Digitaler Würfel: Erzeuge mit random() eine Zahl von 1 bis 6 und zeige das Ergebnis per Tastendruck mit LEDs oder auf einer 7-Segment-Anzeige an.
- Einparkhilfe: Miss den Abstand mit pulseIn(), rechne ihn mit map() in einen Pieptakt um und gib mit tone() einen Warnton aus.
- Automatisches Nachtlicht: Lies die Helligkeit mit analogRead() und stelle mit map() und constrain() die Helligkeit über analogWrite() ein.
- Fernbedienung über die serielle Schnittstelle: Steuere mit Serial.read() und Befehlen vom Computer eine LED, ein Relais oder einen Servomotor.
- Reaktionstest: Lass mit random() zu einem zufälligen Zeitpunkt eine LED aufleuchten und miss deine Reaktionszeit mit attachInterrupt() und millis() auf die Millisekunde genau.
Häufige Fehler und ihre Lösungen
| Fehler | Symptom | Lösung |
|---|---|---|
| pinMode() vergessen | Die LED leuchtet sehr schwach oder gar nicht | pinMode(pin, OUTPUT) in setup() schreiben |
| Taster ohne Widerstand im Modus INPUT | digitalRead() liefert zufällig 0 und 1 | INPUT_PULLUP verwenden; gedrückt ergibt LOW |
| Tippfehler im Befehlsnamen | 'digitalwrite' was not declared in this scope | Auf Groß- und Kleinschreibung achten: digitalWrite |
| Baudrate passt nicht | Wirre Zeichen im seriellen Monitor | Geschwindigkeit des seriellen Monitors an Serial.begin() anpassen |
| analogWrite() an einem Pin ohne PWM | Die LED ist nur ganz an oder ganz aus | Einen Pin mit ~ nehmen (3, 5, 6, 9, 10, 11) |
| millis() in einer int-Variable | Die Zeitsteuerung versagt nach etwa 33 Sekunden | unsigned long verwenden |
| Würfel mit random(1, 6) | Die 6 kommt nie | random(1, 7) schreiben; die Obergrenze ist ausgeschlossen |
| Kommazahlen von map() erwarten | Das Ergebnis ist immer ganzzahlig, kleine Änderungen gehen verloren | Bei Bedarf eine eigene float-Formel schreiben |
| pulseIn() ohne Timeout | Ohne Sensor friert jeder Durchlauf 1 Sekunde ein | 30000 als dritten Parameter übergeben |
| delay() oder Serial in einer ISR | Das Programm hängt oder verhält sich seltsam | In der ISR nur ein volatile-Flag setzen |
Die Befehle in diesem Artikel sind die Bausteine der meisten Projekte, die du mit einem Arduino baust; der Rest sind meist zusätzliche Funktionen aus Bibliotheken. Wenn du jeden Befehl einmal in einer eigenen kleinen Schaltung ausprobierst und das Ergebnis im seriellen Monitor siehst, bleibt das Gelernte viel besser hängen als durch Auswendiglernen. In der BlueGrays-App findest du Projekte, die diese Befehle nutzen, etwa LED einschalten, LED per Taster steuern, Licht mit einem LDR messen, Frequenz mit einem Summer einstellen, Abstand mit dem HC-SR04 messen und ein Würfelprojekt, Schritt für Schritt mit Schaltplänen und kommentiertem Code.
Häufige Fragen
Welche Arduino-Befehle werden am häufigsten verwendet?
Am häufigsten sind pinMode(), digitalWrite(), digitalRead(), analogRead(), analogWrite(), delay(), millis(), Serial.begin() und Serial.println(). Nimmst du noch map() zum Umrechnen, tone() für Töne, pulseIn() für Abstandssensoren und attachInterrupt() für Interrupts dazu, kannst du fast alle Einsteigerprojekte schreiben.
In welcher Sprache werden Arduino-Befehle geschrieben?
Arduino-Code basiert auf C und C++; der Arduino-Core ergänzt die Sprache um fertige Funktionen wie pinMode() und digitalWrite(). Die Befehle sind englisch, unterscheiden Groß- und Kleinschreibung, und jede Anweisung endet mit einem Semikolon. ESP32 und Raspberry Pi Pico lassen sich auf Wunsch auch mit MicroPython programmieren.
Was ist der Unterschied zwischen digitalWrite und analogWrite?
digitalWrite() setzt einen Pin auf einen von nur zwei Zuständen: HIGH (5 V beim Uno) oder LOW (0 V). analogWrite() schaltet den Pin sehr schnell ein und aus und erzeugt so ein PWM-Signal von 0 bis 255, mit dem du die Helligkeit einer LED oder die Drehzahl eines Motors einstellst. Beim Uno funktioniert analogWrite() nur an den mit ~ markierten Pins.
Was bedeuten void setup und void loop?
setup() ist die Funktion, die einmal läuft, wenn das Board eingeschaltet oder zurückgesetzt wird; hier stehen Vorbereitungen wie pinMode() und Serial.begin(). loop() ist die Funktion, die sich nach dem Ende von setup() endlos wiederholt. Das void davor bedeutet, dass diese Funktionen keinen Wert zurückgeben.
Was ist der Unterschied zwischen Serial.print und Serial.println?
Serial.print() gibt die Daten aus und lässt den Cursor in derselben Zeile, sodass die nächsten Daten direkt daneben erscheinen. Serial.println() sendet nach der Ausgabe die Zeilenende-Zeichen (\r\n), sodass die nächsten Daten in einer neuen Zeile beginnen. Um mehrere Werte nebeneinander in einer Zeile zu zeigen, nimmst du zuerst print() und am Ende println().
Was macht die map-Funktion beim Arduino?
map() rechnet eine Zahl proportional von einem Bereich in einen anderen um; zum Beispiel macht sie aus dem Wert 0–1023 von analogRead() den Bereich 0–255 für analogWrite() oder 0–180 Grad für einen Servo. Sie rechnet nur mit Ganzzahlen und begrenzt das Ergebnis nicht, daher solltest du sie gegen Werte außerhalb des Bereichs mit constrain() kombinieren.
Projekte, die du danach bauen kannst
Alle Projekte ansehen
LED Blinken
Einfaches Eingabeprojekt, das eine einzelne LED in bestimmten Intervallen mit Arduino ein- und ausschaltet. Lehrt die Verwendung von digitalWrite und Verzögerungsfunktionen.

LED mit Taster schalten (Push)
Sofortiges (Druck-)Steuerprojekt, bei dem die LED aufleuchtet, wenn die Taste gedrückt wird, und erlischt, wenn sie losgelassen wird. Lehrt die Verwendung von Tastenlesung und bedingtem Ausdruck mit d

Lichtstärke messen mit LDR
Projekt, das die Umgebungslichtintensität mit einem LDR-Sensor misst und sie auf einem seriellen Monitor anzeigt. Lehrt die Grundlagen der analogen Sensorablesung und der seriellen Kommunikation.

Frequenzeinstellung mit Buzzer
Interaktives Projekt mit 4 Tasten zum Erhöhen und Verringern der Frequenz des Summers und zum Ein- und Ausschalten. Lehrt das Lesen mehrerer Tasten und die variable Steuerung.

HC-SR04 Abstandsmessung (serielle Anzeige)
HC-SR04 Ultraschallsensor zur Abstandsmessung und Anzeige des Ergebnisses in cm auf dem seriellen Monitor. Er lehrt das Prinzip der Abstandsberechnung mit Schallwellen.

Knight-Rider-Lauflicht mit einstellbarer Geschwindigkeit
Projekt mit Potentiometer, das die Geschwindigkeit der Knight-Rider-LED-Animation in Echtzeit einstellen kann. Es kombiniert Analogeingang und bidirektionale Schleifensteuerung.

Servomotorbetrieb mit Potentiometer
Projekt, das den Servomotor in Echtzeit steuert, indem es den Potentiometerwert in einen Bereich von 0-180° umwandelt. Lernt die Funktion map() und die Analog-Servo-Integration.

Würfel-Projekt
Würfelprojekt, das bei jedem Tastendruck eine Zufallszahl zwischen 1 und 6 erzeugt und diese auf einer 7-Segment-Anzeige anzeigt. Dank des Entprellungsmechanismus wird ein einziges Ergebnis bei einem

