반응형

【 아두이노모듈#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

 

반응형
반응형

MFRC522 RFID with Nano 33 iot #1아두이노 나노(33 IoT) 보드에 RFID 카드 모듈 사용해 보기!
( feat.  RFID 컴파일 오류 있는 경우도 보세요! )

 

  Nano 33 every(또는 33 iot 등)에서 RFID를 사용해보려 하는데요,  MFRC522 RFID 모듈사용시 컴파일 오류가 일어나는 경우에 대해 먼저 짚고 넘어가 보도록 하겠습니다. 

대표적으로 컴파일 과정에서 오류가 일어나는 경우에는 예전에 설치한 RC522드라이버가 더이상 현재의 아두이노 IDE툴 버전에서는 제대로 작동되지 않아서인 경우가 주요 원인이라고 보시면 됩니다. 

참, 그리고 아두이노 nano every(33 iot)라고 해서 기존의 nano와 핀 배열 및 기본적인 사용법은 크게 다르지 않기 때문에 보드 종류의 문제는 아닙니다.  

 

먼저 지난번 아두이노 우노에서 RC522 모듈을 적용한 이후 새로운 RC522 드라이버가 업데이트 되었는데요, 가장 최근에 것을 다시 다운로드 받아, 아두이노 IDE에서 드라이버를 설치해주시면 됩니다. 

아래가 사이트 링크입니다. 

www.arduinolibraries.info/libraries/mfrc522

 

MFRC522

Arduino RFID Library for MFRC522 (SPI)

www.arduinolibraries.info

아래에 있는 드라이버를 다운로드 받아
 아두이노 IDE 메뉴에서  " 스케치 》 라이브러리 포함하기 》 .ZIP 라이브러리 추가...  " 로 간단히 추가할 수 있습니다.

MFRC522-1.4.7.zip
1.16MB

그리고 아래 처럼, 예제 파일 ReadNUID를 불러온 후 컴파일 해보세요.

(모든 이미지는 클릭하면 확대 됩니다.)

 그런 다음 아래와 같이 nano 보드와 연결된 포트를 확인 또는 제대로 선택하세요.  (자신이 연결한 보드로 선택)

 

 그리고서 연결된 보드로 업로드해 주세요. 

이미지 처럼 업로드 완료가 뜨면 됩니다.

나노 33 IoT 보드 핀맵은 아래와 같습니다.
(보드상의 Pin Out은 구형 Nano 보드 = Every 보드 = Nano 33 IoT 보드 등과 동일합니다)

나노 33 IoT 핀 아웃

- 아래는 아두이노 사이트에서 제공하는 나노 33 IoT 보드의 핀 아웃 모습

나노 33 iot 핀 아웃

 

- 아래는 아두이노 사이트에서 제공하는 나노 에브리(every)의 핀 아웃(Pin Out) 모습입니다.

나노 에브리(every) 핀 아웃

※ 보이는 것처럼 나노 33 IoT 버전과 에브리(every)의 보드상의 핀 아웃은 일치함을 알 수 있습니다. 이는 구형 Nano 보드와도 일치하기 때문에 구형 나노보드에서 사용했던 연결을 그대로 every 보드 등에 대해서도 똑 같이 연결하면 대부분의 경우 작동 됩니다.   다만, 위에서 설명드린 것처럼, 아두이노IDE 오래전 버전에서 작업이 되었던 특정 모듈의 경우,  코드 컴파일 부분에서 에러가 날 수 있으니,  해당 모듈의 제조사 페이지 또는 깃허브 등에서 찾아 업데이트 후 다시 시도해보면 대부분 해결 됩니다. 

 

 

아두이노 나노 33 IoT와 RFID-RC522모듈의 연결

아두이노 나노 33 IoT와 RFID-RC522모듈의 연결

 

동작 실행

 코드가 나노에 업로드 되었다면 UID카드를 가져다 대어 보면,  아래처럼 카드에 따라 각각의 고유한 ID가 인식되는 것을 확인 할 수 있습니다. 

 

 

작업 영상 보기
 

 

반응형
반응형

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

(본문의 모든이미지는 클릭하면 확대하여 볼 수 있습니다)

 

 

 이번 시간에는 아두이노를 가지고 응용작품을 만들때 활용하기 좋은 OLED의 사용법을 다루어 볼게요.

OLED는 무턱대고 사용해보려 한다면, 화면 조차 켜기 어렵고, 회로 연결도 OLED 종류별로 다르기 때문에, 처음 사용자에게는 상당히 어렵게 느껴질 수 있습니다.  또한,  adafruit, U8g 등 주요 라이브러리의 기본 사용법을 안다면, 텍스트 뿐아니라, 도형, 이미지 출력도 쉽게 할 수 있어 이 번 가이드를 보신다면 많은 도움이 되실 것으로 생각합니다. 

 

OLED (Organic Light Emitting Diodes) 

OLED는 유기발광다이오드의 약자로, LCD처럼 백라이트가 필요치 않고 스스로 빛을 내는 패널로 만들어져 있습니다.

 두께도 얇고 휘어지도록 만들 수 있으며, 색 표현력이 우수하여 최근 각광받고 있는 디스플레이입니다.

TV 및 대형 디스플레이 뿐 아니라, 애플워치, 샤오미 밴드와 같은 소형 기기의 디스플레이로도 많이 사용되는데요,

 이번 시간에는 아두이노에 많이 활용되는 OLED 주요 5종에 대해 연결법과 사용법에 대해 다루어 보겠습니다.

물론, 1602(2줄) , 2004(4줄) 액정 디스플레이가 있지만, 해상도가 낮아 , 보통 단순 문자 위주의 표현에 그치는 단점이 있죠.

 이에 비해, OLED는 얇고 작은 크기에도 해상도가 높아, 미려한 이미지와 정보 표시가 가능합니다.

 구글에서 OLED를 검색해보면 아래와 같은 OLED가 검색되는데요, 크게 두 가지 타입으로 나눠져 있는 것을 알 수 있는데요,  통신방식에 따른 I2C Type과 SPI Type이 있습니다. 

 

 I2C 통신과 SPI 통신 방식에 따른 장단점 및 특징은 아래를 참고 하세요.

 

 OLED로서 SPI 타입과 I2C 타입의 주요 차이점으로는, 

SPI 타입은 연결 해야할 선이 I2C보다 많지만 데이터를 뿌려주는(화면구현) 속도가 빠릅니다.  다만, 차이가 그리 크지는 않습니다.     I2C 타입은 연결과 사용이 좀 더 간편한 장점이 있습니다. 
 또한, SPI타입의 경우, OLED 보드 뒷면의 납땜(0옴 저항으로 연결)을 옵션에 따라 제거 또는 연결해 주면 I2C 타입으로도 사용할 수 있습니다.

 

  이상, OLED에 대한 사전 지식과 개요에 대해 설명을 드렸는데요,

그럼, 본격적으로, 아두이노를 이용한 OLED실습을 아래와 같은 순서로 진행해 보겠습니다.

   6.   응용 실습 (로고 이미지 표현)

실습 마지막에는 추가적으로 로고(Logo) 이미지를 가지고 OLED에 표현하는 실습을 담았으니 참고해 보세요. 

 

 【 중요 1  : OLED는 입력된 데이터를 화면에 구현해주기 위한 Driver라는 IC(칩)를 사용하게 되는데요, OLED의 크기, 종류 등 제품에 따라 서로 다른 드라이버를 사용하게 됩니다. 
 이는 OLED를 아두이노에 연결할 때 연결 위치가 달라지게 되며, 드라이버에 따라 사용할 수 있는 라이브러리의 사용 방식도 조금씩 달라지게 됩니다.  따라서 사용하고자 하는 OLED에 대한 기본 스펙(제조사, 드라이버, 크기, 해상도 등)을 알고 시작해야 헤메지 않고 바로 시작할 수 있으니 참고하세요.   

 

대표적으로 많이 사용되는 해상도인 128 x 64 Display의 좌표정보를 참고해 보세요.

 OLED는 가로 128개 세로 64개의 작은 LED점(pixel)을 ON/OFF하여 글자나 이미지를 표현하게 되는데요,  다만, 기본 코딩으로는 텍스트와 같은 단순한 정보 위주로 밖에 표현할 수 없지만,  U8gLIB, Adafruit LIB와 같은 라이브러리를 활용하면, 도형이나, 이미지  표현 등 매우 쉽고 편하게 구현할 수 있게 됩니다. 

【 중요 2 : 구동 드라이버 뿐 아니라, 활용 하려는 라이브러리에 따라 회로 연결이 달라 질 수 있으니, 라이브러리를 잘 살펴봐야 합니다. 아래 1번의 실습에서 처럼, 같은 제조사의 동일한 OLED를 사용함에도 1-1과 1-2의 회로 연결이 달라지는 것을 알 수 있습니다.  이 문제가 중요한 이유는 연결선이 하나라도 맞지 않으면 화면을 제대로 뜨지 없게 됩니다.

# 아래 실습을 진행시 각 실습마다 제시된 라이브러리가 제대로 설치되어 있지 않은 경우 아두이노 컴파일 과정에서 에러가 날 수 있으니, 라이브러리 설치시 잘 살펴 보세요.

『 OLED 핵심 포인트 』

OLED를 처음 활용시 헷갈리고 사용법에 다소 어려움을 겪을 수 있습니다. 아래 핵심포인트를 숙지하시면, OLED 적응에 도움이 되실 거예요.

 

" 실습파일은 아래 링크에서 다운받아도 되며, 라이브러리 설치시 설치되는 예제파일을 열어도 됩니다. "

 

 지금부터의 실습과정에 사용되는 아두이노 파일(.ino)은 각 실습별로 다운로드 링크되어 있으며,  라이브러리를 설치하게 되면 자동으로 설치되는 예제파일을 찾아서 실행해도 무방합니다.  다만, 필요부분 주석제거 및 설정이 안 되어 있는 경우가 있어 직접 변경해주어야 하는데요,  아래 링크 파일은 실습가능한 상태로 변경되어 있으니 아두이노에 익숙지 않은 분들에게는 직접 링크해드리는 파일을 받으시는 걸 권해드립니다.

 

 

▶ [실습 1]  WaveShare 1.3인치 SPI type OLED 실습 (SH1106 Driver) :

 제조사는 WaveShare로서, 제품에 사용된 Driver는 SH1106 이며, 1.3인치크기에 128 x 64의 해상도를 가지고 있습니다. 

 【 #1-1 아두이노 OLED  회로 연결도SH1106_Demo.ino 

 

[ 필수 라이브러리 ]

SH1106_SPI.zip
0.01MB

 

[ 실습파일 다운로드 ] 

SH1106_Demo.zip
0.00MB

 라이브러리를 다운받아 설치하고 실습파일(SH1106_Demo.ino)을 실행하면 아래와 같은 데모화면을 볼 수 있습니다.

 

 

 【 #1-2 아두이노  OLED  회로 연결도  HelloWorld.ino & u8glib 사용 

[ 필수 라이브러리 ]

u8glib_arduino_v1.18.1.zip
1.09MB

[ 실습파일 다운로드 ]

HelloWorld.zip
0.00MB

 에러가 날 경우 라이브러리 설치 여부를 먼저 확인하고, 다음과 같은 아두이노 실습파일에 있는 옵션의 주석을 "//" 제거하였는지? 확인해 보세요.  →   U8GLIB_SH1106_128X64 u8g(13, 11, 10, 9);

 

 

▶ [실습 2]  WaveShare 0.96인치 SPI type OLED 실습 (SSD1306 Driver) :

 제조사는 WaveShare로서, 제품에 사용된 Driver는 SSD1306이며, 0.96인치크기에 128 x 64의 해상도를 가지고 있습니다.  특징으로는 OLED화면 위쪽 1/4 영역은 노란색으로 출력 되며, 나머지 3/4영역은 파란색으로 출력됩니다. 

다만, 출력 문자의 색을 마음대로 바꿀 수 있는 것은 아니며, 해당 부분의 색필름과 같은 필터가 있는 것으로 보여집니다.  해당실습에서는 실습상의 문제인지는 모르겠으나, 출력화면이 다소 어두워 시안성이 떨어지는데요, 특정한 용도가 아니라면 해당OLED 구매는 비추합니다.

 

 【 2 아두이노  OLED  회로 연결도  HelloWorld_2.ino 코드 

라이브러리는 위에서 다운받은 U8glib를 사용하고 있으며, 테스트 코드는 #1-2에 사용된 HelloWorld.ino 파일을 사용합니다.  다만, 아두이노 파일의 설정에서 SSD1306 OLED에 맞는 옵션의 주석을 제거하여 사용하거나, 아래 별도로 첨부해드리는 파일을 받아 실행해보세요. 

 에러가 날 경우 라이브러리 설치 여부를 먼저 확인하고, 다음과 같은 아두이노 실습파일에 있는 옵션의 주석을 "//" 제거하였는지? 확인해 보세요.  →  U8GLIB_SSD1306_128X64 u8g(13, 11, 10, 9);  

HelloWorld_2.zip
0.00MB

[ 출력 화면]

 

 

▶ [실습 3]  WaveShare 0.95인치 SPI type RGB OLED 실습 (SSD1331 Driver) :

제조사는 WaveShare로서, 제품에 사용된 Driver는 SSD1131이며, 0.95인치크기에 96 x 64의 해상도를 가지고 있습니다.  특징으로는 65k 수준의 컬러 출력이 지원되는 점입니다. 아래 데모 예제를 확인해보면 컬러 출력 함수에 대한 사용 방법을 알 수 있습니다.

 

아두이노  OLED  회로 연결도  oled.ino 코드 

[ 필수 라이브러리 ]

arduino.zip
0.01MB

 라이브러리를 추가하면 oled.ino 라는 예제파일이 포함되어 있으며, 이를 실행하면 아래와 같은 화면이 출력 됩니다. 

파일에 포함된 관련 함수들을 이용해서 출력연습을 해보세요. (색 지정, 역상 등의 함수 사용 가능)

