You are on page 1of 24

Estoy creando un programa en C para recibir la temperatura de un sensor DS18B20, y mostrarlo en un glcd mediante un PIC 16F887.

La simulacion corre perfecta, pero a la hora de probarlo fisicamente, el glcd no hace mas que mostrarme 85.0 C, y no cambia. Alguien sabe porque puede ser? A continuacion adjunto el programa: Citar #include <termometro.h> #include <HDM64GS12.c> #include <graphics_1.c> #include <1wire.c> #include <ds1820.c> #include <eeprom.c>

int8 Pro[]= "PROYECTO"; int8 Ter[]= "TERMOMETRO"; float temperatura_antigua ; float temperatura_nueva ; char palabra [16],palabra2 [16]; int8 guar[]= "Guardando"; int8 tempe[]= "Temperatura"; int8 trans[]= "Transmitiendo..."; float resultado;

void main() { setup_comparator(NC_NC_NC_NC); // This device COMP currently not supported by the PICWizard

glcd_init(ON); delay_ms(20); glcd_rect(10,10,110,58,no,on); glcd_rect(18,18,68,28,no,on); glcd_rect(38,38,100,48,no,on); glcd_text57(20,20,Pro,1,on); glcd_text57(40,40,Ter,1,on); delay_ms(1500); glcd_fillScreen(0); glcd_rect(10,25,110,42,no,on);

while (1) {

temperatura_nueva = ds1820_read ();

// Se vuelve a leer el sensor y este valor se escribe // en una nueva variable

if (temperatura_nueva != temperatura_antigua){ glcd_rect(50,30,105,40,yes,OFF); sprintf(palabra,"TEMP = %3.1f &C",temperatura_nueva); glcd_text57(15, 30,palabra, 1, ON); temperatura_antigua = temperatura_nueva ; }

// Se compara la temperatura vieja con la nueva // Se borra la temperatura vieja // Se vuelve a crear un array de valores

if (input(PIN_A0)){ glcd_text57(2, 10,guar, 1, ON); glcd_text57(60, 10,tempe, 1, ON); guardar(temperatura_nueva,0); delay_ms(1500); glcd_rect(2,10,126,20,yes,off); } if (input(PIN_A1)){ glcd_text57(10,50,trans,1,on); delay_ms(1500); leer(resultado,0); sprintf(palabra2,"Temperatura = %f",resultado); printf (palabra2); glcd_rect(10,50,110,60,yes,off); } } }

Libreria DS18B20:
float ds1820_read() { int8 busy=0, temp1, temp2; signed int16 temp3; float result;

onewire_reset(); onewire_write(0xCC); onewire_write(0x44);

while (busy == 0) busy = onewire_read();

onewire_reset(); onewire_write(0xCC); onewire_write(0xBE); temp1 = onewire_read(); temp2 = onewire_read(); temp3 = make16(temp2, temp1);

//result = (float) temp3 / 2.0;

//Calculation for DS18S20 with 0.5 deg C resolution

result = (float) temp3 / 16.0; //Calculation for DS18B20 with 0.1 deg C resolution

delay_ms(200); return(result); }

Libreria 1wire:
// (C) copyright 2003 j.d.sandoz / jds-pic !at! losdos.dyndns.org // released under the GNU GENERAL PUBLIC LICENSE (GPL) // refer to http://www.gnu.org/licenses/gpl.txt // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA /***********************1Wire Class***********************/ /*Description: This class handles all communication */ /* between the processor and the 1wire */ /* sensors. /*********************************************************/ /*-------1-wire definitions-------*/ #define ONE_WIRE_PIN PIN_C2 /*******************1-wire communication functions********************/ /************onewire_reset*************************************************/ /*This function initiates the 1wire bus */ /* */ /*PARAMETERS: */ /*RETURNS: */ /*********************************************************************/ void onewire_reset() // OK if just using a single permanently connected device { output_low(ONE_WIRE_PIN); delay_us( 500 ); // pull 1-wire low for reset pulse output_float(ONE_WIRE_PIN); // float 1-wire high delay_us( 500 ); // wait-out remaining initialisation window. output_float(ONE_WIRE_PIN); } /*********************** onewire_write() ********************************/ /*This function writes a byte to the sensor.*/ /* */ /*Parameters: byte - the byte to be written to the 1-wire */ /*Returns: */ /*********************************************************************/ void onewire_write(int data)

