Click here to Skip to main content
Click here to Skip to main content

Temperature Measurement as an Example of a 1-Wire Technology Application

By , 2 Feb 2009
 

Introduction

The 1-Wire technology was invented by Dallas Semiconductor Corp.[1] It was designed for a device communication bus system that provides data transmission using two wires: the first for ground, and the second for power and data. The communication is realized between master devices (PC, microcomputer) and slave devices (memory EPROM, temperature sensor, A/D converter, Real Time clock etc.). Although the 1-Wire technology is old, it is still applied in many branches of the industry. The concept of the article is to describe how to construct own the DS9097E adapter and communicate with it. In the Internet, you can find many programs to communicate with 1-Wire devices, but my implementation of the COneWire class is more effective, and it could be easily adopted for the specific applications. For visualization of temperature measurement, I have used the OpenGL library.

Preparation of the DS9097E adapter

If you don't feel up to soldering electronic elements, you could buy the DS9097E adapter. But, I think that doing something by your own could be a good experience and costless.

Elements needed:

  • Printed circuit board 5x7 pins.
  • Two Schockley diodes BAT85.
  • One 3,9 V Zener diode.
  • One 6,2 V Zener diode.
  • One resistor 1,5 KOhm.
  • One RS232 female connector.
  • Two-core cable.
  • One or more DS18B20 temperature sensors.

In Fig. 1, the schematic diagram is described. Be careful while connecting diodes, because they have polarity "+" and "-". The Ready device is presented in Fig. 2. From Fig. 2, you can see that the DS18B20 sensor has three pins whereas we have used only two, why? The DS18B20 sensors could work in two modes. In the first "normal mode", all the pins are connected (ground, data in/out, and power supply voltage). In the second one, where the ground is connected with the power supply, the sensor works using "parasite power". On Fig. 3, the ready circuit board with the soldered elements is shown.

Notice 1: Plug adapter first, then turn on the computer.

Notice 2: If you solder the adapter wrong, it could damage your motherboard.

Fig. 1. Schematic diagram of the DS9097E adapter.

Fig. 2. Ready DS9097E adapter.

Fig. 3. Inside the DS9097E adapter.

The DS9097E adapter which was described in the previous paragraph should be connected to the serial port (COM port). If you do not have any COM-port, you could use a USB to RS232 converter. It will create a virtual COM-port which works as a typical serial port.

Installation of OpenGL and TMEX SDK components

To use the program presented in the article, you should first install the GLUT library[2]. The header files gl.h, glut.h, and glu.h are supposed to be in c:\Program Files\Microsoft Visual Studio\Vc98\Include\GL. It could be changed in the glut.h file. To use 1-Wire devices, Dallas Semiconductor Corp.[1] provides their own drivers. These drivers are included in the TMEX SDK libraries[3]. In the COneWire class, I load the "IBFS32.DLL" library and get access points to the functions included in the library. In the program's directory, "IBFS32.DLL" as well as "IB97E32.DLL" should be placed. In the TMEX SDK documentation, you could find a table where proper DLL files are assigned for different Operating Systems.

Implementation of the COneWire and CDS18B20 classes

After loading the library and setting the initial values in the constructor of COneWire, the StartSesion function should be used. If a 1-Wire device is connected to the COM port by the DS9097E adapter, the function ought to provide a handle to the device. The variables iPortNum and iPortType are the number of the COM-port and the port type which depends on the adapter type. Possible adapter types are listed in the OneWire.h header file.

////////////////////////////////////////////////////////////
// Initializing MicroLan for specified iPort, iPortType.
////////////////////////////////////////////////////////////
bool COneWire::StartSession()
{
    int result;
    if (hInst != NULL)
    {
        SHandle = TMExtendedStartSession(iPortNum,iPortType,NULL);
        if(SHandle > 0)
        {
            // must be called before any non-session functions can be called
            result = TMSetup(SHandle);
            if(result == 1)
            {
                // MicroLan is valid and setup
                iError = OW_NO_ERROR;
                return true;
            }
            else if(result == 0)
            {
                iError = OW_SETUP_FAILED;
                return false;
            }
            else if(result == 2)
            {
                iError = OW_SETUP_MICROLAN_SHORTED;
                return false;
            }
            else if(result == 3)
            {
                iError = OW_SETUP_MICROLAN_NOT_EXIST;
                return false;
            }
            else if(result == 4)
            {
                iError = OW_SETUP_NOT_SUPPORTED;
                return false;
            }
            else
            {
                iError = OW_SESSION_INVALID;
                return false;
            }
        }
        else if(SHandle == 0)
        {
            iError = OW_SESSION_PORT_NOT_AVAILABLE;
            return false;
        }
        else if(SHandle == -1)
        {
            iError = OW_SESSION_NO_DRIVER;
            return false;
        }
        else
        {
            iError = OW_FUN_TMExtendedStartSession;
            return false;
        }
    }
    iError = OW_SESSION_NO_DRIVER;
    return false;
}