[ 출력 화면]

 

 제조사 홈페이지를 통해 arduino 이 외의 다른 보드에 대한 라이브러리와 예제 파일을 다운받을 수도 있으니 참고하세요. ( 예, 라즈베리파이, STM32보드)  [ 링크 : https://www.waveshare.com/wiki/File:0.95inch-RGB-OLED-Code.zip ]

                                    [직접 받기]

0.95inch-RGB-OLED-Code.zip
1.95MB

 

▶ [실습 4]  0.96인치 SPI type (7 Pin) OLED 실습 (SSD1306 Driver) :

 SSD1306드라이버 칩은 0.96인치 128x64 픽셀의 OLED에서 가장 많이 사용되는 OLED입니다. 

따라서,  만약 OLED 제조사도 모르고 어떤 드라이버를 사용하는지? 모르는 OLED를 갖고 있다면,  SSD1306칩을 사용한 OLED라고 생각하고 아래의 회로 연결과 코드를 사용해서 테스트 해보세요.   그렇게 해서 화면이 뜬다면 빙고!

이 OLED는 NC(no connet)핀이 없는 7Pin SPI OLED 인데요, 파란색이 아닌 흰색의 깔끔한 출력을 보여주는 모노크롬(단색) OLED입니다.  핀의 배열순서와 핀 이름도 위의 모델들과는 다르게 표시되어 있는데요, 하지만 기능은 같은 핀입니다. 

  핀 배열은 : 액정면 좌측을 기준으로  GND , VCC , D0 , D1 , RES , DC , CS 순으로 되어 있습니다.

 핀 이름이 다르게 표시되어 있어 기존 OLED를 사용하다보면 많이 헷갈리게 되는데요,  정리를 해드리면, 

1.   CLK = SCK = D0  는 클럭핀으로 모두 같은 역할의 핀으로 이해하면 됩니다.  PC CPU의 클럭과 같은 역할 입니다.

2.   DIN = MOSI = D1 은 실제적인 데이터(입력)를 넣어 주는 핀 입니다. 

3.    D/C = DC = A0  는 모두 Data Command 핀으로 데이터(숫자,글자 등)를 보낼지? 아니면 명령(밝기, 글꼴 등)을 전달할지? 선택하는 명령신호 입력핀으로 이해하면 됩니다.

 

 아두이노  OLED  회로 연결도  www.ssd1306_128x64_spi.ino 코드 

[ 필수 라이브러리 ]

아두이노 스케치 IDE의 라이브러리 관리 창에서 "Adafruit 1306"을 검색하면 나오는 항목(아래 참고)을 선택하여 라이브러리를 설치하세요, 예제파일도 아래 첨부한 파일과 같습니다.  설치 진행시 나타나는 추가적인 GFX Livrary도 추후에 필요하니 모두 설치하면 됩니다. 

  참고로 인터넷으로 다운받을 수 없는 환경을 위해 아래에 라이브러리를 첨부합니다.  만약 zip 라이브러리 추가 형태로 라이브러리가 추가 되지 않을 경우, 아두이노가 설치된 라이브러리 폴더에 압축을 풀어서 복사해 넣으면 적용됩니다. (아두이노 재시작 필요)

Adafruit_SSD1306.zip
0.03MB
윈도우 라이브러리 폴더에 직접 복사하는 위치

[ 출력 화면 ]

 

▶ [실습 5]  0.96인치 I2C type (4 Pin) OLED 실습 (SSD1306 Driver) :

 4Pin으로 된 I2C 방식으로 SSD1306 드라이버 칩을 사용하는 0.96인치 128x64 픽셀의 OLED 입니다.  핀수가 작고 연결 및 다루기 쉬워 가장 많이 선호되는 OLED라고 생각됩니다.   

I2C 방식의 특성상 마스터(아두이노)에서 슬레이브(OLED 등)장치와의 통신을 위해서는 슬레이브 장치의 주소를 알아야 합니다.  특정 주소영역을 가지고 보통의 경우 고유의 주소를 가지고 있습니다. 

액정 1602 LCD의 경우 보통 0x3F 또는 0x27의 고유 주소가 설정된 상태로 제품이 출하되며, 

OLED의 경우 대부분은 0x3C로 되어 있고 혹은 0x3D로 설정되어 있습니다. 

 혹은 라이브러리 관리 메뉴에서 I2C Scanner를 검색후 설치하고, 설치후 추가되는 예제 파일에 있는 scanner를 실행하면 i2c를 이용하는 기기의 주소를 알아낼 수 있습니다.

 또한 경우에 따라 아래처럼 I2C OLED 뒷면에 납땜처리를 해주면 주소를 선택할 수 있습니다.

 이런 과정이 필요한 이유는 만약 같은 아두이노 회로에서 서로 다른 정보를 표시해야 하는 OLED를 두 개 연결해야 할 경우, 서로 다른 주소의 OLED가 각각 있어야 코드에서 각각 호출하여 적용할 수 있기 때문입니다. 

만약 두 OLED에 동일한 정보를 표시하는 경우이면 같은 주소에 병렬로 동일하게 연결하면 됩니다. 

만약, 두 개이상의 서로다른 주소를 가진 I2C OLED를 제어해야 한다면, 아래와 같은  "I2C 확장 멀티플렉서 모듈"을 이용하면 됩니다.  ( TCA9548A 1-to-8 I2C 8-Way IIC Multiplex Expansion Board Module )  : 5$~8$

동일한 주소의 I2C OLED를 최대 8개의 주소로 확장시켜 줍니다.

 

 

 

 아두이노  OLED  회로 연결도  GraphicsTest.ino 코드 

 화면 테스트는 두가지로 해보세요.

[ 실습 5-1 ]

바로 위 실습4에서 Adafruit 라이브러리를 설치하면 같이 설치되는 예제 중,  ssd1306_128x64_i2c.ino 예제를 실행해봅니다.  코드내에서 아래 i2c 주소부분을 확인한 후 실행시켜 보면 실습4에서와 같은 동작을 보실 수 있습니다.

 

(실습파일  5-1)

ssd1306_128x64_i2c.zip
0.00MB

[ 실습 5-2 ]

많이 활용되고 있는 U8glib 라이브러리를 설치하고 열리는 예제파일을 가지고 실습해보세요.

먼저 아래 깃허브 사이트에서 라이브러리를 다운 받습니다. (zip 파일 형태로 받으세요)

https://github.com/olikraus/u8glib

 

olikraus/u8glib

Arduino Monochrom Graphics Library for LCDs and OLEDs - olikraus/u8glib

github.com

(이미지를 클릭하면 확대 됩니다)

U8glib의 예제 중에  "GraphicsTest" 파일을 열어 테스트 해보세요. 

(실습파일)

GraphicsTest.zip
0.00MB

 

[ 실습 5-3 ]

그리고, U8glib 예제 중에 " u8g_structure.ino " 파일을 열어 아래처럼 코드를 확인하고 테스트 해보세요.

 [출력 화면]

 

그리고, 폰트를 사이트에서 참고하여 크기와 모양을 바꾸어 출력할 수도 있습니다.

 이로서 기본적인 5가지의 OLED 사용법을 익혀봤는데요, 

조금 더 응용해서 일반적인 이미지나 로고를 OLED에 띄워 보도록 할게요. 

 

 

▶ [보너스 실습]  0.96인치 I2C type (4 Pin) OLED 실습 (SSD1306 Driver) :

OLED와 라이브러리는  바로 조금전에 사용한 I2C OLED와 U8glib를 사용합니다. (연결도 동일)

 

로고 이미지  ↔ OLED 출력하기 

변환에 사용할 로고 이미지와 아두이노 파일(완성 코드) 다운로드

u8g_structure_logo.zip
0.14MB

1. 먼저 파일을 다운 받으면, 아래와 같은 로고파일을 윈도우 그림판에서 불러옵니다.

2. 그림판 메뉴 중 크기조정을 클릭하여 아래처럼 변경해주세요, 

   - 기준: '픽셀'

   - 가로 세로 비율 유지 :  '체크해제'

   - 가로: 128   

   - 세로: 64

 

3. 확인을 누르고 다른이름으로 저장을 클릭 한 후 '파일형식'을 "단색 비트맵(*.bmp,*dib)" 으로 변경후 저장하세요.

손실 저장.... 어쩌고 하는 팝업창이 두 번 뜨면 모두 "예"로 눌러주면 아래처럼 크기 128x64의 단색으로 변환된 이미지가 저장됩니다.

4. 다음으로 이런 흑백의 이미지를 OLED가 화면 한 점, 한 점을 켜고 끌 수(On/Off) 있는, 판단할 수 있는 데이터로 바꾸어 주어야 합니다.  예를 들어 On의 값은 0xff ,   Off의 값은 0x00  이런 형태입니다. 

하지만, 사람의 손으로 일일이 이미지를 보면서 변환 할 수 없기에 자동 변환 툴이나 변환 웹사이트를 이용하면 됩니다.

 아래에 소개되는 사이트로 연결합니다.  그리고 조금전 생성한 단색이미지를 파일 선택으로 선택해 주세요.

  주소 :  http://javl.github.io/image2cpp 

 옵션을 위와 같이 하면 되며, 3.Preview 에 예측 결과가 나오는데요,  

검은색 부분이 불이 그려지는 것이 아니라, 어두운, 즉, 불이 꺼진 부분이기 때문에, 실제 OLED 화면에서는 역상으로 나오게 되죠.

위 옵션 중에서 Invert image colors 부분을 체크하면 반대로 역상이 됩니다. 

 

다음, 출력 부분의 옵션을 아래와 같이 변경하고,  "Generate code" 버튼을 클릭하면, 그 아래에 변환된 코드가 나오게 됩니다.  이것을 아두이노 코드에 붙여 놓으면 됩니다.

즉, 정리하면 아래와 같이 됩니다. 

 

5. 아두이노 코드에서는 비트맵 이미지를 그려줄 함수를 사용하면 되는데요,  

u8g.drawBitmapP (x, y, 가로pixel/8, 세로pixel, mylogo); 

이때, x, y는 시작점의 위치이며, 현재 이미지의 사이즈는 128x64 사이즈로 OLED에 꽉차는 사이즈이기 때문에, 0,0으로 해 주어야 합니다.

그리고 중요한 것은, 가로 세로의 이미지 크기인 128 , 64 값을 입력하면서,  가로값은 128의 값을 8로 나눈 값인 16으로 입력해주어야 합니다.  이유는 u8g라이브러리의 구동 구조상의 이유인데요,   만약 OLED에 이미지가 깨져서 나온다면,  이부분을 처리하지 않았거나,  위의 이미지 변환웹의 사용을 잘못한 경우가 됩니다. 

 만약, 다른 u8g가 아닌 라이브러리 사용에서는 보통 128이라는 값 그대로 입력합니다.

(결과 출력)

 

6. 마지막으로 이미지를 역상시켜서 두 개의 이미지가 1초 간격으로 번갈아 깜빡이도록 해볼게요.

방법은 동일하고, 위 이미지 변환웹에서 " Invert image colors " 체크하여 역상된 데이터 값을 아두이노 코드에 추가해 주고,  draw1( ) , draw2( ) 호출 함수를 각각 만들어, 1초의 delay(1000); 를 주어 호출해 주면 됩니다.

 이런 방식을 이용하면, 움직이는 이미지도 구현이 가능합니다. 

이상으로 OLED 처음 사용설명서에 대한 설명을 마칩니다. 

OLED모듈은 이런 종류를 처음 다루어 보시는 분들에게는 생각보다 다루기 어렵고 화면이 잘 안뜨는 문제가 발생할 수 있어 많은 시간을 허비하거나 고생하게 됩니다.  그래서  최대한 상세하게 기술하였구요.   동영상 제작에 편집까지 시간이 많이 걸려 고생했지만, OLED를 처음 사용 하시는 분들에게 분명 도움되시리라 생각되네요.  ^^;

아래 영상은 전 과정을 동영상으로 보면서 파악 할 수 있도록 구성했으니, 게시글과 함께 같이 보시면 더욱 이해가 되리라 생각됩니다. 

  

아두이노↔OLED 처음 사용설명서 영상으로보기 

OLED 5종 사용설명서 전과정 영상 보기

[ 본 실습에 사용된 모든 실습도면 모음 받기 ]

 

(OLED 실습 연결도면 모음).zip
0.83MB

 

반응형
반응형

【 아두이노모듈#28 ESP8266 esp-01 활용하기#4 : 스마트폰으로 LED 컨트롤 하기

(본문의 모든이미지는 클릭하면 확대하여 볼 수 있습니다)

 ESP8266은 wifi 네트워크를 이용한 통신이 가능한 모듈입니다.  작은 모듈속에, cpu, 메모리, 입출력 핀을 내장하고 있어서 아두이노 없이 단독으로도 활용가능한 멋진 모듈입니다.

 esp8266 모듈 시리즈는 esp-01 부터 esp-12 모듈까지 스팩별로 다양한 종류가 있으며, esp-12칩셋을 활용한 nodeMCU , ESP-32, WeMos D1-Mini 등등의 다양한 제품군이 있습니다. 

 우선 가장 작고 기본 기능에 충실한 esp-01 모듈을 학습하고 나면, 나머지 모듈에 대해서도 충분히 다루실 수 있으리라 생각합니다. 

 

 지난시간까지 esp-01 모듈회로를 꾸미고 LED 2개를 연결한 다음, LED 깜빡이 코드를 올려 작동시켜 보았는데요, 이번 시간에는 핵심기능인 WiFi 접속을 통해 스마트폰으로 LED2개를 켜고 끄는 컨트롤을 해보려고 합니다. 여기서 중요한 사실은, 비록 LED를 제어하는 단순한 동작이지만, LED가 제어 된다는 뜻은, 원하는 어떤 것이든 제어가 된다는 생각을 가지면 좋습니다.  모터를 제어한다면, 모터를 돌리기 위한 충분한 전원 모듈을 보강해주면 되며,  220V와 같은 큰 전원 제품이나 모듈을 컨트롤 하려고 한다면 릴레이와 같은 부품이나 모듈을 연결하면 구현 가능하기  때문이죠. 

 

  그럼, 이번 시간의 목표인 스마트폰을 이용해서 WiFi 접속을 통해 원격으로, 무선으로 LED 2개를 켜고 끄도록 해보는 실습을 진행할께요.

  물론, 스마트폰의 앱도 앱인벤터를 이용해 직접 만드는 과정도 설명드리는데요,  앱을 스토어에 올리지 않기 때문에 비용 발생도 없으며,  어려운 자바언어를 사용하지 않고 구글의 스크래치와 같은 블록코딩 방식을 이용하기 때문에 처음 사용자라도 10분이면 충분히 앱을 만들 수 있으니,  자신감을 가지고 지금 바로 실습해 보세요.  그리고, 앱인벤터 메뉴부터 기초 앱제작 과정의 콘텐츠 글도 여기 라즈이노IOT 게시판에 올려져 있으니 먼저 참고해도 좋을 듯 합니다.  

 

 ESP-01 모듈의 기본 스펙과 기초 사항은 아래 선수 학습을 통해 확인해보세요. 

 선수학습 :

  1.  ESP-01 펌웨어 기초 & 업데이트 하기(에러 대처) 

  2.  ESP-01 펌웨어 기초 & 업데이트 하기 (영상강좌)

  3.  ESP-01 LED 깜빡이기 회로 만들기 

 

▶ 1. ESP01모듈 사용을 위한 회로도와 코드 & App과 앱인벤터 파일 :

 여기서 아두이노는 USB to TTL 모듈처럼 동작하도록 회로를 연결하였어요.

(아두이노의 Reset→GND에 연결, 0번,1번 하드웨어 시리얼 핀 사용)

 

 

[ 중요 사항 ] 

 아래 회로들을 보시기전에 개념정리를 위해 지금 이 부분을 꼭 읽어보세요. 

아래 회로가 #1 ~ #4까지 있습니다. 

기본적으로 ESP-01모듈을 메인 보드로 사용하는 개념이며,  #1과 #2회로의 우노 보드는 프로그램을 업로드하여 실행 시키는 보드로 사용한게 아니고, ESP-01모듈에 프로그램을 업로드 시키기위한 하드웨어 시리얼 통신장치로 사용한 것 뿐입니다.    그래서 #3과 #4회로에서는 USB-to-TTL 전용모듈을 사용한 예시를 든 것입니다.  

 

 여기서 중요!!!   #1과 #2의 차이가 무엇인지?   #3과 #4의 차이가 무엇인지 설명 드릴께요.

ESP-01 모듈의 경우 플래시메모리에 프로그래밍을 올리기 위해서는 쓰기모드로 만들어 주어야 합니다. 

쓰기모드가 되기 위해서는 ESP-01모듈의 'GPIO 0'번 단자가 GND에 연결되어 있으면 쓰기모드가 됩니다. 

그리고 이렇게 코드를 올린 다음에는 올려진 코드로 프로그램을 돌리기 위해서는 'GPIO 0'번 단자는 다시 GND에서 분리 시켜야 합니다, 또는 LED를 연결해서 사용하면 되는 것이죠. 

 

만약 코드를 업로드 하는 과정에서 아래와 같은 에러가 난다면,  이는 GPIO0 번 단자를 GND에 연결하지 않고 업로드를 진행해서 나는 에러입니다. 

warning: espcomm_sync failed
error: espcomm_open failed
error: espcomm_upload_mem failed
error: espcomm_upload_mem failed

그래서, 우노를 이용할때 #1번 회로 연결로 코드를 업로드 시키고,   #2번 회로로 연결해서 LED를 GPIO 0번 단자까지 모두 연결 시켜 돌리기 위한 회로를 의미합니다.   

 

마찬가지로, USB-to-TTL 모듈을 이용할때 #3번 회로 연결로 코드를 업로드 시키고, #4번 회로로 LED를 GPIO 0번 단자까지 모두 연결시켜서 LED2 개 모두 돌리기 위한 회로 연결을 보여드린 것입니다. 

 

 

그리고, 코드 업로드 직전에 회로에 연결된 리셋 버튼(플래시 스위치)을 한 번 눌러 주고 ,  업로드 시키면 에러 없이 잘 진행 됩니다.  

 

이렇게 해도 에러가 난다면,  그건, 어딘가에 회로 연결이 잘못 되었거나, 접촉불량일 가능성이 있으니 연결과,  불량점퍼선이 있는지? 멀티테스터기로 체크해보시고,  또는 브레드보드도 자주 끼우고 빼다 보켠 접촉부위가 헐거워져 접촉이 불안정 할 수 있으니 브레드 보드도 체크해보세요. 

 

 

 【 #1 PC → 아두이노 ESP01  회로 연결도

(이전 LED 깜빡이 회로와 동일합니다  - 이미지를 클릭하면 확대 됩니다.)

 여기서 아두이노는 USB to TTL 모듈처럼 동작하게 되는 하드웨어 시리얼 통신을 이용하게 되는데요, 장점은 소프트웨어 통신에 필요한 통신속도인 9600bps로 통신하기 위한 까다로운 펌웨어 업데이트 작업이 필요 없게 됩니다.

 단, 아두이노에 시리얼 통신관련 방해가 되지 않도록 비어 있는 코드를 넣어 초기화 해주거나, 아두이노를 막 뜯었을 때 들어있는 Blink예제와 같은 단순, 기본 예제 코드만 업로드 되어 있으면 상관없습니다. (에러 방지) 

 

【 #2  ESP01 ↔ LED 연결도 

(이전 LED 깜빡이 회로와 동일합니다)

 #1번 회로에서 GPIO 0번에 연결된 선에 추가 LED와 저항을 연결해주면 됩니다.

 

 【 #3 PC → USBtoTTL  ESP01  회로 연결도 

(이전 LED 깜빡이 회로와 동일합니다)

※ USB to TTL 모듈의 출력핀 혹은 점퍼 설정은 반드시 3.3V를 사용해야 ESP01 모듈이 손상되지 않습니다.

 USB to TTL 모듈을 이용하면, 아두이노 없이 esp01 모듈에 코드를 올릴 수 있어요.  다르게 이야기하면, ESP01 모듈도 아두이노처럼 사용할 수 있는 모듈이예요. 내부에 용량은 작지만 프로그램 저장 공간인 플래시롬도 있고, 프로그램이 동작할 수 있도록 메모리도 있으며, CPU도 갖춰져 있는 보드이기 때문이죠. 

 참고로 USB to TTL 모듈은 크게 FTDI 사에서 만든 모듈과,  호환칩셋 제조사인 cp2102 모듈 시리즈가 대표적인데요,  회로 연결 방법의 차이 때문 인지는 모르겠지만, 본 실습에서는 전송에러가 전혀 없었던, cp2102 모듈을 사용하는 것을 권해드려요.  다만, 호환칩셋이여서 최초 연결시 간단히 드라이버 업뎃을 해주기만 하면 되요. 

 

【 #4  ESP01(LEDx2) USBtoTTL 연결도  

※ USB to TTL 모듈의 출력핀 혹은 점퍼 설정은 반드시 3.3V를 사용해야 ESP01 모듈이 손상되지 않습니다.

바로 위 회로 연결과 거의 같으며, LED를 두 개 이용하기 위해 GPIO 0번 단자에 LED를 추가로 연결해준 연결 도면 입니다. 

 

 아두이노 스케치 IDE에 WiFi 보드 추가하기 :

 중요 포인트는 아두이노에 코드를 올리려는 것이 아니라, ESP01 모듈 보드에 코드릴 올리는 것임을 기억하세요~!  ^^

 따라서 아두이노 스케치 IDE에 ESP-01보드를 선택할 수 있어야 하는데요,  하지만, 아두이노 스케치 IDE에는 기본적으로 선택할 수 있는 WiFi보드가 보이지 않죠. 

 이럴 때 아래와 같은 간단한 작업으로 WiFi 보드를 추가해 주면 메뉴에서 WiFi 보드가 보이게 됩니다.

 

 우선 아두이노 IDE를 열고 메뉴,  ' 파일  환경설정 '을 클릭 하세요. 

 위 그림에서 점선 부분 비어 있는 곳에 아래 주소를 붙여넣기 해주세요.

환경 설정 주소 :  http://arduino.esp8266.com/stable/package_esp8266com_index.json   

[ 위 주소부분 새창 열기(링크복사) ]

 

 

확인을 누르고 

 아래 이미지 처럼 아두이노IDE에서   툴  보드  보드메니저 항목을 클릭 합니다.

 보드메니저 창이 열리면 아래 그림처럼 검색항목에 esp8266을 입력하고 엔터 하세요.

그리고 반드시 버전을 2.3.0 버전으로 설치하세요!!! 

만약 최신 버전을 설치하게 되면, 현재 올리는 코드에서 사용된 함수 등이 달라 제대로 동작 되지 않을 수 있고, 아두이노 관련 IDE의 보드 관련 메뉴옵션 항목이 달라서 헷갈릴 수 있어요. 

 아래 그림처럼 2.3.0 버전으로 설치되면 됩니다. 

 

 아두이노IDE에서   툴  보드메니저 항목으로 들어가 보면,  아래처럼 WiFi 보드 메뉴가 추가 된 것을 볼 수 있습니다.

그럼 wifi 보드 중에서 화살표시 처럼 Generic ESP8266 Module 보드를 선택합니다.

그리고 다시 툴메뉴로 들어가 보면 WiFi 관련된 옵션메뉴가 나와있는데,  아래 이미지 처럼 옵션을 선택해 주세요. 

아울러 아두이노가 연결된 포트를 선택하세요.

 

----------------  [추가 사항]  ------------------

보드메니저의 보드 추가 화면에서, 8266보드 버전을 최신 버전으로 설치하였고, 아래와 같은 설정으로 했을 때 문제 없이 작동 되었기에 추가 사항 보충합니다. 

 

코드 전송후 시리얼 모니터창을 열고, 속도를 115200bps로, Both NL & CR 로 설정한 다음 ESP-01회로에 있는 리셋 버튼을 눌러 주면, 아래 처럼 IP를 할당 받은 것을 볼 수 있습니다. 

단, 주의 할 것은, 코드 전송하기 위해 GND에 연결해 놓았던, GPIO 0번 단자를 GND에서 빼고서 LED에 연결해 주어야 아래처럼 정상 작동 합니다.  

----------------------------- [ 추가 사항 끝 부분 ] ----------------------------

 

 

 

 그럼, 이제 WiFi로 접속하여 LED를 제어하는 코드를 아두이노 스케치에서 열어,  코드를 업로드 해보겠습니다

코드는 아래와 같으며, zip으로 폴더째로 압축해 올리니 다운받아 압축을 풀어서 사용하세요. 압축용량은 1.38KB 입니다.

[ ESP01 업로드 코드 ]  다운로드

WiFiWebServerLED2OK.zip
0.00MB

 

[ WiFi LED 제어 코드 ]

/*  ### 스마트폰 WiFi로 esp8266모듈회로의 LED 켜고·끄기 ### 
 *  1. LED를 연결한 esp8266 회로를 서버로 동작시킨다. 
 *  2. 앱인벤터를 이용하여 접속앱을 직접 제작 한다.
 *  3. 접속앱에서 esp8266 서버 주소를 입력하고 접속한다. 
 *    (접속 IP 주소는 코드 업로드가 완료되면 시리얼모니터(115200bps)를 통해 확인 가능함)
 *  4. 앱화면의 버튼을 눌러 LED를 On·Off 할 수 있다.(GPIO0(LED1), GPIO2(LED2))
 *  5. 아두이노 우노를 제거하고 미니 전원을 연결하여 소형화 된 무선 WiFi 모듈을 구성해본다.  
 *    http://server_ip/gpio0/0 이면 GPIO0(LED1) 를 LOW로 설정,
 *    http://server_ip/gpio0/1 이면 GPIO0(LED1) 를 HIGH로 설정,
 *    http://server_ip/gpio2/0 이면 GPIO2(LED2) 를 LOW로 설정,
 *    http://server_ip/gpio2/1 이면 GPIO2(LED2) 를 HIGH로 설정,  *    
 *  주의 : 반드시 동일한 내부 네트웍(하나의 공유기로 연결된)에서 동작 시켜야 접속이 이루어 집니다.
 */

#include <ESP8266WiFI.h>
#define GPIO0 0
#define GPIO2 2
const char* ssid = "xxxx";         // 공유기(AP) 접속 ID
const char* password = "*****";    // 공유기(AP) 접속 패스워드
// 서버 인스턴스를 생성합니다 (80번 포트 지정)
WiFiServer server(80);

void setup() {
  Serial.begin(115200);
  delay(10);
  // GPIO 포트들을 초기화 합니다
  pinMode(GPIO0, OUTPUT);
  digitalWrite(GPIO0, 0);
  pinMode(GPIO2, OUTPUT);
  digitalWrite(GPIO2, 0);
  // Serial 통신으로 WiFi 네트웍에 연결합니다.
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  
  WiFi.begin(ssid, password);  // 네트웍에 설정된 id와 패스워드로 접속을 합니다.
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  
  // 서버 시작
  server.begin();
  Serial.println("Server started");

  // 서버의(esp8266) IP 주소를 출력합니다 
  Serial.println(WiFi.localIP());
}

void loop() {
  // 클라이언트가 접속하는지 체크 합니다
  WiFiClient client = server.available();
  if (!client) {
    return;
  }
  
  // 클라이언트가 데이터를 보낼 때까지 기다립니다.
  Serial.println("new client");
  while(!client.available()){
    delay(1);
  }
  
  // 요청 첫 출을 읽어 옵니다.
  String req = client.readStringUntil('\r');
  Serial.println(req);
  client.flush();
  
  // 요청 사항과 비교해봅니다.
  int GP0val=0;
  int GP2val=0;
  
  if (req.indexOf("/gpio0/0") != -1)
    GP0val = 0;
  else if (req.indexOf("/gpio0/1") != -1) 
    GP0val = 1;
  else if (req.indexOf("/gpio2/0") != -1)
    GP2val = 0;
  else if (req.indexOf("/gpio2/1") != -1)
    GP2val = 1;
  else {
    Serial.println("invalid request");
    client.stop();
    return;
  }
  // 요청에 따라 GPIO 들을 셋팅합니다(ON 또는 OFF)
  digitalWrite(GPIO0, GP0val);
  digitalWrite(GPIO2, GP2val);  
  client.flush();
  // 응답을 준비합니다.
  String s1 = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n \r\n\r\nGPIO 0 is now ";
  String s2 = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n \r\n\r\nGPIO 2 is now ";
  s1 += (GP0val)?"HIGH":"LOW";   //GP0val 값에 따라 HIGH 또는 LOW 응답합니다.
  s1 += "\n";
  s2 += (GP2val)?"HIGH":"LOW";   //GP2val 값에 따라 HIGH 또는 LOW 응답합니다.
  s2 += "\n";

  // 클라이언트로 응답을 보냅니다
  client.print(s1);
  delay(1);
  client.print(s2);
  delay(1);
  Serial.println("Client disonnected");  // 응답완료 후에는 클라이언트를 닫습니다.

 

 

[ 안드로이드 구동 앱 App 다운로드 (.Apk)]  다운로드

WebLED2.apk
3.36MB

 

[ 앱-인밴터 제작 프로젝트 파일(.aia) ]  다운로드

 

WebLED2.aia
0.01MB

앱 인벤터 메뉴중 아래 Import project (.aia) from my computer... 메뉴를 통해 다운받은 위의 첨부파일을

선택해주면, 본 글에서와 똑같은 완성된 화면디자인과 블록을 열 수 있어요. 

 

▶ 2. 전체 실습 과정 순서 & 설명

- 1. 위의 #1번 연결도면을 참고하여 회로를 연결해줍니다.  

 

- 2. 아두이노 스케치 IDE에  WiFi 보드를 추가해 줍니다 (위, 추가 내용 참조)

 

- 3. LED 제어 코드를 아두이노를 통해 ESP01 모듈에 업로드해 줍니다.

 

- 코드 업로드 후 회로연결을 아래처럼 LED를 추가 연결해 줍니다. 

- 시리얼 모니터창을 열고 리셋 버튼을 누르면 , 아래 화면처럼 esp01모듈이 WiFi 공유기로 부터 할당 받은 IP를 확인할 수 있어요.   이때 시리얼 모니터의 출력이 깨져 나온다면, 통신속도(보드레이트)가 맞아 않아 그러하니, 코드에 설정한 115,200bps 로 맞추어 주면 제대로 표시 됩니다.

 

 

- 앱제작전, 하드웨어를 테스트 하기 위해 위에서 제공하는 앱을 다운받아 설치 후 아래 과정을 테스트하거나,  이글 후반부에 소개되는 앱제작을 먼저 진행 후 다시 여기로 와서 실습을 진행하여도 됩니다. 

- 앱 설치와 실행 후 자신의 WiFi가 할당받은 주소를 앱의 주소입력창에 입력하고, On Off 버튼을 눌렀을 때 LED가 ON/OFF 잘 되는지? 확인 해보세요.

 

- 이번엔, 아두이노가 아닌 USB to TTL 모듈을 사용해서 동작코드를 esp01 WiFi 모듈에 전송 해 볼게요.

연결 회로도면은 이글 위쪽에 있는  #3번과 #4번 연결도를 참고하세요.  FTDI칩셋 모듈보다는, cp2102호환 칩셋을 사용한 커버터가 에러 없이 코드전송이 잘 되어 추천 드려요.  다만, 호환 칩셋이므로, 처음 PC에 연결 할 때 제어판의 장치관리자에서 cp2102 모듈의 드라이버를 설치해주어야 제대로 장치가 인식됩니다. 

 

- 코드 전송후 시리얼 모니터 창을 띄워 WiFi 모듈이 할당 받은 주소를 확인해보세요.

 

- 모듈이 할당 받은 주소를 앱에 입력하여 동작시켜 보면, 잘 동작하는 것을 볼수 있어요. 3

- 아래 이미지 처럼, AMS1117 3.3V 레귤레이터 모듈과 3.7V(80mA) 소형 리튬폴리머 배터리를 이용하면 휴대성이 업된 미니 WiFi 기기를 만들 수 있어요. 

 

- 앱 인벤터를 이용한 안드로이드 앱제작

 앱인벤터를 이용하면, 자바와 같은 다소 어려운 코딩지식이나, 안드로이드 스튜디오와 같은 복잡한 툴 사용을 하지 않더라도, 충분히 원하는 동작의 앱을 만들 수 있어요.  이 글에 있는 영상강좌를 따라 해보면, 10분이면 충분히 따라 할 수 있으니 지금 바로 해보세요. 

 혹시, 앱인벤터의 메뉴 설명부터 앱인벤터 실행을 위한 구글 계정 가입 등의 안내글이 필요하다면,  여기 라즈이노 사이트에 게시한 앱인벤터 기초 과정 글을 먼저 참고하셔도 좋습니다. 

 또는 유튜브에 올린 앱인벤터 기초강좌를 보셔도 좋아요. 

(링크 :  https://www.youtube.com/playlist?list=PLu4OqX22_eU29GPIGqHsH_rU28vCNaV63 )

 

- 앱인벤터 제작과정은 아래 유튜브 영상의 후반부를 참고하세요

- 앱인벤터의 완성된 디자인편집화면 모습

위 앱인밴터 제작에 사용된 텍스트 이미지 다운로드 : 

Text_Image.zip
0.01MB

 

- 앱인벤터의 완성된 블록화면 모습

- 앱인벤터 제작이 완료 되면, 앱인벤터 Build메뉴에서 앱을 빌드(제작)하세요. 

영상에서는 아래 두 가지 빌드 방법중 두 번째 방법으로 진행했어요.  앱을 우선 PC에 저장하고 스마트폰을 USB데이터 케이블로 PC와 연결한 후 만들어진 xxxxx.apk 앱설치파일을 복사해 넣는 방법으로 진행 했습니다. 

-  그럼, 스마트폰에서 파일탐색앱 같은 것을 실행시켜 스마트폰에 옮겨진 앱설치파일을 찾아 설치해주세요. ( 동의를 묻는 팝업창이 뜨면 모드 예로 해주셔야 설치가 진행됩니다)

 

- 앱이 설치 되었다면, esp모듈을 놓고 테스트해보세요. 

- 아두이노를 이용한 esp01 회로와, 휴대용으로 만든 미니 esp01 버전 두 가지를 놓고 IP번호를 선택해가며 테스트 해볼 수 있습니다. 

- 최종 실습에 성공했다면, 여려개의 WiFI 모듈을 구성해서 동시에 제어할 수 있는데요,  LED 이외의 모듈을 달아 본인이 원하는 동작회로를 구성해보고, 앱인벤터도 좀더 다양한 동작과 앱꾸미기를 더해서 응용 실습을 해볼 수 있습니다. 

 

▶ 3. 전체 실습 과정 영상으로 보기

https://youtu.be/_Ugw-8EPOa8

 

 

▶ 4. 코드 업그레이드
: LED를 개별로 On Off 제어가 되도록 코드 일부를 업데이트 했으니 꼭 참고해 보세요(아래 링크 클릭!)

【 아두이노 프로젝 업뎃#1】 ESP8266 esp-01 스마트폰으로 LED 컨트롤 하기 업뎃 자료


반응형
반응형

 

【 아두이노모듈#27 ESP8266 esp-01 활용하기#3 : LED 깜빡이기 (Plus 휴대용 무선기기 만들기)

(본문의 모든이미지는 클릭하면 확대하여 볼 수 있습니다)

 

 ESP8266은 wifi 통신을 이용하고 인터넷(네트웍)이나 직접 연결(무선)로 제어가 가능한 모듈이며, cpu, 메모리, 입출력 핀을 내장하고 있어서 아두이노 없이 단독으로도 활용가능한 모듈입니다.

모듈 종류는 세부 스팩별로 다양하게 있지만, esp8266모듈중에 가장 기본인 esp-01모듈에 대해 다룹니다. 가격이 저렴하고 2개의 입출력 포트를 쉽게 활용할 수 있고, 크기가 작아 소형 무선기기로 만들 수 있는 장점이 있습니다. 더욱이 WiFi에 접속할 수 있는 Station 기능과 WiFi AP로 동작시킬 수 있는 아주 매력적인 모듈입니다. 

  그럼 이번시간에는 esp8266 보드에 LED2개를 연결하고 깜빡이게 하는 코드를 올려 볼텐데요, 첫 째 아두이노를 활용하는 방법과, USB to TTL 모듈을 활용하는 방법에 대해 각각 설명합니다.  그리고 esp-01 핀 소켓(breakout)을 이용해서 미니 회로로 꾸며 보도록 하겠습니다.

 아울러 다음 시간에는 웹서버로서 동작할 수 있도록 강의할 예정이니 많은 관심 부탁드릴께요~

esp8266기본 모델인 esp-01

Module Espressif ESP8266
ESP8266 Version ESP-01
동작 명령 방식 UART AT Command
안테나 On-Board Ceramic Antenna
통신 방식 802.11 b/g/n 지원
통신 속도(Baud Rate) - 115200(디폴트)   
- 소프트웨어-시리얼: 57600bps~2000000bps 
- 하드웨어-시리얼 : 9600bps~2000000bps
Flash memory 16M Byte
프로세서 스피드 80-160Mhz
크기(Size) 14.5 x 24.8 mm
   

 선수학습 :

  1.  ESP-01 펌웨어 기초 & 업데이트 하기(에러 대처) 

  2.  ESP-01 펌웨어 기초 & 업데이트 하기 (영상강좌)

 

▶ 1. 아두이노를 이용해 코드를 업로드 하기 :

 여기서 아두이노는 USB to TTL 모듈처럼 동작하게 되는 하드웨어 시리얼 통신을 이용해 볼텐데요, 장점은 소프트웨어 통신에 필요한 통신속도인 9600bps로 통신하기 위한 까다로운 펌웨어 업데이트 작업이 필요 없게 됩니다.

아래 회로를 참고하여 아두이노를 구성해주세요,  단, 아두이노에 시리얼 통신관련 방해가 되지 않도록 비어 있는 코드를 넣어 초기화 해주거나, 아두이노를 막 뜯었을 때 들어있는 Blink예제와 같은 단순, 기본 예제 코드만 업로드 되어 있으면 상관없습니다. (에러 방지) 

아두이노를 USB to TTL 모듈처럼 이용한 WiFi모듈 연결 회로

 위 회로에서 아두이노의 Reset 단자가 GND에 연결 되면, 아두이노의 플래시롬에 코드를 업로드 하지 않게 되고 USB to TTL 모듈과 같은 하드웨어 시리얼 통신기기와 같은 역할을 하게 됩니다. 

따라서 만약 아두이노에 코드를 업로드 하려고 한다면, Reset단자와 GND단자의 연결을 해제하면 됩니다. 

만약 아두이노에 시리얼 통신을 사용하는 코드가 있으면 통신에 방해를 줄 수 있으니 비어있는 코드를 아두이노에 업로드 해주거나, Blink와 같은 단순한 예제 코드가 들어 있으면 문제 없습니다.

 

 아두이노에서 3.3V 출력만 사용하세요. (일부 아두이노 호환보드에서는 잘 사용되지 않는 3.3V쪽에 저가의 부품을 사용하다보니 출력이 약할 수 있습니다, 이때 WiFi모듈 동작에 문제가 될 수 있음.) 

 

 또한, WiFi 모듈의 경우 3.3V레벨의 전압만 인가해야 합니다. 만약 5V와 같은 높은 전압이 일정시간 이상 인가 되면 WiFi 모듈이 손상될 수 있는데요,  WiFi 모듈의 VCC단자 뿐아니라, 신호를 수신하는 RX단자에도 3.3V레벨을 넣어 주어야 합니다.  이 때문에 1K옴 저항 세 개를 이용한 전압분배 회로를 넣어 준 것인데요, 5V의 2/3 지점이 3.3V가 되는 원리입니다.  따라서 1K옴과 2K옴 저항 두 개를 사용해서 연결해도 됩니다.  아두이노의 TX 출력단자의 출력도 5V레벨 이기에 WiFi의 Rx단자에 직접 연결하면 손상을 입힐 수 있기 때문입니다. 

 회로의 플래시 스위치는 영상에서 처럼 굳이 달지 않고 직접 GND로 연결해주는 것이 더 편할 수 있어요.

 아두이노 보드를 자세히 보면, 0번 단자에 'RxD ◀' 라고 표시되어 있는데요, 0번 단자가 Rx 단자가 아니라 , 외부Rx단자를 여기에 연결하라는 뜻이므로 아두이노의 0번은 Tx단자 입니다.  마찬가지로,  TxD 라고 표시 되어 있는 1번 단자는 외부 Tx단자로 연결하라는 뜻으로 Rx단자입니다. 

 

아두이노 스케치 IDE에 WiFi 보드 추가하기 :

  LED를 깜빡이게 하는 코드는 아두이노에 올리려는 것이 아니라, 아두이노를 통해 WiFi에 코드를 올리려고 하는 것이예요.  그러면 아두이노 스케치 IDE에서 WiFi보드를 선택할 수 있어야 WiFi 보드에 코드를 올리겠죠?   하지만, 아두이노 스케치 IDE에는 아두이노 보드 종류들만 있어서 WiFi보드 선택이 안 됩니다. 

이럴 때 아래와 같은 간단한 작업으로 WiFi 보드를 추가해 주면 메뉴에서 WiFi 보드가 나타나게 됩니다.

 

 우선 아두이노 IDE를 열고 메뉴,  ' 파일 환경설정 '을 클릭 하세요. 

 위 그림에서 점선 부분 비어 있는 곳에 아래 주소를 붙여넣기 해주세요.

환경 설정 주소 :  http://arduino.esp8266.com/stable/package_esp8266com_index.json   

[ 위 주소부분 새창 열기(링크복사) ]

 

 

확인을 누르고 

 아래 이미지 처럼 아두이노IDE에서   툴  보드 보드메니저 항목을 클릭 합니다.

 보드메니저 창이 열리면 아래 그림처럼 검색항목에 esp8266을 입력하고 엔터 하세요.

그리고 반드시 버전을 2.3.0 버전으로 설치하세요!!! 

만약 최신 버전을 설치하게 되면, 현재 올리는 코드에서 사용된 함수 등이 달라 제대로 동작 되지 않을 수 있고, 아두이노 관련 IDE의 보드 관련 메뉴옵션 항목이 달라서 헷갈릴 수 있어요. 

 아래 그림처럼 2.3.0 버전으로 설치되면 됩니다. 

 

 아두이노IDE에서   툴  보드메니저 항목으로 들어가 보면,  아래처럼 WiFi 보드 메뉴가 추가 된 것을 볼 수 있습니다.

그럼 wifi 보드 중에서 화살표시 처럼 Generic ESP8266 Module 보드를 선택합니다.

그리고 다시 툴메뉴로 들어가 보면 WiFi 관련된 옵션메뉴가 나와있는데,  아래 이미지 처럼 옵션을 선택해 주세요. 

아울러 아두이노가 연결된 포트를 선택하세요.

 

----------------  [추가 사항]  ------------------

보드메니저의 보드 추가 화면에서, 8266보드 버전을 최신 버전으로 설치하였고, 아래와 같은 설정으로 했을 때 문제 없이 작동 되었기에 추가 사항 보충합니다. 

 

코드 전송후 시리얼 모니터창을 열고, 속도를 115200bps로, Both NL & CR 로 설정한 다음 ESP-01회로에 있는 리셋 버튼을 눌러 주면, 아래 처럼 IP를 할당 받은 것을 볼 수 있습니다. 

단, 주의 할 것은, 코드 전송하기 위해 GND에 연결해 놓았던, GPIO 0번 단자를 GND에서 빼고서 LED에 연결해 주어야 아래처럼 정상 작동 합니다.  

----------------------------- [ 추가 사항 끝 부분 ] ----------------------------

 

 

그럼, 이제 LED를 깜빡이게 하는 코드를 열고 업로드 해보겠습니다

코드는 아래와 같으며, zip으로 폴더째로 압축해 올리니 다운받아 압축을 풀어서 사용하세요.

Two_LED_OnOff.zip
0.00MB

- LED x 2 깜빡이 코드 

const int GPIO0 = 0;
const int GPIO2 = 2;
void setup() {
  Serial.begin(115200);
  pinMode(GPIO0, OUTPUT);   
  pinMode(GPIO2, OUTPUT);   

void loop() {
  Serial.println("GPIO0, GPIO2 are LOW");
  digitalWrite(GPIO0, LOW);   
  digitalWrite(GPIO2, LOW);                                 
  delay(1000);                
  Serial.println("GPIO0, GPIO2 are HIGH");
  digitalWrite(GPIO0, HIGH);  
  digitalWrite(GPIO2, HIGH);
  delay(2000);                
}

 

- 이제 아래 그림처럼, 업로드 버튼을 눌러 코드를 WiFi모듈에 업로드해 주세요.  

업로드 전 WiFi 에 연결된 리셋(Reset)스위치를 꼭 누르고 있어야 합니다. 혹은 

위 그림처럼, 100% 완료 되어야 합니다. 

만약, 아래 그림처럼 도중에 에러가 나면,  업로드가 되지 않은 것이니 문제를 해결하고 다시 시도해 주세요.

위와 같은 에러가 난다면, WiFi 모듈의 RST 단자에 연결된 리셋 스위치를 다시 한 번 눌러주거나 GND단자에 직접 연결해주고서 업로드 버튼을 누르면 해결됩니다.  또한 GPIO 0번단자를 GND에 반드시 연결해야 합니다. 

 

- WiFi에 코드 업로드가 제대로 되었다면, 아래처럼 GND에 연결해 놓았던 GPIO 0번 단자를 330옴 저항과 LED를 추가로 연결해 줍니다.  

- 그럼 두 개의 저항이 아래 이미지 처럼 두 개의 LED가 1초 간격으로 깜빡일 거예요.

 

- 그럼, 이제 코드 연습겸 아래 이미지 처럼, 점선 부분의 코드로 바꾸어 봅니다.

 (두 개의 LED가 번갈아 가며, 0.5초 간격으로 깜빡임)

- 바뀐 코드를 다시 업로드 하기 위해 위에서 했던 과정을 다시 해줍니다. 

 1) GPIO 0번 단자를 GND로 연결하기

 2) 리셋 버튼을 누르고 아두이노에서 업로드 버튼 클릭하기 (100%까지 기다림)

 3) 업로드 완료 되면, GPIO 0번 단자를 추가된 LED에 연결하고 리셋 버튼을 한 번 눌러줌

그럼 아래 그림처럼 LED가 0.5초 간격으로 번갈아 깜빡이는 걸 볼 수 있습니다.

  

▶ 2. USB to TTL 을 이용해 WiFi에 코드를 업로드 하기 :

아래 이미지 처럼 아두이노 없이 USB to TTL(또는 USB to Serial이라고 부름) 모듈을 이용해서 코드를 업로드 해볼께요.   사실, 위에서 아두이노가 아두이노의 역할을 한 것이 아니라 지금 여기의 USB to TTL 모듈의 역할을 한 것이라 이해하면 됩니다. 

USB to TTL 모듈에는 몇가지 종류가 있는데요,  위 이미지의 두 가지를 사용해 본 결과 둘 다 업로드 완성된 회로에서의 작동은 문제 없었으나, WiFi의 롬에 코드를 업로드 할 때 FTDI 칩셋의 USB to TTL 모듈의 경우 업로드 때 에러가 계속 났었기 때문에,  cp2102 호환 칩셋을 사용한 USB to TTL 모듈을 사용 해보시길 권장해드려요. 

 추가적으로 CP2102 칩셋을 처음 PC에 연결하면, 장치 인식을 위해 제어판 장치관리자에서 드라이버를 설치해 주어야 합니다. 

Windows10 사용자라면,  윈도우키 + 'X'를 눌러 장치관리자를 클릭해 들어가세요.   그리고 드라이버 설치가 안 된 알수없는 장치를 찾아 속성 화면을 찾아 들어간 후,  또는 드라이버 미설치 장치를 선택, 마우스 우클릭 후 드라이버 업데이트 진행하면 아래 그림처럼 CP2102 USB to TTL 장치가 제대로 안착된 화면을 볼 수 있어요. 

 제가 연결한 CP2102 장치는 Com23포트가 할당 되었네요. 

 

그럼 아두이노 IDE의    포트 메뉴 에서 23번 포트로 장치 선택을 해주면 업로드 준비가 됩니다. 

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

 

아두이노 연결 때와 같은 방법으로 코드 업로드가 완료 되면, 아래 그림처럼 LED를 하나더 추가 연결해 주면 됩니다. 

 

 실제 영상에서는 WiFI모듈을 브레드보드에 깔끔하게 연결 하기 위해  esp-01 breakout 소켓을 사용하였는데요, 영상에서는 기판을 잘라 직접 납땜해서 만들었지만,  웬만하면 그냥 인터넷에서 하나 사서 사용하시는 걸 권해드려요. ㅎㅎ ㅋ 

자작해본 esp-01 breakout 소켓

 

 업로드 다 되고 LED를 2개 모두 연결하면 아래 이미지 처럼 동작이 잘 되네요. 

- 자 이제 USB to TTL 모듈을 제거해 볼까요?  USB to TTL 모듈은 아두이노IDE를 통해 코드를 전송하는 기능과 WiFi 모듈에 전원을 공급하기 위한 역할을 했는데요,  코드는 전송되었고, 외부전원만 연결해주면, USB to TTL이 없어도 동작하게 됩니다. 

 

 외부 전원용으로는 회로를 작게 유지하기 위해 작은 부품들을 사용했습니다. 

배터리는 3.7V 80mAh짜리 리튬폴리머 사용했고,  3.3V 정격 전원용으로 AMS1117(3.3V) 정전압 모듈을 사용했습니다. 

연결한 결과 아주 잘 작동 하고 있네요.

 

끝으로, WiFi 모듈마다 서로 다른 코드를 업로드 해 놓고 바꿔 끼워가며 활용할 수 있겠네요.

그럼 전체 이 글의 내용전체를 영상으로 쉽게 설명해 놓았으니 아래 영상을 꼭 한번 보세요.

다음 글에서는 앱인벤터로 앱을 직접 만들고 앱에서 버튼을 누르면 WiFi로 LED를 켜고 끄는 내용을 다루어 보겠습니다.   

 

반응형
반응형

【 영상-아두이노모듈#26 ESP8266 ep-01 활용하기#2 : 펌웨어 업뎃 영상 강좌

 

 지난 시간 ESP8266중 기본 모델인 esp-01모듈의 소개와 펌웨어 업데이트에 대해 그리고 업뎃 실패에 따른 에러대처에 대해 다루었는데요, 펌웨어 업뎃이 생각만큼 쉽지 않고 연결 방법도 헷갈리는 경우가 많아서 esp모듈을 처음 접하는 분들이 많이 어려워하고 있기에, 영상버전으로 차근 차근 설명을 하고 보여드리고자 제작하게 되었습니다.  앞글을 참고하면서 영상을 보신다면 보다 쉽게 이해되시리라 생각됩니다. ^^;

 

 

▶ 선수학습 :

    1. [아두이노 모듈#25] 【 아두이노모듈#25】 ESP8266 esp-01 활용하기#1   ☜ (클릭)

(모듈 기본 정보-상세내용은 위 선수학습 참조)

Module Espressif ESP8266
ESP8266 Version ESP-01
동작 명령 방식 UART AT Command
안테나 On-Board Ceramic Antenna
통신 방식 802.11 b/g/n 지원
통신 속도(Baud Rate) - 115200(디폴트)   
- 소프트웨어-시리얼: 57600bps~2000000bps 
- 하드웨어-시리얼 : 9600bps~2000000bps
Flash memory 16M Byte
프로세서 스피드 80-160Mhz
크기(Size) 14.5 x 24.8 mm

ESP-01 모듈 활용의 장점


▶ 1. 아두이노 우노에 연결하여 업뎃 하기 : 

※ 영상에서 사용된 아두이노와 esp-01 모듈의 연결 회로도 :
(이미지를 클릭하면 확대 됩니다)

아두이노를 하드웨어 USB to TTL 모듈처럼 이용하는 방법이 가장 확실합니다.  따라서 아두이노의 Reset단자를 GND에 연결하여 MCU는 동작하지 않게 하고 하드웨어적으로 시리얼 통신 하도록 0번, 1번 핀을 이용해 통신하면 됩니다. 

 이때, 0번을  esp-01의 Rx 단자에 연결하고, 1번을  esp-01의 Tx 단자에 연결 하여야 합니다. 그리고 CH_PD 단자가 +3.3V에 함께 연결 되어 있어야 하고, GPIO0 단자는 GND로 연결해야 하며,  반드시 5V 전원을 사용하지 말고 아두이노의 3.3V 전원을 사용해야 esp-01모듈의 손상을 방지 할 수 있습니다.


※ 영상에서 사용된 USB to TTL 모듈을 이용한 펌웨어 업데이트 회로도 :
(이미지를 클릭하면 확대 됩니다)

ESP8266 USB to TTL 펌웨어 업뎃 연결도

 아래의 플래시 프로그램으로 download 하기 전에, Program 스위치를 눌러 주어야 업로드가 진행됩니다.

업로드 에러가 날 때는 스위치 누르는 타이밍을 바꾸어 가며 여러번 시도해 보세요. 

또는 회로 연결이 잘 못 되어 있을 경우 업로드 되지 않습니다. 

 

 

※ 플래시 업로드 프로그램 :  

- 아래 zip첨부파일을 다운로드 합니다. (한글 폴더 아래가 아닌 C:\ 루트 드라이버로 옮겨 놓고 압축을 풀어서 사용하세요)

ESP8266-flasher_AT-mode-Updater.zip
8.56MB

 

 - 압축을 풀면 아래와 같은 내용물(파일)이 보입니다.

  - 파일 중에서 esp8266_flasher.exe 파일을 실행시키면 아래와 같은 형태로 실행됩니다.

 ( 기타 자세한 내용은 이전글과 영상을 참고하세요 )

※ 플래시 업로드가 완료 되면, 아래의 회로를 구성하여 AT모드 통신을 통해 esp-01모듈의 설정을 진행할 수 있습니다. 
(이미지를 클릭하면 확대 됩니다)

AT 모드 통신을 위한 연결도면

- 아두이노 포트의 출력은 5V 레벨이므로 WiFi모듈 Rx 수신단자에 3.3V로 다운된 입력을 주기위해 저항 분배를 사용 하였습니다.

- 통신을 위해서는 esp-01 모듈의 Reset 핀을 GND로 리셋 시켜주거나 전원을 껏다 켜주어야 합니다.

통신모드와 보드레이트(9600)를 맞추어 주세요

- 주요 AT 모드 명령어

 - AT명령어 정리 파일 다운로드 :

AT 명령어 요약집.pdf
0.12MB

 

▶ 1. esp-01 업데이트 하기 영상 강좌 보기 : 

 

 

 

【 유튜브로 보기 】

 

반응형
반응형

【 아두이노모듈#25 ESP8266 ep-01 활용하기#1 : 펌웨어 업데이트 에러 해결 (내용보강-완료,영상추가)

 ESP8266은 wifi 통신을 이용하고 인터넷(네트웍)이나 직접 연결(무선)로 제어가 가능한 모듈이며, cpu, 메모리, 입출력 핀을 내장하고 있어서 아두이노 없이 단독으로도 활용가능한 모듈입니다.

모듈 종류는 세부 스팩별로 아래처럼 다양하게 구성되어 있습니다.

다양한 ESP8266 제품군

 그 밖에 ESP12 모듈을 탑재하여 아두이노 처럼 다양한 포트와 확장성을 가지게 하고 사물인터넷(IoT) 구축에 최적화된 보드로, nodeMCU 제품군도 출시되어 있습니다. 

NodeMCU 제품

 사물인터넷, IoT 쪽에 관심이 있다면 우선 ESP8266 esp-01 등과 같은 초기 버전 몇 가지 먼저 다루어 본 후,  NodeMCU 제품군 활용으로 넘어가는 학습이 좋을 듯 합니다.

 

 다른 한편으로 ESP8266 (esp-12e)모듈이 탑재된 아두이노도 있습니다.  기존 아두이노의 경우 비싼 wifi 쉴드를 따로 장착하는 번거러움 없이,  esp-12와 같은 wifi 모듈이 보드에 탑재된 아두이노 버전이라고 이해하시면 되며, 아두이노를 조금이라도 다루어 보셨다면 사용하기에도 크게 어렵지 않습니다.  그리고 최근에는  크기가 작아서 활용도가 높은 D1 mini 제품도 인기가 좋습니다.  Wemos 보드도 차후에 한 번 다루어 보도록 하겠습니다.

아두이노 Wemos D1(좌측) 과 D1 mini (우측)

  그럼, 그 첫 번째 시간으로 ESP8266의 가장 기본이라고 할 수 있는 esp-01 버전에 대해 다루어 볼 텐데요?   가장 기본이지만, 처음 사용하시는 분에게는 결코 만만치 않습니다. 

 그 이유는, esp-01 모듈의 펌웨어 업데이트 라는 관문이 있기 때문이죠.

오늘은 펌웨어 업데이트 필요성과 그 방법에 대해 먼저 다루어 보도록 하겠습니다.

 

ESP-01 WiFi 모듈

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

 


 esp-01은 가장 좋은 가성비를 갖고 있어서 많이 활용되는 모듈인데요?   하지만, 큰 난관(?)이 기다리고 있습니다. 

 esp01을 아두이노에 연결하여 이용하고자 할 때, 서로간 시리얼 통신을 사용해야 하는데, 우리가 많이 사용하는 아두이노 '우노' 보드는 시리얼 통신핀을 1개만 가지고 있습니다(하드웨어 시리얼).  그런데 이 시리얼 통신핀은 PC와 통신하는데(코드 전송, 시리얼 모니터 사용 등) 사용되기 때문에 esp-01과 통신을 할 수 없게 됩니다.   그래서, 우노의 디지털 입출력핀을 이용해서 소프트웨어적으로 'SoftwareSerial' 통신 방법을 이용하게 됩니다. 

 'SoftwareSerial'은 통신 속도를 115,200bps까지 지원하지만, PC의 시리얼 데이터 전송 속도는 이상적인 조건에서 최대 57600bps까지만 가능한데요,   이에 비해, esp-01 모듈의 통신 속도는 115200bps로 기본 셋팅 되어 있기 때문에 서로간 통신이 어렵습니다.   

 그래서 나온 해결방법이 통신 속도를 변경할 수 있도록, esp-01의 플래시 메모리에 있는 펌웨어를 업그레이드 해주게 되면 'SoftwareSerial'이 통신가능한 속도로 변경가능해집니다.

 

  이때 안정적인 통신이 이루어지는 9600bps로 변경하여 사용하게 됩니다.   

(단,  esp-01 모듈의 제조 생산 시기별로 기본 업로드 된 펌웨어 버전이 여러가지여서, 펌웨어 업뎃 없이 통신속도 변경이 AT모드에서 가능할 수도 있으니 참고하세요) 

 

 그런데, 해결방법이 펌웨어 업그레이드라고 나왔지만, 이게 만만치 않습니다. 

아두이노나 이런쪽에 경험이 많지 않은 초기학습자의 경우 인터넷의 자료와 방법을 찾아 보면서 해봐도, 한 번에 해결되는 경우가 매우 드물기 때문에, 많은 사람들이 시도하며 끙끙 앓다가 중도에 포기하거나 한 동안 덮어 두는 사태가(?) 벌어지게 되죠. 

 이에 라즈이노IoT에서는 좀더 세심하게 공을 들여서 설명을 드리고자 하오니,  차근 차근 글을 읽으면서 진행해 보시면 좋은 결과가 있을 것 같습니다.  ^^&

 

더보기

 펌웨어 업데이트 하기 (ESP8266-esp01)

 

★ ☆ ★ 펌웨어 업뎃(교체)을 하는 이유  ★ ☆ ★

1. 펌웨어 업뎃(교체)을 하는 이유 ?
 - 펌웨어 업데이트를 해야하는 이유는 몇 가지가 있습니다. 
 생산되는 esp-01 모듈의 제조시기나 업체(카피 제품 등)에 따라 내장된 펌웨어가 다르고, 디폴트 보-레이트(Baud Rate)가 다를 수 있습니다. 
기본적으로는 esp8266은 AI-Thinker사의 AT-커맨드, 즉 명령어 기반의 AT 명령어를 수신하고 해당 명령어를 실행할 수 있는데, 이를 적절히 사용하기 위한 버전의 펌웨어로 업데이트(교체) 하고자 하거나, esp8266의 보-레이트(Baud Rate)를 변경하고자 할 때 진행하게 됩니다.  본 실습에서는 최신 버전 펌웨어로 업뎃을 하는 것은 아닙니다. 실습을 진행하는데 문제가 없는 안정된 버전으로 펌웨어 교체를 하는 것이며, 가지고 있는 다른 버전의 펌웨어로 교체해도 되지만, 보-레이트가 맞지 않거나 할 경우 등, 실습에 문제가 있을 수 있으므로, 여기서 제공하는 펌웨어로 실습을 진행해 보고 다른 버전으로도 테스트를 해보세요.

 그래서 ESP-01 모듈의 펌웨어 업뎃을 반드시 해야 하는 건 아닙니다. 
 모듈 구매 직후에는 보통은 ESP-01 모듈의 기본 펌웨어가 AT-커맨드(명령어)로 바로 통신이 되지 않는 펌웨어 인 경우가 많습니다.  이런 이유로 펌웨어를 바꾸게 되며, 똑 같은 AT-커맨드 펌웨어라 하더라더 버전에 따라 명령어 지원 가지수도 조금씩 다릅니다. 
따라서, 디폴트 펌웨어 버전에 따라 필요없을 수 있으며,  esp8266을 wifi 어뎁터가 아니라 플래시 메모리에 아두이노 처럼 코드를 올려 사용하고자 할 경우에는 펌웨어 업뎃 없이 바로 사용하면 됩니다. 

▶  esp-8266과 통신하는 방법은 크게 두 가지로 볼 수 있는데요, 
1. AT Command 명령어를 이용한 통신은 PC와 연결된 ESP-01과 PC사이에 시리얼통신을 이용한 통신이구요 이 상태에서 아두이노 IDE의 시리얼 통신창에서 AT 명령어를 입력해서 esp8266의 모드를 바꾸거나, 주변 WiFi에 접속 시킬 수 있습니다.  
2. esp8266의 두 번째 사용법은 시리얼 모니터 등으로 AT 명령어를 직접 사용하지 않고 아두이노 코드에서 WiFi통신이 가능한 코드를 넣고 사용하는 방법입니다. 

※ 먼저 펌웨어 업데이트 하는 방법에는 대표적으로 아래의 세 가지가 있습니다. 

1. 아두이노에 펌웨어 업데이트용 결선 형태로 ESP-01을 연결하고 업데이트 하는 방법.

2. 와이파이 USB to ESP8266 시리얼 전용 어댑터를 사용하는 방법.

시판중인 esp-01 전용 wifi 어뎁터 2가지

 

3. 아두이노 프로미니 처럼 PC와의 통신을 위해서는 별도의 USB to UART 통신 모듈이 필요한데, 이런 모듈을 이용하여 펌웨어를 업데이트 하는 방법이 있습니다.

FTDI칩셋의 통신모듈과(좌측)   cp2102호환 칩셋의 통신모듈(우측)

 

▶ 1. 아두이노 우노에 연결하여 업뎃 하기 : 

    [ 연결 회로 ]

※ 주의 : esp-01의 전원으로는 3.3V를 연결해야 합니다. 만약, 5V를 연결하여도 esp-01모듈이 고장나지 않고 버틸 수는 있지만 장시간 5V 전원을 가할 경우 고장이 날 수 있기 때문에 주의해야 합니다.

 또한, 일부 아두이노 호환보드의 경우 비용절감의 문제로 잘 사용되지 않는 3.3V 단자 쪽의 부품을 저출력의 부품을 사용한 결과 출력(전류)이 낮아 esp모듈의 업데이트나 동작이 불안정하기도 합니다.  이럴 때는 5V 단자를 사용하여 아래에서 소개되는 저항의 분배(1:2)를 이용해 3.3V의 출력을 뽑아서 사용하면 해결 될 수 있습니다. 

 

 1. 아두이노로 esp8266(esp-01) 모듈 펌웨어 업데이트 하기! 

 아두이노를 하드웨어 USB to TTL 모듈처럼 이용하는 방법이 가장 확실합니다.  따라서 아두이노의 Reset단자를 GND에 연결하여 MCU는 동작하지 않게 하고 하드웨어적으로 시리얼 통신 하도록 0번, 1번 핀을 이용해 통신하면 됩니다. 

 이때, 0번을  esp-01의 Rx 단자에 연결하고, 1번을  esp-01의 Tx 단자에 연결 하여야 합니다. 그리고 CH_PD 단자가 +3.3V에 함께 연결 되어 있어야 하고, GPIO0 단자는 GND로 연결해야 하며,  반드시 5V 전원을 사용하지 말고 아두이노의 3.3V 전원을 사용해야 esp-01모듈의 손상을 방지 할 수 있습니다.

 

 

 - 아래 zip첨부파일을 다운로드 합니다. (한글 폴더 아래가 아닌 C:\ 루트 드라이버로 옮겨 놓고 압축을 풀어서 사용하세요)

ESP8266-flasher_AT-mode-Updater.zip
8.56MB

 

 - 압축을 풀면 아래와 같은 내용물(파일)이 보입니다.

 

  - 파일 중에서 esp8266_flasher.exe 파일을 실행시키면 아래와 같은 형태로 실행됩니다.

 

그럼 아래 번호 순서대로 작업 진행을 합니다. 

펌웨어 업뎃이 진행되는 모습

 

 

- 1번 'Bin' 버튼을 클릭해서 업데이트용 펌웨어 파일을 불러 옵니다.

 : 바로 위에서 다운받은 파일 중,  v0.9.2.2 AT Firmware.bin 이라는 파일을 선택해 줍니다. 

(만약,  업데이트 후에, AT통신이 안 된다면, v0.9.2.2 AT Firmware.bin 파일로 업뎃했는지 다시 한 번 확인해주세요.  펌웨어의 esp8266 통신속도는 : 9600bps 입니다.  이 걸로 업뎃하게 되면, 갖고 계신 esp-01모듈의 기본 통신속도가 9600bps로 설정됩니다.)

- 2번 아두이노를 연결하면 연결된 시리얼포트 번호가 몇 번인지? 알아내어 그 포트 번호를 적습니다.

 : 포트 번호를 알아내는 방법은 크게 두 가지인데요? 가장 쉬운것은 아두이노 스케치 IDE에서 번호를 알아내는 방법입니다. (아두이노가 연결되면 추가된 포트 번호 옆에 (Arduino Uno) 표시가 뜹니다. 단, 아두이노 우노의 경우만 영어 이름이 표시되고,  나노 혹은 프로미니의 경우 포트 번호만 표시됨) 

 

 또는 키보드 윈도우키 + 'X' 키를 누르면 나타나는 메뉴중 장치관리자를 열어 '포트' 항목에 보이는 아두이노가 연결된 포트 번호를 확인 할 수 있습니다.

- 3번 Download 버튼을 클릭하고, 펌웨어가 아두이노를 통해 ESP-01모듈로 다운로드(업데이트) 되는 과정을 지켜봅니다. 

 : 다운로드 진행표시는 (99%) 까지 나타나고, Leaving...   이표시까지 뜨면 업데이트 성공(완료) 된 겁니다. 

끝에 표시된 ' Failed to leave Flash mode ' 글자는 펌웨어 업데이트와는 관계없으니 무시하셔도 됩니다.

 

※ 만약, 이 단계에서 진행이 잘 안 된다면...  

- 아두이노에 연결한 USB 커넥터 자체를 뽑아서 전원을 종료한 후 다시 아두이노 보드를 꽂아보세요. 
- esp-01 모듈과 아두이노 및 브레드 보드에 연결된 선의 접촉 불량이 있을 수 있습니다. 꼭꼭 잘 눌러 주거나, 
필요한 경우 선을 바꾸어 보세요. 
- 맨 아래 영상에서 처럼, 특별히 연결을 바꾼 것 없지만, 처음에 펌웨어 진행에 Fail.. 이 뜨다가도 선을 만져주거나, 리셋 버튼을 눌러주거나, 아두이노 USB 단자를 제거 후 다시 연결하고 Download 버튼을 눌렀을 때, 펌웨어 업뎃이 잘 진행 된 것을 볼 수 있습니다.  

- 다시 한 번 정리하자면,  아두이노를 빼고(10여초 기다린 후) 다시 연결해서 다운로드 시도를  몇 번 해보세요.  낮은 확률이지만, 10회 시도중 1~2회 정도 업데이트에 성공 합니다.  혹은 5V전원을 연결하거나 하여 esp-01모듈 손상 등 다른 원인으로 인하여 안 될 수 도 있으니, 연결이나 조건을 한 번더 확인해보시기 바라며,  손상이 아닌데도, 아무리 확인해도 문제 없는 것 같은데 안 될 경우에는 ,  아래에 소개되는 2번 esp-01 전용 어댑터를 이용하거나,   3번 USB to TTL 통신모듈을 이용하는 방법으로 진행해 보시기 바랍니다. 
 2번은 테스트를 못해 봤으나,  1번과 3번 방법중에,  3번 USB to TTL(특히, CP2102 모듈을 이용) 을 이용했을 때,  펌웨어 업뎃 성공률이 거의 90% 이상이었습니다.) 

esp-01을 아두이노에 연결한 모습

 

2.  와이파이 USB to ESP8266 시리얼 전용 어댑터를 사용하는 방법.

.  아래와 같은 전용 어댑터를 이용하면 펌웨어 업데이트가 쉽고 간편할 수 있습니다.  

시판중인 esp-01 전용 wifi 어뎁터 2가지

또한, esp-01 breakout(1500~2000원) 이라는 핀 아웃 커넥터를 이용하면 브레드 보드에 직접 꽂아서 연결할 수 있어서 연결이 깔끔해집니다.

 

3.  USB to UART 통신 모듈을 이용하여 펌웨어를 업데이트 하는 방법.  (CP2102 모듈 추천!!)

 : 개인적으로 성공확률이 높았던 것은,  위에 1번 아두이노 방법과, CP2102 모듈을 이용한 방법이 플래시 업데이트 성공확률이 높았습니다.  연결이 잘못되거나 다른 방법을 사용하여 잘 안 될 경우에는 시간소비와  스트레스가 엄청납니다.  ㅠㅠ

 프로미니 코드 업로드용으로 주로 사용했던, FTDI USB to Serial 모듈은 성공확률이 매우 낮았습니다. (진행되는 도중에 멈춰버리는 현상 자주 나타남) 

하지만 1번 아두이노 경우와 함께,  cp2102의 호환 칩셋을 사용한 USB to TTL(Serial)  모듈로 시도해본 결과 백발 백중 모두 성공하였습니다.  ^^;  하지만, 모듈 구매시,  FTDI USB 모듈의 경우 다음에 다룰 내용에서 펌웨어 업데이트 필요없이(115200으로통신) esp-01과 연결하여 작업하는 경우 3.3V 출력 선택이 가능하기 때문에 FTDI USB 모듈도 같이 구매하는 걸 추천 드립니다

FTDI칩셋의 통신모듈과(좌측)   cp2102호환 칩셋의 통신모듈(우측)

 

cp2102모듈의 경우, 처음 연결할 때 장치관리자에서 ch340 칩셋 드라이버를 업데이트(설치) 해주어야 제대로 사용이 가능합니다. 

 (cp2102 usb to ttl 모듈, 가격 : 2,000원 내외)

 

 

펌웨어 업그레이드 영상 : 
(cp2102 usb to ttl 모듈로 펌웨어 업그레이드 영상은 맨 아래 영상을 참고하세요)

CP2102 (USB to TTL) 모듈을 사용한 펌웨어 업데이트 연결도면

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 통신을 사용하거나 하는 등의 기존 코드가 들어 있을 경우 이런 에러가 나타나기도 한다. 

 

 

▶ 3. 펌웨어 완료 후 AT 통신 모드로 확인 및 셋팅 하기 : 

 

※ 위 이미지 처럼 펌웨어 업로드가 완료되면, 아래에 있는 AT-통신모드용 아두이노 연결을 통해 ,  아두이노의 시리얼 통신창을 통해 AT통신 모드로 진입이 된다.  이때 아래와 같은 AT통신을 위한 아두이노 코드를 아두이노에 새로 업로드 해주어야 한다. 

ESP-8266 AT-통신 모드를 위한 연결도면

- AT통신모드에서는 '하드웨어 시리얼'이 아닌 '소프트웨어 시리얼' 통신을  이용해야 하므로 아두이노의 0번, 1번 핀에 연결된 것을 2번, 3번 등의 다른 디지털핀으로 연결해야 합니다. 

- 펌웨어 업데이트 때 'GPIO 0'번 핀을 GND 단자에 연결 하였는데,  이 단자를 제거 해야 합니다. 

- esp-01모듈은 3.3v로 동작되는 것이 원칙이므로, Rx 수신 단자에 수신되는 신호도 3.3v 레벨로 수신되도록 저항을 이용해 연결해 주어야 하는데,   1 ㏀ 3개를 연결하고 1㏀ 두 개가  연결된 쪽에 Rx 수신단자를 연결하면 :  5v x (2/3) = 3.3333...v  전압 레벨의 신호를 입력해 줄 수 있습니다.  

- 만약 위 회로 연결대로 하였으나, AT통신이 안 될 경우 CH_PD 단자와 +전원(3.3v) 사이에 10㏀ 저항을 넣어서 실행해보기 바랍니다. 

위 회로대로 하여도 안 될 경우 10K의 저항을 추가해본다

 

- 아래와 같은 아두이노 코드를 아두이노에 넣어 줍니다.

아두이노의 2번 단자를 수신단자(Rx)로 지정했으면, 여기에 esp-01 모듈의 Tx 단자가 연결되고, 

아두이노의 3번 단자를 송신단자(Tx)로 지정했으면, 여기에 esp-01 모듈의 Rx 단자로, 교차하도록 연결이 되는 식입니다.  이렇게 해야 서로간 데이터를 주고받을 수 있는 통신이 이루어 집니다.

- 시리얼 모니터 통신속도는 9600으로 하세요. esp8266의 통신속도를 9600으로 했다면, 시리얼 통신 속도도 9600으로 해야, 본 게시글에서 안내드리는 AT명령어 대부분이 적용됩니다.
- 만약 esp8266의 통신속도를 115200으로 했을 때는, 시리얼 모니터 통신속도는 9600이나 115200으로 하여도 별 상관없이 시리얼 모니터창에 잘 입력(응답)됩니다. 
그리고 설정한 대로,  시리얼 모니터 통신창 하단의 속도를 동일하게 맞추어 주세요. 
- 그리고,  esp-01의 통신 속도는 9600에 맞추어 줍니다. (코드에서, ESP-wifi.begin(9600) 부분!)  본 게시글에 링크드린,  펌웨어(

 

- 위 코드를 첨부로 올립니다.(zip 압축)

wifi_test2.zip
0.00MB

- 이제 준비가 완료 되면, 아두이노의 시리얼모니터 창을 열고 명령 라인에 'AT'를 입력해 봅니다.

 - 그리고 아래처럼 'OK'라는 응답이 떨어지면, AT모드 진입과 통신 성공입니다.

단, 이때 시리얼모니터 창에 Both NL & CR 로 하시고,  코드와 동일하게 9600보드레이트 으로 설정 되어 있어야 해요.  

 

만약~!!!
다른 펌웨어로 업뎃할 경우, 통신속도가 9600이 아니라 115200일 수 있습니다.
따라서 아래와 같이 응답신호에 OK가 뜨지 않고, 물음표가 뜨는 경우나 아무 응답이 없을 때는, 아두이노의 esp8266 통신속도를 바꾸어 주어야 AT 통신에 문제가 없습니다.

esp-01 모듈의 통신속도를 115200으로 맞추어 주세요 (ESP_wifi.begin(115200) 으로 코드 수정후 업로드) 하세요.  
그러면, 아래 처럼, 제대로 응답신호 글자가 표시 됩니다. 
 

 위, 코드 (115200) 다운로드 받기

wifi_test2_115200.zip
0.00MB

 

 

【 AT(명령어) 통신 테스트 및 설정 】

 

 1) AT   :  기본적으로 'OK'라는 응답을 통해 통신을 확인하는 명령어 입니다.

 

 2) AT+GMR
           :  esp-01 wifi 모듈의 버전을 확인 하는 명령어 입니다.

 3) AT+CWMODE
           :  WiFi 모드 확인 및 설정 명령

  - AT+CWMODE?    (명령어 입력시 끝에 물음표를 붙여야 한다)

           : 현재의 WiFi 모드 확인

             1번은 (Station Mode, AP(WiFi 공유기)에 접속할 수 있는 기기로 설정)
             2번은 (AP Mode, Access Point(WiFi 공유기) 기능으로 설정)
             3번은 (AP + Station Mode,  접속기기 + AP , 복합 모드 설정)

