Informe DataLogger
Informe DataLogger
Universidad de Cuenca
Facultad de Ingeniería
Cuenca, Ecuador
Recomendaciones
• Asegurar una correcta calibración del sistema de acondicionamiento de señal del sensor LM35 y del
HS1101 para mejorar la precisión de las mediciones.
• Revisar las conexiones del módulo CCP y del Timer 1 para evitar errores en la medición del periodo
de la señal de humedad.
• Utilizar retardos adecuados o temporizadores para definir el periodo de muestreo del datalogger.
• Comprobar la correcta escritura y lectura de la memoria EEPROM para garantizar la integridad de los
datos almacenados.
Anexos
ANEXO 1: Código principal del datalogger en lenguaje C (PIC-C).
ANEXO 2: Código de los drivers y funciones para la medición de temperatura y humedad relativa.
C:\Users\ASUS TUF\OneDrive\Escritorio\Universidad de Cuenca\7moCiclo\Microprocesadores II\Ejem
1: //--- Universidad de Cuenca ---//---
2: //--- Facultad de Ingeniería - Carrera de Electricidad ---//---
3: //--- Microprocesadores y Microcontroladores II ---//---
4: //--- Ing. Vinicio Thiguez Morán ---//---
5: //---//---
6: //--- Descripción: Sensores de temperatura (LM35) y humedad relativa (HS1101),
7: //--- el programa implementa el registro en memoria EEPROM (datalogger)
8:
9: #include <16F877A.h>
10: #device adc = 10
11: #fuses XT, NOWDT, NOPROTECT, NOLVP
12: #use DELAY(CLOCK=4000000)
13:
14: //--- Configuración del LCD
15: //Definición de los pines de control para el LCD. Deben colocarse siempre antes
16: //de incluir el fichero LCD.C
17: #define LCD_ENABLE_PIN PIN_D3
18: #define LCD_RW_PIN PIN_D2
19: #define LCD_RS_PIN PIN_D1
20: #define LCD_DATA0 PIN_D4
21: #define LCD_DATA1 PIN_D5
22: #define LCD_DATA2 PIN_D6
23: #define LCD_DATA3 PIN_D7
24: //Incluye driver original de PIC C para LCD
25: #include <ENBLANCO.c>
26:
27: //---//---
28: //--- GESTION DE PUERTOS ---//---
29: //---//---
30: #use standard_io(A)
31: #byte TRISA = 0x85
32: #byte TRISC = 0x87
33:
34: //---//---
35: //--- TIMER 1 y MÓDULO CCP ---//---
36: //---//---
37: #byte PIR1 = 0x0C //Registro de banderas de interrupciones 1
38: #bit TMR1IF = PIR1.0
39: #bit CCP1IF = PIR1.5
40: #byte PIE1 = 0x8C //Registro de habilitación (máscaras) de interrupciones 1
41: #bit TMR1IE = PIE1.0
42: #bit CCP1IE = PIE1.5
43: #byte T1CON = 0x10 //Registro de control del TIMER 1
44: #bit TMR1ON = T1CON.0
45: #byte CCP1CON = 0x17 //Registro del módulo CCP
46:
47: //---//---
48: //--- VARIABLES PARA GESTIONAR CELDAS DE MEMORIA EEPROM ---//---
49: //---//---
50: #define DATOS_T 0x00 //Inicio de datos de temperatura
51: #define DATOS_RH 0x02 //Inicio de datos de Humedad Relativa
52: #define DATOS_FIN 0x40 //Número total de datos (de 16 bits) de T o RH que se
53: //pueden almacenar en la EEPROM del PIC (64 datos)
54:
55: //---//---
56: //--- Declaración de variables globales ---//---
57: //---//---
58:
59: //Variables para medición de Temperatura:
60: int8 sensor_lm35_lsb = 0; //Byte menos significativo del dato analógico
61: int8 sensor_lm35_msb = 0; //Byte más significativo del dato analógico
62: int16 sensor_lm35 = 0; //Dato analógico de temperatura
63: float temp_g; //Temperatura ambiental en grados centígrados
64:
65: //Variables para medición de humedad:
66: int8 cuenta = 0; //Cuenta las capturas de CCP1 (de 1 a 2)
67: int8 periodo_LSB = 0; //Byte menos significativo del periodo de la señal
1
C:\Users\ASUS TUF\OneDrive\Escritorio\Universidad de Cuenca\7moCiclo\Microprocesadores II\Ejem
68: int8 periodo_MSB = 0; //Byte más significativo del periodo de la señal
69: int16 captura1 = 0; //Primera captura
70: int16 captura2 = 0; //Segunda captura
71: int16 periodo = 0; //Periodo = captura2 - captura1
72: int16 frecuencia = 0; //Frecuencia de la señal eléctrica del sensor
73: float RH; //Humedad relativa en porcentaje
74:
75: //---//---
76: //--- FICHEROS DE FUNCIONES ---//---
77: //---//---
78: //Contiene las funciones para la medición de temperatura y humedad relativa
79: #include <SensoresTempHum.c>
80:
81: //---//---
82: //--- Función de Interrupción para el módulo CCP ---//---
83: //---//---
84:
85: #int_CCP1
86: void ccp1_int()
87: {
88: if (cuenta == 0)
89: {
90: captura1 = CCP_1;
91: cuenta = 1;
92: }
93: else
94: {
95: captura2 = CCP_1;
96: cuenta = 2;
97: }
98:
99: clear_interrupt(INT_CCP1);
100: }
101:
102: //---//---
103: //--- Función Principal ---//---
104: //---//---
105: void main()
106: {
107: //--- Declaración de variables locales
108: //Contadores para avanzar por las celdas de la EEPROM
109: int8 aux1 = 0;
110: int8 aux2 = 0;
111: int8 num_datos = 0;
112:
113: //--- Inicialización de variables
114: cuenta = 0; //Contador de capturas iniciado en 0
115:
116: //--- Saludo inicial
117: lcd_init();
118: lcd_gotoxy(1,1);
119: printf(lcd_putc, "ELECTRICIDAD");
120: printf(lcd_putc, "\nMICROS II");
121: delay_ms(200);
122:
123: //--- Configuración de pines de E/S
124: bit_set(TRISC,2); //Pin RC2 configurado como entrada
125: bit_set(TRISA,0); //Pin RA0 configurado como entrada
126:
127: //--- Configuración del ADC
128: setup_adc_ports(AN0); //Canal 0 analógico
129: setup_adc(ADC_CLOCK_DIV_8); //Fuente de reloj 8TOSC (TAD = 2us)
130:
131: //--- Configuración del Timer 1 y del módulo CCP ---//
132: //TMR1ON = 0; //Inhabilita temporalmente TMR1
133: setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); //Configuración del Timer 1
134: //TMR1IF = 0; //Borra bandera de int. del TMR1
2
C:\Users\ASUS TUF\OneDrive\Escritorio\Universidad de Cuenca\7moCiclo\Microprocesadores II\Ejem
135: setup_ccp1(CCP_CAPTURE_RE); //Configuración modo CAPTURA en flanco de subida
136: //CCP1IF = 0; //Borra bandera de int. del CCP
137: //Inhabilita temporalmente todas las interrupciones
138: disable_interrupts(INT_TIMER1); //No se utiliza, pero por seguridad
139: disable_interrupts(INT_CCP1);
140: disable_interrupts(GLOBAL);
141:
142: aux1 = DATOS_T;
143: aux2 = DATOS_RH;
144:
145: //--- Bucle de actividad infinito ---//
146: while(true)
147: {
148: //--- MEDICIÓN DE TEMPERATURA Y HUMEDAD RELATIVA ---//
149: TEMPERATURA();
150: HUMEDAD();
151: //---//
152:
153: //--- REGISTRO DE DATOS EN MEMORIA EEPROM ---//
154: if(num_datos <= DATOS_FIN)
155: {
156: //Define las direcciones donde se grabarán T y RH
157: aux1 = num_datos;
158: //Dirección para T
159: aux1 = (aux1 * 4) + DATOS_T;
160: //Dirección para RH
161: aux2 = aux1 + 1;
162:
163: //Graba los datos en la EEPROM
164: //Temperatura
165: write_eeprom(DATOS_T + aux1, sensor_lm35_lsb);
166: write_eeprom(DATOS_T + aux2, sensor_lm35_msb);
167: //Humedad relativa
168: write_eeprom(DATOS_RH + aux1, periodo_LSB);
169: write_eeprom(DATOS_RH + aux2, periodo_MSB);
170:
171: //Incrementa contador de número de datos grabados
172: num_datos++;
173: }
174: //---//
175:
176: //--- Visualización de resultados de las mediciones
177: lcd_gotoxy(1,1);
178: printf(lcd_putc, "HR = %2.1f %%", RH);
179: printf(lcd_putc, "\nTemp: = %1.1f oC", temp_g);
180:
181: //LED indicador para pruebas de funcionamiento
182: output_toggle(PIN_D0); //Led indicador
183:
184: //Periodo de muestreo (se puede implementar con un TIMER)
185: delay_ms(250);
186:
187: }
188: }
3
C:\Users\ASUS TUF\OneDrive\Escritorio\Universidad de Cuenca\7moCiclo\Microprocesadores II\Ejem
1: // FUNCIONES ESPECIALES PARA EL PROGRAMA
2: // PARA LAS MEDICIONES DE TEMPERATURA Y HUMEDAD RELATIVA
3:
4: void TEMPERATURA () //Medicion de temperatura ambiental
5: {
6: // Reinicio de variables
7: sensor_lm35 = 0;
8: sensor_lm35_lsb = 0;
9: sensor_lm35_msb = 0;
10:
11: // Conversion y lectura de la senal analogica
12: set_adc_channel(0); // Selecciona el canal AN0
13: delay_us(20); // Tiempo de adquisicion
14: sensor_lm35 = read_adc(); // Inicia la conversion y lee el resultado
15:
16: // Separa en 2 bytes la variable sensor_lm35
17: sensor_lm35_lsb = make8(sensor_lm35,0);
18: sensor_lm35_msb = make8(sensor_lm35,1);
19:
20: // Calculos
21: // Conversion a tension (10 bits, Vref = 5V)
22: temp_g = (5.0 * sensor_lm35) / 1024.0;
23: // Ecuacion del sistema de acondicionamiento de senal:
24: // Vout = 6.67*V1 + V2 => invertir la ecuacion del acondicionador
25: // (ajusta la ecuacion si tu acondicionador es diferente)
26: temp_g = ((temp_g - 1.0) / 6.67) / 0.01;
27: }
28:
29: void HUMEDAD () //Medicion de la humedad relativa
30: {
31: // Reinicio de variables
32: periodo = 0;
33: captura1 = 0;
34: captura2 = 0;
35: periodo_LSB = 0;
36: periodo_MSB = 0;
37:
38: // Pone timer1 a cero y borra bandera CCP1
39: set_timer1(0);
40: CCP1IF = 0; // borra posible bandera previa
41:
42: // Habilita interrupciones del CCP y globalmente
43: enable_interrupts(INT_CCP1); // habilita la interrupcion de CCP1
44: enable_interrupts(GLOBAL); // habilita interrupcion global
45:
46: cuenta = 0; // asegura que el contador inicie en 0
47:
48: // Espera las 2 capturas pero con timeout para evitar bloqueo infinito
49: // Ajusta el valor del timeout según tu velocidad de muestreo/periodo esperado
50: unsigned long timeout = 50000UL;
51: while ((cuenta != 2) && (timeout-- > 0))
52: {
53: timeout--; // busy-wait breve; la ISR debe incrementar 'cuenta'
54: // no pongas código pesado aquí para no interferir con la ISR
55: }
56:
57: // Si timeout llegó a 0, no hubo ambas capturas
58: if (cuenta != 2)
59: {
60: // Deshabilita la interrupcion si quedó habilitada
61: disable_interrupts(INT_CCP1);
62: // Establece valores por defecto para evitar división por cero
63: periodo = 0;
64: frecuencia = 0;
65: }
66: else
67: {
1
C:\Users\ASUS TUF\OneDrive\Escritorio\Universidad de Cuenca\7moCiclo\Microprocesadores II\Ejem
68: // Tenemos ambas capturas válidas
69: disable_interrupts(INT_CCP1); // deshabilita la interrupcion del modulo CCP
70: // Reinicia contador para la próxima medición
71: cuenta = 0;
72:
73: // Calcula periodo
74: periodo = captura2 - captura1; // resultado en ticks de timer1
75:
76: // Convierte periodo (ticks) a microsegundos si tu Timer1 está a 1MHz de tick
77: // --> en tu configuración T1_INTERNAL | T1_DIV_BY_1 con Fosc=4MHz, Tosc=250ns,
78: // Timer1 tick = 1 microsegundo si usas prescaler/uso adecuado. Ajusta si es necesar
79: // Aquí asumimos que 'periodo' está ya en us tal como tu comentario original.
80:
81: // Separa de 2 bytes la variable periodo
82: periodo_LSB = make8(periodo,0);
83: periodo_MSB = make8(periodo,1);
84:
85: if (periodo > 0)
86: {
87: // frecuencia en Hz; si periodo está en microsegundos:
88: frecuencia = (int16)((1.0 / (float)periodo) * 1000000.0);
89: }
90: else
91: {
92: frecuencia = 0;
93: }
94: }
95:
96: // Calculo de la humedad relativa en funcion de la frecuencia
97: // Ecuacion: RH = (7599 - frecuencia)/13.56 (Aproximacion lineal)
98: RH = (7599.00 - (float)frecuencia) / 13.56;
99: }
2
A B C D E F G H I J
0 VCC 0
R7 R8 C3
18k 12- 120k
22pF
2
U2 12+
1
X1
1
U3:B CRYSTAL
U1 R9 R10 1
U3:A
4
39.0 C4
1
13 33
8
OSC1/CLKIN RB0/INT 470 10k
R3(2) 6 RA0 14 34
OSC2/CLKOUT RB1
2 3 R4 7 35
VOUT RA0 RB2
1 5 22pF 2 36
RA0 RA0/AN0 RB3/PGM
2 18k 3
RA1/AN1 RB4
37 C2
R3 4
RA2/AN2/VREF-/CVREF RB5
38 4.7uF
8
3 LM35 100k 5 39
LM358N RA3/AN3/VREF+ RB6/PGC
4
6 40
LM358N RA4/T0CKI/C1OUT RB7/PGD
R6 7
2 RA5/AN4/SS/C2OUT
15 2
RC0/T1OSO/T1CKI
120k 8 16
RE0/AN5/RD RC1/T1OSI/CCP2
9 17
12- 12+ RE1/AN6/WR RC2/CCP1
10 18
RE2/AN7/CS RC3/SCK/SCL Sensor
R5 R1 23
VEE RC4/SDI/SDA
1 24
MCLR/Vpp/THV RC5/SDO
470 470 25
RC6/TX/CK
26
VCC RC7/RX/DT
3 19 RD0 3
12+ RD0/PSP0 RD1
C1 RD1/PSP1
20
1uF 21 RD2
RD2/PSP2 RD3
22
RV1 RD3/PSP3 RD4
U4:A 27
RD4/PSP4 RD5 RD[0..7]
28
8
RD5/PSP5 RD6
RV1(3) 29
RD6/PSP6 RD7
3 U4:A(OP) 30
21%
RD7/PSP7
1
2 PIC16F877A
4 4
1000k
4
LM358N
LCD1
12- LM016L
5 5
VDD
VSS
VEE
RW U5
RS
D0
D1
D2
D3
D4
D5
D6
D7
8
E
4 3
R11
VCC
R Q A
1
2
3
4
5
6
7
8
9
10
11
12
13
14
6 1k
6
7
DC B
RD1
RD2
RD3
RD4
RD5
RD6
RD7
Sensor
5
CV C
RD0
RD[0..7] D
GND
2 6
TR TH
D1 R13
7 LED-GREEN 1000k 7
1
NE555
C5
190pF
R2
470 R12
47k
8 82% 8
RV2
1000k
A B C D E F G H I J