Jump to content
43oh

Reading the ds18b20 temperature sensor


Recommended Posts

zeke, it works perfect now.

 

Excellent!

 

I did need to make one change to your code: ROMCode[7] should be ROMCode[0].

 

Ah, good catch. Such are the dangers of coding past midnight :oops:

 

Thanks again for all the help you've provided, its definitely helping me learn.

 

You're most welcome!

Glad I could help.

 

Thank you for giving me the motivation to figure this out too.

Link to post
Share on other sites
  • 3 months later...

Sorry. No. The one wire protocol is bound by time and is inflexible.

 

It would be much easier to adapt your LCD code to run at 16MHz. In my understanding, your LCD delays will have to be scaled.

 

@RobG, can you comment on what changes he might need to make to his LCD routines?

Link to post
Share on other sites

Hi!

I solved it :) You have right, it is easier to adopt LCD library:

 

#define sendData(data) send(data, 1)
#define sendInstruction(data) send(data, 0)
#define initDisplay() sendInstruction(0x3C); sendInstruction(0x0E); clearDisplay(); sendInstruction(0x06); delayMicroseconds(2000); //for 16Mhz
#define clearDisplay() sendInstruction(0x01); delayMicroseconds(2000)
#define DATAPIN BIT6
#define CLOCKPIN BIT5
#define ENABLEPIN BIT4

void send(char data, char registerSelect);
void sendDataArray(char data[], char length);

char charIndex = 0;
char bitCounter = 0;

void sendDataArray(char data[], char length) {
  charIndex = 0;
    while(charIndex < length) {
       sendData(data[charIndex]);
       charIndex++;
    [b]   delayMicroseconds(100);     //for 16Mhz[/b]
    }
}

void send(char data, char registerSelect) {
  bitCounter = 0;
  while(bitCounter < 8) {
       (data & BIT7) ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
       data <<= 1;
       P1OUT |= CLOCKPIN;
       P1OUT &= ~CLOCKPIN;
       bitCounter++;
    [b]   delayMicroseconds(100);      //for16Mhz[/b]
    }
    registerSelect ? (P1OUT |= DATAPIN) : (P1OUT &= ~DATAPIN);
    P1OUT &= ~ENABLEPIN;
    P1OUT |= ENABLEPIN;
}

And everything works for me :) Of course it is @RobG code, I wrote in only delays (Thanks for 3 wire solution :D)

Link to post
Share on other sites
  • 4 weeks later...

hi zeke, thanks for reply.

i have try this code and modify it and i get "0C".

actually i using 'salvo' for my processor.

originally it us analog sensor and i change it to ds18b20.

 

 

"#define WIRE_PORT 45" //im using port 5.1

 

what if i use "#define WIRE_PORT P5DIR = BIT" is there any deferent?

 

 

 

p/s: i am really new to this msp430. before this i use MPLAB. here is my code main.c. :D

 

#include "main.h"
#include "salvo.h"
#include "CSK_USART.h"
#define SENDING_TASK_TALK_USB		2

#define WIRE_PORT  45
#define LOW 0
#define HIGH 1
#define INPUT 0
#define OUTPUT 1   
#define READROM     0x33
#define SKIPROM     0xCC
#define CONVERTTEMP     0x44
#define READSCRATCHPAD  0xBE
#define delayMicroseconds(n) __delay_cycles(n<<4)


int  OW_Reset( int Pin );
void OW_WriteByte(int Pin, char d);
char OW_ReadByte(int Pin);
char digitalRead( char Pin );
void pinMode( int Pin, int Out );
void digitalWrite( int Pin, int Bit );

int m;
int ROMCode[8];
int ScratchPad[9];
int HighByte, LowByte, TReading, SignBit, Tc_100, Whole, Fract;

typedef struct {
 unsigned int USBpresent:1;
 unsigned int ACLKOutEnabled:1;
 unsigned int MCLKOutEnabled:2;
} CSK_typeStatus;

CSK_typeStatus CSK_status;