명령라인에 : ' AT+CWMODE? ' 를 입력 후 엔터

 

아래는 복합모드로 설정한 모습이다.   명령라인에, ' AT+CWMODE=3 ' 을 입력 후 엔터키를 누른다. 

명령라인에 : ' AT+CWMODE=3 ' 을 입력 후 엔터

 

 4) AT+CWLAP        ( 여기는 ?물음표 붙이지 마세요~!)
           :  주변의 AP(WiFi공유기) 리스트를 시리얼 모니터 창에 출력 명령

 5) AT+CWJAP="SSID","비번"
           :  특정 AP에 연결  (주의: 명령어 사이 사이 공백이 없어야 함)

   - 만약, 비번없이 보안이 안 되어 있는 AP에 접속할 경우,

    - AT+CWJAP="SSID",""  으로 입력 하면 됩니다.

 

6) AT+CWSAP="SSID","비번","채널 id","보안방식"
           :  AP모드 사용시, SSID, 비번, 채널, 보안방식을 설정하는 명령어

           보안방식

              0 : OPEN
              2 : WPA_PSK
              3 : WPA2_PSK
              4 : WPA_WPA2_PSK

 

 

7) AT+CWJAP?

           :  연결된 AP 확인

 

8) AT+CWQAP

         : AP 접속 해제 명령

 

 

