Hola a todos!
Estoy con una confusión por ser nuevo en programación de Arduino. Quiero armar un sistema de alarma son un sensor de tensión "zmpt101b", que cuando baje de cierto nivel de tensión suene una sirena o encienda un indicador, seria una salida a un modulo de relé.
Logre hacer funcionar correctamente el sensor y puedo ver los parámetros de tensión en el monitor serie, pero después al querer hacer la lógica con la función "if y else" y hacer encender el relé cuando el nivel de tensión sea menor al establecido, el relé queda siempre activado.
Dejo el código de programación a ver si alguno con mas experiencia puede ver en que me estoy equivocando.
Muchas gracias!
#include <Filters.h>
float testFrequency = 50; // Frecuencia (Hz)
float windowLength = 40.0/testFrequency; // promedio de la señal
int Sensor = 0; //A0
float intercept = -0.04; // para ser ajustado en base a las pruebas de calibración
float slope = 0.0405; // para ser ajustado en base a las pruebas de calibración
float volts; // Voltaje
unsigned long periodo = 1000; // tiempo de lectura
unsigned long tiempoAnterior = 0;
float Nivel = volts; // nivel de volts
int AlarmaLowLevel = 100; // Si baja de este nivel activa alarma pin 7
int Alarma = 7; //salida rele 1, por bajo nivel
void setup() {
pinMode (Alarma, OUTPUT); //definir rele 1 como salida, activa alarma o desactiva
Serial.begin(9600);
delay(5000);
}
void loop() {
RunningStatistics inputStats; //inicio sensor de voltaje
inputStats.setWindowSecs(windowLength); //inicio sensor de voltaje
while(true) {
Sensor = analogRead(A1); //leer pin analógico
inputStats.input(Sensor);
if((unsigned long)(millis() - tiempoAnterior) >= periodo) {
volts = intercept + slope * inputStats.sigma(); //offset y amplitud
volts = volts*(40.3231); //calibración
Serial.print("\tVoltaje: "); // solo para ver voltaje en monitor serie
Serial.println(volts); // solo para ver voltaje en monitor serie
tiempoAnterior = millis();
}
}
if(AlarmaLowLevel > Nivel) //inicio logica de alarma
{
digitalWrite(Alarma,LOW);
}
else
{
digitalWrite(Alarma,HIGH);
}
}
#include <Filters.h>
float testFrequency = 50; // Frecuencia (Hz)
float windowLength = 40.0/testFrequency; // promedio de la señal
int Sensor = 0; //A0
float intercept = -0.04; // para ser ajustado en base a las pruebas de calibración
float slope = 0.0405; // para ser ajustado en base a las pruebas de calibración
float volts; // Voltaje
unsigned long periodo = 1000; // tiempo de lectura
unsigned long tiempoAnterior = 0;
float Nivel = volts; // nivel de volts
int AlarmaLowLevel = 100; // Si baja de este nivel activa alarma pin 7
int Alarma = 7; //salida rele 1, por bajo nivel
void setup() {
pinMode (Alarma, OUTPUT); //definir rele 1 como salida, activa alarma o desactiva
Serial.begin(9600);
delay(5000);
}
void loop() {
RunningStatistics inputStats; //inicio sensor de voltaje
inputStats.setWindowSecs(windowLength); //inicio sensor de voltaje
Sensor = analogRead(A1); //leer pin analógico
inputStats.input(Sensor);
if((millis() - tiempoAnterior) >= periodo) {
volts = intercept + slope * inputStats.sigma(); //offset y amplitud
volts = volts*(40.3231); //calibración
Nivel = volts;
Serial.print("\tVoltaje: "); // solo para ver voltaje en monitor serie
Serial.println(volts); // solo para ver voltaje en monitor serie
tiempoAnterior = millis();
}
if(AlarmaLowLevel > Nivel) //inicio logica de alarma
{
digitalWrite(Alarma,LOW);
}
else
{
digitalWrite(Alarma,HIGH);
}
}
Probalo ahora.
Como dijo @DanX3 tenía un while() innecesario que lo trababa todo y olvidaste reasignar Nivel.
Por otro lado todos los parametros del primer if() ya son unsigned long por lo que no es necesario forzar el tipo.
Hola muchas gracias, ahora mismo lo pruebo sin el while. El parámetro Nivel lo tengo asignado al comienzo como los "volts" del sensor. No se si estará bien asignado, porque copie el código del sensor donde esta la calibración del mismo y utilizo esa variable ya calculada.
Hola muchas gracias por la respuesta, la variable nivel la tengo asignada arriba como la salida de "volts", ahora nos si estará bien asignada. Porque copie el código del sensor de un ejemplo, y al tener una calibración utilice directamente la salida ya calculada como mi nivel.
Veo que la librería Filters.h es especial en como toma los datos asi que ese while(1) que a todos nos molesta, en realidad tiene un break cuando la ventana de tiempo se termina.
A ver si esto funciona, simplemente poniendo las comparación luego de cuando muestras los datos.
void loop() {
RunningStatistics inputStats; // inicio sensor de voltaje
inputStats.setWindowSecs(windowLength); // inicio sensor de voltaje
while (true) {
Sensor = analogRead(A1); // leer pin analógico
inputStats.input(Sensor);
if ((unsigned long)(millis() - tiempoAnterior) >= periodo) {
volts = intercept + slope * inputStats.sigma(); // offset y amplitud
volts = volts * (40.3231); // calibración
Nivel = volts; // <=== esto tmb es importante
Serial.print("\tVoltaje: "); // solo para ver voltaje en monitor serie
Serial.println(volts); // solo para ver voltaje en monitor serie
if (AlarmaLowLevel > Nivel) { // inicio logica de alarma
digitalWrite(Alarma, LOW);
} else {
digitalWrite(Alarma, HIGH);
}
tiempoAnterior = millis();
}
}
}
Funciono! muchísimas gracias! Aprovecho a hacerte una consultas de unas dudas que me surgen.
Veo que pones "Nivel = volts" dentro del loop, era eso en si el problema? o es que debía incluir la función If dentro de toda la función "while"
Y si no es mucha molestia, cuando arranca el sensor por unos 3 segundos toma al principio mediciones erradas, que no son las verdaderas y esto hace que la alarma actué, como seria la forma de darle un delay a toda la programación así al enchufar el circuito no empieza sonando la alarma hasta que se estabilice la medición del sensor.
Una vez mas, muchísimas gracias!
Si ese era el mayor de los problemas. Luego poner los condicionales dentro es anecdótico.
Me gusta mas poner que se haga un cambio si realmente lo hubo, que no este como loco cambiando.
Deberias poner una histéresis o sea.. que cambie o se active para un lado como esta pero que se apague no cuando no se de la condición
#include <Filters.h>
float testFrequency = 50; // Frecuencia (Hz)
float windowLength = 40.0/testFrequency; // promedio de la señal
int Sensor = 0; //A0
float intercept = -0.04; // para ser ajustado en base a las pruebas de calibración
float slope = 0.0405; // para ser ajustado en base a las pruebas de calibración
float volts; // Voltaje
unsigned long periodo = 1000; // tiempo de lectura
unsigned long tiempoAnterior = 0;
float Nivel = volts; // nivel de volts
int AlarmaLowLevel = 100; // Si baja de este nivel activa alarma pin 7
int Alarma = 7; //salida rele 1, por bajo nivel
void setup() {
pinMode (Alarma, OUTPUT); //definir rele 1 como salida, activa alarma o desactiva
Serial.begin(9600);
delay(5000);
RunningStatistics inputStats; //inicio sensor de voltaje
inputStats.setWindowSecs(windowLength); //inicio sensor de voltaje
}
void loop() {
Sensor = analogRead(A1); // leer pin analógico
inputStats.input(Sensor);
if ((millis() - tiempoAnterior) >= periodo) {
volts = intercept + slope * inputStats.sigma(); // offset y amplitud
volts = volts * (40.3231); // calibración
Nivel = volts; // <=== esto tmb es importante
Serial.print("\tVoltaje: "); // solo para ver voltaje en monitor serie
Serial.println(volts); // solo para ver voltaje en monitor serie
if (AlarmaLowLevel > Nivel) { // inicio logica de alarma
digitalWrite(Alarma, LOW);
} else {
digitalWrite(Alarma, HIGH);
}
tiempoAnterior = millis();
}
}
Mira la librería y vas a ver que entre en ese while(true) que parece infinito pero como tiene una ventana de lectura, termina el saliendo con algun break. No lo busqué porque no es importante para mi en este momento. Pero asi funciona!!
Yo habia hecho lo mismo que vos, vi que te dijo que no funcionaba y entonces miré la librería y ahi me di cuenta como trabaja.
Como sueles decir "Aclaren de dónde descargaron la librería para evitar pérdidas de tiempo" o algo así.
A falta de aclaración miraba la librería Filters que se encuentra en el gestor de la IDE, o sea la de hideakitai, y resultó que ésta es Filters-master de ThamKhao.
La verdad es que es una cosa muy chula, como una mini estación. Los conocimientos sobre este tema te serán muy útiles en la vida. Me encontré con esto cuando estaba instalando un sistema de seguridad ajax, sólo con sensores. Quiero que mi hijo se dedique a la ingeniería eléctrica o a la programación. Es una de las áreas más demandadas de la vida en este momento. Creo que es muy digno que un hombre sea capaz de entenderlo, al menos para sí mismo.