Comandos de Arduino: lista con sintaxis, ejemplos y errores
Comandos de Arduino explicados: pinMode, digitalWrite, analogRead, analogWrite, millis, Serial, map, tone, pulseIn y attachInterrupt con ejemplos y errores.
Los comandos de Arduino son funciones ya preparadas que le dicen a la placa qué hacer: pinMode() convierte un pin en salida, digitalWrite() enciende un LED, analogRead() lee un sensor y Serial.println() envía un mensaje al ordenador. La mayoría de los programas de Arduino no son más que una veintena de comandos básicos combinados de distintas formas. Cuando entiendes bien estos comandos y su significado, puedes leer cualquier código que encuentres, desde hacer parpadear un LED hasta un coche robot, y escribir tu propio proyecto desde cero.
En esta guía hemos agrupado los comandos de Arduino más usados en cuatro categorías: entrada y salida, tiempo, matemáticas y comunicación. Para cada comando encontrarás la sintaxis, el significado de sus parámetros, un ejemplo corto que compila y funciona en un Arduino Uno y el error que más cometen los principiantes. En las últimas secciones veremos también cómo se comportan de forma distinta esos mismos comandos en el ESP32 y cuáles son sus equivalentes en MicroPython para la Raspberry Pi Pico.

¿Qué es un comando de Arduino y cómo se ejecuta un programa?
El código de Arduino se basa en C/C++; casi todo lo que llamamos «comandos» son en realidad funciones que el núcleo de Arduino te ofrece ya hechas. Una función recibe parámetros entre paréntesis (por ejemplo, un número de pin y un valor) y algunas devuelven un resultado: digitalRead() te da el estado de un pin y millis() el tiempo transcurrido. Todo programa de Arduino tiene dos funciones obligatorias: setup() se ejecuta una sola vez al encender o reiniciar la placa, y loop() se repite después sin parar. La preparación, como la configuración de los pines y Serial.begin(), va en setup(), y lo que debe ocurrir de forma continua va en 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}Tener en cuenta tres reglas desde el principio te ahorra muchos errores de compilación: los comandos distinguen entre mayúsculas y minúsculas (si escribes digitalwrite obtendrás el error «'digitalwrite' was not declared in this scope»), cada instrucción termina con punto y coma, y los textos van entre comillas dobles mientras que los caracteres sueltos van entre comillas simples. Para los tipos de variables y estructuras como if y for, echa un vistazo a los fundamentos de programación de Arduino.
Lista de comandos de Arduino: tablas por categoría
Las cuatro tablas siguientes resumen casi todos los comandos que usarás en tus proyectos del día a día. El primer grupo son los comandos de entrada y salida: definen la función de un pin, le aplican una tensión o leen un valor de él. Puedes ver los números de pin de tu placa en la herramienta Pinout.
| Comando | Sintaxis | Para qué sirve | Ejemplo |
|---|---|---|---|
| pinMode | pinMode(pin, modo) | Configura un pin como entrada o salida | pinMode(13, OUTPUT); |
| digitalWrite | digitalWrite(pin, valor) | Pone un pin en HIGH (5 V) o LOW (0 V) | digitalWrite(13, HIGH); |
| digitalRead | digitalRead(pin) | Lee si un pin está en HIGH o en LOW | int b = digitalRead(2); |
| analogRead | analogRead(pin) | Convierte una tensión de 0–5 V en un número de 0 a 1023 | int v = analogRead(A0); |
| analogWrite | analogWrite(pin, valor) | Genera una señal PWM de 0 a 255 | analogWrite(9, 128); |
| analogReference | analogReference(tipo) | Elige la tensión de referencia de analogRead | analogReference(INTERNAL); |
| tone / noTone | tone(pin, frecuencia, duración) | Produce un sonido con una onda cuadrada; noTone lo detiene | tone(8, 440, 500); |
| pulseIn | pulseIn(pin, valor, tiempoLímite) | Mide la duración de un pulso en µs | pulseIn(10, HIGH, 30000); |
| shiftOut | shiftOut(pinDatos, pinReloj, orden, byte) | Envía un byte bit a bit (por ejemplo a un 74HC595) | shiftOut(11, 12, MSBFIRST, 255); |
| attachInterrupt | attachInterrupt(interrupción, función, modo) | Llama a una función en cuanto cambia un pin | attachInterrupt(digitalPinToInterrupt(2), say, FALLING); |
El segundo grupo son los comandos de tiempo. Entender la diferencia entre delay(), que espera, y millis() y micros(), que miden el tiempo, es la clave para escribir un programa que funcione con fluidez.
| Comando | Sintaxis | Para qué sirve | Ojo |
|---|---|---|---|
| delay | delay(ms) | Espera los milisegundos indicados | El programa se detiene durante ese tiempo |
| delayMicroseconds | delayMicroseconds(us) | Espera unos microsegundos | Es preciso entre 3 y 16383 µs |
| millis | millis() | Devuelve los milisegundos desde el arranque | unsigned long; se desborda a los 49,7 días aprox. |
| micros | micros() | Devuelve los microsegundos desde el arranque | En el Uno avanza de 4 en 4 µs y se desborda a los 70 minutos aprox. |
El tercer grupo son los comandos de matemáticas; sirven para convertir la lectura de un sensor a otro rango, limitarla o generar un número aleatorio. El cuarto grupo, los comandos de comunicación, permite que la placa intercambie datos con el ordenador y con otros dispositivos.
| Comando | Sintaxis | Para qué sirve | Resultado de ejemplo |
|---|---|---|---|
| map | map(x, desdeMin, desdeMax, haciaMin, haciaMax) | Reescala un rango a otro | map(512, 0, 1023, 0, 255) → 127 |
| constrain | constrain(x, mínimo, máximo) | Mantiene un valor entre dos límites | constrain(300, 0, 255) → 255 |
| min / max | min(a, b) / max(a, b) | Devuelve el menor o el mayor | min(7, 3) → 3 |
| abs | abs(x) | Valor absoluto | abs(-12) → 12 |
| pow / sqrt / sq | pow(base, exponente), sqrt(x), sq(x) | Potencia, raíz cuadrada, cuadrado | pow(2, 10) → 1024.0 |
| random | random(min, max) | Entero aleatorio (max no incluido) | random(1, 7) → de 1 a 6 |
| randomSeed | randomSeed(semilla) | Cambia el punto de partida de la secuencia aleatoria | randomSeed(analogRead(A3)); |
| Comando | Para qué sirve | Ejemplo |
|---|---|---|
| Serial.begin(velocidad) | Abre el puerto serie a la velocidad en baudios indicada | Serial.begin(9600); |
| Serial.print(dato) | Imprime el dato y se queda en la misma línea | Serial.print(temperatura); |
| Serial.println(dato) | Imprime el dato y pasa a la línea siguiente | Serial.println("Hola"); |
| Serial.available() | Devuelve el número de bytes pendientes de leer | if (Serial.available() > 0) |
| Serial.read() | Lee un byte; devuelve -1 si no hay datos | char c = Serial.read(); |
| Serial.readStringUntil(c) | Lee texto hasta un carácter concreto | String s = Serial.readStringUntil('\n'); |
| Serial.parseInt() | Extrae un entero del texto recibido | int n = Serial.parseInt(); |
| Serial.write(byte) | Envía un byte en bruto | Serial.write(65); // 'A' |
| Wire.begin() | Inicia el bus I2C (Wire.h) | Wire.begin(); |
| SPI.begin() | Inicia el bus SPI (SPI.h) | SPI.begin(); |
pinMode(): definir la función de un pin
pinMode(pin, modo) indica si un pin digital será entrada o salida y normalmente se escribe una sola vez dentro de setup(). Hay tres modos: OUTPUT convierte el pin en salida (para manejar un LED, un zumbador o un relé), INPUT lo convierte en una entrada de alta impedancia (para circuitos con una resistencia pull-up o pull-down externa) e INPUT_PULLUP lo configura como entrada y conecta a 5 V una resistencia interna de unos 20–50 kΩ. Los pines analógicos (A0–A5) también pueden usarse como pines digitales con pinMode; por ejemplo, pinMode(A0, OUTPUT) es un comando válido.
digitalWrite() y digitalRead(): salida y entrada digital
digitalWrite(pin, HIGH) lleva un pin de salida a 5 V en el Uno y digitalWrite(pin, LOW) lo lleva a 0 V. Es seguro sacar hasta 20 mA de un pin (el máximo absoluto es 40 mA); conecta siempre el LED con una resistencia, y puedes calcular el valor adecuado con la calculadora de resistencia para LED. digitalRead(pin) mira la tensión del pin y devuelve HIGH o LOW; en el Uno, aproximadamente todo lo que supera 3 V cuenta como HIGH y lo que está por debajo de 1,5 V como LOW. En el siguiente ejemplo, el LED integrado se enciende al pulsar el pulsador conectado a D2:
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}Con INPUT_PULLUP la lógica se invierte: con el pulsador suelto, el pin lee HIGH gracias a la resistencia interna, y al pulsarlo lee LOW porque queda conectado a GND. Si conectas el pulsador sin resistencia y en modo INPUT, el pin queda flotando y digitalRead() devuelve valores al azar; incluso acercar la mano puede cambiar el resultado. Para el rebote del pulsador y las formas correctas de conectarlo, consulta cómo conectar un pulsador a Arduino.
analogRead() y analogWrite(): lectura analógica y PWM
analogRead(pin) usa un convertidor de 10 bits (ADC) para transformar una tensión de 0 a 5 V en los pines A0–A5 en un número de 0 a 1023. Cada lectura tarda unos 100 µs, así que puedes hacer unas 10.000 lecturas por segundo. Para pasar el número a tensión se usa valor × 5,0 / 1023; por ejemplo, una lectura de 512 equivale a unos 2,5 V. La tensión de referencia se puede cambiar con analogReference(): la opción INTERNAL usa la referencia interna de 1,1 V del Uno y mejora la resolución con tensiones pequeñas. Tienes todos los detalles sobre resolución y referencia en ADC y conversión analógico-digital.
A pesar de su nombre, analogWrite(pin, valor) no genera una tensión analógica real. Enciende y apaga el pin muy rápido para crear una señal PWM: 0 significa siempre apagado, 255 siempre encendido y 127 encendido aproximadamente la mitad del tiempo. De esa media sale que un LED nos parezca a medio brillo y que un motor gire despacio. En el Uno solo dan PWM los pines 3, 5, 6, 9, 10 y 11, marcados con ~ en la placa; la frecuencia es de 490 Hz en la mayoría y de 980 Hz en los pines 5 y 6. analogWrite() configura el pin como salida por sí mismo, así que pinMode no es obligatorio. El siguiente código regula el brillo de un LED con un potenciómetro y escribe la lectura junto con la tensión en el Monitor Serie; para los detalles sobre ciclo de trabajo y frecuencia, consulta ¿Qué es 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() y micros(): comandos de tiempo
delay(ms) espera los milisegundos indicados y, mientras tanto, no se ejecuta ninguna otra línea de loop(); delay(1000) es una pausa completa de un segundo. Para esperas cortas del orden de microsegundos existe delayMicroseconds(), que es preciso entre 3 y 16383 µs. millis(), en cambio, no espera: devuelve el tiempo transcurrido desde que arrancó la placa, en milisegundos. Guarda siempre el resultado en una variable de tipo unsigned long: si usas int, en el Uno el valor se desborda en cuanto supera 32.767, es decir, a los 33 segundos aproximadamente, y la temporización falla. millis() vuelve a cero cada 49,7 días aproximadamente; el método de la resta que verás abajo sigue funcionando bien incluso con ese desbordamiento.
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}Con este patrón loop() nunca se detiene: mientras el LED sigue parpadeando puedes leer un pulsador, medir un sensor y actualizar una pantalla en el mismo bucle. micros() funciona igual pero en microsegundos; en el Uno avanza de 4 en 4 µs y se desborda a los 70 minutos aproximadamente. Explicamos con todo detalle cómo ejecutar varias tareas a la vez en Arduino millis() en lugar de delay().
Serial.begin(), Serial.print() y Serial.read(): comunicación serie
Los comandos Serial permiten que el Arduino hable con tu ordenador a través del cable USB y son tu herramienta más importante para depurar. Serial.begin(9600) abre el puerto serie a 9600 bits por segundo; si la velocidad del Monitor Serie no coincide, verás caracteres extraños en la pantalla. Serial.print() imprime el dato y se queda en la misma línea, mientras que Serial.println() pasa a la línea siguiente después de imprimir. Con un segundo parámetro puedes elegir el formato: Serial.print(78, HEX) muestra «4E», Serial.print(78, BIN) muestra «1001110» y Serial.print(3.14159, 3) muestra «3.142» (los decimales salen por defecto con 2 cifras). Escribir los textos fijos dentro de F("...") ahorra espacio en los 2 KB de RAM del Uno.
Para leer datos, primero compruebas con Serial.available() si hay bytes esperando en el búfer; el búfer de recepción del Uno es de 64 bytes. Serial.read() toma un solo byte de ese búfer y devuelve -1 si no hay nada que leer. El siguiente código enciende y apaga el LED con los caracteres 1 y 0 que envíes desde el Monitor Serie:
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}Fíjate en que la comparación se hace con '1' (comillas simples, es decir, un carácter): el 1 que escribes en el teclado corresponde al número 49 en la tabla ASCII, por eso la condición c == 1 nunca se cumple. Para números de varias cifras puedes usar Serial.parseInt(), y para leer una línea entera, Serial.readStringUntil('\n'). Sobre los ajustes de fin de línea del Monitor Serie, la velocidad en baudios y el Serial Plotter, consulta cómo usar el Monitor Serie de Arduino.
map() y constrain(): escalar y limitar valores
map(valor, desdeMin, desdeMax, haciaMin, haciaMax) traslada un número de un rango a otro de forma proporcional. La fórmula que hay detrás es: (x − desdeMin) × (haciaMax − haciaMin) / (desdeMax − desdeMin) + haciaMin. Por ejemplo, map(512, 0, 1023, 0, 255) da 127 y no 127,6, porque map() trabaja solo con números enteros y descarta los decimales. Si inviertes el rango de destino obtienes una relación inversa: map(x, 0, 1023, 255, 0). map() no limita el resultado; si la entrada sale del rango que indicaste, la salida también se sale. Por eso suele combinarse con constrain(x, mínimo, máximo).
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}En este ejemplo el LDR da valores entre 200 y 800 en la habitación. Si de noche la lectura baja a 100, map() calcula 297; sin constrain(), analogWrite() recibiría ese valor fuera del rango 0–255. En el Uno, un valor así da resultados distintos e inesperados según el pin: en los pines 3, 5, 6 y 11, que usan temporizadores de 8 bits, 297 se desborda y se comporta como 41, así que el LED casi se apaga en plena oscuridad en lugar de brillar al máximo. Como constrain(), min(), max() y abs() están definidas como macros en el Uno, no pongas x++ ni otra llamada a función dentro de los paréntesis; la expresión puede evaluarse más de una vez y dar resultados inesperados. Para conectar el LDR, consulta sensor de luz LDR.
tone() y noTone(): sonido con un zumbador
tone(pin, frecuencia, duración) genera en un pin una onda cuadrada con un ciclo de trabajo del 50 % y hace sonar a esa frecuencia un zumbador pasivo o un pequeño altavoz. La duración se indica en milisegundos y es opcional; si no la pones, el sonido sigue hasta que llames a noTone(pin). Un detalle importante: tone() no espera; inicia el sonido y pasa enseguida a la línea siguiente. Por eso, al tocar notas seguidas, necesitas un delay() al menos tan largo como la nota después de cada llamada a tone(); si no, solo oirás la última.
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}- Límites de frecuencia: En el Uno no se pueden generar tonos por debajo de 31 Hz y el límite superior es 65.535 Hz; con un zumbador el rango útil va aproximadamente de 100 a 5000 Hz.
- Un solo sonido: Solo un pin puede emitir un tono a la vez; para sonar en otro pin primero tienes que detener el anterior con noTone().
- Conflicto con PWM: En el Uno tone() usa el Timer2, así que mientras suena se altera analogWrite() en los pines 3 y 11.
- Zumbador activo: Como tiene su propio oscilador, su frecuencia no se puede cambiar con tone(); basta con encenderlo y apagarlo con digitalWrite(). Las diferencias están en ¿Qué es un zumbador?.
pulseIn(): medir la duración de un pulso
pulseIn(pin, HIGH) espera a que el pin pase a HIGH, mide cuánto tiempo permanece en HIGH y devuelve el resultado en microsegundos; puede medir pulsos de 10 µs a 3 minutos. Su uso más conocido es el sensor de distancia ultrasónico HC-SR04: el sensor entrega un pulso tan largo como lo que tarda el sonido en ir y volver. El sonido viaja por el aire a unos 343 m/s, es decir, 0,0343 cm/µs; como el recorrido es de ida y vuelta, distancia = duración × 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}El tercer parámetro, el tiempo límite, es muy importante. Si no lo indicas, pulseIn() espera 1 segundo cuando no llega ningún pulso y devuelve 0; si se suelta el cable del sensor, todo el programa se congela un segundo en cada vuelta. Un tiempo límite de 30000 µs equivale a unos 5 metros, suficiente para los 4 metros de alcance del HC-SR04. Para la conexión y la precisión del sensor, consulta sensor de distancia HC-SR04.
attachInterrupt(): reaccionar al instante con interrupciones
attachInterrupt(digitalPinToInterrupt(pin), función, modo) ejecuta la función que le indiques en el mismo instante en que cambia un pin, haga lo que haga loop() en ese momento. Esta función se llama rutina de servicio de interrupción (ISR). El modo puede tomar cuatro valores: RISING se dispara al pasar de LOW a HIGH, FALLING al pasar de HIGH a LOW, CHANGE con cada cambio y LOW mientras el pin siga en LOW. En el Uno y el Nano solo los pines D2 y D3 pueden generar interrupciones así; en el Mega se pueden usar los pines 2, 3, 18, 19, 20 y 21. Es ideal para no perderte los pasos de un encoder que gira rápido, los pulsos de un anemómetro o una pulsación muy breve.
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() y randomSeed(): generar números aleatorios
random(max) devuelve un entero aleatorio entre 0 y max−1, y random(min, max) uno entre min y max−1; el límite superior no se incluye en el resultado. Por eso, para un dado de 1 a 6 se escribe random(1, 7). Arduino no genera aleatoriedad real: calcula una secuencia de números con una fórmula fija, así que si no llamas a randomSeed() verás los mismos números en el mismo orden cada vez que arranque la placa. Usar como semilla el ruido de un pin analógico sin conectar lo resuelve en la práctica:
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}Comandos de Arduino en el ESP32: qué debes tener en cuenta
El ESP32 se programa en el Arduino IDE con los mismos comandos, y la mayor parte del código de este artículo funciona directamente si cambias los números de pin. Pero como el hardware es distinto, algunos comandos se comportan de otra manera. La diferencia más importante es la tensión: los pines del ESP32 trabajan a 3,3 V, digitalWrite(pin, HIGH) da 3,3 V y no debes conectar señales de 5 V directamente a los pines. Para conocer mejor la placa, consulta ¿Qué es el ESP32?.
| Comando | Arduino Uno | ESP32 |
|---|---|---|
| digitalWrite(pin, HIGH) | 5 V | 3,3 V |
| analogRead() | 10 bits, 0–1023, A0–A5 | 12 bits, 0–4095; con el Wi-Fi activo, solo los pines ADC1 (GPIO 32–39) |
| analogWrite() | Solo los pines ~ (3, 5, 6, 9, 10, 11), 490/980 Hz | Casi cualquier GPIO con salida; frecuencia con ledcAttach(pin, frecuencia, resolución) |
| attachInterrupt() | Solo D2 y D3 | Todos los GPIO; a la ISR se le añade IRAM_ATTR |
| tone() | Usa el Timer2 y altera el PWM de 3 y 11 | Funciona con el hardware LEDC |
| Serial.begin() | Normalmente 9600 | Normalmente 115200 (los mensajes de arranque también usan esa velocidad) |
| delay() | Deja el procesador completamente esperando | Cede el tiempo a FreeRTOS; el Wi-Fi sigue funcionando en segundo plano |
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}Como en el ESP32 analogRead() devuelve valores de 0 a 4095, el rango de map() cambia en consecuencia. El IRAM_ATTR delante de la ISR coloca el código en la memoria interna rápida; si falta, en algunas situaciones la placa puede reiniciarse con un «Guru Meditation Error». Las lecturas analógicas del ESP32 no son lineales cerca de los extremos (alrededor de 0 V y de 3,3 V); si necesitas una medida más precisa, la función analogReadMilliVolts() devuelve un valor calibrado en milivoltios.
Raspberry Pi Pico: equivalentes en MicroPython de los comandos de Arduino
Si programas la Raspberry Pi Pico con el Arduino IDE (núcleo arduino-pico), todos los comandos de este artículo funcionan con el mismo nombre; analogRead() devuelve 10 bits por defecto y analogWrite() genera PWM a 1 kHz. Sin embargo, la Pico se usa sobre todo con MicroPython. Allí los comandos se escriben con objetos de los módulos machine y time; la lógica es la misma y solo cambia la sintaxis. Los pines de la Pico también son de 3,3 V y sus entradas analógicas son los pines GP26, GP27 y GP28. Para empezar, consulta ¿Qué es la Raspberry Pi Pico?.
| Comando de Arduino | Equivalente en MicroPython | Nota |
|---|---|---|
| pinMode(15, OUTPUT) | led = Pin(15, Pin.OUT) | El objeto Pin se crea una vez |
| pinMode(14, INPUT_PULLUP) | btn = Pin(14, Pin.IN, Pin.PULL_UP) | Resistencia pull-up interna |
| digitalWrite(15, HIGH) | led.value(1) | También vale led.on() |
| digitalRead(14) | btn.value() | Devuelve 0 o 1 |
| analogRead(A0) | ADC(26).read_u16() | Devuelve de 0 a 65535 |
| analogWrite(15, 128) | PWM(Pin(15)).duty_u16(32768) | Ciclo de trabajo de 0 a 65535 |
| delay(500) | time.sleep_ms(500) | También vale time.sleep(0.5) |
| millis() | time.ticks_ms() | Para diferencias, time.ticks_diff() |
| Serial.println(x) | print(x) | Aparece en la consola de Thonny |
| tone(pin, 440) | pwm.freq(440) y pwm.duty_u16(32768) | Para silenciar, duty_u16(0) |
| pulseIn(pin, HIGH, 30000) | machine.time_pulse_us(pin, 1, 30000) | Devuelve un valor negativo si vence el tiempo |
| attachInterrupt(...) | btn.irq(trigger=Pin.IRQ_FALLING, handler=f) | f recibe el objeto pin como parámetro |
| random(1, 7) | random.randint(1, 6) | El límite superior se incluye |
| map() / constrain() | No vienen incluidas, las escribes tú | Para 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)Como ves en la tabla, en MicroPython random.randint(1, 6) incluye el límite superior y da el mismo resultado que random(1, 7) en Arduino; time.ticks_diff() aporta la misma seguridad ante el desbordamiento que la resta con millis(). Son justo estas pequeñas diferencias las que más confunden al pasar de una plataforma a otra. Para los demás comandos básicos de MicroPython, echa un vistazo a fundamentos de MicroPython.
Ideas de proyectos con estos comandos
- Semáforo: Enciende tres LED en secuencia con pinMode(), digitalWrite() y delay(); lo explicamos paso a paso en semáforo con Arduino.
- Dado digital: Genera un número de 1 a 6 con random() y, al pulsar el botón, muestra el resultado con LED o en un display de 7 segmentos.
- Sensor de aparcamiento: Mide la distancia con pulseIn(), conviértela en un intervalo de pitidos con map() y emite un aviso con tone().
- Luz nocturna automática: Lee la luz con analogRead() y ajusta el brillo de analogWrite() con map() y constrain().
- Mando por puerto serie: Controla un LED, un relé o un servomotor con órdenes enviadas desde el ordenador mediante Serial.read().
- Test de reacción: Enciende un LED en un momento aleatorio con random() y mide tu tiempo de reacción al milisegundo con attachInterrupt() y millis().
Errores frecuentes y cómo solucionarlos
| Error | Síntoma | Solución |
|---|---|---|
| Olvidar pinMode() | El LED brilla muy poco o no se enciende | Escribe pinMode(pin, OUTPUT) en setup() |
| Pulsador sin resistencia en modo INPUT | digitalRead() devuelve 0 y 1 al azar | Usa INPUT_PULLUP; pulsado se lee LOW |
| Error tipográfico en el nombre del comando | 'digitalwrite' was not declared in this scope | Cuida las mayúsculas y minúsculas: digitalWrite |
| La velocidad en baudios no coincide | Caracteres extraños en el Monitor Serie | Iguala la velocidad del Monitor Serie con Serial.begin() |
| analogWrite() en un pin sin PWM | El LED solo está totalmente encendido o apagado | Usa un pin marcado con ~ (3, 5, 6, 9, 10, 11) |
| Guardar millis() en un int | La temporización falla a los 33 segundos aprox. | Usa unsigned long |
| Dado con random(1, 6) | Nunca sale el 6 | Escribe random(1, 7); el límite superior no se incluye |
| Esperar decimales de map() | El resultado siempre es entero y se pierden los cambios pequeños | Si hace falta, escribe tu propia fórmula con float |
| pulseIn() sin tiempo límite | Sin sensor, cada vuelta se congela 1 segundo | Pasa 30000 como tercer parámetro |
| delay() o Serial dentro de una ISR | El programa se bloquea o se comporta de forma extraña | En la ISR cambia solo una bandera volatile |
Los comandos de este artículo son las piezas básicas de la mayoría de los proyectos que harás con Arduino; el resto son, sobre todo, funciones adicionales que aportan las librerías. Probar cada comando una vez en su propio circuito pequeño y ver el resultado en el Monitor Serie hace que lo aprendido se quede mucho mejor que memorizarlo. En la app BlueGrays encontrarás, paso a paso y con esquemas de circuito y código comentado, proyectos que usan estos comandos, como encender un LED, controlar un LED con un pulsador, medir la luz con un LDR, ajustar la frecuencia de un zumbador, medir distancias con el HC-SR04 y un proyecto de dado.
Preguntas frecuentes
¿Cuáles son los comandos de Arduino más usados?
Los más habituales son pinMode(), digitalWrite(), digitalRead(), analogRead(), analogWrite(), delay(), millis(), Serial.begin() y Serial.println(). Si les sumas map() para escalar valores, tone() para el sonido, pulseIn() para los sensores de distancia y attachInterrupt() para las interrupciones, puedes escribir casi todos tus proyectos de principiante.
¿En qué lenguaje se escriben los comandos de Arduino?
El código de Arduino se basa en C y C++; el núcleo de Arduino añade al lenguaje funciones ya hechas como pinMode() y digitalWrite(). Los comandos están en inglés, distinguen entre mayúsculas y minúsculas y cada instrucción termina con punto y coma. El ESP32 y la Raspberry Pi Pico también se pueden programar en MicroPython si lo prefieres.
¿Qué diferencia hay entre digitalWrite y analogWrite?
digitalWrite() pone un pin en uno de solo dos estados: HIGH (5 V en el Uno) o LOW (0 V). analogWrite() enciende y apaga el pin muy rápido para generar una señal PWM de 0 a 255, con la que puedes regular el brillo de un LED o la velocidad de un motor. En el Uno, analogWrite() solo funciona en los pines marcados con ~.
¿Qué significan void setup y void loop?
setup() es la función que se ejecuta una vez al encender o reiniciar la placa; aquí va la preparación, como pinMode() y Serial.begin(). loop() es la función que se repite sin fin cuando termina setup(). El void que llevan delante indica que estas funciones no devuelven ningún valor.
¿Qué diferencia hay entre Serial.print y Serial.println?
Serial.print() imprime el dato y deja el cursor en la misma línea, de modo que lo siguiente aparece justo al lado. Serial.println() envía después los caracteres de fin de línea (\r\n), así que el siguiente dato empieza en una línea nueva. Para mostrar varios valores seguidos en una misma línea se usa primero print() y al final println().
¿Para qué sirve la función map de Arduino?
map() convierte un número de un rango a otro de forma proporcional; por ejemplo, transforma el valor 0–1023 de analogRead() al rango 0–255 de analogWrite() o a 0–180 grados para un servo. Trabaja solo con enteros y no limita el resultado, por eso se recomienda combinarla con constrain() para las entradas fuera de rango.
Proyectos para hacer después de leer esto
Ver todos los proyectos
Parpadeo de LED
Proyecto básico de entrada que enciende y apaga un único LED a determinados intervalos con Arduino. Enseña el uso de las funciones digitalWrite y delay.