9) AT+CIFSR

           :  할당 받은 IP 주소 확인

 

10) AT+CIPSTATUS

           :  TCP/IP 연결 상태 확인   (만약, STATUS:2  이면, IP 주소을 획득한 상태)

 

11) AT+CIPSTART=종류,주소,포트

           :  TCP/UDP 연결  

 

12) AT+CIPSEND=크기  ,    > 표시후 '데이터' 입력 후 엔터

           :  특정 바이트 크기의 데이터를 보내기 위한 명령어

 

 

13) AT+CIPCLOSE

           :  TCP/UDP 연결 해제

 

 

14) AT+CIPMUX=모드

           :  다중 접속 설정 (서버코드를 돌리기 위해서는 다중 접속설정이 필요)

              예, esp-01 모듈에 연결된 led를 wifi공유기로 연결된 PC나 핫스팟으로 연결된 스마트폰으로 켜거나 끄려고 할 때, 다중접속모드를 멀티서버('1')로 설정 되어 있어야 함.

           -   AT+CIPMUX=0: Single 클라이언트
           -   AT+CIPMUX=1:Multiple 서버

 

15) AT+CIPSERVER=모드,포트

         :  TCP 서버 모드로 설정  ( AT+CIPMUX=1, '다중접속모드' 인 상태에서 실행)

         : 모드'0'은 서버를 의미하므로, 항상 1로 고정함. HTTP 접속인 경우 80포트 고정,      

 

