Creative Code

아두이노 프로젝트 최종정리(기상관측계) 본문

Projects

아두이노 프로젝트 최종정리(기상관측계)

빛하루 2023. 8. 20. 13:18

※마스터 보드 코드

#include <Wire.h>
#include <LiquidCrystal.h>

char receivedData[32];                            //데이터를 받아온 후 저장할 배열
bool sendData = true;                             //데이터 송신 여부
int status;                                       //수신한 데이터의 값 저장
const int SW_0 = 6;                               //스위치 0번버튼을 6번 디지털 핀에 연결
const int SW_1 = 7;                               //스위치 1번버튼을 7번 디지털 핀에 연결
const int SW_2 = 8;                               //스위치 2번버튼을 8번 디지털 핀에 연결

LiquidCrystal lcd(12, 11, 2, 3, 4, 5);            //lcd 연결핀 12,11,2,3,4,5번

void SW0_Pressed(void) {                          //온도를 체크하는 함수 (0번 스위치)
  if (sendData) {                                 //송신을 시작할 때
    Wire.beginTransmission(5);                    //온도를 체크하는 slave보드의 주소값은 5
    Wire.write("temp");                           //온도를 체크하라는 명령을 전달
    Wire.endTransmission();                       //전송 종료
    delay(80);                                    //통신이 얽히는 것을 방지하기 위한 delay시간 부여 
    sendData = false;                             //송신이 완료되어 false로 변경

    Wire.requestFrom(9, 32);                      //32바이트만큼 데이터를 요청
    Wire.onReceive(receiveEvent);                 //데이터 수신함수
    delay(80);                                    //통신 얽힘 방지를 위한 delay시간 부여
    Serial.println("'C");

    lcd.clear();                                  //lcd화면 초기화
    lcd.setCursor(0, 0);
    lcd.write(byte(0));                           //lcd화면 글자 "온" 출력
    lcd.setCursor(1, 0);                      
    lcd.write(byte(1));                           //lcd화면 글자 "도" 출력
    lcd.setCursor(2, 0);
    lcd.print(":");
    lcd.setCursor(3, 0);        
    lcd.print(status / 10);                       //lcd화면에 온도 측정값 출력
    lcd.setCursor(4, 0);
    lcd.print(status % 10);
    lcd.setCursor(5, 0);
    lcd.print("'");
    lcd.setCursor(6, 0);
    lcd.print("C");
    if (status >= 33 && status < 35) {            //온도 측정값이 33도이상 35도 미만이면 폭염주의보 경고 메시지 출력
      lcd.setCursor(0, 1);
      lcd.print("heat wave 1");
    } else if (status >= 35) {                    //온도 측정값이 35도이상이면 폭염경보 메시지 출력
      lcd.setCursor(0, 1);  
      lcd.print("heat wave 2");
    } else if (status <= -12 && status > -15) {   //DHT11센서의 측정범위는 0도~50도 이지만 -12도이하 -15도 초과 일때는 한파 주의보 경고 메시지 출력
      lcd.setCursor(0, 1);
      lcd.print("cold wave 1");
    } else if (status <= -15) {                   //-15도 미만일 때는 한파 경보 메시지 출력
      lcd.setCursor(0, 1);
      lcd.print("cold wave 2");
    }
  }
}

