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.
bool COneWire::StartSession()
{
int result;
if (hInst != NULL)
{
SHandle = TMExtendedStartSession(iPortNum,iPortType,NULL);
if(SHandle > 0)
{
result = TMSetup(SHandle);
if(result == 1)
{
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.
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.
int COneWire::FindDevices()
{
int didsetup,result, <doce>DevId,i;
if (SHandle > 0)
{
didsetup = 0;
DevId = 0;
while(1)
{
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
{
result = TMNext(SHandle,(void far*)StateBuffer);
if (result > 0)
{
ROM[DevId][0] = 0;
result = TMRom(SHandle,(void far *)StateBuffer,(short far *)ROM[DevId]);
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.
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);
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;
CurrTemp = ((float)DATA[0] + ((float)DATA[1]*256.0f))/16.0f;
return true;
}
Usage
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); term.ReadScratchpad(&res,&tl,&th);
if(res != DS18B20_RES_12)
{
term.WriteScratchpad(DS18B20_RES_12,0x0,0x14);
term.CopyScratchpadToEEPROM(); }
}
while(!_kbhit())
{
if(term.ReadTemperature() &&
(term.GetCurrTemp() != term.GetPrevTemp()))
{
}
}
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
- iButton
- GLUT - The OpenGL Utility Toolkit
- iButton®: 1-Wire® SDK for Windows