16) AT+CWLIF

         :  모듈의 SoftAP에 접속된 station 리스트를 보여준다.

17). AT+CWDHCP : DHCP 활성/비활성 설정(AP mode)

18). AT+CIPSTAMAC : Station Mode의 MAC 주소 설정(Station Mode)

19). AT+CIPAPMAC :  AP Mode의 MAC 주소 설정(AP Mode)

20). AT+CIPSTA : Station Mode의 IP 주소를 설정(고정 IP)

21). AT+CIPAP : AP Mode의 IP 주소를 설정

 

22) AT+RST

         :  새로 리스타트(Restart) 시킨다. 

 

이상과 같이 AT 명령어 모드에서 사용가능한 주요 명령어를 정리 하였는데요,

각 AT 명령어 별로 좀더 상세한 설명(영문)을 참조하려면 아래 링크를 살펴보세요.

https://github.com/espressif/ESP8266_AT/wiki/AT

 

espressif/ESP8266_AT

This project is not maintained, please use https://github.com/espressif/esp-at. - espressif/ESP8266_AT

github.com

또한, 정리된 AT명령어 요약집 pdf 파일을 공유합니다.

AT 명령어 요약집.pdf
0.12MB

 

▶ LED등 회로 연결하여 운용을 할 때는 아래와 같은 형태로 연결하면 됩니다.

   ( 기본 AT-mode 연결과 유사하며, Reset 단자를 연결하거나, GPIO 0번, GPIO 1번 핀을 활용 할 수 있습니다,  플래시(업뎃) 모드 일 때 GND에 연결 되었던 GPIO 0번 단자는 반드시 GND에서 오픈 시켜주어야 함)

 - 리셋 단자에는 4.7K의 풀업 저항과 함께 GND로 연결 되는 스위치를 달아 리셋 할 수 있도록 활용하게 됩니다. 

 - 각 GPIO 핀으로 스위치와 같은 형태로 입력을 받거나,  LED와 같은 부품을 달아 출력으로 사용할 수 있습니다.

 

