InicioTarjetas de DesarrolloAlcoholímetro usando el RP2040 de la UNIT DUAL MCU

Alcoholímetro usando el RP2040 de la UNIT DUAL MCU

A continuación se muestra un alcoholímetro usando una tira NeoPixel a modo de columna luminosa, la cual mediante diferentes colores y número de píxeles indicara la concentración de alcohol detectado por el sensor MQ-3, todo usando el RP2040 integrado en la tarjeta UNIT DUAL MCU que por su parte se energiza usando una batería LiPo de 3.7 V.

Introducción

En este proyecto te mostraremos cómo construir un alcoholímetro visual utilizando una tira de LEDs NeoPixel y un sensor de gas MQ-3, todo controlado por la versátil tarjeta UNIT DUAL MCU basada en el microcontrolador RP2040.

A través de este sistema, es posible visualizar en tiempo real la concentración de alcohol en el ambiente mediante una columna de luz que cambia de color e intensidad según el nivel detectado. Además, se incorpora un buzzer como sistema de alerta en caso de detectar niveles elevados, y se propone el uso de una batería LiPo para dotar al dispositivo de portabilidad. Este proyecto resulta ideal para quienes desean iniciarse en el desarrollo de dispositivos interactivos con sensores, aprendizaje de microcontroladores y control de LEDs RGB.

Materiales

Diagrama de conexión

Para prototipar el alcoholímetro usando el RP2040 de la UNIT DUAL MCU se usará el siguiente diagrama donde el sensor MQ-3 y la tira NeoPixel están alimentados a 3.3 V que provienen directamente de la tarjeta de desarrollo UNIT DUAL MCU. Dichos componentes tiene un consumo aproximado de 110 mA, donde 90 mA son consumidos por el sensor de alcohol, ya que este internamente contiene un elemento calefactor que requiere de esa corriente para operar correctamente, por lo que te recomendamos revisar los datos de corriente máxima que pueden entregar otras placas en caso de que desees realizar este proyecto en otras plataformas de desarrollo, pero por lo pronto la UNIT DUAL MCU puede operar cómodamente con este consumo 😉

En el diagrama se propone el uso de una batería Li Po para añadir portabilidad al proyecto, la cual se conecta fácilmente con el conector JST integrado en la placa 😉

Esquemático

En la imagen que a continuación se muestra se observan claramente las conexiones de alimentación y de datos de los sensores y de la tira NeoPixel.

Código

Nota

⚠️ Antes de cargar cualquier código en la UNIT DUAL MCU debes elegir con el selector USB el microcontrolador que desees programar ⚠️

A la par, asegúrate de elegir tu placa y tu puerto COM en el Arduino IDE

En la nueva versión de la UNIT DUAL MCU ONE el cambio de microcontrolador mediante el selector USB mecánico ya no es necesario, ya que la PC se puede comunicar a la vez con ambos dispositivos. Puedes tener dos monitores seriales recibiendo datos al mismo tiempo, uno para la ESP32 y otro para el RP2040 😉

Explicación

En el programa es importante notar que dentro de la función void setup() además de la inicialización de la tira NeoPixel, del monitor serial y de la declaración de las entradas, observamos una serie de líneas de código que se encargan de la calibración de sensor. Para ello realizamos una pausa inicial de 15 segundos para dar tiempo a que el elemento calefactor dentro del MQ-3 alcance una temperatura que le permita realizar las posteriores mediciones con mayor fidelidad. Después tomamos una medición del sensor, la cual será almacenada en la variable V0 la cual es sumamente importante porque será usada como referencia a partir de la cual se detecta la concentración del alcohol mediante una resta:

De la forma en que se lee la tensión que entrega el pin analógico del sensor MQ-3 (A0) señalamos la siguiente línea de código:
analogRead(sensor)/310.0;


Donde analogRead(sensor)entrega valores de 0 a 1023 (que corresponden al la resolución de 8 bits que por default tiene el RP2040) y estos valores se dividen entre 310 para obtener valores de 0 a 3.3 V que provienen del sensor MQ-3 como se muestra:

Después el programa contiene la lógica para encender cada color según los rangos de tensión que se obtengan del sensor MQ-3, esto mediante condicionales if.

#include <NeoPixelBus.h> // Librería para controlar tiras de LED NeoPixel

const uint16_t PixelCount = 8; // Número de LEDs en la tira
const uint8_t PixelPin = 2;    // Pin GPIO donde está conectada la tira LED

#define sensor A2             // Pin analógico (GPIO28) conectado al sensor MQ-3
#define colorSaturation 128   // Saturación de color para los LEDs (0-255)
#define buzzer 3              // Pin digital conectado al buzzer
#define espera 30000          // Tiempo de espera en ms para activación del buzzer (30 segundos)


