레이블이 ESP-12E인 게시물을 표시합니다. 모든 게시물 표시
레이블이 ESP-12E인 게시물을 표시합니다. 모든 게시물 표시

2018년 10월 23일 화요일

360도 회전 가능한 로터리 인코더를 사용하자.

1. 세월은 변했지만...


 아날로그 세상에서 디지털 세상으로 세월이 변했지만, 아날로그에 대한 향수는 지울수 없다. 감성과 사용의 편리성을 고려하면 로터리 인코더는 아주 오랜 세월을 나와 함께 할것 같다.
360도 회전 가능한 로터리 인코더

이 모델은 연결핀이 5개 이며, 중심부는 버튼 스위치 기능이 있다.


2. 연결은 해보았지만...

 연결이 어려운 것도 아니고, 저항 두개와 점퍼케이블만 있으면 가능하니, 바로 연결해 보았다.  아래의 그림처럼 연결하고 각 핀의 이름은 인터넷을 뒤적 뒤적하여 매칭했다.


신호를 좀더 제대로 처리하고 싶다면, 아래와 같이 연결하면 될듯 하다.
(난 저항만 쓰고 나머지는  S/W로 해결)



각핀을 Wemos D1 mini에 아래와 같이 연결하였다.
    Wemos             Encoder
    D1 ------------------ CLK
    D2 ------------------ DT
    D3 ------------------ SW
    3.3 ------------------ +
    GND ---------------  GND

허허.. 연결을 하고 코드를 실행하니, 난리도 아니였다.  버튼을 한번 눌렀다가 떼었는데 2번 눌렸다 뗀걸로 신호가 잡히고, 시계 방향으로 돌리고 있는데 반시계 방향 신호가 잡히는 둥 사용하기 껄끄러운 상태였다.


3. S/W 방식으로 보완을...

 아마도 내가 구입한 인코더가 워낙 싼 모델 인듯 하여 소프트웨어 방식으로 보정을 했다. 0.01초 이내에 버튼 신호가 2회 연속 들어오면 뒤의 버튼 신호를 무시하는 방식이다. 회전신호 역시 0.01초 이내의 신호는 무시하는 방식이다.  결론은 아주 성공적이었다. 물론 완벽한 신호를 원한다면, 더 좋은 모듈을 사서 사용하는 것을 권장한다.


4. 사용 방법 및 소스코드는...

 사용 방법은 어려울 것도 없다. 그냥 헤더 파일을 인클루드 하고 신호핀 3개만 잘 정의해 주면 된다. 아래와 같이 사용한다.  ( loop 함수에 feed() 호출 필수)

/*------------------------------------------------------------------
    360도 회전 가능한 로터리 인코더 사용 예제
------------------------------------------------------------------*/
#include "Rotary360Potentiometer.h"

// 신호를 받기 위하여 D1, D2, D3  핀을 사용한다
Rotary360Potentiometer pot(D1, D2, D3);

void setup() {
  Serial.begin (115200);
}

void loop() {
  switch (pot.feed()) {
    case POTNET_NEUTRAL:
      break;
    case POTNET_CW:
      Serial.println("Potentiometer CW");
      break;
    case POTNET_CCW:
      Serial.println("Potentiometer CCW");
      break;
    case POTNET_BTN_DN:
      Serial.println("Potentiometer BTN DN");
      break;
    case POTNET_BTN_UP:
      Serial.println("Potentiometer UP");
      break;
  }
}


Rotary360Potentiometer.h  file

/*------------------------------------------------------------------
   BSD License
   Copyright (c) 2018 terminal0070@gmail.com

  360도 회전 가능한 로터리 포텐셔미터를 위한 클래스
  5개의 핀을 가지는 포텐셔 미터용이다.
  아래의 외형을 가지며, 각핀의 명칭은 아래와 같다.
           +--------------+
 A (CLK) --|              |--   SW
 C (GND) --|     (  )     |
 B   (DT)--|              |--  VCC
           +--------------+           
  ------------------------------------------------------------------*/
#ifndef POTENTIOMETER_360_H
#define POTENTIOMETER_360_H