unsigned int ADCresult; 
unsigned long int DegC;
unsigned int seed = 123;
unsigned char tempA = 0;

extern void TaskExerciseIO ( void );

char strTmp[30];	// usable to anyone who wants it ...
char strTmp2[30];

#if defined(MAKE_FOR_SALVO_MONITOR)
void OSInitMonitor(void); // move to header file
#endif

extern void slipdev_char_put (unsigned char c);
unsigned char reset(void) ;


void TaskTalkUSB( void )
{
   static unsigned char saveP1DIR;
   static unsigned char saveP1OUT;
   static unsigned char saveP1SEL;
   static unsigned char saveP6DIR;
   static unsigned char saveP6OUT;

   CSK_status.USBpresent = 1;

   for (;
   {       
     /* repeat every second*/
       OS_Delay(93);  

   /* is USB connected?*/     
       if ( CSK_status.USBpresent )
       { 
            /* proceed if USB/MHX I/F is not in use*/
           OS_WaitBinSem(BINSEM_USB_MHX_AVAIL_P, OSNO_TIMEOUT);

           /* save current config                          */
           saveP1DIR = P1DIR;
           saveP1OUT = P1OUT;
           saveP1SEL = P1SEL;
           saveP6DIR = P6DIR;
           saveP6OUT = P6OUT;

           /* disable all control signals to avoid spurious*/
           /*  writes when P1.7 goes LOW (below) */
           P6OUT |=  BIT5+BIT4+BIT3;
           P6DIR |=  BIT5+BIT4+BIT3;

           /* wait for signals to settle*/
           OS_Delay(1);

           /* write a 0 to P1.7 */
           P1SEL &= ~BIT7;
           P1OUT &= ~BIT7;
           P1DIR |=  BIT7;

           CSK_DEBUGPUTS("TalkUSB: Acquired USB/MHX I/F for USB.");

           /* send a simple message out the USB port. */
           /*  Don't close the USB connection until the*/
           /*  message is completely gone (derived */
           /*  empirically	... 6 ticks is adequate fpr 9600 baud)*/
           sprintf(strTmp, "red_devil:" "fire is %d C", DegC); 
           CSK_Msg1(strTmp);
           OS_Delay(14);

           /* note activity*/
           CSK_DEBUGPUTS("TalkUSB: Sending to USB.");

           /* restore current config  */
           P6OUT = saveP6OUT;
           P6DIR = saveP6DIR;
           P1SEL = saveP1SEL;
           P1OUT = saveP1OUT;
           P1DIR = saveP1DIR;

          /* release USB/MHX I/F */     
           OSSignalBinSem(BINSEM_USB_MHX_AVAIL_P); 
           CSK_DEBUGPUTS("TalkUSB: Released USB/MHX I/F.");
       }
   }
}



/*************************************************************************************************************/
void TaskMeasureAmbientTemp( void )
{
     if ( 1 == OW_Reset( WIRE_PORT ) )
     {
       OW_WriteByte( WIRE_PORT, 0x33 );  // Read ROM Code from DS18B20

       for( m=0; m<8; m++ )
       {
         // Read the values inside of the ROMCode array in the debugger window
         ROMCode[m] = OW_ReadByte( WIRE_PORT );
       }
     }

     if ( 1 == OW_Reset( WIRE_PORT ) )
     {
       OW_WriteByte( WIRE_PORT, SKIPROM );  // Skip ROM Code matching
       OW_WriteByte( WIRE_PORT, CONVERTTEMP );  // Read ROM Code from DS18B20
       OW_Reset( WIRE_PORT );
       OW_WriteByte( WIRE_PORT, SKIPROM );  // Skip ROM Code matching
       OW_WriteByte( WIRE_PORT, READSCRATCHPAD );  // Read ScratchPad from DS18B20

       for( m=0; m<9; m++ )
       {
         // Read the values inside of the ScratchPad array in the debugger window
         ScratchPad[m] = OW_ReadByte( WIRE_PORT );
       }
     }


     OW_Reset( WIRE_PORT );
     OW_WriteByte( WIRE_PORT, SKIPROM );         // Skip ROM Code matching
     OW_WriteByte( WIRE_PORT, CONVERTTEMP );     // Read ROM Code from DS18B20
     OW_Reset( WIRE_PORT );
     OW_WriteByte( WIRE_PORT, SKIPROM );         // Skip ROM Code matching
     OW_WriteByte( WIRE_PORT, READSCRATCHPAD );  // Read ScratchPad from DS18B20

     LowByte  = OW_ReadByte( WIRE_PORT );
     HighByte = OW_ReadByte( WIRE_PORT );

     // Thanks again "Mr. Anderson" for this code
     TReading = ( HighByte << 8 ) + LowByte;
     SignBit = TReading & 0x8000;  // test most sig bit
     if ( 1 == SignBit ) // negative
     {
       TReading = (TReading ^ 0xffff) + 1; // 2's comp
     }
     Tc_100 = ( 6 * TReading ) + TReading / 4;    // multiply by (100 * 0.0625) or 6.25

     Whole = Tc_100 / 100;  // separate off the whole and fractional portions
     Fract = Tc_100 % 100;

     delayMicroseconds( 1000 );

}

       int OW_Reset( int Pin )
       {
         int presence = 0;

         delayMicroseconds( 0 );  // delay for 0us
         digitalWrite( Pin, LOW );
         pinMode( Pin, OUTPUT );
         delayMicroseconds( 480 );  // delay for 480us
         pinMode( Pin, INPUT );
         delayMicroseconds( 70 );  // delay for 70us

         if( 0 == digitalRead( WIRE_PORT ) )
         {
           presence |= 1;      // Presense pulse detected
         }
         else
         {
           presence;     // ds18b20 is not there
         }

         delayMicroseconds( 410 );  // delay for 410us

         return ( presence );        // return the sampled presence pulse result 
       }

       // Peter Anderson wrote this
       void OW_WriteByte( int Pin, char d )
       {
         char n;
         for(n=8; n!=0; n--)
         {
           if ( (d & 0x01) == 1 )
           {
             digitalWrite( Pin, LOW );
             pinMode( Pin, OUTPUT );
             delayMicroseconds( 5 );
             pinMode( Pin, INPUT );
             delayMicroseconds( 60 );
           }
           else
           {
             digitalWrite( Pin, LOW );
             pinMode( Pin, OUTPUT );
             delayMicroseconds( 60 );
             pinMode( Pin, INPUT );
           }
           d = d >> 1;
         }
       }

       // Peter Anderson wrote this
       char OW_ReadByte( int pin )
       {
         char d, n, b;

         for ( n=0; n<8; n++ )
         {
           digitalWrite( pin, LOW );
           pinMode( pin, OUTPUT);
           delayMicroseconds( 5 );
           pinMode( pin, INPUT );
           delayMicroseconds( 5 );
           b = digitalRead( pin );
           delayMicroseconds( 50 );
           d = (d >> 1) | (b << 7); // shift d to right and insert b in most sig bit position
         }
         return(d);
       }

       //------------------------------------------------------------------------------
       // Arduino like digitalRead, pinMode, and digitalWrite helper functions.
       //------------------------------------------------------------------------------
       char digitalRead( char Pin )
       {
         // Read P1IN and mask it with the 1wPin then shift it to the LSB position
         return ( (P5IN &  (1 << Pin) ) >> Pin );
       }

       void pinMode( int pin, int out )
       {         
         if( 1 == out )
         {
           P5DIR |= (1 << pin);
         }
         else
         {
           P5DIR &= (~(1 << pin));
         }
       }

       void digitalWrite(int Pin, int Bit)
       {
         if ( 1 == ( Bit ) )
         {
           P5OUT |= ( 1 << Pin );      // if the Bit is HIGH then drive the 1wBus HIGH
         }
         else
         {
           P5OUT &= ( ~(1 << Pin) );   // if the Bit is LOW then drive the 1wBus LOW   
         }
       }


/*******************************main***********************************************************/
void main (void)
{
   unsigned int i, j, delay;


   WDT_OFF;             // Stop WDT

   /* clock initialization. Requires only 32.768kHz LFXTAL*/
   			//DCO=0x03
   DCOCTL=0x60;		//DCO.1,DCO.0
   BCSCTL2=0x00;
   BCSCTL1=0x84;		//XT2OFF,RSEL.2


BCSCTL1 &= ~XT2OFF; // Turn on XT2
do 
{
	// Wait for XT2 to stablize
	IFG1 &= ~OFIFG; // Clear OSCFault flag
	for (i = 0xFFF; i > 0; i--); // Time for flag to set
} while ((IFG1 & OFIFG) == OFIFG); // OSCFault flag still set?     
BCSCTL2 |= SELS; // SMCLK = XTAL2 (7.3728MHz)


   /* all CSK_ control signals are active LOW */
   P1OUT  =  0xFF;
   P2OUT  =  0xFF;
   P3OUT  =  0xFF;
   P4OUT  =  0xFF;
   P5OUT  =  0xFF;
   P6OUT  =  0xFF;

   /* P1.0 is used to drive a diagnostic LED */
   /* P1.7 controls the USB interface (-OE_USB)  */
   P1SEL &= ~(BIT7 + BIT0);
   P1OUT &= ~BIT0;
   P1OUT |=  BIT7;
   P1DIR |=  BIT7 + BIT0;

   /* P4.6 is used to drive +5V_SW (-ON_+5V). P4.5 is  */
   /*  used to control power to the SD/MMC interface*/
   P4SEL &= ~(BIT6+BIT5);
   P4OUT |=  (BIT6+BIT5);
   P4DIR |=  (BIT6+BIT5);


   /* other init stuff*/
   Init();

   /* init USARTs to 9600,N,8,1*/
   CSK_OpenUSART0(COM0_CONFIG);
   CSK_OpenUSART1(COM1_CONFIG);

   /* initialize Salvo*/
   OSInit();

   #if defined(MAKE_FOR_SALVO_MONITOR)
   OSInitMonitor();
   P2SEL &= ~(BIT2 + BIT1 + BIT0);
   P2OUT &= ~(BIT2 + BIT1 + BIT0);
   P2DIR |=  (BIT2 + BIT1 + BIT0);
   #endif

   /* enable interrupts (enables USART transmitters)*/
   OSEi(); 

   /* create tasks*/

   OSCreateTask(TaskTalkUSB,            TASK_TALK_USB_P,        5);
   OSCreateTask(TaskMeasureAmbientTemp, TASK_MEASURE_AMBIENT_TEMP_P, 11);


   /* create events*/
   OSCreateBinSem(BINSEM_USB_MHX_AVAIL_P, 1);
  // OSCreateBinSem(BINSEM_CMD_CHAR_P,      0);

   /* enable watchdog */
   //WDT_ON;

   /* go*/
   for (;
   {
OSSched();
   }
}

Link to post
Share on other sites
  • 2 months later...
  • 2 weeks later...

page 3 of datasheet for ds18s20 shows method how we can get more accurate results, than 0.5 degree. After reading scratchpad we will need 4 values:

1) Temperature: ScratchPad[0]

2) Sign: ScratchPad[1]

3) Count_remain: ScratchPad[6]

4) Count_per_C: ScratchPad[7] //it always equals 16

 

so, code should looks like this:

LowByte  = ScratchPad[0];
HighByte = ScratchPad[1];
COUNT_REMAIN = ScratchPad[6];
COUNT_PER_C = ScratchPad[7];

if (HighByte) TReading = -LowByte;
     else          TReading = LowByte;

Tc_100 = ((TReading * 50) - 25 + ((COUNT_PER_C - COUNT_REMAIN)*100) / COUNT_PER_C)/10;
/*
//a little bit faster version is
Tc_100 = ((TReading * 50) - 25 + (((16 - COUNT_REMAIN)*100) >> 4))/10
*/

Whole = Tc_100 / 10;
Fract = Tc_100 % 10;

Link to post
Share on other sites

Code for 1820, 18S20, 18B20 and 1822 from my Digital Picture Frame Thermometer project.

 

       int tc, tf;  // Temperature in deg C and deg F - units of 1/16 degree
       unsigned char id[10];  // ID of sensor
       unsigned char b[8];  // Read from sensor

       tc = b[1]; tc <<= 8; tc |= b[0];            // All
       if(id[0] == 0x10) {                         // DS1820 and DS18S20 only
           tc <<= 3;                               // Convert 1/2 C resolution to 1/16 C resolution
           if(b[7] == 16) {                        // DS18S20 12 bit only (divisor of DS1820 is not fixed at 16)
               tc &= 0xFFF0; tc += (12 - b[6]);    // Update with residual count for 1/16 C resolution
           }                                       //
       }                                           //
       tf = ((tc + (tc << 3)) + 2562 ) / 5;        // Convert deg C to deg F

Link to post
Share on other sites
Hi

Is there any possibility to get work it with DCO set on 1Mhz?

I've made a few tests, this code starts working good from 5Mhz. At lower frequencies readout unstable or impossible.

 

BUT I find a way how to run this algorithm with DCO on 1 MHz. All you need is to rewrite the arduino-like part using defines instread of using functions. This is my code:

 

//------------------------------------------------------------------------------
// Arduino like digitalRead, pinMode, and digitalWrite and some other helper functions.
//------------------------------------------------------------------------------
#define LOW 0
#define HIGH 1
#define INPUT 0
#define OUTPUT 1   

#define delayMicroseconds(n) __delay_cycles(1*n)
#define delay(n) delayMicroseconds(1000u*n)

#define digitalRead(Pin) (P1IN &  1 << Pin) >> Pin

#define setOUTPUT(pin) P1DIR |=   (1 << pin)
#define setINPUT(pin)  P1DIR &= (~(1 << pin))
#define pinMode(pin, out) set##out(pin)

#define setHIGH(pin) P1OUT |=  (1 << pin)
#define setLOW(pin)  P1OUT &=(~(1 << pin))
#define digitalWrite(pin, bit) set##bit(pin)

Link to post
Share on other sites

I'm trying to get this code running on a MSP430G2553. Unfortunately I get following error:

identifier "TIMERA0_VECTOR" is undefined	

I don't even get where TIMERA0_VECTOR is defined when using a MSP430G2231. I see some defines in the *.h files - if I understand it right, "TIMERA0_VECTOR" is a name that will be defined as an interupt vector :eh:

 

I know, my problem leads in a little bit offtopic direction, but could someone please point me in the right direction how to overcome such problems, please?

 

regards,

leo

 

EDIT:

ok, found out that TAIV is TA0IV in 2553-ish msp430

 

EDIT2:

and TIMERA0_VECTOR seems to be TIMER0_A1_VECTOR

 

I found these two by stupid searching for "timer" in the *.h files - I still need the knowledge how to get this information the quick and more coordinated way :)

 

now I have to figure out the bunch of errors that occured -.-

Link to post
Share on other sites
I'm trying to get this code running on a MSP430G2553. Unfortunately I get following error:

I found these two by stupid searching for "timer" in the *.h files - I still need the knowledge how to get this information the quick and more coordinated way :)

 

now I have to figure out the bunch of errors that occured -.-

 

You can look at the datasheets, or the functional block diagrams, or use GRACE. When a device

only contains one instance of a peripheral sometimes they don't bother to add the instance number.

The g2231 only has one timer so they don't say Timer0_ .. they just use Timer

 

I like to look at the diagrams as I'm a visual person:

 

msp430g2231 - functional block diagram

 

fbd_slas694h.gif

 

msp430g2553 - functional block diagram

 

fbd_slas735c.gif

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...