지구본

[아두이노] 2. I2C LCD와 온도센서로 센서들을 제어해보자 본문

Arduino

[아두이노] 2. I2C LCD와 온도센서로 센서들을 제어해보자

디스피어 2023. 4. 17. 14:05

지난 시간에 LED의 기본 제어 코드를 작성해보았고, 

이번에는 마찬가지로 만끽 스마트 바스 제작에 필요한 I2C LCD와 온도센서를 이용해 센서들을 제어해보았습니다.

마찬가지로 초안이기 때문에 코드와 회로도는 달라질 수 있습니다.

 

 

[아두이노] 1. LED 켜기/끄기 및 색 변경

지구팀에서 만끽 스마트 바스에서 사용하게 될 LED의 기본 제어 코드를 작성해보았습니다. 초안이기 때문에 코드와 회로도는 달라질 수 있습니다. 틴커캐드 사이트를 이용하여 진행을 하였습니

zigo0bone.tistory.com

 

틴커캐드 사이트를 이용하여 진행을 하였습니다.

코드는 Arduino IDE를 이용하여 작성하였습니다.

틴커캐드 사이트에는 저희가 원하는 센서가 부족하기 때문에 다른 센서로 대체하여 진행하였습니다. 

따라서 틴커캐드의 시뮬레이션과 실제 동작이 다르게 적용될 수 있습니다. 

 

기본 구성


먼저 온도센서를 이용해 현재 온도에 해당하는 값을 LCD에 출력해 주었습니다.

그 뒤에 아직 스마트폰 통신을 통한 설정 온도를 받아오는 것을 구현하지 못했기 때문에 

시리얼 모니터에 값을 직접 설정하여 설정 온도를 지정하고, 출력하였습니다.

버튼을 클릭시 현재 온도와 설정 온도를 스위치할 수 있습니다.

I2C LCD와 온도 센서

 

그 외의 각종 센서들을 온도 센서에서 측정한 온도에 따라 작동하겠끔 해주었습니다.

이 과정에서 팬, 열선, 밸브를 구현해 주어야 했지만

틴커캐드 사이트에서는 저희가 원하던 부품을 찾을 수 없었기 때문에 모터와 LED로 대체하였습니다.

팬, 열선, 밸브

 

 

필요 부품

  • 아두이노 우노 1개
  • 방수 온도 센서 1개
  • 푸쉬 버튼 2개
  • I2C LCD 1개
  • LED 2개(열선, 밸브 대체)
  • 모터 1개(팬 대체)
  • 220옴 저항 2개
  • 10k옴 저항 2개

 

회로 구성


현재 온도 출력
설정 온도 출력

 

  • Fan 핀을 6번 핀에 연결
  • Heat 핀을 7번 핀에 연결
  • ValveButton 핀을 8번 핀에 연결
  • Valve 핀을 9번 핀에 연결
  • LCDButton 핀을 13번 핀에 연결
  • TMP 핀을 A0 핀에 연결
  • LCD SDA 핀을 A4 핀에 연결
  • LCD SCL 핀을 A5 핀에 연결

 

코드


틴커캐드에서 시뮬레이션이 잘되었던 코드가 실제 아두이노에서는 동작하지 않았습니다.

어쩔수없이 실제 아두이노용 코드로 수정하였고, 잘 동작하였습니다.

그러나 수정 코드는 틴커캐드에서는 동작하지 않았습니다.

틴커캐드는 확인용으로 진행하였기 때문에 실제 아두이노용 코드를 바탕으로 개발을 진행하게 될 것 같습니다.

 

틴커캐드 코드

#include <LiquidCrystal_I2C.h>

#define HEAT  7 //핀번호 정의
#define FAN   6
#define VALVE   9
#define VALVEBUTTON  8
#define LCDBUTTON 13

char buffer[20];  //통신을 할때 buffer배열에 전송받은 데이터 입력
char bufferIndex = 0;

LiquidCrystal_I2C lcd(0x20,16,2); //핀번호로 LCD모듈 초기화

void setup()
{
  lcd.init();
  lcd.backlight();
  Serial.begin(9600);
  pinMode(LCDBUTTON, INPUT);
}

void loop()
{
  while(Serial.available())
  {
    buffer[bufferIndex]  = Serial.read();   //시리얼 통신으로 버퍼배열에 데이터 수신
    bufferIndex++;  //데이터 수신 후 버퍼 인덱스 1 증가
  }
  float setTemp = atof(buffer); // 설정 온도, atof()함수로 char값을 float값으로 변환
 
  int tempValue = analogRead(A0);
  float voltage = tempValue*5.0/1024.0;
  float temperature = voltage*100-50; // 현재 온도 계산식
 
  int valveButton = digitalRead(VALVEBUTTON);
  int lcdButton = digitalRead(LCDBUTTON);
  Serial.println(lcdButton);
 
  valve_h_onoff(VALVE, valveButton);
  fan_onoff(HEAT,FAN,setTemp,temperature);
  temp_cur_res(lcdButton,setTemp,temperature);
}

void valve_h_onoff(int valve, int valveButton)   // 온수 on/off
{
  if(valveButton == HIGH){ //신호를 받았을 때 밸브 on/off
    digitalWrite(valve, HIGH);
  }
  else{
    digitalWrite(valve,LOW);
  }
}

