|
|
View previous topic :: View next topic |
Author |
Message |
mahdihir
Joined: 01 Dec 2013 Posts: 7 Location: Iran
|
DS18b20 running problem |
Posted: Tue Apr 21, 2015 6:11 am |
|
|
My dear friends.
I hope you are doing well.
I need to run a DS18b20 sensor with 4 digit 7 segment.
but the value is shown in display is not the correct temperature.
main cod is:
/////////////////////////////////////
#include <16F1937.h>
#device *=16
#device adc=10
#FUSES NOWDT, HS, PUT, NOPROTECT, NODEBUG, BROWNOUT, NOLVP, NOCPD, NOWRT
#use delay(clock=20000000)
#include<1wire.c>
#include<lcd.c>
#include<ds1820.c>
/* --- configure DS1820 temparture sensor --- */
#define DS1820_DATAPIN PIN_A0
const char n[] ={0xfe, 0xb0, 0x6d, 0x79, 0x33, 0x5B, 0x5F, 0x70, 0xFF, 0x7b , 0x01 , 0x80}; //0 1 2 3 4 5 6 7 8 9 - dot
static char m[] ={0x00, 0X7f, 0XBF, 0XDF, 0XEF };
//static unsigned char Digit;
unsigned int16 digit1_temp, digit2_temp, digit3_temp, digit4_temp, o ;
float temp;
int i ;
//signed int16 d1;
void main()
{
// port_E_pullups(0x0F);
while(TRUE)
{
output_C(0X00);
output_B(0X00);
///////digits
temp = ds1820_read();
o=temp*10;
digit1_temp=o%10;
digit2_temp=o/10%10;
digit3_temp=o/100%10;
digit4_temp=o/1000;
delay_ms(800);
////////////////////////////////////////////// show tempreture
for (i=0; i<50; i++) {
output_c(n[digit4_temp]);
output_B(m[1]);
delay_ms(2);
//output_c(n[0]);
output_c(n[digit3_temp]);
output_B(m[2]);
delay_ms(2);
//output_c(n[0]);
output_c(n[digit2_temp]);
output_B(m[3]);
delay_ms(2);
//output_c(n[0]);
output_c(n[digit1_temp]);
output_B(m[4]);
delay_ms(2);
//output_c(n[0]);
}
}
}
//////////////////////////////////////////////////
the 1wire.c
//////////////////////////////////////////////
// (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_A0
/*******************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 );
}
///////////////////////////////////////////////////////////
the ds1820.c
//////////////////////////////////////////////////////////
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);
}
thanks |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Apr 21, 2015 6:49 am |
|
|
Start by using the "code" button. You've been here long enough to know how it works.
What is wrong with the temperature reading?
Is it:_
A) A totally silly value?
B) Always a bit high/low?
C) Always a lot high/low?
D) Always the same?
Have you tried sending the raw readings to a PC via RS232?
Mike |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9220 Location: Greensville,Ontario
|
|
Posted: Tue Apr 21, 2015 7:51 am |
|
|
I'm with Mike on this...
Have you tried sending the raw readings to a PC via RS232?
... you need to
figure out is it a bad sensor or bad program.
If you dump out the raw data and 'do the math' yourself, you'll see where the problem is.
Also read the datasheet to see what the data should be.If your room temperature is 70*c and you get 85*c that's a problem, but if you get 80*C that might be within tolerance.
Jay |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Apr 21, 2015 8:37 am |
|
|
Code: | 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 |
This was the problem for me about 3 days ago that i tried that code.
I "changed" it to this and it worked:
Code: | //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 |
i didnt spend more time trying to figure out why the first line does not work.
if you do, let us Know.
G. _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19492
|
|
Posted: Tue Apr 21, 2015 9:30 am |
|
|
That depends on which chip you actually have.
You need to verify with a magnifying glass whether you have the 'S' or 'B' chips. The former returns counts in 1/16th degree steps, the latter in 1/2 degree steps. If your chip manufacturer does not match the data sheet you are using, get the one from the manufacturer you have, and see how their device labeling works (beware, some have numbers like
DS18
20SB
(on surface mount parts). This is actually an 'S' chip, not a 'B'.... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9220 Location: Greensville,Ontario
|
|
Posted: Tue Apr 21, 2015 10:43 am |
|
|
also....
this...
"the ds1820.c"
may not be the correct driver.
I seem to recall 3 variations of the temp sensor and there were minor timing differences. I did use the 'parasitic' version as it allowed for 2 wire operation with 100' of 2 conductor cable.
just something else to consider.
jay |
|
|
ELCouz
Joined: 18 Jul 2007 Posts: 427 Location: Montreal,Quebec
|
|
Posted: Tue Apr 21, 2015 12:17 pm |
|
|
temtronic wrote: | also....
this...
"the ds1820.c"
may not be the correct driver.
I seem to recall 3 variations of the temp sensor and there were minor timing differences. I did use the 'parasitic' version as it allowed for 2 wire operation with 100' of 2 conductor cable.
just something else to consider.
jay |
Also the 1-wire driver for that have a waiting loop that can hang to whole PIC if no ds18b20 are detected or have failed...
I prefer the TMP75, TMP175 or TMP275 from TI... straight easy I2C! No delays instant reading (*** excluding conversion time for 9 /10 /11 and 12-bit adc)
up to 27 devices on I2C too (TMP175)! (distance might be a factor thought)
EDIT: However with the NXP PCA9600 you can extend the I2C to 100 meters easily! _________________ Regards,
Laurent
-----------
Here's my first visual theme for the CCS C Compiler. Enjoy! |
|
|
Gabriel
Joined: 03 Aug 2009 Posts: 1067 Location: Panama
|
|
Posted: Tue Apr 21, 2015 3:25 pm |
|
|
.... i should pay more attention to the comments.
i have the DS18B20 _________________ CCS PCM 5.078 & CCS PCH 5.093 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19492
|
|
Posted: Wed Apr 22, 2015 12:53 am |
|
|
Yes.....
Explains a lot. I suspect though that you had 8* the reading you expected, so at least you were working for everything else..
However looking at the original code for this thread, there area lot of steps to everything here:
Debugging must always be a 'divide and conquer' operation. This is what is being pointed to:
1) Get the PIC actually working. Can you display numbers?. Can you (for instance), get a counter working, counting at the correct rate?.
2) Then get the sensor working. This is Temtronics point. Don't try the complexity of tying the display to the sensor, get the number from the sensor, and make sure this is a sensible number.
3) Only once you have each part working _separately_, try to tie them together.
As comments, first there are too many delays.
The sensor needs a delay, between readings while the line is used to power it, but you have 200mSec in this, then another 800mSec in the main code, then another 400mSec while the value is displayed. At least two of these delays can be got rid of.
Then the maths is awful. Get rid of the float. The display just displays integer values, so just change the one wire code to return a suitable integer. If you are only wanting degrees C, then stay with integer in the driver. Just multiply by five, and return this as an integer, not a float.
Then the conversion to digits is done about the most inefficient way possible. Look at ldiv, which returns both the quotient, and remainder, in one operation.
Normally the display would be done using an interrupt, so the value is displayed continuously _while_ the other code is reading the new value. The current approach is going to have the display doing nothing for nearly a second, and then just displaying the value for a little while, then returning to displaying the last segments output, while it goes off and reads a new value. Not exactly easy to read. At the least, turn the display off while taking the new reading, or have the display handled via an interrupt. |
|
|
|
|
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
|