【 본 게시글의 펌웨어 업데이트 모습(에러해결 모습) 및 AT 모드 진입 영상 】

 

 

 

그럼, 시간에는 esp-01 모듈을 활용한 예제를 다루어 보도록 하겠습니다. 

 

 

아래 이어지는 응용 강좌를 클릭해보세요~

【 아두이노모듈#27】 ESP8266 esp-01 활용하기#3 : LED 깜빡이기 

【 아두이노모듈#28】 ESP8266 esp-01 활용하기#4 : 스마트폰으로 LED 컨트롤 하기

반응형
반응형

※ 주의! : 18650과 같은 리튭배터리는 직접적인 합선(쇼트)이나  회로내에서의 합선 등에 의해 불꽃과 소폭발의 가능성이 있는 제품이므로 다루실 때 충분한 주의와 사전지식이 필요하니 주의하시기 바랍니다.

 

배터리 충전】 18650 리튬배터리 + TP4056 충전모듈

 

 아두이노를 가지고 응용회로를 만들거나 프로젝트를 하다보면 전원공급을 어떻게 할 것인가에 직면하게 됩니다.  최종 완성품에 완성도를 높이려면 전원(전력)공급에 문제 없고, 비교적 장시간 사용가능하며, 교환비용이 저렴하거나 재충전이 가능한 방식을 고려하게 됩니다. 

 이런 요구 사항을 대부분 충족해줄 수 있는 것이바로 리튬이온 18650 충전지 입니다.