void valve_c_onoff(int valve, int valveButton)   // 냉수 on/off
{
  if(valveButton == HIGH){  //신호를 받았을 때 밸브 on/off
    digitalWrite(valve, HIGH);
  }
  else{
    digitalWrite(valve,LOW);
  }
}

void fan_onoff(int heat, int fan, float stemp, float ptemp) // 팬 on/off
{
  if(ptemp < stemp)
  {
    digitalWrite(heat, HIGH);  // 현재 온도가 설정 온도보다 낮을 경우 열선 on
    digitalWrite(fan, HIGH);  // 현재 온도가 설정 온도보다 낮을 경우 팬 on
  }

  else
  {
    digitalWrite(heat,LOW);  // 현재 온도가 설정 온도보다 같거나 높을 경우 열선 off
    digitalWrite(fan, LOW);  // 현재 온도가 설정 온도보다 같거나 높을 경우 팬 off
  }
}

void temp_cur_res(int lcdButton, float stemp, float ptemp)
{
  if(lcdButton == HIGH) //눌렀을 때, 설정온도
  {
    if(stemp != 0) {
      lcd.print("SETTING : ");
      lcd.print(stemp);
      lcd.print("C");
      Serial.print("Input data : ");
      Serial.println(stemp);  //float값으로 변환된 데이터 출력
    }
    delay(1000);
    lcd.clear();
  }
  else  //누르지 않았을 때, 현재온도
  {
    String tempStr = String(ptemp);
    lcd.print("CURRENT : " + tempStr);
    lcd.print("C");
    Serial.println(tempStr);

    delay(1000);
    lcd.clear();
  }
}
 
 

실제 아두이노 구현 코드

#include <LiquidCrystal_I2C.h>
#include <OneWire.h>

#define HEAT  7 //핀번호 정의
#define FAN   6
#define VALVE   9
#define VALVEBUTTON  8
#define LCDBUTTON 13
#define DS18S20_Pin 2 // 방수온도센서

char buffer[20];  //통신을 할때 buffer배열에 전송받은 데이터 입력
char bufferIndex = 0;

OneWire ds(DS18S20_Pin);
LiquidCrystal_I2C lcd(0x27,16,2); //핀번호로 LCD모듈 초기화

void setup()
{
  lcd.init();
  lcd.backlight();
  Serial.begin(9600);
  pinMode(LCDBUTTON, INPUT);
}

void loop()
{
  while(Serial.available())
  {
    buffer[bufferIndex]  = Serial.read();   //시리얼 통신으로 버퍼배열에 데이터 수신
    bufferIndex++;  //데이터 수신 후 버퍼 인덱스 1 증가
  }
  float setTemp = atof(buffer); // 설정 온도, atof()함수로 char값을 float값으로 변환
 
  float temperature = temp_sensor();

  int valveButton = digitalRead(VALVEBUTTON);
  int lcdButton = digitalRead(LCDBUTTON);
  Serial.println("LCD버튼 : " + lcdButton);
 
  valve_h_onoff(VALVE, valveButton);
  fan_onoff(HEAT,FAN,setTemp,temperature);
  temp_cur_res(lcdButton,setTemp,temperature);
}

void valve_h_onoff(int valve, int valveButton)   // 온수 on/off
{
  if(valveButton == HIGH){  //신호를 받았을 때 밸브 on/off
    digitalWrite(valve, HIGH);
  }
  else{
    digitalWrite(valve,LOW);
  }
}

void valve_c_onoff(int valve, int valveButton)   // 냉수 on/off
{
  if(valveButton == HIGH){  //신호를 받았을 때 밸브 on/off
    digitalWrite(valve, HIGH);
  }
  else{
    digitalWrite(valve,LOW);
  }
}

void fan_onoff(int heat, int fan, float stemp, float ptemp) // 팬 on/off
{
  if(ptemp < stemp)
  {
    digitalWrite(heat, HIGH);  // 현재 온도가 설정 온도보다 낮을 경우 열선 on
    digitalWrite(fan, HIGH);  // 현재 온도가 설정 온도보다 낮을 경우 팬 on
  }

  else
  {
    digitalWrite(heat,LOW);  // 현재 온도가 설정 온도보다 같거나 높을 경우 열선 off
    digitalWrite(fan, LOW);  // 현재 온도가 설정 온도보다 같거나 높을 경우 팬 off
  }
}

void temp_cur_res(int lcdButton, float stemp, float ptemp)
{
  if(lcdButton == HIGH) //눌렀을 때, 설정온도
  {
    if(stemp != 0) {
      lcd.print("SETTING : ");
      lcd.print(stemp);
      lcd.print("C");
      Serial.print("Input data : ");
      Serial.println(stemp);  //float값으로 변환된 데이터 출력
    }
    delay(1000);
    lcd.clear();
  }
  else  //누르지 않았을 때, 현재온도
  {
    String tempStr = String(ptemp);
    lcd.print("CURRENT : " + tempStr);
    lcd.print("C");
    Serial.println("tempStr : " + tempStr);

    delay(1000);
    lcd.clear();
  }
}

float temp_censor(){  // 온도를 받고 계산
  byte data[12];
  byte addr[8];
  if(!ds.search(addr)){
    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);
  byte present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);

  for(int i =0;i<9;i++){
    data[i] = ds.read();
  }

  ds.reset_search();
  byte MSB = data[1];
  byte LSB = data[0];
  float tempRead = ((MSB << 8) | LSB);
  float TemperatureSum = tempRead /16;
  return TemperatureSum;
}