지난 시간에 LED의 기본 제어 코드를 작성해보았고,
이번에는 마찬가지로 만끽 스마트 바스 제작에 필요한 I2C LCD와 온도센서를 이용해 센서들을 제어해보았습니다.
마찬가지로 초안이기 때문에 코드와 회로도는 달라질 수 있습니다.
틴커캐드 사이트를 이용하여 진행을 하였습니다.
코드는 Arduino IDE를 이용하여 작성하였습니다.
틴커캐드 사이트에는 저희가 원하는 센서가 부족하기 때문에 다른 센서로 대체하여 진행하였습니다.
따라서 틴커캐드의 시뮬레이션과 실제 동작이 다르게 적용될 수 있습니다.
기본 구성
먼저 온도센서를 이용해 현재 온도에 해당하는 값을 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;
}