Click here to Skip to main content
15,861,168 members
Articles / Multimedia / OpenGL

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

Rate me:
Please Sign up or sign in to vote.
4.86/5 (35 votes)
2 Feb 2009CPOL4 min read 112.1K   2K   61   26
The article describes how to make a DS9097E adapter and read the temperature from a DS18B20 sensor by using the COneWire class.

Image 1

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.

Image 2

Fig. 1. Schematic diagram of the DS9097E adapter.

Image 3

Fig. 2. Ready DS9097E adapter.

Image 4

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.

C++
////////////////////////////////////////////////////////////
// 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.

C++
////////////////////////////////////////////////////////////
// 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.

C++
////////////////////////////////////////////////////////////
// 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.

C++
////////////////////////////////////////////////////////////
// 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

C++
// 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)


Written By
Engineer Technical University of Lodz
Poland Poland
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionQuestion Pin
Member 131488592-May-17 7:28
Member 131488592-May-17 7:28 
QuestionSource code for Visual Basic 6? Pin
holbxas26-Sep-10 11:22
holbxas26-Sep-10 11:22 
AnswerRe: Source code for Visual Basic 6? Pin
Jakub Piwowarczyk8-Dec-11 8:42
Jakub Piwowarczyk8-Dec-11 8:42 
Generalschematic Pin
Alexandre Bencz7-Jun-10 11:05
Alexandre Bencz7-Jun-10 11:05 
GeneralRe: schematic Pin
Jakub Piwowarczyk8-Dec-11 8:41
Jakub Piwowarczyk8-Dec-11 8:41 
GeneralTryed- it works! Pin
ingvar810-Feb-10 20:11
ingvar810-Feb-10 20:11 
GeneralRe: Tryed- it works! Pin
Jakub Piwowarczyk1-Mar-10 3:22
Jakub Piwowarczyk1-Mar-10 3:22 
GeneralUSB iButton Pin
transoft20-Apr-09 15:57
transoft20-Apr-09 15:57 
GeneralRe: USB iButton Pin
Jakub Piwowarczyk21-Apr-09 0:06
Jakub Piwowarczyk21-Apr-09 0:06 
GeneralNice article Pin
Polanek16-Mar-09 11:48
Polanek16-Mar-09 11:48 
QuestionGreat article! Pin
Angel Kafazov11-Feb-09 1:34
Angel Kafazov11-Feb-09 1:34 
AnswerRe: Great article! Pin
Jakub Piwowarczyk11-Feb-09 5:24
Jakub Piwowarczyk11-Feb-09 5:24 
General22.2 Pin
Stan Alex9-Feb-09 3:37
Stan Alex9-Feb-09 3:37 
Nice weather in Poland there! Cool | :cool:
GeneralRe: 22.2 Pin
Jakub Piwowarczyk9-Feb-09 8:52
Jakub Piwowarczyk9-Feb-09 8:52 
GeneralQuestion Pin
WKremlor8-Feb-09 4:46
WKremlor8-Feb-09 4:46 
GeneralRe: Question Pin
Jakub Piwowarczyk9-Feb-09 8:48
Jakub Piwowarczyk9-Feb-09 8:48 
Generalit's cool! Pin
Jason.LYJ6-Feb-09 20:51
professionalJason.LYJ6-Feb-09 20:51 
QuestionWhere can I buy those parts used in your article? Pin
transoft3-Feb-09 2:45
transoft3-Feb-09 2:45 
AnswerRe: Where can I buy those parts used in your article? Pin
Jakub Piwowarczyk3-Feb-09 11:33
Jakub Piwowarczyk3-Feb-09 11:33 
AnswerRe: Where can I buy those parts used in your article? Pin
John M. Drescher6-Feb-09 3:25
John M. Drescher6-Feb-09 3:25 
GeneralGreat Pin
sam.hill2-Feb-09 18:40
sam.hill2-Feb-09 18:40 
GeneralRe: Great Pin
Jakub Piwowarczyk4-Feb-09 1:07
Jakub Piwowarczyk4-Feb-09 1:07 
GeneralHardware Pin
supercat92-Feb-09 12:18
supercat92-Feb-09 12:18 
GeneralRe: Hardware Pin
Jakub Piwowarczyk3-Feb-09 2:15
Jakub Piwowarczyk3-Feb-09 2:15 
GeneralInteresting article Pin
Jim Crafton2-Feb-09 9:25
Jim Crafton2-Feb-09 9:25 

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

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.