Problemas con demoras de lectura con sensor de temperatura

hola a todos quisiera pedir una asesoría ya que en el buscador de la pagina no encuentro lo que yo buscaba por que tengo un sensor de temperatura lm35 conectado al pic16f877a y yo declaro que la temperatura es mayor a 36 grados este accione unos motores y un led y que en el lcd aparesca alerta pero este cambia no se queda fijo cambia de alerta a normal y los motores encienden 5 segundos y se apagan sigue asi por un rato y lo que quiero es que se quede fijo a menos que la temperatura sea menos de 36 por que aun asi siendo 40 grados cambia ya intente subir las demoras pero lo que hace sea lenta la lectura en el lcd y tambien los motores se accionen incorrectamente lo que necesito es si me pueden explicar por que paso eso.

Código:
#include "16f877.h"                    
# device *=16
#device adc=10                         
#use delay(clock=4000000)      
#fuses xt,nowdt,noput,nobrownout,nolvp,noprotect   
#include "lcd.c"             
#use standard_io (D)
#use standard_io (A)
#use standard_io (B)
#use standard_io (C)

float temperatura;

void main()
{


setup_adc_ports(RA0_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
setup_COUNTERS(RTCC_internal.rtcc_div_1);
set_adc_channel(0);

lcd_init();
lcd_gotoxy(5,1);
lcd_putc("Bienvenido");
delay_ms(350);
lcd_init();


while(true)
{
temperatura=(float)read_adc()/2;
//********grados centigrados
lcd_gotoxy(5,1);
printf(lcd_putc,"%f",temperatura);
lcd_gotoxy(12,1);
lcd_putc("Grados");
delay_ms(200);



if(temperatura<=150&&temperatura>=40)
{
output_high(pin_a1);
output_low(pin_a2);
output_low(pin_a3);
output_high(pin_b0);
output_high(pin_b1);
output_low(pin_b2);
output_high(pin_c0);
output_high(pin_c1);
output_low(pin_c2);


lcd_gotoxy(5,2);
lcd_putc("Alta");
delay_ms(2000);
}

else
{
output_low(pin_a1);
output_high(pin_a2);
output_low(pin_a3);
output_low(pin_b0);
output_low(pin_b1);
output_low(pin_b2);
output_low(pin_c0);
output_low(pin_c1);
output_low(pin_c2);


lcd_gotoxy(5,2);
lcd_putc("Normal");
delay_ms(2000);
}
if(temperatura<=500&&temperatura<=16)
{
output_low(pin_a1);
output_low(pin_a2);
output_high(pin_a3);
output_high(pin_b0);
output_low(pin_b1);
output_high(pin_b2);
output_high(pin_c0);
output_low(pin_c1);
output_high(pin_c2);


lcd_gotoxy(5,2);
lcd_putc("Baja");
delay_ms(2000);
}
else
{
output_low(pin_a1);
output_high(pin_a2);
output_low(pin_a3);
output_low(pin_b0);
output_low(pin_b1);
output_low(pin_b2);
output_low(pin_c0);
output_low(pin_c1);
output_low(pin_c2);


lcd_gotoxy(5,2);
lcd_putc("Normal");
delay_ms(2000);
}
}

}

ahi esta el codigo que utilize para hacer mi circuito solo necesito que se quede fijo hasta que baje la temperatura por que no se queda asi gracias por comprension
 
Última edición por un moderador:
Olvida los delays, los entierras y no los usas mas. Son inútiles al 10000000% (es una opinión personal objeto de gran discordia)
Usa temporizadores por interrupciones así no tendrás muerto el sistema dos segundos que eso es una eternidad y media.

Si pasa algo en esos delays el sistema está muerto.
 
Olvida los delays, los entierras y no los usas mas. Son inútiles al 10000000% (es una opinión personal objeto de gran discordia)
Usa temporizadores por interrupciones así no tendrás muerto el sistema dos segundos que eso es una eternidad y media.

Si pasa algo en esos delays el sistema está muerto.

como uso los temporizadores por interrupción?
 
En un PIC y en C ni idea. Si quieres te lo digo en assembler en un 8052 o en arduino en en wiring.
La idea es que si haces un bucle de 2s está 2s muerto.

Una solución no muy elegante pero funcional es que hagas un bucle con 20 retardos de 100ms y en cada bucle compruebes/actualices cosas
Es casi lo mismo, pero ahora tardas dos segundos en tomar una decisión, de este modo tardarás 100ms.
 
En un PIC y en C ni idea. Si quieres te lo digo en assembler en un 8052 o en arduino en en wiring.
La idea es que si haces un bucle de 2s está 2s muerto.

Una solución no muy elegante pero funcional es que hagas un bucle con 20 retardos de 100ms y en cada bucle compruebes/actualices cosas
Es casi lo mismo, pero ahora tardas dos segundos en tomar una decisión, de este modo tardarás 100ms.

bueno es que resulta que el codigo lo tengo que explicar y en c se me hace mas facil de explicarlo que en ensamblador pero de todos modos gracias
 
Los retardos en c, detienen la ejecución del código según el tiempo que les pongas, así que el problema continuará.
Como dice Scooter, utiliza timers, estos se ejecutan de una manera diferente y no afectan tu código.
Estos se programan tomando en cuenta la Fosc y el prescaler que utilices para dividir ese tiempo, y si utilizas interrupciones tendrás más opciones.

Yo igual he trabajado con el LM35 y debido a su sensibilidad (10mV/C) puede hacer que el ADC del microcontrolador cambie sus lecturas rápidamente.
Esto puedes solucionarlo aumentando un poco el tiempo de adquisición del modulo y muestrear el resultado unas x veces.

Intenta ésto:
PHP:
unsigned int valor_adc; = 0 //variable de más de 10 bits
float temperatura = 0.00;

void main (void) {

ADCON0 = 0b11000000; //TAD de 6us, PortA.f0 como analógico
ADCON1 = 0b10001110; //Justificación a la derecha, Vcc como Vref

while(1) {

ADCON.ADON = 1; // modulo ADC activado
Delay_us(20);       //TADQ  de 20us (o más), necesario para que el condensador interno del pic se cargue
ADCON.GO = 1;    //inicia conversión ADC
while(ADCON.GO == 1); espera que termine la conversión

valor_adc = (ADRESH << 8) + ADRESL; //guarda el resultado de 10 bits


temperatura = Resolución * valor_adc;  //calcula la resolución

//
código para el  muestreo de la temperatura
//

}
La resolución la calculas, ya sea que utilizas VCC como Vref, pero si quieres más precisión del LM35, te recomiendo que bajes Vref cercano a los 1.5 V. para tener una resolución de 1 bit/°C.

El muestreo no es más que la suma de varias temperaturas y sacar la media de dicha suma.
Esto lo puedes hacer con un sentencia FOR, y para reducir tiempos usa los timers e interrupciones.



Ensamblador y lenguaje C, son muy parecidos, solo que ensamblador utiliza menos memoria del microcontrolador, pero esto se puede igualar en C, si reduces el uso de las librerías y trabajas directamente con los registros.
 
Última edición por un moderador:
los delay en c, detienen la ejecución del código según el tiempo que les pongas, así que el problema continuara. Como dice Scooter, utiliza timers estos se ejecutan de una manera diferente y no afectan tu código. Estos se programan tomando en cuenta la Fosc y el prescalar que utilizes para dividir ese tiempo, y si utilizas interrupciones tendrás mas opciones.

Yo igual eh trabajado con el LM35 y debido a su sensibilidad (10mV/C) puede hacer que el ADC del microcontrolador cambie sus lecturas rápidamente. Esto puedes solucionarlo aumentando un poco el tiempo de adquisición del modulo y muestrear el resultado unas x veces, intenta esto:

unsigned int valor_adc; = 0 //variable de más de 10 bits
float temperatura = 0.00;

void main (void) {

ADCON0 = 0b11000000; //TAD de 6us, PortA.f0 como analógico
ADCON1 = 0b10001110; //Justificación a la derecha, Vcc como Vref

while(1) {

ADCON.ADON = 1; // modulo ADC activado
Delay_us(20); //TADQ de 20us (o más), necesario para que el condensador interno del pic se cargue
ADCON.GO = 1; //inicia conversión ADC
while(ADCON.GO == 1); espera que termine la conversión

valor_adc = (ADRESH << 8) + ADRESL; //guarda el resultado de 10 bits


temperatura = Resolución * valor_adc; //calcula la resolución

//
código para el muestreo de la temperatura
//

}


La resolución la calculas, ya sea que utilizas VCC como Vref, pero si quieres mas precisión del LM35 te recomiendo que vajes Vref cercano a los 1.5 V para tener una resolución de 1 bit/°C.

el muestreo no es mas que la suma de varias temperaturas y sacar la media de dicha suma. Esto lo puedes hacer con un sentencia FOR, y para reducir tiempos usa los timers e interrupciones.



Ensamblador y lenguaje C, son muy parecidos, solo que ensamblador utiliza menos memoria del microcontrolador, pero esto se puede igualar en C, si reduces el uso de las librerías y trabajas directamente con los registros.

en esta parte
//
código para el muestreo de la temperatura
//
ya va todo mi codigo donde pongo los condicionales if y demas
 
No, ahí va la sentencia FOR que te mencioné, y después tu código.
Necesitas un muestreo de la temperatura para que la lectura sea más o menos decente.

Me explico:
Digamos que tu sensor muestra los siguientes valores: 24, 25, 24, 25, 23, 24, 27, 24, 26, 24. (ya sea por el ruido eléctrico, defecto de fabrica del sensor o es muy sensible)

La sumatoria da 246, y este valor lo divides entre el número de valores, osea 10, y la media te da un valor de 24.6, siendo la temperatura 24 (si eliminas los decimales) y si observas en los valores el 24 es el que más se repite.

Después de eso sigue tu código. ¿Me entiendes?



Chécalo, y si no, probamos otra cosa.
 
Última edición por un moderador:
Hola, más allá de las buenas recomendaciones de los compañeros sobre el detalle que causa el delay, tienes varios problemas en tu código.
Por ejem, en éstas sentencias:

if(temperatura<=150&&temperatura>=40)
if(temperatura<=500&&temperatura<=16)

Si te fijas en el 2do. "if" la comparación con la magnitud 500, no tiene sentido, ya que la 2da. comparación con 16, "le hace sombra", me explico?
Otro problema está en el puerto a2, ya que hay controversias lógicas, pues en la negación "else" en una sentencia lo activas y en la otra sentencia afirmativa, la niegas. Analiza ese punto.
 
Última edición:
Buenas, y digo yo, ¿por que no usas un DS18B20?, que es digital, en vez del LM35, te puedo decir que yo lo uso para casi todo, va de maravilla y ademas usas menos codigo.
 
Atrás
Arriba