반응형

아두이노 Proj1시간! 2가지 스타일 시계 뚝딱 만들기! 
TM1637(시계 & 온도계)   //   LCD(시계 & 온도계 & 날짜 & 요일)


DS3231 Clock 모듈을 이용해서 디지털 시계 겸 온도계를 뚝딱! 만들어 보겠습니다.

아두이노를 이용하여 시계류를 만들 때 고려해야 할 사항은 몇 일이 지나도 시간이 정확해야 하며, 
작품의 전원이 차단 되더라도 흘러가는 시간이 기억되어 있어야 합니다.
이 두 가지 기능을 제공해주는 RTC 모듈이 바로 DS3231인데요, 
가격도 저렴하면서, 온도 센서가 있어 주변 온도 값도 출력해주는 멋진 모듈입니다.

그럼, 이 모듈을 가지고 영상에서처럼, 두 가지 버전으로 만들어 보겠습니다.
하나는 TM1637 숫자표시 모듈을 가지고 만들어 볼 텐데요,  평상시에는 시간을 표시하다가, 터치센서 또는 스위치를 누르면 온도값을 표시해주도록 하겠습니다. 


두 번째로 LCD 액정 디스플레이를 이용해서 시간 온도뿐 아니라 날짜와 요일까지 모두 표시할 수 있는 장치를 만들어 볼게요. 


물론, 이 모든 데이터는 DS3231 모듈에서 얻을 수 있기 때문에 어렵지 않게 제작할 수 있습니다. 

 《 TM1637 시계 & 온도계  만들기

① 연결도면

1번. TM1637 모듈과 터치 센서를 사용한 회로 연결은 아래와 같이 합니다.


여기서 한가지, 저렴한 복제 나노보드의 경우 CH340 통신칩을 이용하게 되는데요, 처음 사용되는 PC에는 관련 드라이버가 없기 때문에, 드라이버 설치가 필요할 수 있습니다. 
Window키 +‘X’키를 함께 눌러 장치관리자를 열어보세요. 
만약 이 부분 포트 영역에 드라이버가 잡히지 않거나, 경고 표시가 뜬다면 지금 보여드리는 것처럼 드라이버를 설치해 보세요. 
만약, 드라이버가 잘 잡혀 있거나, 아두이노 정품 보드를 사용하는 경우에는 이 과정을 건너뛰면 됩니다. 

그게 아니라면 아래처럼  "CH340"으로 구글 검색 후 아래 보이는 중국어 사이트를 여세요. 

운영체제 버전을 확인하고 파란색의 내려 받기 버튼을 클릭합니다.
위 다운로드 파일 직접 링크했으니 아래 파일을 받아도 됩니다. 
1. Windows 버전용( ↓ )

CH341SER.ZIP
0.28MB

 

2. Mac OS 버전용( ↓ )

CH341SER_MAC.ZIP
0.24MB

 

다운로드 받은 파일의 압축을 풀고 설치를 진행하세요. 


그런 다음, 장치관리자의 포트 부분을 확인해 보면 화면처럼 드라이버가 잘 잡혀 있는 것을 볼 수 있습니다.
아두이노 나노의 경우, 펌웨어를 개인적으로 업뎃 하지 않았다면, 프로세서는 “(Old Bootloader)”로 선택해주세요.

② 아두이노 코드

< 날짜&시간 설정 코드 > 
 :  1번 TM1637회로와  2번 LCD 회로에 공통적으로 사용되는 DS3231의 현재 시간 설정용 코드입니다.

/* [ DS3231 RTC 모듈에 시간 날짜 셋팅하기 코드 ] 
 * 아래 코드를 입력하고 시간 설정은 아두이노IDE의 시리얼모니터로 아래와 같이 입력함
 * 예시) T:설정명령, 22년 01월 07일 18시 55분 00초 금요일 이라면, => :T2201071855006  
 * 요일(1~7, 1:일 2:월 3:화 4:수 5:목 6:금 7:토)
 */

#include <Wire.h>
#define DS3231_I2C_ADDRESS 104
//만약 컴파일 에러시 아래 5줄의 주석 부분을 해제하세요.
//byte decToBcd(byte val);
//void watchConsole();
//void set3231Date();
//void get3231Date();
//float get3231Temp();
 
// DS3231의 데이터핀 연결은 아래처럼 하세요(우노/나노 동일)
// SCL - pin A5
// SDA - pin A4
 
byte seconds, minutes, hours, day, date, month, year;
char weekDay[4];
 
byte tMSB, tLSB;
float temp3231;
 
void setup()
{
  Wire.begin();
  Serial.begin(9600);
}
 
void loop()
{ 
  watchConsole();
  get3231Date();
  Serial.print(weekDay);
  Serial.print(", 20");
  Serial.print(year, DEC);
  Serial.print("/");
  Serial.print(month, DEC);
  Serial.print("/");
  Serial.print(date, DEC);
  Serial.print(" - ");
  Serial.print(hours, DEC); 
  Serial.print(":"); 
  Serial.print(minutes, DEC); 
  Serial.print(":"); 
  Serial.print(seconds, DEC);
  Serial.print(" - Temp: "); 
  Serial.println(get3231Temp());
  delay(1000);
}
 
// 10진수를 2진화 10진수인 BCD 로 변환 (Binary Coded Decimal)
byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}
 
void watchConsole()
{
  if (Serial.available()) {      // Look for char in serial queue and process if found
    if (Serial.read() == 84) {   //If command = "T" Set Date
      set3231Date();
      get3231Date();
      Serial.println(" ");
    }
  }
}
 
//시간설정
// T(설정명령) + 년(00~99) + 월(01~12) + 일(01~31) + 시(00~23) + 분(00~59) + 초(00~59) + 요일(1~7, 일1 월2 화3 수4 목5 금6 토7)
// 예: T1605091300002 (2016년 5월 9일 13시 00분 00초 월요일)
void set3231Date()
{
  year    = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  month   = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  date    = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  hours   = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  minutes = (byte) ((Serial.read() - 48) *10 +  (Serial.read() - 48));
  seconds = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48));
  day     = (byte) (Serial.read() - 48);
 
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x00);
  Wire.write(decToBcd(seconds));
  Wire.write(decToBcd(minutes));
  Wire.write(decToBcd(hours));
  Wire.write(decToBcd(day));
  Wire.write(decToBcd(date));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}
 
 
void get3231Date()
{
  // send request to receive data starting at register 0
  Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
  Wire.write(0x00); // start at register 0
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes
 
  if(Wire.available()) {
    seconds = Wire.read(); // get seconds
    minutes = Wire.read(); // get minutes
    hours   = Wire.read();   // get hours
    day     = Wire.read();
    date    = Wire.read();
    month   = Wire.read(); //temp month
    year    = Wire.read();
       
    seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); // convert BCD to decimal
    minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111)); // convert BCD to decimal
    hours   = (((hours & B00110000)>>4)*10 + (hours & B00001111)); // convert BCD to decimal (assume 24 hour mode)
//  필요한 경우, 아래 24시간을 12시간 단위로 표시하는 코드 추가
    if (hours > 12 ) {
      hours = hours - 12;
    }
    day     = (day & B00000111); // 1-7
    date    = (((date & B00110000)>>4)*10 + (date & B00001111)); // 1-31
    month   = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
    year    = (((year & B11110000)>>4)*10 + (year & B00001111));
  }
  else {
    //oh noes, no data!
  }
 
  switch (day) {
    case 1:
      strcpy(weekDay, "Sun");
      break;
    case 2:
      strcpy(weekDay, "Mon");
      break;
    case 3:
      strcpy(weekDay, "Tue");
      break;
    case 4:
      strcpy(weekDay, "Wed");
      break;
    case 5:
      strcpy(weekDay, "Thu");
      break;
    case 6:
      strcpy(weekDay, "Fri");
      break;
    case 7:
      strcpy(weekDay, "Sat");
      break;
  }
}
 
float get3231Temp()
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
  if (Wire.available()) {
    tMSB = Wire.read(); 
    tLSB = Wire.read(); 
    temp3231 = (tMSB & B01111111); 
    temp3231 += ( (tLSB >> 6) * 0.25 ); //소수점 아래 단위의 온도값을 0.25단위씩 처리
  }
  else {
    // 에러일 경우 아무 데이터도 출력하지 아니함
  }
  return temp3231;
}

<  날짜&시간 설정 코드 다운로드 >

01_DS3231RTC_Setting.zip
0.00MB


< 1번 TM1637 시간&온도 표시 코드 >

/* 
 *  DS3231 & TM1637 & 터치(SW)센서로 시계/온도 번갈아 출력하는 코드.
 *  터치센서는 어떤 종류든 사용 가능하며, 기계적인 토글스위치, 슬라이드스위치 등도 가능.
 *  RTClib 라이브러리를 검색하여 설치하거나, 만약 설치한 라이브러리가 맞지 않다면, 삭제하고 아래 제공하는 라이브러리를 다운 받으세요.
 *  TM1637Display 라이브러리도 함께 제공합니다.(비슷한 라이브러리가 여러 개이기 때문에 반드시 제공하는 라이브러리로 설치하세요)
  */
#include <Wire.h>           // 아두이노 IDE 설치시 기본 제공됨
#include <RTClib.h>         // RTClib 라이브러리
#include <TM1637Display.h>  // TM1637Display 라이브러리
#define CLK 8            // TM1637 CLK 핀
#define DIO 9            // TM1637 DIO 핀
#define DS3231_I2C_ADDRESS 104
#define Touch 7
RTC_DS3231 rtc;         // RTC 모듈 객체 생성
TM1637Display display(CLK, DIO);
int Time, Minute;       // 시간, 분 변수 지정
char daysOfTheWeek[7][12] = {"SUN", "MON", "TUE", "WEN", "THU", "FRI", "SAT"};
float temp3231;
byte tMSB, tLSB;

void setup () {
  Wire.begin();
  display.setBrightness(7); // 0~7, 밝기 조절 : 0(가장 어두움)~ 7(가장 밝음)
  Serial.begin(9600);     // RTC 모듈 체크 루틴
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  pinMode(Touch, INPUT);
}
void loop () {
  get3231Temp();
  //  Serial.println(temp3231);
  int SW = digitalRead(Touch);
  //  Serial.println(SW);
  delay(100);
  DateTime now = rtc.now();
  int Time = now.hour();
//  필요한 경우, 아래 24시간을 12시간 단위로 표시하는 코드 추가
  if (Time>12) { Time=Time-12; }
  
  int Minute = now.minute();
  int digitoneT = Time / 10;
  int digittwoT = Time % 10;
  int digitoneM = Minute / 10;
  int digittwoM = Minute % 10;
  uint8_t data[] = { 0x0, 0x0, 0x0, 0x0};
  uint8_t segto;
  // 아래, 스위치 터치가 없으면 시간을 표시하고, 터치 시 온도를 표시함.
  if (SW == 0) {
    data[0] = display.encodeDigit(digitoneT);
    data[1] = display.encodeDigit(digittwoT);
    data[2] = display.encodeDigit(digitoneM);
    data[3] = display.encodeDigit(digittwoM);
    segto = 0x80 | display.encodeDigit(digittwoT);//시계도트 제어
    display.setSegments(&segto, 1, 1); //시계도트 제어
    delay(500);
    display.setSegments(data);  // 배열값에 있는 시계 데이터 출력
    delay(500);
  } else {
    //    Serial.println(tMSB);   // 온도 값 앞 두자리
    //    Serial.println("\t");
    //    Serial.println(((tLSB >> 6) * 0.25)*100);  // 온도 값 소수점 이하 두 자리(0.25 단위로 표시함)
    //    delay(100);

    int tempLSB = ((tLSB >> 6) * 0.25) * 100;
    int digitTemp1 = tMSB / 10;         // 십의 자리 온도 값
    int digitTemp2 = tMSB % 10;         // 일의 자리 온도 값
    int digitTemp3 = tempLSB / 10;    // 소수 첫 자리 온도 값
    int digitTemp4 = tempLSB % 10;    // 소수 둘째 자리 온도 값
    data[0] = display.encodeDigit(digitTemp1);
    data[1] = display.encodeDigit(digitTemp2);
    data[2] = display.encodeDigit(12);   // 온도 기호(C)표시 숫자 12를 엔코딩해서 세번째 FND에 출력함.
//    data[3] = display.encodeDigit(12); // 네번째 자리 비움
    display.setSegments(data);  // 배열값에 있는 데이터 출력
  }
}

float get3231Temp()
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
  if (Wire.available()) {
    tMSB = Wire.read(); 
    tLSB = Wire.read(); 
    temp3231 = (tMSB & B01111111); 
    temp3231 += ( (tLSB >> 6) * 0.25 ); //소수점 아래 단위의 온도값을 0.25단위씩 처리
  }
  else {
    // 에러일 경우 아무 데이터도 출력하지 아니함
  }
  return temp3231;
}

< 라이브러리 다운로드 >
1. RTClib

RTClib.zip
0.02MB

2. TM1637Display

TM1637-master.zip
1.36MB

3. LiquidCrystal_I2C (2번째 I2C LCD를 활용한 코드 실행을 위해 필요한 라이브러리 입니다)

Arduino-LiquidCrystal-I2C-library-master.zip
0.01MB

 

앞의 연결 도면을 보고,  가지고 있는 브레드보드를 이용해서 연결하면 됩니다.
터치 센서는 어떤 종류든 상관 없습니다, 지금은 터치를 하면 불빛이 들어오는 센서를 사용해 볼게요.
일반 On/Off 스위치와의 차이점은 터치시 Signal 단자로 전압이 출력됩니다. 
그럼, 그 전압을 아두이노 포트로 체크하여 처리해 주면 됩니다.

 

날짜 및 시간 값을 저장하고 제공해 주는 RTC 모듈은 몇가지가 있지만, 오차가 거의 없는 이 DS3231모듈을 추천합니다.

좌우 대칭으로 핀이 설계 되어 있어, 연결하기 편한 쪽을 사용하면 됩니다.
기존에 납땜되어 있는 핀은 브레드보드에 세우듯이 꽂아야 하기에 이 핀을 사용하지 않고, 브레드보드에 밀착될 수 있도록 새로 연결하면 좋습니다.
그리고 모든 핀을 사용할 필요 없고, SCL / SDA / VCC / GND 핀만 사용하면 됩니다.
물론 인두기가 없다면 그냥 점프선을 연결해서 사용하면 됩니다.

 

TM1637 디스플레이는 4개의 FND로 연결되어 있어 시간을 나타내기에 편리한 모듈입니다.

TM1637 또한 그냥 연결해도 되지만 기존 핀을 제거하고 보기 좋게 밀착시켜 볼게요.


브레드보드의 내부 연결 구조상 직접 꽂으려면 핀 작업을 해야 밀착시킬 수 있습니다.

그럼, 제공해 드리는 DS3231RTC_Setting 파일을 가지고 시간을 설정해 보세요.

코드가 업로드 된 상태에서 시리얼 모터를 열면 아래처럼 초기화된 시간을 볼 수 있습니다. 


현재시간으로 설정하는 방법은 코드 속에도 적혀 있는데요,
예를 들어, 먼저 시리얼 모니터 입력창에 T를 입력하고 22년 01월 07일 19시 23분 00초, 금요일 6 형태로 입력합니다. 
→  T2201071923006   엔터

입력 완료 후 엔터를 치면, 바뀐 시간으로 적용되는 것을 볼 수 있습니다.


Temp는 모듈 주변에 체크되는 온도 값을 보여주는데요, 초기 값이 실제 온도치보다 좀 더 높게 나타나는 경우가 있지만, 시간이 지나면서 실제 온도로 맞춰지게 됩니다.


이제, RTC 모듈에 현재 시간을 설정했으니, RTC모듈의 Data를 받아와서 TM1637에 표시해주는 "TM1637..." 코드를 나노에 업로드하면 됩니다. 

그리고 , 라이브러리 파일이 설치되어야 하는데요, 
라이브러리 관리창에서 검색 후 설치하거나, 링크해 드리는 파일을 설치하면 됩니다.
TM1637Display 라이브러리의 경우 이름이 같더라도 내용이 다른 라이브러리를 설치하게 되면, 컴파일 시 에러가 날 수 있는데요, 그럴 경우 위에서 제공해 드리는 라이브러리를 설치해 보세요.

 기본적으로 시간을 표시하고 있다가 스위치를 터치하면 온도 표시가 됩니다.
온도는 31℃로 정확하게 잘 표시되고 있습니다. (온풍기 옆에서 테스트 중)
간혹 온도가 비정상적으로 높게(7~10℃이상) 측정되는 경우가 있는데요, 측정 초기에만 그렇고 시간이 지나면 대부분은 정상적인 온도를 표시해 줍니다.

< 1번. TM1637 시계 회로 완성 및 동작 모습 >

스위치를 터치하면, 시계 표시에서 온도 표시로 바뀝니다. 

 

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

그럼, 두 번째 LCD 시계를 조립해 볼게요.

 《 LCD 날짜 & 시계 & 온도계  만들기 

① 연결도면

2번. I2C LCD 모듈과 DS3231 모듈을 사용한 회로 연결은 아래와 같이 합니다.

나노 보드의 연결도 우노 보드의 핀과 거의 일치하기 때문에 쉽게 연결할 수 있습니다.  위 회로를 참고해서 나노보드를 조립해 보세요. 

I2C 타입의 LCD를 사용하면 매우 쉽게 연결할 수 있는데요, 
I2C 타입의 모듈을 2개 이상 여러개를 사용하더라도 모듈의 SDA(데이터)핀과 SCL(클럭신호)핀들을 각각 묶어주고 우노(나노)의 SDA, SCL에 연결해 주면 됩니다.
I2C 모듈에는 ‘고유주소’들이 매겨져 있기 때문에 아두이노에서 구분 처리할 수 있습니다.
LCD의 경우, 핀이‘ㄱ’자로 되어 있어 브레드보드에 꽂기 편하도록 공구를 이용해서 세워보세요.


준비되었으면, 제공해드리는 LCD용 시계 코드를 열고 업로드 하세요.
LCD를 사용할 때 장점은 데이터를 표시할 수 있는 영역이 훨씬 넓은 것인데요,
년, 월, 일, 시, 분, 초와 온도 등 DS3231에서 추출할 수 있는 모든 데이터를 출력해 볼 수 있습니다.


나노가 연결된 포트와 보드 선택을 확인하고 아래 제공해 드리는 코드를 업로드 합니다.

< 2번 LCD 날짜 & 시간 & 온도 표시 코드 >

/* 
 *  DS3231 RTC이용하여 LCD에 날자(요일)/ 시계 / 온도 값 출력하는 코드 
 *  LCD는 I2C 모듈이 있는 것을 사용하고 있음. 대부분의 I2C LCD의 I2C주소는 0x27임 
 */
#include <LiquidCrystal_I2C.h> 
LiquidCrystal_I2C lcd (0x27, 16,2); 
 
#include <Wire.h>                  // 아두이노 IDE 설치시 기본 제공됨
#include <RTClib.h>                // RTClib 라이브러리
#define DS3231_I2C_ADDRESS 104     // DS3231의 I2C 주소
RTC_DS3231 rtc;        
int Time, Minute;       
char daysOfTheWeek[7][12] = {"SUN", "MON", "TUE", "WEN", "THU", "FRI", "SAT"};
float temp3231;
byte tMSB, tLSB;

void setup () {
  Wire.begin();
  Serial.begin(9600);    
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  lcd.begin();  
  lcd.clear();
}
void loop () {
  get3231Temp();
  delay(100);
  DateTime now = rtc.now();
  int HOUR=now.hour();
//  필요한 경우, 아래 3줄의 24시간을 12시간 단위로 표시하는 코드 추가, 필요 없다면 주석처리!
  int Time = now.hour();
  if (Time>12) { HOUR=now.hour()-12; 
  } else { HOUR=now.hour(); }

  lcd.setCursor(0,0); 
  lcd.print(now.year());
  lcd.print("/");
  lcd.print(now.month());
  lcd.setCursor(7,0); 
  lcd.print("/");
  lcd.print(now.day());    
  lcd.setCursor(10,0); 
  lcd.print(&daysOfTheWeek[now.dayOfTheWeek()][0]);
  lcd.print("day");
  lcd.setCursor(0,1); 
  lcd.print(HOUR);
  lcd.setCursor(2,1); 
  lcd.print(":");
  lcd.print(now.minute());
  lcd.setCursor(5,1); 
  lcd.print(":");
  lcd.print(now.second());
  //"0 " 0뒤에 공백이 있으며, 표시 단위가 변할 때 잔상을 제거하기 위함임.
  if (now.second()==0) { lcd.setCursor(6,1); lcd.print("0 "); }    
  if (now.minute()==0) { lcd.setCursor(3,1); lcd.print("0 "); }    
  if (HOUR==0) { lcd.setCursor(0,1); lcd.print("0 "); }    
  if (now.month()==0) { lcd.setCursor(5,0); lcd.print("0 "); }    
  if (now.day()==0) { lcd.setCursor(8,0); lcd.print("0 "); }    
  lcd.setCursor(9,1);
  lcd.print(temp3231);
  lcd.print(char(223)); // '˚' 표시용 특수문자 아스키 코드값
  lcd.print("C"); 
}

float get3231Temp()
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
  if (Wire.available()) {
    tMSB = Wire.read(); 
    tLSB = Wire.read(); 
    temp3231 = (tMSB & B01111111); 
    temp3231 += ( (tLSB >> 6) * 0.25 ); //소수점 아래 단위의 온도값을 0.25단위씩 처리
  }
  else {
    // 에러일 경우 아무 데이터도 출력하지 아니함
  }
  return temp3231;
}

< LCD 날짜 & 시계 & 온도 표시용 코드 다운로드 >

03_LCD_DS3231_Temp_Clock.zip
0.00MB


 시간뿐 아니라 달력 기능까지 표시할 수 있고, 온도까지 한 번에 출력할 수 있어 좋습니다.
만약, LCD에 불은 들어오지만 데이터 표시가 안 되는 경우가 있다면 지금처럼 LCD 뒷면에 있는 반고정저항 값을 좌 또는 우로 조금씩 조절해 보세요.


저항 값의 위치가 한 쪽으로 치우쳐져 있을 경우 지금처럼 데이터 표시가 되지 않거나 과하게 표시 될 수 있으니, 적절한 위치로 조절해 보세요.
참고로, LCD관련 코딩을 할 때는 잔상 효과를 고려해서 작성해 주어야 하는데요, 
예를 들어, 59초에서 0초로 넘어 갈때, 앞자리 5가 계속 남아 있게 됩니다.
 ( 59 → 0 → 1 → 2 → 3,   실제 : 59 → 50 → 51 → 52 → 53 )

이럴때는 숫자 데이터를 표시할 때 공백을 넣어 앞 숫자를 지워주는 방법으로 간단히 해결 할 수 있습니다.

코드에는 12시간제로 표시하거나 24시간제 표시로 변경할 수 있도록 하였습니다.
참고로, 저렴한 DS3231모듈의 경우 내장된 플래시 메모리가 불량인 경우가 간혹 있습니다 .
이럴 경우, 시간을 설정하여도 전원이 제거되고 다시 연결하면 시간이 리셋되기도 합니다 .
 혹은 DS3231에 있는 리튬배터리가 다된(방전) 경우가 있는데요,  이럴 때는 일반적으로 PC나  자동차 리모컨키에 많이 들어가는 CR2032로 교체해 주면 됩니다.

그럼, 드라이버 관련 다른 문제가 없다고 보고, 코드를 아두이노에 업로드합니다.

< 2번 LCD 날짜 & 시간 & 온도 표시 코드 >

/* 
 *  DS3231 RTC이용하여 LCD에 날자(요일)/ 시계 / 온도 값 출력하는 코드 
 *  LCD는 I2C 모듈이 있는 것을 사용하고 있음. 대부분의 I2C LCD의 I2C주소는 0x27임 
 */
 
#include <LiquidCrystal_I2C.h> 
LiquidCrystal_I2C lcd (0x27, 16,2); 
 
#include <Wire.h>                  // 아두이노 IDE 설치시 기본 제공됨
#include <RTClib.h>                // RTClib 라이브러리
#define DS3231_I2C_ADDRESS 104     // DS3231의 I2C 주소
RTC_DS3231 rtc;        
int Time, Minute;       
char daysOfTheWeek[7][12] = {"SUN", "MON", "TUE", "WEN", "THU", "FRI", "SAT"};
float temp3231;
byte tMSB, tLSB;

void setup () {
  Wire.begin();
  Serial.begin(9600);    
  if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }
  lcd.begin();  
  lcd.clear();
}
void loop () {
  get3231Temp();
  delay(100);
  DateTime now = rtc.now();
  int HOUR=now.hour();
//  필요한 경우, 아래 3줄의 24시간을 12시간 단위로 표시하는 코드 추가, 필요 없다면 주석처리!
  int Time = now.hour();
  if (Time>12) { HOUR=now.hour()-12; 
  } else { HOUR=now.hour(); }

  lcd.setCursor(0,0); 
  lcd.print(now.year());
  lcd.print("/");
  lcd.print(now.month());
  lcd.setCursor(7,0); 
  lcd.print("/");
  lcd.print(now.day());    
  lcd.setCursor(10,0); 
  lcd.print(&daysOfTheWeek[now.dayOfTheWeek()][0]);
  lcd.print("day");
  lcd.setCursor(0,1); 
  lcd.print(HOUR);
  lcd.setCursor(2,1); 
  lcd.print(":");
  lcd.print(now.minute());
  lcd.setCursor(5,1); 
  lcd.print(":");
  lcd.print(now.second());
  //"0 " 0뒤에 공백이 있으며, 표시 단위가 변할 때 잔상을 제거하기 위함임.
  if (now.second()==0) { lcd.setCursor(6,1); lcd.print("0 "); }    
  if (now.minute()==0) { lcd.setCursor(3,1); lcd.print("0 "); }    
  if (HOUR==0) { lcd.setCursor(0,1); lcd.print("0 "); }    
  if (now.month()==0) { lcd.setCursor(5,0); lcd.print("0 "); }    
  if (now.day()==0) { lcd.setCursor(8,0); lcd.print("0 "); }    
  lcd.setCursor(9,1);
  lcd.print(temp3231);
  lcd.print(char(223)); // '˚' 표시용 특수문자 아스키 코드값
  lcd.print("C"); 
}

float get3231Temp()
{
  Wire.beginTransmission(DS3231_I2C_ADDRESS);
  Wire.write(0x11);
  Wire.endTransmission();
  Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
  if (Wire.available()) {
    tMSB = Wire.read(); 
    tLSB = Wire.read(); 
    temp3231 = (tMSB & B01111111); 
    temp3231 += ( (tLSB >> 6) * 0.25 ); //소수점 아래 단위의 온도값을 0.25단위씩 처리
  }
  else {
    // 에러일 경우 아무 데이터도 출력하지 아니함
  }
  return temp3231;
}

< 2번 LCD용 시계 코드 다운로드 >

03_LCD_DS3231_Temp_Clock.zip
0.00MB

코드 업로드 하면, 아래처럼 동작이 됩니다.

 

네, 이렇게 DS3231 모듈을 이용해서 두 가지 버전의 시계겸 온도계를 만들어 보았습니다.

감사합니다.

 《 디지털 시계 뚝딱! 만들기 동영상 설명 참고하세요

 

반응형
반응형

WiFi 기능이 있는 D1 mini 를 사용한 스마트 화분을 만들어 볼게요.
이번에 다루는 내용(목차)입니다.


이번 스마트 화분은 WiFi를 활용하고 미니 사이즈로 만들어 실용성을 높여 제작하였습니다.
ThingSpeak라는 IoT 클라우드 서버를 활용하는 방법에 대해서도 다루고 있으니 여러 방면으로 도움이 되실 듯 합니다.


1. 주요 부품별 특징과 개요 

 ① D1 mini

 D1 mini의 실제 크기 비교입니다.

D1 mini의 가장 큰 장점은 크기가 작고  WiFi 기능을 사용하면서도, esp-01 모듈보다 여유 있는 입출력 포트와 함께 강력한 성능을 발휘한다는 점입니다.

D1 mini 스펙

3.3V 전원을 사용하는 무선통신 모듈이나 OLED등 여러 모듈들과 전원을 연계하기가 편하며, 3.7V 리튬 배터리로도 구동 가능하여 제품의 사이즈를 작게 만들 수 있습니다.

기존 자료에 PWM기능핀을 표시하였습니다

 ② 토양 습도 센서

  토양습도 센서의 스펙입니다.

토양수분 센서는 측정 단자로 전류를 흘려서 되돌아오는 전류량으로 저항값을 알아내고 모듈의 A0 단자를 통해 저항값에 대응하는 0~4.2V 사이의 전압을 출력해 주는 모듈입니다.


이 전압 값을 우노 보드의 경우 10bit의 분해능을 가진 아날로그 A0 포트로 입력받으면 10 bit (2의 10승), 즉 0~1024의 데이터로 처리할 수 있게 됩니다.
그럼, code에서는 'if'와 같은 '비교문'으로 입력 값에 따라 모터를 돌리거나 멈추게 하면 됩니다.

 ③ OLED (Organic Light Emitting Diodes)

클릭 후, 확대하여 보세요


  OLED는 통신방식에 따라 'I2C' 타입과  'SPI' 타입으로 나뉘는데요, 위 이미지와 같은 장단점이 있으며, 보통 선 연결이 간단한 'I2C' 타입을 많이 선호하고 있습니다.  여기에서도 'I2C' 타입으로 진행하고자 합니다. 

우노와 I2C OLED를 연결한 예시입니다

 ④ AMS1117 (3.3V 출력용)

AMS1117레귤레이터는,  3.3V 정전압 출력용이 있고, 5V 정전압 출력용이 있습니다. 
먼저 레귤레이터란, 입력 전압에 상관없이 출력 전압을 일정하게 고정시켜 주는 것을 말하는데요, AMS1117을 거치게 되면 출력되는 전압은 3.3V로 일정하게 유지됩니다.  따라서 3.3V 전용 전압을 사용해야 하는 주요 모듈에는 이러한 정전압 컨버터를 사용하게 됩니다 . 다만, 입력 전압은 최소 4.3V 이상 되어야 하는데, 회로를 거치며 1V 가량이 다운되기 때문이죠. 

아래는 AMS1117을 사용하여 3.3V 전원을 필요로 하는 기기에 연결하는 방법을 보여드립니다.

D1 mini 와 OLED 모두 3.3V 전원으로 동작이 되는 보드입니다

 

 ⑤ L9110S 모터드라이버

L9110S H-Bridge 모터 드라이버 모듈입니다. 
아두이노 포트의 출력(전류)은 최대 40mA로 그리 크지 않은데요, LED를 작동시키는 데는 문제없지만, 모터, 특히 기어가 달린 모터를 사용하거나 용량이 큰 모터 혹은, 부하가 걸린 상태에서는 모터를 제대로 작동 시킬 수 없습니다.
이럴 때, 전원을 분리 공급해 줄 수 있는 릴레이 모듈을 사용하거나,  L9110S나, L298N 모듈처럼, 출력을 증폭시켜 줄 모터 드라이버 모듈을 사용하게 됩니다.

사용방법은 아래 그림처럼 사용할 수 있습니다.  직류 모터는 모듈 하나당 2개 연결이 가능하며, 스텝모터의 경우 4선식 스텝모터 하나의 연결이 가능합니다.

L9110S 사용 방법 예시

⑥ 워터 펌프

워터 펌프는 전원을 넣으면, 모터 끝에 연결한 날개형태의 임펠러가 회전하면서 물을 '입수구'로 빨아들여서,  '출수구'로 배출하게 됩니다. 펌프 종류에 따라 다른데요, 화면과 같은 펌프는 물속에 잠기게 하여 작동시켜야 하며 물 밖에서 테스트할 때는 너무 오래 작동시키지 않아야 합니다. 물속에서 작동되는 이유로 모터 회전에 따른 과열을 상쇄해 주는 점을 고려해 만들었기 때문입니다.
(입수 튜브가 달려 있는 펌프는 물 밖에서 사용할 수 있음, 단 물 밖에서 사용되는 소형 펌프의 경우 구조상 물 흡입이 잘 안 될 수 있음) 

튜브의 길이는 물통과 화분의 위치를 고려해 조금 여유 있게 정하면 됩니다.
튜브의 내경은 펌프 출수구의 외경보다 조금 작은 것을 선택해야 물의 수압으로 인해 쉽게 빠지지 않습니다. (튜브를 벌려 출수구 바깥으로 끼워주세요)

 

⑦ 기타 부품


물통으로는 어떤 것이든 괜찮지만, 엎질러질 것을 감안해 뚜껑을 닫을 수 있는 것이 좋으며 수중 펌프 모터를 사용한다면, 구하기도 쉽고 입구를 쉽게 통과하는 '1.8L 우유통'으로 선택해 보세요.  기타 부품으로는 회로의 연결을 도와줄 작은 사이즈의 브레드 보드가 필요하고요, 터미널 단자는 배터리 소켓의 전선처럼 단단하지 않은 흐물흐물한 연선을 브레드 보드에 꽂으려 할 때 사용하면 편리합니다. 

회로를 만들 때 기본적으로 회로의 전원을 켜고 끌 수 있도록 스위치를 달아주면 좋습니다. 하지만 스위치와 터미널 단자가 반드시 있어야 하는 것은 아니니,  재료를 준비하지 못했다면 제외하고 제작해도 됩니다.
회로에 사용할 전원 방식은,  이미지에 보이는 것처럼 다양하게 선택할 수 있습니다. 
이동이 잦거나 크기를 작게 만들려 할 경우에는 건전지나 리튬이온배터리가 좋으며, 상시적으로 화분에 적용하고자 한다면, 배터리 교환/충전의 번거로움이 없는 어댑터를 추천해요.
배터리를 연결할 경우, 생각보다 오래 가지 못합니다. 실제로, '리튬폴리머',  '18650 리튬이온' 등의 배터리로 테스트해본 결과, 배터리 용량에 따라,  1일~3일 정도 작동된 후 배터리가 소진되었으니 참고하세요.


단선은 내부의 선이 하나의 굵고 단단한 선으로 되어 있어 '브레드보드'에 직접 꽂기가 편하지만 연선은 여러 가닥의 얇은 선으로 되어 있어 잘 휘어지기 때문에 영상과 같은 터미널 단자를 이용하면  쉽게 '브레드보드'에 연결할 수 있습니다.

 

2. 핵심 부품 활용법 및 환경설정 

 ① D1 mini 활용법

그럼,  'D1 mini'와   'OLED'에 대해 좀 더 상세히 설명드려 볼게요.
'Wemos D1mini'기종은 ESP8266시리즈 중,'ESP-12EX'칩을 적용한 'NodeMCU'의 한 종류인데요, 'WiFi' 기능을 핵심으로, 사용하지 않는 핀을 전부 제거하여 보드 크기를 최소화한 기종입니다. 즉, 아두이노 '우노'의 축소 버전인 '나노'가 있다면, 'Wemos D1'의 '나노' 버전이라 할 수 있습니다. 

D1mini는 Wifi를 지원하고 크기가 작으면서 가격도 저렴해, 다양한 'IoT'기기 제작에 활용됩니다. 
아두이노와 같은 보드들은 하나의 핀에 여러 가지 핀 명칭이 붙는데요 잠시 정리해 볼게요. 

이런 보드들은 다목적용으로 사용할 수 있도록 여러 기능의 핀들이 필요하게 됩니다. 만약, 한 핀에 하나의 전용 기능만 둔다면 지금의 핀 수보다 훨씬 많아야 하며 그렇게 된다면, 보드 사이즈 또한 매우 커지게 됩니다. 
때문에, 어떤 조건이나 코드에 따라 하나의 핀이 여러 가지 기능을 할 수 있도록 화면과 같은 '핀 맵'(Pin Map)을 구성하게 됩니다. 
우선, 보드에 인쇄되어 있는 핀은 하드웨어적으로 부르는 핀 명칭이며, ESP pin은  ESP 칩셋을 개발한 'ESPRESSIF SYSTEMS'회사에서 붙여놓은 핀 번호이고요, 아두이노와 같은 보드 종류에 상관없이 일반적으로 명명되는 GPIO라는 핀 명칭이 있습니다. 
그 밖에, 전원핀과 아날로그 입력(A0), SPI, I2C, UART 통신을 위한 핀이 표시되어 있어요. 
'GPIO'란 'General Purpose Input Ouput' 의 줄임말로, 핀을 입력 또는 출력 용도로 사용할 수 있게 하는 핀을 말합니다.
'아두이노'뿐 아니라 '라즈베리파이' 등 다른 보드에서도 일반적으로 많이 사용하는 명칭입니다. 
그런데, 아두이노 코딩에서는 이런 'GPIO핀'과 '보드핀' 번호를 구분해야 동작이 됩니다. 
숫자만 적으면 GPIO 핀 번호로 인식되고, 숫자앞에 D를 붙이면 보드의 핀번호로 인식되어 처리됩니다.

코드 작성시 보드핀 번호와 GPIO핀 번호를 구분하여 사용합니다

 그리고, 보드를 재부팅하려면 리셋 버튼을 눌러주면 됩니다.
그럼, 보드 전원 관련하여 정리해 드릴게요.  'D1 mini' 보드는 '마이크로 5핀' 케이블을 이용하여 전원을 공급받고 PC와 통신도 할 수 있는데요, micro 5핀 단자로 전원이 공급되면, 5v 단자로 5v ,  3.3v 단자로는 3.3v가 각각 출력됩니다.

그럼, 회로에서는 3.3v 전원과 5v 전원을 여기서 끌어다 사용할 수 있습니다.
그리고 'micro 5핀' 커넥터 전원의 공급이 없더라도 ,  'D1 Mini' 보드를 구동 시킬 수 있는데요,
5v 단자에 전원을 넣거나,  3.3v 단자에 전원을 넣으면 동작이 됩니다. (최대 24v, 이하로 입력) 
결론적으로 전원 단자는 입력과 출력이 되는 양방향 단자인데요,  
5v 단자에  5v를 넣으면 ,  3.3v 단자에서도  3.3v 전원을 뽑아 쓸 수 있습니다. 

반대로, 3.3v 단자에 3.3v 를 넣으면 , 5v 단자에는 약2.8v 정도만 출력 되는데요,  전압이 소모되어 낮아질 수는 있어도 입력한 전압에 비해 커질 수는 없기 때문이죠. 

② 아두이노 IDE 환경설정

이 주소를 복사 후 붙여넣으세요     https://arduino.esp8266.com/stable/package_esp8266com_index.json  

D1 mini 보드 또한 esp8266 칩셋을 사용하기 때문에, esp-01과 똑같은 주소 링크를 '파일》환경설정》추가적인 보드... URLs' 항목에 넣어 주세요.
그리고,  '툴 》보드 》보드매니저...' 항목을 열어서  검색창에 'esp8266'으로 검색하세요. 검색된 'esp8266' 보드 패키지를 설치해 주면, IDE에 'esp8266' 관련 보드 메뉴들이 추가됩니다.


그럼, 그중에서 'WeMos D1 R2 & mini' 보드를 선택하면, IDE에서의 설정은 끝나게 됩니다.

아두이노 IDE 버전이 업데이트 되면서 표시되는 이름이 조금씩 다를 수는 있습니다

③ OLED 활용법

 'OLED'에  로고 이미지를 넣고 활용하는 방법에 대해 설명드릴게요. 
이미 언급했듯이 연결이 좀 더 간편한 'I2C' 타입 'OLED'를 사용해 보려고 합니다.
'OLED'기본 사용법이 궁금하다면, 아래 링크 해드리는 'OLED'기초 영상을 참고해 보세요

【 아두이노모듈#29】 OLED 처음 사용 설명서 #1 (SPI, I2C 주요 5종 사용법 안내)

'OLED'에 단순히 데이터만 표시하는 것보다 화면처럼 작품에 어울리는 이미지를 넣어주면 좋아요. 


로고로 사용할 이미지는 구글 등에서 검색해도 되지만, 종류별로 잘 분류되어 있는 아이콘 이미지 사이트를 알려드릴 테니 활용해 보세요.  웹 주소는 'IconArchive.com'인데요,  보이는 것처럼 깔끔한 이미지들이 잘 분류되어 있어요.
https://iconarchive.com/

여기서는 화면에 보이는 '꽃화분' 이미지를 다운로드 받아 보세요. 검책창에 'flowerpot'으로 검색합니다.
검색된 이미지 중에서, 화면과 같은 이미지를 클릭해서 다운로드해 보세요.


'다운로드 PNG' 버튼을 누르면 이미지가 확대되는데요, 
아래 이미지 위에서 마우스 '우클릭'으로 다운로드 하세요.

배경이 투명한 PNG 파일 포맷은, 로고 작업에 매우 유용한 파일 형식입니다.
물론 그림 형태의 이미지도 사용할 수 있지만, 검정과 흰색의 단색만 표현되는 OLED에서는 이미지가 깔끔하게 표시되지 않기 때문에, 이런 심플한 이미지를 권해드립니다.

이제, 그림판을 실행시켜 다운로드한 이미지를 불러오세요.

이미지 크기를 'OLED'에 표시될 사이즈로 맞추고 단색 비트맵 형식으로  바꾸어줘야 하는데요, 그림판으로 손쉽게 해결할 수 있습니다.
그림판의
1. 화면 메뉴에서 "크기 조정" 도구 버튼을 클릭하세요. 


2. 기준을  "픽셀"로 바꾸어 주세요.

3. 이미지의 세로 길이가 OLED 세로 사이즈인 '64pixel'을 넘지 말아야 하므로 60 정도로 할게요.

만약 '가로 세로 비율 유지' 체크를 해제하면, 가로 세로 크기를 각각 설정할 수 있습니다.
4. '파일 》 다른 이름으로 저장' 메뉴에서  'BMP 그림'을 선택하세요.

5. '파일형식' 옵션에서 '단색 비트맵'으로 선택하고 저장 버튼을 클릭하세요.

아래처럼,
6. 경고 팝업창이 뜨면 모두 '확인'을 클릭하면 됩니다.

이제 이미지에 대한 정보를 아두이노 IDE 코딩 툴에서 처리할 수 있도록 'XBM' 파일로 변환해 볼 텐데요.
화면에 보이는 사이트로 접속하면  프로그램 설치 없이 간단히 변환할 수 있습니다 (링크참조).

XBM 파일은 이미지 데이터를 쉼표로 구분한,  바이트 값으로 인코딩 된 파일인데요,  C소스 파일의 형태를 취하고 있어

아두이노 IDE에서 바로 활용하기 편한 장점이 있습니다.
C소스 파일의 형태를 취하고 있어 아두이노 IDE에서 바로 활용하기 편한 장점이 있습니다.

1. Convert image to XBM 화면에 있는 '파일 선택'을 클릭하세요.
2. 조금 전에 60x60 pixel로 저장한 '~~~.bmp'파일을 선택하세요.
3. 'Convert and Download' 버튼을 누르면, '~~~.XBM' 파일로 변환되어 저장됩니다.
4. 'Convert and Download' 버튼을 누르면, '~~~.XBM' 파일로 변환되어 저장됩니다.
5. 이 파일을 '메모장' 혹은 '워드패드' 등으로 연결하여 열어 보면,

아래 이미지처럼 이미지가 C언어 기반의 데이터 배열로 변환 된 것을 알 수 있습니다.

4.그럼 이 부분을 'flowerpot'이라는 적당한 배열 변수명으로 바꾸어 아두이노 코드에 넣으면 됩니다.


아래처럼 별도로 'image.h'형태의 텍스트 파일을 만들어 추가해 주거나,  직접 코드에 넣으면 됩니다 .

아두이노 메인 코드에서는 화면과 같은 형식으로 함수를 호출해 주면 이미지정보를 불러오게 됩니다.
'#define'으로 정의하지 않고, 폭과 높이 값을 숫자로 직접 넣어도 됩니다.

 

④ L9220S / AMS1117 / Soil Sensor / Slide SW 활용법

그럼, 센서와 나머지 모듈들의 활용법에 대해 설명드립니다.
펌프 모터를 원활히 돌리기 위한 모터 구동용 드라이버 L9110S 사용법을 설명드릴게요.


아울러 출력을 조금 높이고 싶은데,  'L298N' 모듈을 갖고 있다면, 이 모듈로 바꾸어 사용해도 됩니다
(단, 코드 수정 필요)

L9110S 모듈을 자세히 보면 반을 나누어 '모터 A'쪽 입출력과 '모터B'쪽 입출력으로 나뉘어 있는데요,
A, B 중 어느 한 쪽에 모터를 연결해서 사용하면 됩니다. 

만약 'A쪽'에 연결하였다면,  아두이노로부터의 제어신호 입력은 여기 'A쪽'으로 넣어 주어야 합니다. 
그리고 여기에 전원을 넣어주면 모터 모듈을 통해 모터가 동작하게 되죠.

모터는, A-1A에 HIGH, A-1B에 LOW신호를 넣으면 모터가, 예를들어 시계방향으로 회전하게 되고 , 반대로, 'A-1A'에 LOW, 'A-1B'에 HIGH 신호를 넣으면 모터가, 반대 방향으로 회전하게 됩니다.
화면과 같은 펌프는 회전방향에 상관없이 출수구로 물이 나오니 모터회전 방향은 신경쓰지 않아도 되
요

'AMS1117' 모듈의 사용법입니다
아두이노에 사용되는 모듈은 3.3v혹은 5v의 일정하게 유지되는 전압을 입력받아야 정상작동됩니다 .
이렇게 일정한 전압을 출력해 주는 것을 '전압 레귤레이터(Voltage Regulator)라고 합니다.

3.3v 칩을 사용한 3.3v 레귤레이터가 있으며, 5v 칩을 사용한 5v 레귤레이터 모듈이 있는데요,
여기서는 3.3v 레귤레이터 모듈을 사용하고 있습니다.

주의사항으로는 레귤레이터를 거치면서 1v 가량이 소모되기 때문에 입력은 최소 4.3v이상이어야 하며, 최대 허용 전류용량(mA)이 800mA이기 때문에 소모 전력이 이를 넘어서는 큰 장치나, 너무 많은 수의 장치를 연결할 경우 'AMS1117'모듈이 손상될 수 있습니다.  이럴 때는 용량이 보다 더 큰, 다른 종류의 레귤레이터 모듈을 사용해야 합니다.

AMS1117 모듈의 전원 연결 예시

회로 연결을 보면, 레귤레이터에서 나오는 출력을 장치 세 곳의 전원으로 연결한 것을 알 수 있는데요,  출력의 +(플러스)는 각 모듈의 +전원(Vcc) 단자에 연결하고, 출력의 -(마이너스)도 각각의, -GND 단자에 연결해 주면 각각의 기기에 3.3v의 전원이 공급됩니다. 

토양(soil) 센서의 활용법입니다.
아래 보이는 센서는 일반적으로 많이 활용되는 센서인데요
토양 센서는 탐침 사이로 수분이 있으면 전류가 잘 흐르는 원리를 이용하는데요,

그 변화되는 값을 아날로그 A0 단자로는 0v~4.2v 사이의 전압 값으로 출력 시키며(5v 입력 기준) 디지털 D0단자로는 특정 경계값 아래로는 0v(Low), 위로는 5v(High)를 출력 시킵니다(5V입력기준)

하지만, 이 센서의 단점이 있는데요, 장기간 사용 시 금속 부분이 산화에 의한 부식이 진행되어,  제대로 동작되지 않을 수 있습니다.  

따라서, 이를 해결하고자,  부식에 강한 얇은 '금도금'을 입힌 제품이 있으며,
아래 처럼, 아예 금속 자체를 사용하지 않는 정전 방식의 센서가 있습니다.

또는, 아예 금속 자체를 사용하지 않는 정전 방식의 센서가 있습니다. 

둘 다, 앞의 센서보다 가격이 조금 비싼데요, 활용 목적에 맞게 선택해 보세요. 

정전식 센서의 사용법도 'D0' 단자가 없는 것을 제외하고는 같습니다. 
알려드리는 아두이노 코딩도 변경 없이 사용하면 됩니다.

회로 연결 또한, 그림처럼 간단하게 연결됩니다.

 

녹색 영역이 흙에 삽입되는 권장 구간이며, 

화분의 특성상 물과의 접촉이 예상되는 붉은 원 영역을 보호하면 좋은데요, 방수를위해 절연테이프를 감거나 본영상에서처럼 글루건을 이용해 글루스틱으로 코딩하면 좋습니다.

스위치의 원리와 활용법입니다.
스위치는 토글, 푸시버튼, 로커, 리밋(limit) 스위치 등 많은 종류가 존재하지만, 기본 기능은 두 선(전기적 접점)을 연결하거나, 끊어 주는 역할입니다. 

여기서는 슬라이드 타입의 스위치를 사용하는데요, '브레드보드'에 꽂기 편한 타입이며, 전원을 연결하거나 차단하는 용도로 사용합니다.
아래 스위치의 작동 구조를 눈여겨보세요.  슬라이드 스위치에서는 가운데 핀이 제일 중요한데요,

가운데 핀을 어느 한쪽에 반드시 연결하여 사용하여야  On / Off 기능을 사용할 수 있습니다.
아래는 스위치를 A-B 연결시킨 ON 상태로 두면, 전원이 연결되어 LED가 켜지게 되고,

아래와 같이 스위치를 B-C 연결시킨다면 OFF 상태로 되고, 전원이 차단되어 LED가 꺼지게 됩니다.



다음으로 전원 방식을 사용 환경에 맞게 선택하면 됩니다.

AA 타입의 건전지는 가장 구하기 쉬운 장점과 교체가 번거롭고 비용이 많이 든다는 단점이 있습니다 .
리튬 폴리머 또는 이온 배터리는 얇고 가벼운 장점과 충전 및 작은 커넥터 연결의 불편함이 있습니다.|
'18650 리튬이온' 배터리는 이동성과 충전의 편리함이 있고, 
주기적 교환의 불편함과, 회로 내 쇼트에 의한 발화를 ※주의! 해야 합니다.
어댑터를 연결하면 배터리 교환에 대한 불편함이 없고, 상시적인 전원 공급이 가능한 장점이 있고,
설치되는 곳에 전원 공급 콘센트 등이 있어야 한다는 제약이 있습니다.
실습에서는 배터리 연결도 해보았고, 어댑터 또는 마이크로5핀 USB전원케이블도 연결해 보았는데요, 

(추천)분리형 어댑터/USB멀티탭을 이용, 마이크로5핀 케이블만 간단히 연결할 수 있어 매우 편리해요. 

 

① IoT 화분 개념도

수분 자동 공급 IoT 화분의 개념도입니다.  개념도를 보면서 어떻게 연결을 해야할지 파악하면 좋습니다.

수분 자동 공급 화분을 구현할 때, 단계를 나누어 작업해보면 좋습니다.
1단계로 기본적인 물공급 화분을 제작하는 것으로 진행하고, 
2단계는 wifi를 이용해 클라우드 서버에 접속해 IoT기능을 활용해 볼 수 있는 실습으로 진행해 보세요.

② IoT화분 연결도면

아래는, 이 개념을 바탕으로 실제 회로 동작을 위한 연결도입니다.

이미지를 클릭하여 확대해서 보세요

전원은 앞서 설명드린 것처럼,  배터리 혹은 어댑터 중 선택하면 됩니다. 
펌프 모터는 물에 잠기는 것과 물 밖에서 호수만 넣어 동작되는 것을 선택할 수 있습니다. 
이번 프로젝트에 사용한 펌프는 3v~6v로 동작하는 소형 펌프이기 때문에 문제가 없지만, 
만약 용량이 좀 더 큰 펌프로 교체할 경우,  전력 부족으로 제대로 동작하지 않을 수 있어요,
필요하다면 용량에 맞추어 릴레이 모듈 추가나 '전원공급부'를 보강하여야 합니다(코드 변경도 필요함)

③ 펌프모터 전선 연장하기

펌핑모터 전선 연장하기
펌프 모터의 '전원선'은 기본적으로 길이가 매우 짧기 때문에,  '전원선'을 여유 있게 아래처럼 연장해 보세요.

전기적 연결이 안정적이려면 연결 부위에 인두기로 납땜을 해주면 제일 좋고, 인두기가 없더라도 전선 외피를 충분히 탈피하여 접촉면이 커지도록 손으로 잘 꼬아 주면 됩니다. 
그리고 물에 접촉될 확률이 높은 만큼 연결 부위를 전기 테잎 혹은 열수축튜브 등으로 감싸주어야 해요. 
수축 튜브는 사이즈 별로 있으며, 라이터 혹은 헤어드라이기 등으로 수축 시킬 수 있습니다.

각각의 선을 수축 튜브로 감싸준 다음, 좀 더 굵고 긴 튜브로 전체를 다시 감싸주면 깔끔하게 마감을 할 수 있습니다.

④ 펌프 물통 제작하기

이제 우유통을 이용해서 수분 공급 물통을 만들어 볼게요. 물통은 생수통도 있고 여러 가지를 생각해볼 수 있지만, 
물이 오염되거나 쏟아지지 않도록 뚜껑을 닫을 수 있는 것이 좋으며, 수중모터가 통과할 수 있는 입구 크기를 지니는 물통을 찾다 보니, 구하기도 쉬운  1.8L 우유통을 사용하게 되었습니다. 

⑤ 펌프 호수(튜브) 끼우기

이제 펌프 호수를 끼워 볼게요, 만약, 펌프 호수를 끼울 때, 너무 쉽게 들어간다면, 좀 더 작은 내경의 호수를 사용하세요.
펌프가 가동될 때, 물의 압력으로 호수가 쉽게 빠져버릴 수 있기 때문입니다. 


이제 호수가 통과할 크기의 구멍을 뚫어주겠습니다.  

구멍은 핸드드릴을 사용해서 뚫을 수도 있지만, 드릴 작업은 손을 다칠 위험이 있으니 장갑을 끼고 안전에 주의해 주세요. 
가급적이면, 아래처럼, 집에 막 쓰는 인두기 '막두기'가 있다면, 인두기 사용을 권해드려요,  드릴로 뚫는 것보다, 작업이 훨씬 수월해집니다. 

호수와 모터의 전원 케이블을 함께 끼워주세요. 

그리고,  펌프의 전원선은 호수와 전원 케이블이 따로 놀지 않도록 머리를 땋듯이 감아주면 좋습니다

 

⑥ 아두이노 코드 작성하기

아두이노 코딩입니다.


현재 WiFi 기능이 있는 것과 없는 것, 두 가지 코드를 제공해드리는데요,
먼저,  
1.  WiFi 기능을 사용하지 않는 코드로 기본기능을 테스트해 보세요. 
2. 사용하고자 하는  OLED가 따로 있다면, 해당 부분의 코드를 수정하세요.
3.  펌프를 작동시킬 센서의 값은 화분의 종류와 상태에 따라 테스트해보며 수정하면 됩니다.
4. 코드 '컴파일'할 때  발생하는 에러의 대부분은 라이브러리 문제입니다.
5. 라이브러리가 없거나, 같은 이름이라도 버전이 다르거나, 제공자가 다르면 에러가 발생하게 됩니다.

《 ① WiFi 기능 없는 Basic Code 》

: WiFi로 데이터 전송하는 기능 없이 순수하게 자동 물관리하며 작동 상태를 OLED에 표시해 주는 기본 코드입니다.

#include <ESP8266WiFi.h>
#include "SSD1306Wire.h"            // I2C용 OLED 라이브러리 사용
// SSD1306Wire  display(0x3c, 2, 0);   // esp8266-01 과 OLED를 연결할 경우 GPIO (SDA, SCK) 포트 번호
SSD1306Wire  display(0x3c, 4, 5);  // D1 mini 와 OLED를 연결할 경우 GPIO (SDA, SCL) 포트 번호
int motorA1 =  D6; // L9110S 모듈에 연결할 핀 번호 (D1 mini 보드에 적힌 ESP핀 번호 임)
int motorA2  = D7; // L9110S 모듈에 연결할 핀 번호 (D1 mini 보드에 적힌 ESP핀 번호 임)
int sensorVal = A0; // D1 mini 보드의 아날로그 포트 번호

void setup(){
    Serial.begin(9600);
    pinMode( motorA1 , OUTPUT); 
    pinMode( motorA2 , OUTPUT);   
    display.init();
    display.flipScreenVertically();  // 스크린 상하 플립
    display.setFont(ArialMT_Plain_16);  // ArialMT_Plain폰트는 10, 16, 24
    display.drawString(20, 32, "by RasINO IoT");        
    display.display();  // 이미지나 글자를 출력(변경) 하고자 할 때는 이 명령어를 보내야 화면에 나타납니다.
    delay(2000);
    display.clear();
}

void loop () {    
    sensorVal = map(analogRead(A0), 450, 1023, 100, 0); //토양센서 측정범위를 확인 후 100~0의 값으로 변환함
//    Serial.print("Sensor = ");
//    Serial.println(analogRead(A0));  // 0(건조) ~ 100(습함) 값 출력    
    display.setFont(ArialMT_Plain_16);  // ArialMT_Plain폰트는 10, 16, 24  
    display.drawString(0, 0, "Pot :");
    display.drawString(40, 0, String(sensorVal));    
// #A --테스트 후, 모터를 작동시킬 센서 값을 조절해주세요 -- 현재는 80으로 설정 --  
    if ( sensorVal < 80) {
      display.setFont(ArialMT_Plain_16);  // ArialMT_Plain폰트는 10, 16, 24  
//      Serial.print("Pot is Very Dry !");
//      Serial.print("Now Pumping...");
      digitalWrite(motorA1, HIGH);
      digitalWrite(motorA2, LOW);
      display.drawString(0, 30, "Pot Dri!");
      display.drawString(0, 45, "Pumping...");
      display.display();
      delay(10);
    } else {
      digitalWrite(motorA1, LOW);
      digitalWrite(motorA2, LOW);
      display.drawString(0, 30, "Pot OK!");
      display.drawString(0, 45, "Sleeping...");
      display.display();
      delay(10);
    }
    display.clear();
}

<코드 다운로드>

AutoPot_OLED_Basic.zip
0.00MB

그럼, 코드를 컴파일합니다.   
만약 아래처럼, 컴파일 에러가 난다면, 특히 라이브러리 에러가 난다면 기존 라이브러리를 백업해 두거나 삭제하고서,
지금 제공해드리는 라이브러리를 설치해 보세요.


 ① <ESP8266WiFi.h> 라이브러리 다운로드 

ESP8266WiFi.zip
0.08MB


 ② <SSD1306Wire.h> 라이브러리 다운로드
(SSD1306 OLED 드라이버를 사용하는 경우에 필요한 라이브러리입니다. 만약 제 작품에 사용한 OLED가 아닌 다른 드라이버를 사용하는 OLED를 사용한다면 라이브러리 에러가 날 수 있으니, 갖고 있는 OLED의 제조사 홈페이지 등에서 관련 라이브러리를 찾아 설치해 보세요)

esp8266-oled-ssd1306-master.zip
0.29MB



만약, 위 라이브러리를 설치하였음에도 라이브러리 에러가 나는 경우에는 아두이노 IDE 메뉴에서 보드 선택을 D1 mini로 해주었는지 확인해 보세요.   기본적인 우노 보드나 다른 보드로 선택되어 있는 상태에서 컴파일 하게 되면 라이브러리 에러가 아님에도 라이브러리 에러처럼 보이는 에러가 날 수 있습니다. (아래 이미지 참조)

보드가 연결 된 포트까지 정확히 선택해 주세요


 보드 메뉴에 "WeMos D1 R2 & mini"와 같은 혹은 유사한 이름의 보드가 없다면,   제 글 상단에 알려드린 것처럼, 아두이노 IDE의 환경설정 부분에 보드 목록(Json 주소)을 추가해 주세요.

이 주소를 복사 후 붙여넣으세요     https://arduino.esp8266.com/stable/package_esp8266com_index.json  

파일 》 환경설정 》 추가적인 보드  'URLs' 부분에 'ESP8266보드' 링크를 추가해 주세요. 
그리고,  "툴 》 보드" 메뉴로 다시 들어가 보면,  ESP8266관련 보드들이 추가된 것을 볼 수 있습니다. 
그럼, 목록 중에서, ' Wemos D1 R2 & mini '를 선택하세요.

컴파일이 문제 없이 되었다면,  D1 mini에 코드를 전송하면 됩니다.

코드를 잠시 살펴볼게요. 
 sensorVal = map(analogRead(A0), 450, 1023, 100, 0);   
이 부분에서는 토양센서를 화분에 꽂아 보고 수분이 제일 적을 때와 제일 많을 때(측정 최대치)를 먼저 확인하여 고쳐주세요. 이 실험에 사용된 화분에서는 450(Min)과 1023(Max) 입니다.   이를 계산하기 쉽게 100~0의 값으로 '매핑(mapping)'하였습니다.

그리고,  if ( sensorVal < 80)  이 부분에서, 센서의 수분이 80이하는 측정되면 펌프를 작동하도록 하였는데요, 
여러분의 화분 상태나 조건에 따라 필요한 수치로 바꾸어 주면 됩니다. 

그리고 모터가 돌아가거나  돌아가지 않을 때의 상태를 쉽게 알 수 있도록 아래처럼, OLED에 글자를 표시하도록 하였습니다.
      display.drawString(0, 30, "Pot Dri!");
      display.drawString(0, 45, "Pumping...");  // 펌프가 작동 중...

      display.drawString(0, 30, "Pot OK!");
      display.drawString(0, 45, "Sleeping...");  // 펌프가 작동 안 함.

그럼 회로를 연결하고 코드를 업로드하여 테스트해보세요.

 

《 ② WiFi 접속 기능 있는 WiFi Web Code 》

만약, 잘 작동한다면, 이제 WiFi 기능을 넣은 코드로 테스트해 보면 됩니다. 
: 자신 주변의 WiFi에 접속해 보는 코드를 가지고 테스트해 보는 코드입니다.  
WiFi에 접속이 되면 ThingSpeak 라는 클라우드 서버로 접속이 되는 코드입니다.
( 단, 이 기능을 완벽히 사용하려면 이 글 후반부에 있는 ThingSpeak의 계정 가입 후 설정 및 토큰을 받아야 하지만, 주변 WiFi접속이 잘 되는지까지는 테스트 가능합니다)  

#include <ESP8266WiFi.h> //제시한 라이브러리를 설치 후에도 이부분에 에러가 나면,ESP8266환경설정과,보드를 D1 mini(esp8266보드 계열)로 선택했는지 확인.
#include <WiFiUdp.h>
#include "mySSID.h"
#include "Images.h"
#include "SSD1306Wire.h"           // I2C용 OLED 라이브러리 사용

// SSD1306Wire  display(0x3c, 2, 0);  // esp8266-01 과 OLED를 연결할 경우 GPIO (SDA, SCK) 포트 번호
SSD1306Wire  display(0x3c, 4, 5);  // D1 mini 와 OLED를 연결할 경우 GPIO (SDA, SCL) 포트 번호
String apiKey = thingSpeak_Pot;  // ThingSpeak의 Write API Key 입력 (사이트 가입후 받은 번호를 직접 입력) 
char ssid[] = mySSID1;  // 파일 추가로 입력해도 되고, 여기에 WiFi이름을 직접 입력해도 됩니다.
char pass[] = myPASS1;  // WiFi 비번 입력.
const char* server = "api.thingspeak.com";
WiFiClient client;    // client 시작하기

int motorA1 =  D6;   // L9110S 모듈 관련 변수 선언
int motorA2  = D7;   // L9110S 모듈 관련 변수 선언
int sensorVal = A0;

void setup(){
    display.init();
    display.clear();
    display.flipScreenVertically();  // 스크린 상하 플립
    display.drawXbm(0, 0, RasLogo_W, RasLogo_H, RasLogo);       
    display.display(); 
    delay(2000);
    display.clear();
    display.drawRect(0, 0, 128, 64);
    display.setFont(ArialMT_Plain_16);  // ArialMT_Plain폰트는 10, 16, 24
//    display.setTextAlignment(TEXT_ALIGN_CENTER);    // LEFT , RIGHT
    display.drawString(5, 10, "Auto Flower Pot");        
    display.setFont(ArialMT_Plain_10);  // ArialMT_Plain폰트는 10, 16, 24    
    display.drawString(8, 36, "RasINO.TISTORY.COM");            
    display.drawString(11, 48, "YouTube:RasINO IOT");         
    display.display(); 
    delay(3500);    
    
    Serial.begin(9600);
    WiFi.begin(ssid, pass);
    while (WiFi.status() != WL_CONNECTED) {
      delay(100);
      Serial.print("*");
      display.clear();
      display.drawString(11, 48, "Connecting WiFi...");               
      display.display(); 
      delay(6000);
      break;
    }
    pinMode( motorA1 , OUTPUT); 
    pinMode( motorA2 , OUTPUT);   
    display.clear();
}

void loop () {
    sensorVal = map(analogRead(A0), 450, 1023, 100, 0);  // 토양센서 측정범위 확인 후 0~9의 값으로 맵핑값 저장
//    Serial.print("Asensor = ");
//    Serial.println(analogRead(A0));  // 0(건조) ~ 100(습함) 값 출력    
    display.drawXbm(0, 0, flowerPot_W, flowerPot_H, flowerPot);
    display.setFont(ArialMT_Plain_16);  // ArialMT_Plain폰트는 10, 16, 24  
    display.drawString(50, 0, "Pot :");
    display.drawString(90, 0, String(sensorVal));    
    if ( sensorVal < 52) {
      display.setFont(ArialMT_Plain_16);  // ArialMT_Plain폰트는 10, 16, 24  
//      Serial.print("Pot is Very Dry !");
//      Serial.print("Now Pumping...");
      digitalWrite(motorA1, HIGH);
      digitalWrite(motorA2, LOW);
      display.drawString(50, 30, "Pot Dri !");
      display.drawString(50, 45, "Pumping...");
      display.display();
      delay(10);    
    } else {
      digitalWrite(motorA1, LOW);
      digitalWrite(motorA2, LOW);
      display.drawString(50, 30, "Pot OK!");
      display.drawString(50, 45, "Sleeping...");
      display.display();
      delay(10);
    }
    display.clear();

    if (client.connect(server,80))   //   "184.106.153.149" or api.thingspeak.com   
    {  
       String sendData = apiKey+"&field1="+String(sensorVal)+"\r\n\r\n";      
       //Serial.println(sendData);
       client.print("POST /update HTTP/1.1\n");
       client.print("Host: api.thingspeak.com\n");
       client.print("Connection: close\n");
       client.print("X-THINGSPEAKAPIKEY: "+apiKey+"\n");
       client.print("Content-Type: application/x-www-form-urlencoded\n");
       client.print("Content-Length: ");
       client.print(sendData.length());
       client.print("\n\n");
       client.print(sendData);
       delay(10);
    }
}

<코드 다운로드>

AutoPot_OLED_Web01_Ras.zip
0.00MB

 보통 WiFi접속의 경우, 집에서 WiFi공유기에 접속하는 경우와,  회사에서 회사의 WiFi공유기에 접속하는 경우, 그리고 자신의 핸드폰의 핫스팟(테더링) 으로 접속하는 3가지로 나누어 볼 수 있는데요, 
이 3가지의 WiFi에 대응이 되도록 WiFi ID와 비번의 목록 파일(mySSID.h)을 사용자 정의 라이브러리 파일로 따로 만들었습니다.   예를 들어, 1번은 집에서 사용할 때의 WiFi이고,  2번은 회사,  3번은 자신의 스마트폰 핫스팟 입니다.
 그런데, 그냥 이 목록을 만들지 않고 접속 가능한 한 가지 WiFi ID와 비번을 직접입력 해도 됩니다. 

만약 아래와 같은 에러가 난다면, "mySSID.h"와 같은 파일 이름의 라이브러리 파일을 만들고 아두이노 코드가 있는 폴더에 옮겨 놓으면 됩니다. 

그래서 mySSID.h와 같은 파일이 아두이노 코드 폴더에 함께 있으면 아래처럼 표시됩니다. (#include "mySSID.h" 코드 필요)

그런데, 이렇게 여러가지 WiFi 필요 없고 바로 접속 가능한 WiFi 하나만 아래 코드처럼 입력해도 됩니다. 

WiFI ID와 비번을 직접 입력해도 됩니다

 

 OLED에 올릴 이미지 데이터도 코드에 직접 넣어도 되지만  코드가 번잡해지기 때문에 아래처럼 "Image.h"라는 사용자 정의 라이브러리 파일로 만들었습니다. 
위 아두이노 코드 압축파일을 다운로드하면 그 속에 아래의 Images.h파일도 함께 들어 있습니다.

 

그럼 이제, WiFi접속 기능을 넣은 코드를 살펴볼게요.  
기본동작은 앞의 코드와 같고, 'WiFi'접속을 통해서 수분 데이터를 'Web'과 스마트폰에서 볼수 있는 기능입니다 .
이 기능을 활용하려면, 클라우드 서버가 필요한데요, 몇 가지 플랫폼 중에서 'thingspeak.com'를 이용해보겠습니다, 무료기능으로 충분히 사용 가능해요. 

아래처럼,  thingspeak 이용을 위한 내용을 넣어 주어야 합니다

apikey 항목에는 여러분이 Thingspeak 사이트에 회원가입 후 부여받은 Write API Key를 입력해야 해
요.
나머지 부분은 앞의 기본 코드와 동일하며,  표시하고 싶은 내용이나 로고를 추가해 넣으면 됩니다. 
그리고 앞서 설명한 것처럼, 'I2C  OLED'용 라이브러리는 몇 가지 종류가 있습니다.
그 중에서, 본 글에서 사용한 'SSD1306Wire.h' 라이브러리의 사용할 때 중요한 점이 있는데요,
출력하고자 하는 내용 뒤에는 OLED에 뿌려주는 명령어인 'display.display( )'를 꼭 넣어주여야 해요. 

그래서, 'OLED' 관련 기본 코드 구조는 아래와 같으니 참고하세요  ('SSD1306Wire.h' 를 사용할 경우)

여기서는 처음 라즈이노IoT의 로고가 2초가량 나오고 화분 이미지가 나오도록 하였습니다.  
LogoA표시를 위해 display.display( )함수를 사용하고서, 표시할 시간 delay를 적당히 주면 됩니다. 
그리고  LOGO B를 나타내기 전에 이전 로고의 잔상을 display.clear( )함수로 지워주어야 합니다. 

아래 부분이 'thingSpeak 클라우드 서버'로 접속해서 정보를 전달해 주는 부분입니다.

thingSpeak에서 제공하는 형식이며, 오타가 나면, 정보를 제대로 주고받을 수 없으니 주의해야 해요.

그럼,  thingSpeak 서버를 사용하는 방법에 대해 다루어 볼게요. 

《 thingSpeak 서버를 사용하는 방법 》

먼저,  1.  thingSpeak.com으로 접속하여  회원가입을 진행합니다.

아래 2.  Get Started 버튼을 클릭하세요.

 

3.  ' Create one! '을 클릭하여 새로운 계정 만들기로 들어갑니다.

4.  여러분의 'Email 주소'와 함께 관련 내용을 채우고 계속 진행해 주면, 쉽게 회원가입이 됩니다.


5.  가입 완료 후 등록 한 Email을(아이디) 넣고 로그인을 합니다.
그럼,  여러분들의 화면에는 비어있는 My Channels이 열리게 됩니다.


' New Channel '을 클릭하면 화면과 같은 프로젝트 채널을 하나씩 생성할 수 있습니다.

이미 생성된,  각 프로젝트를 클릭해서 열어보면,  아래처럼 설정한 항목들의 데이터가 보이는데요.
데이터를 보내는 하드웨어가 계속 작동 중이면,  데이터가 계속 수집 되게 됩니다. 


" Private " 채널은 본인만 확인할 수 있는 채널이며, " Public " 채널은 측정 데이터를 외부에 공개할 수 있는 채널입니다.
아래처럼, " Channel Settings "에서는 채널에서 측정하고자 하는 항목의 이름과 표시 방법을 정할 수 있습니다. 

" Sharing " 을 통해 데이터를 e-mail로 보낼 수 있고요,


각자 고유한 " API Keys "를 부여받게 되는데요,  아두이노 코드에 사용될 중요한 키입니다.

그 중에서 " Write API Key "는 thingSpeak 서버로 데이터를 보내기 위해 사용되는 인증키입니다.
" Read API Keys "는 thingSpeak 서버에 기록된 데이터를 읽어 올 때 필요한 인증키입니다. 

각 API Key들은 필요하다면, 삭제 후 다시 부여받을 수 있습니다. 
아두이노 코드로 돌아가 보면, 이 부분에 자신의 API Key를 적어 넣으면 되는데요, 화분의 습도 데이터를 서버에 기록하는 상황이므로 "Write API Key"를 적어야 합니다. 

Key를 직접 적어 넣어도 되며, 여기서처럼,  #define으로 정의하여 추가 파일로 연결해도 됩니다. 


새 채널을 만들 때,  복잡해 보여도 실제로 중요한 항목은 몇 가지 되지 않으니 염려 마세요. 
반드시 필요한 항목은,  "새 채널의 이름" 항목과, 데이터를 표시할  항목(Field)만 입력하면 됩니다. 
나머지는 설명을 달거나 필요할 경우의 옵션입니다.


테스트를 해보니, 필드의 제목을 한글로 적으면, 처음엔 문제없지만,  재접속할 때 한글 제목이 깨지는 것 외에는 모두 잘 작동되었습니다.  그래서 그냥 영어로 네이밍 하는게 좋습니다. 
마지막으로 "Save Channel"을 클릭하면 채널 생성이 완료됩니다.

"Field"(항목)가 두 개 이상이라면, "Add Visualizations"으로 추가하여 옵션을 조정할 수 있습니다. 
" Add Widgets "으로 데이터를 표시하고 싶은 형태를 선택하여 추가할 수 있습니다.

위젯의 종류에 따라, 필요한 범위나 표시할 색을 지정해 보세요. 


추후에 데이터가 수신되면 경고 표시는 사라지며, 데이터 표시가 시작됩니다. 

"Export recent data"를 통해 최근의 데이터를 Json, XML, CSV 등의 파일로 저장하여 활용할 수 있습니다.
우선 예시로, 엑셀에서 활용 가능한 CSV 파일로 저장해 보겠습니다.

CSV 파일은 ' , ' 콤마로 구분된 데이터 파일로, 엑셀에서는 '셀(Cell)'단위로 불러올 수 있기 때문에 데이터를 다듬을 필요 없어 편합니다. 
그러면, 측정된 데이터를 가지고 엑셀 차트를 만들어 활용하거나, 엑셀 데이터로 축적해 둘 수 있습니다.

자, 이제 IoT 서버도 준비되었으면,  코드를 컴파일 시켜 아두이노로 업로드하세요.
만약, 자신이 부여받은 API키나 서버 관련 정보가 정확하지 않다면, 아두이노 자동물공급 기능은 실행 되는데 문제 없지만 서버로 데이터가 전달되지 않아 웹이나 앱에서 값이 제대로 표시되지 않을 수 있습니다. 

추가적으로,  영상에서 보았던, 스마트폰용 앱을 설치해서 데이터를 확인해 볼 수 있습니다.
구글 플레이스토어에서, " thingspeak "로 검색해서 앱을 다운로드해 설치하세요. 
'thing Speak'를 이용하는 앱은 몇 가지 있으니 사용해보고 더 편한 것으로 하면 됩니다. 

앱에서 채널을 추가하여 데이터를 표시하고자 할 때,  입력이 요구되는 " Channel ID "는 , 
'thingSpeak' 사이트에서 채널을 생성할 때, 자동 부여되는 '채널 ID'를 입력하면 됩니다.
생성 채널별로 ID가 각각 있기 때문에, 앱에서 보려고 하는 채널의 ID를 입력해 주면 됩니다.



드디어,  회로 조립입니다.

아두이노 코드가 업로드된, D1 mini를 준비하고 회로도에 따라 부품들을 연결해 주세요. 
영상에 보이는 전원 레귤레이터는 뒤집어 꽂을 수 있도록 핀을 반대 방향으로 납땜한 것입니다.
따라서 여러분은 어떤 방향이든, 배치하기 수월한 방향으로 꽂으면 됩니다. 
중요한 것은 영상은 참고로 하고, 부품 연결을 회로도를 보고 극성에 주의하여 정확히 연결해야 합니다.


영상에 보이는 녹색 철심은 말랑한 튜브를 흙 속 깊이 잘 들어가도록 하고 고정하기 위한 용도인데요, 
쉽게 구할 수 있는 세탁소의 철심 옷걸이를 벤치로 잘라, 간단히 만들 수 있습니다. 


그럼, 전원을 'ON' 시키면, 로고가 나오고서,  'WiFi'에 접속을 시도하고 있네요.
그리고 데이터가 함께 표시되는 최종 화면이 나오면 성공입니다.



그럼, 동작이 잘 되는지 확인해 볼게요.
흙이 말랐을 때를 가정해서, 센서를 들어 올려볼게요.


센서 값이 코드에서 정한 값 이하로 내려가면, 곧바로 펌프 모터가 작동해서 물이 나오는지 보세요.
그리고 센서를 습기 가득한 흙 속으로 밀어 넣었을 때, 펌프 모터가 멈추면 정상 작동하는 것입니다


별도로 배터리 소모를 줄이기 위해 'OLED'에 전원 스위치를 연결해 보았는데요, 'OLED'가 꺼져 있어도 잘 작동하는지 확인 중입니다.

네,  아주 잘 작동하고 있네요.

실험을 해보니 OLED를 꺼놓더라도 소형 배터리의 한계로 3일 이상 지속되기는 힘들었습니다.
만약,  배터리 교환이 불편하다면, 어댑터로 상시 전원을 사용하는 것이 가장 좋습니다.
하지만, '리튬폴리머' 배터리를 사용하면 제품의 크기를 가장 작게 만들 수 있는 장점이 있습니다. 

그럼  이번엔,  재충전 사용 및 활용도가 높은 18650 리튬 배터리를 사용해보겠습니다.

다만, '18650'과 같은 '리튬이온 배터리'는 합선에 의한 '발화' 및 '소폭발'이 쉽게 일어나니 ,  따라서 연결 과정이나 사용 과정에서 반드시 주의가 필요합니다.  3.7V 두 개를 '직렬' 연결한 7.4V가 되는 소켓을 사용하고 있는데요,
소켓의 출력 선이 부드러운 연선으로 되어 있어,  '브레드보드'에 꽂기 어렵기 때문에, 
영상에 보이는 터미널 단자를 사용하면 쉽게 꽂을 수 있습니다.

역시 잘 작동 되고 있습니다.

아울러, ThingSpeak 앱을 연결하여 활용성을 높일 수 있습니다. 

스마트폰의 앱과 PC의 웹에서 함께 데이터를 관리할 수 있습니다.


먼저 기본형을 만들어 보세요,  그리고 실제 장시간 테스트를 해보았을 때, 아쉬운 부분을 보완하는 방법을 지금 설명해드릴 테니 적용해 보세요. 


1.  장시간 사용에 따른 금속 탐지 부위의 부식 문제는 
: 센서를 정전용량 방식으로 바꾸면 쉽게 해결할 수 있습니다.


2.  물과의 접촉이 우려되는 연결 부위를 
: 열 수축 튜브를 사용하면 쉽게 차단할 수 있고, 연결도 단단히 할 수 있습니다.


 화분에 직접 삽입되는 센서의 회로 부분이 외부에 노출되어 있어
3. 물이나 흙의 접촉으로 인해 손상이 될 수 있는데요 : 쉽게 구할 수 있는 '글루건'으로 코팅을 해주면 간단히 해결할 수 있습니다.


4. 배터리 장착 테스트를 통해 확인한 결과,  대용량 배터리가 아니라면, 2~3일마다 배터리를 교체나, 충전해 주어야 하는 불편함이 있었는데요,  USB 소켓을 통해 어댑터 혹은 멀티탭의 상시 전원을 사용하면 별다른 관리 없이 사용할 수 있어요.

 

5.  마지막으로  물과의 접촉 가능성이 큰,  회로 본체를 보호하는 것이 필요합니다
 케이스를 씌워주면 좋은데요,  주변에 투명 아크릴 케이스가 있다면, 정말 보기에도 좋을 것 같네요.




※  그럼,  지금껏 설명드린 방법을 사용하여,  집이나 사무실의 화분을 자동으로 관리해 주는 
   IoT 시스템을 재미있게 만들어 보세요 ~  *^^*

감사합니다.

반응형
반응형

▶ 아래가 아두이노 메가 보드의 핀맵 또는 핀 아웃입니다.(이미지를 클릭하면 확대 됩니다)

이미지 :&nbsp; Arduino.cc
이미지 : Arduino.cc
아두이노 메가의 디지털 핀맵
아두이노 메가 기타 핀
이미지 : www.theengineeringprojects.com

▶ 아래는 아두이노 메가의 데이터 시트입니다. 

이미지 :&nbsp; Arduino.cc

 

▶ 아두이노 메가에서 여러개의 하드웨어 시리얼 통신핀 사용하기
 아두이노 메가에서는 여러개의 하드웨어 시리얼 통신핀을 제공하고 있는데요, 이를 사용하는 방법에 대해 설명드립니다.

메가 핀 옆에 글자로 14번 15번은 TX3, RX3 , 16번 17번은 TX2, RX2,  18번 19번은 TX1, RX1 로 표시되어 있는데요,
0번 1번은 그냥 RX, TX로 생각하면 되는데요, 
 일반적으로 아두이노 우노에서는 하나뿐인 하드웨어 시리얼 핀을 선언할 때는 Serial.begin 로 선언하고,  사용할 때는 Serial.print("  ") 와 같이 사용하게 되는데요,  Mega보드의 경우,

Setup ( )  {    }에서,  
Tx1 , Rx1은  Serial1.begin 과 같이 선언해주고,  
Tx2 , Rx2는  Serial2.begin 과 같이 선언해주고,  
Tx3 , Rx3는  Serial3.begin 과 같이 선언해주고,  

main ( )  {   } 에서 사용할 때는, 
Tx1 , Rx1은  Serial1.print 와 같이 사용하면 되고,  
Tx2 , Rx2는  Serial2.print 와 같이 사용하면 되고,  
Tx3 , Rx3는  Serial3.print 와 같이 사용하면 됩니다.

 

참고로 아두이노 우노에서는 모든핀을 소프트웨어 통신핀으로 사용할 수 있지만,  메가 보드에서는 소프트웨어 통신 핀으로 사용 가능한 핀이 정해져 있습니다. 
   - 아두이노 메가의 경우10, 11, 12, 13, 14, 15, 50, 51, 52, 53, 62, 63, 64번 핀이 사용 가능하고 
   - 아두이노 레오나르도의 경우 8, 9, 10, 11, 14, 15, 16번 핀을 소프트웨어 통신 핀으로 사용 할 수 있어요.

반응형
반응형

 아래는 재충전이 가능한 리튬이온 배터리와 일반 건전지의 사이즈 비교 입니다.

Rasino IoT 배터리 비교

원통형 리튬이온 배터리는 공칭 전압이 3.7v인 배터리가 주를 이루고 있습니다
(
그외 리튬전지의 경우 공칭전압이 3.6v~3.8v사이 제품이 판매되어 나오고는 있으나 보호회로가 없는 원통형 리튬이온 배터리의 거의 대부분은 3.7v 제품이라고 보시면 됩니다.
아래는 배터리 속에 포함된 배터리 보호 회로의 모습입니다.



공칭전압이란?  충전 및 방전 상황에 따라 전압이 변하는 경우에 정해놓은 대표전압 또는 기준전압을 말합니다. 배터리의 경우 공칭전압은 보통 만충전압과 방전 중지 전압의 대략적인 중간 값으로 정합니다.
 
18650 리튬이온 배터리의 경우 만충전압이 4.2v 이며, 중지 전압은 3.0v 정도 입니다.(제조사에 따라 0.1~0.2v 차이가 있음).
만약, 3.0v 이하로 지속적으로 방전을 시킬 경우, 2.5v 정도까지 방전 되면 더 이상 재충전이 불가한 상태가 됩니다.  따라서 배터리 보호회로는 과충전 방지와 과방전 방지 기능을 넣은 것으로서, 과방전 방지 기능을 통해 3.0v이하로 전압이 떨어지면 자동으로 출력을 차단하는 기능입니다.  과충전의 경우 4.2v 만충전압을 넘어 지속적으로 충전이 되면 폭발할 위험성이 있습니다.   또한 +, - 두 극을 합선 시킬 시 역시 불꽃이 튀면서 화재 및 폭발의 위험성이 있으니 리튬이온 배터리의 경우 꼭 사용상의 주의가 필요합니다.
또한, 과충전보호회로가 달린 배터리라 하더라도, 확률은 크지 않지만 보호회로가 망가지거나 불량이 될 경우, 화재의 위험성이 있으므로, 장시간 자리를 비운 상태에서는 충전을 삼가는 것이 좋습니다.

이미지 : [대전시 소방본부 제공=연합뉴스]

 리튬이온 배터리의 보관은 직사광선을 피하고, 습기 없는 곳에서 사용과 보관하여야 하며, 여름철 차량내 방치 금지이며, 장시간 보관 시 80%수준 충전된상태(공칭전압의 조금 상회하는 정도)로 충전하여 보관하는 것이 좋으며 약 3개월 정도마다 한 번씩은 충전해주면 오래 사용할 수 있습니다.

 
리튬이온배터리는 메모리 효과가 없는 배터리 이므로 절대 완전 방전까지 사용하지 말고 그때 그때 충전해 주는 것이 좋습니다.( 메모리 효과 : 니켈 계열 배터리의 경우 충전된 전기를 모두 소진하기 전에 다시 충전하게 되면 다 사용하지 못한 지점으로 용량의 한계를 기억해 버리는 현상을 말하며, 이런 유형의 배터리는 <완전충전
완전방전> 형태로 사용하는 것이 좋습니다)

이미지 출처 : Devicemart.co.kr



 
배터리의 폐기는 절대 구멍을 내어 버리는 것은 금물이며 배터리를 소진 시킨 후 소금물에 담그거나 하여 완전 방전을 시켜, 반드시 배터리 전용 수거함으로 배출시켜야 합니다.

배터리의 이름인 18650의 이름은 : 직경mm + 높이mm + 0(원통형)을 나열한 것으로 18650이라는 이름으로 하여금 이 배터리는 '직경18mm, 높이 65mm, 원통형'의 배터리라는 것을 알 수 있습니다.

Rasino ioT , 18650 / 18350 사이즈 비교

이 외에 다양한 사이즈의 배터리가 아래 그림처럼 존재합니다.

이미지 : www.alibaba.com

 

반응형
반응형

( ※ 본 게시글의 모든 이미지는 클릭하면 자세히 볼 수 있도록 확대됩니다!)

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 현재 Blynk 서비스가 2.0 으로 바뀌었습니다.  Blynk서비스가 포화됨에 따라, 기존 서비스는 새로운 회원가입(로그인)이 안됩니다.  따라서 2.0 버전으로 새로 가입을 하고 사용해야 합니다,  다만 Blynk 사용법이 다소 상이합니다. 따라서 하드웨어 활용법 등의 방법을 참고하거나 응용해보시면 됩니다. 
 만약, 기존 Blynk에 로그인 되시는 분은 이 게시글 그대로 제작 및 작업이 가능합니다. 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

 


# ESP-01 + 아두이노 나노 + Blynk의 최적의 갓성비 조합을 이용해서 스마트폰 WiFi를 통한 IoT 제어 장치를 만들어 보는 학습 시리즈를 준비했습니다. ESP8266 중 베스트 모듈인 esp-01 모듈의 기본 사용법(펌웨어 업뎃 포함)과 어려운 앱 코딩이 전혀 필요 없는 Blynk 앱 사용법을 포함하였습니다.


【 아두이노Proj#14
】 ESP8266 esp-01 + Blynk + 아두이노 Nano 스마트폰 제어 풀코스

 

ESP8266 SoC 칩셋


: ESP8266은 상하이에 본사를 둔 에스프레시프 시스템즈(Espressif SystemS)사에서 개발한 와이파이 통신 기능을 포함한 마이크로 컨트롤러(
또는 SoC - System On Chip라 불려짐)입니다.   2014년 첫 선을 보인 이래로 현재까지 wifi통신 모듈 시장을 평정한 것으로 평가되고 있는 만큼 인기가 높습니다.
이 칩셋을 가지고 Ai-Thinker라는 회사에서 아두이노 보드처럼 코드를 올리고 혼자 동작이 가능하도록 플래시 메모리 등을 탑재한 첫 보드가 바로 ESP-01 모듈입니다. 

ESP8266 칩셋을 활용하여 만든 ESP-01 보드(ESP8266칩 옆의 검은색 칩이 메모리임)


  이는 여러 가지 시리즈로 제작되었는데,  ESP-01 , ESP-02, ...  ESP-12, ESP-13, ESP-14, ESP...  모듈까지 플래시 메모리와 제어 포트 증가 등 성능을 향상해 출시하였습니다.  현재는 저렴한 비용과 저전력, 순수한 WiFi 기능의 단순한 동작을 요구하는 곳에는 ESP-01 보드가 많이 사용되고 있고,  좀 더 고성능과 확장성이 요구되는 곳에는 ESP012 모듈(ESP-12, ESP-12E, ESP12F)이 가장 많이 애용되고 있다고 볼 수 있습니다.  
즉, ESP8266-01~14 보드 시리즈는 단순한 wifi 어댑터 역할뿐 아니라, 아두이노 보드 없이 아두이노처럼 프로그램을 올려 독자적으로 동작 가능한 보드인데요, 
"아두이노+wifi 실드"를 저렴하고 작고 심플하게 합쳐 놓은 것과 같은 기능으로 인해 인기가 매우 높다고 보시면 됩니다.  
그래서, IoT 사물인터넷 시스템 구축과 같은 하드웨어 적인 부분을 생각하신다면, 꼭 활용해 보시길 권해드립니다. 

〔 일러두기 〕
 먼저, 여러분들이 본격적으로(?) esp8266을 접하기 전에, 여담으로 한 말씀드릴게요. 
우선, esp8266은 이미 접해본 분들은 아시겠지만,  esp8266, 특히 esp-01 모듈을 막연히 시작하려고 하는 그 순간부터 이른바 지옥문이 열리는 경험을 하시게 됩니다.  마치, 동네 뒷산 오르듯 가벼운 옷차림으로 나섰다가, 반지의 제왕에서나 나올법한 험난한 반지원정대에 참여하게 되었다는 사실을 뒤늦게 깨닫게 됩니다.  >,.< 
대충 정리하고 빠져나오려 해도 이미 늪에 들어와 있는 상황이어서 빠져나오기도 쉽지 않음을 느끼실 겁니다.
 esp8266 관련하여 자료들이 많이 있지만,  오히려 수많은 자료의 홍수로 인해 개념을 정확히 잡아가며 이해하기가 쉽지 않습니다.
 그래서 제안을 드리면, 초반에 너무, 한 번에 모두 이해하려는 마음을 조금 비우시고, esp8266에 시간을 넉넉하게 투입할 수도 있다는 생각으로 접근하신다면, 의외의 큰 스트레스로 인해 중도에 포기하시는 일은 없으시리라 생각됩니다. 
당연히 이런 초반의 어려움을 쉽게 극복할 수 있도록 이번 게시물과 영상 제작 시 중점을 두어 만들었습니다.
 (사실. esp-01 모듈보다 nodeMCU나 esp-32 같은 상위 레벨의 고급 모듈이 오히려 사용하기는 더 쉽습니다
  다시 말해서, esp-01 모듈을 다룰 수 있으면 상위 모듈은 자료만 조금 살펴보면 그냥 하실 수 있습니다 ^^& ) 

 그래서 본, 게시글은 삽질에 가까운 비슷한 실험을 수십 차례 반복하면서 알게 된 사실들을 정리하고 난해했던 개념 몇 가지를 정리해 올립니다.
 이번 게시글과 실습 영상을 제작하는데 참, 많은 시간이 걸려 힘들었지만, 아무쪼록 험난한 반지원정대 길에, 간달프 역할은 못해도, 조금의 도움이라도 되었으면 하는 바람입니다.^^;;



《 esp-01 스펙 spec. 》

Module Espressif ESP8266
ESP8266 Version ESP-01
동작 명령 방식 UART AT Command
안테나 On-Board Ceramic Antenna
통신 방식 802.11 b/g/n 지원
통신 속도(Baud Rate) -115200(디폴트) : 생산된 모듈 펌웨어에 따라 9600(디폴트)도 있음
-소프트웨어-시리얼: ~ 57600bps이하, 이상은 지원X, 불안정
-하드웨어-시리얼 : 9600bps~2000000bps
Flash memory 512KB  ,   ESP-01S 모듈은 (1MB)
프로세서 스피드 80-160Mhz
크기(Size) 14.5 x 24.8 mm

 

《 esp8266 WiFi 모드  》
  : esp8266의 'AP모드'와 '스테이션(Station) 모드'의 개념

 쉽게 설명하자면, A.P(액세스 포인트)는  다른 기기들이 네트워크에 접속할 수 있도록 wifi 무선 접속 환경을 제공하는 기기(wifi 공유기)를 말하며, 스테이션은 wifi 공유기에 접속을 하려는 기기를 말합니다.

A.P (Access Point)

 esp8266이 네트워크(인터넷)에 연결하기 위해서는 AP(Access Point)가 필요하며, AP는 무선 연결(wifi)을 사용하여 네트워크에 연결하기 위한 접점(Access Point)으로 이해할 수 있습니다.  AP는 다른 말로 무선공유기라 불리며,  일반 가정에서는 라우터와 결합된 무선공유기(AP)를 이용해 노트북과 스마트폰 등에서 무선 인터넷을 사용하게 됩니다.  
이때, 노트북이나 스마트폰은 단말(기) 또는 스테이션(Station-STA)이라 부릅니다.  
 그리고 스마트폰(스테이션)은 무선공유기로부터 DHCP(동적 IP 할당) 형태로 사설 IP(내부 네트워크 전용 IP)를 할당받아 무선 네트워크에 접속이 가능해지고, 라우터 기능을 가진 공유기(일반적인 A.P 공유기)를 거처 외부의 다른 네트워크 또는 인터넷을 이용할 수 있게 됩니다.
 ESP8266 모듈은 wifi 네트워크(AP 공유기)에 접속(참여)하는 '1. 스테이션 모드'로 동작할 수 있고,  스테이션들의 접속을 받아들여 네트워크를 만들어 주는 '2. AP 모드'로 동작시킬 수 있습니다.  (esp8266이 2번 AP 모드 일 때는 외부 네트워크와의 연결은 전혀 할 수 없습니다- 즉 내부 네트워크만 형성할 수 있습니다)
 또한 esp8266 모듈을 '3. AP모드와+스테이션의 복합 모드'로 설정이 가능한데, 일반적인 A.P 공유기와는 조금 다른 제한적인 기능으로 작동되며, 차이점은 아래 내용과 이미지를 참고해 주세요. 

 위의 이미지와 같은 일반적인 전용 AP 공유기의 경우 내부 IP주소뿐 아니라, 공인 IP주소를 가지고 있는데, 스테이션의 연결을 받아주면서 스테이션들이 직접 인터넷과 같은 외부 네트워크에 연결하도록 지원을 합니다. 
 하지만, 이런 스테이션들의 직접적인 외부 네트워크(인터넷) 연결을 지원하지 못하고,  A.P 자신만 직접적으로 외부 네트워크(인터넷) 연결이 가능한 AP를 소프트 AP(Soft AP)라고 합니다.
 이것이 전용 AP 공유기와 esp8266이 3.AP모드+스테이션 복합 모드로 동작할 때와의 차이점입니다.   
그리고 위에서 말한 일반적인 AP(Access Point) 공유기는 무선 WiFi 네트워크 지원과 함께 유선 네트워크를 함께 지원하는데, esp8266은 유선 인터페이스를 지원하지 않기 때문에, 그래서 유사한 기능만 지원한다는 의미로, 소프트 AP라고 불리기도 합니다. 

 정리하면, esp8266은 3가지 모드로 설정하여 사용할 수 있는데, 1. 스테이션 모드와,  2. AP모드, 3. 스테이션+소프트 AP모드의 3가지 형태중 하나로 선택하여 사용할 수 있습니다. 
이 3가지 모드의 핵심적인 특징을 아래 이미지로 표현했으니 참고해 보세요. 
(이미지에 표시되는 IP 숫자는 예시로 든 것입니다.)


『 1. ESP8266 스테이션 모드 접속 』

ESP8266(esp-01)의 스테이션 모드 접속

esp8266은 스마트폰이나 노트북이 wifi A.P에 접속하듯 , 인터넷을 이용하기 위한 하나의 스테이션으로서 접속 가능합니다.  esp8266이 전용 wifiA.P로부터 I.P(사설)를 할당받아 하나의 스테이션으로 A.P에 접속하고 A.P를 통한 외부 네트워크(인터넷)에 접속할 수 있습니다.   그리고, 동일한 내부 네트워크에 연결된 다른 스테이션과의 접속이 가능합니다. 

 

『 2. ESP8266 소프트 A.P 모드 접속 』

ESP8266(esp-01)의 소프트 A.P 모드 접속

ESP8266은 소프트 A.P 모드로 동작시킬 수 있습니다.   이때, esp8266은 A.P로서 자신에게 접속한 스테이션들에게 사설 IP를 할당해주며 접속할 수 있도록 합니다.  또한 자신(A.P)에게 접속된(동일 네트워크 형성) 다른 스테이션 간의 통신(접속)도 가능하도록 합니다. 

 

『 3. ESP8266 소프트 A.P 와 스테이션 복합 모드 접속 』

ESP8266은 소프트 A.P와 스테이션의 복합 모드로 사용하도록 설정할 수 있습니다. 
작동 범위는 아래 이미지의 형태로 됩니다. 

ESP8266(esp-01)의 소프트 A.P + 스테이션 복합 모드 접속

ESP8266이 '3. 소프트 AP+스테이션 복합모드'일 때는 다른 스테이션들을 접속시켜 내부 네트워크를 형성할 수 있으며, 스테이션 간 통신이 가능하고 스테이션들이 소프트 A.P(esp8266)에 접속(통신)이 가능합니다.   다만, 소프트 A.P(esp8266)인 esp8266만 외부 네트워크에 접속이 가능하고, esp8266(소프트 A.P) 하단의 스테이션들은 esp8266을 통과하여 외부 네트워크에 접속은 불가합니다. 

 

ESP8266의 가장 기본 모델인 ESP-01 모듈의 실습을 진행합니다. 】

《  ESP-01의 사용법 》
기본적으로, ESP8266 모듈은 크게 두 가지 형태로 작동시킬 수 있습니다. 
 아두이노와 같은 마이크로 프로세서 보드에 연결시켜 wifi 기능을 해주는 어댑터로써의 역할이 가능합니다. 
② 마치 아두이노를 사용하는 것처럼 ESP8266 모듈의 플래시 메모리에 코드를 올리고 동작시키는 컨트롤러 보드 형태로 사용 가능합니다. (물론 wifi기능도 사용 가능),  단, ESP-01 모듈의 경우 일반적인 아두이노 보드에 비해 코드를 올릴 수 있는 메모리 용량이 적으며, 활용 가능한 입출력 포트가 최대 2개뿐으로 확장성은 떨어지지만, 프로젝트를 구현할 때 사이즈가 작아지고 제어할 포트 수가 적은 곳에는 활용하기 좋습니다. 

《 ESP-01의 통신 방법 》
- esp-01 모듈은 PC와 연결하여 코드를 올리려고 할 때 UART라는 통신방식을 사용하며,  ①번과 같이 wifi 어댑터기로서의 동작을 위해서도 아두이노 같은 장치와의 연결에 UART라는 통신 방식을 사용합니다. 
UART(Universal asynchronous receiver/transmitter)는 비동기 시리얼통신을 뜻하며 병렬 데이터의 형태를 직렬(시리얼) 방식으로 전환하여 전송하는 통신방법으로, 병렬 통신에 비해 적은 수의 케이블로 다소 긴 거리에도 에러 없이(보정)  통신이 가능한 장점이 있습니다. 
  PC와 ↔ 폰,  PC와 ↔ 아두이노 사이에 사용되는 USB 케이블 통신이 대표적입니다.  그리고 esp-01 모듈과도 이런 UART 방식의 시리얼 통신을 이용합니다. 

UART(Universal asynchronous receiver&amp;amp;amp;amp;transmitter) : 비동기 시리얼통신


 아두이노와 esp-01 보드 양쪽의 송신단(Tx)과 수신단(Rx)을 서로 크로스하여 두 줄의 케이블로 서로 연결하여 시리얼 형태(직렬 통신)로 데이터를 주고받게 됩니다.  그리고 이런 UART 통신 방식은 아두이노를 사용하지 않고 직접 PC와 연결하여 esp-01 보드에 펌웨어를 업로드하려고 할 때도 사용되는데,  이때 PC의 인터페이스는 USB이기 때문에,  USB↔UART 변환 장치(보드)가 필요합니다.   보통 USB to UART 또는 USB to TTL 시리얼 어댑터 보드라고 불리는데 대표적으로 FTDI칩을 사용한 보드나,  CP2102 칩을 사용한 보드가 있습니다.  여기서는 테스트 결과 펌웨어 업뎃이 좀 더 잘 되는 CP2102 보드 모듈을 이용합니다.

USB to UART 변환을 위한 대표적 모듈 2가지

 

《 ESP8266 모듈 시리즈의 프로그래밍 방법 》
 ① ESP8266 SDK 사용 :  이클립스 개발환경(Eclipse)과 C/C++ 언어를 사용하여 프로그래밍함.
 ② AT 명령어 사용  :   AT 명령어 펌웨어를 설치하여 AT-Command로 프로그래밍(설정) 함.
 ③ NodeMCU와 루아 스크립트 사용 : NodeMCU 펌웨어를 설치하여 루아(Lua) 스크립트를 사용하여 프로그래밍함.
 ④ 아두이노 IDE 사용 : ESP8266 보드를 아두이노 보드의 한 종류로 인식시켜 아두이노식 C/C++로 프로그래밍함.

 위 ①~④의 방법 중에서 esp-01 모듈을 가장 손쉽고 간편하게 사용할 수 있는 아두이노 IDE를 사용한 방법으로 진행합니다.

《 ESP-01 모듈 펌웨어 업뎃(교체)을 하는 이유 》
 
1. 펌웨어 업뎃(교체)을 하는 이유?
 - 펌웨어 업데이트를 해야 하는 이유는 몇 가지가 있습니다. 
시리얼 통신에서 데이터의 전송 속도를 나타낼 때 보-레이트(Baud Rate)라는 것을 사용합니다.
보-레이트의 속도 값을 나타내는 단위로는 bps(Bit per second)라 하여, 1초 동안 전송할 수 있는 비트(bit)의 수를 의미합니다.   bps 속도는 보통 아래와 같은 값으로 약속하여 구분해 놓았고, 이 속도 중 하나로 선택하여 통신하게 됩니다. 
1200bps, 2400bps, 4800bps, 9600bps, 19200bps, 38400bps, 57600bps, 74880bps, 115200bps,
 230400bps, 250000bps, 500000bps, 1000000bps, 2000000bps
이때, 통신하는 기기는 서로 같은 속도로 설정을 해야 데어터를 정확하게 주고받을 수 있게 됩니다. 
 즉, PC와 ESP-01 모듈의 보-레이트 설정이 서로 같아야 하고, 아두이노와 ESP-01 모듈의 보-레이트 설정이 동일해야 제대로 통신이 된다는 이야기입니다. 

기기간에 보-레이트 설정이 서로 일치해야 제대로 통신이 이루어집니다


 그런데, esp-01은 생산되는 모듈의 제조시기나 업체(카피 제품 등)에 따라 내장된 펌웨어가 다르고, 펌웨어에 설정된 디폴트 보-레이트(Baud Rate)를 보통은 바로 알기 어렵습니다.
 따라서 알고 있는(원하는) 속도의 펌웨어로 교체하기 위함이 있습니다. 
 그리고 esp8266은 AI-Thinker사의 AT-커맨드, 즉 명령어 기반의 AT 명령어를 수신하고 해당 명령어를 실행할 수 있는데, 이를 사용하기 위한 버전의 펌웨어로 업데이트(교체) 하게 됩니다.
 AT-명령(커맨드) 펌웨어는 여러 가지 시리얼 통신프로그램이나 아두이노 IDE의 시리얼 모니터를 통해서 사용할 수 있으며,  문자열 기반의 AT통신 명령어를 사용하여 esp-01 모듈의 설정을 바꾸거나 하는 등의 명령을 보내어 실행(통신)시킬 수 있게 됩니다. 

허큘리스를 이용해서 AT-커맨드로 시리얼통신을 하고 있음

《 ↓↓ 허큘리스 통신프로그램 다운로드 ↓↓ 》

hercules_3-2-8.exe
1.24MB
아두이노 IDE의 시리얼 모니터를 통해 AT명령어로 통신하고 있음



 그리고 아울러 하드웨어 시리얼 통신 단자가 하나뿐인 아두이노 우노(나노)를 PC와 같이 사용하기 위해서는 펌웨어 업데이트(esp통신속도를 9600 bps로 낮춤)가 필요하기도 합니다. 
(PC ↔ 아두이노 우노 ↔ esp-01 )

우노(나노)에서 하드웨어시리얼 통신과 소프트시리얼 통신을 동시에 사용하기 위한 펌웨어 업뎃(교체)


 본 실습에서는 최신 버전 펌웨어로 업뎃을 하는 것은 아닙니다. 실습을 진행하는데 문제가 없는 실행이 잘 되는 버전으로 펌웨어 교체를 하는 것이며, 가지고 있는 다른 버전의 펌웨어로 교체해도 되지만, 보-레이트가 맞지 않거나 할 경우 등, 실습에 문제가 있을 수 있으므로, 여기서 제공하는 펌웨어로 실습을 진행해 보고 , 필요하다면 가지고 있는 다른 버전으로도 직접 테스트를 해보세요.

 
 주의사항은, 판매되고 있는 esp-01 모듈들이 겉모습은 같아 보여도 펌웨어 버전이나,  flash메모리 용량 및 일부 성능이 다를 수 있습니다.(따라서 가격 차이가 조금 있으며, ESP-01 기본 버전은 플래시 메모리 용량이 512KB이지만, ESP-01S 버전이라고 불리는 모듈은 2MB입니다. 겉모습은 거의 차이 없어 보임).
  기본적으로는 판매되는 esp-01 기본 모델을 사서 여기서 안내하는 펌웨어로 업뎃하면 실습을 진행하는데 크게 문제는 없습니다. (단, 흔하지는 않지만, 초기 불량이나 작업 과정에서의 손상이 생길 수 있기에 esp-01 모듈을 최소 2개 이상, 여유 있게 준비하면 좋을 것 같네요)

 그런데 ESP-01 모듈의 펌웨어 업뎃을 반드시 해야 하는 건 아닙니다. 
 구매 모듈마다 다른 것 같은데요, 대개의 경우 구매한 모듈은 보통 ESP-01 모듈의 기본 펌웨어가 AT-커맨드(명령어)로 바로 통신이 되지 않는 펌웨어인 경우가 많은 것 같습니다.  이런 이유로 펌웨어를 바꾸게 되며,  AT-커맨드 펌웨어 버전이나 종류에 따라 AT통신 명령어 지원 가짓수도 조금씩 다릅니다. 
따라서, 작성하려는 코드와 통신속도가 일치하거나 하여, 디폴트 펌웨어 버전에 따라 필요 없을 수 있으며, 또한 esp8266을 wifi 어뎁터가 아니라 플래시 메모리에 아두이노처럼 코드를 올려 사용하고자 할 경우에는 펌웨어 업뎃 없이 바로 사용할 수 있습니다.

 다만, 본 실습의 원활한 진행을 위해서는 안내해 드리는 펌웨어 버전으로 업뎃을 해주세요.

 

▣ "ESP8266(esp-01) 활용하기 풀코스" 실습 진행 순서

실습 진행 순서

 
1. 실습 준비 :  ① 실습 재료 준비    ② ESP-01 Adapter 및 주요 부품 소개
2. 펌웨어 업뎃  : ESP-01 모듈의 펌웨어 업뎃 ( 방법 ① 아두이노 나노보드 이용 / 방법 ② CP2102 USBtoTTL 이용)
3. Blynk 소개 & App 설치 (이후, 실습부터는 Blynk 앱을 설치한 스마트폰에서 wifi통신으로 제어하게 됩니다)
4. 《 하드웨어 제어 실습 with WiFi 》 
   - (실습 1) LED ON/OFF 제어하기
   - (실습 2) 파워 TR을 이용한 미니 드론 모터 구동

   - (실습 2) L9110S 모터 드라이버 모듈 이용한 DC 모터 구동
   - (실습 3) 서보모터 구동 (실습 3-1) 서보모터 1개 각도 제어 / (실습 3-2) 서보모터 2개 구동하여 틸트 브래킷 제어) 
   - (실습 4) 릴레이 사용하여 220V 전등(전기제품) ON/ OFF 제어
   - (실습 5) 온습도 센서 값 실시간으로 스마트폰에 표시하기(Blynk App 사용)

==========================================================================
==========================================================================

 

【 1-1. 실습 재료 및 준비 】

※ 실습을 위한 재료 준비 (특정 부품은 여유 있게 준비하면 실습에 도움이 됩니다)   
 1. 아두이노 우노(나노) 1개
 2. ESP-01 1개 (최소 2개 이상 권장 : 실습 시 모듈 손상 및 불량 대비와 활용성 측면) 
 3. ESP-01 breakout 소켓 1개 (최소 2개 이상 권장 : 모듈 불량 대비)
 4. USB to TTL 어댑터 (CP2102 모듈) 1개
 5. ESP-01 전용 4핀 어댑터 1개
 6. 소형 DC 모터(5V 이하 규격) 1개
 7. 미니 드론 모터와 프롭(5V 이하 규격) 1개
 8. L9110S 모터 드라이버 모듈 (또는 L298N 모듈 : 게시글과 영상에서는 L9110S로 설명드립니다)
 9. LED 2개 , 저항 2개 (200Ω ~ 330Ω 사이 값 아무거나 가능)
 10. 서보모터 (SG90 또는 유사 모터) 2개
 11. 미니(170홀) 또는 소형(400홀) 브레드보드 여러 개 : 여기서는 미니 보드 5~7개를 사용하여 설명드립니다
 12.  '1 채널 릴레이 모듈' (릴레이 동작전압 DC 5V / 제어 가능 전력 : 250 ACV, 30 DCV, 10A까지 )
 13.  220V용 전구(LED 전구도 가능)와 소켓
 14.  220V(돼지코) 플러그와 전원선 (플러그 전원선 일체형도 가능)  : 2가닥 일반선, 접지선 포함된 3가닥 가능
 15.  브레드 보드 연결용 점퍼선  
 16. 스마트폰 (안드로이드 계열 / IOS 계열 모두 가능)

부품명   부품 실물 부품 설명
1. 아두이노 우노 또는 나노 1개

아두이노 우노 또는 나노 보드
2. ESP-01   1개 이상
실습시 모듈 손상 및 불량 대비와
활용성 측면에서 여유 있는 수량 권장
3. ESP-01 breakout 소켓  1개 이상

모듈 불량 대비 최소 2개 준비 권장
(흔한 경우는 아니지만 간혹, PCB 기판 연결 불량이 있을 수 있음)
4. USB to TTL 어댑터 (CP2102 모듈) 1개

CP2102칩셋을 사용한 USB to TTL 전용 어댑터
5. ESP-01 전용 4핀 어댑터 1개
ESP-01 전용 Adapter(어댑터), 
VCC, GND, Rx, Tx 4개의 핀과 3.3V 전원 레귤레이팅 회로가 포함되어 5V 전원을 그대로 사용 가능한 간편 어댑터
6. 소형 DC 모터(5V 이하 규격) 1개
미니 카, 및 소형 장난감 등에 많이 사용되는
5V 이하 규격의 소형 DC 모터 준비
7. 미니 드론 모터와 프롭 1개
동작 전원 5V 이하 규격의 미니 드론 모터와 여기에 맞는 프로펠러 1셋
8. L9110S 모터 드라이버 모듈 1개
또는 L298N 모듈을 사용해도 됨
단, 여기서는 L9110S로 설명드립니다
9. LED 2개 , 저항 2개 

- LED 색상 관계 없음
- 저항값은 200Ω ~ 330Ω 사잇 값 어떤 값이든 됩니다.
- 저항값이 낮으면 LED가 밝아지며, 저항값이 높으면 LED가 어두워짐 (단, 너무 낮으면 LED 손상될 수 있으며, 너무 높으면 LED가 켜지지 않음)
10. 서보모터 (SG90또는 유사 모터) 2개
MG90, E-Max, MG945 등 가지고 있는 서보 모터 활용 가능 (이번 실습에서 회전 각도는 상관 없음)
11. 미니(170홀) 또는 소형(400홀) 브레드보드
미니 브레드보드는 측면 홈과 홀더를 이용하여 블럭조립하듯 가볍게 이어 붙일 수 있음
- 170홀 미니 보드 최소 5~6개 이상 준비하거나,
- 400홀 소형 보드는 최소 2개 이상 준비
12.  '1채널 릴레이 모듈'  1개
5V의 신호레벨로 220V 용 전원 기기의 On/Off 스위치 역할로 사용합니다. 
- 1ch(채널)은 선 하나를 제어할 수 있으며,
- 2ch은 전원선 선 두개를 제어할 수 있음
 (2ch 모듈로 채널 하나만 사용해도 됨)
13.  220V용 전구(LED전구도 가능)와
소켓(리셉터클-receptacle)  각 1개

- 전구(램프)는 교류 220V용 (일반 소켓사이즈용)
  LED 전구도 가능
- 소켓(리셉터클)은 소형이 아닌 일반소켓사이즈
  ( 일반적인 규격 : 6A , 220V AC )
14.  220V(돼지코) 플러그와 전원선 1개

 아래, 두 가지 형태 중에 하나만 준비

- 220V용 플러그와 별도의 전원선 : 선과 플러그가 따로 있는 형태로 캡을 열고 선을 넣어 나사를 조여 조립(연결) 하는 타입.
  (접지 없는 2가닥 또는 접지선 포함된 3가닥 케이블 모두 가능)  

- 플러그와 전원선이 결합된 일체형 전원 케이블
  (접지 없는 2가닥 또는 접지선 포함된 3가닥 케이블 모두 가능)
15.  브레드 보드 연결용 점퍼선
브레드 보드에서의 부품 연결용
16. 스마트폰
안드로이드 계열 또는 IOS 계열(아이폰) 모두 가능 (Blynk 앱 설치와 작동을 위해 사용됨)


【 1-2.  주요 모듈 소개 】


  ① esp-01 모듈용 breakout 소켓 

 esp01 모듈 전용 breakout 소켓을 구매하면 위 이미지처럼, 핀이 결합되어 있지 않기 때문에, 납땜을 위한 인두기와 실납이 필요할 수 있으니 참고하세요.   breakout 소켓이 없어도 됩니다. 하지만 점퍼 케이블로 일일이 연결해야 하기에 깔끔한 회로 조립을 원하시면 breakout 소켓을 사용해보세요. 아래처럼 브레드보드에 장착되어 연결이 편리합니다.

 (주의~!  위 이미지를 참고하여 esp8266을 꽂는 방향에 주의해 주세요. 반대로 돌려 꽂지 마세요)

 

 ② esp-01  adapter(어댑터)


 esp-01 어댑터는 이미 펌웨어 업뎃이 완료 되었거나 업뎃이 필요 없는 esp-01 모듈을, 시리얼 통신 핀과 전원 핀만 간편히 사용할 수 있도록 만들어진 어댑터입니다.  
 esp-01 모듈은 3.3V의 전원과 신호 레벨로 동작되는 모듈이기에, 아두이노에서 기본적으로 사용되는 5V 전원이나 TX의 신호 레벨(5V)은 esp-01 모듈을 손상시킬 수 있습니다.  그런데, 어댑터에는 5V를 → 3.3V로 레귤레이팅 시켜주는 부품이 함께 구성되어 있어, 별다른 부가 회로 없이, esp-01 모듈을 4개의 핀으로 사용할 수 있는 편리한 모듈입니다. ( 만약, 이 모듈을 갖고 있지 않다면,  1㏀ 등으로 1대 2의 저항 분배를 하거나, 다른 부품을 사용하여 연결해서 사용하면 됩니다 )

ESP-01 어댑터 핀아웃(Adapter Pinout)
ESP-01 모듈을 장착한 모습 ( 장착 방향에 주의~! )


 ③ L9110S 모터 드라이버 모듈


 모터의 경우 일반적으로 직접 전압(전력)을 넣어 돌리려 할 경우, 공급 전력이 상대적으로 커야 하는데,  만약, 조금이라도 큰 모터를 사용하거나 부하가 걸려있는 모터를 돌리려고 할 경우  아두이노 포트에서 나오는 약 40mA 출력만으로는 돌리기가 버겁습니다. 

L298N 과 L9110S ic들 모두 모터드라이버 모듈에 들어가는 핵심IC들 입니다


 따라서 위 이미지에서 처럼  L298N과 같은 H브릿지 IC 같은 것을 사용하여 회로를 구성해주어야 아두이노의 포트 출력 신호로 정회전이나 역회전과 같은 제어가 가능한데,  이런 목적과 기능들을 하나의 모듈로 만들어 놓은 것이 바로,  L298N 모듈(L298 IC칩 사용)이며,  이 보다 용량과 사이즈를 줄인 모듈이 아래 이미지에 있는 L9110S 모듈(L9110S IC칩 사용)입니다. 

L9110S 모터 드라이버 모듈
L9110S 스팩

위 이미지를 보면, DC 모터는 A와 B 두 개까지 사용(제어) 가능하며, 이 번 실습에서는,  채널A 혹은 채널 B 한쪽만 사용하면 됩니다. 

 

④ 1 채널 릴레이 모듈

실습에 사용된 1채널 릴레이 모듈

 릴레이는 보통 DC 5V~12V 정도의 낮은 전압으로 동작되는 회로에서,  교류 220V와 같은 높은 전압의 회로를 On/Off 시킬 수 있는 전자식 스위치 역할을 해주는 장치입니다. 
  릴레이의 내부에 코일이 있고, 여기에 5V의 작은 전원만 넣어 주면, 전자석 형태의 코일이 작동되어, 코일에 영향을 받은 철핀이 당겨져  NC에 연결되어 있던 핀이 휘어져서 NO핀으로 연결되는 원리로 작동합니다.
그리고 코일의 전류가 사라지면, 다시 철핀의 탄성으로 인해 원래의 NC위치로 돌아가게(연결) 됩니다

전자석 형태의 코일에 전압이 가해지면, NC에 붙어 있던 핀이 NO쪽으로 당겨져 연결 됩니다, 그리고 코일의 전류가 사라지면, 다시 철핀의 탄성으로 원래의 NC위치로 돌아가게 됩니다
Bulb(전구) 같은 220V 전기가 흐르는 라인에 연결하여 On /Off 시킬 수 있습니다

☞ 릴레이 핀 용어 정리 :   
- NO (Normally Open) : 평상시 연결되어 있지 않은 열린(Open) 상태
- NC (Normally Closed) : 평상시 연결(Connect) 되어 있는 상태
- COM (Common) : 공통 단자(핀)

 
릴레이 사용법 (Rasino)
 - 릴레이는 코일에 전류를 흘려 코일의 유도 작용에 의해 접점을 On / Off 해주는 스위치입니다
 - 이를 이용하면, 낮은 전압(예, 5V)으로 220V의 전원을 끊거나 연결시킬 수 있습니다.
 - 좌측 IN에 HIGH(또는 LOW) 신호가 가해지면 Com단자와 NO 단자가 연결되어 스위치 형태로 작동됩니다.
    《 릴레이 핀 용어 정리 》
     - NO (Normally Open) : 평상시 연결되어 있지 않은 열린(Open) 상태
     - NC (Normally Closed) : 평상시 연결(Connect) 되어 있는 상태
     - COM (Common) : 공통 단자(핀)

  - NC단자와 Com 단자가 디폴트로 연결 되어 있고, 릴레이가 동작이 되면 이 연결이 끊어지고,
    Com단자가 NO단자와 연결이 됩니다. 이 부분을 전기제품이나 콘센트의 한쪽 부분의 연결을 끊어 
    스위치 형태로 구성할 수 있습니다.

 

《 1채널 릴레이 》 기본 스팩 
1. 입력 컨트롤 전압 - 동작 전원 5V 필요
- 5V레벨의 High/Low 제어 신호
2. 컨트롤 가능한 전원 최대
- 30V, 10A의 DC 전원을 제어하거나
- 250V의 10A의 AC 전원을 제어할 수 있음

3.  ※ 주의 사항 - 컨트롤 전원이 클 경우 충분히 결딜 수 있는 굵기의 전선 사용 할 것. (220V 라인에 얇은 점퍼선 같은 것을 연결할 경우 전선이 100% 녹아 내립니다)
- 220V 라인 쪽은 감전에 유의하고, 피복이 벗겨진 곳이 드러나지 않도록 마감처리를 깔끔하게 하세요

릴레이 모듈을 위에서 바라본 모습

릴레이를 보면 점퍼를 연결할 수 있는 3개의 핀이 보이는데요, VCC-GND에 5V의 직류 전원을 넣어 주고, 
IN핀으로 아두이노에서 제어할 포트와 연결해 주면 됩니다.  
 그리고 220V 회로 혹은 전원선 중 한 선의 중간 부분을 잘라서,  잘린 한쪽을 COM단자에 연결하고(COM은 반드시 사용)하고, 잘린 나머지 한쪽을 NO 단자 또는 NC 단자 중 하나를 선택해서 연결하면 됩니다. 
(처음에는 떨어 뜨려 놓다가 제어 신호가 들어오면 연결시킬 것이냐?,  아니면 처음부터 연결시켜 놓다가, 제어 신호가 들어오면 떨어뜨릴 것이냐?를 생각해서 결정합니다.)

다만, 릴레이 하단에 보면, 똑같은 스펙의 릴레이라도, 제어 신호가 High 신호에 동작하는 것이 있고, Low 신호에 동작하는 것이 있습니다.  그런데 사실 어떤 것을 구매하든, NO단자와 NC단자의 연결을 바꾸어 주면 원하는 대로 사용할 수 있으니 아무거나 구매하면 되고, 일반적으로 Low Level Trigger 제품이 많이 판매되고 있는 것으로 보입니다.

핀 이름이 중국어로 되어 있는 모듈도 있습니다. (아래 설명)

▶ 만약, 릴레이 모듈의 단자 이름이 중국어로 되어 있을 경우가 있는데요,  이럴 때는 VCC와 GND에 전원을 넣었다 뺐다 해보면서, 테스트기 같은 걸 통해 어느 단자와 붙고 안 붙고를 알아낼 수 있습니다. 
 그런데, 기본적으로 중국어 뜻을 해석해 보면,  가운데 公共端(공공단)은 공통 단자라는 뜻이고 ,  常开(cháng kāi-상개)는 평상시 열려 있다는 뜻으로 NO(normally Open) 단자에 해당되고,  常闭(cháng bì-상폐)는 평상시 닫혀 있다는 뜻으로, NC(normally Closed)에 해당됩니다.


⑤ 220V용 전구(LED 전구도 가능)와 소켓(리셉터클-receptacle)
 여기서 실습 예시를 드는 220V용 전구는 여러 가지 220V용 전구 제품 어떤 것도 활용 가능합니다. 
 전구의 소켓 모양도 여러 가지 타입이 있습니다.


 다만 여기에 실습 예시로 드는 타입은 E타입이며, E타입 중에도 사이즈가 여러가지 있으니, 전구의 사이즈에 맞는 소켓(리셉터클)을 구매해야 합니다. 
 일반적으로 많이 사용되는 백열등 전구의 규격은 E-26입니다.
전구의 최초 발명자는 에디슨(Edison)이죠, 그래서 에디슨이 발명한 형태의 전구 규격 형식에 E글자가 들어가고, 직경 26 mm 수치가 붙어 E-26이라는 규격이 붙여졌습니다. 
이번 실습에 사용한 전구는 아래와 같은 E-26 사이즈의 전구와 (소켓) 리셉터클입니다. (물론 다른 사이즈와 형태를 사용해도 됩니다)

돌려끼는 소켓 타입 전구의 사이즈들 (일반적으로 사용되는 백열 또는 LED전구는 E26 입니다)

 

반응형

 

【 3. 펌웨어 업뎃 】

ESP-01 모듈의 펌웨어 업뎃 관련한 자세하고 상세한 자료는 위에 링크해드린 사전학습 자료 1번을 참고해 주세요. 
  여기서 펌웨어(Firmware)란? 
 :
우리가 흔히 컴퓨터에서 사용되는 용어인 하드웨어와 소프트웨어라는 말은 많이 들어 봤을 텐데요, 펌웨어는 이 두 가지의 중간쯤 역할을 하는 것으로 이해할 수 있습니다.  만약 펌웨어라는 존재가 없다면 소프트웨어에서 기능을 변경하거나 추가하고자 할 때, 거기에 맞대응되는 하드웨어의 논리회로를 하드웨어적으로 일일이 구성해야 하는 어려움이 있습니다.  즉, 소프트웨어 변경에 따라 대응하여 동작할 수 있는 각각의 하드웨어를 새로 만들어야 하는 것과 같은 어려움이 발생합니다.  하지만, 하드웨어 내부에 롬(Rom)과 같은 사라지지 않는 메모리 저장공간을 만들어 두고,  변경되는 소프트웨어 설정에 대응할 수 있는 논리회로 처리 코드를 내재하여 처리할 수 있게 하는 것이 바로 펌웨어입니다.   
 그래서, 똑같은 하드웨어라고 해도 내부의 펌웨어가 달라지면, 지원되는 기능이나 성능 혹은 돌아가는 소프트웨어를 달리 할 수 있는 특징이 있습니다.   예를 들어, 내비게이션에 펌웨어를 업데이트하게 되면, 이전에 지원하지 않던 고용량의 SD 메모리카드 지원이라든지, 시스템이 전혀 다른 내비 OS를 인식시킨다든지, 등의 역할을 해줄 수 있습니다. 

 그래서 펌웨어는 일반적인 소프트웨어처럼, 사용자가 임의로 자주 수정할 수 있는 소프트웨어와는 다른 특성을 가졌고, 하드웨어의 기본적인 설정과 동작을 세팅해주기 위해 하드웨어에 기본 탑재되는 소프트웨어로 이해할 수 있습니다.    

ESP-01 모듈에는 이미 펌웨어가 올려져 있습니다.  하지만 본 실습의 원활한 진행을 위해서는 여기서 안내해 드리는 펌웨어 버전으로 업데이트(최신 버전으로 바꾸는 것이 아니며, 특정 버전으로 변경)를 진행합니다.   
ESP-01 모듈의 출하 제품마다, 출하 시 설치된 펌웨어 버전들이 다르며, esp-01이라는 동일한 이름으로 판매되어도 장착된 메모리를 용량이 다른 경우도 있고, 현재는 메모리 용량을 더욱 키운 esp-01S라는 모듈도 출시되어 있습니다.
이 둘의 일반적으로 알려진 용량은,  ESP-01(512KB, 4 Mbit) ,  ESP-01S(1MB, 8 Mbit)입니다.
 esp-01 관련 실습을 진행할 때, 내장된 기존 펌웨어의 변경이 필요한 경우도 있지만 변경 없이 사용해도 되는 경우가 있을 수 있습니다. 

 

 《 펌웨어 업뎃 실습 》
 AT-커맨드 통신이 가능한 펌웨어를 업뎃하는 실습을 진행합니다.
 ESP-01 모듈의 펌웨어 업뎃은 ①아두이노 우노(나노)와 같은 보드를 USB to TTL 어댑터처럼 사용하여 업뎃하는 방법이 있고 위에서 소개한 ② USB to TTL 변환 모듈을 이용한 방법이 가장 대표적입니다. 
①번의 아두이노를 이용한 방법에서는 펌웨어 업로드(다운로드) 실패 시 리셋을 눌러보거나, 아두이노 보드를 PC USB에서 분리 후 다시 연결 시도해 보거나 하는 등의 조치가 필요할 수 있습니다. 
 개인적으로는 원샷 원킬로 바로바로 잘 되는 ②번 USB to TTL(CP2102) 모듈을 이용한 방법을 추천드립니다. 
 하지만 학습 차원에서 실습은 ①번과 ②번 모두 진행해 보는 것을 추천합니다.

펌웨어 업뎃을 위해서는 아래의 esp8266 flasher(플래셔) 프로그램이 필요합니다.  물론 다른 프로그램을 이용한 방법도 있지만, 여기서는 제일 심플하고 업뎃하기 간편한 아래 프로그램으로 진행하겠습니다.

ESP8266-flasher_AT-mode-Updater.zip
8.56MB

현재의 압축파일을 다운로드하여 풀면 아래와 같은 세 개의 파일이 나옵니다.

펌웨어 압축 파일을 푼 모습

"esp8266_flasher.exe" 파일이 펌웨어 업뎃을 해주는 프로그램이며, "v0.9.2.2 AT Firmware.bin" 파일이 이번 실습에서 업로드시킬 펌웨어 소스 파일입니다.

  아두이노를 USB to TTL 어댑터처럼 사용하여 펌웨어 업데이트 하기. 
(아래 연결도에는 아두이노 우노를 사용하였으나,  아두이노 나노와 같은 보드를 연결하여도 됩니다-영상에서는 나노를 사용하여 보여드립니다)
 아두이노 우노 또한 PC(USB 포트)와 시리얼 통신하기 위한 통신칩(Atmega16u2)이 포함되어 있고, 하드웨어 및 소프트웨어 시리얼 통신(Tx , Rx)을 지원하기 때문에 esp8266와 연결하여 펌웨어를 업데이트해줄 수 있습니다. 
즉, 이때는 아두이노 보드의 플래시 메모리에 코드를 올려 동작시키는 방식이 아니며, 아두이노는 PC와 esp8266 보드를 연결시켜 주는 단순한 USB to TTL 어댑터로써의 역할로 사용됩니다.  이렇게 동작시키기 위해서는, 아두이노의 Reset 포트에 GND를 연결하면 되는데, 이렇게 하면 아두이노를
컨트롤러 보드로서 동작되지 않도록 하는 역할을 합니다. 즉 아두이노의 플래시 메모리에 코드가 올라가지 못하는 상태가 되고 본래의 아두이노 기능은 작동되지 않는다고 이해하시면 좋습니다.  

1. ESP-01 펌웨어 업뎃을 위한 연결도(우노) 
: 우노를 가지고 있다면 아래 이미지를 참고하여 회로를 연결해 주세요.

ESP-01 펌웨어 업뎃 회로(우노)

 만약, 위와 같이 했음에도 불구하고 업뎃이 잘 안 되는 경우가 생기는데요,  기본적으로는 정말 연결 도면대로 제대로 연결했는지? 확인해야 합니다.  단순 연결 실수가 생각 외로 자주 있는 일이니까요.   
그리고, esp-01 모듈의 경우 5V를 전원으로 공급하면 손상될 수 있기에 3.3V 전원을 공급해야 합니다.
 아두이노가 PC USB를 통해 공급받는 전류는 커야 500mA 정도인데요, esp-01 모듈의 경우 순간적으로 500mA이상 소모하는 경우가 있습니다.  기본적으로 esp-01 모듈이 아두이노에서 공급받는 출력 전류가 충분하지 않아서 업뎃이 잘 안 되거나, 실행시킬 때 오류를 보이기도 합니다.
 또한 아두이노의 경우 오픈소스이다 보니, 복제품도 많고 생산단가를 낮추기 위해 저품질의 3.3V 레귤레이터를 사용하는 경우도 있어, 3.3V 전원 핀의 출력 전류가 충분치 않은 경우도 있는 것 같습니다. 
 이런 전류 부족 상황이 의심이 되는 경우,  1단계로 10uF 이상의 전해콘덴서를 연결해 주면 약간의 전원 보충이 될 수 있어 해결될 수 있습니다.  하지만, 이것 만으로도 충분치 않을 경우, 아래 회로처럼, 별도의 3.3V 외부 전원을 연결하여 공급해 주는 방법이 있습니다.  3.3V의 외부 전원을 공급하기 위한 방법에는 여러 가지가 있으나, 그나마 저비용으로 쉽게 구현하기 위해 AMS1117 칩셋을 이용한 3.3V 레귤레이터 모듈을 사용해 봤습니다.(이때, 콘덴서는 생략 가능) 
  여기에 공급되는 전원은 출력 3.3V보다 1V정도 큰 전원이면 상관없습니다.  최소 4.3V(3.3V+1V) 이상을 공급해 주면 됩니다.   그리고 중요한 것은 AMS1117의 GND선(Vout-)과 아두이노의 GND는 이미지처럼 공통으로 연결해주어야 합니다.  이러므로해서 서로 다른 두 개의 전원이 공통의 GND를 기준으로 가지게 됩니다.

ESP-01 펌웨어 업뎃 보강회로(우노)

 다른 예시로는 "브레드 보드 전용 전원 공급 모듈"도 사용하기 편할 수 있습니다.   (브레드 보드에 꽂을 수 있고 5V, 3.3V를 스위치로 선택 공급 가능함),  전원은 아두이노 나노에 연결하는 것과 같은 USB 미니 케이블 전원으로 공급하거나  DC 배럴 잭 타입 5V 이상의 어댑터로 공급할 수 있습니다.

브레드 보드에, 간단하게 5V 또는 3.3V를 공급해 주는 모듈

 아두이노 나노의 경우 우노와 핀 배열이 거의 같고 기능 또한 같으면서 사이즈가 작아 우노를 대체하여 많이 사용됩니다.  여기에 아래 이미지처럼,  브레이크 아웃(break out) 소켓을 사용하면 작은 브레드 보드에 꽂아 조립이 가능하니, 점퍼선으로 너저분하지도 않고 깔끔한 펌웨어 업데이트 회로를 만들 수 있어 좋은 것 같습니다.
아두이노 나노와 esp-01 breakout 소켓을 이용한 심플 회로도를 참고해 보세요.

기본적인 펌웨어 업뎃 연결은 아래와 같은 형태로 연결됩니다.

아두이노 나노와 BreakOut 소켓을 이용한 펌웨어 업뎃 연결도
아두이노 나노와 BreakOut 소켓을 5V 전원으로 연결 실험한 모습(주의! esp-01 모듈이 손상될 수 있습니다~!!!)

 하지만 주의~!!!
esp-01 모듈은 기본적으로 3.3V 전원으로 안전하게 작동되는 보드이며,  전원뿐 아니라, 신호의 전압 레벨도 3.3V가 안전하며, 5V 이상의 전압 레벨(신호)이 지속적으로 입력된다면, 모듈이 손상될 수 있다는 점 기억하세요.
물론, 위와 같이 연결하고 테스트 결과, 다행히 손상은 입지 않았고 작동도 했지만,  짧은 시간의 동작 확인이어서 문제가 발생하지 않았을 것으로 추정됩니다.  따라서  상황에 따라서는 짧은 순간이어도 분명히 모듈이 손상될 수 있기 때문에,  아래와 같은 3.3V 전원 사용과 함께, 저항을 이용한 전압의 분배로 3.3V를 만든 신호가 입력되도록 연결해 주어야 합니다. 

3.3V 전원사용과 레벨변환 저항 이용한 연결 모습

위와 같이 반드시 3.3V 전원을 사용하고, 저항을 통한 레벨링 된 신호 전압이 인가되도록 실습해 주세요.

펌웨어를 업데이트(혹은 다운로드: 펌웨어 프로그램을 esp-01의 롬 영역으로 다운로드시킨다는 의미로 사용함) 시켜주는 프로그램은 대표적으로 두~세 가지 정도 되는데요,  최신 펌웨어이거나 esp-01 기본 모델이 아닌 메모리 용량이 더 크거나 제각각인 모듈에 맞추어 줄 수 있는 업데이트 툴은 따로 있지만,  여기서는 기본 모듈을 업데이트하는 데 사용하기 쉽고 간편한, 플래셔(flasher)라는 툴을 사용합니다. 

 위와 같이 연결하고, 앞서 자료 링크한 esp8266 플래셔(flasher) 프로그램을 다운로드하여 압축을 풀면 아래와 같은 3개의 파일을 확인할 수 있습니다. 

※ 주의~!  
 flasher 파일을 실행시키기 위해서는 한글 이름으로 된 폴더 아래에서는 실행하지 마세요!!! 
만약 한글 폴더 아래에서 프로그램을 실행시킬 경우 대표적인 증상으로, 'xxx.bin'파일을 연결시켜도 선택한 'xxx.bin'파일의 이름과 경로가 표시되지 않는 증상이 나타납니다. ( 상위 폴더 중에 하나라도 한글 폴더가 있으면 안 됩니다)
그리고,  esp8266 관련된 다수의 펌웨어 파일이 존재하는데, 본 게시글에서 소개하는 방법을 실행하기 위해서는 여기서 소개해드린 "v0.9.2.2 AT Firmware.bin" 파일을 선택하세요. 물론, 다른 펌웨어 파일도 가능하지만,  통신 속도가 다르거나, AT-커맨드가 전혀 먹히지 않는 다른 용도의 펌웨어가 있으니 주의해야 합니다. 
ⓐ 먼저 esp8266_flasher.exe 파일을 실행하세요

ⓑ 그럼 아래의 번호 순대로 클릭해서 진행하면 됩니다.

  - ①번의 Bin을 클릭해서 "v0.9.2.2 AT Firmware.bin"파일을 선택하세요.
  - ②번의 COM1 영역에 아두이노가 연결된 포트 번호를 적어줍니다. ('윈도키+K'를 눌러 포트 번호를 확인할 수 있음)
  - ③번 Download 버튼을 누르면, 아두이노에 연결된 esp-01 모듈로 펌웨어 파일이 download 되며 업뎃이 시작됩니다.

펌웨어 업뎃이 완료된 모습

 - 위 이미지를 참고해서 보면, (99%)까지 진행되고, Leaving... 메시지까지만 표시되면 100%업뎃이 완료 된 상태입니다. 
 마지막에 "Failed to leave Flash mode" 메시지는 펌웨어 업뎃 성공/실패하고는 관련 없으니 무시하면 됩니다.

②  USB to TTL 전용 어댑터를 사용한 방법.
 CP2102 어댑터와 같은 USB to TTL 전용 어댑터를 사용하면, 업데이트 작업이 편리하고 업데이트 성공률이 개인적 기준으로 거의 90% 이상 나올 정도로 잘됩니다.   그리고 아래 이미지 나와 있는, esp-01 breakout 소켓이 있으면 좀 더 편하게 작업이 가능하지만, 만약 없다면,  점퍼선으로 바로 연결하면 됩니다.   esp-01 보드는 핀 구조가 2줄로 좁게 배열되어 있기 때문에,  브레드보드에 직접 꽂아서 연결할 수 있는데요,  breakout 소켓을 사용하면, 브레드보드에 꽂을 수 있고 부가적인 부품과 함께 회로 연결을 할 수 있어 편리합니다.

 위와 같이 연결하고, 앞서 자료 링크한 esp8266 플래셔(flasher) 프로그램을 다운로드하여 사용하는 방법을 똑같이 진행하면 됩니다.  단, 이때 포트번호는 장치 관리자에서 CP2102 USB to TTL 모듈의 COM 포트 번호로 입력하여 Download 진행하면 됩니다. 

혹은 아래와 같은 USB to ESP8266 전용 어댑터를 사용하면, 별도의 선 연결 없이 간단히 펌웨어를 업데이트할 수 있습니다. 

USB to ESP8266 어댑터

다만, 위와 같은 어댑터는 번잡한 연결은 피할 수 있지만, 정작 esp-01의 플래시 메모리에 코드를 올리려고 할 때, GPIO 0번 핀을 GND로 리셋(연결) 시켜줘야 하는데, 그런 기능은 제공하고 있지 못합니다. 
따라서, 위의 모듈에 아래와 같은 3가지 부가적인 방법 중 하나로 해결할 수 있으니,  만약 이 모듈을 사용하려고 한다면, 참고해 보세요. (방법 1: 10K 옴의 가변저항 연결방법 / 방법 2: 점퍼 스위치 연결방법 / 방법 3: 푸시버튼스위치 연결방법)
코드 업로드 완료 후에는 해당 연결은 다시 해제해야 정상적으로 작동하기 때문에, 점퍼나 눌렀다 뗄 수 있는 스위치 형태로 작업하게 되는 것이지요.

USB-to-esp8266 어댑터의 플래시 메모리에 코드 업로드를 위한 3가지 해결방법
플래시 메모리에 코드 업로드를 위해서는, PC에 연결할 때 스위치를 먼저 누른 상태로 USB에 연결합니다.

물론 아래 모듈처럼, 아예 코드를 업로드 모드와 노멀 작동 모드로 전환할 수 있도록 스위치가 달려 있는 모듈도 나와 있습니다.    

USB to ESP01 Adapter 모듈 with switch

 하지만 기본 단가가 비싸기도 하고 활용성이 떨어지는데요, 구매해서 활용은 가능하지만,
CP2102 USB to TTL 모듈과 + esp01 breakout 소켓을 사용하는 방법이 가격도 저렴하고, 브레드보드에 연결하여 활용하기에도 좀 더 편한 점이 있어 추천드립니다. 

펌웨어 업데이트 시 에러 증상과 대처 방법 :

1. 만약 아래와 같은 fail to connect라는 문자가 떴다면, 

1. 전원을 연결한 선을 뺐다가 다시 꽂아 본다.    
(브레드 보드에 선을 연결할 경우 선의 접촉이 잘 안 될 수 있으니 접촉이 잘 되도록 확인)

2. TX와 RX 선이 제대로 연결되었는지 확인한다.  
(아두이노의 Tx와 esp-01의 Rx와 연결하고,  아두이노의 Rx와 esp-01의 Tx와  교차로 연결하여야 통신이 됨)

3. ESP8266에 빨간 불이 들어왔는지 확인한다.   
( ESP-01 모듈에 빨간불은 전원이 연결된 표시 이므로, 불이 들어오지 않는다면 ESP-01 모듈의 전원 연결 선을 체크)

 4. 아두이노 USB 포트를 다시 뺐다가 연결한다.   
(USB 포트 인식이 안 되거나,  잘 못된 USB 포트 번호를 넣어 진행할 경우 , USB를 다시 꽂아 보고, 정확한 포트번호 기입)

5. 'CH_PD단자'와  'GPIO 0 단자'를 확인한다.   
(펌웨어 업로드 시에는 esp-01 모듈을 운용할 때와는 달리  CH_PD단자는 플러스(+3.3V)에 연결하고, GPIO 0 단자는 GND(0V)에 연결하여야 펌웨어 업로드가 제대로 진행이 된다.) 

 6. 전원을 5.0V로 잠시 바꾸어 연결하거나,  저항의 1:2 분배 연결을 통해 연결해준다.

( 아두이노 호환 보드를 사용하거나 할 경우 3.3V의 출력이 낮아 제대로 진행이 안 될 경우가 있으니, 짧은 시간 동안 아두이노의 5V 전원을 이용해 보거나,  5V단자로 바꾼 상태에서 1K 옴 저항과 2K 옴 저항의 분배 방법을 이용하여 높은 전류의 3.3V 전원을 넣어 본다. )

 

2. 만약 아래와 같은 'Invalid head of packet'이라는 에러 증상이 나타난다면,

아두이노 코드를 Blink 예제 코드와 같은 기본 코드 혹은 내용을 모두 지우고 업로드 한 아두이노로 펌웨어 업데이트를 진행해본다.   아두이노에 Serial 통신을 사용하거나 하는 등의 기존 코드가 들어 있을 경우 이런 에러가 나타나기도 한다. 

 



《 AT 통신 하기 》

AT 통신 관련해서는 아래 이전 게시글에 상세히 안내하였으니, AT통신 명령어의 종류나 기본 사용법 등을 참고하려면 아래 링크를 참고해 보세요.
【 아두이노 모듈#25】ESP8266 esp-01 활용하기#1 : 펌웨어 업뎃(AT-통신하기 명령어 사용하기)

 여기서는 AT-통신이 되는 과정과 결과 위주로 설명드리고 있으니, AT-명령어/통신 관련된 기초 내용이 필요하신 분은 꼭 위 링크를 함께 참조해 보세요.

《 1-1. 브레이크 아웃(BreakOut) 소켓 활용하여 AT-명령어/통신 테스트하기 》

먼저, BreakOut 소켓을 가지고 AT통신 테스트 및 동작을 시키기 위해서는 아래와 같은 연결로 바꾸어야 합니다. 그럼 아래 이미지는 앞서 소개한 breakOut 소켓과 나노보드를 기본적으로 연결한 회로입니다.
아래 수정된 회로를 참고하여 회로 연결을 펌웨어 업데이트용 연결 → AT통신 및 동작회로용 연결로 바꾸세요.
주의~!  :  바로 아래 회로는 모듈 손상이 예상될 수 있는 연결이어서 연결을 삼가고 레벨 변환 저항을 사용한 회로로 연결해야 합니다~!

ESP01 AT통신 및 동작을 위한 회로 연결 (BreakOut소켓과 나노)

하지만~!  이 역시 3.3V 레벨로 회로를 변경해 주어야 모듈이 문제가 생기지 않습니다.
저항이 없어 RX에 연결할 수 없다면, VCC +전원이라도 5V가 아닌 3.3V로 연결해야 합니다.
반드시 아래 회로로 연결해서 진행하세요.

레벨컨버팅 저항을 추가한 ESP01 AT통신 및 동작을 위한 회로 연결 (BreakOut소켓과 나노)

 BreakOut 소켓이 있으면, 펌웨어 업데이트도 가능하고, AT통신과 일반적인 모듈 사용도 가능합니다.
위와 같이 연결 후,  PC와 연결해서 AT-통신 테스트를 해볼 텐데요, 
준비사항으로, 아두이노 IDE를 실행시키고 아래와 같은 통신용 코드를 아두이노로 업로드시켜야 합니다.
그전에, 아두이노 나노(NANO) 보드를 사용할 경우, 나노 보드를 아두이노 IDE에서 프로세서 부분을 선택할 때,
거의 대부분은 "ATmega328( Old Bootloader )"을 선택해야 합니다. 

이미지를 클릭하면 확대 됩니다
코드의 시리얼통신 설정 번호와 회로에서의 연결이 일치해야 합니다

만약, 아래와 같이 코드 업로드 시 에러가 난다면, esp01 모듈 연결이 업로드에 영향을 준 것으로 보입니다. 이럴 때는, esp01 모듈이나 소켓 포함한 모듈 전체를 제거 후 다시 업로드 시도해보면 대부분 해결됩니다.  그리고 나노보드의 전원을 잠시 제거 후(또는 리셋 버튼 이용) 업로드 버튼을 눌러보세요

코드 업로드시 에러가 날 때는, esp-01 모듈의 연결을 해제후 시도해 보세요.

아래 코드를 드래그해서 복사하거나,  첨부파일을 다운로드하여 압축을 풀고 사용해 보세요.

#include <SoftwareSerial.h> 
#define RX 7 
#define TX 6 
SoftwareSerial ESP_wifi(RX, TX); 
void setup() { 
  Serial.begin(9600); 
  ESP_wifi.begin(9600); 
  ESP_wifi.setTimeout(5000); 
  delay(1000); 
} 
void loop() { 
if (Serial.available()){
  ESP_wifi.write(Serial.read()); 
} 
if (ESP_wifi.available()) { 
  Serial.write(ESP_wifi.read()); 
  }
}

AT_Test.zip
0.00MB

                                          ※ AT 통신 테스트를 위한 아두이노 코드 다운로드하기

기본적인 AT 통신 명령어만 정리해 봤습니다. (좀 더 자세한 사항은 위에 안내해드린 링크를 참조해 주세요)
아울러 'Steve AHN'이라는 분이 정리한 "AT-명령어 셋"이라는 ESP8266 모듈에서의 AT 명령어 요약집을 첨부해 드리니 참고해 보세요.   다만,  명령어는 상황에 따라 예를 들어, AP모드일 때만 적용(실행)되는 명령어가 있고, 스테이션 모드일 때만 실행되는 명령어가 있습니다.   
그리고,  명령어 입력 방법이 조금씩 다를 수도 있으니 참고하세요.
(예, 대소문자 구분하거나, 입력 시, 명령어+'?'사용하거나, 명령어+':' 사용 등)

그리고  모든 명령어가 다 실행되는 것은 아닌데요,  설치된 펌웨어 버전(종류)에 따라, 실행되는 명령어가 있고 실행되지 않는 명령어나 추가로 실행될 수 있는 명령어가 있을 수 있다는 점 참고하세요. 
몇 가지 펌웨어를 테스트해봤지만,  개인적으로는 별로 였고,  실습에서 업데이트 한 'v0.9.2.2 AT Firmware.bin' 펌웨어는 좀 오래된 펌웨어이지만,  이 번 실습을 진행하는데 문제가 없고, 9600 bps에서도 잘 실행되니 사용하고 있습니다.  최신 펌웨어나 다른 버전에 대해서는 직접 적용해 보고 판단해 보세요.

위 펌웨어 명령어 중 주요 명령어를 테스트한 부분은 본 게시글의 영상이나,  위에 링크해드린 게시글을 참고해 보세요.

아래 파일은 바로 위에 소개한 AT명령어 요약집(PDF) 파일입니다.

AT 명령어 요약집.pdf
0.12MB

코드 업로드가 되고 아두이노 IDE의 시리얼 모니터의 보 레이트 9600 bps로 맞추어 준 후 아래처럼 AT명령어에 따른 응답이 보인다면 AT-통신이 되는 것입니다.

AT-통신 테스트 성공 화면

 


《 1-2. ESP01 어댑터 모듈 활용하여 AT-명령어/통신 테스트하기 》

다음으로 esp01 어댑터 소켓의 사용방법을 설명드립니다

: ESP01 어댑터 모듈은 4개의 핀으로 구성된 ESP01 전용 어댑터 소켓으로서,  펌웨어 업데이트 때는 활용할 수 없지만,
이미 펌웨어 업뎃을 완료하였거나,  업뎃이 필요 없는 모듈을 4개의 핀만으로 사용 가능하도록 해주는 편리한 모듈입니다.
앞서 설치해야만 했던, 레벨 변환 부품도 이미 내장되어 있어서,  사용하기 편한 5V를 그대로 사용할 수 있어 좋습니다.
그리고, ESP01 모듈의 RX 단자를 위한 레벨 변환도 역시 적용되어 있습니다.
모듈의 연결 방향은 아래처럼 해주세요.

여기서는 5V를 연결해야 합니다. 3.3V레귤레이터 회로가 들어 있는 모듈이기 때문에 3.3V를 입력하면 회로에 소모되는 전력이 있기 때문에 오히려 동작이 안 될 수 있습니다.  아주 높은 전압이 아닌 이상 3.3V 보다 높은 것은 상관없습니다.
그리고서, 조금 전 위에서 올린 AT-통신용 코드가 나노에 올려져 있으면 됩니다.
그럼, 시리얼 모니터를 열고 'AT'와 기타 몇 가지 명령어들을 입력해보세요.
그럼, 아래처럼 AT-명령어로 통신이 되는 것을 보실 수 있습니다.

ESP01 어댑터 모듈을 활용한 AT-통신 테스트

 

이번에는 esp01 어댑터를 보드에 밀착시켜 안정적으로 부착시키기 위해 핀 부분을 다시 납땜해 봤습니다.

esp-01어댑터 핀 재비치 모습입니다

이렇게 작업할 수 있다는 것을 보여드리는 것이기 때문에 이 부분은 참고만 하셔도 됩니다.
기존에 있던 'ㄱ'자 핀을 세우고, 핀헤드의 검은색 부분을 니퍼로 잘라서 빼냈습니다.
그리고 납 흡입기를 이용해서 인두기로 녹인 납을 최대한 빨아들이고, 핀 하나씩 인두기로 다시 열을 가하면 핀을 움직일 수 있는데, 최대한 밑으로 내려서 재 납땜을 하면 됩니다.  
그럼, 이렇게 브레드보드에 납작하게 밀착시킬 수 있게 됩니다.

물론, 이렇게 작업하면, 보드에 꽂을 때 핀 순서가 달라지니, 연결 도면을 보고 맞게 연결해 주세요.
그럼, 테스트를 위해 조금 전의 esp01 모듈을 옮겨 꽂습니다. 

참고로, 주변 WiFi 검색 명령어인  'AT+CWLAP'는 esp01이 '2번 AP모드' 혹은, '3번 AP+스테이션' 복합 모드 상태에서만 작동합니다.

 

《 1-3. ESP01 어댑터 모듈 활용하여 AT-명령어/통신 테스트하기 》

다음으로, USB to TTL 모듈 중 하나인 CP2102 모듈을 사용해서 펌웨어 업뎃을 해보겠습니다.
CP2102 모듈 업뎃은 아두이노보드가 필요없으며, 펌웨어 업뎃 성공률이 높고 사용하기도 매우 편리합니다.
여기에 breakOut 소켓이 있으면 매우 심플한 회로 구성이 가능합니다.

조립된 회로에 esp01 모듈을 연결합니다, 꽂을 때는 항상 방향을 확인해 주세요.
USB 연장 케이블이 있으면 PC USB 포트와 좀 더 편리하게 연결할 수 있습니다.
CP2102에 할당된 COM 포트 번호를 확인하고 입력해 주세요.
그리고서 Download 버튼을 누르면 아래와 같이 Tx Rx 송신 수신 LED가 깜빡이며 펌웨어 업로드가 진행되는 것을 보실 수 있습니다.

그럼, 업뎃이 완료된 esp-01 모듈을 좀 전에 만든 보드로 옮겨서 테스트해 볼게요.
그런데, 만약  AT 명령어를 시리얼 모니터에 입력해도 아무런 반응이 없는 경우가 생기는데요, 
이럴 때는 전원을 제거하고 몇 초 기다린 후 다시 넣어 봅니다.
그래도 AT 명령어가 먹히질 않는다면, esp01 모듈이나 어댑터 자체를 제거 후 다시 연결해 보세.
그럼, 아래 이미지 결과처럼 AT통신에 성공하는 화면을 보실 수 있습니다. 

핀 재배열 납땜한 esp01-어댑터로 AT통신에 성공한 모습

 


【 3. Blynk App 소개와 설치 】

 이번 실습에서는 Blynk(블링크)라는 서비스와 앱을 사용하여 진행합니다. 
일반적으로 집안에서는 wifi를 통해 내부 네트워크(사설 IP)에 연결된 IoT 작품들을 스마트폰으로 컨트롤 하기는 쉽습니다.  하지만, 집 밖 외부에서 컨트롤하려면 "wifi 라우터"의 공인 IP를 IoT 기기가 할당받은 IP로 포트 포워딩 설정을 해야 하는 등의 까다로움이 있습니다.   그리고 스마트폰에서 제어할 목적으로 앱 같은 것을 만들 때, 앱인벤터를 사용하면 전문적인 앱 개발 프로그램에 비해 제작이 쉽긴 하지만, 앱인벤터 사용법이나 코딩 관련 학습이 부족하면 역시 접근에 어려움이 있는 것이 사실입니다. 
 이에 블링크(Blynk)라는 서비스는 공개 사이트처럼 작동되는 서버를 이용하기에 라우터의 포트 포워딩 조치 필요 없이 접근이 가능하며, 직관적인 앱 작성과 강력한 Blynk 자체 라이브러리 제공으로 인해 몇 분 안 걸려 뚝딱하고 앱을 만들 수 있는 서비스입니다.   아두이노 코드에서도 센서의 신호에 일일이 대응하는 코드 작성의 어려움 없이, Blynk 라이브러리와 서버에서 모두 처리를 해주기 때문 몇 가지 함수 선언과 약간의 코드 설정만으로도 코드가 완성되어 코드 작성이 쉬워,  IoT 서비스를 쉽게 구현할 수 있는 장점이 있습니다.

블링크 앱 제작 예시 이미지(blynk.com 제공)

 이번 실습에서 블링크를 활용하려는 목적은 외부에서도 쉽게 집안에 있는 네트워크에 연결된 IoT 작품들을 컨트롤하기 위함이 가장 큽니다.
집안에서 같은 WiFi 네트워크에 접속된 esp8266wifi 모듈을 제어하기는 쉽지만, 외부(네트워크)에서 집에 설치해 놓은 'esp8266+프로젝트'를 컨트롤 하기는 쉽지 않습니다.  
 이에, 공인 서버의 역할을 할 수 있는 Blynk Server 클라우드로 이런 문제를 해결하고 서비스를 제공하고 있습니다.
게다가,  안드로이드와 애플 IOS에서 각각 사용할 수 있는 Blynk App을 이용하면, 복잡한 코딩 작성 없이 아주 쉽게 IOT 시스템을 제어할 수 있는 앱을 만들 수 있어서, 현재 많은 인기를 얻고 있습니다. 
 기본적인 사용은 무료이며  energe라는 시스템을 사용합니다.  처음 시작할 때 2000 energy가 무료로 주어집니다. 
앱을 제작할 때 버튼 같은 구성요소를 위젯이라 부르는데, 제일 작은 버튼의 경우 200 energy가 소요되며,  구성요소를 모두 합산해서 2000 energy까지는 무료로 이용할 수 있습니다.  만약 더 많은 버튼이나 구성요소를 추가 사용하고 싶을 때는 소정의 결제로 에너지를 키울 수 있습니다.  또한 본인이 만든 앱을 타인에게도 이용하게 할 경우에도 소정의 비용 결제가 필요한 것으로 보입니다. 

무료 제공(2000 energy)으로 만든 앱구성과 위젯 종류들
블링크(Blynk)에서 제공하는 다양한 위젯들(앱의 화면을 구성할 때 사용되는 모듈)

 접속 서버는 블링크에서 제공하는 블링크 클라우드 서버를 이용할 수 있으며,  다른 공개 서버를 선택해 이용할 수도 있습니다.  학습 목적으로 또는 본인이 이용하기 위한 간단한 시스템 정도는 거의 비용들이지 않고 앱을 만들어 활용할 수 있습니다.   블링크는 Arduiono 시리즈, ESP8266 시리즈, Raspberry Pi 시리즈 등 거의 대부분의 마이크로 프로세서 보드를 지원하고 있습니다. 

 

[ 블링크 앱 설치 & 계정(회원) 등록 ]

먼저 https://blynk.cc  (또는, blynk.io ) 사이트로 접속합니다.  여기서 자신의 이메일 주소 하나를 아이디로 선택하고 회원가입을 할 수 있으며,  Blynk앱에서도 회원가입이 됩니다.  구글 앱과 애플의 IOS용 앱 모두 동일하게 서비스됩니다.
어차피 Blynk 앱을 설치해야 하니, 플레이스토어(앱 스토어)에서 앱을 다운로드하여 설치하세요. 

Blynk 앱에서 회원가입과 로그인하기

(아래) 로그인 후 뉴 프로젝트를 클릭하면,  새 프로젝트 이름을 입력하고 우노/나노/esp8266 등등 사용할 장치를 선택할 수 있습니다. 
앱 배경 색상은 어둡게(DARK) 또는 밝게(LIGHT) 중 하나를 선택하고, "Create"를 누르면 Blynk를 사용할 기본 준비는 된 상태이며, 이어지는 실습 부분에서 다시 설명드립니다. 


여기까지가 Blynk 앱 설치 및 계정 가입이 완료된 상태입니다. 


 [ Blynk 라이브러리 설치 ]

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
 우선,  아두이노에 라이브러리 설치에 대한 개념이 궁금하다면 아래 링크를 확인해 보세요. 
혹은, 라이브러리 설치 시 에러가 나거나 해결이 잘 안 될 때 참고해 보세요. 
클릭 → 【 아두이노 라이브러리 설치 경로/에러/추가/개념 정리 】 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

 아두이노 IDE에서 Blynk 관련 라이브러리를 이용하기 위해서는 관련 라이브러리를 설치해야 합니다.
이 Blynk 라이브러리로 인해, 아두이노 코드가 매우 간단해져 코드 작성이 쉬워집니다.
Blynk 라이브러리는 크게 두 가지 방법으로 설치할 수 있습니다. 

"Developer"를 클릭하세요.

(아래)  "Get Started"를 클릭해서 "GitHub"로 들어가거나,  첫 화면의 "GitHub"를 클릭해서 들어가세요.

 

(아래) "blynk-library" 항목이 보이는데요, 클릭합니다.

 

이어서 나타나는 아래 화면의 조금 아래쪽에 있는 "Arduino Library" 항목을 클릭하세요.


(아래) 여기 'Tags' 부분을 클릭하면, 최신 버전 순으로 올려진 라이브러리를 모두 볼 수 있습니다.

 


이번 실습들은 전부 V0.61 버전으로 진행하였기에, V0.61 버전을 설치하세요. (V0.6.1 클릭)

 

최신 버전이라고 무조건 좋다고 말할 수 없으며, 버전에 따라 라이브러리 사용법이 달라질 수 있기 때문에 작업에 문제없는 버전으로 선택하는 것입니다. ( 만약, 버전을 바꿀 경우, 코드를 변경해야 할 수도 있습니다.)
만약, 'V0.61'버전으로 실습이 성공하였다면, 다른 버전으로 테스트를 해보는 것도 좋습니다
클릭 후, 나오는 화면 아래쪽으로 스크롤해보면, 아래처럼 다운로드할 수 있습니다.  

다운로드한 압축파일을 풀고 C:\Document\Arduino\libraries\ 아래에 붙여 넣기 하거나,
아두이노 IDE 메뉴에서 ". ZIP 파일로 라이브러리 등록하기"를 이용할 수 있습니다.
만약, .ZIP파일 등록하기를 할 경우, 현재의 압축상태로는 추가되지 않는데요, 
압축을 풀고 압축파일 속, libraries 아래 Blynk 폴더만 따로 다시 압축하여 등록하면 추가됩니다.
(우선,  Blynk.zip으로 압축합니다)

그럼, 아두이노 IDE를 실행하여 방금 압축한 파일을 추가해 주세요.


조금 전에 Blynk.zip이라는 이름으로 압축한 파일을 찾아 선택해 주세요. 

네,  이렇게 하면 압축파일 형태로 라이브러리를 추가할 수 있습니다. 
지금까지는 Blynk 사이트 접속과 깃허브를 통한 라이브러리 찾는 법을 설명드렸습니다.
그럼, 이번에는 좀 더 쉽게 Blynk라이브러리를 설치하는 법을 알려드립니다.

아두이노 IDE 메뉴 : 툴》라이브러리 관리... 를 실행하세요.


(아래) 라이브러리 매니저 검색창에서 "Blynk"로 검색합니다.

"Blynk" 라이브러리 목록이 뜨면, 원하는 버전을 선택하여 설치하면 됩니다.


앞서 ZIP라이브러리를 등록하였더라도, 여기서 버전 0.6.1 버전을 선택해서 설치해 주세요
(실습에 필요한 <BlynkSimpleShieldEsp8266.h> 라이브러리를 추가할 수 있게 됩니다)
간혹, 어떤 특정 라이브러리들은 수동?으로 라이브러리를 C:\Document\Arduino\libraries\ 아래에 붙여 넣기 하더라도, 연관된 라이브러리가 설치되지 않아 에러가 생길 수 있는데요,  이럴 때, 라이브러리 매니저를 통해 설치하면, 필요한 연관 라이브러리도 함께 설치해주기 때문에, 문제를 해결할 수 있습니다. 
따라서, 이 번 라이브러리는 라이브러리 매니저를 통해 V0.6.1 버전을 설치해 주세요.

 만약, 해당 라이브러리가 기존에 설치되었다면, "업데이트"버튼으로 나타나며, 다른 버전으로 변경(업데이트) 설치도 가능합니다.

그럼, 이제 본격적으로 실습 4. 《하드웨어 제어 실습 》 을 진행해 보도록 하겠습니다.

(실습 1) WiFi를 활용한 LED 켜고 끄기 실습을 진행해 보겠습니다. 

먼저,  아래에 보이는 연결도를 참고하여 회로를 조립해 주세요. 

이번 실습부터는 가장 활용하기 편한 ESP-01 어댑터 모듈을 사용하여 실습을 진행합니다.
만약, 어댑터가 없더라도, 위에서 소개한 BreakOut 소켓이나 다른 종류의 어댑터를 사용해도 좋지만, 가급적 위 이미지에 있는 어댑터를 준비해 주시면 훨씬 작업이 간단하고 편해집니다.(레벨 변환 저항이 어댑터에 내장되어 있어 연결이 간단해집니다) 
아래는 어댑터가 없을 경우 BreakOut 소켓을 이용한 연결이니 참고해 주세요. 아래와 같이 연결 후 D2, D3에 LED와 저항을 추가로 연결하면 위와 같은 회로가 됩니다.  이어지는 다른 실습들도 이와 같이 연결하면 됩니다.(따라서, 이후로는 esp-01 어댑터를 이용한 연결도만 보여드립니다)

BreakOut 소켓을 이용한 LED on/off 회로 연결도면


 그럼, 이와 같이 연결된 회로(Nano)에 아두이노 코드를 넣어야 하는데요,  조금 전에 라이브러리 설치와 함께 Blynk관련 예제 파일도 설치가 되는데요,  이 예제 파일을 베이스로 코드 작성을 쉽게 할 수 있습니다. 
그리고, 각각의 예제를 열어 참고해 보면, Blynk 서비스 적용을 위한 코드 파악에도 도움이 됩니다.

이런 예제 파일에는 Blynk 서비스를 사용할 수 있는 예시 코드들이 있기 때문에 수정이 필요한 항목만 채워주면 매우 쉽게 여러분의 응용 작품에 적용시킬 수 있습니다.
위 이미지에 있는 Blynk 》 Boards_WiFi 》'ESP8266_Shield' 예제를 여세요.


우선, 예제 파일의 주석 부분은 깔끔하게 지울게요.

(아래) 가장 먼저 입력이 필요한 부분이 여기 3곳입니다.  

(위)  auth [ ] = 이 부분의 인증 토큰은 Blynk 앱에서 프로젝트를 만들 때(Create Project), 프로젝트마다 발급됩니다. 
그리고,  esp-8266 모듈이 접속할 WiFi 이름(SSID)과 비번(PASS)을 입력해 주세요. 
 자신의 집이나 회사에서 실습을 한다면 해당 WiFi 공유기의 주소와 비번으로 적으면 되고,  만약, 주변 WiFi 공유기를 연결할 수 있는 상황이 아니라면, 핸드폰의 핫스팟을 이용하면 됩니다.

그럼, 블링크 앱을 열고 가입한 E-mail ID와 비번으로 로그인을 합니다. 
New Project를 클릭하세요.  프로젝트 이름에는 'LED On/Off' 등 적당히 입력하고, CHOOSE DEVICE 디바이스 선택에서는 반드시 ③번처럼, Arduino Nano를 선택해야 합니다. 
왜냐하면, 여기서 esp8266-01 보드는 단순히 WiFi 어댑터 기능만 하기 때문에,  프로그램을 올리고 실행시켜주는 보드로 나노(우노)를 사용하고 있기 때문이죠.   따라서 앱인벤터를 통해 아두이노 Nano(우노) 보드를 제어하는 것으로 이해해야 합니다. 

접속 타입은 WiFi를 선택하고 Create Project를 누르세요. 
그럼, 곧바로 아래처럼 이메일로 방금 만든 프로젝트와 관련된 토큰이 전송됩니다. 


그럼 E-mail을 열어서 보내준 토큰을 복사 후 위 코드 auth [ ] = 에 '붙여 넣기' 하면 됩니다. 

그럼, 핸드폰의 핫스팟(테더링) 기능으로 WiFi를 대신하게 하고, 접속시켜 보겠습니다
(만약, 주변 WiFi 접속이 가능한 경우 WiFi로 접속하면 되고, 핸드폰도 동일한  WiFi에 접속되어야 합니다)
이 부분의 코드 수정은 아래와 같습니다. 

자신의 WiFi ID와 비번을 입력하세요. 
그리고, 나노(우노) 보드와 소프트웨어 시리얼 통신을 해야 하기 때문에 아래 이미지의 주석을 해제합니다.

(아래) 그리고  7번(Rx↔Tx)과, 6번(Tx↔Rx) 포트 번호를 변경해 주세요
( Vcc & GND  전원도 연결해 주세요)

 

(아래) ※ 중요!   ESP8266의 통신 속도는 9600 bps로 합니다!
(esp-01 모듈의 펌웨어가 9600 bps로 되어 있기 때문입니다!)

그리고 나머지는 손댈 필요 없고 보이는 것처럼 매우 심플합니다. 복잡한 처리 코드는 Blynk 서버에서 알아서 해결하기 때문에, 코드 작성이 매우 간단하고 쉽습니다.

위와 같이 수정 후, 다른 이름으로 저장하여 사용하면 됩니다.   
또는, 
아래가 전체 코드 내용이며, 다운로드하여서 사용하세요. 
(auth [ ] /  ssid [ ]  /  pass [ ]  부분을 자신의 것으로 변경하세요)

#define BLYNK_PRINT Serial
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>

char auth[] = "zb7ssO2FlJBdl2nvm1TZ7gcqk9vKMZOd";
char ssid[] = "iPhone6K";
char pass[] = "12345678";

#define EspSerial Serial1

#include <SoftwareSerial.h>
SoftwareSerial EspSerial(7, 6); // RX, TX

#define ESP8266_BAUD 9600

ESP8266 wifi(&EspSerial);

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

  delay(10);

  // Set ESP8266 baud rate
  EspSerial.begin(ESP8266_BAUD);
  delay(10);

  Blynk.begin(auth, wifi, ssid, pass);
}

void loop()
{
  Blynk.run();
}

[ 코드 다운로드하기 - 실습 1) LED On/Off 제어하기 코드 -]

Nano_esp01_LED.zip
0.00MB

압축을 풀어 사용하세요.
그럼, 이 코드를 회로에 업로드해 볼게요. 
조립 연결한 회로를 PC와 연결하고, 인식한 포트 번호를 확인합니다. 

 아두이노 나노를 사용한다면, 보통은 ATmega328 (Old Bootloader)를 선택해야 동작됩니다.
그리고, 나노 보드는 연결될 때,  COMxx 포트 옆에 Arduino 표시가 되지 않습니다.  


이때는 (아래) 아두이노 IDE의 우측 하단에 표시된 포트를 확인하거나,  장치 관리자(단축키:Ctrl+X)의 포트 부분을 확인해 보면 알 수 있습니다. 

아두이노 나노가 연결된 포트 확인하는 방법


코드를 업로드할 때는, 회로 연결에 영향을 줄 수 있기 때문에 아래처럼 8266 모듈을 제거한 상태에서 하세요. 


만약 업로드 시 완료가 잘 안된다면, 나노 보드를 리셋시켜주거나, 전원을 제거 후 다시 연결하고 시도하세요.
그럼, 스마트폰 등의 WiFi를(핫스팟) 켜서 8266 나노 보드가 접속하기를 기다려 봅니다. (아래)

 접속이 되었다면,  아두이노 IDE의 시리얼 모니터 창을 여세요.(아래)


그럼, 아래처럼 WiFi 중계기(핫스팟)로부터 할당받은 IP가 표시되고,  ping 속도까지 표시된다면, WiFi 네트워크로 완벽히 연결된 것입니다. 

만약 ping 속도까지 표시되지 않았다면, 핫스팟을 다시 껐다 켜고, 시리얼 모니터 창도 다시 닫고 열어보세요.
그리고, (아래) 앱에서 연결 정보 부분을 터치했을 때, Online으로 된 것을 확인할 수 있는데요,  
(안드로이드 앱은 확인 위치나 방법이 다를 수 있어요)

만약 온라인이 되지 않았다면, 핫스팟 또는 WiFi연결 과정을 다시 시도해 보세요

그럼,  (아래) Blynk 앱에서 빈 화면을 우측에서 좌로 슬라이드해 보면, 앱 화면 구성을 위한 여러 가지 위젯 박스들이 있습니다. (  안드로이드 앱에서는 방법이 조금 다를 수 있으나 쉽게 찾을 수 있습니다 )

위젯 하나당 사용 에너지가 책정되어 있으며, 토털 2,000까지는 무료로 앱 구성 가능합니다. 
필요한 경우 에너지를 추가로 구매하여 사용할 수 있습니다.
(앱을 여러 개 만들거나 타인에게 만든 앱을 주려 할 경우가 아니라면, 이번 실습 내용은 무료로 충분히 이용 가능해요)
그럼, 목록에서 버튼 하나를 불러와서 위젯을 꾹 1초 정도 누르면 위치를 옮길 수 있습니다.

그리고 버튼을 터치하면 세부적인 설정이 가능합니다.
1. 버튼의 이름을 'LED1'로 하고 버튼의 버튼 색상도 변경해 보세요.

2. LED를 연결한 PIN(port)의 출력 방식을 결정해주면 됩니다.
L1 이 연결된 나노의 포트 번호 D2를 선택합니다.

3.  작동 형태는  PUSH/SWITCH 중에 SWITCH로 선택하세요. 
아래는 이 세 가지를 설정 완료한 모습이니 참고하세요.

PUSH는 버튼을 터치하고 있는 동안만 작동(High, 1 ) 되는 방식이며,  SWITCH는 버튼을 한 번씩 터치할 때마다, On/Off (1/0)가 토글(전환)되는 방식입니다.

같은 방법으로 두 번째 LED 'L2'에 대한 위젯 버튼을 만들고 설정해 줍니다. 버튼 2까지 완료되면, 플레이(▶) 버튼을 눌러주세요.


그러면, 앱의 버튼을 눌러서 WiFi로 연결된 나노보드의 L1과 L2를 제어할 수 있게 됩니다.

어떠세요?  굉장하지 않습니까? 
이것이 굉장한 이유는, 지금은 LED를 작동시킨 것이지만,  여기에 릴레이와 같은 부품을 추가적으로 연결하면, 220V와 같은 전구도 무선으로 제어가 된다는 점입니다.(실습 5에서 다루고 있습니다)
 뿐만 아니라, 모터 드라이버 관련 회로를 추가해 주면 모터도 무선으로 켜고 끄거나 방향 제어까지 할 수 있죠.
제어하고자 하는 어떤 것이든 유선으로 직접 제어할 수 있다면 무선으로 전환시킬 수 있다는 뜻이 됩니다.
이것이 IoT에서 이루어지고 있는 핵심 개념이라 할 수 있습니다.
우리 생활 속 주변에 있는 모든 기기들에 대해서, 번거롭고 제한적인 유선을 무선으로 확장시키고, 
WiFi와 같은 여러 가지 무선 네트워크로 연결시켜 언제 어디서든 데이터를 확인하거나 컨트롤할 수 있게 만드는 것!
이런 관점으로 주변을 둘러본다면, ioT로 전환시킬 수 있는 엄청난 일거리(먹거리)들이 보일 거예요. 
ioT의 전망도 밝다고 할 수 있으며,  프로젝트에 따라서는 여기에 Ai 기능을 적용하여 사람이 일일이 관여하기 번거롭거나 복잡한 부분에 대해서는 Ai가 사람의 지능적인 판단을 대신하여, 쉽고 빠르게 처리하는 방향으로 흘러갈 것으로 보입니다. 

그리고 PC와 연결되지 않은 경우에도 동작이 잘 되는지? 보조 배터리로 테스트해 보면, 잘 될 것입니다. 

그런데 일반적인 보조 배터리의 경우, 지속적인 전원 사용이 감지되지 않았을 때는, 자동으로 전원 차단(절전) 기능이 작동하게 됩니다. 
따라서, 실제 프로젝트에 적용할 때는 6~12v 사이의 전원 어댑터 혹은, 18650 리튬전지 등으로 전원을 구성하면 됩니다.
그럼, 실습 1) 은 여기까지이며,  곧바로 실습 2)로 이어집니다. 

 

아래는 실습 2)에서 사용할 회로 도면입니다 회로의 이해를 위해 참고용으로 봐주세요. 

모터 같은 종류는 아두이노 포트의 작은 출력(약, 40mA)으로는 직접적으로 돌리기 힘듭니다.
따라서 모터를 움직여줄 전력을 배터리로 따로 공급하게 되며,  아두이노 포트의 출력은 On/Off 신호로 활용하게 됩니다.  전자적인 스위치 작용을 하는 TR(파워 TR)을 이용해서 위 도면처럼 구성하면 모터를 제어할 수 있습니다.
즉, 아두이노 포트 출력이 있을 때(High, 1)는 TR이 On 되어, 모터와 배터리 회로가 완전히 연결되어 모터가 동작되며,  아두이노 포트에서 출력이 없을 때(Low, 0)는 TR이 Off 되어, 모터와 배터리 연결이 차단되어 모터가 정지하게 됩니다.

뒤에 나오는 (실습 3)에서는 TR 대신, IC를 사용한 모터 드라이버 모듈을 사용하게 되는데요, 연결과 사용이 간편하고, 정·역 방향 제어까지 쉽게 할 수 있습니다.
모터는 내부가 코일 형태로 되어 있어, 동작시킬 때 반대 방향으로, 역기전력이 발생하게 되는데요, 이로 인해 주변 회로(부품)가 손상을 입을 수 있는데, 이를 방지하기 위해,  다이오드를 모터 가까이 화면과 같은 방향으로 연결하면 역기전력(역전류)으로부터 보호할 수 있습니다.   만약 단순히 테스트로 끝낸다면 다이오드를 생략할 수 있습니다.

지금 아래 보이는 것이 부품을 실물 모습으로 연결해 놓은 연결 도면입니다.

(※ 실습 전 주의 사항!)
1. 부품 중에는, 방향이나 핀 이름, + - 극성이 구분되어야 하니, 주의해서 연결해 주세요! (+ , - 반대로 연결 금지!)
2. 리튬 이온(폴리머) 배터리의 경우 + - 극이 서로 만나게(합선) 될 경우 불꽃이 튀면서 화재가 날 수 있습니다. 이런 배터리를 다룰 때는 항상 주의하며, 연결된 상태에서는 자리를 비우지 말고 계속 주시해야 만일의 사태에 대비할 수 있습니다!  실습 후에는 커넥터에서 분리 후, 직사광선을 피해서 안전하게 보관해 주세요.


만약, 적합하지 않은 TR 부품을 사용하거나, 모터 용량이 이것보다 크게 차이가 있을 경우, TR의 스위칭 작용이 되지 않아 제어가 안 될 수 있는데요, 이럴 때는, TR의 Base(B)에 연결된 1KΩ의 저항값을 테스트를 통해 큰 값 또는 작은 값으로 변경해 보세요.

그리고, 5V 이상의 높은 배터리를 사용해야 한다면, 작은 모터에 그냥 사용하지 말고, 배터리 앞쪽에, 3.3V로 낮추어 일정한 출력을 내주는 AMS1117 모듈 같은 것을 사용해서 보호해 주는 것이 좋습니다.

AMS1117 정전압 모듈(3.3V 출력용)

아두이노에서 모터를 함께 사용해야 할 때는, 이렇게 전원을 별도로 분리 공급해 주는 것이 무엇보다 중요합니다.
아두이노와 주변 회로를 돌리면서, 모터까지 돌리기에는 전력 부족이 발생할 수 있으며, 모터의 진동에 의한 노이즈(noise)가 회로의 신호에 영향을 줄 때, 불안정한 동작을 예방할 수 있기 때문입니다.

(아래) 앞서 보여드린 대로 어댑터를 보드에 낮게 고정시키기 위해 핀의 방향을 바꾸어 납땜했는데요, 하지만, 납땜이 익숙지 않은 경우, 무리하게 진행하다 핀패드가 뜯겨 나가게 되면, 신호 전달이 되지 않으니, 기존의 핀 배열대로 사용하는 게 좋습니다.

그럼, 나노보드를 PC와 연결하고 코드를 업로드해 볼게요.
코드는 실습 1)의 코드와 동일합니다. 
(auth [ ] /  ssid [ ]  /  pass [ ]  부분을 자신의 것으로 변경하세요)

#define BLYNK_PRINT Serial
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>

char auth[] = "zb7ssO2FlJBdl2nvm1TZ7gcqk9vKMZOd";
char ssid[] = "iPhone6K";
char pass[] = "12345678";

#define EspSerial Serial1
#include <SoftwareSerial.h>
SoftwareSerial EspSerial(7, 6); // RX, TX
#define ESP8266_BAUD 9600
ESP8266 wifi(&EspSerial);

void setup()
{  
  Serial.begin(9600);
  delay(10); 
  EspSerial.begin(ESP8266_BAUD);
  delay(10);
  Blynk.begin(auth, wifi, ssid, pass);
}

void loop()
{
  Blynk.run();
}

 코드 업로드 시에는 esp어댑터 또는 esp-01 모듈을 제거한 상태에서 진행해야 에러가 나지 않습니다. 
같은 코드지만, 이름을 DCmotor 등으로 다른 이름으로 저장해 두고 관리하면 좋습니다.
  프롭이 빠르게 회전하기 때문에, 고정 없이 그냥 사용하기에는 좀 불안하니, 고정을 잘해 놓는 것이 좋겠습니다. 
그래서, 문구점에서 쉽게 구할 수 있는 하드바를 이용해서 고정해 봤습니다.

 아래가 조립이 완성된 모습입니다. 

 그럼, Blynk 앱에서 동작을 위한 버튼 설정을 아래처럼 해보세요. 
프로젝트를 새로 만들어도 되지만, 간단하기 때문에, 실습 1)의 LED 프로젝트에 그냥 추가해 볼게요.
버튼 하나를 추가하고 자리를 잡은 다음 터치하세요.  버튼의 이름은 DC 드론 모터로 해 볼게요.
버튼의 색을 선택하고, PIN에는 드론 모터가 연결된 나노의 Digital 핀번호 D10을 선택해 줍니다.
작동 방식은 우선 누르고 있는 동안만 동작하도록 PUSH 그대로 설정해 볼게요.
그럼, 'OK'를 눌러 설정을 마무리합니다.

 그럼, 주변에 WiFi가 있는 경우 폰과 나노를 WiFi에 접속시키세요.
여기서는 실습 1)과 마찬가지로, 스마트폰의 핫스팟 기능을 이용해서 나노가 WiFi에 접속할 수 있게 하겠습니다.
아두이노 IDE의 시리얼 모니터를 열면, 아래와 같은 접속 과정을 볼 수 있습니다.

위 이미지처럼,  IP주소가 할당되고, ping :  ...ms 속도가 나타나면 네트워크에 잘 접속된 것입니다.
만약 그렇지 않고, 아래처럼 ESP is not responding으로 표시된다면, esp8266의 설정이나 연결에 문제가 있어 esp칩과 통신이 되지 않아 에러가 발생하게 되며 WiFi 통신이 안 됩니다.

이럴 때는, esp-01의 펌웨어 통신속도(9600 bps)와 코드에 있는 속도가(ESP8266_BAUD) 일치하는지 확인해 보세요. 
대개의 경우 esp-01의 펌웨어 통신속도는 9600bps 혹은 115200 bps 둘 중 하나일 가능성이 큽니다. 
만약, 본 게시글에서 제공해드린 펌웨어로 업데이트하였다면, 9600 bps로 맞추면 됩니다.

그리고, esp-01과의 Rx Tx 번호 연결이 제대로 되어 있는지?  실제 회로의 연결 부분을 확인해 보세요.  
이 부분에서 연결이 서로 바뀌어 있을 경우가 많으니 확인해 보세요.
그럼, 앱에서 접속 버튼(▶)을 누른 상태에서,  모터 동작 버튼을 눌러보세요.

자,  (아래) 버튼을 누르고 있는 동안, 드론 모터 프롭이 회전하는 것을 볼 수 있습니다.

그럼, 여기서 접속을 해제하고, 버튼의 속성을 PUSH → SWITCH로 바꾸어 테스트해보세요. 
그러면, 버튼을 한 번씩 누를 때마다, ON / OFF 가 전환됩니다. 
만약, 버튼을 눌러 처음에 동작이 되는 듯하다가 이후에는 버튼으로 제어가 되지 않는 경우가 발생한다면, 모터의 크기(스펙)에 비해 전원 공급량이 부족하거나, 모터와 나노보드에 하나의 전원으로 구성하게 되었을 때, 모터가 돌아가는 순간, 순간적인 보드 전원 공급 부족으로 인해 제어력을 상실하는 경우가 생길 수 있습니다. 
따라서 충분한 전원 공급이 중요하며, 지금처럼, 전원을 별도로 분리해 주면,  모터 진동으로 인한 노이즈 신호가 컨트롤 보드 쪽으로 최대한 흘러들어 가지 않도록 하여, 오동작을 예방할 수 있습니다.
그리고, 한 회로에 두 개 이상의 전원을 넣을 때는 GND는 서로 연결해 주어 기준을 맞추어 주어야 합니다!
네, 이렇게 해서  DC 모터의 한 종류인 드론 모터를 파워 TR을 이용해서 심플하게 제어해 보았습니다.

 

(실습 3) 모터-드라이버 모듈로 DC 모터 구동하기!
이번 실습에서는 모터 드라이버 모듈 활용법과 DC 모터의 정역 제어까지 다루어 보겠습니다.
아래, 이미지가 이번 실습에 사용될 L9110S IC를 사용해서 만든 모터 드라이버 모듈입니다.

 모터 드라이버 모듈에는 여러 종류가 있으며, 모터 용량이나 기타 상황에 맞게 선택하면 됩니다.
모터 하나만 사용할 경우  (아래) A에 연결하였다면, A-1A , A-1B에 신호 라인과 전원을 연결하고,

(아래) B에 연결하였다면, B-1A , B-1B에 신호 라인과 전원만 연결해서 사용하면 됩니다.

 사용하려는 모터와 이를 돌려줄 전원과 드라이버 모듈의 스펙이 서로 맞아야 합니다.
공급 전원(배터리)은 반드시 모터와 모듈의 입력 전압 범위 내에 있어야 합니다.
용량이 다소 큰 모터를 사용하거나, 또는 현재 모터가 돌아가는 힘이 약하다면, 
배터리의 전력(전압보다는 전류가 중요)을 높여주세요
(ex, 9V 사각 배터리는 전압은 높지만 출력 전류가 낮아 모터용 전원으로는 부적합)
필요할 경우, L9110S 모듈의 출력 전류보다 높은 모듈을 사용하세요.

아래의 도면을 보고 연결하세요.

만약 모터가 용량이 적더라도 고속으로 회전하는 모터라면, 작동 시 제어력을 잃을 수 있습니다.
이럴 때는 저속 모터나, 회전 기어가 들어간 모터를 사용해 보세요.
만약, 나노에 연결된 PC USB의 전원만으로도 모터가 힘겹게 돌아간다면, 모터용으로 적합한 보조 전원을 위 연결도처럼  연결해 주세요.



다음 연결도는 RC-Car처럼 좌우 모터 두 개를 사용하기 위한 연결입니다.

따라서, PC와의 연결을 끊고 RC-Car처럼 따로 작동시키려면, 지금처럼 Vin-GND에 전원을 연결해 주면 됩니다.
코드는 앞의 실습 코드와 내용이 같습니다.(위 코드 참조)
그럼, 위 (실습 3) 연결도를 참고하여 연결해 보세요. 
연결 후에는 PC와 연결하고 보드 설정과 포트를 확인 후, 코드를 업로드하세요.
그리고, WiFi에 연결하고, 시리얼 모니터를 열고 접속 네트워크 접속을 확인합니다.
접속이 안 될 경우에는 나노 리셋 버튼을 누르거나 ESP01 모듈을 탈거 후 재연결을 해보세요.
ping 속도까지 표시되면 접속에 문제가 없습니다.  앞서 실습 1)에서 만든 프로젝트를 그대로 사용해도 되지만, 새 프로젝트를 만들어서 진행하는 걸 보여드릴게요.  
프로젝트 이름을 대략 정하고, 보드 선택을 Arduino Nano로 해주세요. 연결 방식은 WiFi로 선택합니다.

 Create Project 버튼을 누르면, 연결된 메일로 토큰이 전송됩니다.

 그럼, E-mail에서 토큰을 복사해서 여기 아두이노 코드의 토큰 부분에 붙여 넣기 하세요.
그리고 다시, 코드를 컴파일 & 업로드합니다.

WiFi 연결에 문제가 있을 경우에는 보드 전원을 뺐다가 다시 연결해 주세요.
그리고 시리얼 모니터를 열어보면, 이렇게 접속에 성공하는 것을 볼 수 있습니다.

그럼, 앱을 열고 동작 버튼을 추가해 볼게요.
IOS와 안드로이드 앱에서 만드는 방식이 살짝 다르지만, 크게 차이 나지 않아 바로 하실 수 있습니다.

여기서 모터의 동작원리에 대해 먼저 설명드리겠습니다.

모터는 화면처럼 'H' 형태의 연결 구조에서 대략 4가지 형태로 제어됩니다.
먼저,
1. 첫 번째 OPEN의 경우를 보세요. 스위치가 모두 열려 있으니, 모터에 동력이 전달되지 않아 멈춰있게 됩니다.
2. 두 번째, Forward의 경우  SW1, SW4가 닫혀 있어, 전기가 VCC(+)에서부터, 모터를 1에서 2로 통과해, GND로 빠져나가며 모터를 회전시키게 됩니다.
3. 세 번째, Backward의 경우  SW2, SW3이 닫혀(연결되어) 있어, 전기가 VCC(+)에서부터, 모터를 2에서 1로 통과해, GND로 빠져나가며 모터를 회전시키게 됩니다.
이때는 전기가 모터에 반대로 통과하므로 회전 방향이 두 번째와 반대가 됩니다.
4. 네 번째 STOP의 경우는 SW1과 SW2에 모두 전원(연결)을 넣는다 하더라도, 전기가 빠져나갈 수 있는 조건이 되지 않아, 첫 번째 OPEN과 마찬가지로 모터가 회전하지 않습니다.
여기까지가 모터 회전과 방향에 대한 기본 원리인데요, H-Bridge 원리로 제작된 ic를 탑재한 모터 모듈을 사용하면 좀 더 편리하게 제어할 수 있습니다.

H-Bridge와 모터 드라이버 ic의 좀 더 상세한 작동 원리가 궁금하신 분은 아래 링크를 참조해 주세요
https://rasino.tistory.com/141

그럼, 모터 하나를 돌리는 상황을 설명드립니다.

(위 이미지) 모터(모듈)를 제어하려면 두 개의 입력(input1 , input2)으로 제어해야 합니다.
input 1 = Low신호 ,  input 2 = Low신호일 경우, 모터는 멈춥니다.
input 1 = High신호 ,  input 2 = High신호일 경우, 모터는 역시 멈춥니다.
 input 1 = High신호 ,  input 2 = LOW신호일 경우, 모터는 예를 들어 시계방향 회전한다면,
input 1 = Low신호 ,  input 2 = High신호일 경우, 모터는 반시계 방향 회전하게 됩니다.

이번 실습에서 사용하는 L9110S 모듈에서 input 1 , input 2는 Motor A 쪽의  A-1A , A-1B에 해당합니다. 
또는 Motor B 쪽의 B-1A , B-1B를 사용해도 됩니다. 


현재 모터 하나를 제어하기 위해 in1과 in2에 해당하는 버튼 두 개를  만들려고 하고 있습니다.

버튼의 이름과 색상은 자유롭게 정하고, 모터가 연결된 핀(D8)을 적어주세요.
버튼의 작동 방식은 스위치형으로 합니다.

완료를 누르고 두 번째 버튼도 동일하게 만들어주세요.  마지막으로, OK를 누르고 버튼을 적당히 배치해 주면 됩니다.

그리고 ,  앱 상단 우측에 있는 앱 작동 버튼()을 누르세요.
esp01 모듈과 제대로 연결되었다면, 연결 정보를 눌렀을 때, Online 표시가 되어 있는 것을 볼 수 있습니다.

그럼, 여기에 모터만 연결해 주면 됩니다.  속도가 빠른 모터보다는 구동 토크를 높이기 위한 기어 결합형 모터를 사용해 주세요.

그리고, 모터와 연결된 전선을 L9110S 모듈의 모터 A 쪽에 연결해 주세요. (연결할 때, 작은 드라이버 필요)

 그래서, 모터 A-1A의  ON 버튼을 누르면, 아래처럼 모터에 연결된 바퀴가 회전하는 것을 볼 수 있습니다. 

버튼 1 또는 버튼 2 둘 중 하나만 On 되었을 때 모터가 회전하며,  버튼 1, 2에 따라 모터 방향이 반대로 바뀌는 것을 볼 수 있습니다.

앞서 모터(모듈)를 제어하기 위해 두 개의 입력(input1 , input2)으로 제어한다는 내용을 참고하세요. 
 input 1 = Low신호 ,  input 2 = Low신호일 경우, 모터는 멈춥니다.
 input 1 = High신호 ,  input 2 = High신호일 경우, 모터는 역시 멈춥니다.
 input 1 = High신호 ,  input 2 = LOW신호일 경우, 모터는 예를 들어 시계방향 회전한다면,
input 1 = Low신호 ,  input 2 = High신호일 경우, 모터는 반시계 방향 회전하게 됩니다.
그리고, 현재 모듈에 보조 배터리 공급 없이 USB 전원만으로 작동하다 보니, 전원 부족으로 USB 연결이 순간적으로 해제되는 소리가 납니다.  그래서 실제 작품을 구성할 때는 보조 전원도 충실하게 넣어 주는 것이 좋습니다.
지금 보이는 것처럼, 버튼 1, 2가 모두 On이 되어도 멈추는 것을 볼 수 있습니다.
그럼, 이제 모터를 하나 더 연결해 볼 텐데요, 2번 모터용 버튼 2개를 추가해 볼게요.

추가 후, 2번 모터(B)의 버튼을 터치(ON)하면 아래처럼 회전이 됩니다.


  만약 버튼 설정은 그대로 두고 회전 방향을 반대로 하고 싶을 경우에는,  방향을 바꾸고 싶은 모터의 연결된 두 가닥을 서로 바꾸어 다시 끼워주면 됩니다.
여기서, 모터 드라이버 모듈을 좀 더 깔끔하게 연결하기 위해, 기존 핀의 납땜 위치를 새로 바꾸어 보았습니다.
만약 모듈이 하나밖에 없거나, 납땜에 익숙지 않다면, 이렇게 하지 마세요. 
인두기의 열이 잘못 오래 전달될 경우, 동박이 떨어져 나가면, 전기 신호가 전달되지 않게 됩니다.

L9110S 모듈 핀을 다시 납땜하여 연결하고 동작시키는 모습

네, 역시 잘 동작되고 있고, 부품 연결이 좀더 심플해졌습니다.

 그럼 여기서 응용 예시로 스마트폰 컨트롤 RC-Car를 최대한 간단하게 만들어 볼게요.
이건, 아두이노 우노와 브레드보드 결합용 아크릴 판인데요, 
가격도 저렴하고, 사이즈도 적당해서 활용해 보겠습니다.

  기타 준비물은, 모터를 고정하기 위한, 폼 양면테이프나, 글루건이 있으면 됩니다.
그 외에 바퀴 뒤쪽을 받쳐줄 용도로 PCB 지지대(서포트)와 RC-Car 용도의 볼 캐스터 같은 것을 준비하세요.

아래와 같은 형태로 양면 폼 테이프를 이용해서 간단히 붙여 볼게요.   물론, 글루건 및 나사 등으로 고정해도 좋습니다.

모터 두 개 연결로 RC-Car를 만드는 과정은 크게 어렵지 않으니 아래 연결도를 보고 조립해 보세요. 

게시글의 모든 이미지는 클릭하면 확대됩니다

RC-Car로 하려면 PC의 USB로부터 전원이 공급되지 않기에,  도면처럼 Vin-GND에 전원을 연결해야 합니다.
RC-Car용 배터리는 AA 건전지, 18650, 2~3셀 리튬이온 배터리 같은 것 중에서 구하기 쉽거나, 충전 편리성,  조립 사이즈 등을 고려하여 선택하면 됩니다.

배터리의 공급 전압은 나노 보드의 권장 입력 전압인 7v~12v 사이만 맞추면 됩니다. 
여기서는, 11.1v 3셀 리튬이온 배터리를 나노 보드에 공급했고, 모터 모듈 전원으로는 다소 전압이 부족하지만, 크기가 작아서 3.7v 리튬폴리머를 사용했습니다.

배터리 연결과 사용법에 대해 궁금한 분은 아래나 더보기 링크를 참고해 주세요
https://rasino.tistory.com/284   ,   https://rasino.tistory.com/304

아래는 조립이 완료된 모습입니다. 

RC-Car 윗면 모습
RC-Car 옆면 모습
RC-Car 밑면 모습

점퍼선을 사용하지 않고, 22 AWG 굵기의 단선을 이용해서 직접 연결했는데요, 장점은, 작품을 만들 때 지저분해 보이지 않으며, 납땜한 것 못지않게, 연결이 오래 유지되어서 납땜 작업 없이 작품으로 만들어 놓기 좋습니다.
자세한 동작 모습은 영상으로 확인해 주세요.


네, 이상으로 (실습 3)과, 모터 드라이버 모듈을 활용하여 WiFi로 RC-Car까지 만들어 보았습니다.


(실습 4) 서보 모터 구동하기!

서보모터를 구동하기 전에 먼저 PWM에 대해 잠시 짚어볼게요. 
[ PWM 개념도 ]
디지털 보드인 아두이노에서는 아날로그 신호(전압)를 출력할 수 없는데요,
아래와 같이 PWM 방식을 이용하여 아날로그 출력을 보내어 LED 밝기 조절과 같은 할 수 있게 됩니다.
마찬가지로 일정한 간격의 PWM 신호를 출력하여 서보모터의 제어신호를 입력해 줄 수 있습니다. 



이번 실습에서는 서보 모터를 WiFi를 통해 핸드폰으로 제어해 볼게요.
가격이 저렴하고 많이 사용되는 180˚회전용 SG90을 사용해 보겠습니다.

이미지를 클릭하면 확대해서 볼 수 있습니다.

서보(모터)의 각도 제어 방법은  모터 구동을 위한 전원을 두 가닥의 전선으로 공급합니다. 
그리고 주황색의 선으로 모터의 회전각을 결정해 줄 신호를 입력하면, 원하는 각도로 움직이게 할 수 있습니다.

그럼, 어떤 신호를 넣어야 하는지 살펴보겠습니다 

서보는 20ms 주기의 신호에서 1~2ms사이의 펄스 신호로 동작하도록 되어 있습니다.
이때, 이 펄스 신호가 1ms이면, 0˚의 위치로 회전합니다.
마찬가지로, 1.5ms 이면 90˚ ,  2ms이면 180˚도로 회전하게 됩니다.
즉, 1~2ms 사이의 펄스로, 0˚~180˚의 각도를 움직이게 합니다.

그런데, 아두이노에서 단순히 PWM 출력 포트로 analogWrite( ) 함수를 사용해서는, 1~2ms의 펄스를 출력하더라도 20ms의 파형 주기를 맞추기 어렵기 때문에, 직접적으로 서보를 돌리기는 어렵습니다.

그래서 대부분의 경우, 아두이노 IDE 설치 때 포함되는 <Servo.h> 헤더 파일을 이용해서 제어합니다.
(단, 주의! <Servo.h>를 사용하면, 메가를 제외한 아두이노 보드류에서는 9번, 10번에서 PWM 출력 안 됨)

아두이노에서는 <Servo.h> 헤더에 포함된 servo.write(각도) 함수를 이용해서 직접 제어할 수 있고, 
(아래) Blynk에서는 이런 형태로 함수를 사용해서 ,
 Blynk앱의 가상 포트(V0)로 입력되는 값을 WiFi로 전달받아 서보의 각도를 제어하게 됩니다.

그럼, 실습을 위해 화면의 연결도를 참고해서 조립해 주세요. 이어서 모터 하나를 더 추가하면서,
우선, 서보 모터 하나를 연결 후, 아래와 같이 실습을 진행하고,  


(아래) 이어서 모터하나를 더 추가하면서, SG90용 팬 틸트 거치대에 조립하여 테스트해 볼게요.


모터를 사용할 때는 기본적으로 전원을 충실히 받쳐 주어야 합니다. 
모터용 전원을 별도로 공급해 주는 것이 제일 좋으며,  만약 연결한 보조 전원이 충분치 못하거나, 아예, 연결하지 못할 경우, 용량이 좀 되는 전해 콘덴서를 + , - 전원에 붙여줄 경우 도움이 될 수 있습니다.

이때, 콘덴서의 + 리드선은 빨간색 +전원에 , - 리드선은 파란색 -전원에 반드시 구분해서 연결해 주세요.

먼저, 서보모터 기본 사용법을 익히고 WiFi 모듈을 추가해 주는 부분으로 구분해서 실습하면, 이해에 도움이 될 텐데요,  그래서 지금 보이는 연결을 그대로 한 상태에서 WiFi 모듈만 탈거 후 실습하면 됩니다.
그럼, 실습 4)의 준비된 코드를 업로드하세요 (servo_180.ino)
서보 모터가 하나 사용된 코드입니다 (servo_180.ino)

#include <Servo.h>     // 전용 서보 라이브러리 사용
#define servoPin 9     // 서보 모터핀을 지정
Servo servo;           // 서보라이브러리 변수를 초기화한다
int pos=0;             // 현재 각도를 저장할 변수를 지정한다
void setup() {
  servo.attach(servoPin); //서보모터가 연결된 핀을 설정
}
void loop() {
  for(pos=0; pos < 180; pos +=1) { // 서보모터의 각도를 1씩 증가
    servo.write(pos);   
    delay(50); 
  }
}

아래 파일을 다운로드하여 실습해 보세요.

servo_180_1.zip
0.00MB


다시 한번, 주의할 것은, WiFi 모듈을 사용하는 실습이 더라도, 아두이노 보드에 코드를 업로드할 때는 
다른 부품(ESP01)의 연결이 영향을 줄 수 있으므로, 연결을 해제하고 업로드하는 것이 좋습니다.
업로드 전, 보드 선택(Nano)과 프로세서 ATmega328P(Oldbootloader) 선택하고, 연결된 포트 (Com xx) 선택을 정확히 해주고 빌드&업로드를 진행하세요.
코드는 0˚~180˚까지 1˚ 단위로 증가하는 형태로 코딩되어 있는데요, 회전 루프가 완료된 후에는 다시 0˚로 돌아와서 반복적으로 증가하게 됩니다.

0˚~180˚까지 1˚ 단위로 증가하는 실습장면

 


그럼, 여기에서 180˚로 회전 후 다시 0˚부터 시작하지 않고 180˚~ 0˚로 거꾸로 한 스텝씩 회전하도록 해 볼게요.

#include <Servo.h>     // 전용 서보 라이브러리 사용
#define servoPin 9     // 서보 모터핀을 지정
Servo servo;           // 서보라이브러리 변수를 초기화한다
int pos=0;             // 현재 각도를 저장할 변수를 지정한다
void setup() {
  servo.attach(servoPin); //서보모터가 연결된 핀을 설정
}
void loop() {
  for(pos=0; pos < 180; pos +=1) { // 서보모터의 각도를 1씩 증가
    servo.write(pos);   
    delay(50); 
  }
  for(pos=180; pos > 0; pos -=1) { // 서보모터의 각도를 1씩 감소
    servo.write(pos);   
    delay(50); 
  }
}

아래 파일을 다운로드하여 실습해 보세요.

servo_180.zip
0.00MB
180˚로 회전 후 다시 0˚부터 시작하지 않고 180˚~ 0˚로 거꾸로 한 스텝씩 회전

네, 천천히 왕복 회전을 잘 합니다. 

그럼, 여기 서보모터를 동작시키기 위한 'Servo.h' 라이브러리 사용법을 참고하면, Blynk를 통해 WiFi로 서보모터를 제어해 보는 코드를 이해하기 쉬울 텐데요, Blynk 코드는 앞서 와 같고 여기에 <Servo.h> 라이브러리와 관련된 부분을 적용해 주면 됩니다.

프로젝트 토큰은(auth [ ]), Blynk앱에서 새 프로젝트가 아닌 이전 프로젝트 화면에서 작성할 경우 기존 토큰을 그대로 사용해야 하고, 새 프로젝트로 만들 경우, 새로 부여받은 토큰으로 변경해 주면 됩니다.
그리고 서보의 신호선(S)이 연결된 Nano 보드의 디지털 핀 번호를 입력하세요. (여기서는 5번 핀)

마지막 부분에는 Blynk 앱에서 서보모터 움직임에 대한 가상적인 값을 입력받아 처리할 BLYNK_WRITE(V0) 함수를 추가해 주면 코드가 완성됩니다.


그럼, 먼저, Blynk App 부분을 처리해 볼게요.
앱은 앞서 실습 4)의 프로젝트를 그대로 이용해 볼게요. 기존 실습 버튼만 삭제하면 됩니다.
만약 새 프로젝트를 만든다면, 화면에 보이는 + New Project 메뉴로 추가해 주면 됩니다.
토큰도 그대로 사용하면 됩니다.  (아래) 해당 프로젝트의 설정 화면을 열어보면 발행된 토큰을 확인할 수 있는데요, 

E-Mail로 전송받아 코드에 복붙복 하면, 오류(오타)를 줄일 수 있습니다.
만약, 다른 토큰을 사용하면 연결되지 않으니 주의해 주세요
그리고, 프로젝트 이름을 변경할 수도 있습니다.
그럼, 위젯 박스 중에서 Slider를 선택하세요. 

슬라이더의 위치를 잡아주고 크기도 적당히 조절합니다.

슬라이더를 터치해서 속성 화면으로 들어가서,  슬라이더의 이름을 적당히 적어주고, 슬라이더의 색상을 정하고,
핀 설정에서는 나노의 디지털 핀의 입출력을 High/Low형태로 직접 제어하는 것이 아니기 때문에,  그래서 슬라이더 이미지의 움직임에 대한 가상적인 값을 전달해야 하기에 가상 포트(V0)를 선택합니다. 
그리고 V0 값에는,  SG90 서보의 스펙상으로는 0˚~180˚라고 할 수 있으나, 실제적으로는 양쪽 끝으로 움직일 수 없는 각도가 존재하기에, 여유 있게 10˚~170˚ 범위를 입력해 볼게요.  소수점은 나타내지 않음으로 선택(#) 합니다.
지금까지의 슬라이더의 설정 사항은, 아래 이미지를 참고해 보세요. 


설정이 완료되면 OK를 누르고, 나노보드에 코드를 업로드해 볼게요.
서보모터 하나를 작동시키는 코드는 아래와 같습니다.(auth [ ] /  ssid [ ]  /  pass [ ]  부분을 자신의 것으로 변경하세요)

#define BLYNK_PRINT Serial
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <Servo.h>
Servo myServo;
char auth[] = "sUGb7eRobEWFokdZ7TeQjo3NcwxTO_BJ";
char ssid[] = "iPhone6K";
char pass[] = "12345678";
#include <SoftwareSerial.h>
SoftwareSerial EspSerial(7, 6); // (RX→8266TX에 연결, TX→8266RX에 연결)
#define ESP8266_BAUD 9600
ESP8266 wifi(&EspSerial);
void setup()  {
  Serial.begin(9600);
  delay(10);  
  EspSerial.begin(ESP8266_BAUD);
  delay(10);
  Blynk.begin(auth, wifi, ssid, pass);  
  myServo.attach(5);   // 서보의 신호선(S)이 연결된 Nano의 D5번 핀
}
void loop()  {
  Blynk.run();
}
BLYNK_WRITE(V0) {
   myServo.write(param.asInt());
}

BlynkServoOne_nano.zip
0.00MB




코드를 업로드할 때는 esp-01 모듈의 연결을 해제하고 하세요.(esp01 모듈만 어댑터에서 잠시 뽑아 놓으면 됩니다.)

나노 보드 설정과 통신 포트를 확인 후 업로드 버튼을 누르세요.

① 업로드가 완료되면, 다시 모듈을 연결하고, 전원을 연결하세요.
② 스마트폰의 핫스팟을 켜서 접속시키세요.(또는 접속 가능한 주변 WiFI, 단 해당 WiFi의 ID와 Pass가 코드에 등록되어 있어야 함.)
③ 접속 상태를 확인하기 위해 시리얼 모니터를 엽니다.
④ 보통의 경우 리셋 버튼을 한 두 차례 눌러주면 제대로 연결이 됩니다.
⑤ Ping 테스트까지 뜨는지 확인(뜨면 접속이 제대로 된 것)

만약, 핫스팟(WiFi) 접속이 안 될 경우,  폰의 핫스팟을 껐다가 다시 키면서, 나노의 리셋 버튼도 눌러보세요.
⑥ WiFi 또는 핸드폰의 핫스팟에 접속되었다면, Blynk 앱을 열고 연결 버튼()을 눌러 주세요.

만약, 연결에 문제가 없는데도 동작이 안 되는 경우가 있는데요, 브레드보드의 특성상, 접촉이 불안정할 수 있으니 접촉이 잘 되도록 연결 핀을 잘 눌러주거나 만져주세요.
⑦ 슬라이더의 바를 오른쪽 왼쪽으로 옮겨보면 슬라이더의 위치(값)에 따라 무선 WiFi로 연결된 서보모터가 회전하는 것을 볼 수 있습니다.

비록 작은 모터지만 이렇게 WiFi로 제어된다는 것은 의미가 큰데요,  큰 규격의 서보모터를 사용하고, 전원만 받쳐 준다면, 원격에서 더 큰 힘으로 무언가를 작동시킬 수 있다는 뜻이 됩니다.

그럼, 서보모터 하나를 더 추가해 볼 텐데요,  활용성이 좋은 팬 틸트를 적용해서 동작시켜 볼게요.
팬틸트는 두 개의 서보를 사용해서 상·하 좌·우로 움직일 수 있도록 해주는 거치대인데요, 주로 소형 카메라를 올려서 주변을 확인할 수 있는 용도로 활용됩니다. 

 자세한 조립은 본 게시글 끝에 있는 영상을 참고하세요.
그럼, 조립된 팬 틸트를 가지고 연결해서 동작시켜 볼게요. (만약, 팬 틸트가 없는 경우는 그냥 서보 모터 두 개만 놓고 회전을 테스트해 보면 됩니다.)

회로 연결은 다시 아래 연결도를 참고하세요. 

프로그램 코드는 앞서 실습한 코드에서 화살표 부분을 추가해 주면 됩니다 (더보기 파일 링크)

서보모터 두 개를 작동시키는 코드는 아래와 같습니다.(auth [ ] /  ssid [ ]  /  pass [ ]  부분을 자신의 것으로 변경하세요)

#define BLYNK_PRINT Serial
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <Servo.h>
Servo myServo1, myServo2;
//  auth[ ] /  ssid [ ]  /  pass [ ]  부분을 자신의 것으로 변경하세요
char auth[] = "sUGb7eRobEWFokdZ7TeQjo3NcwxTO_BJ";
char ssid[] = "iPhone6K";
char pass[] = "12345678";
#include <SoftwareSerial.h>
SoftwareSerial EspSerial(7, 6); // (RX→8266TX에 연결, TX→8266RX에 연결)
#define ESP8266_BAUD 9600
ESP8266 wifi(&EspSerial);
void setup()  {
  Serial.begin(9600);
  delay(10);
  EspSerial.begin(ESP8266_BAUD);
  delay(10);
  Blynk.begin(auth, wifi, ssid, pass);
  myServo1.attach(3);   // (esp-01의 GPIO 2번 핀)
  myServo2.attach(5);   // (esp-01의 GPIO 2번 핀)
}
void loop() {
  Blynk.run();
}
BLYNK_WRITE(V0) {
   myServo1.write(param.asInt());
}
BLYNK_WRITE(V1) {
   myServo2.write(param.asInt());
}

BlynkServoTwo_nano.zip
0.00MB


코드 업로드까지 하였다면, Blynk 앱에서 슬라이더 B를 하나 더 추가해 주면 됩니다.
두 번째 서보모터 B  제목과 색상을 적당히 적어주세요. 서보 범위 각도 값 [ 10~170 ]을 입력해 주세요.
핀의 방식은 Virtual  V1으로 합니다. (V0가 1번 서보용)
데이터 표시 소수점 자릿수는 이렇게 설정할 수 있는데요.
여기서는 소수점 이하 자리는 없는 것(#)으로 합니다.

코드 전송을 위해 ESP-01 모듈을 잠시 탈거해 주세요.  
 코드를 업로드하고 스마트폰 핫스팟으로 WiFi 접속시키기 위해 , 모듈을 다시 연결합니다.
스마트폰 핫스팟으로 WiFi 접속 시키기 위해 , 모듈을 다시 연결합니다.
앱 실행 버튼(▶)을 누르고 서보 1과 2의 슬라이더를 각각 움직여 보세요.

네, 아주 잘 동작되는데요,  이런 팬 틸트에 아래처럼 가메라 모듈이나 카메라가 달린 ESP32-CAM 같은 것을 올려놓고 활용할 수 있습니다.
  그래서,  카메라 방향 제어를 원격으로 할 수 있게 됩니다. 
이상으로 실습 4) 서보모터를 WiFi로 구동해 보는 실습을 진행하였습니다.

이번 실습은 전등을 WiFi로 제어해 보는 실습입니다.

LED를 WiFi로 제어할 수 있다면, 220V 높은 전압의 전등이라도 제어가 가능합니다.
바로, 릴레이라는 모듈을 사용하면 되는데요,

220V의 높은 전압으로 돌아가는 회로와 5V의 아두이노 회로를 분리해서 동작시킬 수 있어 회로를 보호하면서 낮은 전압으로 높은 전압을 제어할 수 있게 해 줍니다.
그럼, 전등 연결 부분을 자세히 설명드립니다.

전등에 불이 들어오게 하는 구조는 매우 단순한데요, 화면처럼 단순히 220V 코드선을 연결해 주면 됩니다.
그런데 전등과 코드선을 좀 더 쉽게 연결시키기 위해서는 리셉터클이라 불리는 전등 소켓을 이용하면 전선과 쉽게 연결할 수 있습니다. 
소켓의 캡을 돌려 열면 나사로 된 전선을 연결할 수 있는 부분이 나오는데요.

소켓 아래쪽 구멍으로 전선을 넣어 빼내고 나사를 살짝 풀어 그 부분에 전선을 감으면 됩니다.

220V 코드선을 연결하고 램프를 돌려 끼워주면 됩니다.

만약 접지선이 있는 3가닥 코드선이라면 접지선(노란색 바탕의 녹색띠)을 제외하고 연결하면 됩니다.
그리고 릴레이를 두 선 중 아무 선이나 화면처럼 중간에 연결하여 릴레이를 통해 전선을 연결하거나 끊는 스위치로 작동시켜 전등을 On/Off 하게 됩니다.

이제 다시 전체 연결도를 살펴보고 조립해 보세요.
회로에 사용된 릴레이의 스펙입니다.
5V로 동작되는 릴레이며, 릴레이 하나당 교류 250V/10A 또는 직류 30V/10A 이하까지는 허용됩니다.

VCC-GND에는 5V 가량의 전기를 공급하여 릴레이가 동작할 수 있게 하는 것이며, 

아두이노를 통해 IN 핀으로 Low신호(Low level trigger 릴레이 사용 시)가 입력된다면 
평상시 릴레이의 공통 단자인 COM 단자가 ↔ NC와 연결되어있던 것이 해제되면서 COM ↔ NO 단자로 연결이 바뀌게 됩니다.
코일을 이용한 전자석의 원리로 작동시키기 때문에 NC , NO , COM 단자 쪽에 220V 전기가 흘러도 아두이노 쪽에는 전혀 문제가 되지 않습니다.

만약, 하나 이상의 기기를 각각 제어하고 싶다면 릴레이 모듈 수를 늘리면 되는데요, 릴레이 두 개를 합쳐 놓은 2 채널 및 4 채널, 8 채널, 16 채널 등의 모듈 제품을 활용할 수 있습니다.

전등 WiFi 제어에 사용된 아두이노 코드입니다. 
실습 1~3)의 코드와 같습니다. 

/* 라즈이노 IoT ESP-01 풀코스 학습 : (실습5)전등 WiFi 제어하기 
 * 실습 회로 및 준비물과 영상은 링크를 참고하세요
 * https://rasino.tistory.com/335                    */
#define BLYNK_PRINT Serial
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
char auth[] = "sUGb7eRobEWFokdZ7TeQjo3NcwxTO_BJ";    // Blynk 앱의 프로젝트에서 발급된 토큰을 입력하세요
char ssid[] = "iPhone6K";   // WiFi 이름을 입력하세요
char pass[] = "12345678";   // WiFi 비번을 입력하세요
#define EspSerial Serial1
#include <SoftwareSerial.h>
SoftwareSerial EspSerial(7, 6); // RX, TX
#define ESP8266_BAUD 9600
ESP8266 wifi(&EspSerial);
void setup()
{
  Serial.begin(9600);
  delay(10);
  EspSerial.begin(ESP8266_BAUD);
  delay(10);
  Blynk.begin(auth, wifi, ssid, pass);
}
void loop()
{
  Blynk.run();
}

05_BlynkNano_esp01_Lamp.zip
0.00MB

Blynk 서비스는 복잡한 코드 처리 부분은 라이브러리와 Blynk 서버를 통해 해결하기 때문에, 
코딩에 큰 어려움 없이 앱으로 동작되는 스마트 기기를 쉽게 만들 수 있는 것이 장점입니다. 
그럼, 이제 하드웨어를 조립하고 동작시켜 볼게요.
220V를 사용하는 만큼 작품을 안정적으로 고정시켜주는 것이 중요한데요, 아크릴판 2개에 고정해 보았습니다.

전구를 끼울 때는 너무 힘주어 끼우지 않도록 하세요.

LED 전구도 가능하며, 소켓과 규격만 서로 맞추면 됩니다.
우선, 코드를 업로드하기 위해 ESP모듈을 탈거합니다.
나노 보드의 통신 포트와 설정(Old Bootloader)등을 확인하고 코드를 업로드하세요.

업로드가 완료되면 모듈을 다시 연결하고, 플러그를 콘센트에 연결합니다.
주변 WiFi 또는 핫스팟을 사용하여 나노-ESP 회로가 IP를 할당받도록 합니다.
아두이노 IDE의 시리얼 모니터를 열어 WiFI접속을 확인합니다.
아래처럼 회로에 연결된 D10포트를 Blynk앱에서 설정해 주면 됩니다.

동작 버튼(▶)을 누르고 스위치 버튼을 누르면 아래처럼 무선 WiFi를 통해 전등이 켜지(꺼지)는 것을 볼 수 있습니다. 
제작에 사용된 릴레이 타입이 Low level trigger 릴레이어서 On Off 표시와 반대로 작동하고 있는 모습인데요.
아래 그림에서 0을 1로,  1을 0으로 바꾸어 주면 On Off 작동을 반대로 바꿀 수 있습니다. 

멈춤 버튼을 누르고, 누르고 있는 동안 유지되는 PUSH 스위치로 바꾸어 볼 수도 있습니다.
그럼, 기존 실습 1)에서 연결하였던 LED1, 2와 함께 작동시켜 볼게요. 

 

끝으로, 220V 가전제품도 WiFi로 제어가 가능한데요,
※ 지금 이어서 소개하는 영상은 감전에 노출될 수 있으니 반드시 주의해 주세요!
이런 전기류에 대한 경험이 부족한 경우 참고용으로 봐주세요.

제품의 전원코드에 손을 대지 않고 편하게 활용할 수 있는 방법을 설명드립니다.
또한, 접지를 사용할 수 있도록 해주는 것이 전자제품도 보호할 수 있고 전기 감전이 되지 않도록 해주는데요,
예를 들어, 믹서기를 사용하고서 플러그 부분을 만지다 감전되어 깜짝 놀라는 경우도 접지를 통해 믹서기 내부에 저장된 전기를 흘려보내지 못했기 때문에 발생합니다.
아래 전원 코드를 잘라 보면 3색의 전선이 나오는데요,  갈색, 파란색 선이 실제 전기가 흐르는 선이며 노란색과 녹색 줄이 함께 있는 선이 접지와 연결된 접지선입니다.

이런 접지가 되는 전원 케이블과 콘센트(멀티탭)를 이용해서 IoT 콘센트를 만들어 봤습니다. 
220V 라인에 직접 손이 닿아 감전이 되지 않도록 마감(절연) 처리를 잘해주어야 하며,  전원 코드 줄이 당겨졌을 때, 합선이 되지 않도록 고정에도 신경을 써주어야 합니다. 

 케이스를 열어 연결된 것을 살펴보면, 아래와 같은 위치에 접지선을 연결하면 됩니다. 나머지 두 선은 좌우 상관없이 연결하세요. (그림과 같은 2구 콘센트의 경우임)   

그리고 내부를 보면 콘센트 두 곳이 서로 연결되어 있기 때문에,  콘센트에 전기 제품 두 가지를 연결할 경우 동시에 On/Off 되는 점 참고하세요.
릴레이 아래쪽은 220V 고압이 흐르기 때문에 직접 접촉이 되지 않도록 최대한 마감에 신경을 써주어야 합니다.
나노의 경우, USB 포트로 전기를 공급받지 않을 때는 Vin ↔ GND 포트로 공급해 주면 되는데요, 6V~12V 전압과 충분한 전류를 공급해 줄 수 있는 전원으로 공급해 주세요.
여기서는 3.6V 18650 2개를 직렬로 사용하여 7.2V를 입력해 주고 있습니다.
9V 사각 건전지의 경우, 전압이 높더라도 출력 전류가 약한 타입이어서 전원으로 사용하면 배터리가 금방 닳거나 동작이 잘되지 않습니다.
가전제품의 예시로 USB 선풍기를 어댑터를 이용해 테스트해 볼게요. 
이때 선풍기의 전원은 작동하면 바로 동작될 수 있도록 On으로 해두어야 합니다. 
그리고 나노보드에 전원을 연결하고, 주변 WiFi 혹은 폰의 핫스팟에 연결시킵니다.
당연히 아두이노 코드에 입력해 놓은 ID/Pass의 WiFi로 연결해야 합니다. 
기존에 있던 버튼은 지우고 다른 스타일의 버튼을 사용해 볼게요. 
버튼 설정은 앞서 와 동일한 방법으로 설정합니다. 
그럼, Play 버튼을 누르고 동작 버튼을 눌러볼게요.   

비록 미니 선풍기이지만 실제 220V 전기와 콘센트를 이용하기 때문에 220V를 사용하는 전기 전자 제품 사용이 얼마든지 가능합니다.
다만, 콘센트 1구를 사용하든, 2구 모두 사용하든 릴레이 모듈의 최대 허용 전력 아래로만 사용해야 합니다.
( ※콘센트 2구 소비전력 합이 릴레이의 스펙인 교류 250V/10A 또는 직류 30V/10A 이하 제품만 사용해야 합니다)

미니 선풍기만 보여드리기 아쉬워서 실제 선풍기를 함께 작동시켜 볼게요.

네, 지금까지 전등과 가전기기를 스마트폰으로 제어해 보는 실습을 진행했습니다.

(실습-6) 온습도 스마트폰에 표시하기!

이번 실습에 사용될 DHT11 온도/습도 겸용 센서 모듈입니다.
가격이 저렴하고 온도와 습도까지 측정할 수 있어 많이 활용되는 센서입니다.
특징으로, 데이터 출력(측정) 주기가 최소 2초 이상이기 때문에 코드를 작성할 때 데이터 샘플링 주기를 2초 이상으로 해주면 좋습니다.
4핀의 DHT11 센서에 데이터 출력을 위한 저항이 연결된 3핀의 모듈을 사용하는 것이 훨씬 편리합니다. 

여기서는 DHT11 센서 사용을 위해 DHT.h 라이브러리를 사용합니다.
[ 라이브러리 다운로드 ]

DHT.zip
0.00MB

만약, 소수 첫자리까지 출력되는 좀 더 정밀한 센서가 필요하다면, 지금 소개하는 DHT22 센서를 사용하세요.
DHT22 센서는 0.1℃ 단위로 표시되며, 온도/습도 측정 범위도 DHT11보다 넓습니다. 

다만, DHT22센서 가격이 DHT11보다 두 배 정도 비싸고 DHT11 센서만으로도 충분히 활용하기 좋기에 DHT11 센서가 대체적으로 많이 사용되고 있습니다.
아래는 DHT11 센서와 연결된 이번 실습 도면입니다.

마찬가지로, ESP-01 어댑터를 이용해서 연결하는 것이 편하고 좋습니다.
만약 어댑터가 없더라도, 영상 초반에 나오는 Break-Out 소켓을 이용하거나, 소켓 없이 직접 ESP-01을 연결해도 되지만, 전압 레벨 변환을 위한 저항을 연결해야 하기에, 연결이 다소 번거로워질 수 있습니다.
연결이 다소 번거로워질 수 있습니다. 

앞서 보여드린 것처럼, 브레드보드에 꽂기 좋도록 핀의 납땜을 새로 했습니다. 

물론, 기존 핀 모양대로 연결해도 무방합니다.

코드 작성을 위해 앞서 언급한 "DHT.zip" 라이브러리를 다운로드하고 아두이노 IDE에서 .ZIP 라이브러리 추가를 하거나,  문서 폴더 아래 》 아두이노 폴더 》 라이브러리 폴더 아래에 압축파일을 풀어놓은 폴더 그대로 복사해 넣어도 됩니다. 
아래는 【 온습도 센서 표시하기의 아두이노 코드】입니다. 

/* 라즈이노 IoT ESP-01 풀코스 학습 : (실습6)폰으로 온·습도 값 전달받기 with Blynk
 * 실습 회로 및 준비물과 영상은 아래 링크를 참고하세요~ OK!!!
 * https://rasino.tistory.com/335                    */
#define BLYNK_PRINT Serial    
#include <ESP8266_Lib.h>
#include <BlynkSimpleShieldEsp8266.h>
#include <DHT.h>

// 아래 auth [] , ssid [] , pass [] 는 자신의 것으로 바꾸어 입력하세요.
char auth[] = "sUGb7eRobEWFokdZ7TeQjo3NcwxTO_BJ"; //Blynk 프로젝트 토큰 
char ssid[] = "iPhone6K";  // WiFi ID 입력하세요
char pass[] = "12345678";  // WiFi 비번을 입력하세요
#include <SoftwareSerial.h>
SoftwareSerial EspSerial(7, 6); // (RX→8266TX에 연결, TX→8266RX에 연결)
#define DHTPIN 4          
#define DHTTYPE DHT11  
#define ESP8266_BAUD 9600
ESP8266 wifi(&EspSerial);
DHT dht(DHTPIN, DHTTYPE);
void setup() {
  Serial.begin(9600); 
  delay(10);  
  EspSerial.begin(ESP8266_BAUD);
  delay(10);
  Blynk.begin(auth, wifi, ssid, pass);
  dht.begin();
}
void sendSensor() {
  int t = dht.readTemperature(); // 섭씨 온도, 화씨는 readTemperature(true)
  int h = dht.readHumidity();
  Serial.print("Temp:");
  Serial.print(t);
  Serial.print("\t");
  Serial.print("Hum:");
  Serial.print(h);
  Serial.print("\n");
  delay(300);
  Blynk.virtualWrite(V2, t);  // 온도값 전달을 위한 V2 가상포트 설정
  Blynk.virtualWrite(V3, h);  // 온도값 전달을 위한 V3 가상포트 설정
}
void loop() {
  sendSensor();
  Blynk.run();
}

[ 코드 다운로드하기 ]

06_esp01_DHT11.zip
0.00MB

코드에서는 온·습도 값을 시리얼 모니터로도 확인할 수 있도록 하였으니,  먼저, 온·습도 데이터가 제대로 나오는지 시리얼 모니터를 통해 확인하면 좋습니다. 

그리고, (아래) Blynk 앱으로 데이터를 전달하기 위해서는 virtualWrite( V2 , t ) 함수에 가상 포트(V2)를 하나 지정해서 전달하게 됩니다. 

물론, 전달할 데이터는 온도와 습도 두 가지이므로, V2 , V3에 대해 각각 함수를 선언합니다.
그럼, 업로드를 위해 esp01 모듈과 DHT11 센서 모듈을 잠시 분리하고, 나노를 연결하고 포트 설정을 확인한 뒤에 코드를 업로드해 주세요.
업로드 완료 표시가 뜨면, 다시 esp 모듈과, DHT11 센서 모듈을 연결해 주세요.
앞서 언급한 것처럼, 모듈이 연결된 상태에서는 코드 업로드에 영향을 주게 되어 업로드 시, 에러가 날 수 있습니다.

그럼, WiFi에 접속시켜 보겠습니다.  아두이노 IDE의 시리얼 모니터를 여세요.
(아래) Ping 테스트까지 완료되었다면, WiFi 접속이 잘 되었다는 뜻입니다.


이어서, 온도와 습도 데이터가 시리얼 모니터를 통해 출력되고 있는데요, 


이 데이터를 WiFi를 통해 Blynk서버로 보내고,
한편, 스마트폰의 Blynk앱에서는 Blynk서버에 올라오는 데이터를 불러와 앱으로 보여주게 됩니다. 
그럼, 실습 5)에서 사용한 Blynk 프로젝트에서 계속 사용해서 작성해 보겠습니다.
먼저, 프로젝트 제목을 '온·습도 표시하기'로 바꾸어 볼게요.
그리고 기존에 있는 버튼들을 삭제해 주세요.
위젯 항목 중에서 Guage를 선택하세요. 
온도 값 출력을 위한 게이지를 만들 건데요, 그래서 제목을 온도로 적습니다. 
그리고 온도 값이 입력되는 가상 포트 V2로 지정하고 게이지 범위는 센서가 표시할 수 있는 범위를 약간 상회하는 정도로 설정하면 되는데요, 여기서는 -20˚ ~ 60˚ 정도로 해놓을게요. 


이어서 습도에 대해서도 동일한 방법으로 게이지를 만들어 주세요. 
습도는 V3로 지정해서 0%~100% 범위로 지정하면 됩니다. 
센서 값 샘플링 주기는 DHT 센서가 제공할 수 있는 최소 주기인 2초 이상으로 설정하면 됩니다.


그리고, 차트 형태도 표시하기 위해 SuperChart 위젯도 넣어 볼게요. 

적당한 제목을 적고, 표시할 항목에,  온도 항목에 대한 이름과 설정을 진행합니다. 
℃ 표시는 조금 후에 웹브라우저를 통해서 특수문자 ℃를 복사 후 붙여 넣어 볼게요. 
항목을 추가하여 습도에 대해서도 설정을 해주세요. 
화면에는 안 보이지만 특수문자 ℃를 복사했고, 붙여 넣기 하고 있습니다. 

OK를 누르고, 설정이 완료되었으면 '▶' 버튼을 눌러볼게요.
그럼, 이렇게 센서의 온도와 습도 값이 전달되는 것을 볼 수 있습니다.

센서를 손으로 감싸 쥐거나 하여 습도와 온도 값의 변화가 잘 적용되는지? 확인해 보세요.
이번엔 좀 더 확실하게 가습기를 이용해서 습도를 높여 볼게요. 


네, 습도와 온도 변화가 잘 적용되고 있습니다. 
그리고 아래처럼, SuperChart의 전체 보기를 누르면, 

이렇게 전체 화면으로 크게 볼 수 있고, 앞뒤로 스크롤하여 데이터를 확인해 볼 수 있습니다
'···'을 눌러보면 CSV 파일로 저장할 수 있는 메뉴가 나오는데요,  CSV 파일은 쉼표를 기준으로 항목을 구분하여 저장한 데이터 형식으로 엑셀로 열면 셀로 구분되어 열리기 때문에 데이터를 처리하기에 매우 좋습니다.

(아래) 이렇게 Blnyk에 연결된 메일 계정으로 CSV 파일이 전송됩니다.

받은 파일을 컴퓨터에서 열어볼게요.
그럼 이렇게, '. gz'의 압축파일 형태로 되어 있으니 다운로드하여 압축을 풀어 주어야 합니다.

PC에서 앞축을 풀고, 엑셀, 워드패드, 메모장 등으로 열어볼 수 있습니다. 
이 파일을 온도 데이터를 열어본모습이고요, 습도 데이터도 열어서 활용할 수 있습니다. 

  
 그럼, 활용성을 높이기 위해,  PC와 연결을 해제하고 배터리로 작동할 수 있는 것을 보여드릴게요.
전원은 앞서 보여드린, 18650이나, AA 건전지를 사용할 수 있으며, 아두이노 나노에 권장 입력 전원(7v~12v)만 맞추어 주면 됩니다. 
 여기서는, 무선 RC 기기에 많이 활용되는 리튬이온 배터리를 사용해 볼게요.
이 배터리는 배터리 셀 3개가 결합된 3셀 리튬이온 11.1 V (3.7v X 3) 배터리입니다.  
커넥터 종류에 따라 필요한 형태로 선택할 수 있습니다.
만약, 커넥터 종류가 맞지 않다면 변환젠더를 이용할 수도 있습니다.

  현재, 브레드보드에 꽂기 편하도록 PCB핀헤더 작업을 하였습니다.
선과 핀을 납땜하고 노출된 연결 부위는 열수축 튜브(Or 전기테이프)로 마감 처리를 해주면 좋습니다.
배터리 연결은 아두이노 나노의 Vin핀에 ⨁,  GND핀에 ㊀를 연결하면 됩니다. 

 그럼, 핫스팟을 켜서 접속시켜 볼게요. 
접속 표시가 뜨는 것을 확인하고 앱을 실행시켜 보세요.
실행 버튼()을 누르세요.

가습기 및 히터 등으로 온도의 변화를 주면 아주 잘 작동하는 것을 볼 수 있습니다. 

이런 형태로 배터리를 연결하여 무선으로 특정 위치의 온습도 데이터를 스마트폰으로 편리하게 확인할 수 있습니다.
그럼, 마지막으로 각각의 원격 모듈을 앱에서 하나로 만들어 동시에 제어해 볼게요.
하나로 합쳐볼 모듈은 ①WiFi 전등과  ②WiFi 콘센트  ③ 온습도 측정 모듈입니다.
(아래) 현재 3가지 WiFi 작품들이 모두 스마트폰 핫스팟에 연결되어 있습니다.

전구도 요즘 많이 사용되고 있는 LED 등으로 바꾸었습니다. 

네, ① WiFi (LED) 전등이 잘 작동되고 있습니다.

 

② WiFi 콘센트 작품에 연결한 가전기기도 잘 작동합니다. 


③ WiFi 온습도 측정 장치도 직접 열이 나 가습을 해보면 잘 작동합니다. 

동시에 세 가지 모두 작동시켜도 문제없습니다. 


이렇게 해서, ESP-01 모듈과 Blynk 활용을 위한 실습을 풀코스로 진행해 보았습니다.
마지막에 하나의 앱으로 보여드린 3가지 장치는 지금 당장 생활 속 IoT 기기로 활용하기에 아주 좋은 예시입니다.
그럼, 여러분만의 IoT 기기를 만들어 활용해 보세요.

감사합니다 
이상 라즈이노 IoT 였습니다~



 

 

 

반응형
반응형

 이번 시간에는 아두이노 라이브러리에 관해 살펴볼까 합니다.
특히, 아두이노 라이브러리 설치 경로 ,  아두이노 라이브러리 에러, 아두이노 라이브러리 추가 방법 등 아두이노 라이브러리 관련된 개념을 종합적으로 정리해 보겠습니다.

아두이노는 전자 관련 분야뿐 아니라, 이공계 및 비전문 분야인 인문계 등 전분야에서 두루 활용되고 있습니다.
특히 대학 같은 곳에서 졸업논문 대신 창의적 종합설계 능력을 반영한 캡스톤 디자인 작품을 만드는 것에도 아두이노가 많이 활용되고 있습니다.
 그만큼 비전공자도 접근하기 쉽고 빠른 시간 내에 수준 있는 작품을 만들어 낼 수 있기 때문에 인기가 높은데요, 
이를 가능하게 해주는 것이,
1. 하드웨어적으로는 주요 회로 부품의 모듈화를 들 수 있겠습니다. 
  : 예를 들어 예전에는 초음파 센서를 이용한 장애물 회피 RC카를 만든다고 할 때,  수십 개의 전자부품을 이용해서, 초음파 센싱 회로, 모터 구동회로, 마이크로 프로세서 보드 등을 직접 만들어야 했고, 각각의 회로 동작을 검증한 다음, 회로들을 연결하여 동작이 잘 되는지 등 관련 전공자도 제법 많은 시간과 쉽지 않은 과정을 거쳐야 만들 수 있었다면, 
이젠 이런 각각의 회로들을 모듈로 제품화 하였기에 쉽게 각 모듈을 구매 후 연결만 하면 동작이 잘되기 때문에 전자부품 및 회로에 대한 이해의 깊이가 없더라도 충분히 다룰 수 있게 된 것이 하나의 이유가 되겠습니다.  

두 번째로,
2. 소프트웨어적으로 간단하게 코딩 할 수 있도록 다양한 라이브러리가 제공되며,  심플하면서 강력한 IDE툴 무료 제공.
 : 소프트웨어적으로 예전에는 각각의 모듈 회로들을 제어하고 통제하는 코드를 일일이 작성하고 전체 코드를 연결 작성해야 하는 코딩의 어려움이 있었다면,  이제는 제품화된 모듈들의 어려운 제어 코드들을 제조사 또는 유저 그룹 등에서 모듈화 하여 라이브러리로 제공되고 있기 때문에, C 또는 C++ 언어의 기초만 알고 있어도 쉽게 코딩이 가능하다는 것이 아두이노 활용의 큰 매력이며, 장점이라고 말할 수 있습니다. 

 하지만, 아두이노를 시작하고 가장 크게 부딪히는 문제가 바로, 라이브러리 관련 에러라고 할 수 있습니다.

그리고 사실 아두이노에서는 하드웨어 못지 않게 하드웨어를 컨트롤하기 위한 소프트웨어 특히 라이브러리를 관리하고 다루는 것이 매우 중요합니다. 
 따라서 다음의 주요 주제에 대해 알아두면, 아두이노를 활용할 때 부딪히는 문제에 대해 쉽게 해결할 수 있을 것입니다.

 
 [ 1. 아두이노 IDE 표준 라이브러리의 설치 위치 / 경로 파악하기 ]

 아두이노를 사용하기 위해 처음 설치하는 프로그램이 아두이노 IDE입니다.
 아두이노 IDE는 통합개발 환경툴(Integrated Development Enviroment)로서  코드 편집 기능, 컴파일러, 코드 업로더 등이 합쳐진 툴로서 인터페이스가 매우 심플해서 접근하기 쉽고 사용하기에도 아주 편리한 툴입니다.

 아두이노 IDE를 처음 설치하게 되면, 윈도기준으로  C:\Program Files (x86)\Arduino 경로로 설치가 되며,


표준 라이브러리라 하여 기본적으로 설치되는 라이브러리가 있습니다.  C:\Program Files (x86)\Arduino\libraries

표준라이브러리 및 임의 추가된 라이브러리 위치

IDE 설치 버전에 따라 표준라이브러리가 다를 수 있으며, 위·아래 이미지의 경우 일부 사용자 임의로 추가된 것도 포함되어 있습니다. 

표준 라이브러리 위치

 

[ 2. 아두이노 라이브러리 추가하기 / 라이브러리 위치 파악하기 ]

 아두이노에는 엄청나게 많은 모듈들이 있고 이 모듈들을 사용하기 쉽게 라이브러리를 제공하고 있습니다. 
따라서 IDE 설치 이후에 이런 라이브러리를 추가하게 되는데요, 추가할 라이브러리의 설치 위치는 기본적으로 문서 폴더에 설치됩니다.
C:\문서\Arduino    또는  C:\Document\Arduino

 

 

따라서, 아두이노의 경우 설치될 때 표준 라이브러리가 설치되는 곳과 추가 사용자 라이브러리가 설치되는 곳 등 2곳이 존재합니다.     만약 두 곳 모두에 동일한 이름의 라이브러리가 설치될 경우,  해당 라이브러리가 포함된 아두이노 코드를 컴파일할 때 모두 인식되어 충돌 에러를 발생시키게 됩니다. (충돌 해결법은 아래에 소개)


 [ 3. 아두이노 라이브러리 추가하는 3가지 방법 ]


   ① 라이브러리 매니저를 통하여 라이브러리 검색 후 설치하는 방법 :
      아래 이미지의 메뉴 중에서 라이브러리 관리... 를 선택합니다


 아래 이미지의 라이브러리 매니저 검색창에서 원하는 라이브러리를 검색하고 버전 선택을 할 수 있으며 설치 버튼을 누르면 라이브러리가 자동으로 선택됩니다.  (라이브러리 검색 시 이름을 일부만 입력하면 해당 철자가 들어간 모든 라이브러리를 검색해 줍니다)

      이때, 설치되는 파일 위치는 사용자 문서 폴더인 C:\Document\Arduino  위치에 설치됩니다.  (추후 자동 업데이트 포함)

②  또한 라이브러리를 깃허브(Git Hub) 또는 인터넷 검색으로 검색할 때  xxx.zip 형태의 압축파일로 다운로드하게 되는데,  압축 파일을 풀어서 C:\Document\Arduino\ 위치에 폴더 형태로 붙여 넣기 하면 해당 라이브러리를 사용할 수 있습니다. (단, 아두이노 IDE를 재실행해야 적용됩니다),  물론 표준 라이브러리가 설치되는 폴더인 C:\Program Files (x86)\Arduino\libraries\  에 붙여 넣기 하여도 됩니다. 

중요~!  두 가지 폴더 위치 모두에 동일한 이름의 라이브러리를 설치할 경우 에러가 발생합니다!  둘 중 한 곳은 삭제(제거) 해야 합니다.   그냥 라이브러리 폴더 째로 삭제하세요.
그리고 두 폴더의 차이는 두 가지 라이브러리 중 사용자가 설치한 문서 폴더에 있는 라이브러리가 먼저 적용됩니다.  그리고 만약 표준 라이브러리 폴더에 있는 라이브러리보다 버전이 낮더라도 먼저 인식 처리되며, 만약 중복될 경우 표준 라이브러리에 있는 라이브러리를 중복 에러로 표시하게 됩니다.
 또한, 압축을 풀지 않고 압축파일 속이 아래와 같은 특정한 형식으로 된 압축 파일이라면 .zip 파일 추가하기 메뉴로 바로 추가할 수 있습니다.

.zip 파일 추가하기 파일 속 구조( src 폴더 아래에 각종 라이브러리 헤더 파일이 포함 되어 있다)

 

③ 사용자가 직접 만들어 라이브러리를 추가할 수 있습니다.(사용자 정의 라이브러리 만들어 추가하기)
  
조금 전에 설명한  .zip 파일 라이브러리 구조와 같은 구조를 만들어 추가할 수 있습니다. 

src 폴더 아래에 라이브러리 헤더파일(.h)과 소스코드파일(.c)을 작성해서 위치시킨다

 

아두이노 예제 파일(.ino)을 만들어 example 폴더 아래 예제명과 같은 폴더를 만들어 위치시킨다

  -  xxx.h (헤더 파일)과  필요에 따라 xxx.cpp 또는 xxx.c 로된 소스코드 파일  그리고 examples 예제 폴더를 만들고 그 안에 xxx.ino 와 같은 예제 파일을 만들어 놓으면 됩니다. 
  -  그리고 Readme.txt, keywords.txt와 같은 라이브러리 작성자 및 사용법에 관한 안내를 적절한 내용으로 만들면, 이 라이브러리를 다운 받아 사용하는 사람에게 도움이 될 수 있습니다. 
    ( xxx.h 헤더 파일과 examples 폴더 내 .ino 예제 파일 구성은 라이브러리를 추가할 때 인식시키기 위한 필수 항목입니다)
 이런 구조로  .zip 파일 형태로 추가했을 때, 아두이노 IDE 메뉴의 예제 메뉴에서 아두이노 예제 코드를 불러올 수도 있게 됩니다. 


 


 - 반드시 .zip 파일 형태로만 추가할 수 있는 것은 아니며,  단순히 폴더 하나 만들고 그 속에 xxx.h 헤더 파일과 또는 헤더 파일과 xxx.c 소스 파일만 넣고,  C:\Document\Arduino\ 위치에 폴더 형태로 붙여 넣기만 하면 됩니다. ( 아두이노 IDE 재시작 필요)

 

 [ 3. 아두이노 라이브러리 에러 대처하기 ]

 - 라이브러리 설치 시 배포자와 버전이 중요할 수 있는 이유 : 
 같은 이름의 라이브러리라 하더라도, 라이브러리 제작자가 다를 수 있으며 당연히 라이브러리 내의 코드 구성 내용이 다를 수 있어 라이브러리 관련 함수 사용 시 에러가 발생할 수 있습니다.  (이를 구분할 수 있는 방법은 메모장 같은 것으로 파일을 직접 열어보면 알 수 있고, 파일의 용량이 기본적으로 차이가 납니다). 
  또한 같은 라이브러리 제작자라 하더라도 제작 버전에 따라 함수 및 기능 추가, 삭제, 사용법 변경 등이 이루어 지기에 에러가 발생할 수 있습니다.   따라서 보통 인터넷 아두이노 관련 학습 게시글 중에서 게시자가 게시한 글에서 사용한 라이브러리의 버전과 차이가 나는 최신 버전 등을 설치하여 동작시키려 할 때에 에러가 발생할 수 있으므로,  이때는 최신 버전을 삭제하고 라이브러리 버전을 더 낮은 버전으로 선택해서 시도해 보면 에러가 해결될 수 있습니다.

- 같은 이름의 라이브러리가 중복으로 설치된 경우
  : 중복된 라이브러리 중, 하나의 라이브러리를 삭제하여야 합니다.  만약, 두 개의 라이브러리 버전이 다를 경우, 문서 폴더 아래에 설치되는 라이브러리가 먼저 적용이 되니 코드 실행에 필요한 라이브러리 하나를 가급적 문서 폴더에 남겨주세요. ( C:\Document\Arduino )

- 특정 모듈 제조회사에서 배포하는 라이브러리의 경우,  .zip파일 추가하기로 등록하지 말고  라이브러리 매니저를 통해 해당 라이브러리와 함께 연계된 라이브러리를 모두 설치해야 에러가 발생하지 않는 경우가 있습니다. 
 주로 Adafruit 사에서 출시하는 DHT센서 및 자사의 Neopixel LED Matrix 모듈 제품과 같은 경우에 이런 경우가 많은 데요,  아래 이미지처럼, 관련된 추가적인 라이브러리를 Install all로 해서, 모두 설치해 주어야 합니다. 



-  기타 : 원드라이브(OneDrive) 사용자의 경우  온라인 여부 체크하세요.
   간혹 원드라이브를 사용하고 있는 경우,  원드라이브 설정에 따라, 아두이노가 원드라이브에 속한 문서 폴더 아래에 설치되는 경우가 있고,  원드라이브 네트워크가 오프라인 일 때 ,  이를 인지 하지 못하고 라이브러리 에러를 쉽게 찾아내지 못하는 경우가 있습니다. 

- (중요!) 라이브러리 관련된 문제의 원인을 제거 또는 해결하였다면 항상 아두이노 IDE를 재시작해야 적용됩니다.

 

 [ 4. 아두이노 라이브러리 관리하기 ]

 - 자신의 코딩에 사용된 라이브러리는 항상 압축파일 형태로 백업해 두는 것이 좋습니다.
   또한 압축파일 이름이나 혹은 xxx.txt 파일을 만들어 어떤 아두이노 작품에 어떻게 사용한 라이브러리 인지를 기록해 두면 수개월 후 해당 라이브러리를 다시 사용하게 되었을 때,  즉각적으로 사용하기 수월해집니다. 
( 같은 이름의 라이브러리가 여러 개 존재하고 있고,  그 라이브러리마다 적용할 수 있는 함수도 다를 수 있는데, 어떤 코드에는 동작되지만 또 다른 코드에서는 동작이 안 되는 경우가 발생하기 때문입니다. ) 

 - 문서 폴더 아래에 있는 아두이노 라이브러리 폴더 전체를 하나의 파일로 압축 백업해 두면,  컴퓨터에 문제가 있어 윈도를 다시 설치해야 하는 경우에 아두이노 관련 라이브러리를 쉽게 복원할 수 있습니다.

반응형
반응형

【 아두이노초급#5포토레지스터 CDS사용 입·출력 실습 

1

 

 CDS(Cadmium Sulfide : 황화카드뮴 소자)또는 포터 레지스터(Photo Resistor)라 불리는 센서를 가지고 아두이노 입출력 실습을 진행합니다.

▶ 주요 내용
- CDS에 대한 개념, 동작원리
- PWM(pulse width modulation) 정의와 아두이노에서 사용 방식
- 아두이노에서의 입력함수, 출력함수에 대한 사용방법 정리
     [ analogRead ( ) , analogWrite ( ) , digitalRead ( ) , digitalWrite ( ) ]
- CDS 신호 처리 하여, LED의 밝기 조절에 대한 아두이노 코딩과 실습

 CDS는 기본적으로 저항의 역할을 합니다.   그래서, 아래 CDS의 기호에 저항의 이미지가 들어가 있죠. 
그리고, 기호에 보면, 외부로부터의 빛을 받아들이는 것을 의미하는 화살표로 구성되어 있듯이, 빛에 따라 저항값이 바뀌는 특성이 있는 소자입니다.

CDS 센서의 기호

주변이 밝아 센서 표면에 유입되는 빛이 많을수록 저항값이 0Ω에 가까워지고(약 1㏀),  주변이 어두울수록 저항값이 급격하게 커지는(약 10MΩ) 특성을 가집니다.
이런 특성을 이용하면 빛의 밝기를 이용해서, 입력되는 전압(전류)의 크기를 제어할 수 있습니다.
아래에 보이는 회로를 참고하여 CDS 및 기타 부품들을 준비하고 회로를 연결해 주세요.  (CDS 종류나 크기에 상관없이 준비된 것으로 연결하면 됩니다.)

동작 원리를 설명드리면, 적당한 빛이 있을 때 CDS는 특정한 저항값을 가지게 되며,  CDS와 함께 직렬로 연결된 10㏀의 저항에 5V의 전압이 분배되어 걸리게 됩니다.

만약, CDS 주변의 밝기가, CDS의 저항값을 10㏀으로 변화시켰다면,  그래서, 직렬로 연결된 10㏀의 저항과 같은 값이 될 경우,  공급되는 5v 전압은 CDS와 저항 각각에 1/2로 분배되어, 2.5v의 전압이 A0로 입력됩니다. (아래 그림)

 

 그런데, CDS 주변을 아주 밝게 하여 CDS의 저항값이 거의 0Ω에 이르렀다면,  5v의 전원이 10㏀에 모두 걸리게(강하) 되고, 그러면 A0에 이 5v의 전압이 입력되게 됩니다. (아래 그림)

 

 

 그리고 만약, 주변을 아주 어둡게 하여 CDS의 저항값이 거의 수십㏁에 이르렀다면,  직렬연결된 10㏀의 저항값은 CDS의 저항값에 비해 무시할 정도로 작게 되고, 5v의 전원 대부분이 CDS에 걸리게(전압강하) 되어, 이 부분의 전위는 0v (GND)에 가깝게 됩니다. (아래)

이런 원리로, CDS 주변의 밝기에 따라 A0 포트로 0v ~ 5v 사이의 전압이 입력됩니다. 
아두이노의 Analog 입력 포트(A0~A5) 쪽에는 입력된 아날로그 전압 값을 디지털 값으로 변환시켜주는 A/D Converter가 내장되어 있습니다.
우노(나노)에 들어 있는 A/D Converter는 10bit의 분해능(해상력)을 가지고 있는데, 10bit는 2의 10승, 즉 1024의 값이며 아날로그 포트(A0~A5)로 입력되는 0v~5v의 전압을 0~1023의 수치로 변환받을 수 있게 됩니다. (아래)

이때, 아날로그 포트로 아날로그 값을 읽어 들이기 때문에, analogRead(pin)라는 함수를 사용합니다.

이렇게 읽어 들인 수치(0~1023)를 가지고 if 비교문 등을 이용해서, 디지털 포트에 연결된 LED를 켜고 끄거나, 밝기(PWM)를 조절할 수 있습니다.

아두이노의 입출력 함수에 대해 한 번 정리해 드릴게요.
아날로그 포트는 0~5v의 전압을 입력만 받을 수 있는 포트입니다. 따라서 하드웨어적으로 아날로그 포트로 출력은 할 수 없습니다.  아날로그 포트로 데이터(전압)를 입력받을 때는 ‘analogRead ( )’함수를 사용합니다. 



아두이노 디지털 포트로는 입력과 출력이 가능하며,  디지털 포트를 통해 데이터(전압)를 입력 받을 때는‘digitalRead( )’함수를 사용하고,  출력할 때는,‘digitalWrite( )’함수를 사용합니다. 
또한, PWM 방식을 통해 아날로그적인 값(전압)을 디지털 포트로 출력하고자 할 때는 ‘analogWrite( )’함수를 사용합니다.  ( 단, ~기호가 붙은 11, 10, 9, 6, 5, 3번 핀들만 가능합니다 )   (아래)

 

High 신호일 때는 5v 출력을 하고,  Low 신호일 때, 0v 로만 출력시킬 수 있습니다. 
그래서 0v~5v 사잇값 출력이 안 되어 LED 밝기 조절이 안 되고, On/Off 만 하게 됩니다. 
그런데, PWM(pulse width modulation)이라는 방식을 이용하면 마치 아날로그처럼 0v~5v 사잇값을 출력시킬 수 있습니다. 
PWM 방식은 펄스 형태로 High와 Low 신호의 비율(듀티비)을 조절하여 출력하는 방식이며 High 신호의 비율이 높을수록 평균 전압이 5v에 가까워지고, 낮을수록 0v에 가까워집니다.  
그래서, 듀티비를 조절하여 아날로그처럼, 0v~5v 사잇값도 출력할 수 있게 됩니다. 
이런 방법으로 LED의 밝기를 조절할 수 있게 됩니다.

듀티비(Duty)가 높을수록 높은 전압이 출력되고, 낮을수록 낮은 전압이 출력됩니다.
(듀티비 100% : 5v ,  듀티비 50% : 2.5v ,  듀티비 0% : 0v)

당연히 전압이 높을 때, LED가 밝고,  낮은 전압일 때, LED가 어둡게 켜집니다.

아두이노에는 이런 PWM 출력을 할 수 있는 포트가 정해져 있는데요, 포트 번호 옆에 ~ 물결무늬 표시가 있는 포트만 PWM 출력이 가능합니다.  일반적인 디지털 포트 출력은 digitalWrite( pin , value ) 명령어를 사용합니다.

Value가 HIGH 일 때는 5v의 전압이 출력되고, LOW 일때는 0v로 출력되어,    LED가 최대로 밝거나 혹은, LED가 꺼져있는 두 가지 형태만 가능합니다. 


그런데, ~PWM 포트에는 digitalWrite(  ) 명령어뿐 아니라, analogWrite(pin, value)라는 명령어를 사용할 수 있습니다. 
pwm 디지털 포트의 출력은 8bit로 이루어지기 때문에, 최대 2의 8승 값인 256, 즉, 0 ~ 255 사잇값을 value 값으로 출력해 줄 수 있고, 0이면 LED가 제일 어두우며(꺼짐), 127은 중간값, 255 일 때 최대 밝기가 됩니다. 
이렇게 해서 디지털 포트로 밝기 조절과 같은 아날로그 적인 출력 표현이 가능합니다. (아래)

아두이노 코드는 아래를 참고하거나 직접 다운로드하여 보세요.

int LED=9;    //우노에서는 디지털 포트는 숫자만 입력함
int LIGHT=A0; //아날로그 포트는 A0, A1,...형태로 입력함
int val=0;
int fix=0;
void setup() {
 pinMode(LED,OUTPUT);
 Serial.begin(9600);
}
void loop() {
 val=analogRead(LIGHT); 
 int val2 = map(val,0,340,255,0); 
 int val3 = constrain(val2,0,255);
 Serial.println(val3); 
 analogWrite(LED,val3);    
// delay(100);
}

 아두이노 파일입니다.  다운로드한 후 압축을 풀어서 사용하세요.

CDS.zip
0.00MB

CDS는 크기별 종류가 있으며, 5pi(5mm), 7pi, 10pi, 20pi ... 

이미지 참조 : www.societyofrobots.com


제조사별 및 품번 별로도 약간의 다른 특성을 지니고 있는데요,
빛에 따라 반응하는 저항값의 범위가 조금 다르고, 허용 최대 전압이 조금 다를 뿐이어서 이런 실험에서는 크기나 종류에 크게 영향이 없으니 어떤 것이든 실습에 사용하면 됩니다.

그럼, CDS를 연결해 주고, 코드를 빌드&업로드해 주세요. 
시리얼 모니터를 열어보면, 현재 주변의 밝기에 따른 입력값이 나오는 것을 볼 수 있습니다. 
그리고 손으로 가려보면, 수치가 작아지고, 오픈하면 수치가 올라갑니다. 
빛에 노출되는 정도에 따라, 수치가 변하는 것을 볼 수 있는데요,  수치는 CDS의 종류에 따라 달라지기도 하지만, 현재 놓인 장소의 밝기에 따라 달라지게 됩니다. 



그럼, 다른 종류의 CDS도 있으면 바꾸어 실험해 보세요.  
CDS의 종류에 따라서도 입력되는 값의 범위가 다름을 알 수 있습니다. 
따라서, 제공해드리는 코드를 그대로 사용하지 말고, 한 가지 변경해 주어야 하는데요,
밝기의 최소·최대 값 범위를 확인해서, LED의 출력 값 범위와(0~255)와 매핑(매칭)을 시켜야 합니다.  
이렇게 하여야, 현재 주변의 밝기에 따라 LED의 밝기 조절을 최대로(0~255) 할 수 있게 됩니다. 
이를 위해 화면에 보이는 매핑 함수를 사용합니다. 

'값'에는, CDS로부터 값이 입력되는 변수를 써주고,  fromLow, fromHigh 두 자리에는 CDS를 어둡게 했을 때의 최솟값과 밝게 했을 때의 최댓값을 적으세요. 
그리고, toLow, toHigh 두 자리에는 LED의 최대 범위 0과 255를 각각 적습니다. 
그리고, 매핑된 값을 시리얼 모니터로 확인해 보기 위해, val2로 바꾸어 주세요. 
코드는 순차적으로 컴파일되기 때문에, Serial.println(val2)는 val2 변수 선언 이후로 내려 주세요. 
그럼, 컴파일&업로드해서 확인해 보세요. 
약간의 오차가 있겠지만 0~255 범위를 크게 벗어나지 않을 거예요. 
그리고, 좀 더 나아가서 아예 0보다 작고 255보다 큰 값들은 제거해 버리도록 constrain( ) 함수를 써서 처리할 수 있어요.
constrain( ) 처리한 값은 val3에 저장하고,  마찬가지로 serial.println(val3) 문장을 val3선언 이후로 내려주면 됩니다. 
다시 업로드해서 값을 확인해 보세요. 


constrain( val3, 0, 255 ) 처리를 하면, 해당 값 이하(0)와 이상(255)은 잘라버리기 때문에,  해당 값 이외의 숫자가 나오면 안 되는 경우에 활용하면 좋습니다.   
이렇게 하면, LED 밝기를 최대 범위(0~255 : 0v~5v)로 컨트롤할 수 있습니다. 

 만약, CDS가 바뀌거나 실험 장소가 바뀌면 다시 A0로 입력되는 값을 실측해서 적용해 주어야 합니다.
첨부해드린 코드에는 , CDS주변이 어두우면 LED가 점점 어두워지고, 주변이 밝으면 LED가 밝게 작동하는데요,
이 작동을 반대로 하려면,“map( val, 최솟값, 최댓값, 255, 0 )”으로 LED값을 반대로 해주면 됩니다. 

이상으로 포터레지스터 소자인 CDS에 대한 아두이노 입출력 실습을 진행했습니다.
감사합니다.

【 실습과정 영상으로 보기 】

 

반응형
반응형

프로젝트#13손 안대고 손 소독하기!  자동 손 소독기 직접 만들어 봅시다!

 

 여러 사람이 이용하는 공동 장소에서는 손소독기가 있어도, 요즘 같은 시기에 직접 소독제를 만지기 꺼려하는 경우가 있게 되는데요,  이에 손 대지 않고 이용할 수 있는 자동 손소독기를 직접 만들어 보겠습니다.

1. 자동 손소독기 특징
 제작의 주안점은, 센서를 이용해 자동으로 작동하며, 소독액 리필 및 교환이 편리하도록 고려하였습니다.
또한, 전원 코드를 연결하지 않는 무선방식으로 충전식 배터리를 사용하였으며,  아두이노를 활용할 수도 있지만, 아두이노 없이 작동 가능하다면 전력 소모량이 적어지고, 비용도 낮아지는 장점이 있음을 반영했습니다. 
다만, 아두이노 사용하지 않는 펌프방식을 채택하다보니,  소독액이 어느정도 묽어야만 펌핑이 가능하기에, 액상 타입의 소독액만 사용 가능하고 겔타입 소독액은 사용이 어렵습니다.  하지만,  젤 타입도 식염수를 적당량의 비율로 섞어주면,  사용가능합니다.  이번 영상에 사용한 방법 또한 젤 용액과 식염수를 희석하여 사용하였습니다. 
 케이스는 3D 툴을 이용하여 3D 프린팅으로 출력해봤습니다.  물론, 종이 상자나 기존 상품 케이스 같은 것을 활용하셔도 좋습니다. 

본 게시글의 모든 이미지는 클릭시 자세히 확대 됩니다


2. 자동 손소독기 재료 준비

본 게시글의 모든 이미지는 클릭시 자세히 확대 됩니다

① 근접센서 :  FC-51 또는 TCRT-5000  1개,  기능은 동일하며, 적외선 LED 부착위치가 조금 다릅니다. 본 회로에서는 FC-51 사용.
② 파워 트랜지스터 (Power TR) : TIP32C 1개,  PNP 타입이며, 100V 3A까지 견딜수 있는 전력용 TR입니다.
③ 레귤레이터 : AMS1117(5v용) 1개 ,  5v 이상의 입력 전원을 정확히 5v 출력으로 유지시켜 주는 정전압 모듈이며, 5V로 동작되는 부품(근접센서, 샤플로 펌프)을 보호하는 역할도 합니다.  만약,  USB 전원(5V)을 사용한다면, 레귤레이터를 생략할 수 있습니다.
④ On/Off 전원스위치 :  스위치의 역할은 전원을 연결하거나 차단하는 역할로 사용 되기에 스위치의 종류에 크게 구애받지 않습니다.  록커(Rocker)스위치나,  토글스위치, 슬라이드 스위치 등 갖고 있는 스위치 중에 선택하면 되며, 본 회로에서는 록커 스위치 규격에 맞추어 케이스를 디자인 하였기에,  록커 스위치를 사용합니다.
⑤ 저항 (Resistor) :  저항은 본 글에서 사용한 펌프를 사용할 경우 100~300옴의 저항을 사용하며, 만약 더 작은 용량의 모터를 사용한다면, 1㏀ 이상의 저항을 사용해야 될 수 있습니다. 중요한 것은, 직접 테스트를 통해 본인이 갖고 있는 펌프가 원활히 잘 작동할 수 있는 저항 값을 찾아야 합니다. 

⑥ 다이오드 (Diode) : 1N4002~1N4007 사이의 다이오드는 모두 사용 가능 합니다.   마지막 숫자 2는 2A , 3은 3A, 7은 7A로, 최대 견딜 수 있는 허용 전류를 의미합니다.  다이오드는 모터의 역전류에 의한 회로 보호용으로 사용됩니다.
⑦ 전원잭 모듈 (DC005-Power Jack) :  리튬배터리 소켓 중에 배럴잭 타입의 소켓을 사용하게 될 경우, 전원잭 모듈을 사용하면, 연결이 편리합니다.  전원잭 모듈 없이 직접 선으로 연결하여도 무방합니다.
⑧ 리튬배터리 및 전용 소켓 : 18650 3.7v 2개 직렬 연결하여 7.4v로 출력이 되도록 직렬 소켓을 사용합니다. 
 회로가 정상 동작하기 위해서는 최소 5V이상의 전원이 입력되어야 하며, 모터가 들어간 회로에서는 전압보다, 전류가 더 중요한데요, 18650과 같은 전류의 세기가 좋은 배터리를 사용하는 것이 좋습니다.   하지만, 리튬이온 배터리는 합선에 의한 스파크 및 발화가 될 수 있으니 다루실 때 반드시 주의를 기울여야 합니다. (합선 주의! 충전시 장시간 자리이탈 금지! )
⑨ 미니 샤플로 펌프 (3v~5v) :  기어가 달린 모터 펌프로서, 내경-외경 크기가 3mm-5mm인 튜브를 사용하는 모터입니다.  실제 튜브 사용은 2mm-4mm 튜브를 사용했습니다.  만약, 모터가 잘 돌아가지 않는다면, 입력 전원이 특히 전류가 부족한 건 아닌지? 확인해 보시고, 기어 박스 속에 윤활제 같은 것을 발라 보세요.
⑩ 워터펌프용 튜브 : 내경-외경 2mm-4mm인 튜브(호수)를 사용 했습니다. 
⑪ 분사 노즐 :  형태 조절이 가능한 (Adjustable Oil Coolant Nozzle: 쿨란트 노즐)을 사용했는데요, 꼭 이런 노즐이 아니라도 되니 주변에서 쉽게 구할 수 있는 것으로 노즐을 대신 할 수 있습니다.

 

※ 주의! 만약, 사용하고자 하는 모터가 달라진다면, 튜뷰의 치수가 달라질 수 있으며, 동작을 시킬 수 있는 전압이 다를 수 있으니 이에 맞게 전원부 구성을 하셔야 합니다. 


3. 자동 손소독기 연결도 & 회로도

본 게시글의 모든 이미지는 클릭시 자세히 확대 됩니다

화면의 왼쪽이 실물 이미지로 된 연결도이고, 오른쪽이 회로도 입니다.  함께 참고해서 연결해 보세요

 :  회로 동작 원리 설명
근접센서에 물체가 접근하면 적외선 송신 LED에서 발사된 적외선이 물체에 반사되어, 수신LED로 입력되어 물체가 있음을 OUT 핀을 통해 HIGH(약 4.x V전압) 신호로 출력하게 됩니다.

근접센서 사용설명

이 신호 전압이 TR의 B(베이스) 단자로 입력되면, 스위칭 작용에 의해 E(에미터)에 연결된 5V의 전원이 C(콜렉터)로 빠져나가면서 모터를 구동하게 되는 원리입니다.

회로에 사용된 모터와 근접센서의 입력이 5V를 넘지 않아야 하기에, 5V레귤레이터를 연결했습니다.
만약, 5V USB전원을 사용할 경우, 레귤레이터가 필요 없기 때문에 바로 연결하면 됩니다.


4. 자동 손소독기 케이스 디자인

작품의 케이스를, 3D 프린팅으로 출력해서 제작했습니다.
먼저 세정액의 직경을 고려하고, 분사 노즐과 튜브의 직경, 스위치와 센서의 홀 사이즈를 결정합니다.
그리고, 배터리를 내장할 것이지 등에 따라, 전체적인 작품의 크기와 모양을 디자인하면 됩니다.
케이스는 3D 프린팅 출력을 고려하여 캡과 바디로 분리해서 작업 했습니다.
디자인은 라이노로 하였고, 편집 파일도 제공해드리니, 수정해서 사용해도 됩니다.
대부분의 3D 프린터에서 출력가능한, g-code 파일과 stl 파일도 제공해드립니다.

A- 캡 케이스 디자인
먼저, 캡 케이스의 디자인을 살펴 보세요.


자신이 가지고 있는 소독액 용기와 부품의 크기를 실측하여 홀의 크기를 결정하면 됩니다.
홀의 크기는 실제 실측치보다, 1~3mm 정도 조금 더 크게 디자인하는 것이 좋습니다.
라이노와 같은 3D 디자인 툴에서 작업한 결과물을 슬라이서 프로그램으로 넘기기 위해서는 보통 '.stl '파일로 저장하게 됩니다.
대표적인 슬라이서 프로그램인 큐라(Cura)에서 확장자 '.stl'로 저장한 파일을 연 모습입니다.

큐라에서는 보통 프린팅이 진행되면서 오류가 없을지? 사전 체크해 볼 수 있고, 벽을 몇%로 채울지? Support를 넣거나? 배드와 익스트루더 온도 등에 대한 옵션을 설정하게 되죠, 마지막으로 G-Code 파일로 저장하고 3D프린터로 옮겨 출력하면 됩니다.
아래는, 실제 3D 프린터로 출력한 결과 모습입니다.



B- 바디 케이스 디자인
아래는 바디케이스를 디자인한 모습입니다.

근접 센서가 부착되는 방향과 위치를 고려하였고, 배터리를 외부에 부착하기 위한 홀을 추가 했어요.

글자는 양각보다는 음각으로 하는 것이 출력하기에는 더 용이합니다.
그럼 이제, 바디 케이스를 슬라이서로 넘겨 보겠습니다.

 큐라(Cura)에서 모델링 파일을 불러 왔을 때, 3D툴에서 디자인한 기준점(C-PLAN)에 따라 모델링의 방향이 다르게 넘어 오는데요, 출력하기에 적합한 방향과 위치를 잡아줍니다.   기타 벽 채움(Infill) 밀도(%)와 지지대(Support) 사용 등 필요한 설정을 해주고서,  출력을 위한 G-Code 파일로 저장합니다. 
이어, 3D 프린팅을 합니다.

 

《 자동 손소독기 - 3D 프린팅 파일 다운로드 》  
   1. 디자인 뷰 파일( .png, .pdf )
   2. 라이노3D 디자인 작업 파일(.3dm)
   3. 슬라이서 편집가능 파일 (.stl)
   4. 3D 프린터 출력용 파일(.gcode)
 위와 같은 파일을 모두 압축하여 올립니다.  필요하신 분은 받아서 편집하거나 사용해 보세요.

3D_Printing File(자동 손소독기).zip
2.88MB

 


5. 자동 손소독기 작품 조립 제작


손 세정제 펌프캡은 가운데 부분을 뽑아내고 호수를 끼워 만들었습니다.

 오일 쿨란트 노즐에도 호수를 최대한 끝까지 밀어 넣는 것이 좋습니다.
이제 부터는 납땜으로 부품을 연결합니다.  그냥 선만 감아도 되지만 인두기를 이용하여 납땜을 해 놓으면, 더 안정적으로 작동합니다.
만약 브레드 보드를 사용하여 연결하려면, 본체 케이스를 좀 더 크게 만드는 것이 좋습니다.
주의해야 할 것은,  전기적으로 합선이 되면 안 되기에, 열수축 튜브나 테이프 등으로 감아 주면 좋습니다.

 아래,  이미지 처럼 근접센서 모듈에 있는 가변저항을 돌려 센싱을 원하는 거리를 맞추어 봅니다.

작동 거리가 너무 가까울 때는 가변저항을 반대쪽으로 돌려 작동거리를 늘려주세요.
처음엔 배터리를 내장할 계획이었으나, 넣을 공간이 부족하여 홀을 뚫어 외부에 부착하였습니다.

 작동이 제대로 된다면,  이제 부품들을 제대로 고정시켜 보겠습니다.
글루건은 부착도 쉽고, 탈착도 가능하기 때문에 적당히 고정시키기에 좋습니다.
글루건은 전기적으로 절연체이기 때문에 회로나 모듈에 방사되어도 큰 문제 없습니다.  다만, 열 배출이 잘 되도록 전부 덮어 씌우지는 마세요.


캡과 바디는 유격이 있기 때문에, 최종 조립이 다되면, 양면 테이프로 고정을 시켜주면 좋습니다.

아래가 완성된 이미지 입니다. 

 참고로 아래 전체 제작과정을 담은 영상을 참고해서,  여러분만의 자동 손소독기를 만들어 보세요~  ^^

《 전체 작업과정과 설명 영상으로 시청하기 》

반응형
반응형

【 아두이노모듈#31】 #1. 활용성 좋은 HC12 무선 모듈, 봉지 뜯은 김에 마스터해보기 


※ 모든 이미지는 클릭 시 확대되어 선명하게 보실 수 있습니다.


【 HC12 무선 개요 】

 ( Long Range RF Wireless Serial Module ) 
 HC-12 무선 모듈은 433MHz 대역을 사용하는 양방향 통신 무선 모듈이며,  1 대 1 (1 : 1) 통신뿐 아니라,  1 대 다(1 : N) 멀티채널 통신이 가능한 모듈입니다.  통신을 위해서는 최소한 2개의 모듈이 필요합니다. 
 통신주파수가 더 높은 고주파 대역을 사용하는 (예, 2.4 GHz) 무선기기들 보다 장애물에 좀 더 유연하며,  MCU를 내장하고 있어 직렬 포트를 통한 외부 장치와의 통신도 가능한 장점이 있습니다.
  전원을 넣으면 바로 연결이 되고, 응답성이 좋아, 다양한 사물기기간의 통신뿐 아니라,  무선조정 RC-Car와 같은 작품들을 만드는 데에도 활용하기 좋은 모듈입니다.  

 

〔 주요 특징 〕
- 장거리 무선 전송 ( 열린 공간에서 1,000 m의 거리를 5000 bps의 속도로 신호 전송 가능 , 저속 모드 시 1.8Km까지도 가능 )
- 모듈에 MCU가 내장되어 있어 모듈에 별도의 프로그래밍을 해줄 필요 없이 시리얼포트를 통한 AT 명령으로 전송 모드를 선택하거나 설정을 제어할 수 있습니다. 
- 절전모드(FU1), 초절전모드(FU2), 일반모드(FU3), 원거리통신모드(FU4) 등의 다양한 옵션을 제공해 줍니다.
- 100개의 채널을 활용할 수 있습니다. (작동 주파수 범위 : 433.4MHz ~ 473.0MHz , 400KHz 간격으로 100개)
- 시리얼(직렬) 포트를 통한 외부 장치와의 통신이 가능합니다.

〔 주요 사양 〕
- 작동 주파수 :  433.4MHz ~ 473.0MHz , 400KHz 간격으로 100개의 채널 사용가능
- 공급 전압    :  3.2V~5.5V
- 통신 거리    :  열린공간에서 1,000m  ,   저속모드 선택 시 1.8Km 가능,  외부 확장 안테나 연결단자 있음
- 시리얼 통신 속도 : 1200 bps / 2400 bps / 4800 bps / 9600 bps (default) / 19200 bps / 38400 bps / 57600 bps / 115200 bps
- 수신 감도    : -117dBm ~ -100dBm
- 전송 파워    : -1dBm ~ 20dBm
- 인터페이스 프로토콜 : UART / TTL
- 작동 온도    : -40℃ ~ +85
- 크  기         : 27.8mm x 14.4mm x 4mm

▶ HC-12 확장 안테나
(송신 거리 혹은 수신 감도를 높이기 위해 필요에 따라 아래와 같은 확장 안테나를 연결할 수 있습니다.  하지만 반드시 필요한 것은 아니며,  대부분의 경우 기본에 포함된 스프링 안테나를 이용하여도 충분합니다. )

확장 안테나
확장 안테나 연결 부위 확대 모습
확장안테나를 연결한 모습 (nRF24L용 안테나와 호환 가능)
스프링 안테나의 연결(납땜) 위치
스프링 안테나와 확장안테나 위치 표시

아래는 스프링 안테나와 핀의 납땜 모습입니다.  스프링은 세우지 않고 일자로 눕혀 납땜해도 상관없고,  핀도 90도 직각으로 꺾이는 핀을 따로 구해서 HC-12 모듈이 기판이나 브레드보드에 세워 꽂을 수도 있으니 참고하세요.


HC12의 스펙을 하나의 테이블로 보기 좋게 정리해보았습니다

 

 HC12의 FUx 모드 설정에 대한 상세 설명 

 

 HC12의 AT Commands 명령어 정리 


[HC12 모듈 간 통신 방식 설명]


HC12 모듈은 아래 이미지처럼, PC(시리얼 모니터)와 시리얼 방식으로 통신을 합니다.


그리고 HC-12 모듈 사이에 433 MHz 대역으로 RF 무선통신을 하게 됩니다.

 

【 HC12 모듈 실습 - 전체 과정 안내 】

 :  HC12 모듈을 구매하셨다면, 봉지를 뜯은 김에(?) 기초 실습부터 단계별로 진행하여 어느 정도 HC12 모듈을 잘 다룰 수 있는 실습까지 이 번에 모두 담아 보려 했습니다.   최종적으로 서보모터 2개를 동시에 무선으로 제어 해보는 실습까지 진행해 본다면, DC모터를 제어하는 것은 좀 더 쉽기 때문에 RC-Car와 같은  RC 기기류는 자유롭게 만들 수 있게 됩니다.  차기 콘텐츠에는 HC12모듈 활용 편으로 RC-Car를 진행할 예정이니 관심 있으신 분들은 이번 실습을 차근차근 진행해보면 많은 도움이 될 것으로 기대합니다.

《 실습 진행 순서 》
실습 #1에서는 HC12 모듈의 시리얼 통신 기능을 배워볼 텐데요, PC ↔ HC12를 시리얼 모니터를 이용한 시리얼 통신기능 학습입니다.

실습 #2에서는 HC12 모듈 간의 RF 통신 실습입니다. 회로를 1대 1,  또는 1대 2이상 구성한 다음, 시리얼 통신 기능을 이용해서 RF를 통해 문자를 주고받고, 받은 문자에 따라 LED를 켜보는 실습입니다. 

실습 #3은 AT-Command 통신 기능을 사용해보는 실습입니다. AT-명령어를 시리얼 모니터 창으로 입력하여 HC-12 모듈의 채널(주파수) 변경/전송 모드 변경/통신속도/통신 강도 변경 등을 실습합니다.

실습 #4에서는 RF 통신을 이용하여 AT-Command 기능을 활용해 보는 실습입니다.  푸시버튼스위치 2개를 이용하여, 무선통신으로 원격으로 HC12 모듈의 채널을 바꾸어 보는 실습입니다.  이번 실습 4를 이용하면, 채널(주파수) 변경뿐 아니라, 실습 3에서 해보았던, 전송 모드 변경/통신속도/통신 강도 변경 등도 할 수 있습니다. 

실습 #5가변저항을 돌려서 RF 통신으로 원격 회로의 LED 밝기를 조절해 보는 실습입니다. 이번 실습을 통해, 기본적인 데이터 주고받는 방법과 입·출력 포트 제어를 이해할 수 있습니다.

실습 #6은 조이스틱 모듈 하나로 원격의 서보모터 두 대를 제어해 보는 실습입니다.  보통 실습 2에서 처럼 무선으로 수신되는 데이터가 한 가지라면, 처리하기 쉽지만,  조이스틱 모듈에서 나오는 두 가지 데이터를 수신받아, 두 개의 서보모터(x, y) 데이터로 각각 분리하여 다루는 코딩 방법을 익히게 됩니다.  서보 모터를 다룰 수 있게 되면, DC 모터는 더 편하게 다룰 수 있습니다.

 앞 단계 실습이 쉬워 보이더라도, 가급적 순서대로 모든 실습을 직접 해보시길 추천드립니다. 
실습에 사용된 아두이노는 사이즈가 작고 별도의 USB to TTL 모듈이 필요치 않은 나노(Nano) 보드를 이용했습니다.
만약, 나노가 아닌 다른 보드를 사용하여도 되며,  특히 우노(Uno) 보드를 사용한다면, 회로의 연결이나 코딩의 변경 없이 거의 그대로 사용할 수 있습니다.


《 실습 재료 》

본 게시글의 모든 이미지는 클릭하면 선명하게 확대 됩니다

위의 실습재료는 실습 1~실습 6까지 전체 실습을 진행할 수 있는 최소한의 재료입니다. 
만약 실습 2에서와 같은 여러 대의 통신 실습을 진행하려면, ~개 이상이라고 표시된 부품들이 더 필요할 수 있으니 참고하세요.  기본적으로, 아두이노 나노(우노) 2대와 HC12 2개의 송수신 회로를 가지고, 연결을 바꾸어가며, 실습 1부터 실습 6까지 진행하실 수 있습니다.

【 실습  #1 】 나노 HC12회로 두 대를 이용한 시리얼 통신 실습

아래 회로 연결도를 구성해 주고 PC와 연결합니다.
▶ 회로 연결도 
(아두이노 나노와 RF 무선통신 모듈 HC12 연결도)
    ※ 아래와 같은 회로 두 개를 준비합니다.

 

《 콘덴서를 달아봅시다 》
바이패스(Bypass)/ 디커플링(Decoupling)  콘덴서란?
  HC12 모듈과 가까운(멀지 않은) 위치에 노이즈 제거 및 회로 전원 안정화를 위해 아래 회로처럼 콘덴서를 달아 주면 도움이 됩니다.  이런 용도의 콘덴서를 바이패스(Bypass) 콘덴서 또는 디커플링 콘덴서(Decoupling Capacitor)라고 칭합니다.  노이즈와 같은 신호는 때때로 하나의 제대로 된 신호로 인식하게 되고, 그래서 노이즈로 인해 오작동이나 결과에 영향을 주게 됩니다.  그리고 노이즈와 같은 신호는 주파수가 높아서 콘덴서를 통해 그라운드(GND)로 흘려버릴 수 있습니다(ByPass),
  그리고 바이패스/디커플링 콘덴서는 IC나, IC가 들어간 모듈 회로에 순간적으로 전류가 크게 흐르면 손상을 입을 수 있는데 이를 막아주는 역할도 합니다.  그리고 신호(직류 성분)에서 노이즈 성분(교류성분)만 GND로 통과시킨다고 하여 Bypass,  또는 신호(직류성분)에서 노이즈(교류 성분)를 분리해 낸다고 하여 디커플링이라 칭하고 있기 때문에,  기본적으로 같은 개념이며,  용어 또한 혼용해서 사용하고 있습니다. 

  또 한 가지 기능으로 각 부품이나 모듈에 순간적으로 전압(전류) 부족 현상이 생길 수 있는데, 콘덴서에 충전된 전압으로 인해 보충해 주는 역할도 하게 되어,   여러모로 도움이 될 수 있습니다.   여기에 사용되는 콘덴서로는, 무극성(극성 구분이 없는)의 세라믹 콘덴서와 이보다 용량이 큰 유극성의 전해 콘덴서를 주로 사용합니다. 
 굳이 콘덴서 구분을 하자면, 
  - 수백KHz~ 수십MHz의 높은 주파수 노이즈 바이패스 용도로  0.01~0.1uF 용량의 세라믹 콘덴서를 사용하며, 
  - 수Hz~ 수십KHz의 낮은 주파수 노이즈 바이패스 용도로 10~1000uF 용량의 전해 콘덴서를 사용하게 됩니다.
따라서 일부 노이즈에 취약한 특정 회로에서는 모든 노이즈 주파수에 대응하기 위해 세라믹과 전해 콘덴서 함께 사용하기도 합니다. 
  하지만 본 회로에서는 10uF 정도의 전해 콘덴서 하나 넣는 것으로 예시를 들었으며,   
이번 실험을 위해 반드시 달아야 하는 것은 아니니, 콘덴서 부품이 없으신 분들은 그냥 진행하시기 바랍니다. 

바이패스(Bypass)/디커플링/전원 안정화용 콘덴서 부착 회로 모습



▶ 실습 준비 
 - HC12 모듈은 구매 시 대부분 핀이나 안테나의 연결이 되어 있지 않은 상태입니다. 따라서 납땜을 위한 인두기가 필요할 수 있습니다.   납땜 작업 시, 핀의 납땜 방향과 안테나의 납땜 위치를 꼭 확인하고 진행하세요.  또한 납땜 과정에서 인두기로 인해 인접한 부품이 손상될 수 있으니 주의하세요.
 - 기본 제공되는 스프링과 연결핀 납땜한 모습 (작업 상황에 따라 'ㄱ자' 꺾인 핀을 사용하거나 안테나를 눕혀 납땜하여도 무방 합니다. 모두 안테나의 기능을 하는데 문제없습니다. )
 - 위 회로 두 개를 준비합니다.  (아두이노 X 2개,  HC12 모듈 X 2개 )
 - HC-12 모듈의 통신방식은 소프트웨어 시리얼을 이용합니다.  이번 실습에서 하드웨어 시리얼 통신단자(D0, D1)는 PC와의 시리얼 통신에 사용되어 지기 때문이며,  소프트웨어 시리얼 통신 단자는 D2 , D3 뿐 아니라 다른 디지털 단자를 연결하여도 됩니다. (코드 수정 필요)
 

▶ 아두이노 코드 
(아래 코드  아두이노 A / B 두 회로는  코드가 동일합니다.)

《아두이노 A 회로용 코드》 

// ###  'A'회로와 'B'회로 코드 ###  
// 시리얼 모니터를 통한 시리얼 통신 실습입니다.
// HC12모듈을 연결한 동일한 회로 두 개를 준비합니다 (아래 링크 참조)
// RasINO IoT : https://rasino.tistory.com/326

#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // 아두이노 2번을 HC-12 TX Pin에 연결, 3번을 HC-12 RX Pin에 연결.
void setup() { 
  Serial.begin(9600); // Computer ↔ 시리얼포트(아두이노) 통신속도 
  HC12.begin(9600);   //             시리얼포트(아두이노) ↔ HC12   통신속도 
  Serial.println("This is 'A' HC-12 Module");   // 2번째 아두이노 코드는 'B'로 변경 
} 
void loop() { 
  // 시리얼모니터로 수신(입력)데이터가 있을 경우 HC12를 통해 데이터를 발송  
  while (Serial.available()) { 
    String input = Serial.readString();
    HC12.println(input);
  } 
  // HC12모듈이 받은 데이터가 있을 경우 시리얼모니터로 출력
  while (HC12.available()) { 
    String input = HC12.readString();
    Serial.println(input);
  } 
  delay (20);
}



《아두이노 B 회로용 코드》 

// $$$  'B' HC-12 모듈  $$$
// 시리얼 모니터를 통한 시리얼 통신 실습입니다.
// HC12모듈을 연결한 동일한 회로 두 개를 준비합니다 (아래 링크 참조)
// RasINO IoT : https://rasino.tistory.com/326

#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // 아두이노 2번을 HC-12 TX Pin에 연결, 3번을 HC-12 RX Pin에 연결.
void setup() { 
  Serial.begin(9600); // 시리얼포트 ↔ computer 
  HC12.begin(9600);   // 시리얼포트 ↔ HC12 
  Serial.println("This is 'B' HC-12 Module");
} 
void loop() { 
  // 시리얼모니터로 수신(입력)데이터가 있을 경우 HC12를 통해 데이터를 발송
  while (Serial.available()) { 
    String input = Serial.readString();
    HC12.println(input);
  } 
  // HC12모듈이 받은 데이터가 있을 경우 시리얼모니터로 출력
  while (HC12.available()) { 
    String input = HC12.readString();
    Serial.println(input);
  } 
  delay (20);
}


 《 위 코드 다운로드 》
아래 파일을 다운로드하여 압축을 풀어보면, 두 개의 파일이 나옵니다.  A 파일은 아두이노 회로 하나에 업로드하고, B 파일은 나머지 아두이노 회로에 업로드합니다.  하지만 실행되는 코드 내용은 같기 때문에 A나 B파일 하나만 가지고 양쪽 모두에 업로드해도 상관없습니다.  하지만, 실행 과정에서는 각각의 A, B 파일이 따로 존재해야 실습을 진행할 수 있습니다.

(실습 1) Serial Communication.zip
0.00MB


▶ 실행 방법 및 결과

: 코드를 업로드 후 아래 순서로 진행하세요. (HC12 모듈을 연결한 아두이노 회로 하나를 편의상 'A'회로라고 하고 동일한 나머지 아두이노 회로를 'B'회로라고 부를게요.)

1.  'A 회로'를 PC의 USB에 연결합니다.  인식된 포트를 확인하고  업로드할 때 사용하였던 A 아두이노 코드를 열고, 보드(나노) 정보를 선택한 다음, 아두이노 나노가 인식된 포트를 선택해 줍니다. 
2. 이어서, 'B 회로'를 PC의 USB에 연결합니다.  인식된 포트를 확인하고  B 아두이노 코드를 직접 클릭해서 여세요. 
보드(나노) 정보를 선택한다음, 아두이노 나노가 인식된 포트를 선택해 줍니다. 

※ 주의 : 일반적으로 윈도 PC에서 시리얼 포트로 아두이노를 두 개까지 포트를 구분해서 인식할 수 있습니다.  
즉, 장치 자체는 인식하고 코드 업로드도 가능하나, 서로 다른 포트로 할당받는 것은 두 개까지만 가능하다는 말입니다.

★☆★ 아두이노 두 개를 하나의 PC에서 서로 다른 시리얼 포트로 인식시키는 방법 ★☆★
 주의해야 할 것은,  A회로 코드를 열었던 아두이노 IDE의 파일 메뉴에서 '열기' 메뉴로 'B'아두이노 파일을 추가로 열게 되면 아두이노-IDE를 두 개 열어도 둘 다 하나의 포트 쪽으로만 인식이 되는 문제가 생길 수 있습니다.
 비록 화면에 뜬 아두이노 IDE 코드 파일은 두 개로 열려 있으나,  아두이노 회로 두 개를 같이 물려보면, 두 회로 모두 동일한 포트 번호로만 할당됩니다.   그러면, 포트 번호가 같기 때문에 아두이노 회로는 한 번에 하나씩만 동작되어서, 
하나의 PC에서 두 회로 간 통신 실험을 진행할 수 없게 됩니다.  따라서,  파일 탐색 창을 열고 'A 아두이노 파일'과 'B 아두이노 파일'을 각각 마우스 클릭으로 열어야 합니다.   그래서 아두이노 두 대를 연결해보면 서로 다른 포트로 할당받게 되고, PC 하나로 원격으로 이루어지는 것과 같은 시리얼 통신 실험을 해볼 수 있게 됩니다.  ( 두 대까지만 가능!  두 대 이상 연결 시에는 한 대를 제외한 나머지 보드는 같은 포트로 중복인식됨)

3.  아래 이미지처럼, 화면에 'A회로 시리얼 모니터 창'과  'B회로의 시리얼 모니터 창' 두 개를 나란히 여세요.
(반드시 포트 번호가 서로 다르게 되어 있는지 확인해 주세요)

이미지를 클릭하면 확대 됩니다

4. 각각의 시리얼 모니터 창을 여세요. 
(시리얼 모니터 창에 표시된 보드 레이트 Baud Rate가 코드와 같은 9600 bps로 되어 있는지 확인하세요)


(아두이노 연결)  두 개 이상은 같은 포트 번호로 할당받게 되어 구분이 되지 않게 됩니다. 
(동작 화면)  동작은 아래처럼 A-Nano 회로가 연결된 시리얼-모니터 입력창에 문자를 입력하면,  B-Nano 회로가 연결된 시리얼-모니터 화면으로 출력됩니다.   그리고,  양방향 통신이 가능한 모듈이고 코딩도 양방향이 되도록 해 두었기 때문에,  반대로 B-Nano 회로의 시리얼-모니터 입력창에 문자를 입력하면, A-Nano 회로가 연결된 시리얼-모니터 화면으로 출력되는 것을 볼 수 있습니다.

▶ 동작 영상
(본 글 제일 아래 전체 동영상을 참고해보세요 : 음성 설명 있음)

 

【  실습  #2 】 무선 RF로 여러 곳의 LED를 On/Off 하기

: 무선으로 멀리 떨어진 곳의 LED 들을 On/Off , 켜고 끄는 실습입니다.   지금은 LED를 예시로 들지만, 무선으로 LED를 제어할 수 있다는 뜻은 전등이 되었든 모터가 되었든 필요한 부가 장치만 달아주면 충분히 제어할 수 있음을 의미합니다.  예를 들어, 220V로 동작하는 전등을 무선으로 On/Off 하고 싶다면, 릴레이 모듈을 추가해주면 쉽게 해결할 수 있습니다.   

아래 회로 연결도를 구성해 주고 PC와 연결합니다.
▶ 회로 연결도 
(아두이노 나노와 RF 무선통신 모듈 HC12 연결도)
《 실습 2 :  A-Nano 기본회로 》

(실습2) A-Nano 기본회로

  
《 실습2 : B-Nano LED 회로 》

《 실습2 : B-Nano LED 회로 》

▶ 실습 준비 :
 위의 회로 두 가지를 준비해주세요.    LED의 색과 크기는 상관없으며, + , - 극성만 잘 구분해서 연결해주세요. 
저항 역시, 100옴~470옴 사이의 저항 값이면 어느 값이든 사용할 수 있습니다.  저항이 작을수록 LED 빛이 더 밝아지며, 저항 값이 클수록 조금 더 어두워지는 차이가 날 뿐입니다.   하지만, 1K옴이 넘어가게 되면 LED를 켤 수 있는 전류를 공급할 수 없어 LED의 동작 확인이 안 될 수 있습니다.
회로는 송신 회로 'A 하나'와,   수신 'LED 회로' 1개 또는 그 이상을 준비할 수 있습니다. 

▶ 아두이노 코드 
(아래 코드  아두이노 A와 / B회로의 코드를 각각 구분해서 업로드하세요.)

《아두이노 A 회로용 코드》 

// ###  'A' HC-12 모듈   ###
// 시리얼 통신실습 2편 - 시리얼 모니터 문자 입력으로 LED 제어하기!
// HC12모듈을 연결한 동일한 회로 두 개를 준비합니다 (아래 링크 참조)
// RasINO IoT : https://rasino.tistory.com/326

#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // 아두이노 2번을 HC-12 TX Pin에 연결, 3번을 HC-12 RX Pin에 연결.
void setup() { 
  Serial.begin(9600); // Computer ↔ 시리얼포트(아두이노) 통신속도 
  HC12.begin(9600);   //             시리얼포트(아두이노) ↔ HC12   통신속도 
  Serial.println("This is 'A' HC-12 Module");   
} 
void loop() { 
  // 시리얼모니터로 수신(입력)데이터가 있을 경우 HC12를 통해 데이터를 발송  
  while (Serial.available()) { 
    String input = Serial.readString();
    HC12.println(input);
  } 
  // HC12모듈이 받은 데이터가 있을 경우 시리얼모니터로 출력
  while (HC12.available()) { 
    String input = HC12.readString();
    Serial.println(input);
  } 
  delay (20);
}


《아두이노 B , C , D 회로용 코드》 
B회로 하나만 가지고 실습할 수 있으며, 만약 C, D회로를 추가로 늘릴 경우에는 아래 코드에서 비교문 부분에
L1\r\n,   L2\r\n,   L3\r\n 과 같은 부분만 바꾸어서 업로드하면 됩니다.

// $$$  'L1' HC-12 모듈  $$$
// RasINO IoT : https://rasino.tistory.com/
#define LED_L1 5
#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // HC-12 TX Pin, HC-12 RX Pin 

void setup() { 
  Serial.begin(9600); // Computer ↔ 시리얼포트(아두이노) 통신속도
  HC12.begin(9600);   // 시리얼포트(아두이노) ↔ HC12   통신속도
  Serial.println("This is 'L1' HC-12 Module");
  pinMode(LED_L1,OUTPUT);
  digitalWrite(LED_L1,LOW);  
} 
void loop() { 
  // 시리얼모니터로 수신(입력)데이터가 있을 경우 HC12를 통해 데이터를 발송
  while (Serial.available()) { 
    String input = Serial.readString();
    HC12.println(input);
  } 
  // HC12모듈이 받은 데이터가 있을 경우 시리얼모니터로 출력
  while (HC12.available()) { 
    String input = HC12.readString();
    Serial.println(input);    
    if ( input == "ON\r\n" || input == "L1\r\n" )  { //공백 구분함, line ending없음으로 설정(엔터구분) 
      for (int i=0;i<10;i++) {
        digitalWrite(LED_L1,HIGH);
        delay(200);        
        digitalWrite(LED_L1,LOW);        
        delay(200);        
      } 
    } 
  } 
  delay (20);
}

 《 위 코드 다운로드 》
아래 파일을 다운로드 해서 압축을 풀어보면 아래 파일 4개를 들어 있으며, 필요한 파일만 사용하면 됩니다.

(실습 2) RF 통신 with LED.zip
0.00MB
위 압축파일 속에 이와같은 4개의 파일이 있습니다

▶ 동작 실행(방법)
:  A회로의  아두이노-IDE의 시리얼 모니터 창을 열고 커맨드 입력란에 아래와 같이 입력해보세요.
 -  L1  입력   L1 회로(B회로)의 LED가 10회 깜빡입니다. 
 -  L2  입력 →   L2 회로(C회로)의 LED가 10회 깜빡입니다. 
 -  L3  입력 →   L3 회로(D회로)의 LED가 10회 깜빡입니다. 
 -  ON 입력 →   L1, L2, L3 회로의 모든 LED가 10회 깜빡입니다.


코드에서 중요한 부분을 설명드리면,   시리얼 모니터 입력창을 통해 입력한 문자는 L1  또는 ON이라는 문자만 입력되는 것이 아니라, 눈에는 보이지 않지만,  엔터키를 누르기 때문에(전송 버튼 누름도 마찬가지)  줄 바꿈에 해당하는 개행 문자가 입력되게 됩니다.   따라서 이 개행 문자도 함께 비교해 주어야 코드의 if 비교문이 제대로 작동합니다. 

엔터입력하면 개행문자(\r\n) 입력됨

 따라서  아래와 같은 코드 형태로 비교해 주어야 합니다. 
if ( input == "ON\r\n" || input == "L1\r\n" )   { ...  }

또한, 아래처럼, 시리얼 모니터창의 입력 옵션을 line ending 없음으로 해야,  개행 문자 처리가 중복으로 되지 않아 제대로 처리됩니다. 

 

 마지막으로 중요한 한 가지는, 아두이노와 같은 C/C++ 언어 프로그래밍에서 개행 문자의 처리가 운영체제 별로 다르다는 데 있습니다. 
최근에는 아두이노 코딩 환경을 윈도 환경에서 뿐 아니라, 리눅스나 맥 OS 환경에서 많이 하는 것을 볼 수 있는데요,
아래 운영체제 별 개행 문자 처리를 참고하여,  코드에 반영해 주어야 합니다.  ( '\' 표시는 역슬래시입니다)
 → Windows OS 개행 문자 :   \n\r
 → Mac OS 개행문자        :   \r
 → Linux 개행문자           :   \n

 

▶ 동작 영상
(본 글 제일 아래 전체 동영상을 참고해보세요 : 음성 설명 있음)

 

【 센서 실습  #3 】  LED의 밝기를 무선으로 조절하기(with VAR)

: 실습 #3에서는 가변저항 또는 볼륨으로 불리는 VAR(Variable resistor, 또는 Potentiometer)을 이용하여 원격지에 있는 회로의 LED의 밝기를 조절해 보는 실습입니다. 
 또한, VAR 쪽의 송신부에도 LED를 달아서 VAR 값의 변화가 제대로 되는지? 먼저 확인할 수 있도록 하였습니다

▶ 회로 연결도 (VAR이 연결된 회로와 LED 수신 회로 두 가지를 만드세요)
《 회로 1 :  VAR - Nano 송신 회로 》

《 회로 2 :  VAR - Nano 송신 회로 》


▶ 실습 준비 :
 위의 회로 두 가지를 준비해주세요.  가변저항은 여러 가지 종류가 있으며, 어떤 종류를 사용하더라도 사용이 가능합니다. 용량 또한,  1K옴~1M옴 사이의 용량이면 회로를 구성하는데 크게 문제없습니다. (권장, 1K옴~10K옴 사이)

여러가지 가변(반고정) 저항의 종류들

 본격적인 실습 전에,  가변저항의 역할과 활용에 대해 설명드립니다. 

- VAR의 ①번과 ③번 양단에 5V의 전압을 넣어 주면, ②번 단자로 전압이 나오게 되는데요,
VAR 조절 레버를 ①번 끝에서 ③번 끝까지 돌림에 따라, ②번으로 5V~0V 사이의 전압이 출력됩니다.
그리고, VAR의 ②번 단자 출력을 아두이노의 아날로그 입력 단자로 연결하였는데요,
아두이노 내부의 아날로그 입력 단자들에 연결된 AD Converter(Analog to Digital)에 의해 '0~5V'라는 아날로그 값이,  '0~1023'라는 디지털 수치로 변환되어 전달받게 됩니다.
나노(우노)에 내장된 ADConverter는 10bit의 분해능을 갖고 있어 최댓값은 2의 10승 값인 1024가 됩니다.
그리고 아두이노의 출력 단자는 디지털 단자여서 기본적으로 Low(0v)와 High(5v)의 값만 출력되는데요
LED의 밝기를 조절하려면, 0v~5v 사이의 아날로그 값이 필요합니다.

아두이노의 디지털 단자 중에서 아날로그와 같은  출력을 대신해 주는 단자가 PWM 출력 단자인데요.
High와 Low신호의 출력 비율(Duty Cycle)을 조절하여, 출력 전압이 조절되는 효과를 얻을 수 있습니다

아두이노에서는 디지털 단자의 숫자 옆에 '~'물결 기호가 붙어 있는 단자가 바로 PWM기능이 있는 디지털 단자입니다
( ※ Uno와 Nano의 PWM 단자: D3 ,D5, D6, D9, D10, D11 )

~ 물결무늬가 있는 핀이 PWM 출력 기능이 있는 핀입니다

아두이노의 아날로그 입력이 어떻게 디지털 값으로 변환되고 다시 아날로그 형태(디지털 PWM)로 출력되는지 아래 이미지와 함께 설명드리면, 
 나노(우노) 보드의 PWM 포트 출력은 8bit로 처리되기에, 2의 8승 값인, 0~255 사잇값으로 출력됩니다

그런데, A0로 입력된 값은 0~1023 값이고, 출력할 수 있는 최대 범위는 0~255이기 때문에, 입·출력의 매칭이 필요한데요, 아두이노 코드에서 맵핑 함수를 사용하면 간단히 해결할 수 있습니다

0~1023의 범위 값을 0~255값으로 맵핑하는 함수 사용

이렇게 해서 VAR가변저항을 돌려 변화되는 아날로그 입력 전압이(0~5V) 나노의 High(5V), Low(0v) 기능만 할 수 있던 디지털 출력 포트로 PWM 기능을 사용하여 0~5v의 변화되는 출력을 낼 수 있게 되어 LED의 밝기 조절이 가능해집니다. 


▶ 아두이노 코드 
( 아래의 코드 두 가지를 구분해서 각각 아두이노에 업로드해주세요. )
《 회로 1 : VAR 회로 코드 》

// VVVVV  HC-12 'VAR-side' 가변저항 회로 코드   VVVVV
// RasINO IoT : https://rasino.tistory.com/
#define LED_L1 5
#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // HC-12 TX Pin, HC-12 RX Pin 

int Var = 0;

void setup() { 
  Serial.begin(9600); // Computer ↔ 시리얼포트(아두이노) 통신속도
  HC12.begin(9600);   //             시리얼포트(아두이노) ↔ HC12   통신속도
  Serial.println("This is 'VAR controller' HC-12 Module");
  pinMode(LED_L1,OUTPUT);
  digitalWrite(LED_L1,LOW);  
} 
void loop() { 
  Var = map(analogRead(A7), 0, 1023, 0, 255);
  analogWrite(LED_L1, Var);
  Serial.println(Var);  
  HC12.write(Var); // 주의! : 'print()'가 아닌, 'write()'를 사용합니다
  // ※ 'print()'는 숫자의 경우 ASCII값으로 변환하여 전송하기 때문에, 
  // 숫자값 그대로 전송하는 'write()'를 사용합니다
}


《 회로 2 : LED 회로 코드 》

// ### HC-12 'LED-side' 가변저항(LED) 회로 코드   ###
// RasINO IoT : https://rasino.tistory.com/
#define LED_L1 5
#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // HC-12 TX Pin, HC-12 RX Pin 
void setup() { 
  Serial.begin(9600); // computer ↔ 시리얼포트(아두이노) 통신속도
  HC12.begin(9600);   // 시리얼포트(아두이노) ↔ HC12   통신속도
  Serial.println("This is 'LED' Side HC-12 Module"); 
  pinMode(LED_L1,OUTPUT);
  digitalWrite(LED_L1,LOW);  
} 
void loop() { 
  while (HC12.available()) { 
    int input = HC12.read();
    Serial.println(input);
    analogWrite(LED_L1, input);    
  }   
}


《 위 코드 다운로드 》

(실습 3) Var-LED.zip
0.00MB

▶ 동작 실행(방법)
:  VAR이 연결된 나노 회로의 VAR을 한쪽 끝에서 다른 쪽 끝으로 돌려보면 RF 신호를 수신한 LED 회로의 LED의 밝기가 조절됩니다.  이때 보조배터리와 같은 외부 전원만으로도 동작시킬 수 있으며, PC에 연결해서 실습을 진행할 경우 시리얼 모니터 창을 띄우면, 변환되는 0~255 값을 함께 확인할 수 있습니다.

▶ 동작 모습

▶ 실행 영상
(제일 아래 전체 설명 동영상 참고)

【 실습  #4 】
시리얼 통신#1 (AT-커맨드 명령어 사용하기)

: 실습 #4에서는 AT-커맨드 명령어를 사용하여 HC-12 모듈의 설정을 바꾸어 보겠습니다.  이번 실습 4는 #1편과 #2편으로 구분되어 있습니다.
PC와 연결하고 아두이노-IDE의 시리얼 모니터를 사용하여 AT-통신 명령어를 입력하면, HC-12의 '통신 채널 변경', 'Bauds Rate', '통신 모드'와 같은 설정을 변경할 수 있습니다.  AT-명령어 모드로 진입하기 위해서는, HC12 모듈의 SET 단자가 GND(Low)로 연결되어 있어야 합니다.  

▶ 실습 준비 : 회로는 하나만 준비하면 됩니다.  상호 통신이 아니라 PC와 연결하여 AT  명령어를 이용한 HC-12 모듈의 설정 변경 실습이기 때문에, 회로는 하나를 준비하고,  실습은 2가지로 진행합니다. 

▶ 회로 연결도
《 실습 4-1의 회로 :  Set 핀 - GND 연결된 회로 》

▶ 아두이노 코드 
( 아래의 코드를 업로드해주세요. )
《 실습4-1 회로 코드 》

// ###  'AT-Command'  실습     ###
// AT-명령어를 통하여 HC12의 채널/속도/모드... 등을 변경해 보는 실습
// HC12모듈을 연결한 회로를 준비합니다 (아래 링크 참조)
// RasINO IoT : https://rasino.tistory.com/326

#include <SoftwareSerial.h>
SoftwareSerial HC12(2, 3);

void setup() 
{
  Serial.begin(9600); // Computer ↔ 시리얼포트(아두이노) 통신속도 
  HC12.begin(9600);   //             시리얼포트(아두이노) ↔ HC12 통신속도 
}
void loop() 
{   
  while (Serial.available()) {
    HC12.write(Serial.read());
  }
  while (HC12.available()) {
    Serial.write(HC12.read());
  }
}

《 위 코드 다운로드 》

HC12_AT-Change_CH.zip
0.00MB

▶ 동작 실행(방법)
 :  회로를 구성하고 PC와 연결하여 아두이노-IDE의 시리얼 모니터창을 띄우면, AT-명령어 입력 모드 상태가 됩니다.
AT-명령어 모드로 진입하기 위해서는, HC12 모듈의 SET 단자가 GND(Low)로 연결되어 있어야 합니다.

아래, 많은 시간을 들여 직접 정리한 AT-명령어 표를 참고하여 테스트해보세요. 

- '시리얼-모니터' 입력창에 대문자로 'AT '라고 입력하세요.
  'OK'라는 응답 신호가 나온다면, AT-Command 모드 진입에 성공한 것입니다. 

- 'AT+RX'를 입력하면 현재의 주요 설정값을 한 번에 보여줍니다.
- 그리고,  현재 RC001로 '채널 1'로 설정되어 있는 것을 '채널 2'로 바꾸어 보세요.

- 'FUx'모드 설정을 통해 좀 더 특수한 환경에서 동작할 수 있도록 동작 모드를 변경할 수도 있습니다.
만약, FU2와 FU4 모드를 선택한다면, 시리얼 포트 통신속도는 제한된 속도로 자동 변경됩니다.

만약, FU2와 FU4 모드를 선택한다면, 위 이미지의 FUx 모드 상세 설명에서 처럼, 시리얼 포트 통신속도는 제한된 속도로 자동 변경됩니다.
- 송신 파워 설정도 변경해 보세요.


- 'AT+DEFAULT' 명령어로 바뀐 설정을 한 번에 복구할 수 있습니다

- 마지막으로 HC12 모듈의 셋업 설정이 마무리 하였다면,   SET핀을 GND에 연결하였던 선을 제거해야, 
HC12모듈의 통신이 가능하다는 것을 기억하세요.

 

시리얼 통신#2 (AT-커맨드 명령어 사용하기)

이번 실습 4-1는 셋업을 직접 손으로 SET-GND 핀을 연결하지 않고, 프로그램 코딩으로 아두이노의 아웃풋 출력 단자를  LOW / High 출력으로 조절하여 설정하는 실습입니다.   손이 아닌, 코드로 셋업을 조절하게 되면, 채널 변경이나, 모드 변경 등과 같은 기능들을 코드나, 스위치 조작 등 더 다양하게 활용할 수 있게 됩니다. 
▶ 회로 연결도

《 실습 4-2의 회로 :  Set 핀 - 디지털 입출력 핀 연결된 회로 》

SET 핀의 아두이노 포트 연결은 아무 디지털 출력 포트로 선택하면 됩니다.  여기서는 D6번 핀으로 하였고, 코드에도 6번으로 되어 있으니 변경하려 한다면, 코드의 핀 번호를 수정하세요.

▶ 아두이노 코드 
( 아래의 코드를 업로드해주세요. )
《 실습 4-1 회로 코드 》

// ###  'AT-Command'  실습     ###
// HC12 모듈의 Setup Pin을 활용한 HC12의 채널/속도/모드... 변경 실습 
// HC12모듈을 연결한 회로를 준비합니다 (아래 링크 참조)
// RasINO IoT : https://rasino.tistory.com/326

#include <SoftwareSerial.h>
SoftwareSerial HC12(2, 3);
#define setPin 6  // HC12 모듈의 SET 핀에 연결될 아두이노 핀 번호 정의 함

void setup() 
{
  Serial.begin(9600);
  HC12.begin(9600);
  pinMode(setPin,OUTPUT);
  digitalWrite(setPin,LOW);  //  AT command mode 진입
  delay(100);                // 명령어 전달되는 시간을 기다려 줌 
  HC12.write("AT");          // AT 명령어 입력 ( "OK" 문자 응답)
  delay(300);                // 명령어 전달되는 시간을 기다려 줌 
  HC12.write("AT+C003");       // 현재 HC12의 설정 정보를 보여달라는 명령
  delay(300);                // 명령어 전달되는 시간을 기다려 줌   
  HC12.write("AT+FU2");       // 현재 HC12의 설정 정보를 보여달라는 명령
  delay(300);                // 명령어 전달되는 시간을 기다려 줌   
  digitalWrite(setPin,HIGH); // AT-mode 빠져나옴(data 전송모드)
}

void loop() 
{ 
  while (HC12.available()) {
    Serial.write(HC12.read());
  }  
  while (Serial.available()) {
    HC12.write(Serial.read());
  }

}

《 위 코드 다운로드 》

HC12_AT-Use_Setup_pin.zip
0.00MB

▶ 동작 실행(방법)
 :  회로를 아래와 같이 구성하고 PC와 연결하여 아두이노 코드를 업로드하면, 코딩 루틴에 의해 자동으로 채널이 001번 채널에서 002번 채널로 변경되게 됩니다.  

 그럼, 코딩에 의해 자동으로 채널이 변경된 것인지? 확인하기 위해,  그래서 AT 모드로 진입하기 위해 다시 아래처럼, 6번 핀에 연결된 SET-핀을 뽑고,  직접 GND에 연결해 주세요. 

그리고, 아두이노-IDE의 시리얼 모니터 창을 열어 AT+RX 명령어로, 설정 상태를 확인해보면, 채널이 002번 채널로 변경되어 있는 것을 확인할 수 있게 됩니다.
▶ 동작 모습

그럼, 코드를 수정해서, 다른 AT-명령어도 넣어서 적용해 보세요.  (아래는 예시입니다)


이렇게, SET핀을 아두이노 포트로(코드로) 제어하게 되면, 이어지는 실습에서처럼, 버튼으로 채널을 변경하거나, 통신 모드 변경과 같은 것을 쉽게 구현할 수 있습니다.

【 실습  #5 】  무선 버튼으로 통신채널 변경하기

: 실습 #5에서는 '버튼 1'을 누르면, 통신채널 1번으로 동기화되고, '버튼 2'를 누르면, 통신채널 2번으로 동기화되는 실습입니다.  실습#4를 응용한 실습인데요, 버튼 수를 늘려서 변경되는 채널 수를 늘릴 수도 있고, 통신 모드 변경이나 파워 설정 같은 AT모드상에서 변경할 수 있는 것들을 이번 실습을 통해 쉽게 적용시킬 수 있습니다.  

▶ 실습 준비 : 회로는 두 가지를 준비합니다.  버튼(스위치) 2개가 들어간 1번 회로와,  신호를 수신하여 적용되었다는 것을 알 수 있도록 LED를 연결한 2번 회로로 구성됩니다.    또한, 무선 RF의 장점인 채널이 일치하면 1대 N의 통신이 가능함을 보여드립니다.  이 때는 똑같이 적용된 2번 회로가 2개 이상 필요합니다.  기본적으로, 2번 회로 하나만 있어도 실습 5의 학습은 가능합니다. 

[ 회로에 사용된 푸시버튼스위치(PB-SW) 설명 ] 
 아두이노에서 PB-SW는 보통 High 신호와 Low 신호를 입력하고자 할 때 사용하게 되는데요, 
스위치 한쪽을 GND로 연결하고, 나머지 한쪽은 저항을 통하여 VCC로 연결하게 되는데요, 
버튼을 누를 때는 GND로 연결되기 때문에, Low 신호가 아두이노 포트에 입력되며,
버튼을 누르지 않았을 때는 GND와 분리되고, 저항을 통해 VCC로 연결되기 때문에 High 신호가 입력됩니다. 
이때, 저항의 역할은 기본적으로 스위치를 누를 때 GND와 VCC가 합선(Short)되는 것을 방지하고, 누르지 않았을 때는, 확실한 High 신호를 입력되게 하는 역할로 사용되며, 이런 저항의 역할을 바로 풀업(Pull UP) 저항이라 합니다. 
이와 반대되는 개념의 저항을 풀다운(Pull Down) 저항이라 합니다. 

외부 풀업저항 연결

위, 이미지에서 스위치를 닫으면 GND(그라운드, 혹은 0V)에 연결되어 Low 신호가 아두이노의 D5번 포트로 입력되게 되며, 스위치를 오픈하면, 5V의 High 신호가 저항을 타고 D5로 입력되는 구조입니다.    여기서  만약에 저항을 연결하지 않고 직접 5V 전원을 D5로 연결시킬 경우, 스위치를 닫을 때, GND와 5V가 직접적으로 맞닿아 합선(Short)되어 문제가 생기게 되어 저항이 필요하며,   만약 저항과 5V 연결 자체를 하지 않게 될 경우, 스위치를 닫을 때는 확실한 Low신호가 입력되나, 스위치를 오픈할 경우에는 확실한 High 신호가 입력되지 않아 불안정해집니다.  따라서, 이런 이유 때문에 스위치와 함께 사용하게 되는 저항을 일컫어,  확실하게 +전원(5V, VCC)으로 끌어올린다(당긴다)하여, Pull UP 저항이라 칭합니다.   마찬가지로, 아래와 같은 연결의 저항을 풀 다운 저항이라 칭합니다. 

풀 다운(Pull Down) 저항과 스위치의 연결

그런데,  아두이노를 설계할 때, 각 포트마다 스위치를 연결할 경우 필요한 풀업 저항의 연결을 최소화하고자 하는 목적으로 내부 풀업 저항이 설계되어 있습니다. 

따라서, 외부에 별도의 풀업용 저항을 연결할 필요 없으니 회로 구성을 더욱 간단히 할 수 있어 편합니다. 
그럼, 풀업 저항의 기능을 활성화하기 위해서는 아두이노 코드에서,  해당 포트의 입력을 풀업 기능으로 설정만 해주면 됩니다. 
일반 적으로 아두이노 코드에서 예를 들어, D5번 포트를 입력으로 설정할 경우에는, 
pinMode ( 5, INPUT );   이렇게 작성하나,    풀업 기능의 입력을 사용할 경우에는 
pinMode ( 5, INPUT_PULLUP );   이라고 설정해주면 됩니다. 

▶ 회로 연결도(VAR이 연결된 회로와 LED 수신 회로 두 가지를 만드세요)
《 회로 1 :  버튼스위치(PB-SW) Nano 회로 》
회로 1에서도 버튼을 눌렀을 때, 눌러졌다는 것을 알기 위해 LED를 연결해 놓았습니다.

《 회로 2 :  LED - Nano 회로 》

▶ 아두이노 코드 
( 아래의 코드를 업로드해주세요. )
《 실습 5  버튼 스위치 1번 회로 코드 》

/* 《 버튼으로 통신채널 변환하기 》 --- 1번 Nano (버튼 회로) ---  
 * AT명령어를 수정하면 통신속도(거리)/ 동작(통신)모드 / 슬립모드 / 송신파워 등의 설정이 가능함 
 * 회로의 상세자료 및 설명은 게시글 참조 : https://rasino.tistory.com/326
*/

#include <SoftwareSerial.h>  //소프트웨어 시리얼 연결은 2번, 3번 이외의 비어있는 다른 디지털 핀을 사용해도 됨
SoftwareSerial HC12(2, 3);   // (HC12의 TX Pin, HC12의 RX Pin)을 연결할 아두이노 포트 지정 (2번, 3번)
#define setPin 6    // HC12의 SetPin 연결 (AT모드 진입에 사용되는 핀)  
#define btn1 5      // '버튼 1' 연결
#define btn2 9      // '버튼 2' 연결 
#define led 12      // 버튼을 누를 때 확인하기 위한 LED 연결

byte incomingByte;        // 수신 데이터를 바이트 단위로 저장하는 변수 선언
String readBuffer = "";   // 송·수신 데이터 저장을 위한 문자열 변수 선언
int btn1_State = 0;       // 버튼 1의 상태
int btn1_Pressed = 0;     // 버튼 1의 눌러짐 체크 변수
int btn2_State = 0;       // 버튼 2의 상태  
int btn2_Pressed = 0;     // 버튼 2의 눌러짐 체크 변수

void setup() {
  Serial.begin(9600);           // PC와의 시리얼 통신 포트 열기(시작)
  HC12.begin(9600);             // HC12의 시리얼 포트 열기(시작)
  pinMode(setPin, OUTPUT);      // HC12의 AT 모드 진입을 위한 아두이노 연결핀 출력설정
  pinMode(btn1, INPUT_PULLUP);  // 버튼 1을 저항 연결 없이 내부 풀업을 사용하여 연결함
  pinMode(btn2, INPUT_PULLUP);  //     2를 
  pinMode(led, OUTPUT);         // 버튼 입력 표시를 위한 LED 연결  
  digitalWrite(setPin, HIGH);   // HC-12를 일반적인 전송 모드로 설정함 (LOW 일경우 AT 커맨드 모드로 진입함)
  digitalWrite(led,LOW);        // LED OFF로 디폴트 설정
  Serial.println("This is ** Nano1 ** , i'm ready!");
}

void loop() {
  // 문자열 변수 버퍼에 HC12의 수신 데이터 저장
  while (HC12.available()) {             // HC12에 데이터가 있다면
    incomingByte = HC12.read();          // HC12로 부터 바이트(byte) 단위로 읽어 byte타입 변수에 저장
    readBuffer += char(incomingByte);    // 각각의 읽은 바이트를 문자열 변수에 저장 (예시, 'A' 'T' '+' 'R' 'X' → "AT+RX")
  }
  delay(100);
  // 시리얼 데이터가 있을 경우 HC12(1번 nano)의 데이터를 외부 다른 HC12(2번 nano)로 발신
  while (Serial.available()) {
    HC12.write(Serial.read());
  }

// 〔 #####  버튼1이 눌러지면, HC12의 채널을 '001'로 설정하는 루틴의 시작 ##### 〕

  btn1_State = !digitalRead(btn1);    // 버튼의 하드웨어 연결이 누르면 LOW, 떼면 HIGH 입력되므로, '!'로 반전 값 저장함
  if (btn1_State == HIGH & btn1_Pressed == LOW) {   // 만약 버튼1이 눌러지고, 버튼1 눌러짐 체크 변수가 LOW 였다면
    btn1_Pressed = HIGH;            // 버튼1 눌러짐 체크 변수를 HIGH로 함                 
    delay(20);
  }
  if (btn1_Pressed == HIGH) {            // 만약 버튼1 눌러짐 체크 변수가 HIGH 라면,    
    digitalWrite(led, HIGH);             // LED를 켜고  
    HC12.print("AT+C001");               // 다른(nano_2번) HC12모듈에 채널 1로 변경하는 신호 발신
    delay(100);                          // 신호 발신 시간 기다려줌
    // AT 명령어 모드로 진입하는 루틴 시작 (nano_1번)
    digitalWrite(setPin, LOW);           // HC12의 Set핀에 LOW를 입력하여, AT 커맨드(명령어) 모드로 진입함
    delay(100);                          // 시간 딜레이
    HC12.print("AT+C001");               // 채널 1로 변경하는 AT 명령어 보냄
    delay(200);                          // 명령어 적용되는 시간 딜레이
    while (HC12.available()) {           // HC12에 데이터(여기선, AT-명령어 응답 신호)가 있는지가 있는지 체크하여 
      Serial.write(HC12.read());         // 데이터를 시리얼 모니터로 전송
    }
    Serial.println("btn 1 pressed, changing Channel 《 No.1 》");
    digitalWrite(setPin, HIGH);          // 셋핀을 HIGH로 입력하여 AT 커맨드 모드를 빠져나옴
    digitalWrite(led, LOW);              // 버튼을 누를때 켰던 LED를 끔
    btn1_Pressed = LOW;                  // 버튼 눌러짐 체크 변수를 LOW로 함 
  }
// ######################################
  
// 〔 $$$$$  버튼2가 눌러지면, HC12의 채널을 '002'로 설정하는 루틴의 시작 $$$$$ 〕
  btn2_State = !digitalRead(btn2);
  if (btn2_State == HIGH & btn2_Pressed == LOW) {
    btn2_Pressed = HIGH;
    delay(100);
  }
  if (btn2_Pressed == HIGH) {       // 만약 버튼2 눌러짐 체크 변수가 HIGH 라면,  
    digitalWrite(led, HIGH);        // LED를 켜고
    HC12.print("AT+C002");          // 다른(nano_2번) HC12모듈에 채널 2로 변경하는 신호 발신
    delay(100);
    // AT 명령어 모드로 진입하는 루틴 시작 (nano_1번)
    digitalWrite(setPin, LOW);      // HC-12의 Set핀에 LOW가 입력되면, AT 커맨드(명령어) 모드로 진입함
    delay(100);                    
    HC12.print("AT+C002");          // 채널 2로 변경하는 AT 명령어 보냄
    delay(200);
    while (HC12.available()) {      // HC12에 데이터(여기선, AT-명령어 응답 신호)가 있는지가 있는지 체크하여 
      Serial.write(HC12.read());    // 데이터를 시리얼 모니터로 전송
    }
    
    Serial.println("btn 2 pressed, changing Channel 《 No.2 》");
    digitalWrite(setPin, HIGH);     // 셋핀을 HIGH로 입력하여 AT 커맨드 모드를 빠져나옴
    digitalWrite(led, LOW);         // 버튼을 누를때 켰던 LED를 끔
    btn2_Pressed = LOW;
  }
  checkATCommand();                // AT 명령 응답신호 체크함수 호출 
  readBuffer = "";                 // 버퍼를 비움
}

// 시리얼모니터를 통해 AT 명령어를 잘 전달 받았는지, 체크하는 서브함수
void checkATCommand () {
  if (readBuffer.startsWith("AT")) {     // 버퍼에 'AT'로 시작되는 문자열이 있는지 확인
    digitalWrite(setPin, LOW);           // HC-12를,  AT 커맨드 모드로 진입
    delay(100);                          // 시간 딜레이
    HC12.print(readBuffer);              // 버퍼에 있는 내용을 HC12로 보냄
    delay(200);                          // 시간 딜레이
    while (HC12.available()) {           // HC12에 AT-응답 신호가 있는지가 있는지 체크하여 
      Serial.write(HC12.read());         // 시리얼 모니터로 전송
    }
    digitalWrite(setPin, HIGH);          // AT 명령어 모드를 빠져나옴
  }
}

《 위 코드 다운로드 》

btn_SW_One.zip
0.00MB


《 실습5  LED 2번 회로 코드 》

/* 《 버튼으로 통신채널 변환하기 》 --- 2번 Nano (LED 회로) ---  
 * AT명령어를 수정하면 통신속도(거리)/ 동작(통신)모드 / 슬립모드 / 송신파워 등의 설정이 가능함 
 * 회로의 상세자료 및 설명은 게시글 참조 : https://rasino.tistory.com/326
*/

#include <SoftwareSerial.h>
SoftwareSerial HC12(2, 3);  // (HC12의 TX Pin, HC12의 RX Pin)을 연결할 아두이노 포트 지정 (2번, 3번)
#define setPin 6     // HC12의 SetPin 연결 (AT모드 진입에 사용되는 핀)
#define led 5        // 채널이 변경 되었음을 표시하기 위해 LED를 연결함

byte incomingByte;          // 수신 데이터를 바이트 단위로 저장하는 변수 선언
String readBuffer = "";     // 송·수신 데이터 저장을 위한 문자열 변수 선언

void setup() {
  Serial.begin(9600);         // PC와의 시리얼 통신 포트 열기(시작)
  HC12.begin(9600);           // HC12의 시리얼 포트 열기(시작)
  pinMode(setPin, OUTPUT);    // HC12의 AT 모드 진입을 위한 아두이노 연결핀 출력설정
  pinMode(led, OUTPUT);       // 버튼 입력 표시를 위한 LED 연결 
  digitalWrite(setPin, HIGH); // HC-12를 일반적인 전송 모드로 설정함 (LOW 일경우 AT 커맨드 모드로 진입함)
  digitalWrite(led,LOW);      // LED를 OFF로 디폴트 설정  
  Serial.println("This is $$ Nano2 $$ , i'm ready!");
}

void loop() {
  // 문자열 변수 버퍼에 HC12의 수신 데이터 저장
  while (HC12.available()) {             // HC12에 데이터가 있다면
    incomingByte = HC12.read();          // HC12로 부터 바이트(byte) 단위로 읽어 byte타입 변수에 저장
    readBuffer += char(incomingByte);    // 각각의 읽은 바이트를 문자열 변수에 저장 (예시, 'A' 'T' '+' 'R' 'X' → "AT+RX")
  }
  delay(100);
  // 시리얼 데이터가 있을 경우 HC12로 발송
  while (Serial.available()) {
    HC12.write(Serial.read());
  }
  
  // ### nano1번의 버튼1이 눌러질 때 전송받은 데이터가 "AT+C001"이라면, 여기 Nano2에서 HC12의 채널을 '001'로 설정하는 루틴  ###
  
  if (readBuffer == "AT+C001") {         // 만약 버퍼에 저장된 데이터가 "AT+001"이라면,
    digitalWrite(led, HIGH);             // LED를 켜고, 
    digitalWrite(setPin, LOW);           // HC12의 Set핀에 LOW를 입력하여, AT 커맨드(명령어) 모드로 진입함
    delay(100);                          // 시간 딜레이
    HC12.print(readBuffer);              // 버퍼에 있는 데이터로(채널 1로 변경하는 "AT+C001") AT 명령어 보냄
    delay(200);                          // 명령어 적용되는 시간 딜레이
    while (HC12.available()) {           // HC12에 데이터(여기선, AT-명령어 응답 신호)가 있는지가 있는지 체크하여 
      Serial.write(HC12.read());         // 데이터를 시리얼 모니터로 전송
    }
    Serial.println("Channel successfully changed, 《 No.1 》");
    digitalWrite(led, LOW);              // LED를 끔 
    digitalWrite(setPin, HIGH);          // 셋핀을 HIGH로 입력하여 AT 커맨드 모드를 빠져나옴
    readBuffer = "";                     // 버퍼를 비움 
  }
  
// ### nano1번의 버튼2가 눌러질 때 전송받은 데이터가 "AT+C002"이라면, 여기 Nano2에서 HC12의 채널을 '002'로 설정하는 루틴  ###
  if (readBuffer == "AT+C002") {        // 만약 버퍼에 저장된 데이터가 "AT+001"이라면, 
    digitalWrite(led, HIGH);            // LED를 켜고
    digitalWrite(setPin, LOW);          // HC12의 Set핀에 LOW를 입력하여, AT 커맨드(명령어) 모드로 진입함
    delay(100);                         // 시간 딜레이
    HC12.print(readBuffer);             // 버퍼에 있는 데이터로(채널 2로 변경하는 "AT+C002") AT 명령어 보냄
    delay(200);                         // 명령어 적용되는 시간 딜레이
    while (HC12.available()) {          // HC12에 데이터(여기선, AT-명령어 응답 신호)가 있는지가 있는지 체크하여
      Serial.write(HC12.read());        // 데이터를 시리얼 모니터로 전송
    }
    Serial.println("Channel successfully changed, 《 No.2 》");
    digitalWrite(led, LOW);             // LED를 끔
    digitalWrite(setPin, HIGH);         // 셋핀을 HIGH로 입력하여 AT 커맨드 모드를 빠져나옴
    readBuffer = "";                    // 버퍼 비움 
  }
  checkATCommand();                     // AT 명령 응답신호 체크함수 호출
  readBuffer = "";                      // 버퍼를 비움
}

// 시리얼모니터를 통해 AT 명령어를 잘 전달 받았는지, 체크하는 서브함수
void checkATCommand () {
  if (readBuffer.startsWith("AT")) {     // 버퍼에 'AT'로 시작되는 문자열이 있는지 확인
    digitalWrite(setPin, LOW);           // HC-12를,  AT 커맨드 모드로 진입
    delay(100);                          // 시간 딜레이
    HC12.print(readBuffer);              // 버퍼에 있는 내용을 HC12로 보냄
    delay(200);                          // 시간 딜레이
    while (HC12.available()) {           // HC12에 AT-응답 신호가 있는지가 있는지 체크하여 
      Serial.write(HC12.read());         // 시리얼 모니터로 전송
    }
    digitalWrite(setPin, HIGH);          // AT 명령어 모드를 빠져나옴
  }
}


《 위 코드 다운로드 》

LED_Two.zip
0.00MB

 

▶ 동작 실행(방법)
 :  SW1을 누르면 채널 1로 설정되고,  SW2를 누르면 채널 2로 설정됩니다.   이때, 코드가 작동되면서 회로 1과 회로 2에 연결된 LED가 점멸하게 됩니다.   아래 이미지처럼, 시리얼 모니터 상에도 채널이 변경된 정보가 뜨도록 처리했습니다.

아래 동작 이미지는 수신 회로 2개를 더 추가하여, 동시에 수신 회로 3개의 채널을 변경되는 것을 보여드리고 있습니다. 

만약, 일부의 채널이 잘 변경되지 않을 경우에는 코드의 delay( )값을 잘 조절해 보거나,   바뀌지 않는 회로의 HC12 모듈의 채널을 확인해 보시기 바랍니다.  채널 변경 실험 과정 등에서, 1 채널 혹은 2 채널이 아닌 아예 다른 채널로 변경되는 경우가 있으니,  이럴 때는, AT통신용 코드를 업로드하여 AT-커맨드 모드에서 채널 확인해보고, 다시 채널을 1번으로 변경하거나, AT+DEFAULT 디폴트로 바꾸어 놓으면 됩니다. 


【 실습  #6 】  RF 무선 조이스틱으로 서보모터 제어하기

: 실습 #6에서는 조이스틱을 이용하여 서보모터 2 개를 무선으로 제어해 보는 실습입니다. 
무선으로 모터 하나를 제어하는 것은 하나의 데이터만 처리하면 됨으로 비교적 쉽지만,  모터 2개를 제어하는 것은 쉽지 않은데요,  시리얼 형태로 날아오는 데이터를 받아서 A 모터 데이터와 B모터 데이터를 구분해서 처리하는 코드 스킬이 필요하기 때문입니다. 
  이번 실습을 통해서 이런 코드 스킬을 익혀둔다면, 다른 작품에도 동일하게 적용할 수 있으니 매우 유익할 것으로 기대됩니다. 



▶ 실습 준비 :   
 회로는 두 가지를 준비합니다.  조이스틱이 연결된 1번 송신 회로와,  서보 모터 2개로 구성된 2번 수신 회로입니다.
서보모터는 SG-90이라는 모터를 사용하였으나, 다른 종류의 서보모터 사용도 가능합니다.
조이스틱의 경우, 제조사에 따라 핀 배열이 본 게시글에서 사용한 것과다를 수 있으니, 갖고 계신 조이스틱의 핀 배열을 확인하고 연결하세요. 


  [ 회로 동작 원리 ] 
조이스틱을 좌우로 움직일 때, VRx로, 전압값(0v~5v)이 나오면, 이를 아두이노의 A0포트로 입력시키고, 
조이스틱을 위아래로 움직일 때, VRy로, 전압값(0v~5v)이 나오면, 이를 아두이노의 A1포트로 입력시키게 됩니다.
그럼, 실습#3 과정에서 설명했듯이, 나노(우노)에서는 10bit의 분해능을 가진 AD Converter에 의해, 아날로그 전압값은(0v~5v) 디지털 값(0~1023)으로 변환되어,  아두이노 코드에서 'analogRead(A0)' 함수를 통해 변환된 데이터를 읽어서 처리할 수 있게 됩니다. 

서보모터 회로에서는 PWM 기능이 있는 포트를 서보모터의 제어선(노란색 데이터선)과 연결하게 되며, 
<Servo.h>라는 라이브러리를 사용하면 servo.write(각도) 형태로 모터의 회전 위치를 제어할 수 있게 되는 원리입니다.

▶ 회로 연결도 (조이스틱이 연결된 송신 회로 1번과,  서보모터 2개가 연결된 수신 회로 2번 두 가지를 만드세요)
《 회로1 :  조이스틱 Nano 회로 》

 조이스틱을 연결할 때는 아래 이미지처럼, 보통 '암-수' 형태의 점퍼 케이블로 연결하게 됩니다. 

하지만, 여기서는 좀 더 간결한 회로를 만들기 위해, 조이스틱의 있는 핀을 구부려서 브레드보드에 직접 연결하였는데요, 
작업 과정에서 핀이 부러지거나 손상될 수 있으니,  조이스틱의 여유 개수가 있는 분만 시도해 보시기 바랍니다. 
방법은 아래 이미지를 보세요, 조이스틱의 핀은,  아래 분홍색 박스의 이미지와 같은 핀헤더로 납땜되어 있습니다. 
그럼, 핀헤더를 고정하고 있는 플라스틱 부분을 니퍼로 사이사이를 잘라내면,  플라스틱 조각은 빠져나오게 되고,  핀의 길이가 구부려도 여유 있는 상태가 됩니다.   그럼, 브레드보드에 밀착시켜서 꽂을 수 있게 됩니다. 



《 회로 2 :  서보모터 Nano 회로 》

서보모터는 회로도처럼 그냥 2개를 연결시켜 놓기만 해도 되지만, 기왕이면, 아래 이미지와 같은 서보모터 틸트 거치대 같은 것을 활용해서 만들어 보면, 곧바로 응용해볼 수도 있고 해서 좋을 것 같네요. 
예를 들어 틸트 위에 소형 아두이노 카메라 모듈이나, ESP32-CAM과 같은 모듈을 부착해서 활용할 수 있겠네요.

그리고, 위 틸트 거치대의 노란색 화살표 부분을 보면, SG90 서보모터에 같이 동봉된 하얀색 핀과  틸트 거치대 홈의 길이가 딱 맞지 않기 때문에 하얀색 핀을 일부 잘라내어야 합니다. 

그리고, 서보모터 커넥터 핀의 기본 스타일은 암놈 형태의 핀으로 되어 있기 때문에,  브레드 보드에 서보모터 커넥터를 연결하려면, 아래 그림과 같은 핀헤더 연결핀이 필요할 수 있습니다. 

만약, 이미지와 같은 핀헤더가 없다면,  굵은 전선(전선 한 가닥으로 된 단선)을 잘라 꽂거나, 혹은  저항이나 LED와 같은 부품의 리드선(다리)을 잘라서 활용해도 됩니다. 

▶ 아두이노 코드 
( 아래의 코드를 각각의 회로에 업로드해주세요. )
《 실습 6 : 조이스틱 1번 회로 코드 》

// === HC-12 'Joystick' Control 회로 코드   ===
// RasINO IoT : https://rasino.tistory.com/326

#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // HC-12 TX Pin, HC-12 RX Pin 
int Jox=0, Joy=0;

void setup() { 
  Serial.begin(9600); // Computer ↔ 시리얼포트(아두이노) 통신속도
  HC12.begin(9600);   // 시리얼포트(아두이노) ↔ HC12   통신속도
} 
void loop() { 
  // 시리얼모니터로 수신(입력)데이터가 있을 경우 HC12를 통해 데이터를 발송
  Jox = map(analogRead(A0),0,1023,0,180);
  Joy = map(analogRead(A1),0,1023,0,180);
  Serial.print(Jox);
  Serial.print("\t");
  Serial.println(Joy);
  // 아래 X 문자를 아스키 값으로 변환되지 않고 그대로 전송하기 위해 write( )함수 사용
  HC12.print(Jox); HC12.write("X"); // 조이스틱 X축 값을 보내고 이어 "X"문자를 전송  
  HC12.print(Joy); HC12.write("Y"); // 조이스틱 Y축 값을 보내고 이어 "Y"문자를 전송
  delay(50);   // 전송 시간 확보를 위한 딜레이   
}

《 위 코드 다운로드 》

HC12_LED_L3_Joy.zip
0.00MB


《 실습6 : 서보모터 2번 회로 코드 》

// ###  HC-12 '서보 x 2 연결 회로 코드'   ###
// RasINO IoT : https://rasino.tistory.com/326

#include <Servo.h>
#include <SoftwareSerial.h> 
SoftwareSerial HC12(2, 3); // HC-12 TX Pin, HC-12 RX Pin 
Servo servo1, servo2;
int servo1Pin=5;  // 1번 서보모터 연결된 아두이노 핀
int servo2Pin=9;  // 2번 서보모터 연결된 아두이노 핀
byte incomingByte;  // 0~255 값 저장할 수 있는 byte변수 선언
String readBuffer = "";
String readBufferX = "";
String readBufferY = "";
int Jox = 0;
int Joy = 0;
int i = 0;
bool x_ready = false;
bool y_ready = false;
bool x_passed = false;
bool data_received = false;

void setup() { 
  Serial.begin(9600); // computer ↔ 시리얼포트(아두이노) 통신속도
  HC12.begin(9600);   // 시리얼포트(아두이노) ↔ HC12   통신속도
  Serial.println("This is 'A-Servo Motor' HC-12 Module"); 
}  

void loop() { 
  while (HC12.available() > 0) { 
    incomingByte = HC12.read();   // 수신 데이터를 byte 단위로 저장
    readBuffer += char(incomingByte); // 수신되는 데이터를 문자형으로 캐스팅하여 문자열 변수(readBuffer)에 쌓아 둠
  }
  delay(70);  // 송신측 전송 delay(50) 타임보다 최소 같거나 더 높이 설정해 주어야 함.
// 송신측(코드)에서 X joy 값을 보내고 "X" 문자를 보낸 후 ,  Y joy값을 보내고 "Y"문자를 보낸 것을 기억하세요.
  while (i <= sizeof(readBuffer)) {
    if (readBuffer[i] == 'X') {
      x_ready = true;
    }
    if (readBuffer[i] == 'Y') {
      y_ready = true;
    }
    if (!x_ready) {
      readBufferX = readBufferX + (readBuffer[i]);
    }
    if (x_passed && !y_ready){
      readBufferY = readBufferY + (readBuffer[i]);
    }
    if (x_ready) {
      x_passed = true;
    }
    i = i+1;
  }
  data_received = true;  
  Jox = readBufferX.toInt();  //문자열로 저장된 X 데이터 값을 정수형으로 변환하여 저장.
  Joy = readBufferY.toInt();  //문자열로 저장된 Y 데이터 값을 정수형으로 변환하여 저장.
  if (data_received) {
    // 데이터 버퍼 변수 들을 리셋.
    readBuffer = "";  
    readBufferX = "";
    x_ready = false;
    x_passed = false;
    readBufferY = "";
    y_ready = false;
    i=0;
  }
  data_received =false;
  servo1.attach (servo1Pin);
  servo2.attach (servo2Pin);  
  servo1.write(Jox);      
  servo2.write(Joy);      
  delay(26); 
  servo1.detach();
  servo2.detach();
  delay(15);   
  Serial.print(Jox);
  Serial.print("\t");
  Serial.println(Joy); 
}

《 위 코드 다운로드 》

HC12_LED_A_Servo.zip
0.00MB


▶ 동작 실행(방법)
 :  전원을 연결하면,  예를 들어 조이스틱을 상하로 움직이면, 1번 서보모터가 상하로 움직이며,   조이스틱을 좌우로 움직이면, 2번 서보모터가 좌우로 움직이게 됩니다. 
그런데, 제가 올린 영상에 보면, 기본적인 서보모터 제어 코드로 제어하게 되면, 대부분의 경우 서보모터 떨림 현상을 겪게 됩니다.   그렇다고 제어가 안 되는 것은 아니고, 제어되기는 하지만, 조이스틱을 움직이지 않을 때는 더욱 심하게 상하 좌우로 떨게 되어, 작품의 완성도가 상당히 떨어지게 됩니다. 
원인은 몇 가지가 있을 수 있겠지만,  지난번에 올린 서보모터 떨림 개선이라는 게시글을 참고해보세요.  떨림 원인과 개선에 대한 자세한 설명되어 있습니다.  (자료 링크 : 
【 아두이노에러해결#4】 서보모터 떨림, 불안정 현상 해결! )
아무튼 본 게시글의 아두이노 코드에는 attach( )함수와, detatch( )함수를 사용한 개선된 코드로 올려져 있으니 떨림이 거의 없게 동작할 거예요.   그럼에도 모터의 떨림이 생길 수 있는데요, 이럴 때는 아래에 표시된 delay( ) 함수의 시간 값을 조금씩 앞뒤로 조절해 보세요. 

 

그리고 당연한 이야기지만, PC 연결에 의존하지 않고, 보조배터리(5V) 연결로도 무선통신이 되며, 잘 작동이 됩니다. 

 

그럼, 끝으로 HC-12 모듈의 주요 장점을 정리해 드리며, 마치도록 하겠습니다. 
본 게시글 끝에 있는 HC-12 모듈에 대한 풀코스 학습 영상과 꼭 같이 보면서 실습을 한다면, 실습을 진행하는데 별 어려움 없이 완료할 수 있을 것으로 생각됩니다. 
감사합니다~ 
그럼, 오늘도 좋은 하루 보내세요~  &^^ 

 

【 HC-12 모듈 풀 코스 학습 영상 】

 아래 영상을 클릭해보세요.

 

 

반응형
반응형

【 아두이노모듈#30】 #1.기울기 센서(6축 가속도&자이로)에 대해 알아봅시다. 

【 기울기 센서 개요 】

자이로 센서(Gyro Sensor)의 원리는  자이로스코프가 내장된 물체가 회전 운동을 하면 생기는 회전 반발력을 측정하여 전기신호로 바꾸어 출력하고 이를 수치화하여 활용하게 됩니다.  그래서 기울기 센서는 가속도 센서와 자이로 센서의 기능을 통합하여 자세나 위치를 추정할 수 있는 장치를 말하며,  이를 활용한 항공기 및 배(Ship) 등에 사용되는 관성항법장치(INS)는 이동거리와 방향까지 추정할 수 있도록 되어 있습니다.

▶ 주요 활용분야 :

센서 주요활용분야: 드론/AR스마트안경/VR고글/나인봇/핏빗, 미밴드/스마트워치/전자수평계 등

 - 드론 : 비행 중인 드론은 현재의 기울기나 위치 파악은 물론이며,  특정 위치에서의 고정 비행을 할 경우 바람 등으로 인하여 원래의 위치와 자세를 유지하는 기능이 필요한데, 가속도 센서와 자이로 센서가 각각 중력가속도와 각속도를 측정하여 얼마나 기울어졌는지를 파악하여 보정할 수 있도록 해줍니다. 
 - VR/AR :  대표적 VR제품인 오큘러스 고글이나 구글 스마트 안경과 같은 AR 제품의 경우 사용자의 머리(얼굴 방향) 움직임이 있을 경우 자이로 센서를 이용하여 회전을 인식하거나 물체와의 위치를 파악하게 해주는 등의 중요한 역할을 합니다.
- 세그웨이나 나인봇 : 사람의 몸이 기울이는 정도와 방향에 따라 세그웨이/나인봇을 제어할 수 있도록 하는 곳에 자이로(가속도) 센서가 사용됩니다.
- 운동 관련 웨어러블 기기인 핏빗이나 샤오미 밴드 , 스마트 워치 등에서 사람의 움직임 등을 파악하기 위해 사용됩니다. 
 이처럼, 기울기 센서(가속도/자이로 센서)는 다양한 곳에 활용되는데요,  대표적으로 많이 사용되는 GY-521(MPU6050) 모듈을 아두이노를 통하여 학습해 본다면,  이후 아두이노와 함께 다양한 응용 작품을 만드는데 좋은 기회가 될 것으로 생각됩니다 ^^.   
라즈이노 IoT에서는 앞으로 몇 회차에 걸쳐 기울기 센서 모듈을 이용해서 흥미로운 학습과제를 진행할 예정입니다. 
본 페이지에서는 GY-521 모듈의 스펙과 기본 사용법에 관련된 학습이 진행됩니다. 

《 GY-521 모듈(MPU-6050 6축-자이로 가속도 센서) 》

GY-521 기울기 센서 앞·뒷면 모습

IMU-6040 기울기 센서 모듈의 동작원리에 대한,  간략한 설명을 드리면, 
센서 이름에 있는 IMU의 뜻은 Inertial Measurement Unit의 약어로, 관성 측정 장치라는 뜻이 있으며,
IMU-6040 모듈에는 X, Y, Z의 3축 가속도 센서와, 3축 자이로 센서, 온도 센서로 구성되어 있습니다. 온도 센서는 가속도 자이로 값이 급격한 온도 변화에 영향을 받을 경우 적용하기 위해 있는 센서로 일반적인 환경하에서는 적용하지 않고 사용하게 됩니다.

기울기는, 자이로 스코프(Gyroscope)로 측정이 가능하며, 가속도 센서로도 측정 가능합니다. 두 가지가 함께 있는 이유는 서로의 단점이 존재하는데, 이를 보완하기 위함이라고 보시면 됩니다. "자이로 스코프"에는 MEMS Gyroscope 라는 칩, 시스템 혹은 센서라고 하는 것이 들어 있습니다.

MEMS 뜻은 "Micro Electro Mechanical System"의 약어로,  MEMS 센서는 칩이 회전 또는 기울어질 때 전압을 출력 시킵니다. 기울어지는 정도에 따라 비례해서 전압값이 다르게 출력됩니다.

이 전압은 칩 내부에서 16bit ADC 컨버터(아날로그 전압을 디지털 숫자 값으로 변환하는)에 의해 16비트(0 ~ 2의 16승 값 범위)값으로 변환 되고, 이 값을 가지고 아두이노 라이브러리와 프로그래밍 코드에서 처리하여 각도 값으로 변환해서 보여주게 됩니다.

 그리고 MPU-6050에는 Accelerometer(가속도 계)라는 측정 센서가 있습니다. 역시, X, Y, Z 3개의 축으로 구성 되어 있으며, 조금 설명하기 쉽게, 어떤 박스 안에 무게가 있는 둥근 공이 있을 때, -X ↔ 공 ↔ +X 예를 들어, X축을 기준으로 -X축 방향으로 박스를 빠르게 밀었을 때, 공은 제자리에 머물러 있게 되는데, 이는 관성에 의해 +X축 방향으로 이동한 것으로 볼 수 있습니다. 센서에서는 이런 움직임에 대해 각 축 별로 전압으로 측정해 내게 되고, 자이로 센서의 경우처럼, 이를 수치 값으로 변환하여 코드에서 기울기 값 등으로 처리 할 수 있게 됩니다.

 MPU-6050은 위 이미지에서 가운데 정사각형의 IC칩 명칭이며, 이 칩을 이용해서 만든 모듈 이름이 GY-521입니다. 따라서 같은 MPU-6050 칩을 사용한 다른 모델 제품도 있을 수 있으며, 경우에 따라 핀 배열이 다를 수 있습니다. 
하지만 GY-521 모듈이 대표적으로 많이 사용되고 있습니다. 

 MPU-6050은 6축의 자유도(DOF : Degree of Freedom)를 가지며,  3축(x, y, z) 가속도계와 3축(x,y,z) 자이로를 합하여 6 축이라고 하며,  또는 3축 가속도+자이로 2축+온도 1축을 합하여 6축이라고도 합니다. (온도 센서가 포함된 이유는 가속도와 자이로 값이 온도에도 영향을 받기 때문에 온도센서를 활용하면 온도 변화에도 대응하는 값을 얻을 수 있기 때문입니다)   여기에,  지자기(지구자기) 센서의 3축을 추가한 모델이 MPU-9060 ,  9축 센서입니다.  9축 센서를 이용하면 3차원의 위치(지구 상 공간)와 3차원의 방향을 모두 파악할 수 있게 됩니다. 

 - 가속도 센서는 시간에 대한 속도 변화의 비율을 말하는 데요,  중력가속도를 이용하여 가속도를 측정하게 됩니다. 
중력 가속도가 3개의 축 각각에 얼마만큼의 영향을 주었는지를 측정하여 센서의 기울어진 정도를 파악할 수 있게 됩니다.  다만, 가속도 센서의 경우 움직이는 동적인 물체에서는 가속도와 중력이 섞여서 검출되기 때문에 정확한 데이터를 얻기가 힘듭니다,  따라서 정적인 상태에서만 정확한 기울기를 측정할 수 있는 한계가 있습니다. 
 
 - 자이로 센서는 물체의 회전 속도인 '각속도'를 이용하는 센서이기 때문에 각속도 센서라고도 합니다. 역시 3축의 물리량을 측정하여 센서의 움직임을 감지하고 기울기를 측정할 수 있는데요, 동적인 상황에서 가속도 센서에 비해 비교적 안정적인 값이 출력되지만 각도를 계산하는 과정에서 적분 방식을 사용하기 때문에 시간이 지날수록 누적되는 오차가 발생합니다. 

※ 따라서, 가속도 센서와 자이로 센서의 장점을 적절하게 적용하여 코드를 구성한다면 보다 정밀한 결과를 얻을 수 있습니다.   그러므로 센서를 적용하려는 형태와 방법에 따라 코드가 심플해지기도 하며, 외부 라이브러리 사용과 함께 아주 복잡해지기도 합니다.

  바로 위 '6050칩 이미지'를 보면, 직선방향의 화살표가 향하는 방향이 x, y, z 축의 가속도 센서가 적용되는 방향입니다.
  ( 센서를 통해 얻을 수 있는 RAW 데이터 파일 값 중에서 화살표 방향이 +값으로 표시된다면,  화살표 반대방향으로 움직일 시, -(마이너스) 값으로 표시됩니다.   좀 더 정확히 얘기하자면,  중력의 방향을 기준으로 잡고,  중력의 방향은 - , 중력의 반대 방향이 +입니다.  )
 그리고 회전하는 모양의 화살표가 x, y, z 축의 자이로 센서가 적용되는 방향입니다. 
 (마찬가지로,  화살표 방향으로의 회전 일 때 +값이 얻어진다면,  반대 방향으로의 회전 시, -(마이너스) 값이 얻어집니다.  회전 방향에 대한 + 방향은 위 이미지를 참고하세요)
그리고,  이 회전 방향은 특히 드론과 같은 비행체나 배와 같은 곳에 필수적으로 적용이 되는데요,   이 센서가 있어야, 기울기/자세를 유지하거나 보정할 수 있기 때문입니다. 
X축 회전 각도를 Roll (롤)  ,  Y축 회전 각도를 Pitch(피치) ,  Z 축 회전 각도는 Yaw(야우)라고 불립니다. 

 

★ 기억하기 쉽도록 :   사람 머리를 기준으로 
   -  Roll 은  →  고개를 좌우로 갸우뚱갸우뚱 
   -  Pitch는  →  고개를 앞뒤로 끄덕끄덕
   -  Yaw는  →  고개를 도리 도리

그럼, MPU6050 칩의 상세 스펙과 MPU6050을 내장한 GY-521 모듈에 대해 본격적으로 살펴볼게요.

【 기울기 센서 MPU6050 스팩 】

 전원 사용은 일반적으로 5V를 입력하지만, 3V~5V 사이의 전원은 모두 동작하므로, 3.3V 전원을 사용하는 다른 모듈들과 함께 3.3V 전원 연결도 자주 이용됩니다

 보시는 바와 같이 MPU6050 I2C 인터페이스를 이용한 통신으로 측정값을 얻어낼 수 있습니다. 일반적으로 모듈로부터 데이터를 얻기 위해 SCL SDA 핀을 이용(모듈이 슬레이브로 동작)  합니다.  좀더 구체적으로 설명하자면, I2C는 필립스에서 개발한 직렬 컴퓨터 버스이며, 임베디드시스템 혹은 저속의 주변기기와의 통신을 위해 사용된 직렬 통신 방식입니다.  기본적으로 하나의 마스터와 하나 혹은 여러 대의 슬레이브 연결 구조이며 SDA핀으로 데이터를 주고받고,핀의 클럭신호(동기화)에 맞추어 통신하게 됩니다.  아두이노에서는 <Wire.h> 라이브러리를 활용하면 손쉽게 I2C 통신을 할 수 있습니다.  
 XDA XCL은 추가적인 외부의 지자기 센서나 또 다른 센서 연결을 확장하는 시리얼 통신 단자입니다.  External ,  XDA, XCL 연결 단자 입니다.
그리고, 하나의 회로에서 만약 동일한 GY521 모듈을 두 개 구성하여 사용할 경우, I2C 통신 주소를 다르게 하기 위해 AD0 핀에 풀업 저항을 달면 주소를 달리 할 수 있습니다.  모듈의 기본 Slave address 주소는 1101000 이며(0x68), +Vcc쪽으로 풀업 저항(1㏀~10㏀) 연결 시 1101001로(0x69) 변경됩니다.  

【 기울기 센서 실습  #1 】

: 기울기 센서 기본 실습으로 센서로부터 기본적인 RAW 데이터 값을 얻어내 보도록 하겠습니다. 
활용도와 정확도를 높이기 위해서는 라이브러리를 사용해야 하지만, 복잡하고 코드 내용 파악이 어려울 수 있기 때문에, 기초 실습 #1에서는 라이브러리 없이 진행됩니다. 
- MPU6050센서는 16bit ADC가 내장되어 있습니다.  센서의 각축으로부터 가속도와 자이로에 대한 아날로그 데이터를 16bit 분해능을 가진  ADC(Analog Digital Converter)를 거치면서 디지털 수치값으로 얻을 수 있다는 말인데요, 16bit는 2^16 이니 65536의 값인데, -(마이너스)부분까지 반으로 나누어 표시하면 기본적으로는 " -32768 ~ +32767 "  사이값의 출력 범위를 가진다는 말이 됩니다.   
실습 #1에서는 우선 원시 RAW 데이터를 각센서 축별로 출력해보고,
실습 #2는 가속도 센서를 통해 얻은 RAW 데이터로부터 X축과 Y축의 각도를 계산해 내는 실습으로 진행하고, 
실습 #3에서는 자이로 센서를 통해 얻은 RAW 데이터로부터 X축과 Y축의 각도를 얻는 과정으로 진행합니다. 
실습 #4 상보필터 적용 실습
 각 실습별 방법에 대한 장단점 및 기본적인 설명이 안내해 드리며,  상호 보완필터(상보필터)를 적용한 실습 #4로 이어지니 차근차근 하나씩 실습해 보시기 바랍니다.    가급적 실습 #4까지는 외부라이브러리를 배제한 코드를 사용하여 코드 단순화를 통해 동작원리를 이해하는데 도움이 되도록 하였습니다.

아래 회로 연결도를 구성해 주고 PC와 연결합니다.
▶ 회로 연결도
(아두이노 나노와 GY521(MPU6050) 연결도)

아두이노 나노와 GY521(MPU6050) 연결도

▶ 아두이노 코드 
(가속도 x, y, z 축 값과  자이로 x, y, z 축 값의 raw data를 시리얼 모니터로 출력해 보기)

/* 기울기 센서 GY-521(MPU6050) 기초 실습 #1 (RAW 데이터 얻기)                            */ 
/* 아래 코드관련 실습에 대한 설명과 회로도 및 자료는 https://rasino.tistory.com/ 에 있습니다 */

#include<Wire.h>
const int MPU_ADDR = 0x68;    // I2C통신을 위한 MPU6050의 주소
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;   // 가속도(Acceleration) 와 
void getRawData();  // 센서값 얻는 서브함수의 프로토타입 선언 

void setup() {
  initSensor();
  Serial.begin(9600);
  delay(200);
}

void loop() {
  getRawData();          // 센서값 얻어오는 함수 호출
  Serial.print("AcX:");
  Serial.print(AcX);
  Serial.print("   AcY:");
  Serial.print(AcY);
  Serial.print("   AcZ:");
  Serial.print(AcZ);
  Serial.print("   GyX:");
  Serial.print(GyX);
  Serial.print("   GyY:");
  Serial.print(GyY);
  Serial.print("   GyZ:");
  Serial.print(GyZ);
  Serial.println();
  delay(300);  
}

void initSensor() {
  Wire.begin();
  Wire.beginTransmission(MPU_ADDR);   // I2C 통신용 어드레스(주소)
  Wire.write(0x6B);    // MPU6050과 통신을 시작하기 위해서는 0x6B번지에    
  Wire.write(0);       // MPU6050을 동작 대기 모드로 변경
  Wire.endTransmission(true);
}

void getRawData() {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x3B);   // AcX 레지스터 위치(주소)를 지칭합니다
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_ADDR, 14, true);  // AcX 주소 이후의 14byte의 데이터를 요청

  AcX = Wire.read() << 8 | Wire.read(); //두 개의 나뉘어진 바이트를 하나로 이어 붙여서 각 변수에 저장
  AcY = Wire.read() << 8 | Wire.read();
  AcZ = Wire.read() << 8 | Wire.read();
  Tmp = Wire.read() << 8 | Wire.read();
  GyX = Wire.read() << 8 | Wire.read();
  GyY = Wire.read() << 8 | Wire.read();
  GyZ = Wire.read() << 8 | Wire.read();
}

 《 위 코드 다운로드 》

Angle_RawData.zip
0.00MB



▶ 실행 결과
: 코드를 실행해 보면, 가속도 값 3개와 자이로 값3개  총 6개의 값이 일렬로 나타납니다.  센서를 움직여보면
데이터 값이 변하는 것을 볼 수 있습니다.  방향에 따라 + ,  - 값으로 나타나는데요,  현재 보이는 값은 어떤 각도 값이나 보정된 값이 아닌  말 그대로 순수한 Raw data이기 때문에 방향과 위치에 따른 데이터 변화를 유추하기는 어렵습니다.  때문에, 기본적인 Raw 데이터를 추출하는 원리 정도만 파악하시면 되고, 다음 실험에서 삼각함수를 이용한 각도 값을 계산해 보거나 ,  특정 라이브러리를 이용해서 고정시킨 위치 데이터를 확인해 볼 수 있게 됩니다.  또는 프로세싱(Processing)과 같은 그래픽 구현 툴을 이용해서 3D 이미지로 센서의 움직임을 그래픽 화면으로 볼 수 있는 실험도 진행할 예정입니다.  

기울기센서(MPU6050)로부터 Raw 데이터 얻기

▶ 동작 영상
(본 글 제일 아래 전체 동영상을 참고해보세요 : 설명 음성 추가)

【 기울기 센서 실습  #2 】

: 실습 #1에서 Raw 데이터를 얻었다면,  이번엔 이 데이터를 가지고 우리가 흔히 알아보기 쉬운 각도(라디안: radian) 값으로 바꾸어 출력해 보는 실습입니다.
먼저 각도를 얻을 수 있는 방법은,  앞서 설명한 것처럼 크게 세 가지입니다. 
1. 가속도 센서를 이용한 방법
2. 자이로 센서를 이용한 방법
3. 이 둘을 합쳐놓은 '상호보완 필터' 코드를 통해 구하는 방법
이번 실습은 움직임이 없는 상태에서 보다 정확한 값을 구할 수 있는 1번 가속도 센서를 이용한 간단한 방법으로 진행합니다. 때문에 라이브러리 설치 없이 간단히 진행할 수 있고 코드도 비교적 단순하여 파악과 응용이 쉽습니다.
각도(라디안)를 라이브러리 설치 없이 진행되어 구하기 위해서는 중력과 X축, Y축, Z 축과의 기울기를 이용한 삼각함수를 적용해야 하는데요, 해당 수식은 아래와 같습니다. 

Roll/Pitch/Yaw 각도를 구하기 위한 삼각함수 수식

 물론 코드에서는 이 수식이 적용되어 있습니다. 

 회로 연결은 실습 1과 같고 아래에 있는 아두이노 코드를 업로드해 주세요.

▶ 아두이노 코드 
( 코드에서는 가속도 AcX에 대한 'Roll 각도'와 가속도 AcY에 대한 'Pitch 각도'만 구합니다.  앞서 설명드린 것처럼 가속도 센서만 가지고는 Yaw에 해당하는 정확한 AcZ 각도가 구할 수 없습니다.  Z축 Yaw가 중력 방향과 평행한 회전을 하기 때문에 삼각함수를 적용해도 올바른 데이터가 출력되지 않습니다.)

//    Roll과 Pitch 각도 구하기 실습  》                                               
//  가속도 센서만 가지고 롤(Roll)과 피치(Pitch)를 구하는 예제입니다.                          
//  본 코드는 드론과 같은 움직임이 심한 경우가 아닌 비교적 정적인 상태에서 안정된 값을 얻을 수 있으며,
//  복잡한 외부라이브러리를 사용하지 않아 코드가 심플해서 파악후 적용하기가 쉽습니다.
// 아래 코드관련 실습에 대한 설명과 회로도 및 자료는 https://rasino.tistory.com/ 에 있습니다   

#include<Wire.h>

const int MPU_ADDR = 0x68;    // I2C통신을 위한 MPU6050의 주소
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;   // 가속도(Acceleration)와 자이로(Gyro)
double angleAcX;
double angleAcY;
// double angleAcZ;
const double RADIAN_TO_DEGREE = 180 / 3.14159;
void setup() {
  initSensor();
  Serial.begin(9600);
  delay(200);
}

void loop() {
  getAngleXY(); 
  Serial.print("Angle x : ");
  Serial.print(angleAcX);
  Serial.print("\t\t Angle y : ");
  Serial.println(angleAcY);
  delay(20);
}

double getAngleXY() {
  getData();  
  // 삼각함수를 이용한 롤(Roll)의 각도 구하기 
  angleAcX = atan(AcY / sqrt(pow(AcX, 2) + pow(AcZ, 2)));
  angleAcX *= RADIAN_TO_DEGREE;
  // 삼각함수를 이용한 피치(Pitch)의 각도 구하기
  angleAcY = atan(-AcX / sqrt(pow(AcY, 2) + pow(AcZ, 2)));
  angleAcY *= RADIAN_TO_DEGREE;
  // angleAcZ값(Yaw)은 아래의 삼각함수 공식은 있으나, 가속도 센서만 이용해서는 원하는 데이터를 얻을 수 없어 생략
// angleAcZ = atan(sqrt(pow(AcX, 2) + pow(AcY, 2)) / AcZ );
// angleAcZ *= RADIAN_TO_DEGREE;
}

void initSensor() {
  Wire.begin();
  Wire.beginTransmission(MPU_ADDR);   // I2C 통신용 어드레스(주소)
  Wire.write(0x6B);    // MPU6050과 통신을 시작하기 위해서는 0x6B번지에    
  Wire.write(0);
  Wire.endTransmission(true);
}

void getData() {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x3B);   // AcX 레지스터 위치(주소)를 지칭합니다
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_ADDR, 14, true);  // AcX 주소 이후의 14byte의 데이터를 요청
  AcX = Wire.read() << 8 | Wire.read(); //두 개의 나뉘어진 바이트를 하나로 이어 붙여서 각 변수에 저장
  AcY = Wire.read() << 8 | Wire.read();
  AcZ = Wire.read() << 8 | Wire.read();
  Tmp = Wire.read() << 8 | Wire.read();
  GyX = Wire.read() << 8 | Wire.read();
  GyY = Wire.read() << 8 | Wire.read();
  GyZ = Wire.read() << 8 | Wire.read();
}

 《 위 코드 다운로드 》

Angle_Roll_Pitch.zip
0.00MB

▶ 실행 결과
:  main loop( )에 있는 delay(20)을 느리게 혹은 빠르게 조절하여 확인해 볼 수 있습니다.
 센서 보드를 중력의 방향과 수직으로 놓으면 X와 Y는 0도를 가리킵니다.  그 상태에서 Roll(X)을 앞 뒤로 돌려보고, 
Pitch(Y)를 앞뒤로 돌려 보세요.  

 - Roll은 센서 보드 위 화살표 표시를 참고 기준으로 하여,  중력과 반대로 머리를 들면 +각도로 나오며, 중력의 방향으로 머리를 숙이면 -각도를 표시합니다.
 - Pitch 또한 피치 화살표를 기준으로, 화살표 방향으로 숙이면 +각도로 표시되며, 반대방향으로 회전시키면 -각도로 표시됩니다. 
 - 아래 이미지는 시리얼 플로터를 실행시킨 화면인데요, 각도 값을 그래프 형태로 보면 좀 더 직관적으로 파악하기 좋습니다. 
   ( 시리얼 플로터 창 열기 : 아두이노 IDE 툴 메뉴 클릭 》 시리얼 플로터 클릭! )
파란선이 Roll (AcX)에 대한 각도 그래프이며, 빨간선이 Pitch(AcY)에 대한 각도 그래프입니다.
기울기 센서 모듈은 접촉이 불안정할 경우, 데이터가 원하는 대로 나오지 않거나, 오작동 할 수 있습니다.
접촉이 헐렁한 브레드보드를 바꾸어 보거나 연결선을 확인해 보세요.  필요한 경우 납땜으로 연결해 주면 더욱 안정된 접촉이 이루어집니다.
그 외에 동작은 정상 동작하나, 데이터 값이 튀는 노이즈가 심할 경우에는, 추출 값을 3~10회 정도의 평균값 처리하는 루틴을 넣어 주면 어느 정도 해결할 수 있습니다.

▶ 동작 영상

 

【 기울기 센서 실습  #3 】

: 실습 #2에서 MPU6050에 있는 가속도 센서를 이용해서 각도(라디안: radian) 값으로 바꾸어 출력해 보는 실습을 했다면, 이번엔 MPU6050에 있는 자이로 센서를 이용해서 각도를 계산해 출력해 보겠습니다.

1. 가속도 센서를 이용한 방법
2. 자이로 센서를 이용한 방법
3. 이 둘을 합쳐놓은 '상호보완 필터' 코드를 통해 구하는 방법
이번 실습은  2. 자이로 센서를 이용한 방법 입니다. 
 먼저 자이로 센서는 진자의 움직임과 같은 축을 중심으로 회전하는 각속도를 측정합니다.
각속도는 시간당 회전하는 각도를 의미하는데요, 예를 들면, 
1. 수평한 자세를 유지하고 있는 상태이라면, 각속도는 0도/sec를 나타낼 텐데요, 
2. 이 물체가 10초 동안 50도만큼 기울어졌을 경우 ,  이 10초동안은 0이 아닌 각속도 값을 가지게 됩니다. 10초 동안의 평균 각속도는 5도/sec 가 되는데요,  즉,  초당 5도를 움직이는 속력이라 말할 수 있습니다.
3. 기울어지는 동작을 한 후 다시 멈춰서 50도를 유지한다고 할 때, 이때는 다시 각속도가 0도/sec 가 됩니다. 

1번 2번 3번 과정을 거치면서 각속도는 0 -> 5 -> 0으로 바뀌었는데요, 그런데 각도는 0도에서 점차 증가해서 50도가 된 상태입니다.   그래서 각속도가 움직인 각도에 비례해서 증가하는 것이 아니기 때문에, 각도를 구하려면 전체 시간에 해당하는 만큼의 각속도를 모두 합(적분을) 해야합니다.  자이로 센서는 이와 같이 각속도를 데이터로 출력하기 때문에  이 각속도 데이터를 모두 합(적분)하면 기울어진 각도를 계산해 낼 수 있는 원리입니다.  그런데 자이로 센서의 경우 문제는 이러한 적분 때문에 발생하게 됩니다.  센서에서 측정되는 각속도는 노이즈나 미세한 기본 오차 값들이 적분으로 인해, 시간이 지날 수록 쌓여 결국 측정값(각도 오차)의 오차가 커지게 되는 문제가 있습니다.  Drift 현상이 발생합니다. 
(즉, 이 방법만으로는 시간이 지날 수록 각도 혹은 기울기의 오차가 커지게 되는 단점이 있죠. 하지만, 가속도 센서처럼 진동에 영향이 크게 없으며 중력과 일치하는 Z축의 Yaw 각도도 구할 수 있는 장점이 있습니다. 

[ 용어 정리 ]
- Drift 현상 : 조건이 일정함에도 시간이 경과함에 따라서 값이 이탈 또는 흘러가는 현상.
- 각속도란 :  각속도 오메가(ω)는 원운동에서 단위 시간 동안에 회전한 각도를 말하며,  즉, 회전하는 물체에 대한 회전의 빠르기를 의미합니다. 

- 각도 :  각속도에 시간을 곱한 것이 각도 이며,  이것들을 모두 합치면 움직인 전체 각도가 됩니다

속력/속도/가속도 와의 관계식


 회로 연결은 실습 1과 같고 아래에 있는 아두이노 코드를 업로드해 주세요.

▶ 아두이노 코드 
( 코드에서는 시리얼 모니터 통신속도를 115200bps 으로 바꾸었으니, 실행시 시리얼 모니터 창의 보드레이트를 115200 bps로 맞추어 주세요)

// 《 자이로 Gyro 센서로 Roll과 Pitch, Yaw의 각도 구하기 실습  》         
//  자이로 센서만 가지고 롤(Roll)과 피치(Pitch), 야우(Yaw)를 구하는 예제입니다.                          
/* 아래 코드관련 실습에 대한 설명과 회로도 및 자료는 https://rasino.tistory.com/ 에 있습니다    */

#include<Wire.h>

const int MPU_ADDR = 0x68;    // I2C통신을 위한 MPU6050의 주소
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;   // 가속도(Acceleration)와 자이로(Gyro)
double angleAcX, angleAcY, angleAcZ;
double angleGyX, angleGyY, angleGyZ;

const double RADIAN_TO_DEGREE = 180 / 3.14159;  
const double DEG_PER_SEC = 32767 / 250;    // 1초에 회전하는 각도
// GyX, GyY, GyZ 값의 범위 : -32768 ~ +32767 (16비트 정수범위)


unsigned long now = 0;   // 현재 시간 저장용 변수
unsigned long past = 0;  // 이전 시간 저장용 변수
double dt = 0;           // 한 사이클 동안 걸린 시간 변수 

double averAcX, averAcY, averAcZ;
double averGyX, averGyY, averGyZ;

void setup() {
  initSensor();
  Serial.begin(115200);
  caliSensor();   //  초기 센서 캘리브레이션 함수 호출
  past = millis(); // past에 현재 시간 저장  
}

void loop() {
  getData(); 
  getDT();
  angleGyX += ((GyX - averGyX) / DEG_PER_SEC) * dt;
  angleGyY += ((GyY - averGyY) / DEG_PER_SEC) * dt;
  angleGyZ += ((GyZ - averGyZ) / DEG_PER_SEC) * dt;
  
  Serial.print("Angle Gyro X:");
  Serial.print(angleGyX);
  Serial.print("\t\t Angle Gyro y:");
  Serial.print(angleGyY);  
  Serial.print("\t\t Angle Gyro Z:");
  Serial.println(angleGyZ);  
  delay(20);
}

void initSensor() {
  Wire.begin();
  Wire.beginTransmission(MPU_ADDR);   // I2C 통신용 어드레스(주소)
  Wire.write(0x6B);    // MPU6050과 통신을 시작하기 위해서는 0x6B번지에    
  Wire.write(0);
  Wire.endTransmission(true);
}

void getData() {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x3B);   // AcX 레지스터 위치(주소)를 지칭합니다
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_ADDR, 14, true);  // AcX 주소 이후의 14byte의 데이터를 요청
  AcX = Wire.read() << 8 | Wire.read(); //두 개의 나뉘어진 바이트를 하나로 이어 붙여서 각 변수에 저장
  AcY = Wire.read() << 8 | Wire.read();
  AcZ = Wire.read() << 8 | Wire.read();
  Tmp = Wire.read() << 8 | Wire.read();
  GyX = Wire.read() << 8 | Wire.read();
  GyY = Wire.read() << 8 | Wire.read();
  GyZ = Wire.read() << 8 | Wire.read();
}

// loop 한 사이클동안 걸리는 시간을 알기위한 함수
void getDT() {
  now = millis();   
  dt = (now - past) / 1000.0;  
  past = now;
}

// 센서의 초기값을 10회 정도 평균값으로 구하여 저장하는 함수
void caliSensor() {
  double sumAcX = 0 , sumAcY = 0, sumAcZ = 0;
  double sumGyX = 0 , sumGyY = 0, sumGyZ = 0;
  getData();
  for (int i=0;i<10;i++) {
    getData();
    sumAcX+=AcX;  sumAcY+=AcY;  sumAcZ+=AcZ;
    sumGyX+=GyX;  sumGyY+=GyY;  sumGyZ+=GyZ;
    delay(50);
  }
  averAcX=sumAcX/10;  averAcY=sumAcY/10;  averAcZ=sumAcY/10;
  averGyX=sumGyX/10;  averGyY=sumGyY/10;  averGyZ=sumGyZ/10;
}

《 위 코드 다운로드 》

Angle_Gyro.zip
0.00MB

▶ 실행 결과
:  센서 보드를 X축 Y축 Z축 각각 움직여 보세요.

▶ 실행 영상
(제일 아래 전체 설명 동영상 참고)

【 기울기 센서 실습  #4 】

: 실습 #2와 실습#3에서는 각각 가속도 센서와 자이로 센서를 이용한 각도를 구했는데요,
가속도센서는 진동에 약하기 때문에(튀는 데이터값의 영향이 큼) 짧은 시간의 변화에는 약하지만, 긴 시간에 대해서는 정확한 각도를 산출해 낼 수 있고,  자이로센서는 진동에 강하기 때문에 짧은 시간에 대해서는 정확한 각도를 얻을 수 있지만 시간이 지나면서 오차가 누적되어 긴 시간에서는 취약합니다. 
 그래서
각각의 장점도 있지만, 단점이 명확하여 어느 하나의 센서 만으로는 드론과 같은 자세제어나 보정은 어렵습니다.   따라서 센서 둘을 모두 이용하고, 이 둘의 장점을 이용하여 서로의 단점을 보완한 상호보완 필터 코드를 적용하여 사용한다면, 비교적 오류가 없는 각도를 구할 수 있어서  드론 등의 자세제어 코드에 사용할 수 있습니다. 

1. 가속도 센서를 이용한 방법
2. 자이로 센서를 이용한 방법
3. 이 둘을 합쳐놓은 '상호보완 필터' 코드를 통해 구하는 방법
이번 실습은 3. 상호보완 필터를 이용한 방법 입니다. 

 아래 이미지는 상호보완 필터의 개념도 입니다. 

상보필터(상호보완) 개념도

[ 상보필터의 원리 - Complementary Filter ]
- 가속도 센서(Accelerometer)는 센서 특성상 고주파 영역에서 노이즈가 많이 발생하게 되어 정확한 값을 얻기 어려운데요, 그래서 노이즈 영역을 제거하고자 고역은 감쇠시키고,  낮은 주파수 영역을 통과시키는 저역필터(Low Pass Filter)를 적용해주면 정확도가 올라갑니다. 
- 자이로 센서(Gyroscope)는 센서 특성상 저주파 영역에서 값이 변하는 Drift현상이 발생하여 정확한 값을 기대하기가 어렵습니다. 그래서 저역을 감쇠시키고 노이즈가 적은 고역을 통과시키기 위한 고역필터(High Pass Filter)를 적용해주면 역시 정확도가 올라갑니다.   
※ 이렇게 각각의 필터를 통과해서 노이즈가 걸러진 값들을 합하여 보다더 정확한 각도값을 얻게 됩니다. 
이외에 칼만필터(Kalman Filter), Quanternion 라는 것도 있습니다.

상보필터에서는 가속도 센서의 저주파 영역에서의 장점과 , 자이로센서의 고주파 영역에서의 장점만을 융합한 필터로서 , 방법과 코드가 간단하여 적용하기 쉬운 장점이 있습니다.   상보필터에서는 ALPHA라는 가중치 값을 통해 자이로센서와 가속도센서 각각으로부터 얻은 각도를 어떤 비중으로 적용시킬지 정하여 계산하게 되는데요. 
 아래가 바로 보정값(가중치) ALPHA를 적용한 보정된 각도 값의 식(angleFiX) 입니다.
  angleFiX = ALPHA * angleTmpX + (1.0 - ALPHA) * angleAcX;

 여기서 angleTmp 는 자이로센서 값을 기준으로 만든 상보필터 처리를 위한 임시각도이며
X축에 대해 정리하면  angleTmpX = angleFiX + angleGyX * dt  가 됩니다.
가중치 ALPHA 값은 α = T/(T+
Δt) 식으로 구하는데요,  α (ALPHA) = 1 / (1+0.04)  가되어,  α 값은 0.96 이 됩니다.
즉,  1(T) 사이클 도는 동안의 loop Time(Δt=0.04) 을 적용한 식입니다.     그런데 이 값은 고정값은 아니며,  loop Time이 길어지거나 등의 이유로 알파값을 시스템에 맞게 변경할 수 있습니다.
즉, angleFiX 식을 보면 아시겠지만,  자이로 값에 * 0.96 가중치를 곱하고(주고), 가속도 값에 * 0.04의 가중치를 줘서 합한 값이어서 자이로센서(자이로스코프)에 더 의존하는 형태라고 말 할 수 있습니다.   그런데, 이런 형태가 비교적 정밀한(안정적인) 출력값을 내는 이유는,   식을 다시 살펴보면
angleFiX = ALPHA * angleTmpX + (1.0 - ALPHA) * angleAcX;
각도 변화가 상당히 느린 구간(저주파 영역)에서는 자이로센서의 데이터 값이 작아지기 때문에(angleGyX * dt의 누적값 감소), (1.0-ALPHA) = 0.04 가중치 적용으로 작았던 가속도 데이터 값이 상대적으로 커지게 되어 ,  자이로스코프의 저주파 영역에서 발생하는 Drift(드리프트)에 대한 단점을 보완 할 수 있게 됩니다. 

▶ 아두이노 코드 
( 위에서 설명한 식을 코드에 적용한 아두이노 코드입니다.   실습 #1과  실습#2에 소개한 코드를 합쳐서, 상보필터 식을 적용한 코드입니다.   축 3가지를 동시에 시리얼모니터로 확인하기 불편하기 때문에, 일부 축에 주석처리 되어 있으니, 필요한 경우 주석을 해제하여 사용하세요. )
 -  시리얼모티너(플로터) 출력은 아래처럼 각 축별로 비교하기 쉽도록 배치하였습니다. 
    《가속도센서 X축》 출력과 《필터링된 X축》 출력
    《가속도센서 Y축》 출력과 《필터링된 Y축》 출력
    《자이로센서 Z축》 출력과 《필터링된 Z축》 출력

// 《 상보필터를 적용한 Roll과 Pitch, Yaw의 각도 구하기 실습  》         
/* 아래 코드관련 실습에 대한 설명과 회로도 및 자료는 https://rasino.tistory.com/ 에 있습니다    */

#include<Wire.h>

const int MPU_ADDR = 0x68;    // I2C통신을 위한 MPU6050의 주소
int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;   // 가속도(Acceleration)와 자이로(Gyro)
double angleAcX, angleAcY, angleAcZ;
double angleGyX, angleGyY, angleGyZ;
double angleFiX, angleFiY, angleFiZ;

const double RADIAN_TO_DEGREE = 180 / 3.14159;  
const double DEG_PER_SEC = 32767 / 250;    // 1초에 회전하는 각도
const double ALPHA = 1 / (1 + 0.04);
// GyX, GyY, GyZ 값의 범위 : -32768 ~ +32767 (16비트 정수범위)


unsigned long now = 0;   // 현재 시간 저장용 변수
unsigned long past = 0;  // 이전 시간 저장용 변수
double dt = 0;           // 한 사이클 동안 걸린 시간 변수 

double averAcX, averAcY, averAcZ;
double averGyX, averGyY, averGyZ;

void setup() {
  initSensor();
  Serial.begin(115200);
  caliSensor();   //  초기 센서 캘리브레이션 함수 호출
  past = millis(); // past에 현재 시간 저장  
}

void loop() {
  getData(); 
  getDT();

  angleAcX = atan(AcY / sqrt(pow(AcX, 2) + pow(AcZ, 2)));
  angleAcX *= RADIAN_TO_DEGREE;
  angleAcY = atan(-AcX / sqrt(pow(AcY, 2) + pow(AcZ, 2)));
  angleAcY *= RADIAN_TO_DEGREE;
  // 가속도 센서로는 Z축 회전각 계산 불가함.
  
  // 가속도 현재 값에서 초기평균값을 빼서 센서값에 대한 보정
  angleGyX += ((GyX - averGyX) / DEG_PER_SEC) * dt;  //각속도로 변환
  angleGyY += ((GyY - averGyY) / DEG_PER_SEC) * dt;
  angleGyZ += ((GyZ - averGyZ) / DEG_PER_SEC) * dt;

  // 상보필터 처리를 위한 임시각도 저장
  double angleTmpX = angleFiX + angleGyX * dt;
  double angleTmpY = angleFiY + angleGyY * dt;
  double angleTmpZ = angleFiZ + angleGyZ * dt;

  // (상보필터 값 처리) 임시 각도에 0.96가속도 센서로 얻어진 각도 0.04의 비중을 두어 현재 각도를 구함.
  angleFiX = ALPHA * angleTmpX + (1.0 - ALPHA) * angleAcX;
  angleFiY = ALPHA * angleTmpY + (1.0 - ALPHA) * angleAcY;
  angleFiZ = angleGyZ;    // Z축은 자이로 센서만을 이용하열 구함.
  Serial.print("AngleAcX:");
  Serial.print(angleAcX);
  Serial.print("\t FilteredX:");
  Serial.print(angleFiX);
  Serial.print("\t AngleAcY:");
  Serial.print(angleAcY);
  Serial.print("\t FilteredY:");
  Serial.println(angleFiY);
  Serial.print("\t AngleAcZ:");
  Serial.print(angleGyZ);
  Serial.print("\t FilteredZ:");
  Serial.println(angleFiZ);


//  Serial.print("Angle Gyro X:");
//  Serial.print(angleGyX);
//  Serial.print("\t\t Angle Gyro y:");
//  Serial.print(angleGyY);  
//  Serial.print("\t\t Angle Gyro Z:");
//  Serial.println(angleGyZ);  
//  delay(20);
}

void initSensor() {
  Wire.begin();
  Wire.beginTransmission(MPU_ADDR);   // I2C 통신용 어드레스(주소)
  Wire.write(0x6B);    // MPU6050과 통신을 시작하기 위해서는 0x6B번지에    
  Wire.write(0);
  Wire.endTransmission(true);
}

void getData() {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x3B);   // AcX 레지스터 위치(주소)를 지칭합니다
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_ADDR, 14, true);  // AcX 주소 이후의 14byte의 데이터를 요청
  AcX = Wire.read() << 8 | Wire.read(); //두 개의 나뉘어진 바이트를 하나로 이어 붙여서 각 변수에 저장
  AcY = Wire.read() << 8 | Wire.read();
  AcZ = Wire.read() << 8 | Wire.read();
  Tmp = Wire.read() << 8 | Wire.read();
  GyX = Wire.read() << 8 | Wire.read();
  GyY = Wire.read() << 8 | Wire.read();
  GyZ = Wire.read() << 8 | Wire.read();
}

// loop 한 사이클동안 걸리는 시간을 알기위한 함수
void getDT() {
  now = millis();   
  dt = (now - past) / 1000.0;  
  past = now;
}

// 센서의 초기값을 10회 정도 평균값으로 구하여 저장하는 함수
void caliSensor() {
  double sumAcX = 0 , sumAcY = 0, sumAcZ = 0;
  double sumGyX = 0 , sumGyY = 0, sumGyZ = 0;
  getData();
  for (int i=0;i<10;i++) {
    getData();
    sumAcX+=AcX;  sumAcY+=AcY;  sumAcZ+=AcZ;
    sumGyX+=GyX;  sumGyY+=GyY;  sumGyZ+=GyZ;
    delay(50);
  }
  averAcX=sumAcX/10;  averAcY=sumAcY/10;  averAcZ=sumAcY/10;
  averGyX=sumGyX/10;  averGyY=sumGyY/10;  averGyZ=sumGyZ/10;
}

《 위 코드 다운로드 》

Angle_Acc_Gyro_CompFilter.zip
0.00MB


※ 아래 실행결과 화면을 보시면 알겠지만, 상보필터를 적용 후의 그래프는 노이즈나 한 번씩 크게 튀는 값 들이 상당히 제거되어 나타나는 것을 알 수 있습니다.   단, 노이즈 향상을 위해 ALPHA값 등, 보정값을 과도하게 조정하게 되면, 보정된 데이터의 출력 딜레이(시간차)가 발생하게 됩니다.  이는 드론(Drone)과 같은 제어에 있어서는 적시에 올바른 제어를 할 수 없게 만들 수도 있습니다.  

▶ 실행 결과
1.   《가속도센서 X축》 출력과《필터링된 X축》 출력 비교 화면
먼저, 시리얼모니터 화면을 살펴 보세요.(아래 이미지)  , 보드를 77도 정도에서 고정한 상태에서 가속도센서에서 얻은 데이터는 각도 값이 68~70도 사이를 짧은 순간에 제법 심하게 요동치고 있는 반면에, 필터링한 각도 값은, 77도에서 소수점 단위 정도만 변동이 있을 뿐 매우 안정된 출력을 보여주고 있는 것을 알 수 있습니다. 

 그럼, 이제 시리얼 모니터만으로는 잘 체감이 안 되실텐데요, 같은 출력을 아두이노 IDE 메뉴에 있는 '시리얼 플로터'를 통해 그래프로 보면 좀더 확연히 그 차이를 구분하실 수 있게 됩니다. (아래)

파란색 그래프가 가속도센서로 부터 얻은 X축 회전(각도)상태의 데이터인데요,  떨림과 같은 병동이 심한 반면에, 
필터링 코드를 거친 빨간색 X축의 데이터는 이런 노이즈들이 깔끔하게 제거 된 것을 알 수 있습니다.

2.   《가속도센서 Y축》 출력과《필터링된 Y축》 출력 비교 화면
그럼, Y축 그래프도 살펴 볼게요.

역시 마찬가지로, 필터링 되지 않은 Y축 출력과 필터링된 Y축 출력에 차이가 있음을 볼수 있습니다.

3.   《자이로센서 Z축》 출력과《필터링된 Z축》 출력 비교 화면
그리고, Z축 같은 경우는 앞서 설명드린대로, 가속도 센서로부터는 데이터를 얻을 수 없는 상태이고, 따라서 자이로 센서로 부터 얻은 Z축 데이터와,  자이로센서 데이터 가중치가 높은 필터링된 Z축 데이터를 출력해 본 것이어서 두 그래프간의 차이가 거의 없는 그래프 모습을 보여주고 있습니다.

3.  끝으로 전체 축을 동시에 비교해봤습니다. 《자이로센서 X-Y-Z-축》 출력과《필터링된 X-Y-Z축》 출력 화면

X축과 Y축을 0도 기준으로 움직이지 않았을 때 출력 모습

※ 여기서 한가지 생각해볼 수 있는 사항은, 
필터링전 그래프와 필터링후의 그래프간 출력의 시간차가 조금씩 나는 것을 볼 수 있습니다.   이는 더 매끈하게 노이즈를 제거 하려고 ALPHA값 수치를 조정하거나 하다보면, 더 커질 수 있는데요,  이는 공중에서 빠른 반응으로 자세보정을 해야하는 드론과 같은 경우에는 상보필터의 적용이 어려울 수 있습니다.  따라서, 이런 경우 등으로 인해, 대개 칼만필터 같은 것들이 적용이 되고 있습니다.  하지만 칼만필터의 경우는 주로 외부라이브러리도 필요하고 구조적으로 코드가 복잡합니다.   그래서 드론 이외의 모델에서는 코드적으로 매우 심플한 상보필터를 적용해보면, 적용하기도 쉽고, 충분히 만족스러운 결과를 얻을 수 있을 것이라 생각됩니다.


▶ 실행 영상( 이번 MPU6050 실습에 대한 전체 설명 영상을 제작했으니 보신다면 내용이해에 충분히 도움 되실 듯 합니다 )

youtu.be/BTpwAFfeg0I

 

반응형