¡Ha llegado la hora, equipo! La misión final del curso. Este no es solo un proyecto, es la síntesis de todas sus habilidades. Van a construir un dispositivo de instrumentación completo, multifuncional e interactivo que integra medición ambiental, detección de proximidad, registro de datos y una interfaz gráfica avanzada. Hoy se convierten en diseñadores de sistemas embebidos.
🎯 El Reto
Construir una estación de monitoreo "todo en uno" que:
- Mida la temperatura (
DS18B20) y la distancia (HC-SR04). - Permita navegar con un Joystick entre cuatro pantallas en una pantalla OLED:
- Pantalla Principal: Temperatura y aguja de servo.
- Pantalla de Registro de Datos: Máximos y Mínimos.
- Pantalla de Radar Gráfico: Con barrido y blips.
- Pantalla de Radar Numérico: Con barra de proximidad.
- Active una alerta sonora con un Buzzer si la temperatura es muy alta o la distancia es muy corta.
- Permita resetear los datos máximos y mínimos con el botón del joystick.
🔌 El Circuito: La Fusión Final de Sistemas
Componentes Necesarios:
- Placa Arduino UNO, Protoboard y cables.
- 1 Sensor de temperatura
DS18B20con su resistencia de4.7kΩ. - 1 Sensor ultrasónico
HC-SR04. - 1 Pantalla
OLED I2C. - 1 Módulo
Joystick. - 1 Micro Servomotor
SG90. - 1 Buzzer Pasivo.
📝 Instrucciones de Conexión:
- Pantalla OLED (I2C):
SDAa A4,SCLa A5. - Sensor DS18B20 (One-Wire):
DATAal Pin 2 (con resistencia pull-up de 4.7kΩ a 5V). - Sensor Ultrasónico:
Trigal Pin 9,Echoal Pin 10. - Joystick:
VRyal Pin A0,SW(botón) al Pin 3. - Servomotor: Cable de señal al Pin 6.
- Buzzer: Pata positiva (+) al Pin 4, pata negativa (-) a GND.
- Alimentación: Conecta todos los
VCCa 5V y todos losGNDa GND.
⚡ Diagrama de armado
🧠 El Código: El Sistema Operativo Final
Este es el código más completo del curso. Gestiona 4 pantallas, múltiples sensores, actuadores y entradas de usuario simultáneamente.
/*
* PROYECTO INTEGRADOR 3 (Definitivo): Estación Ambiental y Radar Gráfico
* Descripción: Mide temp/distancia, muestra en 4 pantallas OLED navegables,
* registra datos, controla servo y tiene alertas sonoras.
* Por: Profe Campos
* CECyTEM 05 Guacamayas
*/
// --- INCLUSIÓN DE LIBRERÍAS (NUESTRAS "CAJAS DE HERRAMIENTAS") ---
#include <Wire.h> // Necesaria para la comunicación I2C.
#include <Adafruit_GFX.h> // Librería gráfica base de Adafruit.
#include <Adafruit_SSD1306.h> // Librería para controlar nuestra pantalla OLED.
#include <OneWire.h> // Protocolo de comunicación One-Wire.
#include <DallasTemperature.h> // Lectura del sensor DS18B20.
#include <Servo.h> // Control del servomotor.
// --- OBJETOS Y PINES (DEFINIENDO NUESTRO HARDWARE) ---
Adafruit_SSD1306 display(128, 64, &Wire, -1);
OneWire oneWire(2);
DallasTemperature sensors(&oneWire);
Servo miServo;
const int pinTrig = 9;
const int pinEcho = 10;
const int pinJoyY = A0;
const int pinJoySW = 3;
const int pinServo = 6;
const int pinBuzzer = 4;
// --- VARIABLES GLOBALES (LA MEMORIA DE NUESTRO PROGRAMA) ---
int pantallaActual = 0; // 0=Principal, 1=DataLog, 2=Radar Gráfico, 3=Radar Numérico
float distanciaCm = 0;
float tempC = 0;
long duracion;
// Variables para el registro de datos (Data Logging).
float tempMax = -100;
float tempMin = 200;
float distMax = 0;
float distMin = 500;
//=============================================================================
// FUNCIÓN SETUP
//=============================================================================
void setup() {
Serial.begin(9600);
sensors.begin();
miServo.attach(pinServo);
pinMode(pinTrig, OUTPUT);
pinMode(pinEcho, INPUT);
pinMode(pinBuzzer, OUTPUT);
pinMode(pinJoySW, INPUT_PULLUP);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("Fallo al iniciar SSD1306"));
for(;;);
}
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(10, 10);
display.println("SISTEMA");
display.setCursor(10, 35);
display.println("INICIADO");
display.display();
delay(2000);
}
//=============================================================================
// FUNCIÓN LOOP
//=============================================================================
void loop() {
// --- NAVEGACIÓN Y ACCIONES DEL JOYSTICK ---
int valorJoy = analogRead(pinJoyY);
if (valorJoy < 100) {
pantallaActual++;
if (pantallaActual > 3) pantallaActual = 0;
delay(200);
}
if (valorJoy > 900) {
pantallaActual--;
if (pantallaActual < 0) pantallaActual = 3;
delay(200);
}
if (pantallaActual == 1 && digitalRead(pinJoySW) == LOW) {
resetDataLog();
}
// --- LECTURA DE SENSORES ---
leerSensores();
// --- ACTUALIZACIÓN DE DATOS MÁXIMOS Y MÍNIMOS ---
actualizarDataLog();
// --- COMPROBACIÓN DE ALERTAS ---
comprobarAlertas();
// --- ACTUALIZAR PANTALLA ---
display.clearDisplay();
if (pantallaActual == 0) dibujarPantallaPrincipal();
else if (pantallaActual == 1) dibujarPantallaDataLog();
else if (pantallaActual == 2) dibujarPantallaRadarGrafico();
else if (pantallaActual == 3) dibujarPantallaRadarNumerico();
display.display();
delay(100);
}
//=============================================================================
// --- FUNCIONES AUXILIARES ---
//=============================================================================
void leerSensores() {
sensors.requestTemperatures();
tempC = sensors.getTempCByIndex(0);
digitalWrite(pinTrig, LOW);
delayMicroseconds(2);
digitalWrite(pinTrig, HIGH);
delayMicroseconds(10);
digitalWrite(pinTrig, LOW);
duracion = pulseIn(pinEcho, HIGH);
distanciaCm = duracion * 0.0343 / 2.0;
distanciaCm = constrain(distanciaCm, 0, 200);
}
void actualizarDataLog() {
if (tempC > tempMax) tempMax = tempC;
if (tempC < tempMin) tempMin = tempC;
if (distanciaCm > distMax) distMax = distanciaCm;
if (distanciaCm < distMin && distanciaCm > 0) distMin = distanciaCm;
}
void resetDataLog() {
tempMax = tempC;
tempMin = tempC;
distMax = distanciaCm;
distMin = distanciaCm;
tone(pinBuzzer, 1500, 100);
display.clearDisplay();
display.setTextSize(2);
display.setCursor(15,25);
display.print("DATOS");
display.setCursor(5,45);
display.print("REINICIADOS");
display.display();
delay(1000);
}
void comprobarAlertas() {
if (tempC > 40.0 || (distanciaCm < 10 && distanciaCm > 0)) {
display.fillTriangle(0,0, 10,0, 0,10, SSD1306_WHITE);
tone(pinBuzzer, 2000, 150);
}
}
// --- FUNCIONES DE DIBUJO DE PANTALLAS ---
void dibujarPantallaPrincipal() {
display.setTextSize(1);
display.setCursor(0, 0);
display.print("--- MONitoreo AMBIENTAL ---");
display.setTextSize(2);
display.setCursor(5, 20);
display.print(tempC, 1);
display.print(" ");
display.setTextSize(1);
display.drawCircle(75, 22, 3, SSD1306_WHITE);
display.setTextSize(2);
display.print("C");
int anguloTemp = map(tempC, 0, 50, 0, 180);
miServo.write(anguloTemp);
display.setTextSize(1);
display.setCursor(0, 55);
display.print("Mover Joystick->");
}
void dibujarPantallaDataLog() {
display.setTextSize(1);
display.setCursor(0, 0);
display.print("--- REGISTRO DE DATOS ---");
display.setCursor(0, 15);
display.print("T.Max: "); display.print(tempMax, 1); display.print("C");
display.setCursor(0, 28);
display.print("T.Min: "); display.print(tempMin, 1); display.print("C");
display.setCursor(0, 41);
display.print("D.Max: "); display.print(distMax, 0); display.print("cm");
display.setCursor(0, 54);
display.print("D.Min: "); display.print(distMin, 0); display.print("cm");
}
void dibujarPantallaRadarGrafico() {
display.setTextSize(1);
display.setCursor(0, 0);
display.print("--- RADAR GRAFICO ---");
static int anguloScan = 0;
static int direccion = 1;
anguloScan += direccion;
if (anguloScan >= 180 || anguloScan <= 0) {
direccion *= -1;
}
miServo.write(anguloScan);
display.drawArc(64, 63, 60, 60, 0, 180, SSD1306_WHITE);
float anguloRad = anguloScan * PI / 180.0;
int x2 = 64 - cos(anguloRad) * 60;
int y2 = 63 - sin(anguloRad) * 60;
display.drawLine(64, 63, x2, y2, SSD1306_WHITE);
if (distanciaCm < 60) {
float anguloBlip = miServo.read() * PI / 180.0;
int xBlip = 64 - cos(anguloBlip) * distanciaCm;
int yBlip = 63 - sin(anguloBlip) * distanciaCm;
display.fillCircle(xBlip, yBlip, 3, SSD1306_WHITE);
}
}
void dibujarPantallaRadarNumerico() {
display.setTextSize(1);
display.setCursor(0, 0);
display.print("--- RADAR DE PROXIMIDAD ---");
display.setTextSize(3);
display.setCursor(5, 25);
display.print(distanciaCm, 0);
display.setTextSize(2);
display.print("cm");
int barra = map(distanciaCm, 100, 5, 0, 128);
barra = constrain(barra, 0, 128);
display.fillRect(0, 58, barra, 6, SSD1306_WHITE);
int anguloDist = map(distanciaCm, 5, 100, 180, 0);
miServo.write(anguloDist);
}
🏆 ¡MISIÓN CUMPLIDA, INGENIEROS!
¡Lo han logrado! Han recorrido el camino completo desde encender un LED hasta construir un dispositivo de medición multifuncional con una interfaz gráfica. Han demostrado un dominio de sensores digitales, analógicos, protocolos de comunicación I2C y One-Wire, y han creado un sistema robusto y complejo.
Este proyecto no es solo la culminación de un curso, es el primer paso en su carrera como creadores de tecnología. El conocimiento que tienen ahora es la base para la robótica, la domótica, el Internet de las Cosas y la instrumentación industrial.
El futuro es suyo para programarlo. ¡Felicidades! - Profe Campos