티스토리 뷰

오늘은 1602A LCD모듈과 DHT11 온습도모듈을 가지고 온도와 습도를 측정할 수 있는 온습도계를 만들어보겠습니다.


간단하게 DHT11모듈을 이용하여 온도와 습도 수치를 구하고, 1602A 모듈을 이용하여 온도와 습도를 출력하는 것입니다.


두 모듈 모두 많이 많이 사용되는 모듈이고, 예제도 많이 나와있으면서, 가격도 저렴합니다.


시작합니다.


1. 하드웨어 구현




위 이미지를 보시면 RGB LED가 하나 보일 건데요. 이것은 온도와 습도에 맞춰서 쾌적한 온도와 습도인지 나타내기 위한 것으로 없어도 됩니다만, LCD를 멀리서 보기에 글자가 충분히 크지 않고, 색만으로도 충분히 판단할 수 있으므로 LED도 함께 추가해 봤습니다.


(1) 1602A LCD 연결하기

와이어의 연결에 주의하시기 바랍니다. 1602A와 연결되는 라인이 12개입니다. 그리고 가변저항이 하나 필요한데 이는 LCD의 도트밝기를 조정할 수 있도록 하는 저항입니다. 저게 없으면 화면에 아무것도 표시되지 않으므로 반드시 필요한 저항입니다.


(2) DHT11 연결하기

 또한 DHT11 단일 센서를 사용한게 아니고, 기판에 저항등이 작업된 3핀짜리를 기준으로 그림을 그린 것이니 착오가 없도록 합니다. (필요하시면 구글링을 통하여 DHT11의 저항과 4핀중에서 3핀을 구성하는 이미지가 있으므로 참고하시기 바랍니다.)

링크 : http://cdn.instructables.com/FMG/FO2Z/HXRZKJIB/FMGFO2ZHXRZKJIB.LARGE.jpg



2. 소프트웨어 구현



/*
  1602A LCD와 DHT를 이용한 온습도계

  The circuit:
 * LCD RS pin to digital pin 12
 * LCD Enable pin to digital pin 11
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VCC pin to 5V
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)

 This example code is in the public domain.

 http://www.arduino.cc/en/Tutorial/LiquidCrystal


 @auth 김은중
 @email dante2k@gmail.com
 */

// 라이브러리 추가
#include <LiquidCrystal.h>
#include <DHT.h>


// 온습도센서 DHT11 정의 및 초기화
#define PIN_DHT 6
#define DHTTYPE DHT11

DHT dht = DHT(PIN_DHT, DHTTYPE);


// 1602A LCD 초기화
#define PIN_LCD_RS 12
#define PIN_LCD_E 11
#define PIN_LCD_D4 5
#define PIN_LCD_D5 4
#define PIN_LCD_D6 3
#define PIN_LCD_D7 2

#define LCD_WIDTH 16
#define LCD_HEIGHT 2

LiquidCrystal lcd(PIN_LCD_RS, PIN_LCD_E,
    PIN_LCD_D4, PIN_LCD_D5, PIN_LCD_D6, PIN_LCD_D7);

// 섭씨를 표현하기 위한 작은 동그라미 기호
byte CHAR_DEGREE[8] = {
  B00010, B00101, B00010, B00000,
  B00000, B00000, B00000, B00000
};


// RGB LED 핀 정의
#define PIN_BLUE 10
#define PIN_GREEN 9
#define PIN_RED 8

#define COLOR_YELLOW -1
#define COLOR_VIOLET -2
#define COLOR_BLUE_GREEN -3
#define COLOR_BLACK -9

// 측정 주기
#define DELAY_READ_SENSOR 500

// LCD 표시 주기
#define DELAY_LCD_BLINK 500
#define DELAY_LCD_SCROLL 250

// RGB LED 테스트 딜레이
#define DELAY_LED_TEST 500

// 부팅메시지
#define STR_UPPER "Temp, Humidity"
#define STR_BOTTOM "Meter By Dante2K"

// 작동여부 표시용 플래그
boolean runFlag = true;

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

  // LCD 글자수, 줄수
  lcd.begin(LCD_WIDTH, LCD_HEIGHT);
  // 사용자문자 추가
  lcd.createChar(0, CHAR_DEGREE);

  // 3회 문자열 깜박임
  blinkUpperBottom(3, STR_UPPER, STR_BOTTOM);

  // 문자열 상단좌측, 하단우측 이동
  scrollUpperLeftBottomRight(STR_UPPER, STR_BOTTOM);

  // 온습도센서 시작
  dht.begin();

  // RGB LED 초기화
  pinMode(PIN_BLUE, OUTPUT);
  pinMode(PIN_GREEN, OUTPUT);
  pinMode(PIN_RED, OUTPUT);

  // RGB LED 테스트
  testLED();
}

