본문 바로가기
Study/Arduino

Arduino 1-Wire DS18B20 (온도센서 )

by Answer Choi 2018. 4. 4.
반응형


1-Wire


1-Wire는 I²C와 비슷한 듯 하지만, I²C는 선 하나는 클럭신호를, 나머지 선 하나는 데이를 전달합니다.


1-Wire는 Dallas Semiconductor(현재 Maxim Integrated)에서 만들었으며, 


데이터 전송속도가 느리고, 장거리 통신이 가능합니다.


보통 온도계나 기상 관측장비같은 비싸지 않은 장비들에 많이 사용됩니다.


1-Wire 네트워크에 연결된 디바이스들중 마스터 디바이스는 MircoLAN이라고 부릅니다.


마스터에서 타이밍을 이용하여 디바이스를 초기화 하고, 데이터를 쓰고, 읽어옵니다.


DS18B20


DS18B20은 통신선 하나만을 사용하는 1-Wire방식의 온도센서입니다.



<DS18B20 모듈>


DS18B20 온도센서 모듈입니다.


저항과 캐패시터등 주변회로가 달려있습니다.


위쪽 핀을 보면 왼쪽과 오른쪽은 전원이고, 가운데가 데이터 통신을 하는 출력부분입니다.



<확대한 모습>


DS18B20은 -55℃~+125℃까지의 범위 측정이 가능하며, 


-10℃~+85℃사이는 ±5℃의 정확도를 갖습니다.


또한 9-bit~12bit로 온도값을 정밀하게 가져오도록 프로그래밍 가능합니다.


<DS18B20 Datasheet>


DS18B20의 데이터 시트의 온도 레지스터를 보면 16비트의 값으로 되어있습니다.


12비트인 경우 비트 0부터 비트 15까지 모두 사용되고,


11비트인 경우 1~15, 10비트인 경우 2~15, 9비트인 경우 3~15입니다.


비트 0~3은 소수점 값입니다.


Table 1을 보면 온도값의 예시값이 나와있는데, 온도 레지스터의 S는 영상/영하를 뜻합니다.


즉 S가 1이면 영하의 값, S가 0이면 영상의 값입니다.


그리고 2의 보수로 계산이 됩니다.


예를 들어 0.5℃인 경우 0000 0000 0000 1000입니다.


-0.5℃인 경우 2의 보수법을 적용하여 1111 1111 1111 1000이 됩니다.


S 비트(비트11~15)는 모두 1이 됩니다.


<DS18B20 Memory Map>


DS18B20으로부터 9byte의 데이터를 읽어와서 0번지와 1번지의 값을 읽어 연산하면,


온도값을 알 수 있습니다.




아두이노로 연결하기




DS18B20의 OUT 부분을 아두이노 2번핀에 연결하였습니다.


<실제 연결모습>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <OneWire.h>
 
int DS18S20_Pin = 2//DS18S20 Signal pin on digital 2
 
//Temperature chip i/o
OneWire ds(DS18S20_Pin);  // on digital pin 2
 
void setup(void) {
  Serial.begin(9600);
}
 
void loop(void) {
  float temperature = getTemp();
  Serial.println(temperature);
   
  delay(100); //just here to slow down the output so it is easier to read
   
}
 
 
float getTemp(){
  //returns the temperature from one DS18S20 in DEG Celsius
 
  byte data[12];
  byte addr[8];
 
  if ( !ds.search(addr)) {
      //no more sensors on chain, reset search
      ds.reset_search();
      return -1000;
  }
 
  if ( OneWire::crc8( addr, 7!= addr[7]) {
      Serial.println("CRC is not valid!");
      return -1000;
  }
 
  if ( addr[0!= 0x10 && addr[0!= 0x28) {
      Serial.print("Device is not recognized");
      return -1000;
  }
 
  ds.reset();
  ds.select(addr);
  ds.write(0x44,1); // start conversion, with parasite power on at the end
 
  byte present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE); // Read Scratchpad
 
   
  for (int i = 0; i < 9; i++) { // we need 9 bytes
    data[i] = ds.read();
  }
   
  ds.reset_search();
   
  byte MSB = data[1];
  byte LSB = data[0];
 
  float tempRead = ((MSB << 8| LSB); //using two's compliment
  float TemperatureSum = tempRead / 16;
   
  return TemperatureSum;
   
}
cs

<샘플코드>


샘플코드는 모듈 제조업체에서 가져왔습니다.


위 코드를 실행하기전에 onewire 라이브러리를 꼭 설치해 주셔야 합니다.


Line 3~6 : Onewire로 통신 할 GPIO 포트를 설정해 주는 부분입니다.


Line 13~14 : 1-Wire로 온도값을 읽어와서 터미널로 보여주는 코드입이다.


Line 27~41 : 연결된 1-Wire가 제대로 연결되어 있는지 확인합니다.


자세히 살펴보면 위 부분을 읽어옵니다.


Line 27~31 : 위 부분을 못읽어 오면 -1000을 리턴합니다.


Line 33~36 : 위 부분에서 상위 8비트인 CRC가 틀리면 -1000을 리턴합니다.


Line 38~41 : 위 부분에서 하위 8비트인 패밀리코드 0x28h이 아니면 -1000을 리턴합니다.


(코드상 0x10h도 아니고, 0x28h도 아니면 -1000이 리턴됩니다. DS18B20은 0x28h입니다.)


Line 43~45 : DS18B20이 온도값을 읽어 ADC로 변환하여 레지스터에 저장합니다.


Line 47~49 : 메모리 맵을 읽어옵니다.


Line 52~56 : 읽어온 메모리맵의 값을 바이트 배열에 넣어줍니다.


Line 58~62 : 마지막 2바이트(메모리 맵의 0과 1번지)의 데이터를 연산하여 온도값을 구합니다.


여기까지가 Arduino에서 제공해 주는 1-Wire 라이브러리를 통해 


DS18B20의 온도를 구하는 코드입니다.


<1-Wire 라이브러리만 이용한 코드 실행결과>



만약 Dallas Temperature 라이브러리를 추가한다면, 더 간단히 구할 수 있습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Include the libraries we need
#include <OneWire.h>
#include <DallasTemperature.h>
 
// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2
 
// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);
 
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);
 
/*
 * The setup function. We only start the sensors here
 */
void setup(void)
{
  // start serial port
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");
 
  // Start up the library
  sensors.begin();
}
 
/*
 * Main function, get and show the temperature
 */
void loop(void)
  // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");
  // After we got the temperatures, we can print them here.
  // We use the function ByIndex, and as an example get the temperature from the first sensor only.
  Serial.print("Temperature for the device 1 (index 0) is: ");
  Serial.println(sensors.getTempCByIndex(0));  
}
cs


위 코드는 Dallas Temperature 라이브러리의 simple 예제코드입니다.


1-Wire 라이브러리만 사용한 것보다 훨신 간단합니다.


<1-Wire와 Dallas Temperature 라이브러리를 모두 이용한 코드 실행결과>


반응형

인기글