모양은 AA베터리와 유사한 모양이며, 사이즈는 AA 베터리 보다 조금 크지만, 전압과 전류 용량이 훨씬 큽니다.  (아연 탄소 AA: 1.5V , 400~900mAh)  (18650충전지 : 3.6~3.7V ,  1800mAh~3600mAh)

물론 염화칼륨 소재의 알카리 AA건전지는 1.5V전압에, 용량이 1700~3000mAh까지 나오는 것이 있습니다. 하지만, 가격이 비싸고 1회용으로 사용하고 버려야 하는 비용적인 큰 단점이 있습니다. 

 

 그러므로 아두이노 관련 포터블 응용회로나 RC카 등의 키트를 만들때는 재충전이 가능하면서 전압과 용량이 큰18650을 사용하는 것이 활용성 측면에서 큰 장점이 있습니다. 

그리고 여기에 TP-4056과 같은 충전모듈을 사용하면, 조금 고가(?)의 전용 충전기 비용을 아낄 수 있습니다. 

 

 따라서 오늘은 18650베터리와 충전모듈(TP4056), 그리고 충전보호회로에 대해 설명 드릴까 합니다. 

 

 먼저 한 눈에 비교가 되도록 아래 이미지를 만들었는데요, 

 보이시는 바와 같이 18650이 AA 베터리보다 조금더 크며, 높이는 7Cm가 조금 안 됩니다.