// Inicialización de la tira con el método y características del tipo de LED
NeoPixelBus<NeoGrbFeature, NeoWs2812xMethod> strip(PixelCount, PixelPin);


// Definición de colores RGB para los LEDs
RgbColor red(colorSaturation, 0, 0);
RgbColor green(0, colorSaturation, 0);
RgbColor blue(0, 0, colorSaturation);
RgbColor white(colorSaturation);
RgbColor black(0);


float V0 = 0.0; // Valor base (en aire limpio) del sensor
float medicion_maxima = 0.0, ultima_medicion = 0.0;
int counter = 0, op = 0;


void setup() {
  pinMode(sensor, INPUT);     // Definimos el pin del sensor como entrada
  Serial.begin(115200);       // Iniciamos la comunicación serial
  pinMode(buzzer, OUTPUT);    // Configuramos el buzzer como salida


  strip.Begin();              // Inicializamos la tira LED
  strip.Show();               // Apagamos todos los LEDs al principio


  Serial.println("Calibrando sensor...");
  delay(15000);               // Esperamos 15 segundos para estabilizar el sensor
 
  V0 = analogRead(sensor)/310.0; // Leemos valor inicial del sensor (base de comparación)
  Serial.print("V0 = ");
  Serial.println(V0);


  // Indicamos fin de calibración con un bip corto
  digitalWrite(buzzer, HIGH);
  delay(200);
  digitalWrite(buzzer, LOW);
}

void loop() {
  float lectura = analogRead(sensor)/310.0; // Leemos valor actual del sensor


  // Si la lectura supera cierto umbral respecto al valor base, activamos detección
  if (lectura - V0 > 0.2) {
    op = 6;
    counter = 0;
  } else {
    op = 0;
  }

  // Si se detectó alcohol (op > 4), procesamos lectura y encendemos LEDs
  while (op > 4) {
    float medicion_instantanea = 0.0;
    float lectura = 0.0;

    // Promediamos 40 lecturas para mayor precisión
    for (int i = 0; i < 40; i++) {
      medicion_instantanea = analogRead(sensor)/310.0;
      lectura += medicion_instantanea;
      delay(1);
    }
    lectura /= 40.0;

    counter = millis(); // Contador del tiempo transcurrido

    float alcohol = lectura - V0;             // Diferencia respecto a la base
    float barraled = pow(alcohol * 10, 2);    // Cuantificamos intensidad para los LEDs

    Serial.println(barraled);                 // Mostramos en monitor serial
    delay(50);

    // 🟢 Alcohol bajo (1-15): encendemos LED en verde
    if (0.0 < barraled && barraled < 15) {
      int leds = barraled * 0.533333;
      strip.SetPixelColor(leds, green);
      delay(5);
      strip.Show();
    }

    // 🔵 Alcohol medio (15-30): encendemos LED en azul
    else if (15 <= barraled && barraled < 30) {
      int leds = (barraled * 0.533333) - 8;
      strip.SetPixelColor(leds, blue);
      delay(5);
      strip.Show();
    }

    // 🔴 Alcohol alto (30-45): encendemos LED en rojo y activamos alerta
    else if (30 <= barraled && barraled < 45) {
      int leds = (barraled * 0.533333) - 16;
      strip.SetPixelColor(leds, red);
      delay(5);
      strip.Show();

      ultima_medicion = alcohol * 10;
      if (medicion_maxima < ultima_medicion)
        medicion_maxima = ultima_medicion;

      // Si pasa el tiempo definido y la última medición es menor que la máxima anterior
      if (counter > espera && medicion_maxima > ultima_medicion) {
        // Activamos el buzzer varias veces para alerta
        digitalWrite(buzzer, HIGH);
        delay(30);
        digitalWrite(buzzer, LOW);
        delay(30);
        digitalWrite(buzzer, HIGH);
        delay(30);
        digitalWrite(buzzer, LOW);
        delay(10000); // Espera antes de reiniciar sistema

        while (1); // Detenemos el sistema
        op = 0;
      }
    }
  }
}

Conclusiones

Este alcoholímetro visual representa una excelente aplicación del sensor MQ-3 en conjunto con una tira NeoPixel y la placa UNIT DUAL MCU, permitiendo una interpretación rápida e intuitiva del nivel de alcohol presente. A lo largo del desarrollo se explicó desde la conexión de los componentes hasta la lógica del código, resaltando la importancia de la calibración y del manejo visual de los datos sensados. Con una estructura modular y portable, este proyecto no solo cumple una función práctica, sino que también sirve como base para futuras ampliaciones, como el envío de datos a una app o su integración en sistemas de seguridad. ¡Anímate a probarlo y personalizarlo!

TUTORIALES RELACIONADOS