void SW1_Pressed(void) {                          //습도를 측정하는 함수(스위치 1번)
  if (sendData) {                                 //송신을 시작할 때
    Wire.beginTransmission(5);                    //습도를 체크하는 slave보드의 주소값은 5
    Wire.write("humid");                          //습도 측정을 위한 명령어 전달
    Wire.endTransmission();                       //전송 종료
    delay(80);                                    //통신 얽힘 방지를 위한 delay 시간 부여
    sendData = false;                             //송신을 종료했으므로 false로 전환
    Wire.requestFrom(9, 32);                      //32바이트만큼 데이터를 요청
    Wire.onReceive(receiveEvent);                 //데이터 수신함수
    delay(80);                                    //통신 얽힘 방지를 위한 delay 시간 부여
    Serial.println("%");  
    lcd.clear();                                  //lcd화면 초기화
    lcd.setCursor(0, 0);                  
    lcd.write(byte(2));                           //글자 "습" 출력
    lcd.setCursor(1, 0);
    lcd.write(byte(1));                           //글자 "도" 출력
    lcd.setCursor(2, 0);
    lcd.print(":");
    lcd.setCursor(3, 0);
    lcd.print(status / 10);                       //수신한 습도 측정값 출력
    lcd.setCursor(4, 0);
    lcd.print(status % 10);
    lcd.setCursor(5, 0);
    lcd.print("%");
    if (status <= 35 && status > 25) {            //습도 측정값이 25%초과 35% 이하이면 건조 주의보 메시지 출력
      lcd.setCursor(0, 1);                        
      lcd.print("dry caution 1");

    } else if (status <= 25) {                    //습도 측정값이 25%이하이면 건조 경보 메시지 출력
      lcd.setCursor(0, 1);
      lcd.print("dry caution 2");
    }
  }
}

void SW2_Pressed(void) {                          //자외선 측정을 위한 함수(스위치2번)
  if (sendData) {                                 //송신을 시작할 때
    Wire.beginTransmission(6);                    //자외선을 측정하는 slave보드의 주소값은 6
    Wire.write("UV");                             //자외선을 측정하기 위한 명령 전달
    Wire.endTransmission();                       //전송 종료
    delay(80);                                    //통신 얽힘을 방지하기 위한 delay 시간 부여
    sendData = false;                             //송신을 종료했으므로 false로 전환
    Wire.requestFrom(9, 32);                      //32바이트만큼 데이터를 수신
    Wire.onReceive(receiveEvent);                 //데이터를 수신하는 함수
    delay(80);                                    //통신 얽힘을 방지하기 위한 delay시간 부여

    lcd.clear();                                  //lcd화면 초기화
    lcd.setCursor(0, 0);
    lcd.write(byte(3));                           //lcd에 글자"자"출력
    lcd.setCursor(1, 0);    
    lcd.write(byte(4));                           //lcd에 글자"외"출력
    lcd.setCursor(2, 0);
    lcd.write(byte(5));                           //lcd에 글자"선"출력
    lcd.setCursor(3, 0);                          
    lcd.print(":");
    lcd.setCursor(4, 0);                          //lcd에 자외선 측정값 출력
    lcd.print(status / 10);
    lcd.setCursor(5, 0);
    lcd.print(status % 10);
    if (status < 3) {                             //자외선 지수가 3보다 낮을 때 "자외선 낮음"출력
      lcd.setCursor(0, 1);
      lcd.print("UV low"); 
    } else if (status >= 3 && status < 6) {       //자외선 지수가 3이상 6미만 일 때 "자외선 보통"출력
      lcd.setCursor(0, 1);
      lcd.print("UV normal");
    }
    else if (status >= 6 && status < 8) {         //자외선 지수가 6이상 8미만 일 때 "자외선 높음"출력
      lcd.setCursor(0, 1);
      lcd.print("UV high");
    }
     else if (status >= 8 && status < 11) {       //자외선 지수가 8이상 11미만 일 때 "자외선 매우 높음"출력
      lcd.setCursor(0, 1);
      lcd.print("UV very high");
    } 
    else {                                        //자외선 지수가 11이상일 때 "자외선 경고"출력
      lcd.setCursor(0, 1);
      lcd.print("UV warning");
    }
    
  }
}


byte wk[8] =                                //lcd에 글자 "자"를 출력하기 위한 바이트 생성
  {
    0b00010,
    0b11110,
    0b01011,
    0b01010,
    0b10110,
    0b10110,
    0b00010,
    0b00000
  };


byte dhl[8] =                               //글자 "외"
  {
    0b01001,
    0b10101,
    0b10101,
    0b10101,
    0b01001,
    0b00001,
    0b01000,
    0b11110
  };

byte tjs[8] =                               //글자 "선"
  {
    0b01001,
    0b01001,
    0b10111,
    0b10101,
    0b00001,
    0b00000,
    0b10000,
    0b11111
  };