void loop() {
  // DHT11 센서에서 온도, 습도 측정
  float temp = dht.readTemperature();
  float humidity = dht.readHumidity();

  // 정상적인 값이 조회되지 않으면 리턴
  if (isnan(temp) || isnan(humidity)) {
    return;
  }

  // 조회되면 온도, 습도를 LCD에 표시
  lcd.setCursor(0,0);
  lcd.print("Temperat:" + FtoS(temp));
  lcd.write(byte(0));
  lcd.print("C");
  lcd.setCursor(0,1);
  lcd.print("Humidity:" + FtoS(humidity) + " %");

  // 작동되는 것을 표시하기 위한 하단우측에 깜박임표시
  lcd.setCursor(15, 1);
  if (runFlag) {
    lcd.print(".");
  } else {
    lcd.print(" ");
  }
  runFlag = !runFlag;

  // 온도, 습도에 따라서 RGB LED로 표시
  controlLED(temp, humidity);

  delay(DELAY_READ_SENSOR);
}

/**
 * float형 숫자, 소수부분이 0인경우 정수로, 소수부분이 0이 아닌
 * 숫자라면 소수점 이하 첫째자리까지만 표시
 */
static String FtoS(float num) {
  String str = (String) num;

  if ((int) num == num) {
    return str.substring(0, str.indexOf("."));
  } else {
    return str.substring(0, str.indexOf(".") + 2);
  }
}

/**
 * 상단은 우에서 좌로, 하단은 좌에서 우로 이동
 */
void scrollUpperLeftBottomRight(String sUpr, String sBtm) {
  int sUprLen = sUpr.length();
  int sBtmLen = sBtm.length();
  int maxLen = max(sUprLen, sBtmLen);

  // Serial.println("sUprLen:" + String(sUprLen)
  //    + ", sBtmLen:" + String(sBtmLen)
  //    + ", max:" + String(maxLen));

  for (int i = 0; i < LCD_WIDTH + maxLen + 1; i++) {
    lcd.clear();

    lcd.setCursor(LCD_WIDTH - i, 0);
    lcd.print(sUpr);

    lcd.setCursor(i - sBtmLen, 1);
    lcd.print(sBtm);

    delay(DELAY_LCD_SCROLL);
  }
}

/**
 * 상단하단 문자열이 count만큼 깜박임
 */
void blinkUpperBottom(byte count, String sUpr, String sBtm) {
  for (byte i = 0; i < count; i++) {
    lcd.setCursor(0, 0);
    lcd.print(sUpr);
    lcd.setCursor(0, 1);
    lcd.print(sBtm);

    delay(DELAY_LCD_BLINK);

    lcd.clear();

    delay(DELAY_LCD_BLINK);
  }
}

/**
 * RGB LED 테스트
 * 
 * 정해진 순서대로 색 표시
 */
void testLED() {
  turnOnLED(PIN_RED);
  delay(DELAY_LED_TEST);
  turnOnLED(PIN_GREEN);
  delay(DELAY_LED_TEST);
  turnOnLED(PIN_BLUE);
  delay(DELAY_LED_TEST);
  turnOnLED(COLOR_BLACK);
}

/**
 * RGB LED 색 표시
 * 
 * PIN이나 COLOR에 따라서 색상을 표현
 */
void turnOnLED(int8_t pin) {
  // 모든 LED 끔
  digitalWrite(PIN_RED, LOW);
  digitalWrite(PIN_GREEN, LOW);
  digitalWrite(PIN_BLUE, LOW);

  // 핀이나 색에 따라 LED 켜기
  switch (pin) {
    case PIN_RED:
      digitalWrite(PIN_RED, HIGH);
    break;

    case PIN_GREEN:
      digitalWrite(PIN_GREEN, HIGH);
    break;

    case PIN_BLUE:
      digitalWrite(PIN_BLUE, HIGH);
    break;

    case COLOR_YELLOW:
      digitalWrite(PIN_RED, HIGH);
      digitalWrite(PIN_GREEN, HIGH);
    break;

    case COLOR_VIOLET:
      digitalWrite(PIN_RED, HIGH);
      digitalWrite(PIN_BLUE, HIGH);
    break;

    case COLOR_BLUE_GREEN:
      digitalWrite(PIN_GREEN, HIGH);
      digitalWrite(PIN_BLUE, HIGH);
    break;

    case COLOR_BLACK:
      // 모두 끔
    break;
  }
}