enum {POTNET_NEUTRAL, POTNET_CW, POTNET_CCW, POTNET_BTN_DN, POTNET_BTN_UP};
class Rotary360Potentiometer
{
public:
    Rotary360Potentiometer(uint8_t clk_pin, uint8_t dt_pin, uint8_t sw_pin = 255);
  uint8_t feed(void);
private:
  uint8_t m_dClkPin, m_dDtPin;   // pin A, B 정의
  uint8_t m_dSwPin = 255;        // 버튼핀을 사용하는 경우와 사용하지 않는 경우가 있음..
  int8_t m_dPrevClkPinVal;       // CLK(A) Pin의 최종 상태
  int8_t m_dPrevBtnStatus;       // 버튼의 최종상태
  // 버튼을 한번 누르지만 연속으로 누르는 것처럼 되는 것을 막기 위해서..
  uint32_t m_dPrevBtnUpTime = 10;
  // 아래 두개 변수는 로터리를 빠르게 돌리면 가끔씩 역방향으로 돌아 갔다고 센싱하길래
  // 소프트웨어 적으로 보정하는데 사용함.
  uint32_t m_dPrevStatusTime = 10; // 마지막으로 회전을 확인한 시간
};

#endif // POTENTIOMETER_360_H 



Rotary360Potentiometer.cpp file
/*------------------------------------------------------------------
   BSD License
   Copyright (c) 2018 terminal0070@gmail.com
------------------------------------------------------------------*/
#include <Arduino.h>
#include "Rotary360Potentiometer.h"

Rotary360Potentiometer::Rotary360Potentiometer(uint8_t clk_pin, uint8_t dt_pin, uint8_t sw_pin) {
  m_dClkPin = clk_pin;
  m_dDtPin = dt_pin;
  m_dSwPin = sw_pin;
  pinMode(m_dClkPin, INPUT);
  pinMode(m_dDtPin, INPUT);
  m_dPrevClkPinVal = digitalRead(m_dClkPin);
  if (m_dSwPin != 255) { // Switch 핀을 사용한다면
    pinMode(m_dSwPin, INPUT);
    m_dPrevBtnStatus = digitalRead(m_dSwPin);
  }
}

uint8_t Rotary360Potentiometer::feed(void) {
  int8_t status = POTNET_NEUTRAL;
  uint32_t now = millis();

  // 로터리 상태 체크
  int nowClkVal = digitalRead(m_dClkPin);
  if (nowClkVal != m_dPrevClkPinVal) { // 돌리고 있는 상황이면
    // CLK(A)핀이 먼저 바뀌엇다. -> 시계 방향으로 회전중
    if (digitalRead(m_dDtPin) != nowClkVal) {
      status = POTNET_CW;
    } else {// DT(B) 핀이 먼저 바뀌었다.. -> 반시계 방향으로 회전중
      status = POTNET_CCW;
    }
    m_dPrevClkPinVal = nowClkVal;
   
    // 로터리 신호를 소프트웨어적으로 보정
    // 0.01초 이내의 회전 신호가 다시 잡히면 무시한다.
    // 빠른시간내에 회전 신호가 들어온다는 것은 대부분
    // 잘못된 신호이다.
    if (now - m_dPrevStatusTime > 10)  {
      m_dPrevStatusTime = now;
    } else {
      status = POTNET_NEUTRAL;
    }
  }

  // 버튼 처리
  // 코드상 나중이지만, 결론은 버튼 상태가 로터리 보다 우선되는 형태이다
  if (m_dSwPin != 255) {
    int nowBtn = digitalRead(m_dSwPin);
    if (m_dPrevBtnStatus != nowBtn) {
      // 역시 0.01초 이내에 버튼 신호가 연속으로 잡히면.. 결론은 무시한다.
      if (now - m_dPrevBtnUpTime > 10) {
        if (nowBtn) {
          status = POTNET_BTN_UP;
        } else {
          status = POTNET_BTN_DN;
        }
        m_dPrevBtnStatus = nowBtn;
        m_dPrevBtnUpTime = now;
      }
    }
  }

  return status;
}



2017년 8월 16일 수요일

ESP8266으로 만드는 이동식 카메라



1.앞서서...

 이것은 IP 카메라를 대체하기 위하여 제작한 것은 아니다. 오히려 IP카메라 완제품을 35달러에 사는 것이 더 경제적일지도 모른다.  이것은  전원선이나 네트워크 선을 연결하지 않고 실외에 설치 가능한 원격 카메라를 제작하기 위해서이다. 굳이 감시용으로 카메라를 설치하여야 하겠다면 그냥 싼  IP 카메라를 추천한다. 더더욱이 이것은 내가 보고 싶을때 사진을 전송하는 것이 아니라 일정 시간마다 서버로 사진을 전행해 주는 장치이다. 식물이나 날씨등 민감하지 않은 상태를 확인하기 위한 장치이다. 연구, 개발, 부품수급, 제작, 테스트 등의 전 과정은 실제로는 수개월에 걸쳐서 이루어졌다. 

