Hola controleros y controleras, les doy la bienvenida a otra entrada del sitio WEB donde vamos a aprender a Medir el Nivel de Agua de un tanque usando un sensor de presión (MPX5010DP) y CUALQUIER microcontrolador (En este caso usaremos la placa de desarrollo de ARDUINO)
Antes de comenzar, te hago la invitación de que veas nuestro CURSO GRATUITO DE ARDUINO (CLICK AQUI)
Y también de que te suscribas al Canal de YouTUBE si quieres seguir aprendiendo sobre microcontroladores, sensores, programación y teoria de instrumentación y control:
Medición de Nivel de Agua
En esta entrada vamos a discutir una de las formas más económicas de realizar la medición del nivel de un tanque realizado por medio de un sensor de presión diferencial.
En este sitio WEB y en el canal de YouTube, ya hemos hablado de los SENSORES de PRESIÓN. Por eso te recomiendo de que le des un vistazo a esa entrada.
Como vimos en esa entrada anterior, ya sabemos que es la presión, las diferentes presiones que existen y sobre todo que
El nivel y el caudal pueden ser derivados de una medida de presión. Por ejemplo, para medir nivel tenemos que:
\Delta P= P_H - P_L =\rho g h
Por eso a pesar de no emplear un sensor de nivel de agua en este proyecto, es posible realizar la medición de nivel empleando otra característica de la física por medio de un sensor de presión diferencial de aire con arduino.
Sensor de Presión MPX5010DP
Existen diferentes sensores de presión diferencial en el mercado de los microcontroladores conocidos como Sensores de presión tipo MPX, MPX53DP, MPX53GP, MPX2010DP, MPX2010GP, MPX2050DP, MPX10DP, MPX5010DP, etc, y básicamente varían en la capacidad de presión que es capaz de medir el sensor.
Dependiendo de nuestra aplicación deberemos seleccionar el sensor adecuado, recordando que muchos de esos sensores necesitarán ser acoplados a circuitos amplificadores de voltaje para poder ser leidos por un microcontrolador (en este caso nuestro Arduino).
Por eso les recomiendo conseguir el MPX5010DP que ya entrega en su salida un voltaje de 0v – 5v ideal para microcontroladores, a diferencia de su hermano el MPX10DP hasta 50mV lo que requerirá de un amplificador operacional para tratar su señal.
El transductor piezo-resistivo de la serie MPX5010 es un sensor de presión de silicio monolítico de última generación diseñado para una amplia gama de aplicaciones, pero particularmente aquellas que emplean un microcontrolador o microprocesador con entradas ADC. Este transductor patentado de elemento único combina técnicas avanzadas de micromaquinado, metalización de película delgada y procesamiento bipolar para proporcionar una señal de salida analógica precisa y de alto nivel que sea proporcional a la presión aplicada.
MPX5010 puede medir una presión de 10 kPa y MPX5100 puede medir una presión de 100 kPa (14,5 psi). Da salida lineal sobre el rango como se muestra en la figura extraída de la hoja de datos.
Claro está que las aplicaciones de este sensor NO se limitan únicamente a la medición de Nivel, que es el objetivo de esta entrada.
Como vemos en el gráfico anterior, la ecuación para obtener la presión del sensor viene dada por:
P=\dfrac{V_{out}-0.04V_s}{0.09V_s}\pm Tol
es el voltaje de alimentación () y es el voltaje que entrega el sensor (o sea, el que leemos con arduino en bytes y lo transformamos a voltaje) y es la tolerancia, un ajuste que debemos hacerle al sensor para calibrar la medida.
Medición de Nivel por Presión Hidrostática
En este caso vamos a valernos de la presión hidrostática presentada anteriormente para la medición del nivel al interior de un tanque.
El pinado del sensor de presión MPX5010DP se muestra a continuación:
IMPORTANTE: Según el datasheet, el sensor no puede entrar en contacto directo con el liquido, por lo tanto debemos crear un colchón de aire en el interior del tubo que esta conectado al sensor para evitar que el liquido entre al interior del mismo.
Vamos a valernos de que el sensor de presión presenta una medición lineal, según lo pudimos observar en su datasheet y en la gráfica de arriba donde muestra la relación voltaje – Presión. Sin embargo, puedes perfectamente calibrar tu sensor usando una regresión lineal, como la que hicimos el el video con el sensor de temperatura con PIC.
Tomando como base la ecuación de presión diferencial que relaciona la altura (recordando que la presión a la atmosfera es cero):
P=\rho g h
donde es la presión, es la gravedad y es la altura o nivel del tanque.
h=\dfrac{P}{\rho g}
Las unidades que necesitamos saber aqui son, la del Pascal:
Pa=\dfrac{kg}{m.s^2}
densidad del agua (aprox)
\rho_{(agua)}=1000\dfrac{kg}{m^3}
gravedad (aprox)
g=10\dfrac{m}{s^2}
EJEMPLO: Supongamos que estamos leyendo 1kPa=1000Pa, la altura sería:
h=\dfrac{1000\dfrac{kg}{m.s^2}}{1000\dfrac{kg}{m^3}10\dfrac{m}{s^2}}=0.1m=10cm
Descargar hoja de excel de calibración via regresión lineal
>> DESCARGAR AQUI <<
Nota que con esta aplicación de medición de nivel usando un sensor de presión diferencial podríamos pensar en realizar un Control PID Arduino de Nivel.
A continuación te dejo el código para que lo copies y lo pegues en tu compilador, recuerda que para tener acceso a él, solo basta con compartir el contenido de este post, de esa forma ayudas que este sitio web siga aportando más contenidos gratuitos y de calidad.
/*================================================= https://controlautomaticoeducacion.com/arduino/ - 2020 By: Sergio Andres Castaño Giraldo =================================================*/ double Level,Vout,P,Vs=5.0; double aux; double tolP=0.04; // Ajusta la medida de presión int i, rho = 997; double g=9.8; void setup() { Serial.begin(9600); } void loop() { //Voltaje del Sensor MPC5010DP aux=0; for(i=0;i<10;i++){ aux = aux + (float(analogRead(A0))*5.0/1023.0); //v delay(5); } Vout=aux/10.0; //Presión en Kpa según gráfica 4 del Datasheet P = ( Vout - 0.04*Vs ) / (0.09 * Vs) + tolP; //kPa Level = ((P*1000)/(rho*g))*100; //Medida de Nivel del tanque Level = 1.081349*Level + 0.219574; Serial.print("\n\nVoltaje:"); Serial.print(Vout); Serial.println(" v"); Serial.print("Presión:"); Serial.print(P); Serial.println(" kPa"); Serial.print("Nivel:"); Serial.print(Level); Serial.println(" cm"); delay(3000); }
¿Cómo saber si mi sensor MPX sirve para determinado tanque?
Una pregunta bastante común que recibo es como saber cuanto es el nível máximo que aguanta el sensor MPX5010DP o cualquier otro sensor de presión MPX que existe en el mercado. Para saber eso, debemos partir de la ecuación expuesta anteriormente, donde debemos conocer la presión máxima que alcanza el sensor (el cual lo ves en el datasheet) y debes conocer la densidad del líquido que va a contener el tinaco o tanque.
Por ejemplo, el sensor MPX5010DP según su datasheet mide una presión máxima de 10kPa. Si queremos realizar la medición de nivel de agua con arduino, sabemos que la densidad del agua es
h=\dfrac{P}{g\rho}=\dfrac{10kPa}{\left(9.8\ {\rm m/s^2}\right) \left(997\ {\rm Kg/m^3}\right)}
h=\dfrac{10000\ {\rm Kg/(m.s^2)}}{\left(9.8\ {\rm m/s^2}\right) \left(997\ {\rm Kg/m^3}\right)}
h=1.023 \rm m
Lo que indica que el MPX5010DP solo puede ser empleado para medir como máximo un tanque de 1.023 metros de altura de agua. El mismo procedimiento puedes hacerlo para otro tipo de sensor o otro tipo de líquido.
Ejemplo de medición de nivel de agua con Arduino en Tanque Esférico
Vamos a realizar otro ejemplo similar, sin embargo en este caso usamos el sensor de presión diferencial para la medicón de nivel al interior de un tanque esférico:
La imagen anterior muestra un sensor de caudal al interior del tubo de alimentación que usaremos en otro proyecto. Pero lo importante es colocar el sensor de presion para determinar la altura de nivel de agua al interior de este tanque esférico. El circuito a implementar es el siguiente:
El circuito anteiror muestra la conexión del sensor MPX5010DP al pin A0 del arduino. Adicionalemente se muestra la activación de dos bombas empleando dos drivers de potencia diferente las cuales son moduladas con la señal PWM de Arduino. Sin embargo, para el proyecto actual, solo vamos a emplear la bomba conectada al BTS7960 que está en los pines 4 y 6 del arduino.
Para conectar una bomba (o motor) al BTS7960, generalmente necesitas realizar las siguientes conexiones:
- Alimentación (VCC y GND): El BTS7960 necesita una fuente de alimentación que puede variar típicamente entre 5V y hasta más de 20V, dependiendo de las especificaciones del motor. Asegúrate de conectar VCC al positivo de la fuente y GND al negativo.
- Conexiones al Motor: El BTS7960 tiene dos salidas para el motor, marcadas como MA y MB o a veces como B+ y B-. Conecta estas salidas a los dos cables del motor.
- Señales PWM (RPWM y LPWM): Para controlar la velocidad del motor, el BTS7960 utiliza señales de modulación de ancho de pulso (PWM). Las señales RPWM y LPWM controlan la velocidad y la dirección del motor. En el código proporcionado a continuación, la bomba (motor) se activa con una señal PWM en el pin
RPWM1
y se coloca un nivel bajo (LOW) en el pinLPWM1
para mover el motor en una dirección. Si quisieras mover el motor en la dirección opuesta, invertirías los niveles de señal. - Habilitación (Enable): El BTS7960 puede tener también pines de habilitación, que permiten activar o desactivar el driver. Estos pines suelen estar marcados como ENA y ENB o simplemente EN, asegurate de que estén en un estado lógico alto (HIGH) para habilitar el funcionamiento del motor.
El código es el siguiente:
//***************************************************// //***************************************************// //***** Medidor de nivel en Tanque Esferico *****// //***** *****// //***** by: Sergio Andres Castaño Giraldo *****// //***** https://controlautomaticoeducacion.com/ *****// //***** *****// //***************************************************// //***************************************************// // BTS7960 - 1 (Bomba 1) byte RPWM1 = 4; byte LPWM1 = 6; // l298 - 1 (Bomba 3) byte IN3_L1 = 24; byte IN4_L1 = 25; byte BEN_L1 = 5; // Sensor YF-S201 byte flowSensor1Pin = 2; volatile unsigned long pulseCount1 = 0; float flowRate1 = 0.0; unsigned long oldTime = 0; // Sensor MPX5010DP (Presión Diferencial) byte MPX1 = A0; //Estructura da Bomba L298 typedef struct{ byte enPin1; byte enPin2; byte pwmPin; }BombaL; //Estructura da Bomba BTS7960 typedef struct{ byte pwmA; byte pwmB; }BombaBTS; //Crear las bombas con las estructuras const BombaBTS bomba1 = {RPWM1, LPWM1}; const BombaL bomba3 = {IN3_L1, IN4_L1, BEN_L1}; float inputValue = 0; int velocity = 0; float tankLevel = 0; String inputString = ""; // Una cadena para mantener los datos recibidos boolean stringComplete = false; // Ya se recibió toda la cadena? void setup() { Serial.begin(9600); //Comunicación Serial inputString.reserve(200); // Reserva espacio para la cadena pinMode(flowSensor1Pin, INPUT_PULLUP); attachInterrupt(digitalPinToInterrupt(flowSensor1Pin), flowSensor1Interrupt, RISING); } void loop() { //Activar la bomba con el dato del serial velocity = map(inputValue, 0, 100, 0, 255); //Define el PWM de la Bomba digitalWrite(bomba1.pwmA, LOW); analogWrite(bomba1.pwmB, velocity); //PWM /* // Ativar bomba3 (BombaL) digitalWrite(bomba3.enPin1, HIGH); digitalWrite(bomba3.enPin2, LOW); analogWrite(bomba3.pwmPin, velocity); */ //Leitura da altura via pressão tankLevel = readPressureLevel(MPX1, 5.0, 0.03); Serial.print("Nivel Tk1 = "); Serial.println(tankLevel); //Calcular flujo cada 1segundo if ((millis() - oldTime) > 1000) { detachInterrupt(digitalPinToInterrupt(flowSensor1Pin)); flowRate1 = (pulseCount1 * 60.0) / 7.5; // L/min (YF-S201: 1 pulso = 2.25 mL) // Reiniciar conteo de pulsos y tiempo pulseCount1 = 0; oldTime = millis(); attachInterrupt(digitalPinToInterrupt(flowSensor1Pin), flowSensor1Interrupt, RISING); } delay(1000); } // Esta función se llama cada vez que el puerto serie recibe un byte: void serialEvent() { while (Serial.available()) { char inChar = (char)Serial.read(); // Obtiene el nuevo byte inputString += inChar; // Añade el byte a la cadena if (inChar == '\n') { // Si es un byte de nueva línea, la entrada está completa inputValue = inputString.toInt(); // Convierte la cadena a int // Si inputValue está en el rango de 0 a 100 if(inputValue > 100){inputValue = 100;} if(inputValue < 0){inputValue = 0;} inputString = ""; // Limpia la cadena } } } //Función de la interrupción void flowSensor1Interrupt() { pulseCount1++; } //Lectura sensor de presion double readPressureLevel(byte mpxPin, float Vs, float tolP) { // mpcPin = Pino do sensor // Vs = 5.0 Voltagem de alimentação (pode botar o valor exato para maior presição) // tolP = Tolerancia do sensor, usado para ajustar a medida double Vout, P, aux = 0; const int numSamples = 10; double rho = 997; double g=9.8; // Ler voltagem do sensor (filtro de meia móvel) for (int i = 0; i < numSamples; i++) { aux += (double(analogRead(mpxPin)) * 5.0 / 1023.0); delay(5); } Vout = aux / numSamples; // Calcular a pressão em kPa segundo equação do DataSheet (Gráfico) P = (Vout - 0.04 * Vs) / (0.09 * Vs) + tolP; // Calcular o nível do tanque em cm double Level = ((P * 1000) / (rho * g)) * 100; return Level; }
Eso es todo por la entrada del dia de hoy, espero les haya gustado y hayan aprendido algo nuevo. Si te ha servido el contenido de esta entrada, de los videos y los códigos de implementación y deseas apoyar mi trabajo invitandome a un café super barato, puedes hacerlo en el siguiente link:
👉 Invitar a Sergio a un Café ☕️
Que esten muy bien, nos vemos en la siguiente entrada.
Mi nombre es Sergio Andres Castaño Giraldo, y en este sitio web voy a compartir una de las cosas que mas me gusta en la vida y es sobre la Ingeniería de Control y Automatización. El sitio web estará en constante crecimiento, voy a ir publicando material sobre el asunto desde temas básicos hasta temas un poco más complejos. Suscríbete al sitio web, dale me gusta a la página en Facebook y únete al canal de youtube. Espero de corazón que la información que comparto en este sitio, te pueda ser de utilidad. Y nuevamente te doy las gracias y la bienvenida a control automático educación.