Buenos dias estoy intentando medir la velocidad de una gota mediante el desplasamiento entre dos barreras infrarojas. Cada corte de haz de luz medira un tiempo que va desde t0,t1,t2,t3,t4.
int sensor1 = 8;// sensor1 entrada 8 digital
int contador1 =0;
int evento1;
int ingreso1=0;
unsigned long Tim0;//time0
unsigned long Tim1;//time1
unsigned long Tim2;//time2
///////////////////////////////////////////////////////////
int sensor2=6;//sensor2 entrada 6 digital
int contador2= 0;
int evento2;
int ingreso2= 0;
unsigned long Tim3;// time3
unsigned long Tim4;// time4
////////////////////////////
float Vb = 0;
float L= 14.5; // separación sensor1 e sensor2 (cm)
float Ti; //diferencia de Time3-Time1
float Ts; //diferencia de Time4-Time2
void setup() {
Serial.begin(9600);
pinMode(sensor1, INPUT);
pinMode(sensor2, INPUT);
Tim0=millis();
}void loop() {
evento1 =digitalRead(sensor1);
evento2 =digitalRead(sensor2);
if(evento1 ==HIGH) {
Tim1= millis() - Tim0;
if(ingreso1==0){}
} else {( evento1 == LOW);
contador1 ++;
Tim2 = millis();
while ( evento1== LOW ){
evento1 = digitalRead(sensor1);
}
Serial.println("contador1:");
Serial.println(contador1);
Serial.println("Tim1:");
Serial.println(Tim1);
Serial.println("Tim2:");
Serial.println(Tim2);
}
if(evento2 == HIGH) {
Tim3= millis();
if(ingreso2==0){}
} else { (evento2 = LOW);
contador2 ++;
Tim4 = millis();
while ( evento2==LOW){
evento2 = digitalRead(sensor2);
}
Serial.println("contador2:");
Serial.println(contador2);
Serial.println("Tim3:");
Serial.println(Tim3);
Serial.println("Tim4:");
Serial.println(Tim4);
Ti = (Tim3-Tim1);
Serial.println ("Ti:");
Serial.println(Ti);
Ts = (Tim4-Tim2);
Serial.println ("Ts:");
Serial.println(Ts);
//////////////////////////////////////
Vb=(10)*(L/2)*(1/(Ti) + 1/(Ts)); /////// 10 es número para la conversion de millis a seg y metros
Serial.println(Vb);
Hay muchas cosas para corregir en tu código empezando porque esta mal copiado, faltan llaves al final.
El otro tema es que no te explicas convenientemente, o al menos YO no te comprendo.
Porque no haces un esquema indicando donde tienes los sensores.
Si son dos sensores como tomas 4 lecturas o simplementes son 4 gotas?
Dices que cada corte de luz medirá un tiempo, pues una cosa es de la misma gota o de gotas diferentes para lo cual necesitas mas sensores, entonces hablas de medición de varias gotas entre dos sensores ubicados a 14.5 cm supongo.
Bien, bajo este criterio de medir 4 o 5 gotas hago un código mas simple pero que haría teóricamente lo mismo.
Identificaré a cada gota como gota1 a gotaN con N que puede cambiarse para medir mas casos.
No veo el sentido de medir el tiempo 0 ya que no hay gota asociada con el arranque del arduino.
#define LECTURAS 5
unsigned long TimerInicio[LECTURAS]; // timer de 0 a 4, total N timers
unsigned long TimerFin[LECTURAS]; // timer de 0 a 4, total N timers
int sensor1 = 8; // sensor1 entrada 8 digital
int sensor2 = 6; // sensor2 entrada 6 digital
int contador1 = 0;
int evento1, envento1Ant = LOW;
int evento2, envento2Ant = LOW;
float Vb = 0;
float L = 14.5; // separación sensor1 e sensor2 (cm)
void setup() {
Serial.begin(9600);
pinMode(sensor1, INPUT);
pinMode(sensor2, INPUT);
}
void loop() {
char buffer[30];
evento1 = digitalRead(sensor1);
evento2 = digitalRead(sensor2);
if (evento1 && !evento1Ant) {
TimerInicio[contador] = millis();
}
evento1Ant = evento1;
if (evento2 && !evento2Ant) {
TimerFin[contador] = millis();
sprintf(buffer,"Gota%d = %ld", contador, TimerFin[contador]-TimerInicio[contador]);
Serial.println(buffer);
contador++; // incremento contador o sea leo proxima gota.
}
evento2Ant = evento2;
}
No he calculado la velocidad porque creo mas importante que se midan bien los tiempos.
Al terminar de pasar la gota por el segundo sensor se incrementa el contador y lo deja listo para la próxima medición.
Cuando pasa la primera gota me marca T1= 0 y T2 =0 y T3= 0 y solo T4 da un valor , que puede estar errado en mi código y otra pregunta tengo que calcular el T0 desde que se conecto el arduino y restarlo al T1.
Aunque dudo que se mida algo, voy a considerar tu punto de vista porque puedo estar equivocado.
A ver si esto funciona mas o menos adecuadamente?
unsigned long TimerIin[LECTURAS]; // timer de 0 a 4, total N timers
unsigned long TimerIout[LECTURAS]; // timer de 0 a 4, total N timers
unsigned long TimerFin[LECTURAS]; // timer de 0 a 4, total N timers
unsigned long TimerFout[LECTURAS]; // timer de 0 a 4, total N timers
int sensor1 = 8; // sensor1 entrada 8 digital
int sensor2 = 6; // sensor2 entrada 6 digital
int contador1 = 0;
int evento1, envento1Ant = LOW;
int evento2, envento2Ant = LOW;
float Vb = 0;
float L = 14.5; // separación sensor1 e sensor2 (cm)
bool flag = false;
void setup() {
Serial.begin(9600);
pinMode(sensor1, INPUT);
pinMode(sensor2, INPUT);
}
void loop() {
char buffer[50];
evento1 = digitalRead(sensor1);
evento2 = digitalRead(sensor2);
if (evento1 && !evento1Ant) { // acaba de pasar la gota
TimerIin[contador] = micros();
}
while (evento1) {
evento1 = digitalRead(sensor1)
if (!evento1) {
TimerIout[contador] = micros(); // tardó X useg
evento1Ant = evento1;
break;
}
} // espero mientras la gota atraviesa el sensor
if (evento2 && !evento2Ant) {
TimerFin[contador] = micros();
}
while (evento2) {
evento2 = digitalRead(sensor2)
if (!evento2) {
TimerIout[contador] = micros(); // tardó X useg
evento2Ant = evento2;
flag = true;
break;
}
}
if (flag){
sprintf(buffer,"Gota%d = T1=%ld us T2=%ld us T3=%ld us T4=%ld us", contador, TimerIin[contador], TimerIin[contador]-TimerIout[contador],
TimerFin[contador], TimerFout[contador]-TimerFin[contador]);
Serial.println(buffer);
contador++; // incremento contador o sea leo proxima gota.
flag = false; // preparado para otra gota.
}
}
Sirve para 5 gotas.
Dudo que se pueda medir algo en 3mm y yo usaría interrupciones antes que lo que he usado pero a riesgo de equivocarme prueba.
Si no me gana alguien, usaría INT0 en modo CHANGE y INT1 en modo CHANGE tambien.
cada vez que se active una interrupcion veo el flanco y tomo micros(), lo mismo con interrupciones y eso asegurará una lectura mas precisa.
muchas gracias por las respuesta , compile el programa la gota fue detecta pero el tiempo t1 y t2 del primer sensor ( si la gota solo pasa por el primer sensor el tiempo no es detectado) comienza a marcar cuando la gota llega al segundo sensor y lo que no entiendo por que da negativo.
Veo que en el código se me pasó por alto esta línea al comienzo
#define LECTURAS 5
Ahora analizo el código a ver que ocurre.
cambia la linea de sprintf por esta
sprintf(buffer,"Gota%d = T1=%lu us T2=%lu us T3=%lu us T4=%lu us", contador, TimerIin[contador], TimerIin[contador]-TimerIout[contador],
No comienza a marcar cuando pasa por el segundo sensor, comienza a presentar cuando tiene 4 tiempos y eso no ocurre hasta tener el 4to tiempo.
Por eso no te muestra si es tan rapido que no cambia mucho.
Qué sentido tiene leer Gota0 T1 xxxx y los demas en 0? No tiene coherencia para mi.
Me sorprende que a menos velocidad el primer sensor tome 8 useg y el segundo 20 useg que es mas rápido, hubiera espero 20 y 17 por decir algo. Mucha diferencia, o acaso la gota cambia de forma?
sprintf(buffer,"Gota%d = T1=%lu us T2=%lu us T3=%lu us T4=%lu us", contador, TimerIin[contador], TimerIin[contador]-TimerIout[contador],
haciendo serial print Serial.println( buffer ) da tiempos iniciales = 0
Bueno conseguido junto a @jorgeguerrerovargas algunos avances.
Esta es la versión con micros y máquina de estados que se comporta bastante bien
#define LECTURAS 20
unsigned long Timer1in[LECTURAS]; // timer de 0 a 4, total N timers
unsigned long Timer1out[LECTURAS]; // timer de 0 a 4, total N timers
unsigned long Timer2in[LECTURAS]; // timer de 0 a 4, total N timers
unsigned long Timer2out[LECTURAS]; // timer de 0 a 4, total N timers
unsigned long S1, S2, S12;
int sensor1 = 2; // sensor1 entrada 8 digital
int sensor2 = 3; // sensor2 entrada 6 digital
int contador = 0;
int evento1, evento1Ant = LOW;
int evento2, evento2Ant = LOW;
double Vb = 0;
float L = 0.145; // eparación sensor1 e sensor2 (cm)
bool flag = false;
byte estado = 0;
void setup() {
Serial.begin(9600);
pinMode(sensor1, INPUT);
pinMode(sensor2, INPUT);
Serial.println("Comenzando la prueba de medicion de gotas");
}
void loop() {
char buffer[100];
switch(estado) {
case 0: evento1 = digitalRead(sensor1);
if (evento1 &&!evento1Ant) { // acaba de pasar la gota
Timer1in[contador] = micros();
estado = 1;
}
evento1Ant = evento1;
break;
case 1: while (evento1) {
evento1 = digitalRead(sensor1);
if (!evento1) {
Timer1out[contador] = micros(); // tardó X useg
evento1Ant = evento1;
estado = 2;
break;
}
}
break;
case 2: evento2 = digitalRead(sensor2);
if (evento2 && !evento2Ant) {
Timer2in[contador] = micros();
estado = 3;
}
evento2Ant = evento2;
break;
case 3: while (evento2) {
evento2 = digitalRead(sensor2);
if (!evento2) {
Timer2out[contador] = micros(); // tardó X useg
evento2Ant = evento2;
flag = true;
estado = 4;
break;
}
}
break;
case 4: S1 = Timer1out[contador]-Timer1in[contador];
S2 = Timer2out[contador]-Timer2in[contador];
S12 = Timer2in[contador]-Timer1in[contador];
sprintf(buffer,"Gota%2d = S1=%lu us S2=%lu us S12=%lu", contador, S1, S2, S12);
Serial.print(buffer);
Vb = L*1e6/(S12); //
Serial.println(" Velocidad:" +String(Vb));
contador++; // incremento contador o sea leo proxima gota.
if (contador > LECTURAS)
contador = 0;
flag = false; // preparado para otra gota.
estado = 0;
} // end while
} // end loop#define LECTURAS 20
unsigned long Timer1in[LECTURAS]; // timer de 0 a 4, total N timers
unsigned long Timer1out[LECTURAS]; // timer de 0 a 4, total N timers
unsigned long Timer2in[LECTURAS]; // timer de 0 a 4, total N timers
unsigned long Timer2out[LECTURAS]; // timer de 0 a 4, total N timers
unsigned long S1, S2, S12;
int sensor1 = 2; // sensor1 entrada 8 digital
int sensor2 = 3; // sensor2 entrada 6 digital
int contador = 0;
int evento1, evento1Ant = LOW;
int evento2, evento2Ant = LOW;
double Vb = 0;
float L = 0.145; // eparación sensor1 e sensor2 (cm)
bool flag = false;
byte estado = 0;
void setup() {
Serial.begin(9600);
pinMode(sensor1, INPUT);
pinMode(sensor2, INPUT);
Serial.println("Comenzando la prueba de medicion de gotas");
}
void loop() {
char buffer[100];
switch(estado) {
case 0: evento1 = digitalRead(sensor1);
if (evento1 &&!evento1Ant) { // acaba de pasar la gota
Timer1in[contador] = micros();
estado = 1;
}
evento1Ant = evento1;
break;
case 1: while (evento1) {
evento1 = digitalRead(sensor1);
if (!evento1) {
Timer1out[contador] = micros(); // tardó X useg
evento1Ant = evento1;
estado = 2;
break;
}
}
break;
case 2: evento2 = digitalRead(sensor2);
if (evento2 && !evento2Ant) {
Timer2in[contador] = micros();
estado = 3;
}
evento2Ant = evento2;
break;
case 3: while (evento2) {
evento2 = digitalRead(sensor2);
if (!evento2) {
Timer2out[contador] = micros(); // tardó X useg
evento2Ant = evento2;
flag = true;
estado = 4;
break;
}
}
break;
case 4: S1 = Timer1out[contador]-Timer1in[contador];
S2 = Timer2out[contador]-Timer2in[contador];
S12 = Timer2in[contador]-Timer1in[contador];
sprintf(buffer,"Gota%2d = S1=%lu us S2=%lu us S12=%lu", contador, S1, S2, S12);
Serial.print(buffer);
Vb = L*1e6/(S12); //
Serial.println(" Velocidad:" +String(Vb));
contador++; // incremento contador o sea leo proxima gota.
if (contador > LECTURAS)
contador = 0;
flag = false; // preparado para otra gota.
estado = 0;
} // end while
} // end loop
Tengo una mejor versión con Interrupciones pero veo que hay problemas con la alineación de las gotas.
En las pruebas que hicimos hubo lecturas discímiles. Unas pocas no superaban 16 us y otras 2000.
Si la gota tarda 34500 useg en atravesar los 14.5cm y suponemos que la gota puede llegar a medir 3mm de altura entonces unas cuentas simples dicen
145 mm ------------ 34500 us
003 mm ------------ x us = 34500*3/145 = 713 us
como vemos ese es el valor esperable con alguna variación positiva o negativa desde ya.
Dudo que el haz IR atraviese la gota porque por la refracción eso no debería ocurrir, tal vez habría que considerar agregar algún tinte para que las opaque e invalide cualquier posible error de este tipo.
Como no se logró homogeneidad en las lecturas me atrevo a suponer que hay un triple problema: alineación, tamaño y frecuencia
La alineación yo la ajustaria con un puntero laser o maser. Muy fácil aunque el gotero tiene su diámetro asi que habrá que hacerlo de forma paralela.
El tamaño y la frecuencia de las gotas debería asegurar que el ciclo de lectura se cumpla, es decir no se puede enviar una gota hasta que la gota que esta en viaje supera el 2do sensor y todas deben ser mas o menos similares.
La mejor opción es conseguir un gotero como los que se usan en Terapia Médica. No deben ser caros y su uso debería garantizar lecturas mas homogéneas.