2. 대략적 재료 및 가격

  정확한 가격도 사실 계산하기 너무 힘들다.  거의 대부분 중국 알리바바에서 구매하였으며, 한꺼번에 많은 내용을 구매한 터라 정확한 가격을 알지는 못하지만 대략적으로 아래와 같다.
  . OV528 카메라 모듈 : 18000원
  . 18650 배터리 : 4000원
  . Wemos D1 mini 호환 보드 : 3000원
  . 1W 태양광 패널 2개 : 1000원 * 2
  . 락앤락 비스무리 반찬통 : 500원
  . 18650 충전 및 보호 모듈 : 300원
  . 만능보드 : 100원
  . 배터리 홀더 : 200원
  . 저항4개 : 50원 
  . 트랜지스터 3개 : 50원
  . 그외에 글루건, 빈 PET병, 전선약간 및 주변에서 구할 수 있는 것들.

3. 태양광 패널

  사실 이 부분이 가장 오래 테스트 하고 준비한 부분이다. 과연 작은 태양광 패널이 얼마나 전기를 모을수 있을까 하는 것이 걱정되었기 때문이다.  장마철 태양이 적게 비치는 시기에 테스트를 하였고, 다행히도 충분한 전력량을 생산하였다. (내가 구성한 시스템은 1일 약 400mAh 정도를필요로한다.)

일단 실외에 설치할 예정이기 때문에 플라스틱으로 프레임을 구성하였다.

[플라스틱프레임 - 아들 교재 이용]
[반찬통 위에 설치한 모습]

실제로는 2장의 태양광 패널을 붙였다. 
 

4. 납땜

  프로그램 개발은 이미 완료되었고, 회로 설계도 완료된 터라 납땜 작업을 하였다.  납땜은 초등학교 시절 4석 라디오 만들어 본 이후에, 이번 작업이 제일 많이했다. (즉 그만큼 손방인 셈이다.)  
참고로 3개의 트랜지스터는 카메라 모듈에 전원을 공급하는 병렬 스위치이다. 최저전력을 사용하기 위해서 ESP8266을 슬립 모드로 만드는 것 이외에도, 카메라 모듈도 전원을 차단한다.
 
[초기에 설계한 회로도]
 
[기판 전면부]
 
[기판 후면부]
[전면부 소켓에 Wemos D1 mini를 장착한 모습]
 
납땜을 마친 기판은 반찬통 뚜껑에 붙이기로 결정했다. (실외에 설치할 예정이고, 혹시 모를 누수에 의하여 합선되는 것을 방지하기 위하여 높은 위치에 배치하였다.) 글루건으로 약간의 받침대를 뚜껑에 만들고 기판을 피스로 고정하였다.
 
[반찬통 뚜껑에 배치한 모습]
 
 
[측면에서 보면 글루건으로 만든 받침대가 잘 보임]
 
 

5. 배치

  반찬통 바닥에는18650 배터리, 충전보호 모듈, 카메라 모듈을 배치하였다. 또한 반찬통 바닥에는 여러개의 구멍을 뚫어 혹시나 모를 누수에 의한 배수 효과와 내부 과열시 환기가 가능 하도록 하였다.

[위쪽 : 충전모듈, 아래쪽 : 18650 배터리, 오른쪽 : 카메라 모듈]

다만 아무리 투명한 반찬통이라고하여도 카메라를 내부에 넣고 사진을 찍으니, 반찬통이 그다지 투명하지 않다는 것을 알게 되었다.  그래서 반찬통에 구멍을 뚫고 유리 조각을 끼운후 글루건으로 처리하였다.

[사각형 모양의 유리로 일부 대체한 모습]

[전체적으로 조립한 모습]

6. 끝으로...

  다 만든 후에 장마철 기간에 실외에서 테스트 하였다. 성공적으로 동작할 뿐만 아니라, 누수 현상도 크게 걱정할 필요가 없었다. 다만 카메라에 직접적으로 태양이 비추게 되는 경우, 시계가 아주 안좋았다. 그래서 서 카메라를 태양으로 부터 살짝 가려줄 그러한 것을 만들어서 카메라 전면부에 장착하였다.
 적당한 크기의 PET병을 자르고, 유성펜으로 검게 색칠하였다.
 


[나름 그럴듯해 보이는 결과물]


아직 필요한 곳에 설치는 하지 못했지만, 워낙 장소 이동이 수월한 물건이라 이제 가져다 놓기만 하면 될듯하다.

* 이 내용은 처음 작성되어 공개되었고, 내용 보충이 될 수 있습니다.














ESP8266 Digital Input Pin의 불편한 진실

1. 믿었던 놈인데... ESP8266은 2017년도 부터 사용했기 때문에, 7년 정도 사용해 왔었다. 그동안 여러 종류의 내 프로젝트에 사용한 MCU이고, 이에 따라서 신뢰도가 상당히 높았다. 물론 순수한 ESP8266으로 사용하지는 않고 Wemos...