Fundamentos · 17 min de lectura

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.

Placa Arduino Uno con sus pines digitales y analógicos
Arduino Uno: los pines digitales 0–13, las entradas analógicas A0–A5 y los pines PWM marcados con ~ bastan para probar todos los comandos de este artículo.

¿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().

Arduino (C++)
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.

ComandoSintaxisPara qué sirveEjemplo
pinModepinMode(pin, modo)Configura un pin como entrada o salidapinMode(13, OUTPUT);
digitalWritedigitalWrite(pin, valor)Pone un pin en HIGH (5 V) o LOW (0 V)digitalWrite(13, HIGH);
digitalReaddigitalRead(pin)Lee si un pin está en HIGH o en LOWint b = digitalRead(2);
analogReadanalogRead(pin)Convierte una tensión de 0–5 V en un número de 0 a 1023int v = analogRead(A0);
analogWriteanalogWrite(pin, valor)Genera una señal PWM de 0 a 255analogWrite(9, 128);
analogReferenceanalogReference(tipo)Elige la tensión de referencia de analogReadanalogReference(INTERNAL);
tone / noTonetone(pin, frecuencia, duración)Produce un sonido con una onda cuadrada; noTone lo detienetone(8, 440, 500);
pulseInpulseIn(pin, valor, tiempoLímite)Mide la duración de un pulso en µspulseIn(10, HIGH, 30000);
shiftOutshiftOut(pinDatos, pinReloj, orden, byte)Envía un byte bit a bit (por ejemplo a un 74HC595)shiftOut(11, 12, MSBFIRST, 255);
attachInterruptattachInterrupt(interrupción, función, modo)Llama a una función en cuanto cambia un pinattachInterrupt(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.

ComandoSintaxisPara qué sirveOjo
delaydelay(ms)Espera los milisegundos indicadosEl programa se detiene durante ese tiempo
delayMicrosecondsdelayMicroseconds(us)Espera unos microsegundosEs preciso entre 3 y 16383 µs
millismillis()Devuelve los milisegundos desde el arranqueunsigned long; se desborda a los 49,7 días aprox.
microsmicros()Devuelve los microsegundos desde el arranqueEn 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.

ComandoSintaxisPara qué sirveResultado de ejemplo
mapmap(x, desdeMin, desdeMax, haciaMin, haciaMax)Reescala un rango a otromap(512, 0, 1023, 0, 255) → 127
constrainconstrain(x, mínimo, máximo)Mantiene un valor entre dos límitesconstrain(300, 0, 255) → 255
min / maxmin(a, b) / max(a, b)Devuelve el menor o el mayormin(7, 3) → 3
absabs(x)Valor absolutoabs(-12) → 12
pow / sqrt / sqpow(base, exponente), sqrt(x), sq(x)Potencia, raíz cuadrada, cuadradopow(2, 10) → 1024.0
randomrandom(min, max)Entero aleatorio (max no incluido)random(1, 7) → de 1 a 6
randomSeedrandomSeed(semilla)Cambia el punto de partida de la secuencia aleatoriarandomSeed(analogRead(A3));
ComandoPara qué sirveEjemplo
Serial.begin(velocidad)Abre el puerto serie a la velocidad en baudios indicadaSerial.begin(9600);
Serial.print(dato)Imprime el dato y se queda en la misma líneaSerial.print(temperatura);
Serial.println(dato)Imprime el dato y pasa a la línea siguienteSerial.println("Hola");
Serial.available()Devuelve el número de bytes pendientes de leerif (Serial.available() > 0)
Serial.read()Lee un byte; devuelve -1 si no hay datoschar c = Serial.read();
Serial.readStringUntil(c)Lee texto hasta un carácter concretoString s = Serial.readStringUntil('\n');
Serial.parseInt()Extrae un entero del texto recibidoint n = Serial.parseInt();
Serial.write(byte)Envía un byte en brutoSerial.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.

Si olvidas pinMode(pin, OUTPUT) y usas digitalWrite(pin, HIGH), el pin no se convierte en salida; en el Uno ese comando solo activa la resistencia pull-up interna. El LED se enciende, pero muy tenue, porque la corriente tiene que pasar por una resistencia de 20–50 kΩ. Si tu LED brilla poco, lo primero que debes revisar es la línea de pinMode en setup().

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:

Arduino (C++)
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?.

Arduino (C++)
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}
En un pin sin PWM, analogWrite() no puede producir valores intermedios: pone el pin en LOW con valores menores de 128 y en HIGH a partir de 128. Los pines A0–A5 del Uno tampoco dan PWM, y el Uno R3 clásico no tiene salida analógica real (DAC); escribir analogWrite(A0, 100) no te dará 2 V. Si necesitas una tensión analógica real, usa una placa con DAC (como el Uno R4, que tiene un DAC en A0) o añade un filtro RC a una salida PWM.

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.

Arduino (C++)
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:

Arduino (C++)
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).

Arduino (C++)
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.

Arduino (C++)
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.

Arduino (C++)
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.

Arduino (C++)
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}
Declara como volatile toda variable que modifiques dentro de una ISR y mantén la función lo más corta posible. Dentro de una ISR delay() no funciona, millis() no avanza y Serial.print() puede bloquear el programa; actualiza solo una bandera o un contador y haz el trabajo real en loop(). Los pulsadores mecánicos rebotan, así que el contador puede subir varias veces con una sola pulsación; la solución al rebote y todos los detalles sobre interrupciones están en interrupciones en Arduino.

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:

Arduino (C++)
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?.

ComandoArduino UnoESP32
digitalWrite(pin, HIGH)5 V3,3 V
analogRead()10 bits, 0–1023, A0–A512 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 HzCasi cualquier GPIO con salida; frecuencia con ledcAttach(pin, frecuencia, resolución)
attachInterrupt()Solo D2 y D3Todos los GPIO; a la ISR se le añade IRAM_ATTR
tone()Usa el Timer2 y altera el PWM de 3 y 11Funciona con el hardware LEDC
Serial.begin()Normalmente 9600Normalmente 115200 (los mensajes de arranque también usan esa velocidad)
delay()Deja el procesador completamente esperandoCede el tiempo a FreeRTOS; el Wi-Fi sigue funcionando en segundo plano
Arduino (C++)
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 ArduinoEquivalente en MicroPythonNota
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)
MicroPython
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

ErrorSíntomaSolución
Olvidar pinMode()El LED brilla muy poco o no se enciendeEscribe pinMode(pin, OUTPUT) en setup()
Pulsador sin resistencia en modo INPUTdigitalRead() devuelve 0 y 1 al azarUsa INPUT_PULLUP; pulsado se lee LOW
Error tipográfico en el nombre del comando'digitalwrite' was not declared in this scopeCuida las mayúsculas y minúsculas: digitalWrite
La velocidad en baudios no coincideCaracteres extraños en el Monitor SerieIguala la velocidad del Monitor Serie con Serial.begin()
analogWrite() en un pin sin PWMEl LED solo está totalmente encendido o apagadoUsa un pin marcado con ~ (3, 5, 6, 9, 10, 11)
Guardar millis() en un intLa temporización falla a los 33 segundos aprox.Usa unsigned long
Dado con random(1, 6)Nunca sale el 6Escribe 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ñosSi hace falta, escribe tu propia fórmula con float
pulseIn() sin tiempo límiteSin sensor, cada vuelta se congela 1 segundoPasa 30000 como tercer parámetro
delay() o Serial dentro de una ISREl programa se bloquea o se comporta de forma extrañaEn la ISR cambia solo una bandera volatile
Si no tienes claro qué hace exactamente un comando, escribe un pequeño programa de prueba e imprime el resultado con Serial.println(); en el Arduino IDE 2 también puedes hacer clic derecho sobre el nombre del comando y elegir «Ir a la definición» para ver su código fuente. Si tu código no compila, la primera línea del mensaje de error suele señalar dónde está el problema; los mensajes más habituales y sus soluciones están en errores de compilación de Arduino.

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.

Ver todos los proyectos
Parpadeo de LED
#1Principiante

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.

4.6(171)
903
Encender un LED con pulsador (Push)
#9Principiante

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.

4.9(112)
190
Medir la intensidad de luz con LDR
#11Principiante

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.

4.6(78)
124
Ajuste de frecuencia con zumbador
#14Intermedio

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.

4.6(68)
112
HC-SR04 Medición de distancia (pantalla en serie)
#27Principiante

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.

4.6(44)
66
Efecto coche fantástico con velocidad regulable
#8Intermedio

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.

4.5(59)
115
Funcionamiento del servomotor con potenciómetro
#36Principiante
Premium

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.

4.6(37)
51
Proyecto Dados
#79Intermedio
Premium

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

5.0(48)
67