les vencimos

Arduino · Proyectos

Falcon

Falcon · AP-FAL-01

Temperatura y humedad en LCD

Objetivo

Al terminar, el LCD 16x2 enseña la temperatura en grados Celsius y la humedad relativa que mide el DHT11, renovadas cada dos segundos con millis para no congelar el programa. La misma lectura sale por el monitor serie, así que compruebas el sensor aunque el contraste de la pantalla todavía esté mal ajustado. Queda un medidor ambiente estable, listo para leer sin pulsar nada.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Si el puerto no sale, instala el controlador CH340 en el ordenador. Usa una sola placa.
1DHT11sensor-dht11genérico / cloneirrisorio (<1 €)Mide temperatura y humedad. Datos en D2. Espera unos dos segundos entre lecturas fiables.
1LCD 1602 I2Cmodulo-lcd-1602genérico / clonepoco (≈1–3 €)Pantalla en modo paralelo de 4 bits. Ajusta el contraste con el potenciometro del propio modulo hasta ver caracteres.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza DHT11 DATA DHT11 VCC DHT11 GND LCD RS LCD E LCD D4 LCD D5 LCD D6 LCD D7 LCD RW LCD VCC LCD GND D2 5V GND D7 D8 D9 D10 D11 D12

Código

// AP-FAL-01 Temperatura y humedad en LCD
// Pines: DHT D2, LCD RS D7, E D8, D4 D9, D5 D10, D6 D11, D7 D12
#include <DHT.h>
#include <LiquidCrystal.h>

const int PIN_DHT = 2;
const int PIN_RS = 7;
const int PIN_E = 8;
const int PIN_D4 = 9;
const int PIN_D5 = 10;
const int PIN_D6 = 11;
const int PIN_D7 = 12;
const unsigned long PERIODO_MS = 2000;

DHT dht(PIN_DHT, DHT11);
LiquidCrystal lcd(PIN_RS, PIN_E, PIN_D4, PIN_D5, PIN_D6, PIN_D7);

void setup() {
  Serial.begin(9600);
  dht.begin();
  lcd.begin(16, 2);
  lcd.print("Leyendo DHT11");
  Serial.println("AP-FAL-01 listo");
}

void loop() {
  static unsigned long anterior = 0;
  unsigned long ahora = millis();
  if (ahora - anterior < PERIODO_MS) {
    return;
  }
  anterior = ahora;

  float t = dht.readTemperature();
  float h = dht.readHumidity();
  lcd.clear();
  if (isnan(t) || isnan(h)) {
    lcd.print("Sensor no lee");
    Serial.println("Lectura no valida");
    return;
  }

  lcd.setCursor(0, 0);
  lcd.print("T: ");
  lcd.print(t, 1);
  lcd.print(" C");
  lcd.setCursor(0, 1);
  lcd.print("H: ");
  lcd.print(h, 1);
  lcd.print(" %");

  Serial.print("T ");
  Serial.print(t, 1);
  Serial.print(" C  H ");
  Serial.println(h, 1);
}

Pasos

  1. Elige la Uno R3 o la Uno CH340, no las dos a la vez, y en el IDE selecciona la placa Arduino Uno y el puerto correcto.
  2. Conecta el DHT11: datos a D2, alimentacion a 5 V y GND comun. Respeta la serigrafia del modulo para no invertirlo.
  3. Conecta el LCD en 4 bits: RS a D7, E a D8, D4 a D9, D5 a D10, D6 a D11, D7 a D12 y RW a GND.
  4. Instala la libreria DHT sensor library desde el gestor de librerias del IDE. LiquidCrystal ya viene con el nucleo.
  5. Copia el sketch, compilalo y subelo. Abre el monitor serie a 9600 baudios.
  6. Espera el primer refresco de dos segundos y comprueba que temperatura y humedad coinciden en el LCD y en el serie.
  7. Si la pantalla queda en blanco o en cuadros negros, gira el contraste del propio modulo hasta que se lean las letras.

Variantes

Depuración

Software: serial millis

Falcon · AP-FAL-02

Distancia en LCD

Objetivo

Al terminar, el LCD muestra la distancia en centimetros que mide el HC-SR04 y el monitor serie repite la misma cifra. Si el eco no vuelve a tiempo, la pantalla dice que estas fuera de rango en lugar de inventar un numero. El disparo del trigger y la lectura se repiten varias veces por segundo, asi que al mover la mano ves el valor cambiar sin pulsar nada.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1HC-SR04sensor-hc-sr04genérico / cloneirrisorio (<1 €)Trigger en D2 y eco en D3. Alimentacion a 5 V.
1LCD 1602 I2Cmodulo-lcd-1602genérico / clonepoco (≈1–3 €)Muestra los centimetros. Ajusta el contraste del propio modulo.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza HC-SR04 TRIG HC-SR04 ECHO HC-SR04 VCC HC-SR04 GND LCD RS LCD E LCD D4 LCD D5 LCD D6 LCD D7 LCD RW LCD VCC LCD GND D2 D3 5V GND D7 D8 D9 D10 D11 D12

Código

// AP-FAL-02 Distancia en LCD
// Pines: TRIG D2, ECHO D3, LCD RS D7, E D8, D4 D9, D5 D10, D6 D11, D7 D12
#include <LiquidCrystal.h>

const int PIN_TRIG = 2;
const int PIN_ECHO = 3;
const int PIN_RS = 7;
const int PIN_E = 8;
const int PIN_D4 = 9;
const int PIN_D5 = 10;
const int PIN_D6 = 11;
const int PIN_D7 = 12;

LiquidCrystal lcd(PIN_RS, PIN_E, PIN_D4, PIN_D5, PIN_D6, PIN_D7);