byte eo[8] =                                //글자 "대"
  {
    0b00101,
    0b11101,
    0b10101,
    0b10111,
    0b10101,
    0b10101,
    0b11101,
    0b00101
  };

byte rl[8] =                                //글자 "기"
  {
    0b00001,
    0b11101,
    0b00101,
    0b00101,
    0b01001,
    0b10001,
    0b00001,
    0b00000
  };

byte dhs[8] =                               //글자 "온"
  {
    0b01110,
    0b10001,
    0b01110,
    0b00100,
    0b11111,
    0b00000,
    0b10000,
    0b11111
  };


byte eh[8] =                                //글자 "도"
  {
    0b11111,
    0b10000,
    0b10000,
    0b11111,
    0b00000,
    0b00100,
    0b00100,
    0b11111
  };


byte tmq[8] =                               //글자 "습"
  {
    0b00100,
    0b01010,
    0b11111,
    0b00000,
    0b10001,
    0b11111,
    0b10001,
    0b11111
  };

void setup() {
  Wire.begin(9);                            //Master보드의 주소를 9로 설정
  Serial.begin(9600);                       //시리얼 통신
  pinMode(SW_0,INPUT);                      //SW_0의 pinmode 설정
  pinMode(SW_1,INPUT);                      //SW_1의 pinmode 설정
  pinMode(SW_2,INPUT);                      //SW_2의 pinmode 설정
  lcd.begin(16, 2);                         //lcd 기본설정(16*2크기)
  lcd.createChar(0, dhs);                   //글자 "온"
  lcd.createChar(1, eh);                    //글자 "도"
  lcd.createChar(2, tmq);                   //글자 "습"
  lcd.createChar(3, wk);                    //글자 "자"
  lcd.createChar(4, dhl);                   //글자 "외"
  lcd.createChar(5, tjs);                   //글자 "선"
}

void loop() {
  int digitalValue1 = digitalRead(SW_0);    //온도 버튼을 누르면 digitalRead를 통해 1값을 받아 digitalvalue1변수에 저장
  int digitalValue2 = digitalRead(SW_1);    //습도 버튼을 누르면 digitalRead를 통해 1값을 받아 digitalvalue2변수에 저장
  int digitalValue3 = digitalRead(SW_2);    //자외선 버튼을 누르면 digitalRead를 통해 1값을 받아 digitalvalue3변수에 저장
  

  if (digitalValue1 == HIGH) {              //digitalvalue1변수가 HIGH값이면 온도를 측정하는 함수 실행
    SW0_Pressed();
  }
  if (digitalValue2 == HIGH) {              //digitalvalue2변수가 HIGH값이면 습도를 측정하는 함수 실행
    SW1_Pressed(); 
  }
  if (digitalValue3 == HIGH) {              //digitalvalue3변수가 HIGH값이면 자외선을 측정하는 함수 실행
    SW2_Pressed();
  }
}

void receiveEvent(int byteCount) {          //데이터를 받아오는 함수
  if (Wire.available() > 0) {
    int i = 0;
    while (Wire.available()) {              //데이터를 모두 받아올 때 까지 반복
      receivedData[i] = Wire.read();        //데이터를 1바이트씩 받아 문자열배열 receivedData에 저장
      i++;
    } 
    receivedData[i] = '\0';                 //문자열의 마지막에 '\0' 문자 추가
    Serial.print("status : ");              
    status = atoi(receivedData);            //문자열로 데이터를 전송받았으므로 수신한 데이터를 숫자로 전환
    Serial.print(status);
  }
  sendData = true;                          //데이터를 수신한 뒤에도 데이터를 다시 받아올 수 있게 송신모드로 전환
}

※slave보드 (온도,습도) 코드

 

#include <Wire.h>
#include <DHT.h>

char receivedData[32];                               //master보드로 부터 수신한 명령을 저장할 배열
char tempData[32];                                   //측정한 온도데이터를 저장할 배열 -> master보드로 보낼 용도
char humidData[32];                                  //측정한 습도데이터를 저장할 배열 -> master보드로 보낼 용도
const int temp = 2;                                  //온도측정센서와 연결할 디지털 핀
DHT dht(2,DHT11);                                    //2번핀을 DHT11센서와 연결
const int BUZZER = 10;                               //부저의 연결 핀은 10번