When 1-Wire devices are no longer necessary, the EndSession function should be called. Then, it is possible to start a new session.

////////////////////////////////////////////////////////////
// Closing current session for 1-Wire devices.
////////////////////////////////////////////////////////////
bool COneWire::EndSession()
{
    int result;

    if(SHandle > 0)
    {
        result = TMEndSession(SHandle);
        SHandle = NULL;

        if(result == 1)
        {
            iError = OW_NO_ERROR;
            return true;
        }
        else if(result == 0)
        {
            iError = OW_SESSION_HANDLE_ALREADY_INVALID;
            return false;
        }
        else
        {
            iError = OW_FUN_TMEndSession;
            return false;
        }
    }
    else
    {
        iError = OW_SESSION_STOPPED;
        return false;
    }
}

When a session is initialized successfully, the FindDevices function should be called. All connected 1-Wire devices are detected and their unique ROM codes stored in the ROM table. The FindDevices function also checks whether the obtained ROM code has not been corrupted during data sending.

////////////////////////////////////////////////////////////
// Finding all connected 1-Wire devices. The function
// returns number of all devices that were found.
////////////////////////////////////////////////////////////
int COneWire::FindDevices()
{
    int didsetup,result, <doce>DevId,i;

    if (SHandle > 0)
    {
        didsetup = 0;
        DevId = 0;
        while(1)
        {
            // check to see if TMSetup has been done once
            if (!didsetup)
            {
                result = TMSetup(SHandle);
                if(result == 1)
                    didsetup = 1;
                else if(result == 0)
                {
                    iError = OW_SETUP_FAILED;
                    return 0;
                }
                else if(result == 2)
                {
                    iError = OW_SETUP_MICROLAN_SHORTED;
                    return 0;
                }
                else if(result == 3)
                {
                    iError = OW_SETUP_MICROLAN_NOT_EXIST;
                    return 0;
                }
                else if(result == 4)
                {
                    iError = OW_SETUP_NOT_SUPPORTED;
                    return 0;
                }
                else
                {
                    iError = OW_SESSION_INVALID;
                    return 0;
                }
            }
            else
            {
                // only get the next rom after setup complete
                result = TMNext(SHandle,(void far*)StateBuffer);
                if (result > 0)
                {
                    ROM[DevId][0] = 0;
                    result = TMRom(SHandle,(void far *)StateBuffer,(short far *)ROM[DevId]);
                
                    //CRC check:
                    CRC8 = 0;
                    for(i=0;i<7;i++)
                    DoCrc((unsigned char)ROM[DevId][i]);
                    if(DoCrc((unsigned char)ROM[DevId][7]) != 0)
                    {
                        iError = OW_CRC_ERROR;
                        for (i = 0; i < 8; i++)
                        ROM[DevId][i] = 0;
                        return 0;
                    }
                    DevId++;
                }
                else
                    break;
            }
        }
    }
    else
    {
        iError = OW_SESSION_INVALID;
        return 0;
    }

    if(!DevId)
    {
        iError = OW_ZERO_DEVICES;
        return 0;
    }

    iError = OW_NO_ERROR;
    NumberOfDev = DevId;
    return NumberOfDev;
}

All 1-Wire devices provided by the Dallas Semiconductor Corp.[1] contain two groups of commands. The first one is common for all devices (i.e., devices finding, skip ROM command) and the second is suitable only for one 1-Wire device (i.e., temperature conversion). That is why I have written the base class COneWire and the CDS18B20, an inferior class. The function ReadTemperature modifies two variables, CurrTemp and PrevTemp. It also checks if the data received by the PC was not corrupted.

