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 라이브러리를 모두 이용한 코드 실행결과>
'Study > Arduino' 카테고리의 다른 글
비접촉 온도센서(4-20mA 출력) Arudino에서 읽기 (2) | 2018.05.04 |
---|---|
DFRobot Digital Vibration Sensor V2 (0) | 2018.05.03 |
Software Serial 사용하기 (0) | 2018.03.28 |
4-20mA 센서 Arduino에서 읽기(전류센서) (3) | 2018.03.19 |
Arduino Sensor kit 2 - 터치센서, 부저 (0) | 2017.09.20 |