bool sendData = false;                               //데이터 전송모드의 초기 설정은 false;
void setup() {
  Wire.begin(5);                                     //온도,습도를 측정하는 slave보드의 주소값을 5로 설정
  Wire.onReceive(receiveEvent);                      //master보드로 부터 명령을 수신하는 함수
  Serial.begin(9600);                                //시리얼 통신
  dht.begin();                                       //센서 동작 시작
  pinMode(BUZZER,OUTPUT);                            //부저의 pinmode를 OUTPUT으로 설정
}

void loop() {
  if (sendData) {                                    //데이터를 송신모드
    if (strcmp(receivedData,"temp") == 0) {          //master보드로 부터 전달받은 명령이 온도 측정일 경우
      int temperature = dht.readTemperature();       //온도 측정한 값을 int형으로 저장
      if (temperature >= 33 || temperature<=-12) {   //온도가 33도이상이거나 영하12도 이하일 시 경고용으로 부저작동
        tone(BUZZER,600,1000);                       //부저의 음 높낮이는 600, 지속시간은 1초로 설정
      }
      Serial.print(" ");
      Serial.println(temperature);
      Wire.beginTransmission(9);                      //측정한 데이터를 master보드로 보내기위해 master보드의 주소인 9로 연결
      itoa(temperature,tempData,10);                  //측정값을 10진수형태의 문자열로 변환해 tempData배열에 저장
      Wire.write(tempData);                           //변환한 문자열을 master보드로 전송
      delay(80);                                      //통신얽힘 방지를 위한 delay부여
      Wire.endTransmission();                         //전송 종료
      sendData = false;                               //데이터를 전송했으므로 전송모드를 false로 전환
    } 
    else {                                            //master보드로 부터 전달받은 명령이 습도 측정일 경우
      int humidity = dht.readHumidity();              //습도 측정한 값을 int형으로 저장
      Serial.print(" ");
      Serial.println(humidity);
      Wire.beginTransmission(9);                      //측정한 데이터를 master보드로 보내기 위해 master보드의 주소인 9로 연결
      itoa(humidity,humidData,10);                    //측정값을 10진수형태의 문자열로 변환해 tempData배열에 저장
      Wire.write(humidData);                          //변환한 문자열을 master보드로 전송
      delay(80);                                      //통신얽힘 방지를 위한 delay부여
      Wire.endTransmission();                         //전송 종료
      sendData = false;                               //데이터를 전송했으므로 전송모드를 false로 전환
    }
  }
}

void receiveEvent(int byteCount) {                    //master보드로 부터 명령을 받는 함수
  if (Wire.available() > 0) {
    int i = 0;
    while (Wire.available()) {                        //데이터를 모두 받을때 까지 실행
      receivedData[i] = Wire.read();                  //수신 데이터를 배열에 저장
      i++;
    }
    receivedData[i] = '\0';                           //문자열 배열 마지막에 종료를 알리는 '\0'문자를 추가
    Serial.print("Received from Master: "); 
    Serial.println(receivedData);
  }
  sendData = true;                                    //다시 데이터를 요청받을 수 있기 때문에 전송모드를 true로 전환
}

※slave보드 (UV)코드

 

#include <Wire.h>
#include <math.h>

int UVOUT = A0;                                                        //A0 핀에 UV 센서 연결
int REF_3V3 = A1;                                                      //A1 핀에 3.3V 레퍼런스 연결
bool sendData = false;                                                 //데이터 전송모드 초기값 false로 설정
char receivedData[32];                                                 //master보드로부터 수신한 데이터를 저장하는 문자 배열
char UVData[32];                                                       //UV 센서 데이터를 저장하는 문자 배열 ->master보드로 보내기 위한 문자열
const int BUZZER = 10;                                                 // 부저를 10번핀에 연결