Encender un LED con pulsador (Push)
Proyecto de control instantáneo (push) que enciende el LED al pulsar el botón y lo apaga al soltarlo. Enseña el uso de la lectura de botones y la expresión condicional con digitalRead.

Medir la intensidad de luz con LDR
Proyecto que mide la intensidad de la luz ambiental con un sensor LDR y la muestra en un monitor serie. Enseña los fundamentos de la lectura de sensores analógicos y la comunicación serie.

Ajuste de frecuencia con zumbador
Proyecto interactivo con 4 botones que pueden aumentar y disminuir la frecuencia del zumbador, encenderlo y apagarlo. Enseña la lectura de varios botones y el control variable.

HC-SR04 Medición de distancia (pantalla en serie)
Sensor ultrasónico HC-SR04 para medir distancias y mostrar el resultado en cm en el monitor serie. Enseña el principio del cálculo de distancias con ondas sonoras.

Efecto coche fantástico con velocidad regulable
Proyecto con potenciómetro que permite ajustar en tiempo real la velocidad de la animación LED del coche fantástico. Combina entrada analógica y control de bucle bidireccional.

Funcionamiento del servomotor con potenciómetro
Proyecto que controla el servomotor en tiempo real convirtiendo el valor del potenciómetro al rango 0-180°. enseña la función map() y la integración analógico-servo.

Proyecto Dados
Proyecto de dados que genera un número aleatorio entre 1 y 6 a cada pulsación del botón y lo muestra en una pantalla de 7 segmentos. Gracias al mecanismo de rebote, se produce un único resultado en un

