라즈베리파이, 아두이노

[간단한 아두이노 코딩] 5. 온도 센서 사용하기(DS18B20, LM35)

포도알77 2020. 11. 24. 10:08

온도 센서 사용하기(DS18B20, LM35)

 

1. 온도 센서 (DS18B20, LM35)

 가장 흔하게 볼 수 있는 온도 센서는 아날로그 LM35와 디지털 DS18B20이다. 아날로그 센서는 아두이노의 아날로그 핀으로 0~1023까지 값에 해당하는 결과를 반환한다. 이 값은 각 센서 제조사에서 제공하는 공식을 통하여 실제 온도 값을 구할 수 있다. 반면 디지털 센서는 직접 그 값을 반환하기 때문에 별도로 계산할 필요는 없지만 일부 센서의 경우 해당 업체의 라이브러리가 필요한 경우가 있다.

 

 이번 포스팅에서는 아날로그 온도 센서인 LM35와 디지털 온도 센서인 DS18B20을 이용하여 온도를 구해보고, 두 개의 온도 센서의 평균 값이 30이 넘는 경우 LED를 동작하는 간단한 코드를 작성한다.

 


2. LM35 온도 읽기

 LM35는 아날로그 센서로 섭씨 2도에서 150도까지 측정할 수 있다. 또한 0도(0v)부터 1도 상승시 마다 0.01V(10mV)가 증가한다. 입력 핀은 5v, GND 그리고 데이터 라인이며, 데이터 라인은 아날로그 값이므로 아두이노의 ANALOG IN 핀에 입력해야 한다.

 

 아두이노 아날로그 값(X)은 0~1023으로 리턴되며, 이는 GND부터 기준 전압 Vref 값을 매핑한 것과 같다. 따라서 기준전압이 5V라면, 5*X/1024로 계산하면 0~5V 값을 얻을 수 있다.

 이때 LM35 센서는 0.01V마다 1도를 표현하므로, 5*X/1024/0.01으로 계산하게 되면 실제 온도 값을 알 수 있다. 여기서 0.01을 나누는 것은 100을 곱하는것과 같으므로 다시금 아래와 같이 쓸 수 있다.

 

측정 온도 = 5 * X * 100 / 1024

 

 


3. LM35 소스코드

 아날로그 값을 1024로 다시 나누었기 때문에 값은 [0,1)이다. 따라서 항상 소수점으로 계산되어야 정상적인 온도를 구할 수 있다. 이를 위하여 5를 5.0으로 표현하여 소수임을 컴파일러에게 알려준다. 이후에는 항상 큰 방향으로 타입 캐스팅이 일어나므로 신경쓰지 않아도 된다.

 

 또한 Serial 통신을 이용하여 컴퓨터에 실제 센서에서 읽은 값을 출력하기 위하여 setup에서 Serial.begin을 호출하여 준다. 이후 출력하고자하는 내용을 Serial.print 함수를 통해 진행한다. 시리얼 모니터는 단축키 ctrl+shift+M을 통해서 켤 수 있다. 

#define TEMP_LM35 A0

void setup() {
  // 컴퓨터와 UART 통신을 하여, 
  // 아두이노 IDE에 데이터를 송수신 할 수 있음
  // Baud Rate 9600
  Serial.begin(9600);
}

void loop() {
  // LM35 온도 공식을 이용하여 온도값 계산
  // 1도 0.01v 상승
  // 아두이노 아날로그 핀은 0~1까지 0~1023에 대응된다.
  // 따라서 읽은 값을 X는 5V 인가를 감안하면
  // 5 * X / 1024 / 0.01
  // ==  5*X*0.01/1024 == 5*X*100/1024가 된다.
  
  float temp_lm35 = (5.0*analogRead(TEMP_LM35)*100)/1024;
  Serial.print("LM35: "); Serial.println(temp_lm35);
  delay(1000);
}

 

아래와 같이 시리얼 모니터에서 LM35에서 읽은 온도 값이 출력된다.

 