void setup() {
  Serial.begin(9600);                                                  //시리얼 통신
  Wire.begin(6);                                                       //자외선을 측정하는 slave보드의 주소값을 6으로 설정
  Wire.onReceive(receiveEvent);                                        //master보드로 부터 데이터를 수신하는 함수
  pinMode(UVOUT, INPUT);                                               //UV 센서를 INPUT 모드로 설정
  pinMode(REF_3V3, INPUT);                                             //3.3V 레퍼런스 핀을 INPUT 모드로 설정
  pinMode(BUZZER, OUTPUT);                                             //부저를 OUTPUT 모드로 설정
  Serial.println("MP8511 example"); 
}

void loop() {
  if (sendData) {                                                      //데이터 전송모드
    int uvLevel = averageAnalogRead(UVOUT);                            //UV 센서에서 평균 아날로그 값을 읽음
    int refLevel = averageAnalogRead(REF_3V3);                         //3.3V 레퍼런스에서 평균 아날로그 값을 읽음
    float outputVoltage = 3.3 / refLevel * uvLevel;                    //UV 강도에 해당하는 출력 전압 계산
    float uvIntensity = mapfloat(outputVoltage, 0.99, 2.9, 0.0, 15.0); //출력 전압을 UV 강도로 매핑
    Wire.beginTransmission(9);                                         //측정한 데이터를 master보드의 주소값인 9로 전송 시작
    int uvint = (int)uvIntensity;                                      //UV 강도를 정수로 변환
    if (uvint >= 6) {                                                  //UV 강도가 6 이상인 경우 경고음 출력
      tone(BUZZER, 600, 1000);                                         //경고음의 높낮이는 600으로 1초동안 출력
    }
    Serial.print(" UV Intensity (mW/cm^2): ");                         
    Serial.println(uvIntensity);
    Serial.println(uvint);    
    itoa(uvint, UVData, 10);                                           //측정한 값을 master보드로 전송하기위해 문자열로 변환하고 UVData배열에 저장
    Wire.write(UVData);                                                //master보드로 문자열 배열 전송
    delay(100);                                                        //통신 얽힘 방지를 위해 delay 부여
    Wire.endTransmission();                                            //데이터 전송 종료
    sendData = false;                                                  //데이터를 보냈으므로 전송모드 false로 전환
    Serial.println();    
  }
}

// 주어진 핀에서 여러 읽기를 평균내는 함수
// 평균값을 반환
int averageAnalogRead(int pinToRead) {
  byte numberOfReadings = 8;                                           //읽을 횟수
  unsigned int runningValue = 0;                                       //읽은 값들의 합을 저장할 변수

  for (int x = 0; x < numberOfReadings; x++)
    runningValue += analogRead(pinToRead);                             //주어진 핀에서 아날로그 값을 읽어 합산

  runningValue /= numberOfReadings;                                    //합산 값을 읽은 횟수로 나누어 평균을 계산

  return (runningValue);                                               //평균값 반환
}

// float 값에 대한 매핑 함수
float mapfloat(float x, float in_min, float in_max, float out_min, float out_max) {
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;  //매핑 계산
}

void receiveEvent(int byteCount) {                                     //master보드로 부터 명령을 받는 함수
  if (Wire.available() > 0) {
    int i = 0;
    while (Wire.available()) {                                         //데이터를 모두 받을 때 까지 실행
      receivedData[i] = Wire.read();                                   //데이터를 받아 receivedData문자열 배열에 저장
      i++;
    }
    receivedData[i] = '\0';                                            //문자열 종료 문자 추가
    Serial.print("Received from Master : ");
    Serial.println(receivedData);
  }
  sendData = true;                                                     //다음 데이터 요청이 있을시를 대비해 전송모드를 true로 전환
}

 

 

'Projects' 카테고리의 다른 글

Aurora-(2)서버 구축 연습  (0) 2023.11.02
Aurora-(1)로그인 UI화면 구현[클라이언트]  (0) 2023.11.01
Aurora-(0)준비단계  (0) 2023.10.31
OneStargram(기획)  (0) 2023.10.26
아두이노 프로젝트 ppt(기상관측계)  (0) 2023.09.02