|
|
View previous topic :: View next topic |
Author |
Message |
MANEL Guest
|
Read temperature maximum minimum ds1624 |
Posted: Thu Dec 08, 2005 2:31 pm |
|
|
Hi. I've had a circuit with PIC16f877 <--> Ds1624 connected by means I2C. The temperature is OK but the problem is that spent a certain time the temperature is sleep, is always the same one and it does not change although it changes the temperature of the surroundings. also I have a problem with the temperature minimum, the algorithm that I have created not shows minimum but 0ºC always. Somebody finds the problem ?
The program:
#include <16f877.h>
#use delay (clock=4000000)
#use I2C(MASTER, SDA=PIN_C4, SCL=PIN_C3, fast)
#use fast_io(A)
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD
#include <lcd_lolo.c>
#define simbolo_grados 0b11011111
#define simbolo_coma 0b00101100
#define I2CWRITE 0b10010000
#define I2CREAD 0b10010001
#define I2CREAD2 0b10010011
#define DS1624_CMD_ACCESSCONFIG 0xAC
#define DS1624_CMD_INITIATECONVERT 0xEE
#define DS1624_CMD_ACCESSTEMPERATURE 0xAA
#define DS1624_CMD_ACCESSMEMORY 0x17
# byte port_a=6
int datah, datal;
void i2c_conversion()
{
i2c_start();
i2c_write(I2CWRITE);
i2c_write(DS1624_CMD_INITIATECONVERT);
i2c_stop();
}
void i2c_ds1624_inicia()
{
i2c_start();
i2c_write(I2CWRITE);
i2c_write(DS1624_CMD_ACCESSCONFIG);
i2c_write(0b01001011);
i2c_stop();
delay_ms(20);
i2c_conversion();
}
void i2c_ds1624_leer_temp_c()
{
i2c_start();
i2c_write(I2CWRITE);
i2c_write(DS1624_CMD_ACCESSTEMPERATURE);
i2c_start();
i2c_write(I2CREAD);
datah=i2c_read();
datal=i2c_read(0);
i2c_stop();
i2c_ds1624_inicia();
}
int read_ext_eeprom(int address)
{
int data;
i2c_start();
i2c_write(0x90);
i2c_write(0x17);
i2c_write(address);
i2c_start();
i2c_write(0x91);
data=i2c_read();
i2c_stop();
return data;
}
void write_ext_eeprom(int address, int data)
{
i2c_start();
i2c_write(0x90);
i2c_write(0x17);
i2c_write(address);
i2c_write(data);
i2c_stop();
delay_ms(50);
}
void main (void)
{
int temperatura;
int dec,decimal,max, maxd, auxi,auxi2,mini,mind,contador,conta,minimo;
lcd_inicia();
i2c_ds1624_inicia();
set_tris_a(0b111110);
lcd_ponc("\f");
port_a=0;
max=0;
maxd=0;
auxi=0;
mini=5;
mind=99;
auxi2=50;
contador=0;
conta=0;
while(1)
{
contador=contador+1;
if (conta<50) conta=conta+1;
i2c_ds1624_leer_temp_c();
lcd_ponc("\f");
switch(datal)
{
case 248: dec=98; break;
case 240: dec=94; break;
case 232: dec=90; break;
case 224: dec=87; break;
case 216: dec=83; break;
case 208: dec=80; break;
case 200: dec=77; break;
case 192: dec=75; break;
case 184: dec=72; break;
case 176: dec=70; break;
case 168: dec=68; break;
case 160: dec=66; break;
case 152: dec=62; break;
case 144: dec=60; break;
case 136: dec=58; break;
case 128: dec=55; break;
case 120: dec=53; break;
case 112: dec=50; break;
case 104: dec=48; break;
case 96: dec=44; break;
case 88: dec=40; break;
case 80: dec=37; break;
case 72: dec=34; break;
case 64: dec=30; break;
case 56: dec=28; break;
case 48: dec=23; break;
case 40: dec=20; break;
case 32: dec=17; break;
case 24: dec=13; break;
case 16: dec=10; break;
case 8: dec=05; break;
case 0: dec=0; break;
}
lcd_vaixy(1,1);
if (datah>max) max= datah;
if ((dec> maxd) && (auxi<=max))
{
maxd=dec;
auxi=max;
}
if ((dec<= maxd) && (auxi<max))
{
maxd=dec;
auxi=max;
}
if ((dec< mind) && (auxi2>=mini))
{
mind=dec;
auxi2=mini;
mini=datah;
}
if ((dec>= mind) && (auxi2>mini))
{
mind=dec;
auxi2=mini;
}
printf(lcd_ponc,"T= %d%2d%cC",datah,simbolo_coma,dec,simbolo_grados);
lcd_vaixy(1,2);
if (contador<100)
printf(lcd_ponc,"TMax=%d%c%2d%cC",max,simbolo_coma,maxd,simbolo_grados);
if (contador>=100)
printf(lcd_ponc,"TMin=%d%c%2d%cC",mini,simbolo_coma,mind,simbolo_grados);
if (contador>200) contador=0;
if (datah>20) output_high (PIN_A0);
if (datah<=20) output_low (PIN_A0);
}
} |
|
|
jds-pic
Joined: 17 Sep 2003 Posts: 205
|
|
Posted: Fri Dec 09, 2005 2:20 pm |
|
|
(double posted; content in next post)
Last edited by jds-pic on Fri Dec 09, 2005 2:22 pm; edited 1 time in total |
|
|
Guest
|
|
Posted: Fri Dec 09, 2005 2:21 pm |
|
|
MANEL,
(note use of "Code" button below; makes reading much easier)
you are doing a lot of work outside of i2c_ds1624_leer_temp_c(), with the high and low bytes of the result carried back to main() as globals.
in my library code you cut-n-pasted from:
Code: | int i2c_ds1624_read_temp_c(int device_addr) {
int datah, datal;
int addr_mask;
addr_mask=i2c_addr_mask(device_addr);
i2c_start();
i2c_write(DS1624_ID | addr_mask | I2CWRITE); /* mode is write */
i2c_write(DS1624_CMD_ACCESSTEMPERATURE); /* send access temperature command */
i2c_start();
i2c_write(DS1624_ID | addr_mask | I2CREAD); /* mode is read */
datah=i2c_read(); /* msb */
datal=i2c_read(0); /* lsb (=0.5 deg C) & No Ack */
i2c_stop();
if (BIT_TEST(datah,7)) /* defeat the two's complement data output; */
return(0); /* this means NO negative temps are returned */
else /* if datal is > 0.5C, round up the value */
return( ((datal & 0b10000000) ? datah+1 : datah) ); /* returns 0->125 deg C */
} |
so here's an idea...
note that the return value is an unsigned int. the last few lines of the function make it so. for your application, just change the tail end of this function (and it's declaration of course) to return a signed int. then you won't have to screw around with datah and datal in your main.
jds-pic |
|
|
padron70
Joined: 08 Dec 2005 Posts: 7
|
|
Posted: Sun Dec 11, 2005 4:44 pm |
|
|
Thanks jds-pic, I have changed the function i2c_ds1624_leer_temp_c() since you have recommended and the results have been correct with the maximum and minimum temperatures perfectly shown.
The final code:
Code: |
#include <16f877.h>
#use delay (clock=4000000)
#use I2C(MASTER, SDA=PIN_C4, SCL=PIN_C3, fast)
#use fast_io(A)
#fuses XT, NOPROTECT, NOPUT, NOWDT, NOBROWNOUT, NOLVP, NOCPD
#include <lcd_lolo.c>
#define simbolo_grados 0b11011111
#define simbolo_coma 0b00101100
#define I2CWRITE 0b10010000
#define I2CREAD 0b10010001
#define I2CREAD2 0b10010011
#define DS1624_CMD_ACCESSCONFIG 0xAC
#define DS1624_CMD_INITIATECONVERT 0xEE
#define DS1624_CMD_ACCESSTEMPERATURE 0xAA
#define DS1624_CMD_ACCESSMEMORY 0x17
# byte port_a=6
void i2c_conversion()
{
i2c_start();
i2c_write(I2CWRITE);
i2c_write(DS1624_CMD_INITIATECONVERT);
i2c_stop();
}
void i2c_ds1624_inicia()
{
i2c_start();
i2c_write(I2CWRITE);
i2c_write(DS1624_CMD_ACCESSCONFIG);
i2c_write(0b01001011);
i2c_stop();
delay_ms(20);
i2c_conversion();
}
float i2c_ds1624_leer_temp_c()
{
float dec;
int datah, datal;
i2c_start();
i2c_write(I2CWRITE);
i2c_write(DS1624_CMD_ACCESSTEMPERATURE);
i2c_start();
i2c_write(I2CREAD);
datah=i2c_read();
datal=i2c_read(0);
switch(datal)
{
case 248: dec=0.98; break;
case 240: dec=0.94; break;
case 232: dec=0.90; break;
case 224: dec=0.87; break;
case 216: dec=0.83; break;
case 208: dec=0.80; break;
case 200: dec=0.77; break;
case 192: dec=0.75; break;
case 184: dec=0.72; break;
case 176: dec=0.70; break;
case 168: dec=0.68; break;
case 160: dec=0.66; break;
case 152: dec=0.62; break;
case 144: dec=0.60; break;
case 136: dec=0.58; break;
case 128: dec=0.55; break;
case 120: dec=0.53; break;
case 112: dec=0.50; break;
case 104: dec=0.48; break;
case 96: dec=0.44; break;
case 88: dec=0.40; break;
case 80: dec=0.37; break;
case 72: dec=0.34; break;
case 64: dec=0.30; break;
case 56: dec=0.28; break;
case 48: dec=0.23; break;
case 40: dec=0.20; break;
case 32: dec=0.17; break;
case 24: dec=0.13; break;
case 16: dec=0.10; break;
case 8: dec=0.05; break;
case 0: dec=0.00; break;
}
i2c_stop();
i2c_ds1624_inicia();
return (datah + dec);
}
int read_ext_eeprom(int address)
{
int data;
i2c_start();
i2c_write(0x90);
i2c_write(0x17);
i2c_write(address);
i2c_start();
i2c_write(0x91);
data=i2c_read();
i2c_stop();
return data;
}
void write_ext_eeprom(int address, int data)
{
i2c_start();
i2c_write(0x90);
i2c_write(0x17);
i2c_write(address);
i2c_write(data);
i2c_stop();
delay_ms(50);
}
void main (void)
{
float tempe,maximo,minimo;
int contador;
lcd_inicia();
i2c_ds1624_inicia();
set_tris_a(0b111110);
lcd_ponc("\f");
port_a=0;
maximo=0;
minimo=100;
contador=0;
while(1)
{
tempe=i2c_ds1624_leer_temp_c();
i2c_ds1624_inicia();
if (tempe>maximo) maximo= tempe;
if ((tempe<minimo)&& (tempe!=0.0000)) minimo= tempe;
lcd_ponc("\f");
lcd_vaixy(1,1);
printf(lcd_ponc,"T= %4.2f%cC",tempe,simbolo_grados);
lcd_vaixy(1,2);
if (contador<50)
printf(lcd_ponc,"Maxi= %4.2f%cC",maximo,simbolo_grados);
if (contador>=50)
printf(lcd_ponc,"Mini= %4.2f%cC",minimo,simbolo_grados);
if (contador>100) contador=0;
if (tempe>20.00) output_high (PIN_A0);
if (tempe<=20.00) output_low (PIN_A0);
contador=contador+1;
}
}
|
|
|
|
jds-pic
Joined: 17 Sep 2003 Posts: 205
|
|
Posted: Thu Dec 15, 2005 8:27 am |
|
|
padron70 wrote: |
"The final code:"
Code: |
<...>
void i2c_conversion()
{
i2c_start();
i2c_write(I2CWRITE);
i2c_write(DS1624_CMD_INITIATECONVERT);
i2c_stop();
}
void i2c_ds1624_inicia()
{
i2c_start();
i2c_write(I2CWRITE);
i2c_write(DS1624_CMD_ACCESSCONFIG);
i2c_write(0b01001011);
i2c_stop();
delay_ms(20);
i2c_conversion();
}
float i2c_ds1624_leer_temp_c()
{
<...snip...>
i2c_stop();
i2c_ds1624_inicia(); <<<<<< ------ WHY?
return (datah + dec);
}
void main (void)
{
<...snip...>
while(1)
{
tempe=i2c_ds1624_leer_temp_c();
i2c_ds1624_inicia();
<...snip...>
}
}
|
|
you still have a few structural problems and one logic problem...
(1) there is no reason for you to call i2c_ds1624_inicia() from within i2c_ds1624_leer_temp_c(). this is unnecessary and is likely causing you other problems related to...
(2) in i2c_ds1624_inicia() you set up for "one-shot" conversions (using i2c_write(0b01001011);) but you didn't read enough of the DS1624 datasheet to understand that it takes at minimum 400ms (max 1000ms) to complete a conversion. (refer to top of page 14 for the Ttc parameter). the while loop you have in main() makes no provision for enforcing the necessary delay. therefore, you are likely reading imcomplete conversion results, and then restarting the conversion process immediately thereafter. by your current method, i don't think you are getting accurate, repeatable measurements.
to fix (2), you can do one of three things.
a) use "continuous conversion mode" and read from the device whenever you want. it will give you the last valid result even if a new conversion is in process.
b) use a fixed 1000ms delay in your while loop after initiating a one shot conversion.
c) implement a delay_ms(50) loop which periodically checks the "done" bit in the DS1624 status register after you initiate a one shot conversion. only read when the done bit gets set.
the simplest, surest method is (a).
jds-pic
note for our english-speaking readers:
inicia ~= init
leer ~= read |
|
|
Guest Guest
|
|
Posted: Wed Jan 04, 2006 5:30 am |
|
|
What would you suggest if i say that i need water temperature sensor that must be all the time, in the water ?
You stick it in the water and that's it. He should be all time in the water... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|