/**
 * 온도, 습도에 따라서 LED 표시
 * 
 * 온도 : 25도 이하, 27도 이하, 27도 초과 구분
 * 습도 : 55% 미만, 75% 미만, 그외 구분
 */
void controlLED(float temp, float humidity) {
  if (temp <= 25) {
    if (humidity < 55) {
      turnOnLED(PIN_BLUE);
    } else if (humidity < 75) {
      turnOnLED(COLOR_BLUE_GREEN);
    } else {
      turnOnLED(COLOR_VIOLET);
    }
  } else if (temp <= 27) {
    if (humidity < 55) {
      turnOnLED(PIN_GREEN);
    } else if (humidity < 75) {
      turnOnLED(COLOR_YELLOW);
    } else {
      turnOnLED(COLOR_VIOLET);
    }
  } else if (temp > 27) {
    if (humidity < 55) {
      turnOnLED(COLOR_VIOLET);
    } else if (humidity < 75) {
      turnOnLED(PIN_RED);
    } else {
      turnOnLED(PIN_RED);
    }
  }
}

최대한 알아보기 쉽도록 주석을 구석구석 넣었습니다.;; 변수는 최대한 #define 을 사용하여 정의하였고, 변수의 사용을 최대한으로 자제하고 있습니다.


작동하면 간단히 프로그램 명칭을 깜빡임으로 표시, 스크롤로 표시, RGB LED 테스트 순으로 setup이 진행되며, 이후는 DHT 센서에서 읽어들인 값을 이용하여 온도와 습도를 화면에 표시하게 됩니다.


이제부터는 좀 더 실용적으로 사용할 수 있는 기기를 생각해봐야 겠습니다. 사용할 수 있는 센서와 디스플레이, 부품들이 늘어나면 늘어날수록 생각하는 범위도 점점 증가할 것이고, 사물인터넷에도 더 가까워지겠지요?


지금은 단순히 센서의 정보를 디스플레이하는 정도지만, 네트워크에 연결하고, DB에 데이터를 취합하고 원격으로 제어등을 추가하면 점점 큰 프로젝트가 될 것입니다.


끝.

댓글
  • 프로필사진 아두이노초보자 안녕하세요 올려주신 자료 잘보았습니다.
    처음 아두이노를 접해보면서 쉽게 따라할수있었는데요 DHT.h파일이 없어서 LCD DISPLAY에 애를 먹고 있습니다.
    혹시 파일을 올려주실수있을까요?
    2015.09.01 21:25 신고
  • 프로필사진 Favicon of http://www.dante2k.com BlogIcon Dante2k™ http://playground.arduino.cc/Main/DHTLib

    arduino.cc 홈페이지에 해당 라이브러리에 대한 설명이 있구요.

    파일은 잘 읽어보시면 찾을 수 있을 겁니다. gitHub를 이용하여 공유하고 있네요. 혹시 몰라서 라이브러리 소스 링크를 걸어드립니다.

    https://github.com/RobTillaart/Arduino/tree/master/libraries/DHTlib

    gitHub 사이트에 보시면 예제도 잘 설명되어 있습니다. 참고하시기 바랍니다.
    2015.09.01 21:41 신고
  • 프로필사진 아두이노초보자 친절한 설명 감사합니다~ 2015.09.02 09:28 신고
  • 프로필사진 BlogIcon bunny dht.h 링크 타고 갔더니 없어요 ㅠㅠ 2015.11.25 20:05 신고
  • 프로필사진 Favicon of http://www.dante2k.com BlogIcon Dante2k™ https://github.com/markruys/arduino-DHT
    요기도 함 가보시죠..
    http://playground.arduino.cc/Main/DHTLib
    위에 해당 라이브러리를 적용하는 방법과... 위에위에는 다른 분들이 만든 소스도 많이 있으니 하나 없어졌다고 속상해 하지 마시구요;;;
    2015.12.01 17:46 신고
댓글쓰기 폼