그리고 18650의 종류가 충전보호회로가 없는 것과 내부에 포함 된 것 두 가지로 나오는데요?

 충전보호회로가 없는 모델은 사용하는데는 문제없고, 재충전시, 충전보호회로가 있는 전용 충전기를 이용해야 과충전으로 인한 과열 및 발화로부터 안전합니다.

 반면, 보호회로가 내장된 18650 모델은 가격이 조금더 비싸지만 과충전에 대한 자체 보호가 됩니다. 그리고 사이즈(높이)도 약간 더 깁니다.   따라서 18650용 소켓을 구매하실 때, 구분해서 구매해야 합니다.

만약, '비충전보호회로용 18650' 소켓을 구매 했는데 '충전보호회로가 포함된 18650'을 끼워 보면, 들어가지가 않는 낭패(?)를 경험 하시게 됩니다. 

 보통 소켓은 사이즈 차이 때문에 길이차이가 나는, 1. 충전보호회로비내장18650용 소켓 ,   2. 충전보호회로내장18650용 소켓 ,   3. 둘다 장착가능한 18650용소켓 이렇게 세종류로 나뉩니다.  만약 1번 소켓에 충전보호회로가 내장된 18650을 끼우려 한다면, 너무 빡빡해서 들어가지 않습니다. 

 그리고 둘다 끼울수 있는 3번 소켓은 특수제작된 것은 아니고, 둘 다 사용할 수 있도록 사이즈를 중간 정도로 맞춘 건데요, 따라서 보호회로가 내장된 것을 끼울때는 조금 뻑뻑하고, 내장 안 된 것을 끼울 때는 살짝 헐겁습니다. 

따라서, 상황에 맞추어서 선택하되, 어떤 18650을 사용할지 확실히 정한 후, 거기에 맞추어 딱맞는 소켓을 선택하는 것이 좋습니다.  

 그리고 기본적으로 18650 소켓 종류 는  건전지 1개가 들어가는 1구 소켓,  2개가 들어가는 2구 소켓, 3구소켓, 4구 소켓.  이렇게 판매되고 있습니다.  

 

 2구 이상 소켓 마다 직렬 연결된 소켓과 병렬연결된 소켓  이렇게 두 가지로 구분되어 판매됩니다. 

직렬 병렬의 의미는 이렇습니다.  18650 베터리 각 3.7V를 직렬로 연결하면 : 3.7V + 3.7V = 7.4V로 비교적 5V이상의 전압이 필요한 곳에 사용하기 좋습니다.   반대로, 3.7V//3.7V 두개를 병렬로 연결하면, 전압은 3.7V이지만, 용량이 두 배로 늘어나게 되어 사용시간을 늘릴 수 있습니다.   따라서  상황에 맞게 적절한 소켓을 선택하시면 됩니다.  다만, 대부분의 기기가 특히 아두이노는 5V이상을 요구하기에 직렬소켓은 다양한 곳에서 많은 종류가 판매되지만, 병렬소켓은 판매하는 곳이 적습니다. 

참고하시면 좋을 것 같네요. 

 

 그리고 충전 보호 회로에 대해 설명 드리겠습니다.

18650은 충전이 가능한데, 3.7V보다 조금 더 높은 약 4.2~4.5V 정도의 전압으로 충전 시키게 되는데요, 처음엔 많은 전류를 흘려 충전시키다가 목표 전압에 다다르면 전류량을 서서히 줄여가면서 안정적으로 충전이 되도록 해야 하는데,  이런 역할을 담당해주는 충전모듈이 필요하게 됩니다. 

그 모듈이 바로 아래 TP4056 충전모듈입니다. 

 그리고 완충이 된 후에도 계속 충전을 시키게 되면 과충전이 되고 위험성이 생기게 됩니다. 

그래서 완충 후에는 과충전이 되는 걸 방지하기 위해 과충전보호(방지)회로가 딸려 있는 18650전지를 사용해야 합니다.  위 18650비교 사진에서도 보이듯이 과충전보호회로가 없는 18650보다 보호회로가 들어 있는 18650이 길이가 조금더 길죠.  물론 가격도 조금더 비쌉니다.     

 물론 그러면, 보호회로가 없는 18650은 효용성이 떨어질 수 있으나,  아래와 같은 과충전보호(방지)회로가 내장된 TP4056 모듈을 사용하면 이런 문제는 해결 됩니다. 

 따라서 과충전 보호(방지)회로가 둘 다 없는 18650+TP4056 조합만 아니라면 문제없이 사용하실 수 있습니다. 그리고 18650 하나당 TP-4056 모듈 하나씩 사용하시는게 좋습니다. 

 

 그리고 위 사진처럼 고용량의 배터리팩을 만드는 경우에는 과충전보호회로가 없는 저렴한18650배터리를 여러개 묶고, 과충전 방지회로기능과 여러개의 배터리 셀에 골고루 충전이 이루어 질 수 있도록 충전밸런스 기능이 있는 BMS라는 모듈을 추가해서 만들게 됩니다. 

BMS 모듈은 용량과 구성에 따라 여러가지가 있음

 

 그럼, TP-4056 모듈을 사용법을 아래 이미지와 함께 설명드리겠습니다.

왼쪽이 입력측이며,  보통 MicroUSB로 전압을 입력하게 되며, 5V+, - 단자를 통해서 직접 납땜해서 입력할 수도 있습니다.  입력은 4.5V~8V, 1A까지 가능합니다.    그리고 우측은 출력단으로, B+, B- 단자에 베터리를 물리게 되며(극성주의),  위아래 OUT+, - 단자를 통해 배터리의 출력을 연결하여 사용하게 됩니다. 

즉, 출력 OUT+, - 단자에 배터리 전원을 공급해야 할 곳에 연결해주면 됩니다.  그러면, 충전하지 않을 때는 배터리의 출력을 그대로 사용하게 되고, Micro 5핀 전원을 넣어 충전 할 때는 배터리에 충전도 되고 출력으로도 전원이 나와서 사용할 수 있습니다. 

 

만약, 배터리와 외부기기 사이 전원연결을 끊고 연결 하도록 전원 스위치를 달려면, 

보통 출력단자 + 단자 한 쪽에 연결하게 됩니다.   "전원 스위치 연결은 아래쪽에 있는 이미지를 참고 하세요"

 

그리고 충전중 일때는 붉은색 LED가 켜지며, 완충이 되면, 파란색 LED로 바뀝니다.    

<전원 스위치 연결법 참조 >

전원 스위치 연결법 (점선박스 참조)

 

 여기까지 건전지와 18650의 비교,  그리고 배터리 충전을 위한 TP-4056에 대해 다루었습니다.

감사합니다.

 

반응형
반응형

【 아두이노모듈#23 Adafruit 사의 4채널 아두이노 모터쉴드 - 스텝모터 사용하기! #1  

 Adafruit 사의 모터쉴드는 L293D 모터드라이버를 2개를 H-bridge 구성한 4채널 모터드라이브 쉴드 보드이다. 

여기서 쉴드보드란, 아두이노 우노, 메가, 레오나르도 등에 적층하여 사용할 수 있는 확장형 보드라는 의미이다.  따라서 다른 형태의 모터드라이버 보드와는 달리 거추장스러운 선연결이 많이 줄어 들게 되는 장점이 있다.  또한, 서보모터(2개), DC 모터(4개) 혹은 스텝모터(2개)를 함께 연결하여 동시 구동이 가능한 확장성을 지닌 보드이다.  지난 시간 서보모터 연결에 이어, 이번엔 스텝모터 두 개를 연결해보도록 하자.  우선, 보편적으로 많이 사용하는 28BYJ-48 모터를 사용해볼 것이다.  그리고, 28BYJ-48 모터는 ULN2003 이라는 전용 드라이버가 있어서 이를 이용해서 모터쉴드에 연결해도 되고 사용도 간편하지만, Adafruit모터쉴드 자체가 드라이버 역할을 함으로 ULN2003 드라이버 없이 사용해볼 것이다. 

 Let's get it~!

 

▶ 선수학습 :

    1. [아두이노 기초#35] 스텝모터제어하기(28BYJ-48모터 기초) ☜ (클릭)

    2. [아두이노 모듈#22] Adafruit4채널아두이노 모터쉴드   ☜ (클릭)

 

▶ 아두이노 L293D 모터 드라이버 쉴드 스펙

▶ 스텝모터(2개) 제어하기

 

 (사전준비 )

 아래처럼 라이브러리 관리에서 Adafruit 사의 모터 드라이버를 다운받아 라이브러리에 추가 한다.(구글, 깃허브 등에서 다운로드도 가능)

 라이브러리 직접 다운로드 :

Adafruit-Motor-Shield.zip
0.01MB

 

▶ 회로연결 :

 아래와 같이 스텝모터 두 개를 연결한다.

위 이미지는 하단에 아두이노 보드가 2단으로 결합 된 모습임을 참고하라.

 ※ 주의 사항 :

 1. 모터 쉴드를 사용할 때의 전원 공급 방법은 a. 보드에 직접 전원을 연결 (이때, 쉴드의 'PWRJMP' 점퍼가 연결되어 있어야함).   b.  외부전원으로 공급 (이때, 쉴드의 'PWRJMP' 점퍼가 연결되어 있어야함).   c. 보드 전원과 외부전원 동시 공급 (이때, 쉴드의 'PWRJMP' 점퍼는 제거 해야함).

 2. 보드 전원(USB 케이블전원) 만으로는 위 두개의 스텝모터 구동이 안 되거나 부분적으로 동작이 안 될 수 있다.

 이럴 때는, 외부전원(별도의) 을 입력해주면 동작에 문제가 없으나, 사용하는 스텝모터의 정격용량(현재 5v)을 많이 초과 하는 경우 장시간 사용시 스텝모터가 과열되어 손상이 갈 수 있으니, 테스트를 통해 적정 전원을 공급해주어야 한다.

 3. 케이블 연결 순서에 주의 할 것.( 순서가 잘 못되면, 동작이 안 되거나, 반대방향으로 회전한다)

 

【 28BYJ28 스텝모터 부연 설명 

유니폴라 방식의 모터로서(1,3,4,2번으로 전류가 들어가며 5번(Red) 공통단자로 전류가 흘러나오는 연결 구조이다,  15  , 35, 45, 25  )

 색깔을 주의 깊게 보면서,  A → B → C → D의 순서대로 켜지도록 전류를 흘려주면 CW(시계방향),   

 D → C → B → A의 순서대로 흘려주면 CCW(반시계 방향) 으로 모터가 회전하게 된다. 

 

▶ 코딩 :

/* 스텝모터(28BYJ-48) 2대 구동하기                                   */   
/* 라이브러리 메니저 창에서 Ardafruit 검색후 AFMotor.h 설치 */
#include <AFMotor.h> 
// 1스텝당 회전각 5.625˚ * 64스텝 = 360˚
AF_Stepper motor1(64 , 1);  //1회전당 필요 스텝수(64), 연결 모터채널(모터1) 
AF_Stepper motor2(64 , 2);  //1회전당 필요 스텝수(64), 연결 모터채널(모터2) 

void setup() {
  Serial.begin(9600);           
  Serial.println("Stepper test!");
  motor1.setSpeed(200);  // 200 rpm  : 범위(0~255)
  motor2.setSpeed(200);   
}

void loop() {
  Serial.println("Single coil steps"); //SINGLE : 1개의 코일만 동작
  // ( stepsdirectionstyle)
  motor1.step(2048FORWARDSINGLE); // 2048 : 1회전에 필요한 스텝수
  motor2.step(2048, FORWARD, SINGLE);    
  // motorX.release():회전멈추고 전류를 차단함 
  delay(2000);  
  motor1.step(2048, BACKWARD, SINGLE); 
  motor2.step(2048, BACKWARD, SINGLE); 
  delay(2000);
  Serial.println("Double coil steps");
  motor1.step(2048, FORWARD, DOUBLE);  //DOUBLE : 2개의 코일 동작(토크상승)
  motor2.step(2048, FORWARD, DOUBLE);
  delay(2000);
  Serial.println("Interleave coil steps");
  motor1.step(2048, BACKWARD, INTERLEAVE); // INTERLEAVE: 1,2개 코일 번갈아 동작
  motor2.step(2048, BACKWARD, INTERLEAVE); // 약간의 부드러운 구동과,약간의 속도감소
  delay(2000);
  Serial.println("Micrsostep steps");
  motor1.step(2048, FORWARD, MICROSTEP); //MICROSTEP:부드러운회전(단,토크와 속도감소)
  motor2.step(2048, FORWARD, MICROSTEP); 
}

 

【코드 다운로드】

28BYJ-48_2motor.zip
0.00MB

▶ 동작 영상 :

(유튜브 고화질로 보기-옵션:1080P영상)

 https://youtu.be/93dd7Gjszwo

 

(카카오로 보기)

 

반응형