CONTROL DE UNA INCUBADORA karpic:
Resulta que tengo el siguiente código, pretende ser el control de una incubadora y resulta que cuando desactivo las resistencias pull-up para el puerto B deja de funcionar la pantalla LCD y si las activo lo que no me funciona es el control dimmer, esto lo hago en el proteus y no se si esta mal el código o puede ser fallo del proteus. #include <16F876.h> #include #use delay(clock=4000000) #fuses XT,NOWDT,NOPUT,NOLVP,NOBROWNOUT,NOCPD,NOWRT,NODEBUG #define use_portb_lcd TRUE #include "flex_lcd_.c" #include int16 contador; //************ variables dimmer **************************** int pasada2=0; long int muestra2=0; int j=0; int contadora2=1; int intervalador2=1; int auxiliar2=0;
//********************************************************** //******************** dimmer ****************************** // Interrupción del TIMER1, encargado de calcular el tiempo de un semiciclo constante mente. #INT_TIMER1 void temporizador() { set_timer1(0); } // Interrupción del TIMER0, provoca el retardo deseado antes de la excitación #INT_timer0 void tempo() { output_high(PIN_C4); // Ha transcurrido el tiempo, activo la salida } // Interrupción Externa, provocada por el paso por 0V de la señal de entrada #INT_EXT void externa() { if (j==0){ output_high(PIN_B1); j=1; ext_int_edge(H_TO_L); // Cambio la detección del flanco, // para que la proxima sea de bajada } else { output_low(PIN_B1); j=0; ext_int_edge(L_TO_H); // La próxima interrupción será de subida }
if (pasada2==0){ (pasada2==0){ enable_interrupts(INT_TIMER1);
// Activo la cuenta
set_timer1(0); // Comenzando desde cero pasada2=1; } else if (pasada2==1){ muestra2=get_timer1(); // Tiempo medido entre dos pasos por 0 sucesivos set_timer1(0); // Inicio el Timer1 para una nueva cuenta intervalador2=(muestra2/8); // Equiparo los preescaler, y por tanto las unidades // de tiempo de TIMER1 y timer0.
// 8 unidades de TIMER1 equivalen a 1 de timer0 auxiliar2=(intervalador2/4); // Divido el tiempo de un semiciclo en 4 //(por ejemplo). intervalador2=256-auxiliar2; // Este es el valor final a cargar el timer0,
//con esto retardo la señal 1/4 de su semiperido enable_interrupts(INT_timer0);
//set_timer0(intervalador); set_timer0(200); output_low(PIN_C4); // Pongo a 0 la salida, y comienza el retardo } }
//********************************************************************* // Interrupción del TIMER2, encargado de calcular el // tiempo de un semiciclo constantemente. #INT_TIMER2 void INTERRUPTION() { contador ++; set_timer2(0); }
//#byte port_c=0x07 //****************************************************************************** // input(pin_C0) Pulsador de menu y ok // input(pin_C1) Pulsador de flecha abajo (mas) // input(pin_C2) Pulsador de flecha arriba (menos) //****************************************************************************** short actualizar; typedef union { int16 i; float f; } valor; valor humedad, temperatura; byte errorsht11,checksum; unsigned test=1;//, i; int8 testado; float T, H; int16 X, Y, V, X1;
// RUTINA SONDA void sonda(){ errorsht11=0; errorsht11+=sht11_medicion((byte*)&humedad.i, &checksum,HUMI);
//measure humidity errorsht11+=sht11_medicion((byte*) &temperatura.i, &checksum, TEMP);
//measure temperature if(errorsht11!=0) //in case of an error: connection reset { printf(lcd_putc,"\n\rerror:%U", errorsht11); sht11_hard_reset(); }
else { humedad.f=(float)humedad.i; //converts integer to float temperatura.f=(float)temperatura.i; //converts integer to float sht11_calculos(&humedad.f, &temperatura.f); //calculate humidity, temperature } //lcd_gotoxy(1,1); //printf(lcd_putc," Temp. Humedad"); //lcd_gotoxy(0,2); //printf(lcd_putc," %2.2f",temperatura.f); if (temperatura.f < (read_float_eeprom(1))) output_high(pin_A0); if (temperatura.f > (read_float_eeprom(1))) output_low(pin_A0); if (humedad.f < (read_float_eeprom(10)-1)) output_high(pin_A1); if (humedad.f > (read_float_eeprom(10)+1)) output_low(pin_A1); lcd_send_byte(1,0b11011111);
//printf(lcd_putc,"C
%2.2f%%HR",humedad.f);
actualizar=true; delay_ms(100); }
// RUTINA MENU PRINCIPAL void menus() { switch(testado){ case 1: lcd_putc("\f"); lcd_gotoxy(1,1); lcd_putc("1 Temperatura"); break; case 2: lcd_putc("\f"); lcd_gotoxy(1,1); lcd_putc("2 Humedad"); break; case 3: lcd_putc("\f"); lcd_gotoxy(1,1); lcd_putc("3 Volteo"); break; case 4: lcd_putc("\f"); lcd_gotoxy(1,1); lcd_putc("4 Salir"); break; } }
// RUTINA MENU SECUNDARIO void menus2() { switch (testado){ case 1: delay_ms(100); T=read_float_eeprom(1); lcd_putc("\f"); lcd_gotoxy(1,1); lcd_putc("Set Grados "); lcd_putc(223);
//for(i=200;i!=255;i++) //{ //lcd_gotoxy(1,1); //lcd_putc(i); //printf(lcd_putc,"%u",i); //delay_ms(1000); //}; lcd_putc("C"); lcd_gotoxy(5,2); printf(lcd_putc,"%1.1f",T); while(input(pin_C0)) { delay_ms(50); if (!input(pin_C1)) //veo si se presiono xxxxx { delay_ms(50); while (!input(pin_C1)); //si es asi, espero a que se libere T=T+0.10; if (T>40) T=15.00; lcd_gotoxy(5,2); printf(lcd_putc,"%1.1f",T); } if (!input(pin_C2)) //veo si se presiono xxxxx { delay_ms(50); while (!input(pin_C2)); //si es asi, espero a que se libere T=T-0.10; if (T<15) T=40.00; lcd_gotoxy(5,2); printf(lcd_putc,"%1.1f",T); } } while (!input(pin_C0)); write_float_eeprom(1,T); break; case 2: delay_ms(100); H=read_float_eeprom(10); lcd_putc("\f"); lcd_gotoxy(1,1); lcd_putc("Set Humedad %"); lcd_gotoxy(5,2); printf(lcd_putc,"%1.1f",H); while(input(pin_C0)) { delay_ms(50); if (!input(pin_C1)) //veo si se presiono xxxxx { delay_ms(50); //si es asi, espero a que se libere while (!input(pin_C1)); H=H+0.10; if (H>90) H=20.00; lcd_gotoxy(5,2); printf(lcd_putc,"%1.1f",H); } if (!input(pin_C2)) //veo si se presiono xxxxx { delay_ms(50); //si es asi, espero a que se libere while (!input(pin_C2));
H=H-0.10; if (H<20) H=90.00; lcd_gotoxy(5,2); printf(lcd_putc,"%1.1f",H); } } while (!input(pin_C0)); write_float_eeprom(10,H); break; case 3: delay_ms(100); V=read_eeprom(20); lcd_putc("\f"); lcd_gotoxy(1,1); lcd_putc("Set Volteo minu-"); lcd_gotoxy(1,2); lcd_putc("tos"); lcd_gotoxy(5,2); printf(lcd_putc,"%3lu",V); while(input(pin_C0)) { delay_ms(50); if (!input(pin_C1)) //veo si se presiono xxxxx { delay_ms(50); while (!input(pin_C1)); //si es asi, espero a que se libere V++; if (V>120) V=0; lcd_gotoxy(5,2); printf(lcd_putc,"%3lu",V); } if (!input(pin_C2)) //veo si se presiono xxxxx { delay_ms(50); while (!input(pin_C2)); //si es asi, espero a que se libere V--; if (V==-1) V=120; if (V<0) V=120; lcd_gotoxy(5,2); printf(lcd_putc,"%3lu",V); } } while (!input(pin_C0)); write_eeprom(20,V); contador = 0; break; case 4: test=0; break; } }
// RUTINA PULSADOR void pulsador() { menus(); delay_ms(100); while(input(pin_C0)) { delay_ms(50);
if (!input(pin_C1)) { delay_ms(50); while (!input(pin_C1)); testado++; if(testado>4){testado=1;} menus(); } if (!input(pin_C2)) { delay_ms(50); while (!input(pin_C2)); testado--; if(testado==0){testado=4;} menus(); } } while (!input(pin_C0)); menus2();
//veo si se presiono xxxxx
//si es asi, espero a que se libere
//veo si se presiono xxxxx
//si es asi, espero a que se libere
//pulsador(); } void main() {
//****************************************************************************** setup_timer_2(T2_DIV_BY_16,255,16); set_timer2(0); setup_timer_1(T1_INTERNAL | T1_DIV_BY_8); setup_timer_0(RTCC_INTERNAL | RTCC_DIV_64); // Programacion timer0 ENABLE_INTERRUPTS(GLOBAL); // Habilita todas las interrupciones. ENABLE_INTERRUPTS(INT_TIMER2); ENABLE_INTERRUPTS(INT_EXT); ENABLE_INTERRUPTS(INT_RTCC); // Habilita interrupcion timer0. ENABLE_INTERRUPTS(INT_TIMER1); //****************************************************************************** ext_int_edge(L_TO_H);
//
port_b_pullups(true);
setup_adc_ports(NO_ANALOGS); actualizar=true; lcd_init(); sht11_hard_reset();; testado=1; while(true) { V=read_eeprom(20); X1=V*10; X=1*X1; Y=2*X1; if(contador > X){ OUTPUT_HIGH(PIN_A2); } if(contador > Y){ OUTPUT_LOW(PIN_A2); contador = 0; }
//lcd_gotoxy(0,2); //printf(lcd_putc,"%5lu",contador);
//printf(lcd_putc,"%4lu",X); //printf(lcd_putc,"%4lu",Y); //SET_RTCC(131);// RESET_RTCC; if (actualizar) { sonda(); lcd_gotoxy(1,1); printf(lcd_putc," Temp. Humedad"); lcd_gotoxy(0,2); printf(lcd_putc," %2.2f",temperatura.f); printf(lcd_putc,"C %2.2f%%HR",humedad.f); } if (!input(pin_C0)) { delay_ms(50); while (test){pulsador();} } test=1; testado=1; } } Marttyn:
Uy, karpic, creo que es mucho código para que alguien se interese en leerlo por las buenas! Intenta poner solo la parte del código afectado, porque realmente me gustaría ayudarte, pero no tengo el tiempo (ni las ganas) de leer e interpretar tanto texto. Salu2 karpic:
Gracias por tu sugerencia, pero no se realmente donde puede estar el problema. Por el puerto B controlo una LCD menos el pin RB0 que lo utilizo como interrupción externa para detectar el paso por cero de la señal para control del dimmer. Como he dicho antes el problema es que al activar las resistencias pull-up del puerto B deja de funcionar la interrupción externa y si las desactivo lo que no me funciona es la pantalla LCD. RedPic:
La flex_lcd.c lleva unos defines en los que declaras qué pines son los que vas a utilizar para controlar el LCD, debes comprobar que no están en conflicto con el resto de pines de los que haces uso en tu programa. También y por otro lado debes tener claro qué ocurre cuando activas las pull-up y si realmente es lo que necesitas. Ten en cuenta primero que las pull-up conectan los pines del puerto b directamente a Vcc (a 5V), todos los pines y no solo uno de ellos. Segundo, debes usar las pull-ups para pines que sean de entrada. Para pines de salida es una incongruencia utilizarlas. Y solo se utilizan cuando lo externo que conectamos a ellos funcionan enviando la señal tirándola a masa, de forma que si e stán inactivos devuelven, "leen", un 1 y cuando se activan, dan un pulso, devuelven, "leen", un 0. Si activas una pull-up para una entrada que envía un pulso positivo leerás siempre un 1, cuando está en reposo ya que la pull-up está conectada a Vcc y cuando está activo ya que éste también envía una conexión a Vcc. Ve investigando todo esto en t u aplicación y nos cuentas. karpic:
Pues acabo de montar el circuito cargado con el programa que tenia las pull-up desactivadas, o sea en el que no funcionaba el lcd en el simulador, y cual ha sido mi sorpresa que es que f unciona perfectamente, esto me hace pensar que el proteus no simula correctamente esta situación, ahora solo me queda probar la parte del dimmer.
RESISTENCIAS PULL-UP Y RESISTENCIAS EXTERNAS A LOS PUERTOS PIC FOXBATSK:
Me podrían explicar en si como funcionan las resistencias Pull-up y que utilidad tie nen tenerlas activadas o desactivadas en un pic. También, he leído que se recomienda poner una resistencia de 10k a Vcc a un puerto cuando no se usa, pero, ¿a este puerto lo debo de poner como entrada o salida?
RaDoN: Las resistencias pull-up (a Vcc) o pull-down (a GND, masa...) solo son útiles cuando el puerto (sean internas o externas es igual) actúa como entrada. Lo que hace es asegurar un estado en la puerta cuando no le llega ninguna señal, en caso de pull-up un 1, y el pull-down lo contrario, un 0. Pero a la vez estos estados son "flexibles", me explico, si en una pull-down (recuerda un 1 lógico) aparece en la entrada un 1 este prevalece al que tiene la resistencia. Espero haberme explicado, la gama 16f tiene las resistencias en el puerto B, de ello que se use en las aplicaciones para entradas y no tener que usar externas, además como posee interrupciones por cambio de estado, lo hace mas ideal para usar este puerto como entrada. Por cierto, si necesitas usar externas, estas son del orden de 4k7 a 10k LAS RESISTENCIAS DE PULL-UP Una de las cualidades que distinguen a los microcontroladores de los microprocesadores es que encierran en un solo chip todos los elementos posibles de un sistema de control. Con este fin los AVR incorporan en todos sus puertos transistores a manera de fuente de corriente que en la práctica funcionan como resistencias de pull-up. Estas pull-ups nos pueden ahorrar el uso resistencias de sujeción externas en los pines de los puertos configurados como entradas. Las pull-ups se podrían equiparar con resistencias de entre 20 K y 50 K. a partir de dichos valores podemos calcular la corriente que puede fluir por ellas si están activadas. Las pull-ups se pueden habilitar pin por pin independientemente escribiendo un 1 en su registro de salida PORT. Las-pull ups solo serán efectivas en los pines que actúan como entradas; en los pines configurados como salidas las pull-ups quedan automáticamente deshabilitadas. Existe un bit llamado PUD en el registro MCUCR cuya función es deshabilitar todas las pull-ups de todos los puertos si su valor es 1. El bit PUD (Pull-Ups Disable) inicializa a 0 y un posible interés por setearlo puede ser eliminar la pequeña corriente que puede fluir por las pull-ps cuando los pines en cuestión se conectan a 0 lógico. La siguiente figura muestra la conexión de un pulsador al AVR aprovechando la pull-up de un pin de E/S. Fíjate en que las pull-ups no se pueden usar como resistencias para excitar dispositivos como LEDs, relés, etc. Ejemplo de uso de las resistencias de pull-up. La figura de ejemplo muestra la pull-up de un solo pin pero están presentes en todos los pines de E/S del AVR.