float medirCm() {
  digitalWrite(PIN_TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(PIN_TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(PIN_TRIG, LOW);
  unsigned long us = pulseIn(PIN_ECHO, HIGH, 30000UL);
  if (us == 0) {
    return -1.0;
  }
  return us / 58.0;
}

void setup() {
  Serial.begin(9600);
  pinMode(PIN_TRIG, OUTPUT);
  pinMode(PIN_ECHO, INPUT);
  digitalWrite(PIN_TRIG, LOW);
  lcd.begin(16, 2);
  lcd.print("Distancia");
  Serial.println("AP-FAL-02 listo");
}

void loop() {
  static unsigned long anterior = 0;
  unsigned long ahora = millis();
  if (ahora - anterior < 200) {
    return;
  }
  anterior = ahora;

  float cm = medirCm();
  lcd.setCursor(0, 0);
  lcd.print("Distancia      ");
  lcd.setCursor(0, 1);
  if (cm < 0) {
    lcd.print("Fuera de rango ");
    Serial.println("Fuera de rango");
  } else {
    lcd.print(cm, 1);
    lcd.print(" cm        ");
    Serial.print(cm, 1);
    Serial.println(" cm");
  }
}

Pasos

  1. Monta una sola placa, Uno R3 o Uno CH340, y selecciona Arduino Uno en el IDE.
  2. Conecta TRIG del HC-SR04 a D2, ECHO a D3, VCC a 5 V y GND a masa.
  3. Conecta el LCD: RS D7, E D8, D4 D9, D5 D10, D6 D11, D7 D12 y RW a GND.
  4. Copia el sketch, compilalo y subelo. LiquidCrystal forma parte del nucleo, no hace falta instalarla.
  5. Abre el monitor serie a 9600 y apunta el sensor a una pared cercana, entre 5 y 100 cm.
  6. Comprueba que el LCD y el serie marcan centimetros parecidos y que al tapar el sensor sale fuera de rango.
  7. Ajusta el contraste si la pantalla enciende pero no se leen los numeros.

Variantes

Depuración

Software: digitalwrite serial millis

Falcon · AP-FAL-03

Cerradura con PIN en teclado 4×4

Objetivo

Al terminar, la cerradura de juguete se abre solo si tecleas el PIN de cuatro cifras que vive en el propio sketch. No hay servidor, ni clave en la red, ni nada fuera de la placa: el teclado se lee por filas y columnas, el rele se activa unos segundos y luego vuelve a cerrar. La carga del rele es de 5 a 12 V en corriente continua. No se conmuta la red.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1Teclado 4×4modulo-teclado-4x4genérico / clonepoco (≈1–3 €)Matriz de 4 filas y 4 columnas. Filas en D2 a D5 y columnas en D6 a D9.
1Relé 5 Vmodulo-relegenérico / clonepoco (≈1–3 €)Conmuta la cerradura o el solenoide de juguete. Carga de 5 a 12 V. No se conmuta la red. Muchos modulos activan con nivel bajo.
1Zumbador act/pasmodulo-zumbadorgenérico / cloneirrisorio (<1 €)Aviso corto cuando el PIN es incorrecto. Senal en D11.
1LED 5 mmmodulo-ledgenérico / cloneirrisorio (<1 €)Encendido mientras la cerradura esta abierta. Senal en D12.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza Teclado fila 1 Teclado fila 2 Teclado fila 3 Teclado fila 4 Teclado columna 1 Teclado columna 2 Teclado columna 3 Teclado columna 4 Rele IN Zumbador senal LED senal Teclado VCC Rele VCC Zumbador VCC LED VCC Masas de modulos Contactos COM y NO del rele D2 D3 D4 D5 D6 D7 D8 D9 D10 D11 D12 5V GND Cerradura de 5 a 12 V y su fuente

Código

// AP-FAL-03 Cerradura con PIN en teclado 4x4
// Pines: filas D2 D3 D4 D5, columnas D6 D7 D8 D9, rele D10, zumbador D11, led D12
// El PIN vive en este sketch. No hay servidor.
// Carga del rele: 5 a 12 V. No se conmuta la red.

const char PIN_SECRETO[] = "1234";
const byte pinesFila[4] = {2, 3, 4, 5};
const byte pinesCol[4] = {6, 7, 8, 9};
const int PIN_RELE = 10;
const int PIN_ZUM = 11;
const int PIN_LED = 12;
const byte RELE_ON = LOW;
const byte RELE_OFF = HIGH;
const unsigned long ABIERTA_MS = 5000;
const unsigned long ERROR_MS = 800;

const char teclas[4][4] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};

char entrada[5];
byte nEntrada = 0;
bool abierta = false;
unsigned long tEstado = 0;
unsigned long tError = 0;

char leerTecla() {
  for (byte c = 0; c < 4; c++) {
    digitalWrite(pinesCol[c], LOW);
    delayMicroseconds(50);
    for (byte f = 0; f < 4; f++) {
      if (digitalRead(pinesFila[f]) == LOW) {
        digitalWrite(pinesCol[c], HIGH);
        return teclas[f][c];
      }
    }
    digitalWrite(pinesCol[c], HIGH);
  }
  return 0;
}

void cerrar() {
  abierta = false;
  digitalWrite(PIN_RELE, RELE_OFF);
  digitalWrite(PIN_LED, LOW);
}

void setup() {
  Serial.begin(9600);
  for (byte f = 0; f < 4; f++) {
    pinMode(pinesFila[f], INPUT_PULLUP);
  }
  for (byte c = 0; c < 4; c++) {
    pinMode(pinesCol[c], OUTPUT);
    digitalWrite(pinesCol[c], HIGH);
  }
  pinMode(PIN_RELE, OUTPUT);
  pinMode(PIN_ZUM, OUTPUT);
  pinMode(PIN_LED, OUTPUT);
  digitalWrite(PIN_ZUM, LOW);
  cerrar();
  Serial.println("Cerradura local lista. PIN en el sketch, sin servidor.");
}

void loop() {
  unsigned long ahora = millis();
  if (tError != 0 && ahora - tError >= ERROR_MS) {
    digitalWrite(PIN_ZUM, LOW);
    tError = 0;
  }
  if (abierta && ahora - tEstado >= ABIERTA_MS) {
    cerrar();
    nEntrada = 0;
    entrada[0] = 0;
    Serial.println("Cerrada");
  }

  static char previa = 0;
  char tecla = leerTecla();
  if (tecla == 0) {
    previa = 0;
    return;
  }
  if (tecla == previa) {
    return;
  }
  previa = tecla;
  if (abierta) {
    return;
  }
  if (tecla == '*') {
    nEntrada = 0;
    entrada[0] = 0;
    Serial.println("Borrado");
    return;
  }
  if (tecla < '0' || tecla > '9') {
    return;
  }
  if (nEntrada < 4) {
    entrada[nEntrada++] = tecla;
    entrada[nEntrada] = 0;
    Serial.println(entrada);
  }
  if (nEntrada < 4) {
    return;
  }
  if (strcmp(entrada, PIN_SECRETO) == 0) {
    abierta = true;
    tEstado = ahora;
    digitalWrite(PIN_RELE, RELE_ON);
    digitalWrite(PIN_LED, HIGH);
    Serial.println("PIN correcto, abierta");
  } else {
    digitalWrite(PIN_ZUM, HIGH);
    tError = ahora;
    Serial.println("PIN incorrecto");
  }
  nEntrada = 0;
  entrada[0] = 0;
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. El PIN por defecto del sketch es 1234 y solo existe dentro del programa.
  2. Conecta las cuatro filas del teclado a D2, D3, D4 y D5, y las cuatro columnas a D6, D7, D8 y D9.
  3. Conecta el IN del rele a D10, el zumbador a D11 y el led a D12, con las masas a GND y VCC de cada modulo a 5 V si el modulo lo trae.
  4. En los contactos del rele pon solo una cerradura o solenoide de 5 a 12 V con su fuente. No se conmuta la red.
  5. Sube el sketch y abre el monitor serie a 9600. Teclea 1234 y comprueba que el led se enciende y el rele cambia unos cinco segundos.
  6. Teclea otro numero de cuatro cifras y comprueba el pitido de error y que la cerradura no se abre.
  7. Pulsa asterisco a mitad de la clave y confirma en el serie que el buffer se borra antes de volver a probar.

Variantes

Depuración

Software: digitalwrite digitalread millis serial

Falcon · AP-FAL-04

Alarma de puerta con retardo

Objetivo

Al terminar, la alarma no suena en cuanto alimentas la placa: primero cuenta un retardo de armado para que cierres la puerta, y despues, si el reed detecta que se abre, espera un segundo retardo corto antes de activar el zumbador. Si vuelves a cerrar a tiempo, el aviso se cancela. El conteo entero sale de millis, con un filtrado sencillo del contacto para que un rebote no dispare la sirena.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1Reedsensor-reedgenérico / cloneirrisorio (<1 €)En el marco de la puerta. Salida a D2 con pull-up interno. Iman en la hoja: puerta cerrada deja la salida en bajo.
1Zumbador act/pasmodulo-zumbadorgenérico / cloneirrisorio (<1 €)Sirena de la alarma en D8. Suena solo cuando la puerta sigue abierta tras el retardo.
1LED 5 mmmodulo-ledgenérico / cloneirrisorio (<1 €)Indicador de alarma armada en D4. Apagado durante el retardo inicial.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza Reed OUT Reed VCC Reed GND Zumbador senal Zumbador GND LED senal LED GND D2 5V GND D8 D4

Código

// AP-FAL-04 Alarma de puerta con retardo
// Pines: reed D2, led armado D4, zumbador D8
const int PIN_REED = 2;
const int PIN_LED = 4;
const int PIN_ZUM = 8;
const unsigned long ARMADO_MS = 15000;
const unsigned long GRACIA_MS = 3000;
const unsigned long FILTRO_MS = 40;

unsigned long arranque;
bool armada = false;
bool puertaAbierta = false;
unsigned long cambioPuerta = 0;
unsigned long abiertaDesde = 0;
bool sonando = false;

bool leerAbiertaFiltrada(unsigned long ahora) {
  bool lecturaAbierta = digitalRead(PIN_REED) == HIGH;
  if (lecturaAbierta != puertaAbierta) {
    if (ahora - cambioPuerta >= FILTRO_MS) {
      puertaAbierta = lecturaAbierta;
    }
  } else {
    cambioPuerta = ahora;
  }
  return puertaAbierta;
}

void setup() {
  Serial.begin(9600);
  pinMode(PIN_REED, INPUT_PULLUP);
  pinMode(PIN_LED, OUTPUT);
  pinMode(PIN_ZUM, OUTPUT);
  digitalWrite(PIN_LED, LOW);
  digitalWrite(PIN_ZUM, LOW);
  arranque = millis();
  cambioPuerta = arranque;
  Serial.println("Retardo de armado. Cierra la puerta.");
}

void loop() {
  unsigned long ahora = millis();
  bool abierta = leerAbiertaFiltrada(ahora);

  if (!armada) {
    digitalWrite(PIN_LED, LOW);
    digitalWrite(PIN_ZUM, LOW);
    if (ahora - arranque >= ARMADO_MS) {
      armada = true;
      abiertaDesde = 0;
      Serial.println("Alarma armada");
    }
    return;
  }

  digitalWrite(PIN_LED, HIGH);
  if (!abierta) {
    abiertaDesde = 0;
    if (sonando) {
      sonando = false;
      digitalWrite(PIN_ZUM, LOW);
      Serial.println("Puerta cerrada, silencio");
    }
    return;
  }

  if (abiertaDesde == 0) {
    abiertaDesde = ahora;
    Serial.println("Puerta abierta, empieza la gracia");
  }
  if (!sonando && ahora - abiertaDesde >= GRACIA_MS) {
    sonando = true;
    digitalWrite(PIN_ZUM, HIGH);
    Serial.println("Alarma");
  }
}

Pasos

  1. Monta una sola placa, selecciona Arduino Uno y conecta la salida del reed a D2 y su GND a masa.
  2. Si el reed es un modulo con VCC, alimentalo a 5 V. Si es un contacto seco, no pongas 5 V: basta D2 y GND.
  3. Coloca el iman de forma que, con la puerta cerrada, el serie acabe viendo el contacto en bajo.
  4. Conecta el led de armado a D4 y el zumbador a D8, ambos con su masa a GND.
  5. Sube el sketch y abre el monitor serie a 9600. Durante quince segundos la alarma no debe sonar aunque abras.
  6. Pasado el armado, abre la puerta: el zumbador espera tres segundos y solo entonces suena. Cierrala y debe callar.
  7. Vuelve a abrir y cierra antes de tres segundos para comprobar que la gracia cancela el aviso.

Variantes

Depuración

Software: digitalread digitalwrite millis serial debounce

Enseñanza: L33 Alarma con sensor

Falcon · AP-FAL-05

Riego según humedad del suelo

Objetivo

Al terminar, la placa lee la humedad del suelo por A0 y, si la tierra esta seca por encima del umbral que calibres, activa el rele el tiempo justo para regar y luego lo corta aunque el sensor tarde en reaccionar. La bomba o la electrovalvula es una carga de 5 a 12 V en corriente continua, con su propia fuente. No se conmuta la red. Entre dos riegos hay una pausa para no encharcar si el sensor falla.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1Humedad suelosensor-humedad-suelogenérico / cloneirrisorio (<1 €)Sonda analogica en A0. Calibra en seco y en humedo porque el numero cambia con cada modulo.
1Relé 5 Vmodulo-relegenérico / clonepoco (≈1–3 €)Conmuta la bomba o la electrovalvula. Carga de 5 a 12 V. No se conmuta la red. Activo a nivel bajo.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza Sensor de suelo AO Sensor de suelo VCC Sensor de suelo GND Rele IN Rele VCC Rele GND Contactos COM y NO A0 5V GND D8 Bomba o electrovalvula de 5 a 12 V

Código

// AP-FAL-05 Riego segun humedad del suelo
// Pines: suelo A0, rele D8
// Carga de 5 a 12 V. No se conmuta la red.
const int PIN_SUELO = A0;
const int PIN_RELE = 8;
const byte RELE_ON = LOW;
const byte RELE_OFF = HIGH;

// Muchos modulos dan un numero ALTO con la tierra seca. Calibralo.
const int UMBRAL_SECO = 650;
const unsigned long PERIODO_MS = 1000;
const unsigned long RIEGO_MS = 8000;
const unsigned long PAUSA_MS = 20000;

bool regando = false;
unsigned long inicioRiego = 0;
unsigned long finRiego = 0;

void escribirRele(bool on) {
  digitalWrite(PIN_RELE, on ? RELE_ON : RELE_OFF);
}

void setup() {
  Serial.begin(9600);
  pinMode(PIN_RELE, OUTPUT);
  escribirRele(false);
  Serial.println("Riego listo. Rele en reposo.");
}

void loop() {
  unsigned long ahora = millis();
  static unsigned long anterior = 0;
  if (ahora - anterior < PERIODO_MS) {
    return;
  }
  anterior = ahora;

  int suelo = analogRead(PIN_SUELO);
  Serial.print("Suelo ");
  Serial.println(suelo);

  if (regando) {
    if (ahora - inicioRiego >= RIEGO_MS) {
      regando = false;
      finRiego = ahora;
      escribirRele(false);
      Serial.println("Fin de riego y pausa");
    }
    return;
  }

  if (finRiego != 0 && ahora - finRiego < PAUSA_MS) {
    escribirRele(false);
    return;
  }

  if (suelo >= UMBRAL_SECO) {
    regando = true;
    inicioRiego = ahora;
    escribirRele(true);
    Serial.println("Tierra seca, riego");
  } else {
    escribirRele(false);
  }
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta la salida analogica del sensor de suelo a A0, VCC a 5 V y GND a masa.
  2. Clava la sonda en la tierra de prueba, no en el aire, y deja el modulo electronico fuera del agua.
  3. Conecta el IN del rele a D8, su VCC a 5 V y su GND a masa. Deja la bomba desconectada en la primera prueba.
  4. Sube el sketch, abre el serie a 9600 y anota el numero en seco y el numero recien regado. Ajusta UMBRAL_SECO entre los dos.
  5. Solo entonces conecta en COM y NO una bomba o electrovalvula de 5 a 12 V con su fuente. No se conmuta la red.
  6. Seca la sonda o sube el umbral y comprueba que el rele se activa como mucho ocho segundos y luego espera la pausa.
  7. Humedece la tierra y confirma que, fuera de la pausa, el rele permanece en reposo.

Variantes

Depuración

Software: analogread digitalwrite millis serial

Falcon · AP-FAL-06

Barrera: ultrasonidos y servo

Objetivo

Al terminar, una barrera de juguete movida por el servo se levanta cuando el HC-SR04 ve un objeto a menos de veinte centimetros y vuelve a la posicion cerrada cuando el hueco queda libre. El servo solo recibe orden al cambiar de estado, para que no vibre, y el monitor serie te dice si la barrera esta abierta o cerrada junto con la distancia. Queda un paso automatico que puedes probar con la mano, sin empujar el brazo.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1HC-SR04sensor-hc-sr04genérico / cloneirrisorio (<1 €)Trigger en D6 y eco en D7, mirando al hueco por donde pasas la mano.
1Servo SG90modulo-servogenérico / clonepoco (≈1–3 €)Barrera en D9. Comparte GND con la placa. Si la placa se reinicia, alimenta el servo con 5 V externos y la misma masa.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza HC-SR04 TRIG HC-SR04 ECHO HC-SR04 VCC HC-SR04 GND Servo senal Servo VCC Servo GND Alimentacion del servo D6 D7 5V GND D9 Fuente de 5 V compartiendo solo GND

Código

// AP-FAL-06 Barrera: ultrasonidos y servo
// Pines: TRIG D6, ECHO D7, servo D9
#include <Servo.h>

const int PIN_TRIG = 6;
const int PIN_ECHO = 7;
const int PIN_SERVO = 9;
const int ANGULO_CERRADA = 0;
const int ANGULO_ABIERTA = 90;
const float UMBRAL_CM = 20.0;

Servo barrera;
bool abierta = false;

float medirCm() {
  digitalWrite(PIN_TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(PIN_TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(PIN_TRIG, LOW);
  unsigned long us = pulseIn(PIN_ECHO, HIGH, 30000UL);
  if (us == 0) {
    return -1.0;
  }
  return us / 58.0;
}

void mover(bool abrir) {
  if (abrir == abierta) {
    return;
  }
  abierta = abrir;
  barrera.write(abierta ? ANGULO_ABIERTA : ANGULO_CERRADA);
  Serial.println(abierta ? "Barrera abierta" : "Barrera cerrada");
}

void setup() {
  Serial.begin(9600);
  pinMode(PIN_TRIG, OUTPUT);
  pinMode(PIN_ECHO, INPUT);
  digitalWrite(PIN_TRIG, LOW);
  barrera.attach(PIN_SERVO);
  barrera.write(ANGULO_CERRADA);
  Serial.println("Barrera lista");
}

void loop() {
  static unsigned long anterior = 0;
  unsigned long ahora = millis();
  if (ahora - anterior < 150) {
    return;
  }
  anterior = ahora;

  float cm = medirCm();
  Serial.print("cm ");
  Serial.println(cm);
  bool hayAlgo = (cm > 2.0 && cm < UMBRAL_CM);
  mover(hayAlgo);
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta TRIG a D6, ECHO a D7, VCC del HC-SR04 a 5 V y GND a masa.
  2. Conecta la senal del servo a D9, su positivo a 5 V y su GND al GND de la placa.
  3. Sujeta un palo ligero al servo como barrera de juguete, sin forzar el engranaje con la mano mientras esta alimentado.
  4. Sube el sketch. La libreria Servo viene con el nucleo. Abre el serie a 9600.
  5. Sin nada delante, la barrera debe quedarse en el angulo cerrado. Acerca la mano a menos de 20 cm y debe pasar a 90 grados.
  6. Retira la mano y comprueba que vuelve a cero y que el serie no reescribe la orden en cada vuelta si no hay cambio.
  7. Si la placa se reinicia al moverse, alimenta el servo con 5 V externos unidos solo por GND.

Variantes

Depuración

Software: servo digitalwrite millis serial

Falcon · AP-FAL-07

Semáforo con presencia

Objetivo

Al terminar, tres leds hacen de semaforo de juguete y cambian de fase con millis, sin quedarse bloqueados en una espera. El verde y el ambar duran un tiempo fijo; el rojo puede acortarse si el HC-SR04 detecta presencia cerca, siempre que el rojo lleve ya un minimo encendido. Si no pasa nadie, el rojo cumple su tiempo maximo y el ciclo sigue solo. El serie te dice la fase activa para que no dependas solo de los colores.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1LED 5 mmmodulo-ledgenérico / cloneirrisorio (<1 €)Led rojo en D2.
1LED 5 mmmodulo-ledgenérico / cloneirrisorio (<1 €)Led ambar en D3.
1LED 5 mmmodulo-ledgenérico / cloneirrisorio (<1 €)Led verde en D4.
1HC-SR04sensor-hc-sr04genérico / cloneirrisorio (<1 €)Detecta presencia. Trigger en D7 y eco en D8.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza LED rojo senal LED ambar senal LED verde senal Masas de los tres leds HC-SR04 TRIG HC-SR04 ECHO HC-SR04 VCC HC-SR04 GND VCC de los modulos de led D2 D3 D4 GND D7 D8 5V

Código

// AP-FAL-07 Semaforo con presencia
// Pines: rojo D2, ambar D3, verde D4, TRIG D7, ECHO D8
const int PIN_ROJO = 2;
const int PIN_AMBAR = 3;
const int PIN_VERDE = 4;
const int PIN_TRIG = 7;
const int PIN_ECHO = 8;

enum Fase { VERDE, AMBAR, ROJO };
Fase fase = VERDE;
unsigned long inicioFase = 0;

const unsigned long T_VERDE = 5000;
const unsigned long T_AMBAR = 2000;
const unsigned long T_ROJO_MIN = 2000;
const unsigned long T_ROJO_MAX = 8000;
const float CERCA_CM = 40.0;

float medirCm() {
  digitalWrite(PIN_TRIG, LOW);
  delayMicroseconds(2);
  digitalWrite(PIN_TRIG, HIGH);
  delayMicroseconds(10);
  digitalWrite(PIN_TRIG, LOW);
  unsigned long us = pulseIn(PIN_ECHO, HIGH, 30000UL);
  if (us == 0) {
    return -1.0;
  }
  return us / 58.0;
}

void pintar() {
  digitalWrite(PIN_VERDE, fase == VERDE ? HIGH : LOW);
  digitalWrite(PIN_AMBAR, fase == AMBAR ? HIGH : LOW);
  digitalWrite(PIN_ROJO, fase == ROJO ? HIGH : LOW);
}

void cambiar(Fase nueva, unsigned long ahora) {
  fase = nueva;
  inicioFase = ahora;
  pintar();
  if (fase == VERDE) Serial.println("Fase verde");
  if (fase == AMBAR) Serial.println("Fase ambar");
  if (fase == ROJO) Serial.println("Fase rojo");
}

void setup() {
  Serial.begin(9600);
  pinMode(PIN_ROJO, OUTPUT);
  pinMode(PIN_AMBAR, OUTPUT);
  pinMode(PIN_VERDE, OUTPUT);
  pinMode(PIN_TRIG, OUTPUT);
  pinMode(PIN_ECHO, INPUT);
  cambiar(VERDE, millis());
}

void loop() {
  unsigned long ahora = millis();
  unsigned long lleva = ahora - inicioFase;

  if (fase == VERDE && lleva >= T_VERDE) {
    cambiar(AMBAR, ahora);
    return;
  }
  if (fase == AMBAR && lleva >= T_AMBAR) {
    cambiar(ROJO, ahora);
    return;
  }
  if (fase == ROJO) {
    float cm = medirCm();
    bool presencia = (cm > 2.0 && cm < CERCA_CM);
    if (lleva >= T_ROJO_MAX || (presencia && lleva >= T_ROJO_MIN)) {
      cambiar(VERDE, ahora);
    }
  }
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta el led rojo a D2, el ambar a D3 y el verde a D4, con sus masas a GND.
  2. Conecta TRIG del HC-SR04 a D7, ECHO a D8, VCC a 5 V y GND a masa, apuntando hacia donde vas a poner la mano.
  3. Sube el sketch y abre el monitor serie a 9600. Deben sucederse verde, ambar y rojo sin que el programa se quede mudo.
  4. Durante el rojo, no pongas nada delante: la fase debe agotar unos ocho segundos antes de volver al verde.
  5. Reinicia, espera al rojo y acerca la mano a menos de 40 cm cuando ya lleve un par de segundos. El verde tiene que adelantarse.
  6. Comprueba que en el primer instante del rojo la presencia no lo salta: el minimo de dos segundos se respeta.
  7. Si un color no enciende, cambia solo ese modulo antes de tocar los tiempos.

Variantes

Depuración

Software: digitalwrite millis maquina-estados serial

Falcon · AP-FAL-08

Termostato on/off con histéresis

Objetivo

Al terminar, el rele se comporta como un termostato de verdad: enciende la carga cuando la temperatura baja del umbral bajo y no la apaga hasta llegar al umbral alto. Esa histéresis evita que el rele tabletee cuando el sensor ronda un solo numero. Entre medias no hace nada aunque la lectura se mueva un poco. La carga es de 5 a 12 V en corriente continua. No se conmuta la red. Si el DHT11 falla una lectura, el rele se queda como estaba.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1DHT11sensor-dht11genérico / cloneirrisorio (<1 €)Temperatura en D2. La humedad se lee pero el termostato decide solo con los grados.
1Relé 5 Vmodulo-relegenérico / clonepoco (≈1–3 €)Conmuta un calentador o un ventilador de juguete. Carga de 5 a 12 V. No se conmuta la red.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza DHT11 DATA DHT11 VCC DHT11 GND Rele IN Rele VCC Rele GND Contactos COM y NO D2 5V GND D8 Carga de 5 a 12 V

Código

// AP-FAL-08 Termostato on/off con histeresis
// Pines: DHT D2, rele D8
// Umbral alto y umbral bajo: no es un unico punto de conmutacion.
// Carga de 5 a 12 V. No se conmuta la red.
#include <DHT.h>

const int PIN_DHT = 2;
const int PIN_RELE = 8;
const byte RELE_ON = LOW;
const byte RELE_OFF = HIGH;
const float UMBRAL_ALTO = 25.0;
const float UMBRAL_BAJO = 22.0;
const unsigned long PERIODO_MS = 2000;

DHT dht(PIN_DHT, DHT11);
bool calentando = false;

void aplicarRele() {
  digitalWrite(PIN_RELE, calentando ? RELE_ON : RELE_OFF);
}

void setup() {
  Serial.begin(9600);
  pinMode(PIN_RELE, OUTPUT);
  dht.begin();
  calentando = false;
  aplicarRele();
  Serial.println("Termostato listo");
}

void loop() {
  static unsigned long anterior = 0;
  unsigned long ahora = millis();
  if (ahora - anterior < PERIODO_MS) {
    return;
  }
  anterior = ahora;

  float t = dht.readTemperature();
  if (isnan(t)) {
    Serial.println("Lectura no valida, el rele no cambia");
    return;
  }

  if (calentando) {
    if (t >= UMBRAL_ALTO) {
      calentando = false;
    }
  } else {
    if (t <= UMBRAL_BAJO) {
      calentando = true;
    }
  }
  aplicarRele();

  Serial.print("T ");
  Serial.print(t, 1);
  Serial.print(" C  ");
  Serial.print("alto ");
  Serial.print(UMBRAL_ALTO, 1);
  Serial.print(" bajo ");
  Serial.print(UMBRAL_BAJO, 1);
  Serial.println(calentando ? "  CALOR" : "  REPOSO");
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta el DHT11: datos a D2, VCC a 5 V y GND a masa.
  2. Instala la libreria DHT sensor library desde el gestor de librerias del IDE.
  3. Conecta el IN del rele a D8 y su alimentacion de bobina a 5 V y GND. Deja la carga sin conectar en el primer ensayo.
  4. Sube el sketch y abre el serie a 9600. Anota la temperatura de la sala.
  5. Pon UMBRAL_BAJO un grado por encima de la sala y UMBRAL_ALTO dos grados mas alto, vuelve a subir y comprueba que entra en CALOR.
  6. Calienta el sensor con los dedos, sin mojarlo, hasta pasar el umbral alto y confirma que pasa a REPOSO y no vuelve a encender al bajar solo unas decimas.
  7. Conecta entonces una carga de 5 a 12 V en COM y NO. No se conmuta la red.

Variantes

Depuración

Software: digitalwrite serial millis

Falcon · AP-FAL-09

Registro en tarjeta SD

Objetivo

Al terminar, cada cinco segundos la placa lee el potenciometro y anade una linea al archivo REGISTRO.CSV de la tarjeta SD, con el tiempo en millis y el valor analogico. Puedes apagar, sacar la tarjeta y abrir el archivo en el ordenador para ver que las medidas siguen ahi. El chip select queda fijo en D10 y el resto del bus es el SPI del nucleo: D11, D12 y D13. Si la tarjeta no arranca, el serie lo dice y no finge que ha guardado nada.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1microSD SPImodulo-sdgenérico / clonepoco (≈1–3 €)Lector SPI. CS obligatorio en D10. Tarjeta formateada en FAT16 o FAT32.
1Potenciómetromodulo-potenciometrogenérico / cloneirrisorio (<1 €)Genera el dato que se registra, del extremo a A0. Sirve para probar el archivo sin otro sensor.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza Modulo SD CS Modulo SD MOSI Modulo SD MISO Modulo SD SCK Modulo SD VCC Modulo SD GND Potenciometro cursor Potenciometro extremo alto Potenciometro extremo bajo CS del lector D10 D11 D12 D13 5V GND A0 Solo D10, no otro pin

Código

// AP-FAL-09 Registro en tarjeta SD
// Pines: CS D10, MOSI D11, MISO D12, SCK D13, potenciometro A0
// Libreria SD del nucleo. SPI del nucleo.
#include <SPI.h>
#include <SD.h>

const int PIN_CS = 10;
const int PIN_POT = A0;
const unsigned long PERIODO_MS = 5000;

bool sdOk = false;

void setup() {
  Serial.begin(9600);
  sdOk = SD.begin(PIN_CS);
  if (!sdOk) {
    Serial.println("Fallo SD. Revisa CS en D10, SPI y la tarjeta.");
    return;
  }
  Serial.println("SD lista en D10");
}

void loop() {
  if (!sdOk) {
    return;
  }
  static unsigned long anterior = 0;
  unsigned long ahora = millis();
  if (ahora - anterior < PERIODO_MS) {
    return;
  }
  anterior = ahora;

  int valor = analogRead(PIN_POT);
  File f = SD.open("REGISTRO.CSV", FILE_WRITE);
  if (!f) {
    Serial.println("No se abre REGISTRO.CSV");
    return;
  }
  f.print(ahora);
  f.print(",");
  f.println(valor);
  f.close();

  Serial.print("Guardado ");
  Serial.print(ahora);
  Serial.print(",");
  Serial.println(valor);
}

Pasos

  1. Formatea la tarjeta en FAT32 con un lector del ordenador y dejala vacia, con nombre de volumen corto.
  2. Monta una sola placa. Conecta CS a D10, MOSI a D11, MISO a D12, SCK a D13, VCC y GND del modulo SD.
  3. Conecta el cursor del potenciometro a A0 y los extremos a 5 V y GND.
  4. Inserta la tarjeta, sube el sketch y abre el serie a 9600. Tiene que decir que la SD esta lista.
  5. Gira el potenciometro y espera dos o tres lineas de Guardado. Apaga la placa antes de sacar la tarjeta.
  6. Lee REGISTRO.CSV en el ordenador y comprueba que cada linea trae millis y el valor, y que el valor cambio al girar.
  7. Si begin falla, no sigas escribiendo a ciegas: revisa el pin D10 y que la tarjeta entre hasta el fondo.

Variantes

Depuración

Software: sd spi analogread serial millis

Falcon · AP-FAL-10

Reloj DS3231 en LCD

Objetivo

Al terminar, el LCD muestra la fecha y la hora que mantiene el DS3231 por I2C, y siguen avanzando aunque reinicies la placa, porque el reloj no depende del millis de la Uno. La primera vez que el modulo ha perdido la pila, el sketch carga la hora de compilacion; despues no la pisa en cada arranque. El monitor serie repite la hora una vez por segundo para que compruebes el bus aunque el contraste del LCD este cerrado.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno. SDA en A4 y SCL en A5.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1RTC DS3231modulo-ds3231genérico / clonepoco (≈1–3 €)Reloj I2C. Direccion 0x68. Instala la libreria RTClib desde el gestor del IDE.
1LCD 1602 I2Cmodulo-lcd-1602genérico / clonepoco (≈1–3 €)Fecha en la primera linea y hora en la segunda, en paralelo de 4 bits.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza DS3231 SDA DS3231 SCL DS3231 VCC DS3231 GND LCD RS LCD E LCD D4 LCD D5 LCD D6 LCD D7 LCD RW LCD VCC LCD GND A4 A5 5V GND D7 D8 D9 D10 D11 D12

Código

// AP-FAL-10 Reloj DS3231 en LCD
// Pines: SDA A4, SCL A5, LCD RS D7, E D8, D4 D9, D5 D10, D6 D11, D7 D12
// RTC por I2C con RTClib. El DS3231 responde en 0x68.
#include <Wire.h>
#include <RTClib.h>
#include <LiquidCrystal.h>

const int PIN_RS = 7;
const int PIN_E = 8;
const int PIN_D4 = 9;
const int PIN_D5 = 10;
const int PIN_D6 = 11;
const int PIN_D7 = 12;

RTC_DS3231 rtc;
LiquidCrystal lcd(PIN_RS, PIN_E, PIN_D4, PIN_D5, PIN_D6, PIN_D7);
bool rtcOk = false;

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  rtcOk = rtc.begin();
  if (!rtcOk) {
    lcd.print("RTC no responde");
    Serial.println("DS3231 no responde en I2C");
    return;
  }
  if (rtc.lostPower()) {
    rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    Serial.println("Hora cargada desde la compilacion");
  }
  Serial.println("Reloj listo");
}

void loop() {
  if (!rtcOk) {
    return;
  }
  static unsigned long anterior = 0;
  unsigned long ahoraMs = millis();
  if (ahoraMs - anterior < 1000) {
    return;
  }
  anterior = ahoraMs;

  DateTime t = rtc.now();
  lcd.setCursor(0, 0);
  if (t.day() < 10) lcd.print('0');
  lcd.print(t.day());
  lcd.print('/');
  if (t.month() < 10) lcd.print('0');
  lcd.print(t.month());
  lcd.print('/');
  lcd.print(t.year());

  lcd.setCursor(0, 1);
  if (t.hour() < 10) lcd.print('0');
  lcd.print(t.hour());
  lcd.print(':');
  if (t.minute() < 10) lcd.print('0');
  lcd.print(t.minute());
  lcd.print(':');
  if (t.second() < 10) lcd.print('0');
  lcd.print(t.second());
  lcd.print("    ");

  Serial.print(t.hour());
  Serial.print(':');
  Serial.print(t.minute());
  Serial.print(':');
  Serial.println(t.second());
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta SDA del DS3231 a A4, SCL a A5, VCC a 5 V y GND a masa.
  2. Conecta el LCD en 4 bits: RS D7, E D8, D4 D9, D5 D10, D6 D11, D7 D12 y RW a GND.
  3. Instala la libreria RTClib desde el gestor de librerias. Wire y LiquidCrystal ya vienen en el nucleo.
  4. Sube el sketch con el modulo puesto. Si la pila estaba vacia, la hora inicial sera la del momento de compilar.
  5. Abre el serie a 9600 y comprueba que los segundos avanzan tambien tras pulsar el reset de la placa.
  6. Ajusta el contraste del LCD hasta ver la fecha arriba y la hora abajo.
  7. Si quieres otra hora, pon el reloj en hora en un unico adjust, sube el sketch una vez y luego quita esa linea para no pisarla en cada arranque.

Variantes

Depuración

Software: i2c rtc serial millis

Falcon · AP-FAL-11

Menú en LCD con tres pulsadores

Objetivo

Al terminar, el LCD muestra un menu de tres ajustes y puedes recorrerlo con dos pulsadores y cambiar el valor con el tercero, sin que un rebote te salte varias lineas. El programa distingue navegar de editar con una maquina de estados corta, asi que el boton de aceptar no se mezcla con el de avanzar. Los valores se ven tambien por el monitor serie. No se guarda nada todavia: al reiniciar vuelven los valores iniciales, y eso es justo lo que este montaje deja funcionando.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1LCD 1602 I2Cmodulo-lcd-1602genérico / clonepoco (≈1–3 €)Muestra el nombre del ajuste y su valor.
1Pulsadormodulo-pulsadorgenérico / cloneirrisorio (<1 €)Anterior, en D2, a masa, con pull-up interno.
1Pulsadormodulo-pulsadorgenérico / cloneirrisorio (<1 €)Siguiente, en D3, a masa, con pull-up interno.
1Pulsadormodulo-pulsadorgenérico / cloneirrisorio (<1 €)Aceptar o sumar, en D4, a masa, con pull-up interno.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza Pulsador anterior Pulsador siguiente Pulsador aceptar Pulsadores GND LCD RS LCD E LCD D4 LCD D5 LCD D6 LCD D7 LCD RW LCD VCC LCD GND D2 D3 D4 GND D7 D8 D9 D10 D11 D12 5V

Código

// AP-FAL-11 Menu en LCD con tres pulsadores
// Pines: anterior D2, siguiente D3, aceptar D4
// LCD RS D7, E D8, D4 D9, D5 D10, D6 D11, D7 D12
#include <LiquidCrystal.h>

const int PIN_ANT = 2;
const int PIN_SIG = 3;
const int PIN_OK = 4;
const int PIN_RS = 7;
const int PIN_E = 8;
const int PIN_D4 = 9;
const int PIN_D5 = 10;
const int PIN_D6 = 11;
const int PIN_D7 = 12;
const unsigned long VENTANA_MS = 40;

enum Vista { NAVEGA, EDITA };
Vista vista = NAVEGA;

const char *NOMBRE[3] = {"Brillo", "Periodo", "Aviso"};
int valor[3] = {10, 2, 0};
const int TOPE[3] = {100, 30, 1};
byte indice = 0;

LiquidCrystal lcd(PIN_RS, PIN_E, PIN_D4, PIN_D5, PIN_D6, PIN_D7);

bool flanco(byte pin) {
  static unsigned long cambio[20];
  static byte estable[20];
  static byte previo[20];
  static bool listo = false;
  if (!listo) {
    for (byte i = 0; i < 20; i++) {
      estable[i] = HIGH;
      previo[i] = HIGH;
      cambio[i] = 0;
    }
    listo = true;
  }
  bool lectura = digitalRead(pin);
  unsigned long ahora = millis();
  if (lectura != estable[pin]) {
    if (ahora - cambio[pin] >= VENTANA_MS) {
      estable[pin] = lectura;
    }
  } else {
    cambio[pin] = ahora;
  }
  bool pulso = (previo[pin] == HIGH && estable[pin] == LOW);
  previo[pin] = estable[pin];
  return pulso;
}

void pintar() {
  lcd.setCursor(0, 0);
  lcd.print(vista == NAVEGA ? "Menu " : "Edit ");
  lcd.print(indice + 1);
  lcd.print("/3        ");
  lcd.setCursor(0, 1);
  lcd.print(NOMBRE[indice]);
  lcd.print(" ");
  lcd.print(valor[indice]);
  lcd.print("     ");
}

void setup() {
  Serial.begin(9600);
  pinMode(PIN_ANT, INPUT_PULLUP);
  pinMode(PIN_SIG, INPUT_PULLUP);
  pinMode(PIN_OK, INPUT_PULLUP);
  lcd.begin(16, 2);
  pintar();
  Serial.println("Menu listo");
}

void loop() {
  bool cambio = false;
  if (flanco(PIN_ANT)) {
    if (vista == NAVEGA) {
      indice = (indice == 0) ? 2 : indice - 1;
    } else if (valor[indice] > 0) {
      valor[indice]--;
    }
    cambio = true;
  }
  if (flanco(PIN_SIG)) {
    if (vista == NAVEGA) {
      indice = (indice + 1) % 3;
    } else if (valor[indice] < TOPE[indice]) {
      valor[indice]++;
    }
    cambio = true;
  }
  if (flanco(PIN_OK)) {
    vista = (vista == NAVEGA) ? EDITA : NAVEGA;
    cambio = true;
  }
  if (cambio) {
    pintar();
    Serial.print(NOMBRE[indice]);
    Serial.print(" = ");
    Serial.println(valor[indice]);
  }
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta los tres pulsadores entre D2, D3 y D4 y GND. No les pongas 5 V en el contacto.
  2. Conecta el LCD: RS D7, E D8, D4 D9, D5 D10, D6 D11, D7 D12 y RW a GND.
  3. Sube el sketch y abre el serie a 9600. LiquidCrystal viene en el nucleo.
  4. Con el menu en modo Menu, usa D3 para avanzar y D2 para retroceder entre Brillo, Periodo y Aviso.
  5. Pulsa D4 para pasar a Edit, cambia el numero con D2 y D3, y pulsa D4 otra vez para volver a navegar.
  6. Comprueba que una sola pulsacion no dispara varias lineas en el serie. Si lo hace, sube la ventana de filtro.
  7. Reinicia la placa y confirma que los valores vuelven al origen: este montaje aun no los guarda.

Variantes

Depuración

Software: digitalread debounce millis maquina-estados serial

Falcon · AP-FAL-12

Voltímetro con divisor resistivo

Objetivo

Al terminar, el monitor serie muestra la tension en el pin A0 y la tension exterior estimada con un divisor de dos resistencias iguales de 10 kΩ. Como las dos valen lo mismo, fuera hay el doble que en el pin. La entrada de la placa, que es el nudo del divisor, no debe pasar de 5 V: con este par, la tension que mides por fuera no debe pasar de 10 V. No hay pantalla; lees el resultado en el serie y compruebas con una pila o una fuente baja antes de fiarte del numero.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno. La referencia analogica es la de 5 V de la propia placa.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1Resistenciasmodulo-resistenciagenérico / cloneirrisorio (<1 €)10 kΩ. Rama alta del divisor, entre la tension a medir y A0. La entrada del pin no debe pasar de 5 V.
1Resistenciasmodulo-resistenciagenérico / cloneirrisorio (<1 €)10 kΩ. Rama baja del divisor, entre A0 y GND. La entrada del pin no debe pasar de 5 V.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza Tension exterior a medir Otro extremo de la resistencia alta de 10 kΩ Resistencia baja de 10 kΩ Masa de la fuente que mides Nudo A0 del divisor Extremo libre de la resistencia alta de 10 kΩ A0 A0 y GND GND Entrada analogica de la Uno

Código

// AP-FAL-12 Voltimetro con divisor resistivo
// Pines: A0 es el nudo entre dos resistencias de 10 kOhm.
// La entrada del pin no debe pasar de 5 V.
const int PIN_MEDIDA = A0;
const float VREF = 5.0;
const float R_ALTA = 10000.0; // 10 kOhm
const float R_BAJA = 10000.0; // 10 kOhm
const unsigned long PERIODO_MS = 400;

void setup() {
  Serial.begin(9600);
  Serial.println("Voltimetro listo. Entrada A0 maximo 5 V.");
}

void loop() {
  static unsigned long anterior = 0;
  unsigned long ahora = millis();
  if (ahora - anterior < PERIODO_MS) {
    return;
  }
  anterior = ahora;

  int adc = analogRead(PIN_MEDIDA);
  float vPin = adc * (VREF / 1023.0);
  float vExt = vPin * (R_ALTA + R_BAJA) / R_BAJA;

  Serial.print("ADC ");
  Serial.print(adc);
  Serial.print("  Vpin ");
  Serial.print(vPin, 2);
  Serial.print(" V  Vext ");
  Serial.print(vExt, 2);
  Serial.println(" V");

  if (vPin > 4.8) {
    Serial.println("Casi al tope: no subas mas la tension exterior.");
  }
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. No conectes todavia la tension que quieres medir.
  2. Pon la resistencia de 10 kΩ entre el punto exterior y A0, y la otra de 10 kΩ entre A0 y GND.
  3. Une la masa de la fuente que vas a medir con el GND de la placa. Sin esa masa comun la lectura no vale.
  4. Sube el sketch y abre el serie a 9600. Con la entrada a masa, Vpin tiene que quedar cerca de cero.
  5. Prueba primero con una pila de 1,5 V o de 9 V en el extremo exterior, nunca con la red, y compara Vext con un polimetro si lo tienes.
  6. Si Vpin se acerca a 5 V, para: la entrada no debe pasar de 5 V. Con 10 kΩ y 10 kΩ el exterior no debe pasar de 10 V.
  7. Gira o cambia la fuente solo dentro de ese limite y comprueba que Vext vale aproximadamente el doble de Vpin.

Variantes

Depuración

Software: analogread serial millis

Falcon · AP-FAL-13

Brillo proporcional a un sensor

Objetivo

Al terminar, el led cambia de brillo con PWM segun lo que ve el LDR: a mas luz en el divisor, mas cuentas en A0 y mas pulso alto en D9. No es un encendido seco, es un analogWrite proporcional, y el serie te ensena el valor leido y el duty para que ajustes la resistencia si el led se queda siempre apagado o siempre a tope. El montaje queda reaccionando solo, sin pulsador.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno. D9 tiene PWM.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa. D9 tambien tiene PWM.
1LDRsensor-ldrgenérico / cloneirrisorio (<1 €)Fotorresistencia entre 5 V y A0. Mas luz, menos resistencia, mas tension en el nudo.
1Resistenciasmodulo-resistenciagenérico / cloneirrisorio (<1 €)10 kΩ entre A0 y GND. Cierra el divisor con el LDR.
1LED 5 mmmodulo-ledgenérico / cloneirrisorio (<1 €)Brillo en D9 mediante PWM. El modulo ya trae su resistencia de limitacion.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza LDR extremo alto LDR extremo bajo Resistencia 10 kΩ LED senal LED GND LED VCC Nudo A0 5V A0 A0 y GND D9 GND Entrada de la placa

Código

// AP-FAL-13 Brillo proporcional a un sensor
// Pines: LDR en A0 con 10 kOhm a GND, LED PWM en D9
const int PIN_LDR = A0;
const int PIN_LED = 9;
const unsigned long PERIODO_MS = 50;

void setup() {
  Serial.begin(9600);
  pinMode(PIN_LED, OUTPUT);
  analogWrite(PIN_LED, 0);
  Serial.println("Brillo proporcional listo");
}

void loop() {
  static unsigned long anterior = 0;
  unsigned long ahora = millis();
  if (ahora - anterior < PERIODO_MS) {
    return;
  }
  anterior = ahora;

  int luz = analogRead(PIN_LDR);
  int brillo = map(luz, 0, 1023, 0, 255);
  brillo = constrain(brillo, 0, 255);
  analogWrite(PIN_LED, brillo);

  Serial.print("LDR ");
  Serial.print(luz);
  Serial.print("  PWM ");
  Serial.println(brillo);
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta el LDR entre 5 V y A0.
  2. Conecta la resistencia de 10 kΩ entre A0 y GND para cerrar el divisor.
  3. Conecta la senal del led a D9 y su masa a GND. D9 es un pin con PWM en la Uno.
  4. Sube el sketch y abre el serie a 9600. Tapa el LDR: el numero y el brillo deben bajar.
  5. Ilumina el LDR con una linterna del movil y comprueba que el PWM sube y el led se ve mas brillante, no solo encendido o apagado.
  6. Si el margen es pobre, acerca o aleja la luz hasta usar buena parte de la escala de 0 a 1023 antes de cambiar componentes.
  7. Deja el montaje un minuto y confirma que el brillo sigue a la luz sin que tengas que pulsar nada.

Variantes

Depuración

Software: analogread pwm analogwrite serial millis

Falcon · AP-FAL-14

Cafetera de juguete (máquina de estados)

Objetivo

Al terminar, la cafetera de juguete recorre reposo, calentando, lista y sirviendo con un enum y un switch. Cada fase enciende su led y pasa a la siguiente cuando vence su tiempo o cuando pulsas, contando con millis. No hay esperas bloqueantes largas: mientras calienta, el programa sigue dando vueltas y puede atender el pulsador al llegar a lista. Un pitido corto avisa al pasar a lista, tambien cortado por tiempo. Queda un ciclo que puedes repetir sin reiniciar la placa.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1Pulsadormodulo-pulsadorgenérico / cloneirrisorio (<1 €)Arranca el ciclo y, cuando esta lista, empieza a servir. Entre D2 y GND.
1LED 5 mmmodulo-ledgenérico / cloneirrisorio (<1 €)Led de calentando en D3.
1LED 5 mmmodulo-ledgenérico / cloneirrisorio (<1 €)Led de lista en D4.
1LED 5 mmmodulo-ledgenérico / cloneirrisorio (<1 €)Led de sirviendo en D5.
1Zumbador act/pasmodulo-zumbadorgenérico / cloneirrisorio (<1 €)Pitido corto al llegar a lista. Senal en D6.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza Pulsador Pulsador GND LED calentando LED lista LED sirviendo Zumbador senal Masas de leds y zumbador VCC de los modulos que lo traigan D2 GND D3 D4 D5 D6 5V

Código

// AP-FAL-14 Cafetera de juguete
// Pines: boton D2, calor D3, lista D4, servir D5, zumbador D6
// Maquina de estados con enum y switch. Sin esperas bloqueantes.
const int PIN_BOTON = 2;
const int PIN_CALOR = 3;
const int PIN_LISTA = 4;
const int PIN_SERVIR = 5;
const int PIN_ZUM = 6;

enum Estado { REPOSO, CALENTANDO, LISTA, SIRVIENDO };
Estado estado = REPOSO;

const unsigned long T_CALENTAR = 8000;
const unsigned long T_SERVIR = 4000;
const unsigned long T_PITIDO = 150;

unsigned long tFase = 0;
unsigned long finPitido = 0;
bool pitido = false;
bool botonAntes = HIGH;

void leds(bool calor, bool lista, bool servir) {
  digitalWrite(PIN_CALOR, calor ? HIGH : LOW);
  digitalWrite(PIN_LISTA, lista ? HIGH : LOW);
  digitalWrite(PIN_SERVIR, servir ? HIGH : LOW);
}

void entrar(Estado nuevo, unsigned long ahora) {
  estado = nuevo;
  tFase = ahora;
  if (nuevo == LISTA) {
    pitido = true;
    finPitido = ahora + T_PITIDO;
  }
  Serial.println(
    nuevo == REPOSO ? "REPOSO" :
    nuevo == CALENTANDO ? "CALENTANDO" :
    nuevo == LISTA ? "LISTA" : "SIRVIENDO");
}

bool pulsado() {
  bool ahoraBtn = digitalRead(PIN_BOTON);
  bool flanco = (botonAntes == HIGH && ahoraBtn == LOW);
  botonAntes = ahoraBtn;
  return flanco;
}

void setup() {
  Serial.begin(9600);
  pinMode(PIN_BOTON, INPUT_PULLUP);
  pinMode(PIN_CALOR, OUTPUT);
  pinMode(PIN_LISTA, OUTPUT);
  pinMode(PIN_SERVIR, OUTPUT);
  pinMode(PIN_ZUM, OUTPUT);
  digitalWrite(PIN_ZUM, LOW);
  leds(false, false, false);
  entrar(REPOSO, millis());
}

void loop() {
  unsigned long ahora = millis();
  if (pitido) {
    digitalWrite(PIN_ZUM, HIGH);
    if (ahora >= finPitido) {
      pitido = false;
      digitalWrite(PIN_ZUM, LOW);
    }
  }

  bool clic = pulsado();
  switch (estado) {
    case REPOSO:
      leds(false, false, false);
      if (clic) {
        entrar(CALENTANDO, ahora);
      }
      break;
    case CALENTANDO:
      leds(true, false, false);
      if (ahora - tFase >= T_CALENTAR) {
        entrar(LISTA, ahora);
      }
      break;
    case LISTA:
      leds(false, true, false);
      if (clic) {
        entrar(SIRVIENDO, ahora);
      }
      break;
    case SIRVIENDO:
      leds(false, false, true);
      if (ahora - tFase >= T_SERVIR) {
        entrar(REPOSO, ahora);
      }
      break;
    default:
      entrar(REPOSO, ahora);
      break;
  }
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta el pulsador entre D2 y GND.
  2. Conecta el led de calor a D3, el de lista a D4, el de servicio a D5 y el zumbador a D6, con las masas a GND.
  3. Sube el sketch y abre el serie a 9600. Debe quedar en REPOSO con los tres leds apagados.
  4. Pulsa una vez. Tiene que pasar a CALENTANDO y encender solo el led de D3 durante unos ocho segundos, mientras el serie sigue vivo.
  5. Al cumplir el tiempo suena un pitido corto y queda LISTA. Pulsa otra vez para SIRVIENDO y espera a que vuelva solo a REPOSO.
  6. Durante CALENTANDO no hace falta pulsar: la transicion la hace el tiempo. Comprueba que la placa no se queda congelada.
  7. Recorre el ciclo dos veces seguidas para ver que el enum vuelve a REPOSO sin reiniciar.

Variantes

Depuración

Software: maquina-estados millis digitalread digitalwrite serial

Falcon · AP-FAL-15

Dos placas por SoftwareSerial

Objetivo

Al terminar, dos placas se hablan por SoftwareSerial sin tocar los pines 0 y 1, que siguen libres para el monitor serie de cada una. La placa A envia una frase cada dos segundos por su TX en D11 y la placa B la recibe en su RX en D10, la copia al serie y conmuta un led. El cable va cruzado, TX con RX, y las masas van unidas. En el codigo los dos sketches van separados por un comentario claro: grabas cada bloque en su placa, no los dos a la vez en la misma.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
2Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Hacen falta dos placas Uno R3, una emisora y una receptora. Cada una con su cable USB.
2Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa: dos clones CH340 en lugar del par R3. No sumes los dos pares; monta dos placas iguales en total.
1LED 5 mmmodulo-ledgenérico / cloneirrisorio (<1 €)Va en la placa B, patilla D4. Parpadea al recibir bytes.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza Placa A TX D11 Placa B TX D11 GND de la placa A LED senal en la placa B LED GND Enlace serie entre placas Placa B RX D10 Placa A RX D10 GND de la placa B D4 de la placa B Pines D10 y D11, nunca D0 ni D1

Código

// AP-FAL-15 Dos placas por SoftwareSerial
// Cada bloque se graba en una placa distinta.
// RX en D10, TX en D11. No usa los pines 0 ni 1.

/* ============================================================
   SKETCH PLACA A (emisora)
   Graba este programa solo en la primera placa.
   ============================================================ */
#include <SoftwareSerial.h>

SoftwareSerial enlace(10, 11); // RX, TX

void setup() {
  Serial.begin(9600);
  enlace.begin(9600);
  Serial.println("Placa A lista");
}

void loop() {
  static unsigned long anterior = 0;
  unsigned long ahora = millis();
  if (ahora - anterior >= 2000) {
    anterior = ahora;
    enlace.println("hola desde A");
    Serial.println("Enviado");
  }
  while (enlace.available()) {
    Serial.write(enlace.read());
  }
}

/* ============================================================
   SKETCH PLACA B (receptora)
   Graba este programa solo en la segunda placa.
   ============================================================ */
#include <SoftwareSerial.h>

SoftwareSerial enlace(10, 11); // RX, TX
const int PIN_LED = 4;

void setup() {
  Serial.begin(9600);
  enlace.begin(9600);
  pinMode(PIN_LED, OUTPUT);
  Serial.println("Placa B lista");
}

void loop() {
  while (enlace.available()) {
    char c = enlace.read();
    Serial.write(c);
    digitalWrite(PIN_LED, !digitalRead(PIN_LED));
  }
}

Pasos

  1. Prepara dos placas del mismo tipo: dos Uno R3 o, en su lugar, dos Uno CH340. No mezcles el recuento.
  2. Une GND con GND. Cruza A D11 con B D10 y B D11 con A D10. No uses D0 ni D1 para ese enlace.
  3. Pon el led en D4 de la placa B, con su masa al GND de esa misma placa.
  4. Copia solo el bloque de la placa A, compilalo y subelo a la primera placa con el IDE en Arduino Uno.
  5. Copia solo el bloque de la placa B en un sketch nuevo, subelo a la segunda placa y abre su monitor serie a 9600.
  6. Alimenta las dos a la vez. En A debes ver Enviado cada dos segundos y en B la frase hola desde A, con el led cambiando.
  7. Si B no recibe, invierte el cruce una sola vez y vuelve a probar antes de tocar el codigo.

Variantes

Depuración

Software: softwareserial serial digitalwrite digitalread millis

Falcon · AP-FAL-16

Escáner I2C

Objetivo

Al terminar, la placa recorre las direcciones I2C de la 1 a la 126 y escribe en el monitor serie las que responden. Con el DS3231 conectado tienes que ver 0x68, que es su direccion fija, y asi compruebas SDA, SCL y la masa antes de intentar leer la hora. El barrido se repite cada pocos segundos usando millis, de modo que puedes enchufar o quitar el modulo y ver como aparece o desaparece sin volver a subir el sketch.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En la Uno, SDA es A4 y SCL es A5.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1RTC DS3231modulo-ds3231genérico / clonepoco (≈1–3 €)Dispositivo I2C de prueba. Debe aparecer en la direccion 0x68.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza DS3231 SDA DS3231 SCL DS3231 VCC DS3231 GND Bus I2C A4 A5 5V GND A4 y A5 unicamente

Código

// AP-FAL-16 Escaner I2C
// Pines: SDA A4, SCL A5. El DS3231 responde en 0x68.
#include <Wire.h>

const unsigned long PERIODO_MS = 3000;

void setup() {
  Wire.begin();
  Serial.begin(9600);
  Serial.println("Escaner I2C en A4 y A5");
}

void loop() {
  static unsigned long anterior = 0;
  unsigned long ahora = millis();
  if (anterior != 0 && ahora - anterior < PERIODO_MS) {
    return;
  }
  anterior = ahora;

  byte encontrados = 0;
  Serial.println("Buscando...");
  for (byte addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    byte err = Wire.endTransmission();
    if (err == 0) {
      Serial.print("Encontrado en 0x");
      if (addr < 16) {
        Serial.print('0');
      }
      Serial.println(addr, HEX);
      encontrados++;
    }
  }
  if (encontrados == 0) {
    Serial.println("Ningun dispositivo. Revisa A4, A5, 5 V y GND.");
  } else {
    Serial.print("Total ");
    Serial.println(encontrados);
  }
  Serial.println("---");
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta SDA del DS3231 a A4, SCL a A5, VCC a 5 V y GND a masa.
  2. Sube el sketch. Wire forma parte del nucleo, no instales otra libreria para este escaner.
  3. Abre el monitor serie a 9600 y espera el primer barrido.
  4. Confirma que aparece 0x68. Esa es la direccion del DS3231.
  5. Desconecta solo SDA, espera el siguiente barrido y comprueba que 0x68 desaparece. Vuelve a conectarlo.
  6. Si tienes otro modulo I2C a 5 V, ponlo en paralelo en A4, A5, 5 V y GND y mira si sale una segunda direccion.
  7. Anota las direcciones que veas: te serviran antes de escribir un programa que hable con ese chip.

Variantes

Depuración

Software: i2c serial millis

Falcon · AP-FAL-17

Guardar el último ajuste en EEPROM

Objetivo

Al terminar, el brillo que dejas en el potenciometro se puede guardar en la EEPROM de la propia placa al pulsar el boton, y al reiniciar o al quitar el USB el led vuelve a ese ultimo ajuste sin que tengas que girar nada. El sketch usa EEPROM.h del nucleo y EEPROM.update para no gastar la celda si el valor no ha cambiado. El serie confirma lo recuperado al arrancar y lo guardado en cada pulsacion. El potencio sigue pudiendo previsualizar otro brillo antes de decidirte a grabarlo.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. La EEPROM es la interna del ATmega328P, no un chip aparte.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout y la misma EEPROM interna. Usa una sola placa.
1Potenciómetromodulo-potenciometrogenérico / cloneirrisorio (<1 €)Ajuste en vivo. Cursor a A0, extremos a 5 V y GND.
1Pulsadormodulo-pulsadorgenérico / cloneirrisorio (<1 €)Guarda el valor actual. Entre D2 y GND.
1LED 5 mmmodulo-ledgenérico / cloneirrisorio (<1 €)Muestra el brillo por PWM en D9.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza Potenciometro cursor Potenciometro extremo alto Potenciometro extremo bajo Pulsador Pulsador GND LED senal LED GND Celda de memoria A0 5V GND D2 D9 EEPROM interna, direccion 0

Código

// AP-FAL-17 Guardar el ultimo ajuste en EEPROM
// Pines: potenciometro A0, pulsador D2, LED PWM D9
// Libreria EEPROM.h del nucleo. Direccion 0.
#include <EEPROM.h>

const int PIN_POT = A0;
const int PIN_BOTON = 2;
const int PIN_LED = 9;
const int DIR = 0;
const unsigned long VENTANA_MS = 40;

byte brilloGuardado = 0;
bool seguirPot = false;
int potAlArrancar = 0;
bool estable = HIGH;
bool previo = HIGH;
unsigned long cambioBtn = 0;

void aplicar(byte brillo) {
  analogWrite(PIN_LED, brillo);
}

bool flancoGuardar() {
  bool lectura = digitalRead(PIN_BOTON);
  unsigned long ahora = millis();
  if (lectura != estable) {
    if (ahora - cambioBtn >= VENTANA_MS) {
      estable = lectura;
    }
  } else {
    cambioBtn = ahora;
  }
  bool pulso = (previo == HIGH && estable == LOW);
  previo = estable;
  return pulso;
}

void setup() {
  Serial.begin(9600);
  pinMode(PIN_BOTON, INPUT_PULLUP);
  pinMode(PIN_LED, OUTPUT);
  brilloGuardado = EEPROM.read(DIR);
  aplicar(brilloGuardado);
  potAlArrancar = analogRead(PIN_POT);
  Serial.print("Recuperado de EEPROM ");
  Serial.println(brilloGuardado);
}

void loop() {
  int lectura = analogRead(PIN_POT);
  byte propuesto = lectura / 4;
  if (abs(lectura - potAlArrancar) > 12) {
    seguirPot = true;
  }
  if (seguirPot) {
    aplicar(propuesto);
  } else {
    aplicar(brilloGuardado);
  }

  if (flancoGuardar()) {
    EEPROM.update(DIR, propuesto);
    brilloGuardado = propuesto;
    seguirPot = false;
    potAlArrancar = lectura;
    aplicar(brilloGuardado);
    Serial.print("Guardado en EEPROM ");
    Serial.println(propuesto);
  }
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta el cursor del potenciometro a A0 y los extremos a 5 V y GND.
  2. Conecta el pulsador entre D2 y GND, y el led de brillo a D9 con su masa a GND.
  3. Sube el sketch. EEPROM.h viene en el nucleo. Abre el serie a 9600 y anota el byte recuperado, que la primera vez sera basura o 255.
  4. Gira el potenciometro hasta un brillo medio y pulsa una sola vez. El serie debe decir que lo ha guardado.
  5. Cambia el potenciometro de sitio, desconecta el USB, vuelve a alimentar y comprueba que el led arranca en el brillo guardado antes de que muevas el mando.
  6. Gira de nuevo sin pulsar y confirma que la vista previa cambia, pero un reset sin pulsar recupera otra vez el ultimo ajuste.
  7. Pulsa varias veces sin mover el mando: update no debe reescribir si el byte ya es el mismo, aunque el serie confirme la accion.

Variantes

Depuración

Software: eeprom analogread analogwrite pwm digitalread millis serial

Falcon · AP-FAL-18

Contar pulsos con interrupción

Objetivo

Al terminar, cada flanco de bajada en el pin 2 suma un pulso dentro de una interrupcion, aunque el loop este ocupado imprimiendo por el serie. El contador es volatile y solo se copia con las interrupciones paradas un instante, para no leer un numero a medias. El monitor serie enseña el total varias veces por segundo. Puedes pulsar a mano y ver que la cuenta sube sin preguntar en cada vuelta del loop si el pin ha cambiado. El pin de la interrupcion es el 2, que en la Uno esta preparado para ello.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. La interrupcion externa INT0 esta en el pin 2.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. La interrupcion sigue en el pin 2. Usa una sola placa.
1Pulsadormodulo-pulsadorgenérico / cloneirrisorio (<1 €)Genera el pulso. Entre el pin 2 y GND. El rebote mecanico puede contar varios pulsos por pulsacion.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza Pulsador Pulsador GND Pin de interrupcion D2 GND Solo el pin 2

Código

// AP-FAL-18 Contar pulsos con interrupcion
// Pin 2 = INT0. Flanco de bajada. El contador es volatile.
const byte PIN_PULSO = 2;

volatile unsigned long pulsos = 0;

void contarPulso() {
  pulsos++;
}

void setup() {
  Serial.begin(9600);
  pinMode(PIN_PULSO, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(PIN_PULSO), contarPulso, FALLING);
  Serial.println("Contador listo en el pin 2");
}

void loop() {
  static unsigned long anterior = 0;
  unsigned long ahora = millis();
  if (ahora - anterior < 300) {
    return;
  }
  anterior = ahora;

  noInterrupts();
  unsigned long copia = pulsos;
  interrupts();

  Serial.print("Pulsos ");
  Serial.println(copia);
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta el pulsador entre el pin 2 y GND. No uses otro pin.
  2. Sube el sketch y abre el serie a 9600. Tiene que imprimir Pulsos 0 de forma periodica.
  3. Pulsa varias veces. La cuenta debe subir. Un pulsador mecanico a menudo suma mas de uno por golpe: es el rebote, no un fallo del pin.
  4. Mantente sin pulsar y comprueba que el numero se queda quieto entre lineas del serie.
  5. Reinicia la placa y confirma que la cuenta vuelve a cero: esta variable no vive en EEPROM.
  6. No llames a Serial dentro de contarPulso. La interrupcion solo incrementa.

Variantes

Depuración

Software: interrupciones serial millis

Falcon · AP-FAL-19

Antirrebote en una función reutilizable

Objetivo

Al terminar, el pulsador pasa por una funcion reutilizable que solo devuelve un flanco cuando el nivel lleva quieto el tiempo de filtro. El led de D8 conmuta una vez por pulsacion valida, y el serie cuenta esos flancos, no los rebotes. La funcion no guarda un unico boton escondido: recibe una estructura con el pin y su estado, asi que puedes declararla otra vez para un segundo pulsador sin copiar el filtro. El programa sigue libre gracias a millis.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
1Pulsadormodulo-pulsadorgenérico / cloneirrisorio (<1 €)Entrada ruidosa de prueba. Entre D2 y GND.
1LED 5 mmmodulo-ledgenérico / cloneirrisorio (<1 €)Cambia de estado una sola vez por flanco ya filtrado. Senal en D8.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza Pulsador Pulsador GND LED senal LED GND LED VCC D2 GND D8 5V

Código

// AP-FAL-19 Antirrebote en una funcion reutilizable
// Pines: pulsador D2, led D8
// flancoPulsado() sirve para cualquier Entrada que le pases.
const int PIN_LED = 8;
const unsigned long VENTANA_MS = 35;

struct Entrada {
  byte pin;
  byte nivelEstable;
  byte nivelPrevio;
  unsigned long instanteCambio;
};

void iniciarEntrada(Entrada &e, byte pin) {
  e.pin = pin;
  pinMode(e.pin, INPUT_PULLUP);
  e.nivelEstable = digitalRead(e.pin);
  e.nivelPrevio = e.nivelEstable;
  e.instanteCambio = millis();
}

// true solo una vez, cuando el pulsador a masa ya esta estable.
bool flancoPulsado(Entrada &e, unsigned long ventanaMs) {
  byte lectura = digitalRead(e.pin);
  unsigned long ahora = millis();
  if (lectura != e.nivelEstable) {
    if (ahora - e.instanteCambio >= ventanaMs) {
      e.nivelEstable = lectura;
    }
  } else {
    e.instanteCambio = ahora;
  }
  bool flanco = (e.nivelPrevio == HIGH && e.nivelEstable == LOW);
  e.nivelPrevio = e.nivelEstable;
  return flanco;
}

Entrada boton;
bool ledOn = false;
unsigned long aceptados = 0;

void setup() {
  Serial.begin(9600);
  pinMode(PIN_LED, OUTPUT);
  digitalWrite(PIN_LED, LOW);
  iniciarEntrada(boton, 2); // D2
  Serial.println("Antirrebote listo");
}

void loop() {
  if (flancoPulsado(boton, VENTANA_MS)) {
    ledOn = !ledOn;
    digitalWrite(PIN_LED, ledOn ? HIGH : LOW);
    aceptados++;
    Serial.print("Flanco valido ");
    Serial.println(aceptados);
  }
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta el pulsador entre D2 y GND.
  2. Conecta el led a D8 y su masa a GND.
  3. Sube el sketch y abre el serie a 9600.
  4. Pulsa y suelta varias veces, despacio. Cada pulsacion debe sumar un solo flanco y conmutar el led una vez.
  5. Prueba pulsaciones rapidas pero limpias y comprueba que no aparecen rafagas de lineas por un solo golpe.
  6. Lee flancoPulsado e iniciarEntrada y fijate en que el estado viaja en la estructura, no en variables sueltas de un unico pin.

Variantes

Depuración

Software: debounce digitalread digitalwrite millis serial

Falcon · AP-FAL-20

Cuatro relés con nombre en LCD

Objetivo

Al terminar, cuatro reles se gobiernan con cuatro pulsadores y el LCD va mostrando el nombre de cada uno y si esta en ON o en OFF. Los nombres son luz, bomba, ventilador y cerradura, las cuatro de juguete. Cada rele solo puede conmutar una carga de 5 a 12 V en corriente continua, con su propia fuente. No se conmuta la red. El filtrado evita que un rebote cambie dos veces el mismo canal, y el serie repite el nombre y el estado cada vez que conmutas.

Materiales

Cant.PiezaFichaOrigenPrecio relativoEn este montaje
1Arduino Uno R3placa-uno-r3original / oficialconsultar (>10 €)Placa principal. En el IDE elige Arduino Uno.
1Uno R3 clone CH340placa-uno-ch340genérico / clonepoco (≈1–3 €)Alternativa con el mismo pinout. Usa una sola placa.
4Relé 5 Vmodulo-relegenérico / clonepoco (≈1–3 €)Cuatro canales: D2 luz, D3 bomba, D4 ventilador y D5 cerradura. Carga de 5 a 12 V cada uno. No se conmuta la red.
4Pulsadormodulo-pulsadorgenérico / cloneirrisorio (<1 €)Uno por rele, en A0, A1, A2 y A3, cada contacto hacia GND.
1LCD 1602 I2Cmodulo-lcd-1602genérico / clonepoco (≈1–3 €)Muestra el nombre del rele y ON u OFF. Paralelo de 4 bits.

La franja sale del catálogo de Hardware. No es un precio de tienda.

Cableado

Placa Pieza Rele luz IN Rele bomba IN Rele ventilador IN Rele cerradura IN Pulsador luz Pulsador bomba Pulsador ventilador Pulsador cerradura Pulsadores GND Rele VCC de los cuatro modulos Rele GND de los cuatro modulos LCD RS LCD E LCD D4 LCD D5 LCD D6 LCD D7 LCD RW LCD VCC LCD GND Contactos COM y NO de cada rele D2 D3 D4 D5 A0 A1 A2 A3 GND 5V D12 D11 D10 D9 D8 D7 Carga de 5 a 12 V de ese canal

Código

// AP-FAL-20 Cuatro reles con nombre en LCD
// Pines: reles D2 D3 D4 D5, pulsadores A0 A1 A2 A3
// LCD RS D12, E D11, D4 D10, D5 D9, D6 D8, D7 D7
// Carga de 5 a 12 V. No se conmuta la red.
#include <LiquidCrystal.h>

const byte PIN_RELE[4] = {2, 3, 4, 5};
const byte PIN_BTN[4] = {A0, A1, A2, A3};
const char *NOMBRE[4] = {"Luz 12V", "Bomba", "Ventilador", "Cerradura"};
const byte RELE_ON = LOW;
const byte RELE_OFF = HIGH;
const unsigned long VENTANA_MS = 40;

bool activo[4] = {false, false, false, false};
byte estable[4] = {HIGH, HIGH, HIGH, HIGH};
byte previo[4] = {HIGH, HIGH, HIGH, HIGH};
unsigned long cambio[4] = {0, 0, 0, 0};

LiquidCrystal lcd(12, 11, 10, 9, 8, 7);

void aplicar(byte i) {
  digitalWrite(PIN_RELE[i], activo[i] ? RELE_ON : RELE_OFF);
}

bool flanco(byte i) {
  byte lectura = digitalRead(PIN_BTN[i]);
  unsigned long ahora = millis();
  if (lectura != estable[i]) {
    if (ahora - cambio[i] >= VENTANA_MS) {
      estable[i] = lectura;
    }
  } else {
    cambio[i] = ahora;
  }
  bool pulso = (previo[i] == HIGH && estable[i] == LOW);
  previo[i] = estable[i];
  return pulso;
}

void escribirLinea(byte fila, const char *txt) {
  lcd.setCursor(0, fila);
  byte n = 0;
  while (txt[n] != 0 && n < 16) {
    lcd.print(txt[n]);
    n++;
  }
  while (n < 16) {
    lcd.print(' ');
    n++;
  }
}

void pintar(unsigned long ahora) {
  static byte cual = 0;
  static unsigned long anterior = 0;
  if (ahora - anterior >= 1500) {
    anterior = ahora;
    cual = (cual + 1) % 4;
  }
  escribirLinea(0, NOMBRE[cual]);
  escribirLinea(1, activo[cual] ? "ON  5-12 V" : "OFF 5-12 V");
}

void setup() {
  Serial.begin(9600);
  lcd.begin(16, 2);
  for (byte i = 0; i < 4; i++) {
    pinMode(PIN_RELE[i], OUTPUT);
    pinMode(PIN_BTN[i], INPUT_PULLUP);
    aplicar(i);
  }
  Serial.println("Cuatro reles. No se conmuta la red.");
  pintar(millis());
}

void loop() {
  unsigned long ahora = millis();
  for (byte i = 0; i < 4; i++) {
    if (flanco(i)) {
      activo[i] = !activo[i];
      aplicar(i);
      Serial.print(NOMBRE[i]);
      Serial.println(activo[i] ? " ON" : " OFF");
    }
  }
  pintar(ahora);
}

Pasos

  1. Monta una sola placa y selecciona Arduino Uno. Conecta los IN de los cuatro reles a D2, D3, D4 y D5, con VCC de bobina a 5 V y GND comun.
  2. Conecta los pulsadores a A0, A1, A2 y A3, cada uno con el otro extremo a GND.
  3. Conecta el LCD: RS D12, E D11, D4 D10, D5 D9, D6 D8, D7 D7 y RW a GND.
  4. Sube el sketch sin cargas en los contactos. Abre el serie a 9600 y pulsa cada boton: el nombre correcto tiene que cambiar de OFF a ON y oirse el clic.
  5. Mira el LCD: cada segundo y medio rota el nombre y el estado, siempre con el aviso 5-12 V.
  6. Solo entonces conecta en cada COM y NO una carga de 5 a 12 V con su fuente. No se conmuta la red.
  7. Recorre los cuatro nombres y comprueba que apagar en el pulsador devuelve ese rele a reposo sin tocar los otros tres.

Variantes

Depuración

Software: digitalwrite digitalread debounce millis serial