4. DS18B20 온도 읽기

 DS18B20은 디지털 온도 센서로 해당 센서를 읽기 위해서는 라이브러리를 이용하거나 혹은 주소값을 이용하여 직접 엑세스 하여야 한다. 그러나 아두이노에서는 굳이 그런 난이도의 접근은 필요없겠다 싶어서 라이브러리를 이용한 간단한 방법을 포스팅한다.

 

 DS18B20은 LM35와 똑같이 3개의 핀을 가지며, 차이점이라면 Pull up 저항을 데이터 라인에 달아주어야 한다. 이때 권장 저항은 4.7k이지만 만약 동일한 저항이 없다면 비슷한 저항을 달아주면 된다.

 

 디지털 센서이므로 데이터 라인은 디지털 핀 2번에 연결해준다. 

 

 


5. DS18B20 소스코드 + 라이브러리 추가하기

 

 

 이제 라이브러리를 추가해보자. 

 (1) 상단 메뉴의 스케치-> 라이브러리 포함하기 -> 라이브러리 관리 혹은 ctrl + shift +I를 눌러 준다.

 

 (2) 라이브러리 매니저에 DS18B20을 검색해서 Dallas Temperature를 설치하여 준다.

 아래와 같은 창이 나온다면, 그냥 Install All을 해주는 편이 낫다.

 

 이제 소스코드를 작성하자. 이러한 예제 코드는 각 라이브러리에 포함되어 있거나 혹은 구글링을 하면 쉽게 찾을 수 있다.

// DS 온도 라이브러리 추가
#include <OneWire.h>
#include <DallasTemperature.h>

// DS18B20 디지털 2번핀
#define TEMP_18B20 2

// 라이브러리 호출 방식에 따라 호출
OneWire oneWire(TEMP_18B20);
DallasTemperature sensors(&oneWire);

void setup() {
  Serial.begin(9600);
}

void loop() {
  // 센서 값을 읽음(다수개의 DS18B20 연결 가능)
  sensors.requestTemperatures();
  // 첫번째 DS18B20의 온도를 가져옴
  float temp_18b20 = sensors.getTempCByIndex(0);
  Serial.print("DS18B20: "); Serial.println(temp_18b20);
  delay(1000);
}

 

 실제 실행한 결과는 다음과 같다.


6. 두 온도 센서를 읽어 LED 켜기

 

 이제 서로 다른 두 온도 센서의 결과를 평균내어 30도가 넘어가면 LED를 켜는 회로를 구성해보자. 이 두개를 섞어 쓰는 이유는 서로 다른 종류이기도 하지만, 온도 센서 자체의 오차가 존재함을 알았으면 하는 뜻이 담겨있다.

 

 각 센서의 회로 구성은 달라진 것 없이 동일하며, LED 회로 또한 이전 포스트에서 꾸준히 사용한 형식이다.

LM35는 A1, DS18B20은 D2 그리고 LED는 D8핀을 이용할 것이다.

 ** A0에서 A1으로 바뀐 것은 아래의 회로도를 A1으로 캡쳐해버려서이다. 별뜻 없음

 

 

#include <OneWire.h>
#include <DallasTemperature.h>

#define LED_RED 8
#define TEMP_LM35 A1
#define TEMP_18B20 2

OneWire oneWire(TEMP_18B20);
DallasTemperature sensors(&oneWire);

void setup() {
  Serial.begin(9600);
  pinMode(LED_RED, OUTPUT);
}

void loop() {
  float temp_lm35 = (5.0*analogRead(TEMP_LM35)*100)/1024.0;
  
  sensors.requestTemperatures();
  float temp_18b20 = sensors.getTempCByIndex(0);
  Serial.print("LM35: "); Serial.print(temp_lm35);
  Serial.print(", DS18B20: "); Serial.println(temp_18b20);
  delay(1000);

  int led_on = (temp_18b20+temp_lm35)/2 > 30.0;
  digitalWrite(LED_RED, led_on);
}
페이스북으로 공유카카오톡으로 공유카카오스토리로 공유트위터로 공유URL 복사