Buenas.
Estoy implementando un proyecto con un pic24f sobre un control de riego. La idea es adquirir, a través de varios sensores, la insolación, la temperatura, la humedad relativa y la velocidad del viento. Con esos datos realizar una serie de cálculos para determinar cuando hay que regar una plantación (según evapotranspiración y balance de agua en el suelo).
El proyecto ya lo tengo casi terminado (lectura de todos los sensores, cálculos...) y ahora estoy repasando todo el código para detectar posibles fallos que pudieran ocurrir y que dejarían el pic "colgado".
Uno de esos fallos es en referencia al termómetro DS18B20. Ese termómetro utiliza para comunicarse un bus one-wire. Se trata de una comunicación por un solo hilo. El tema está en yo, para hacer la lectura de la temperatura, desactivo todas las interrupciones que pudieran distorsionar la lectura. Esto me funciona bien y no hay problema. El problema que veo en la implementación que he hecho es que si hay una desconexión del DS18B20 (falla el cable) o ese se estropea, el pic quedará esperando la respuesta de este infinitamente, quedando colgado ahí.
El código de la rutina que tengo es esa:
float llegir_temperatura (void)
{
int temp;
float temperatura;
unsigned char correcte=1, crc[9], i, error=0;
_IC1IE = 0; //Desactiva interrupció IC1
_INT1IE = 0; //Desactiva interrupció Interrupcio Externa 1
_INT2IE = 0; //Desactiva interrupció Interrupcio Externa 2
while (correcte != 0)
{
while (pols_reset_OW()==1); //Realitzar reset i esperar pols presència ds18b20
escriure_byte_OW(Skip_rom); //Saltar orde ROM
escriure_byte_OW(Convert_T); //Indicar a ds18b20 que realitzi conversió temperatura
while (llegir_bit_OW()==0); //Esperar que ds18b20 acabi conversió temperatura
while (pols_reset_OW()==1); //Realitzar reset i esperar pols presència ds18b20
escriure_byte_OW(Skip_rom); //Saltar orde ROM
escriure_byte_OW(Read_scratchpad); //Llegir dades de ds18b20
for (i=0; i<9; i++)
{
crc[i] = llegir_byte_OW(); //Guarda el valor dels 9 bytes del scratchpad
}
correcte = comprovar_crc(crc); //Comprovar si la lectura ha estat correcte
//Al quart intent de lectura amb fallo CRC sortir i avisar
}
_IC1IE = 1; //Activa interrupció IC1
_INT1IE = 1; //Activa interrupció Interrupcio Externa 1
_INT2IE = 1; //Activa interrupció Interrupcio Externa 2
temp = crc[1] << 8;
temp = temp | crc[0]; //Uneix LSB i MSB de la temperatura en 2 bytes
if (temp & 0x80) //Temperatura negativa
{
temp = ~temp + 1;
temperatura = (((float) temp)/16)* (-1);
}
else //Temperatura positiva
temperatura = ((float) temp)/16;
return (temperatura);
}
Cuando entro en la función, desactivo algunas interrupciones y realizo un "pulso de reset" y espero que el DS18B20 responda. Si por lo que fuera el DS18B20 no responde el programa se queda esperando indefinidamente.
A mi, la única manera que se me ocurre es la siguiente
T4CONbits.TON = 1; //Activa el Timer 4 en mode 16 bits
_T4IE = 1;
while (correcte != 0)
{
TMR4 = 0;
PR4 = 0xF424;
_LATA0 = 1;
while (_T4IF != 1);
_LATA0 = 0;
_T4IF = 0;
while (_T4IF != 1)
{
if (pols_reset_OW()==0)
{
error = 0;
//break;
}
else
{
error = 1;
correcte = 0;
}
}
_T4IF = 0;
Falta parte del código pero solo muestro lo modificado. Mediante el Timer4 (Timer 1 lo uso con el módulo IC1 y el timer 2 y 3 los tengo como contador de 32bytes para otra cosa). Las primeras líneas modificadas era para ver si entraba bien (parpadeo de un led de 4s). Luego, entro en un bucle while que durará como mucho 4s (oscilador de 8MHz, timer4 con preescaler 1:256), si el pulso de respuesta del DS18B20 se recibe marca error 0 y sinó error 1.
No me gusta demasiado esta manera (la encuentro poco clara, y poco "elegante") pero me viene otra manera de hacerlo. Lo quería hacer por rutina de interrupción pero no se como ya que al salir de ella vuelve al bucle.
El problema que tengo es que me parpadea el led y luego el pic se resetea, no lo entiendo. En RCON me marca reset de mclr, por SWR, por POR y Bor.
No se que pasa.
Si alguien tiene alguna idea del poruqe me será de gran ayuda.
Gracias