Hola a todos.
En primer lugar quiero pedir disculpas si no he publicado el post en el foro adecuado, y si así fuese ruego al administrador retire este post o lo cambie de lugar.
Soy estudiante de Ingeniería, y necesito vuestra ayuda para poder terminar un programa de Arduino para un proyecto que estoy desarrollando conmpuesto por varias partes, entre otras una placa Arduino, que podría ser un Arduino UNO o un Arduino Mega ADK.
Hasta ahora nunca había tocado nada de Arduino, y me está constando un poco programar correctamente el Hadware.
Voy a explicar brevemente mi proyecto y exponer el programa que he realizado y que no termina de funcionar bien.
Básicamente la placa de Arduino lo que va ha hacer es contar los pulsos en flanco de bajada que transmite un molino cada vez que da una vuelta. Este dato junto a otros que recibe por bluetooth (puerto serie) anteriormente (del tipo de hélice usada por el molino y de el tiempo en el que se cuentan los pulsos), se usan para hacer un cálculo y convertir esos datos en rps y posterormente en velocidad (m/s). Este dato de velocidad se transmite por Bluetooth (puerto serie)
La placa de Arduino tiene conectado el molinete a la entrada digital 2 (podría ser otra), activada una resitencia pull up, y conectado a su puerto serie un modem Bluetooth HC-06, integrado en un placa X-Bee, que a su vez está montada en una shield de X-Bee para Arduino (UNO o MEGA).
Desdee que se enciende la placa Arduino el molino puede ya estar dando vueltas, pero solo hay que contar los pulsos en un momento y tiempo dados.
El dispositivo que envía los datos por Bluetooth es un móvil, y en el momento en que la conexión entre el modem y el móvil es correcta, transmite via serie primero un "caracter" para indicar el tiempo y luego otro para indicar el tipo de molino-hélice.
Posteriormente, cuando se presiona un botón en el móvil se envía un tercer "caracter" para indicar el comienzo de la cuenta atrás del tiempo establecido y empezar a contar los pulsos desde ese momento hasta que termina la cuenta de tiempo. Es decir, si el tiempo establecido es de 20 s, cuando se presiona el botón empieza la cuenta atrás (20,19,18,...,1,0) y se cuentan todos los pulsos en flanco de bajada obtenidos en ese periodo. El Arduino realiza los cálculos y de inmediato envía la cifra resultante por Bluetooth al móvil. Este proceso se repite varias veces, pero siempre con la misma hélice-molino seleccionada y con el mismo tiempo, hasta que se apage Arduino.
Para los cálculos del tiempo he empleado varios métodos, pero todo el mundo me aconseja usar un timer, por lo que he incorporado la librería MStimer2, aunque desconozco si la estoy aplicando correctamente. Para contar los pulsos uso interrupciones, pero no consigo hacerlas funcionar en el momento adecuado. También he utilizado algunas funciones que en C creo que funcionarían pero aquí me dan problemas de compilación.
Me estoy esforzando en aprender pero no termino de pillarle el tranquillo. Si simplifico el programa y pongo un tiempo fijo y una hélice única he conseguido buenos resultados, pero cuando Arduino envía los datos al móvil no coinciden con la visualización en pantalla de los mismos, sino que van con retraso, es decir, la segunda vez que presiono el botón de comienzo recibo los datos de los pulsos contados en la primera vez.
Os escribo mi programa con comentarios, y estoy dispuesto ha aceptar todo tipo de sugerencias, pero que no me obliguen a modificar mucho el programa del móvil, por que se me complican los plazos de entraga del trabajo en la universidad.
Para indicar el tiempo el móvil envia un carecter que puede ser a, b, c, d, e, f. Cada uno coresponde a 20, 30, 40, 50, 60 y 120 segundos respectivamente.
Posteriormente (con retardo de 1 segundo) envía otro caracter que puede ser g, j. El primero corresponde con "molino-helice 1" y el segundo con "molino-helice 2" de distintos fabricantes.
Después, cada vez que se presione un botón en el móvil, envía el "caracter" p, para indicar el comienzo de la cuenta atrás del tiempo mientras se cuentan los pulsos.
/PROGRAMA CUENTAPULSOS TEMPORIZADO/
#include <MsTimer2.h>
volatile unsigned long con_vueltas = 0;
typedef struct s_temp{ /no estoy seguro de que esto funcione en Arduino, me ha hechado una mano un compañero con esta parte/
unsigned char activo;
unsigned int cuenta;
}TD_TEMP;
TD_TEMP tiempo1;
float rps; //variable donde almaceno las revoluciones por segundo
float velocidad;
long temp;//variable que recibo por bluetooth al inicio de conectar el modem
int tipo_helice;//variable que recibo por bluetooth al inicio y siempre después de temp
long tiempo1;
unsigned char time_is_OFF(TD_TEMP *timer) {
if((timer->activo)&&(timer->cuenta==0))
{
timer->activo = 0;
return(1);
}
else return(0);
}
void setup(){
pinMode(2, INPUT);
Serial.begin(9600);
digitalWrite (2,HIGH); //activo resistencia Pull-Up interna
attachInterrupt(0, cambio_estado, FALLING); //Utilizo interrupciones para cambio de estado por flanco de bajada
MsTimer2::set (1000, flash);//1000ms de periodo
MsTimer2::start();
}
void loop() {
while (Serial.available()){
char dato= Serial.read();
switch (dato){
//Variable de tiempo q envio desde Android via Bluetooth
case 'a': temp = 20;
break;
case 'b': temp = 30;
break;
case 'c': temp = 40;
break;
case 'd': temp = 50;
break;
case 'e': temp = 60;
break;
case 'f': temp = 120;
break;
//Variable que indica la hélice usada
case 'g': tipo_helice = 1;
break;
case 'j': tipo_helice = 2;
break;
//Empiezo a contar el tiempo
case 'p':
/TENGO QUE AÑADIR AQUÍ UNA FUNCIÓN PARA HABILITAR INTERRUPCIÓN cambio_estado, no se bien si esto funciona/
interrupts ();
request_time (&tiempo1,temp);//Comienza cuenta atrás
while (!time_is_OFF(&tiempo1));//BUCLE INFINITO SIN ACCIÓN HASTA QUE TERMINA CUENTA ATRÁS
detachInterrupt(0);//Apaga interrupción cambio_estado
calcular_velocidad();//Envía el dato de velocidad a Android
reset_variables();//Resetea las variables utilizadas
break;
}
}
}
void calcular_velocidad(){
if (tipo_helice = 1){
rps = ((con_vueltas)/(temp/1000.0));//revoluciones por segundo de este molino con su hélice
if (rps < 1.98) velocidad = (((31.17 * rps) + 1.93)/100);//formula matemática propia del molino
else if (rps > 10.27) velocidad = (((33.44 * rps) - 14.09)/100);//formula propia del molino
else velocidad = (((32.05 * rps) + 0.19)/100);//fórmula propia del molino
}
else{
rps = (((con_vueltas)/3)/(temp/1000.0));//revoluciones por segundo de este otro molino con su hélice
if (rps < 0.36) velocidad = ((0.4850 * rps) - 0.003);//formula matemática propia del molino
else velocidad = ((0.4850 * rps) - 0.003); //formula matemática propia del molino
}
Serial.println (velocidad);//envía el dato de velocidad al móvil por bluetooth conectado en puerto serie
}
void flash(){
dec_temp (&tiempo1);
}
void cambio_estado(){ //función que cuenta vueltas cuando cambia el pulso a flanco de bajada
con_vueltas++;
}
void reset_variables(){ //Reseteo variables
con_vueltas=0; //contador a cero
Serial.flush();//Borro cache puerto serie
}
void dec_time(TD_TEMP *timer) {
if((timer->activo)&&(timer->cuenta>0))timer->cuenta -= 1;
}
void request_time(TD_TEMP *timer, unsigned int mseg) {
timer->cuenta = mseg;
timer->activo = 1;
}
Perdón si en el programa exite alguna incoherencia, o alguna función no esta bien declarada, no soy programador, tan solo aficionado.
Agradecería vuestra ayuda porque no se muy bien como seguir.
Muchas gracias y saludos.