{ int count; for (count=0; count<8; ++count) { output_low(ONE_WIRE_PIN); delay_us( 2 ); // pull 1-wire low to initiate write time-slot. output_bit(ONE_WIRE_PIN, shift_right(&data,1,0)); // set output bit on 1-wire delay_us( 60 ); // wait until end of write slot. output_float(ONE_WIRE_PIN); // set 1-wire high again, delay_us( 2 ); // for more than 1us minimum. } } /*********************** read1wire() *********************************/ /*This function reads the 8 -bit data via the 1-wire sensor. */ /* */ /*Parameters: */ /*Returns: 8-bit (1-byte) data from sensor */ /*********************************************************************/ int onewire_read() { int count, data; for (count=0; count<8; ++count) { output_low(ONE_WIRE_PIN); delay_us( 2 ); // pull 1-wire low to initiate read time-slot. output_float(ONE_WIRE_PIN); // now let 1-wire float high, delay_us( 8 ); // let device state stabilise, shift_right(&data,1,input(ONE_WIRE_PIN)); // and load result. delay_us( 120 ); // wait until end of read slot. } return( data ); }

PIC C, CCS, Interfacing with a Dallas DS1820 Thermometer


Overview In routine 1820_1.C a temperature measurement is made on RB.0, RB.1, RB.2 and RB.3. For each measurement, all nine bytes are stored in array buff and displayed on the serial LCD. Note that on terminals other than RB.0, the temperature (the first two bytes) is falsely reported as zero. This suggest a problem with the strong pullup routine where a hard logic one is maintained on DQ for 250 ms. However, I don't see the problem. If you find it, please let me know. In routine 1820_2.C the 8-byte ROM address of the DS1820 is fetched and saved to the 16F84's EEPROM and displayed on the LCD display. The ROM address is then fetched and the DS1820 is addressed (match ROM), a temperature measurement is performed and the nine bytes are displayed on the LCD In routine 1820_3.C, a temperature measurement (Skip ROM) is performed and the nine bytes are displayed. A cyclic redundancy check is then performed on the nine bytes and the result is displayed. Note that the CRC should be 0x00. More discussion of the CRC algorithm appears on my main PIC page.
// 1820_1.C, CCS - PCM (PIC16F84) // // Illustrates an implementation of Dallas 1-wire interface. // (Ilustra una implementacin de interfaz de 1 alambre Dallas) // // // // // // Configuration. DS1820 on RB.0, RB.1, RB.2 and RB.3. Note a 4.7K pullup to +5V is required. DS1820s configured in parasite power mode. That is, VCC connected to ground. (La configuracin. El DS1820 en RB.0, RB.1, RB.2 y RB.3. Note un 4.7K el pullup para +5V es requerido.Los DS1820s configurados en parsito impulsan modo.

es decir, VCC se conect a la tierra.)

// Reads and displays nine bytes from each device in turn and displays // the result on serial LCD connected to RA.0. //( el resultado en LCD serial se conect al RA.0.) // Bug. Temperature (first two bytes) is zero on RB.1, RB.2 and RB.3 // // copyright, Peter H. Anderson, Baltimore, MD, April, '99 #include <16f84.h> #include <string.h> #include <defs_f84.h> #define MAX_SENSORS 4 // 1-wire prototypes void _1w_init(int sensor); int _1w_in_byte(int sensor); void _1w_out_byte(int d, int sensor); void _1w_pin_hi(int sensor); void _1w_pin_low(int sensor); void _1w_strong_pull_up(int sensor); // not used in this routine // delay routines void delay_ms(long t); void delay_10us(int t); // LCD routines void lcd_init(void); void out_RAM_str(int *s); void lcd_hex_byte(int val); void lcd_dec_byte(int val, int digits);

int num_to_char(int val); void lcd_char(int ch); void lcd_new_line(void); #define TxData 0 // output to serial LCD

void main(void) { int buff[9], sensor, n; for (sensor=0; sensor<MAX_SENSORS; sensor++) { _1w_init(sensor); _1w_out_byte(0xcc, sensor); // skip ROM _1w_out_byte(0x44, sensor); _1w_strong_pull_up(sensor); _1w_init(sensor); _1w_out_byte(0xcc, sensor); _1w_out_byte(0xbe, sensor); // perform temperature conversion

// skip ROM // read the result

for (n=0; n<9; n++) { buff[n]=_1w_in_byte(sensor); } lcd_init(); lcd_hex_byte(sensor); lcd_new_line(); // display the sensor number

for (n=0; n<4; n++) // display 4 bytes { lcd_hex_byte(buff[n]); lcd_char(' '); } lcd_new_line(); for (n=4; n<9; n++) // displays the other 5 bytes { lcd_hex_byte(buff[n]); lcd_char(' '); } lcd_new_line(); } } // The following are standard 1-Wire routines. void _1w_init(int sensor) { _1w_pin_hi(sensor); _1w_pin_low(sensor); delay_10us(50); _1w_pin_hi(sensor); delay_10us(50); delay_ms(1000);

int _1w_in_byte(int sensor) { int n, i_byte, temp, mask; mask = 0xff & (~(0x01<<sensor)); for (n=0; n<8; n++) {

PORTB=0x00; TRISB=mask; TRISB=0xff; #asm CLRWDT NOP NOP #endasm temp=PORTB; if (temp & ~mask) { i_byte=(i_byte>>1) | 0x80; } else { i_byte=i_byte >> 1; } delay_10us(6); } return(i_byte); }

// least sig bit first

void _1w_out_byte(int d, int sensor) { int n, mask; mask = 0xff & (~(0x01<<sensor)); for(n=0; n<8; n++) { if (d&0x01) { PORTB=0; TRISB=mask; // momentary low TRISB=0xff; delay_10us(6); } else {

} }

} d=d>>1;

PORTB=0; TRISB=mask; delay_10us(6); TRISB=0xff;

void _1w_pin_hi(int sensor) { TRISB = 0xff; } void _1w_pin_low(int sensor) { PORTB = 0x00; TRISB = 0xff & (~(0x01 << sensor)); } void _1w_strong_pull_up(int sensor) // bring DQ to strong +5VDC { PORTB = 0x01 << sensor; TRISB = 0xff & (~(0x01 << sensor)); delay_ms(250); TRISB = 0xff; } // delay routines void delay_10us(int t)

{ #asm

BCF STATUS, RP0 DELAY_10US_1: CLRWDT NOP NOP NOP NOP NOP NOP DECFSZ t, F GOTO DELAY_10US_1 #endasm } void delay_ms(long t) { do { delay_10us(100); } while(--t); } // delays t millisecs

// LCD routines int num_to_char(int val) { int ch; if (val < 10) { ch=val+'0'; } else { val=val-10; ch=val + 'A'; } return(ch); }

// converts val to hex character

void lcd_char(int ch) // serial output to PIC-n-LCD, 9600 baud { int n, dly; // start bit + 8 data bits #asm BCF STATUS, RP0 MOVLW 9 MOVWF n BCF STATUS, C

LCD_CHAR_1: BTFSS STATUS, C BSF PORTA, TxData BTFSC STATUS, C BCF PORTA, TxData MOVLW 32 MOVWF dly LCD_CHAR_2: DECFSZ dly, F GOTO LCD_CHAR_2 RRF ch, F DECFSZ n, F GOTO LCD_CHAR_1 BCF PORTA, TxData

CLRWDT MOVLW 96 MOVWF dly LCD_CHAR_3: DECFSZ dly, F GOTO LCD_CHAR_3 CLRWDT #endasm } void lcd_init(void) // sets TxData in idle state and resets PIC-n-LCD { #asm BCF STATUS, RP0 BCF PORTA, TxData BSF STATUS, RP0 BCF TRISA, TxData BCF STATUS, RP0 #endasm lcd_char(0x0c); delay_ms(250); } void lcd_new_line(void) // outputs 0x0d, 0x0a { lcd_char(0x0d); delay_ms(10); // give the PIC-n-LCD time to perform the lcd_char(0x0a); // new line function delay_ms(10); } void out_RAM_str(int s) { while(*s) { lcd_char(*s); ++s; } } void lcd_hex_byte(int val) // displays val in hex format { int ch; ch = num_to_char((val>>4) & 0x0f); lcd_char(ch); ch = num_to_char(val&0x0f); lcd_char(ch); } void lcd_dec_byte(int val, int digits) // displays byte in decimal as either 1, 2 or 3 digits { int d; int ch; if (digits == 3) { d=val/100; ch=num_to_char(d); lcd_char(ch); } if (digits >1) // take the two lowest digits { val=val%100; d=val/10; ch=num_to_char(d); lcd_char(ch); } if (digits == 1) // take the least significant digit { val = val%100; } d=val % 10;

} // // // // // // // // // // // // // // // //

ch=num_to_char(d); lcd_char(ch); Program 1820_2.C Reads 64-bit address from DS1820, saves to the 16F84's EEPROM and displays it on serial LCD. Uses 64-bit address to perform temperature measurement. is displayed on serial LCD Data is

16F84 DS1820 PortB.0 (term 6) ------------------------------ DQ (term 2) PORTA, Bit 0 (terminal 17) ------ TX ----------> to RX on Serial LCD copyright, Peter H. Anderson, Baltimore, MD, Apr, 99

#case #include <16f84.h> #include <string.h> #include <defs_f84.h> void display_lcd(int *d, int num_vals); void get_16f84_eeprom(int adr, int *d, int num_vals); void put_16f84_eeprom(int adr, int *d, int num_vals); void write_16f84_eeprom(int adr, int d); int read_16f84_eeprom(int adr); void ds1820_read_rom(int *d, int sensor); void make_temperature_meas(int *adr, int *d, int sensor); // 1-wire prototypes void _1w_init(int sensor); int _1w_in_byte(int sensor); void _1w_out_byte(int d, int sensor); void _1w_pin_hi(int sensor); void _1w_pin_low(int sensor); void _1w_strong_pull_up(int sensor); // not used in this routine // delay routines void delay_ms(long t); void delay_10us(int t); // LCD routines void lcd_init(void); void out_RAM_str(int *s); void lcd_hex_byte(int val); void lcd_dec_byte(int val, int digits); int num_to_char(int val); void lcd_char(int ch); void lcd_new_line(void); #define TxData 0 void main(void) { int dev_adr[8], t_dat[9]; lcd_init(); ds1820_read_rom(dev_adr, 0); // read serial number from DS1820 display_lcd(dev_adr, 8); // display the result on LCD put_16f84_eeprom(0x00, dev_adr, 8); // save to eeprom, beginning at adr 0x00, 8 bytes

// temporary storage

// now fetch the serial number, address and perform a temperature // measurment get_16f84_eeprom(0x00, dev_adr, 8); // fetch from 16F84, 8 bytes and return in array d make_temperature_meas(dev_adr, t_dat, 0); display_lcd(t_dat, 9); // display the 9 byte result #asm DONE: clrwdt GOTO DONE #endasm } void display_lcd(int *d, int num_vals) { int n; for (n=0; n<num_vals; n++) { if ((n%4==0) && (n!=0)) { lcd_new_line(); } lcd_hex_byte(d[n]); lcd_char(' '); } lcd_new_line(); } void put_16f84_eeprom(int adr, int *d, int num_vals) { int n; for(n=0; n<num_vals; n++, adr++) { write_16f84_eeprom(adr, d[n]); } } void get_16f84_eeprom(int adr, int *d, int num_vals) { int n; for(n=0; n<num_vals; n++, adr++) { d[n]=read_16f84_eeprom(adr); } } void write_16f84_eeprom(int adr, int d) { EEADR = adr; EEDATA = d; wren = 1; EECON2 = 0x55; EECON2 = 0xaa; wr = 1; delay_ms(20); wren = 0; } int read_16f84_eeprom(int adr) { EEADR=adr; rd=1; // set the read bit // protection sequence // begin programming sequence // disable write enable

return(EEDATA); } void ds1820_read_rom(int *d, int sensor) { int n; _1w_init(sensor); _1w_out_byte(0x33, sensor); for(n=0; n<8; n++) { d[n]=_1w_in_byte(sensor); } } void make_temperature_meas(int *adr, int *d, int sensor) { int n; _1w_init(sensor); _1w_out_byte(0x55, sensor); // match ROM for(n=0; n<8; n++) // followed by the 8-byte ROM address { _1w_out_byte(adr[n], sensor); } _1w_out_byte(0x44, sensor); // start temperature conversion _1w_strong_pull_up(sensor); _1w_init(sensor); _1w_out_byte(0x55, sensor); // match ROM for(n=0; n<8; n++) // followed by the 8-byte ROM address { _1w_out_byte(adr[n], sensor); } _1w_out_byte(0xbe, sensor); for(n=0; n<9; n++) { d[n]=_1w_in_byte(sensor); }

// // // // // // // // //

1-Wire, delay and LCD routines are the same as 1820_1.C 1820_3.C Cyclic redudancy check (CRC). Makes measurement and displays the nine values on serial LCD. Then calculates CRC and displays. copyright, Peter H. Anderson, Baltimore, MD, Apr, '99

#case #include <16f84.h> #include <string.h> #include <defs_f84.h> int calc_crc(int *buff, int num_vals); // 1-wire prototypes void _1w_init(int sensor); int _1w_in_byte(int sensor); void _1w_out_byte(int d, int sensor); void _1w_pin_hi(int sensor); void _1w_pin_low(int sensor); void _1w_strong_pull_up(int sensor); // delay routines void delay_ms(long t); void delay_10us(int t); // LCD routines void lcd_init(void); void out_RAM_str(int *s); void lcd_hex_byte(int val); void lcd_dec_byte(int val, int digits); int num_to_char(int val); void lcd_char(int ch); void lcd_new_line(void); #define TxData 0 void main(void) { int buff[9], sensor=0, crc, n; _1w_init(sensor); _1w_out_byte(0xcc, sensor); _1w_out_byte(0x44, sensor); _1w_strong_pull_up(sensor); _1w_init(sensor); _1w_out_byte(0xcc, sensor); _1w_out_byte(0xbe, sensor); for (n=0; n<9; n++) { buff[n]=_1w_in_byte(sensor); } lcd_init(); for (n=0; n<4; n++) { lcd_hex_byte(buff[n]); lcd_char(' '); // skip ROM // perform temperature conversion

// skip ROM

} lcd_new_line(); for (n=4; n<9; n++) { lcd_hex_byte(buff[n]); lcd_char(' '); } lcd_new_line(); crc = calc_crc(buff, 9); lcd_hex_byte(crc); lcd_new_line(); delay_ms(500); } int calc_crc(int *buff, int num_vals) { int shift_reg=0, data_bit, sr_lsb, fb_bit, i, j; for (i=0; i<num_vals; i++) // for each byte { for(j=0; j<8; j++) // for each bit { data_bit = (buff[i]>>j)&0x01; sr_lsb = shift_reg & 0x01; fb_bit = (data_bit ^ sr_lsb) & 0x01; shift_reg = shift_reg >> 1; if (fb_bit) { shift_reg = shift_reg ^ 0x8c; } } } return(shift_reg); } // 1_Wire, delay and LCD routines are the same as in 1820_1.c

Hola, aqui os dejo una libreria en CCS para el sensor de temperatura DS1820, la pega es que consume mucha memoria, si alguien conoce una libreria mejor que la pegue.

//////////////////////////////////////////////////////////////////////////// //// Library for a Dallas 1820 Temperature chip //// //// //// //// init_temp(); Call before the other functions are used //// //// //// //// //// //// d = read_full_temp(); Read the temp in degrees C (0 to 125) //// //// //// //////////////////////////////////////////////////////////////////////////// #ifndef DS1820_PIN #define DS1820_PIN #endif

PIN_B0

#define TOUCH_PIN DS1820_PIN #include "touch.c" void init_temp() { } float read_full_temp() { byte i, buffer[9]; float minstep; if (touch_present()) { touch_write_byte(0xCC); touch_write_byte (0x44); delay_ms(200); touch_present(); touch_write_byte(0xCC); touch_write_byte (0xBE); // // // // // // // get present (reset) Skip ROM Start Conversion delay 200 ms get present (reset) Skip ROM Read Scratch Pad (2) (3) (4) (5) (6) (7)

for(i=0; i<9;i++) // read 9 bytes buffer[i] = touch_read_byte(); }

//minstep = (float)(buffer[0]/2)-0.25+((float)( buffer[7]-buffer[6])/buffer[7]); if(buffer[1]){ minstep = (float)(-1)*(~make16(buffer[1],buffer[0])+1)/2; }else{ minstep = (float)(make16(buffer[1],buffer[0])/2); } minstep = minstep - 0.25 + ((float)( buffer[7] - buffer[6])/buffer[7]); return (minstep); }

Ejemplo de uso:

#include <16F876.h> //Standard header file #fuses NOWDT,HS, NOPUT, NOPROTECT,NOLVP,BROWNOUT //Oscillator mode HS #use delay(clock=20000000) //Clock speed HZ = 20MHZ #define use_portd_lcd //define for use port d lcd #define DS1820_PIN #include "lcd.c" #include "ds1820.c" void main() { float minstep; int16 a; int b; lcd_init(); do { minstep = read_full_temp(); printf (lcd_putc,"\fTemp :%3.2f C", minstep); delay_ms(1000); } while (TRUE); PIN_A2 #define use_portb_lcd TRUE

A CONTINUACIN PONGO EL CDIGO DE UN CIRCUITO QUE SENSA LA TEMPERATURA DE DOS SENSORES CUANDO LA TEMPERATURA SE PASA DEL RANGO -1 Y 8 ENCIENDE UNOS LEDS DESPUS DE 5 SEG. EN SEAL DE ALARMA, LA TEMPERATURA SENSADA ME LA MUESTRA EN UNA LCD, LO QUE NECESITO AHORA ES QUE LA TEMPERATURA ME LA MUESTRE EN DISPLAYS DE 7 SEGMENTOS ANODO COMN, PERO LA VERDAD NO TENGO IDEA DE COMO HACERLO, ESPERO ME PUEDEN AYUDAR COMO SE HARA EL CDIGO: A CONTINUACIN EL CDIGO CON LA LCD: #include "C:\Users\G\Documents\.Docs GFT\TRABAJOS(pic)\Termometros\sensores.h" #define LCD_TYPE 2 #include <lcd.c> double SEN,SEN2; int16 segundos=0; char grados=0xDF; #define alarma PIN_B0 #define luz PIN_B1 #define sensor1_pos 0 //pin A0 #define sensor1_neg 1 //pin A1 #define sensor2_pos 2 //pin A2 #define sensor2_neg 4 //pin A5 void leer_sen1(void) { set_adc_channel(sensor1_pos); //selecciona el terminal positivo del sensor 1 delay_us(100); SEN=read_adc(); //lo lee y guarda en SEN set_adc_channel(sensor1_neg); //selecciona terminal negativo delay_us(100); SEN=SEN-(read_adc()); //lo lee y lo resta de la lectura } void leer_sen2(void) { set_adc_channel(sensor2_pos); delay_us(100); SEN2=read_adc(); set_adc_channel(sensor2_neg); delay_us(100); SEN2=SEN2-(read_adc()); } void main() { lcd_init(); setup_adc_ports(AN0_AN1_AN2_AN4_VSS_VREF); setup_adc(ADC_CLOCK_DIV_64); setup_psp(PSP_DISABLED); setup_spi(SPI_SS_DISABLED); setup_wdt(WDT_OFF); setup_timer_0(RTCC_INTERNAL); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DISABLED,0,1); lcd_gotoxy(2,1); printf(lcd_putc,"REFRI1:"); lcd_gotoxy(2,2); printf(lcd_putc,"REFRI2:"); while(true)

{ leer_sen1(); // toma la lectura del sensor1 ya sea psitiva o negativa lcd_gotoxy(9,1); // Y LO MUESTRA EN EL LCD printf(lcd_putc," %2.1f%cC",SEN,grados); leer_sen2(); //toma la lectura del sensor2 ya sea positiva o negativa lcd_gotoxy(9,2); // Y LO MUESTRA EN LCD printf(lcd_putc," %2.1f%cC",SEN2,grados); if(((SEN>8)|(SEN<-1))|((SEN2>8)|(SEN2<-1))) // si SEN y SEN2 superan 8 grados o bajan de -1 entonces { segundos++; // se incrementa el contador de segundos y if(segundos==5) // se pregunta si ha llegado a X segundos, seria 900) { while(true) { output_high(alarma);// si segundos ha llegado a 5 encender alarma output_high(luz); delay_ms(250); output_low(alarma); output_low(luz); delay_ms(250); } } } else { segundos=0; // resetea la cuenta de segundos output_low(alarma); // y apaga la alarma si es que ya hubiera sido activada output_low(luz); } delay_ms(1000); // simple retardo de 1 segundo sin usar timer ni interrupciones } }

Buenas noches, en pregunta de algunos sobre sensores, posteare un control de temperatura muy sencillo, esta basado en la lectura de un sensor de temperatura el famoso LM35 y la salida la entrega en dos displays de 7 segmentos. Explico: #include <18f452.h> //Mc a utilizar #include <STDIO.h> //librera para hacer operaciones matemticas #fuses hs,nowdt,noprotect,nolvp //High speed, sin perro guardian, no pretegido, no bajo voltaje. #use delay(clock=4000000,RESTART_WDT) //reloj a 4 MHz #byte porta=0xf80 #byte portb=0xf81 #byte portc=0xf82 // Cambiando nombres a los puertos #byte portd=0xf83 #byte porte=0xf84 void main() // Deja de leer todo lo primero y vamonos a: { int const disp [10] = /*{0x3f, 0x06, 0x5b, 0x4f,0x66, //declaramos los vectores para el display (Catodo Comn) 0x6d, 0x7d, 0x07, 0x7f, 0x6f};*/ {0x40, 0x79, 0x24,0x30, 0x19, //declaramos los vectores para el display (Anodo Comn) 0x12, 0x02, 0x78, 0x00, 0x18}; int uni,dec,multi,k; //Variables para los displays y k como retardo int b=1; // Bandera lgica int a=1; //Bandera lgica float temp,temperatura; //Variables para las operaciones y as obtener la temperatura dentro del PIC float dato; SETUP_TIMER_2(t2_div_by_16,200,10); //definimos el Timer 2 enable_interrupts(GLOBAL); //Activamos las interrupciones globales setup_adc_ports(2); //nmero de puertos ADC, puse 2 porque aveces conecto otro sensor y sacar promedios. setup_adc(adc_clock_div_32); //Configuracin de los ADC set_adc_channel(0); //Activamos el ADC 0 delay_us(10); //Esperamos 10 microsegundos set_tris_B(0x00); set_tris_C(0x80); //Configuracin de puertos.

set_tris_D(0x00); portb=0; //Limpiamos el puerto b, que es donde estan conectados los displays de 7 segmentos.

while (TRUE) //Programa { dato = read_adc(); //Leemos el ADC y metemos el valor a la variable dato read_adc(ADC_START_ONLY); //decirle al pic que solo y nicamente lea el ADC para una buena lectura dato = read_adc(ADC_READ_ONLY); //meter de nuevo el valor a dato para corroborar temp = (0.0196078*dato); //porqu 0.0196078? 5 volts entre 255 (recordemos que estamos trabajando con 8 bytes del ADC) nos da ese numero, o sea conversion de Analgico a digital. multi = temp*100; //multiplicamos por 100 para tener la temperatura real entre 10. dec = multi/10; //Con esta operacin solo tengo el dato de las decenas uni = multi%10; //Con esta solo tengo el dato de las unidades en una variable temperatura = temp * 100; //Temperatura con el valor verdadero. // Control para encender o apgar un ventilador o una bomba if(temperatura > 29 && a==0) //Se activa D2 (Ventilador) { b=1; output_high(PIN_D2); output_low(PIN_D1); } if(temperatura <= 29 && temperatura >= 27) //Todo esta inactivo { b=1; output_low(PIN_D2); output_low(PIN_D1); } if(temperatura < 27 && b==0) //Se activa D1 (Calentador) { a=1; output_low(PIN_D2); output_high(PIN_D1); } if(temperatura < 25) { b=0; } if(temperatura > 31) {

a=0; } //Para mostrar la temperatura en dos Displays de 7 segmentos, recordemos que los displays son multiplexados, primero prende uno y despus el otro tan rapido que no alcanzamos a percibirlo, esto se logra con un transistor, si hay duda en esto, me dara a la tarea de subir el diagrama, pero el multiplexeo se hace con la patita B7, las dems son las que van conectadas con su respectiva resistencia a los displays de 7 segmentos. Explico: for (k=0;k<=50;k++) //Variable k me permite crear ciclos con la orden "for" para el multiplexeo y aparte tiempo al PIC para que piense. { portb=disp[uni]; Le digo al pic que me arroje el dato de "uni" al vector "disp" para mostrar las unidades en los displays. delay_ms(10); //Retardo de 10 ms y se apaga. portb=disp[dec] + 0x80; // le digo al pic que me arroje el dato de "dec" al vector "disp" y que mande un 1 (5 volts) a la patita B7 para que se encienda todo el display de las decenas. delay_ms(5); //Dura 5 ms prendido y se apaga } //Volvemos a empezar el ciclo for infinitamente, ya que la variable al alcanzar las 51 cuentas, vuelve a leer el pic y se vuelve a hacer 0. } } Bueno espero que haya quedado claro como leer un sensor y mostrarlo en displays de 7 segmentos en este caso solo 2, si se necesitan 4 displays, se ocupa un poco mas de electrnica para lograrlo sin desperdiciar patitas del PIC, muy sencillo. Estamos para ayudar y ensear...

QUE TAL DE NUEVO, YA CONSEGU EL PROTEUS 7.6, TENAS RAZN CON ESTA VERSIN YA NO TUVE PROBLEMAS A LA HORA DE LA SIMULACIN CON LOS LM35, MUCHAS GRACIAS. YA TENGO LOS DOS SENSORES FUNCIONANDO, SOLO QUE HAY UN DETALLE, LA ALARMA SE ACTIVA SLO CUANDO LOS DOS SENSORES SE SALEN DEL RANGO, Y LO QUE REQUIERO ES QUE SE ACTIVE CUANDO CUALQUIERA DE LOS DOS SE SALGA DEL RANGO, LO MS QUE PUDE LOGRAR ES QUE MET UN WHILE ANTES DEL LTIMO IF Y SI FUNCION PERO SOLAMENTE CUANDO EL SENSOR 1 SE SALE DEL RANGO, CUANDO EL SENSOR DOS SE SALE NO PASA NADA. Y SI QUITO EL WHILE SUCEDE LO DEL PRINCIPIO, ADEMS QUE CUANDO AGREGU EL WHILE SI FUNCIONA LA SIMULACIN PERO ME SALEN VARIOS MENSAJES DE ADVERTENCIA CON LA SIGUIENTE LEYENDA: "[PIC18ADC]PC=0x0854.ADC conversion started before 'wait' time has expired following previous conversion or channel change. A CONTINUACIN PONGO EL CDIGO: #include "C:\Users\G\Documents\Docs GFT\TRABAJOS\term.h" #define LCD_TYPE 2 #include <lcd.c> double SEN,SEN2; int16 segundos=0; #define alarma PIN_B0 #define luz PIN_B1 #define sensor1_pos 0 //pin A0 #define sensor1_neg 1 //pin A1 #define sensor2_pos 2 //pin A2 #define sensor2_neg 4 //pin A5 void leer_sen1(void) { set_adc_channel(sensor1_pos); //selecciona el terminal positivo delay_us(10); //del sensor 1 SEN=read_adc(); //y lo lee y guarda en SEN set_adc_channel(sensor1_neg); //selecciona terminal negativo delay_us(10); SEN=SEN-(read_adc()); //lo lee y lo resta de la lectura } void leer_sen2(void) {

set_adc_channel(sensor2_pos); delay_us(10); SEN2=read_adc(); set_adc_channel(sensor2_neg); delay_us(10); SEN2=SEN2-(read_adc()); } void main() { lcd_init(); setup_adc_ports(AN0_AN1_AN2_AN4_VSS_VREF); setup_adc(ADC_CLOCK_DIV_64); setup_psp(PSP_DISABLED); setup_spi(SPI_SS_DISABLED); setup_wdt(WDT_OFF); setup_timer_0(RTCC_INTERNAL); setup_timer_1(T1_DISABLED); setup_timer_2(T2_DISABLED,0,1); lcd_gotoxy(2,1); printf(lcd_putc,"REFRI1:"); lcd_gotoxy(2,2); printf(lcd_putc,"REFRI2:"); while(true) { leer_sen1(); // toma la lectura del sensor1 ya sea positiva o negativa lcd_gotoxy(9,1); // Y LO MUESTRA EN EL LCD printf(lcd_putc," %2.1f'C",SEN); leer_sen2(); //toma la lectura del sensor2 ya sea positiva o negativa lcd_gotoxy(9,2); // Y LO MUESTRA EN LCD printf(lcd_putc," %2.1f'C",SEN2);

if( (SEN>8) | (SEN<-1) ){ // si SEN supera 8 grados o baja de -1 entonces segundos++; // se incrementa el contador de segundos y if(segundos==5){ // se pregunta si ha llegado a 5 output_high(alarma); // si segundos ha llegado a 5 encender alarma output_high(luz); } }

else{ segundos=0; // resetea la cuenta de segundos output_low(alarma); // y apaga la alarma si es que ya hubiera sido activada output_low(luz); } delay_ms(1000); // simple retardo de 1 segundo sin usar timer ni interrupciones //WHILE(TRUE) CUANDO PONGO ESTE WHILE FUNCIONA UNICAMENTE EL SENSOR 1 //{if( (SEN2>8) | (SEN2<-1) ){ // si SEN2 supera 8 grados o baja de -1 entonces segundos++; // se incrementa el contador de segundos y if(segundos==5){ // se pregunta si ha llegado a 5 segundos output_high(alarma); // si segundos ha llegado a 5 encender alarma output_high(luz); } } else{ segundos=0; // resetea la cuenta de segundos output_low(alarma); // y apaga la alarma si es que ya hubiera sido activada output_low(luz); } delay_ms(1000); } } ESPERO ME PUEDAN AYUDAR Y ME DIGAN EN QUE ESTOY MAL, O QU ME FALTA AGREGARLE O QUITARLE,, TAMBIEN MANDO LA SIMULACIN:

You might also like