Politecnico di Torino
CORSO DI LAUREA MAGISTRALE IN INGEGNERIA ELETTRONICA
ELECTRONIC SYSTEMS ENGINEERING
Project
Barillaro Giuseppe 198431 Busignani Fabio 197883
25 dicembre 2013
Abstract This article is a report edited by Barillaro and Busignani where the steps to realize an acquisition system for temperature measuring, exploiting DS18B20 and ATmega328, are illustrated. The report is divided into six parts. The rst one is dedicated to description of temperature sensor used. The second and the third illustrate the rmware behavior, and how to use the graphic user interface respectively. The fourth part shows the systems tests. The fth one contains PCB description and the last has rmware and software code.
Contents
1 Introduction 2 DS18B20 2.1 Internal architecture . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Measuring Temperature . . . . . . . . . . . . . . . . . . . . . . . . 3 Firmware 4 Interface 5 Test 6 Schematic and PCB 1 2 2 5 6 7 9 11
7 Code 11 7.1 Arduino Wiring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11 7.2 C# - Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 List of Figures Bibliography 24 24
II
Introduction
The aim of this project is to design an acquisition system which allows to user to know the temperature value. In this system microcontroller drives the sampling data and sends it through serial communication to the PC. Sampling period is imposed by the user and can assume 15, 30, 45 and 60 seconds. This project is divided into three dierent steps: 1. Firmware realization (Sec.3). 2. Graphic user interface design (Sec.4). 3. Schematic and PCB design (Sec.6). Before starting with the previous steps, we show a summary of the used sensor, the DS18B20 (Sec:2). In order to achieve this project we used ve dierent softwares: Arduino IDE to create the rmware which describes the behavioral that ATmega328 has to be; Visual Studio 2013 to realize the GUI that user can exploit to set the options and view the temperature; Saleae Logic for testing the system using a logic analyzer; Cadence OrCAD Capture to design the schematic of the system; Cadence Allegro to design the PCB of the system. In the following sections the steps that we have followed are shown.
DS18B20
Figure 1: DS18B20 - Pin conguration The DS18B20 is a digital thermal sensor manufactured by DALLAS MAXIM, which is the owner of 1wire protocol, exploited by this device. The sensor provides a temperature value in Celsius degree, whit programmable resolution from 9 to 12 bit. It has an operating temperature range of 55 C to +125 C (with an accuracy equal to 0.5 C over the range of 10 C to +85 C ). We used the three pin TO-92 package, as shown in (Fig. 1). One of more relevant features is that this device can operate in parasitic mode, i.e. without any external power supply; exploiting this parasitic mode, the designer can place the sensor free from any kind of problems produced by power supplying (i.e. space constrains). Anyway in our project power source isnt a problem, thus we didnt exploit parasitic mode. In fact, the DS18B20 can also be powered by the conventional method of connecting an external power supply to the VDD pin, so the schematic of our circuit is shown in (Fig. 2).
Figure 2: DS18B20 - Hardware implementation
2.1
Internal architecture
Diving into the device, supporting by the (Fig. 3), we can notice that DS18B20 is composed of follows parts: 2
Figure 3: DS18B20 - Block diagram Parasitic power circuit This circuit, exploiting two diodes (D1 and D2 in (Fig. 3)), allows to recognize what kind of power mode is in use. When the parasitic mode is employed, VDD pin is tied to the ground thus D2 is reverse biased and the Cpp capacitor is charged by pull-up resistor of the bus through D1. This behavior can be done only in presence of an high logic level on the bus. In fact while a low logic level is present on it, both D1 and D2 are reverse biased, so capacitor is oating and the charge inside it is kept. 64-bit ROM It is a ROM memory which contain a serial code of 64 bits. This code is unique for each device and its exploit at every time the microprocessor which drives 1-wire bus, needs to recognize each device connected to the same bus. Since we used only a sensor, this code is completely useless in our design. Scratchpad It is a volatile SRAM composed of 9 byte: Byte 0: Temperature[LSB] Byte 1: Temperature[MSB] Byte 2: TH register Byte 3: TL register Byte 4: Conguration register Byte 5: Reserved Byte 6: Reserved Byte 7: Reserved Byte 8: CRC ROM code
Conguration register This register is located both within the Scratchpad and EEPROM, in order to keep in device memory its content also when the power supply is unplugged. Conguration register can be exploited by the user for setting the converter resolution bits of DS18B20, through two bits: R0 and R1 as explained in (Fig. 4). The same gure shown the compromise between resolution bits and conversion time due to the analog to digital conversion process.
Figure 4: DS18B20 - Conguration register 8-bit ROM code CRC It allows a periodic control of redundancy bits in order to check the data transmission and rectify any error. The ROM code CRC is computed on the rst 56 ROM bits and allocated in the most signicant byte of the register itself. So, to verify that the transmission is occurred without any error, the master recomputes the CRC value of coming data and veries whether the code is equal to the ROM CRC. Certainly, if user skips 64 ROM code request, CRC control will not able to be exploited. TH-TL Registers Two 8 bits registers which shall contain the minimum (TL) and the maximum (TH) measurable temperature. As the conguration register, also these two registers are either inside the Scratchpad and the EEPROM to keep the informations also after devices power-o. After every temperature conversion, the digital information is compared with TH and TL contents, if T > T H o T < T L an alarm is generated. For watching if a device connected to bus has generated an alarm, master can use Alarm Search [ECh] command which returns ROM code of every sensor which has the alarm ag asserts.
2.2
Measuring Temperature
As previously mentioned, the DS18B20 sensor exploits 1-wire protocol. The 1-Wire is a device communications bus system designed by Dallas - Maxim that provides low-speed data (16 Kbps) and power over a single signal wire. The kind of transmission is half duplex, thus both the master and the slave can receive/transmit data. The 1-Wire bus system uses a master - multi slaves protocol. To start the transaction for accessing the DS18B20 an exact sequence has to be followed. The sequence is exhibits in block diagram of (Fig. 7(b)) and its composed by following steps: 1. Initialization The bus master transmits a reset pulse, whether a slave is tied to the bus, it replies with a pulse. Timing for the reset and presence pulse is illustrated in (Fig. 5).
Figure 5: 1-Wire - Initialization timing 2. Skip ROM[CCh] After that the connected device replies to reset pulse, since we used only one sensor, the second command sends by master is Skip ROM. Using this command, the master addresses all devices on the bus. 3. Convert Temperature[44h] To initiate a single temperature conversion, master send this command on the bus. Following the analog to digital conversion, thermal data is stored in two registers of Scratchpad: TH and TL . Conversion process takes amount of time shown in (Fig. 4). In (Fig. 6) the two bytes in which temperature is stored are illustrated. Thus, 4 bits are dedicated to decimal part, 7 bits to integer part and one bit to the sign(S): S = 0 positive temperature, S = 1 negative temperature. 4. First and second step are redone 5. Read Scratchpad [BEh] Finally, master sends this command to read the contents of the Scratchpad. 5
Figure 6: DS18B20 - Temperature data registers The data transfer starts with the least signicant byte and continues through the Scratchpad until the last signicant byte. So, rst byte received represent the LSB, while the second is the MSB.
Firmware
To realize this project an ATmega328 microcontroller is exploited. The code of the rmware is shown in (Sec.7). The microcontroller communicates with PC for setting the sampling period and ADC bits resolution, and also for visualizing the temperature on PCs monitor. In this design, two dierent library are exploited: Timer library, to control the sampling period, implementing a software counter. Software because timer internal to ATmega328 can achieve as maximum interrupt period 8388.608 mS , which is lower than minimum sampling period. OneWire library, to use 1-Wire standard protocol. The rmware describes the following behavioral: microcontroller wait that data about ADC bits resolution and sampling period have come from the serial port, after that it follows the steps shown in (Fig.7(b)) and described in (Sec.2.2) for obtaining temperature value every sampling period. So, when ATmega328 receives the temperature data, it immediately sends these data to PC. In fact, computer will be delegated for data decoding because it has better resolution for arithmetical operations that microcontroller. The main can be described by (Fig.7(a)),
(a) Main
(b) Temperature acquisition process
Figure 7: Flow chart
Interface
As already mentioned, in our design, user can interact with the system through the PC. To ease this interaction we realized a simple program using Visual Studio 2013 , so the consumer can use a GUI (Graphic User Interface) for changing some options.
Figure 8: Window of the program The program is composed by just a form, so user can modify the setting and view the temperature value through a window shown in (Fig. 8). Watching (Fig. 8) the parts of program are exposed: TextBox, where user can see the temperature value in the selected unit; Temperature unit of measure ComboBox, where user can set three dierent units of measure: Celsius, Fahrenheit and Kelvin ; Open Serial Port Button, through this button user can open the selected serial port with selected settings; Start Button, with this user starts the communication between PC and microcontroller; Resolution ComboBox, where user can select the ADC bits resolution; Conversion Time Label, this label shows the time employed to the analog to digital conversion process; PORT ComboBox, where user can choose between available PORT COM that where embedded system is connected; Baudrate ComboBox, this can be exploited by the user for setting the communication baudrate; Sampling Period ComboBox, through this combo box the user can choose when temperature has to be update.
Test
For testing the design we used a logic analyzer in order to watch the waveform. First of all we tested 1-Wire library, (Fig.9) shows the communication sequence between ATmega328 and DS18B20, when the rst reads temperature data from the second (last steps shown in (Fig.7(b))).
Figure 9: Read sensor sequence In (Fig.9) we can see the following command succession: 1. Bus Reset, according with the (Fig.5) the two initialization pulse can be show; 2. Skip ROM ; 3. Read Screatchpad, sending BEh (19010 ) master begins the data reading; 4. Receive LSB, microcontroller receives LSB data (18310 ); 5. Receive MSB, microcontroller receives MSB data (110 , so the temperature value in this case is given by 27.4375 C ) Second we tested the delay function exploited to ensure that ADC embedded inside the sensor can work well. Since this amount of time is function of bit resolution (Fig.4), we can see four dierent delays. As shown in (Fig:10) we chose to introduce delays bigger than that indicated in devices datasheet for being sure that conversion time is respected. Finally, we tested Timer library, used to realize the sampling period. From design specication, the users can choose timer period between 15, 30, 45 and 60 seconds. These four value of sampling period are tested and illustrated in (Fig11).
(a) 9 bits resolution
(b) 10 bits resolution
(c) 11 bits resolution
(d) 12 bits resolution
Figure 10: Delay in function of ADC resolution
(a) 15 seconds
(b) 30 seconds
(c) 45 seconds
(d) 60 seconds
Figure 11: Sampling period
10
6 7
7.1
1
Schematic and PCB Code
Arduino Wiring
#include Timer.h #include<OneWire.h> Timer t; OneWire ds(8);
11
int BIT = 0; byte Setting; long varPeriod = 0; int bo=0; char go = 0; byte LSB,MSB; int i = 0; void setup() { Serial.begin(9600); } void loop() { t.update(); if(bo==0) { if(Serial.available()>0) { BIT = Serial.parseInt(); //the rst data coming from PC is the ADC resolution switch (BIT) { case 9: Setting = 0x1F; break; case 10: Setting = 0x3F; break; case 11: Setting = 0x5F; break; case 12: Setting = 0x7F; break; } if(ds.reset()) {
16
21
26
31
36
41
11
46
ds.write(0x4E); //access in setting register ds.write(0x38); //upper bound +56 degree celsius ds.write(0x4A);//lower bound 10 degree celsius ds.write(Setting); } bo = 1;
51
56
61
66
71
} } else if(bo==1) { bo = 0; if(Serial.available()>0) { varPeriod = Serial.parseInt(); //seconds data is the sampling period switch (varPeriod) { case 15: varPeriod = 15000; break; case 30: varPeriod = 30000; break; case 45: varPeriod = 45000; break; case 60: varPeriod = 60000; break; } t.stop(i); i=t.every(varPeriod, CalcolaTemperatura); } } }
76
81
86
void CalcolaTemperatura() { if(ds.reset()) { //controls the presence of the sensor, making a line reset //Serial.println(Sensor present!); ds.skip(); //skips the ROM CODE reception, //due to the presence of just one sensor on the bus ds.write(0x44,1); //sends the request of conversion switch (BIT) { case 9: delay(100); //wait until the end of conversion
91
12
96
101
break; case 10: delay(200); //wait until the end of conversion break; case 11: delay(400); //wait until the end of conversion break; case 12: delay(800); //wait until the end of conversion break; } ds.reset(); ds.skip(); ds.write(0xBE); //sends read request:the sensor sends all data stored inside it LSB=ds.read(); //stores in LSB the content of bank 0 of the memory MSB=ds.read(); //stores in LSB the content of bank 1 of the memory Serial.println(LSB); Serial.ush(); Serial.println(MSB); Serial.ush(); } else Serial.println(no); }
106
111
116
7.2
1
C# - Form
System; System.Collections.Generic; System.ComponentModel; System.Data; System.Drawing; System.Linq; System.Text; System.Threading.Tasks; System.Windows.Forms; System.IO.Ports;
using using using using using using using using using using
11
16
namespace WindowsFormsApplication1 { public partial class Temperature : Form { delegate void PrintTempCallback(string text); string varCOM = COM5; int varBaudRate = 9600; int varBIT = 12; int varPeriod = 15;
13
21
26
31
36
byte MSB, LSB; short i; string varShowTemp; public Temperature() { InitializeComponent(); i = 0; button3.Enabled = false; comboBox1.Text = Celsius; varShowTemp = Celsius; comboBox2.Text = BIT.ToString(); comboBox3.Text = PortCOM; comboBox4.Text = BaudRate.ToString(); comboBox5.Text = Period.ToString(); serialPort1 = new SerialPort(); serialPort1.DataReceived += new SerialDataReceivedEventHandler(tempReceivedEventHandler); } private void Temperature Load(object sender, EventArgs e) { comboBox4.Items.AddRange(System.IO.Ports.SerialPort.GetPortNames()); } private void button2 Click(object sender, EventArgs e) { if (!serialPort1.IsOpen) { serialPort1.PortName = varCOM; serialPort1.BaudRate = varBaudRate; serialPort1.Parity = Parity.None; serialPort1.StopBits = StopBits.One; serialPort1.DataBits = 8; serialPort1.DtrEnable = true; serialPort1.Handshake = Handshake.None; serialPort1.ReceivedBytesThreshold = 1; try { serialPort1.Open(); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } this.button2.Text = Close; button3.Enabled = true; }
41
46
51
56
61
66
14
71
76
else { serialPort1.Close(); this.button2.Text = Open; button3.Enabled = false; } } private void tempReceivedEventHandler(object sender, SerialDataReceivedEventArgs e) { string temp = serialPort1.ReadLine(); temp = temp.TrimEnd(\r);//Rimuovo lacapo dalla stringa temp temp = temp.TrimEnd(\n);//Rimuovo lacapo dalla stringa temp if (temp == no) { PrintTemp(Sensor unconnected); i = 0; } else { if (i == 0) { LSB = Convert.ToByte(temp); i = 1; } else if (i == 1) { MSB = Convert.ToByte(temp); i = 2; busoStampa(); } } }
81
86
91
96
101
106
111
116
private void PrintTemp(string text) { // InvokeRequired required compares the thread ID of the // calling thread to the thread ID of the creating thread. // If these threads are dierent, it returns true. if (this.textBox1.InvokeRequired) { PrintTempCallback d = new PrintTempCallback(PrintTemp); this.Invoke(d, new object[] { text }); } else { this.textBox1.Text = text; }
15
121
} private void Temperature Closing(object sender, System.ComponentModel.CancelEventArgs e) { serialPort1.Close(); } private void button3 Click(object sender, EventArgs e) { serialPort1.Write(BIT.ToString() + + Period.ToString()); } private void PrintCelsius(byte MSB,byte LSB) { oat celsius = getCelsius(MSB, LSB); PrintTemp(Temperature: + celsius.ToString(0.0000)+ C); } private void PrintKelvin(byte MSB, byte LSB) { oat kelvin = getCelsius(MSB, LSB); kelvin += 273.15F; PrintTemp(Temperature: + kelvin.ToString(0.0000)+ K); } private void PrintFahrenheit(byte MSB, byte LSB) { oat Fahrenheit = getCelsius(MSB, LSB); Fahrenheit = 1.8F; PrintTemp(Temperature: + Fahrenheit.ToString(0.0000)+ F); } private oat getCelsius(byte MSB,byte LSB) { oat celsius = 0; switch(BIT) { case 9: if ((LSB & 0x80) == 0x80) { celsius += (oat)System.Math.Pow(2, 3); } if ((LSB & 0x40) == 0x40) { celsius += (oat)System.Math.Pow(2, 2); } if ((LSB & 0x20) == 0x20) { celsius += (oat)System.Math.Pow(2, 1); } if ((LSB & 0x10) == 0x10) { celsius += (oat)System.Math.Pow(2, 0);
126
131
136
141
146
151
156
161
166
16
171
176
181
186
191
196
201
206
211
216
} if ((LSB & 0x08) == 0x08) { celsius += (oat)System.Math.Pow(2, } if ((MSB & 0x01) == 0x01) { celsius += (oat)System.Math.Pow(2, } if ((MSB & 0x02) == 0x02) { celsius += (oat)System.Math.Pow(2, } if ((MSB & 0x04) == 0x04) { celsius += (oat)System.Math.Pow(2, } if ((MSB & 0x04) == 0x08) { celsius = 1; } break; case 10: if ((LSB & 0x80) == 0x80) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x40) == 0x40) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x20) == 0x20) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x10) == 0x10) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x08) == 0x08) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x04) == 0x04) { celsius += (oat)System.Math.Pow(2, } if ((MSB & 0x01) == 0x01) { celsius += (oat)System.Math.Pow(2,
1);
4);
5);
6);
3);
2);
1);
0);
1);
2);
4);
17
221
226
231
236
241
246
251
256
261
266
} if ((MSB & 0x02) == 0x02) { celsius += (oat)System.Math.Pow(2, } if ((MSB & 0x04) == 0x04) { celsius += (oat)System.Math.Pow(2, } if ((MSB & 0x04) == 0x08) { celsius = 1; } break; case 11: if ((LSB & 0x80) == 0x80) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x40) == 0x40) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x20) == 0x20) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x10) == 0x10) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x08) == 0x08) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x04) == 0x04) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x02) == 0x02) { celsius += (oat)System.Math.Pow(2, } if ((MSB & 0x01) == 0x01) { celsius += (oat)System.Math.Pow(2, } if ((MSB & 0x02) == 0x02) { celsius += (oat)System.Math.Pow(2,
5);
6);
3);
2);
1);
0);
1);
2);
3);
4);
5);
18
271
276
281
286
291
296
301
306
311
316
} if ((MSB & 0x04) == 0x04) { celsius += (oat)System.Math.Pow(2, } if ((MSB & 0x04) == 0x08) { celsius = 1; } break; case 12: if ((LSB & 0x80) == 0x80) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x40) == 0x40) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x20) == 0x20) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x10) == 0x10) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x08) == 0x08) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x04) == 0x04) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x02) == 0x02) { celsius += (oat)System.Math.Pow(2, } if ((LSB & 0x01) == 0x01) { celsius += (oat)System.Math.Pow(2, } if ((MSB & 0x01) == 0x01) { celsius += (oat)System.Math.Pow(2, } if ((MSB & 0x02) == 0x02) { celsius += (oat)System.Math.Pow(2,
6);
3);
2);
1);
0);
1);
2);
3);
4);
4);
5);
19
321
326
} if ((MSB & 0x04) == 0x04) { celsius += (oat)System.Math.Pow(2, 6); } if ((MSB & 0x04) == 0x08) { celsius = 1; } break; } return celsius; }
331
336
private void comboBox1 SelectedIndexChanged(object sender, EventArgs e) { varShowTemp = comboBox1.Text; }
341
private void textBox1 TextChanged 1(object sender, EventArgs e) { }
346
351
356
361
private void busoStampa() { switch (varShowTemp) { case Celsius: PrintCelsius(MSB, LSB); break; case Kelvin: PrintKelvin(MSB, LSB); break; case Fahrenheit: PrintFahrenheit(MSB, LSB); break; default: PrintCelsius(MSB, LSB); break; } i = 0; } public int Period { get {
366
20
371
return varPeriod; } set { varPeriod = value;
376
} } public int BIT { get { return varBIT; } set { varBIT = value; } } public string PortCOM { get { return varCOM; } set { varCOM = value; } } public int BaudRate { get { return varBaudRate; } set { varBaudRate = value; } } private void comboBox2 SelectedIndexChanged(object sender, EventArgs e) { BIT = Convert.ToInt32(comboBox2.Text); switch (BIT) { case 9: textBox2.Text = 93.75 ms;
381
386
391
396
401
406
411
416
21
421
426
break; case 10: textBox2.Text = 187.5 ms; break; case 11: textBox2.Text = 375 ms; break; case 12: textBox2.Text = 750 ms; break; } try { serialPort1.Write(BIT.ToString() + + Period.ToString()); } catch (Exception ex) { //MessageBox.Show(ex.ToString()); } } private void textBox2 TextChanged(object sender, EventArgs e) {
431
436
441
446
} private void comboBox3 SelectedIndexChanged(object sender, EventArgs e) { PortCOM = comboBox3.Text; } private void comboBox4 SelectedIndexChanged(object sender, EventArgs e) { BaudRate = Convert.ToInt32(comboBox4.Text); } private void comboBox5 SelectedIndexChanged(object sender, EventArgs e) { Period = Convert.ToInt32(comboBox5.Text); try { serialPort1.Write(BIT.ToString() + + Period.ToString()); } catch (Exception ex) { //MessageBox.Show(ex.ToString()); } }
451
456
461
466
22
471
} }
23
List of Figures
1 2 3 4 5 6 7 8 9 10 11 DS18B20 - Pin conguration . . . . . . DS18B20 - Hardware implementation . DS18B20 - Block diagram . . . . . . . DS18B20 - Conguration register . . . 1-Wire - Initialization timing . . . . . . DS18B20 - Temperature data registers Flow chart . . . . . . . . . . . . . . . . Window of the program . . . . . . . . Read sensor sequence . . . . . . . . . . Delay in function of ADC resolution . . Sampling period . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 3 4 5 6 7 8 9 10 10
Bibliography
Wikipedia page of 1-Wire; Datasheet of DS18B20, Dallas - Maxim ; Timer library, Arduino community ; 1-Wire library, Arduino community ;
24