////////////////////////////////////////////////////////////
// Procedure for reading temperature from specified device.
////////////////////////////////////////////////////////////
bool CDS18B20::ReadTemperature()
{
    unsigned char DATA[10];
    unsigned long st;
    int i;

    if (TMAccess(SHandle,&StateBuffer) != 1)
    {
        iError = OW_NO_PRESENCE;
        return false;
    }

    if(!Reset())
    {
        iError = OW_NO_PRESENCE;
        return false;
    }

    TMTouchByte(SHandle,0x55);

    if(!SendROM())
    {
        iError = OW_NO_PRESENCE;
        return false;
    }

    TMOneWireLevel(SHandle,0,1,2);
    TMTouchByte(SHandle,0x44);
    st = GetTickCount() + 1000; 
    while (GetTickCount() < st)
    TMValidSession(SHandle);
    TMOneWireLevel(SHandle,0,0,0);
    if(!Reset())
    {
        iError = OW_NO_PRESENCE;
        return false;
    }

    TMTouchByte(SHandle,0x55);
    if(!SendROM())
    {
        iError = OW_NO_PRESENCE;
        return false;
    }

    TMTouchByte(SHandle,0xBE);

    // check CRC8
    CRC8 = 0;
    for(i=0;i<8;i++)
    {
        DATA[i] = (unsigned char)TMTouchByte(SHandle,(short)0xFF);
        DoCrc(DATA[i]);
    }
    
    if(DoCrc((unsigned char)TMTouchByte(SHandle,(short)0xFF)) != 0)
    {
        iError = OW_CRC_ERROR;
        return false;
    }

    iError = OW_NO_ERROR;
    PrevTemp = CurrTemp;
  
    // TLSB -> DATA[0], TMSB -> DATA[1]
    CurrTemp = ((float)DATA[0] + ((float)DATA[1]*256.0f))/16.0f;
    return true;
}

Usage

// connecting to com port 1
CDS18B20 term("IBFS32.DLL",OW_ADAPTER_DS9097E,1);

void main()
{
    Resolution res;
    short th,tl;

    if(term.StartSession())
    {
        if(!term.FindDevices())
        exit(-1);
        term.SetDevice(0); // selecting the firs device
        term.ReadScratchpad(&res,&tl,&th);
           // setting resolution to 12-bit, 
           // low temp. alarm 0 deg., high temp. alarm 20 deg.
        if(res != DS18B20_RES_12)
        // if resolution in DS18B20 is less than 12 then change it
        {
            term.WriteScratchpad(DS18B20_RES_12,0x0,0x14);
            term.CopyScratchpadToEEPROM(); // copies settings to EEPROM
        }
    }
    
    /* ... */

    while(!_kbhit())
    {
        if(term.ReadTemperature() && 
          (term.GetCurrTemp() != term.GetPrevTemp()))
        {
            /* display temperature */
        }
    }

    term.EndSession();
}

Conclusions

The COneWire class enables to communicate with different kinds of 1-Wire devices. It provides many useful functions for sending and receiving commands, writing and reading the scratchpad, and many others. The article described the common applications of 1-Wire devices, like the measurement of the most important physical parameter - temperature.

Bibliography

  1. iButton
  2. GLUT - The OpenGL Utility Toolkit
  3. iButton®: 1-Wire® SDK for Windows

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Jakub Piwowarczyk
Engineer Technical University of Lodz
Poland Poland
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionSource code for Visual Basic 6?memberholbxas26 Sep '10 - 11:22 
Source code for Visual Basic 6?
AnswerRe: Source code for Visual Basic 6?memberJakub Piwowarczyk8 Dec '11 - 8:42 
Unfortunately I do not have code in visual basic
Jakub Piwowarczyk

GeneralschematicmemberFlackPanzer7 Jun '10 - 11:05 
Hi Smile | :)
 
you can pass me the names of components, to help me find him in Eagle.
 
ThanksSmile | :)
GeneralRe: schematicmemberJakub Piwowarczyk8 Dec '11 - 8:41 
I am using protel 99se. For unknown elements I am creating dedicated libs.
Jakub Piwowarczyk

GeneralTryed- it works!memberingvar810 Feb '10 - 20:11 
My plan is adopt this to USB
I know how match works is behind that.
 
Great work, consider the materials behind that subject is not really good covered.
GeneralRe: Tryed- it works!memberJakub Piwowarczyk1 Mar '10 - 3:22 
It was my first such project, now I have better practice.
To adopt it to usb you should use FTDI Chip (http://www.ftdichip.com[^])
Jakub Piwowarczyk

GeneralUSB iButtonmembertransoft20 Apr '09 - 15:57 
Hi
 
Is there any USB iButton?
 
Thanks
GeneralRe: USB iButtonmemberJakub Piwowarczyk21 Apr '09 - 0:06 
You can use RS232 to USB converter or buy special adapter with USB interface http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3834[^]
 
Jakub Piwowarczyk

GeneralNice articlememberPolanek16 Mar '09 - 11:48 
Best regards
QuestionGreat article!memberAngel Kafazov11 Feb '09 - 1:34 
Hi, very good article, I love it.
 
What kind of hardware (sensors/devices) can one hook on this kind of wire? I am interested in energy monitoring applications, do you have something in mind about that?

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130523.1 | Last Updated 2 Feb 2009
Article Copyright 2009 by Jakub Piwowarczyk
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid