7 Replies Latest reply on May 9, 2020 10:00 PM by EvPa_264126

    Reading temperature from DS18B20 on PSoC 5

    NaAh_4673366

      Hi everyone,

       

      I wrote a code to read the temperature from a 1-Wire based digital thermometer DS18B20 and show it using UART communication. But I always get the temperature 127.

      I could not find out the reason. Can anyone please help? Thanks.

       

      I am using CY8CKIT-059PSoC5LP

        • 1. Re: Reading temperature from DS18B20 on PSoC 5
          BoTa_264741

          NaAh,

          You can borrow the code from

          Component to read DS18B20 digital temperature sensors

          or use existing component as-is

           

          If you want to develop own code, I suggest to start with tested component from the link above and to make sure you are able to read the sensor correctly. Typical issue is too small pull-up resistor, and incorrect 1-wite timing intervals.

          /odissey1

          • 2. Re: Reading temperature from DS18B20 on PSoC 5
            EvPa_264126

            signals of your project:dallas.jpg

            • 3. Re: Reading temperature from DS18B20 on PSoC 5
              MoTa_728816

              Hi,

               

              Since your code is very difficult for me, I added my code to print the result.

              In the following man.c, I did a couple of things.

              (1) Print out all data read

              (2) Print temp_msb and temp_lsb following the datasheet of DS18B20

               

              When I un-comment the line below

                      // scratchpad[0] = 0x91 ; scratchpad[1] = 0x01 ; /* this is +25.0625 */

              Tera Term output was

              000-TeraTerm-log.JPG

              Note: Since I don't have the sensor, the reading was all 0x00,

              but as I forced scratchpad[0] = 0x91, scratchpad[1] = 0x01

              the result temp was shown as 85.0000

               

              So please use attached code to check

              - If the sensor reading is correct

              - If the values displayed are correct

               

              main.c

              =======================

              /* ========================================

              *

              *

              *

              * ========================================

              */

              #include "project.h"

              #include "stdio.h"

              #define STR_LEN 64

              char    str[STR_LEN+1] ;

              void    print(char *str)

              {

                  UART_PutString(str) ;

              }

              void cls(void)

              {

                  print("\033c") ; /* reset */

                  CyDelay(20) ;

                  print("\033[2J") ; /* clear screen */

                  CyDelay(20) ;

              }

               

              void splash(char *prog_name)

              {

                  cls() ;

                  if (prog_name && *prog_name) {

                      print(prog_name) ;

                  }

                  print(" (") ;

                  print(__DATE__) ;

                  print(" ") ;

                  print(__TIME__) ;

                  print(")\n") ;

              }

               

              #define RESET_PULSE 480

              #define PRESENCE_PULSE 70

              #define END_SLOT 410

              #define TIME_SLOT 60

              #define RECOVERY_TIME 10

              #define WRITE_0_SLOT 60

              #define WRITE_1_SLOT 10

              #define READ_INIT_DELAY 6

              #define READ_VALID_DELAY 6

               

               

              #define SKIP_ROM 0xCC

              #define WRITE_SCRPAD 0x4E

              #define RESOL_12BIT 0x7F

              #define START_CONVERT 0x44

              #define READ_SCRPAD 0xBE

               

               

              char string[50];

              int ow_Reset(void)

              {

              int presence;

              Wire1_Write(0); //pull DQ line low

              CyDelayUs(RESET_PULSE); // leave it low for 480us

              Wire1_Write(1); // allow line to return high

              CyDelayUs(PRESENCE_PULSE); // wait for presence

              presence = Wire1_Read(); // get presence signal

              CyDelayUs(END_SLOT); // wait for end of timeslot

              return presence; // presence signal returned

              } // 0=presence, 1 = no part

               

               

               

               

              void OW_Write_Bit(int bit)

              {  

                 

                  /* Write is initiated from this step*/

                  Wire1_Write(0);

                 

                  // Write '0' bit

                  if(bit==0)

                  {

                      /* Minimum 60us for logic_0 */

                      CyDelayUs(WRITE_0_SLOT);

                      // Releases the bus

                      Wire1_Write(1);

                  }

                  // Write '1' bit

                  else

                  {

                      /* Release to 1 before 15us for logic_1 */

                      CyDelayUs(WRITE_1_SLOT);

                      // Releases the bus

                      Wire1_Write(1);

                      // Complete the time slot

                      CyDelayUs(50);

                    

                  }

                  

                  /* Minimum recovery time 1us between write steps is ncessary, 10us is used */

                  CyDelayUs(RECOVERY_TIME);

              }

               

               

              int OW_Read_Bit(void)

              {

                 

                  /* Initiate read by pulling line low */

                  Wire1_Write(0);

                  /* Minimum time 1us, to initiate delay */

                  CyDelayUs(READ_INIT_DELAY);

                  Wire1_Write(1);

                  /* Data valid before 15us, should be sampled before that*/

                  CyDelayUs(READ_VALID_DELAY);

                  // Sample the bit value from the slave

                  return(Wire1_Read());

                  // Complete the time slot and 10us recovery

                  CyDelayUs(58);

              }

               

               

              //-----------------------------------------------------------------------------

              // Write 1-Wire data byte

              //

              void OW_Write_Byte(int data)

              {

                      int loop;

               

               

                      // Loop to write each bit in the byte, LS-bit first

                      for (loop = 0; loop < 8; loop++)

                      {

                              OW_Write_Bit(data & 0x01);

               

               

                              // shift the data byte for the next bit

                              data >>= 1;

                      }

              }

               

               

              //-----------------------------------------------------------------------------

              // Read 1-Wire data byte and return it

              //

              int OW_Read_Byte(void)

              {

                      int loop, result=0;

               

               

                      for (loop = 0; loop < 8; loop++)

                      {

                              // shift the result to get it ready for the next bit

                              result >>= 1;

               

               

                              // if result is one, then set MS bit

                              if (OW_Read_Bit())

                                      result |= 0x80;

                      }

                      return result;

              }

               

               

               

               

              int main(void)

              {

                  int i ;

                  int16_t tempx16 ;

                 

                  CyGlobalIntEnable; /* Enable global interrupts. */

                  UART_Start();

                  splash("5LP DS18B20 Test") ;

                 

                  char scratchpad[10];

                  int temp_lsb,temp_msb;

                  int k;

                  //int temp_c;

                  //int tempr;

                  //uint8 connect;

                 

                  ow_Reset();

                  /* As only single sensor is present in channel-Skip command */

                  OW_Write_Byte(SKIP_ROM);

                  /*Write Scratch Pad command*/

                  OW_Write_Byte(WRITE_SCRPAD);

                 

                  /* Alarm registers are unused, Writing Random values*/

                  /*TH*/

                  OW_Write_Byte(0x55);

                  /*TL*/

                  OW_Write_Byte(0xA2);

                  /* Config(resoluion)7F- 12 bit resolution */

                  OW_Write_Byte(RESOL_12BIT);

                 

                  for(;;)

                  {

                      ow_Reset();

                      /*Skip address check command */

                     OW_Write_Byte(SKIP_ROM);

                     /* Start Convert*/

                     OW_Write_Byte(START_CONVERT);

                 

                     /* Wait until conversion completes */

                     CyDelayUs(104);

                     ow_Reset();

                    

                     /*Skip address check command */

                     OW_Write_Byte(SKIP_ROM);

                     /*Read Scratch Pad command*/

                     OW_Write_Byte(READ_SCRPAD);

                 

                      /*Copy the scratpad from slave*/

                      for( k=0;k<9;k++)

                      {

                      scratchpad[k]=OW_Read_Byte();

                      }

                     

                      print("Data Read : ") ;

                      for (i = 0 ; i < 9 ; i++ ) {

                          snprintf(str, STR_LEN, "0x%02X ", scratchpad[i]) ;

                          print(str) ;

                      }

                      print(" : ") ;

               

               

                      #if 0

                      for (

                          temp_msb = scratchpad[1]; // Sign byte + lsbit

                          temp_lsb = scratchpad[0]; // Temp data plus lsb

                          if (temp_msb <= 0x80){temp_lsb = (temp_lsb/2);} // shift to get whole degree

                          temp_msb = temp_msb & 0x80; // mask all but the sign bit

                          if (temp_msb >= 0x80) {temp_lsb = (~temp_lsb)+1;} // twos complement

                          if (temp_msb >= 0x80) {temp_lsb = (temp_lsb/2);}// shift to get whole degree

                          if (temp_msb >= 0x80) {temp_lsb = ((-1)*temp_lsb);} // add sign bit

                          sprintf(string,"\n\rTempC= %d degrees C", (int)temp_lsb ); // print temp. C

                         

                          UART_PutString(string);

                      #endif

                     

                      /* test data : To test, uncomment one line */

                      // scratchpad[0] = 0xD0 ; scratchpad[1] = 0x07 ; /* this is +125 */

                      // scratchpad[0] = 0x50 ; scratchpad[1] = 0x05 ; /* this is +85 */  

                      // scratchpad[0] = 0x91 ; scratchpad[1] = 0x01 ; /* this is +25.0625 */

                      // scratchpad[0] = 0xA2 ; scratchpad[1] = 0x00 ; /* this is +10.125 */      

                      // scratchpad[0] = 0x08 ; scratchpad[1] = 0x00 ; /* this is +0.5 */

                      // scratchpad[0] = 0x00 ; scratchpad[1] = 0x00 ; /* this is 0.0 */

                      // scratchpad[0] = 0xF8 ; scratchpad[1] = 0xFF ; /* this is -0.5 */

                      // scratchpad[0] = 0x5E ; scratchpad[1] = 0xFF ; /* this is -10.125 */   

                      // scratchpad[0] = 0x6F ; scratchpad[1] = 0xFE ; /* this is -25.0625 */

                      // scratchpad[0] = 0x90 ; scratchpad[1] = 0xFC ; /* this is -55.0 */       

                     

                      temp_msb = scratchpad[1] ; /*   S,   S,   S,   S,    S,  2^6,  2^5,  2^4 */

                      temp_lsb = scratchpad[0] ; /* 2^3, 2^2, 2^1, 2^0, 2^-1, 2^-2, 2^-3, 2^-4 */

                      tempx16 = (temp_msb << 8) | temp_lsb ; /* make a int16_t from 2 bytes */

                      if (tempx16 < 0) {

                          print("-") ;

                          tempx16 = -1 * tempx16 ;

                      }

                      snprintf(str, STR_LEN, "%d", (tempx16 >> 4)) ; /* integer part */

                      print(str) ;

                      snprintf(str, STR_LEN, ".%04d\n\r", (tempx16 % 16) * 625) ; /* fraction part */

                      print(str) ;

                  }

              }

              =======================

               

              attached is the modified project of yours.

               

              moto

              • 4. Re: Reading temperature from DS18B20 on PSoC 5
                NaAh_4673366

                Hi MoTa_728816

                 

                I am getting this by running your code:

                1wire.PNG

                • 5. Re: Reading temperature from DS18B20 on PSoC 5
                  MoTa_728816

                  Hi,

                   

                  That screen shot means you are not correctly reading the value of the sensor.

                  Since I don't have the sensor I can't debug that part.

                   

                  Please read the datasheet and fix your code

                  or consider using the "working" sample from /odissey1-san.

                   

                  moto

                  • 6. Re: Reading temperature from DS18B20 on PSoC 5
                    MoTa_728816

                    Hi,

                     

                    Once thing I could notice was OW_Read_Bit(), CyDelayUs(58) is never called.

                    So I would suggest to modify it to

                     

                    ==========================

                    int OW_Read_Bit(void)

                    {

                        int read_bit ; // <====

                        /* Initiate read by pulling line low */

                        Wire1_Write(0);

                        /* Minimum time 1us, to initiate delay */

                        CyDelayUs(READ_INIT_DELAY);

                        Wire1_Write(1);

                        /* Data valid before 15us, should be sampled before that*/

                        CyDelayUs(READ_VALID_DELAY);

                        // Sample the bit value from the slave

                       read_bit = Wire1_Read() ; // <=====

                    //    return(Wire1_Read()); // <====

                        // Complete the time slot and 10us recovery

                        CyDelayUs(58);

                        return( read_bit ) ; // <====

                    }

                    ==========================

                     

                    moto

                    • 7. Re: Reading temperature from DS18B20 on PSoC 5
                      EvPa_264126

                      Please check the timings

                      #define READ_INIT_DELAY 6

                      #define READ_VALID_DELAY 6
                      1w.jpg
                      my be:

                       

                      int OW_Read_Bit(void)

                      {

                          CyDelayUs(20);// Complete the time slot and 10us recovery

                          Wire1_Write(0);

                          /* Minimum time 1us, to initiate delay */

                          CyDelayUs(10);

                          Wire1_Write(1);

                          /* Data valid before 15us, should be sampled before that*/

                          CyDelayUs(5);

                          // Sample the bit value from the slave

                          return(Wire1_Read());

                      }