2019년 3월 25일 월요일

포맥스(Formex)를 이용한 Counter Sink 비트 케이스

1.  Counter Sink Bit?

  목공을 안하는 사람 입장에서는 이 단어는 참 애매하고도, 생소한 단어이다. 글을 적는 나 조차도 수개월 전 처음 알게 되었다.

[ Counter Sink bit - aliexpress 발췌 ] 

 이것은 원뿔 모양으로 보링(가공)하기 위한 비트로, 주로 접시머리(Flat head) 나사의 머리를 끼우기 위한 홈을 파는 용도로 쓰인다. 나사가 박힐 예비 구멍을 뚫은 후에 그 자리에 카운터싱크 비트로 접시머리가 들어갈 공간을 파주면 된다. 카운터싱크 비트를 쓰지 않으면 아래의 왼쪽 그림처럼 나사머리가 툭 튀어나와 걸리적 거리고  다칠수도 있다.



2. From Aliexpress

 Counter Sink의 경우 처음 소개한 이미지의 저렴한 버전도 있지만, 드릴비트와 결합 형태로 사용 가능한 버전도 있다. 어디까지나 초보이며, 연구자의 자세로 가장 저렴한 버전을 구매하였다. 나는 배송료를 포함하여 $2.08에 구매하였다.  아래에 내가 구매한 사이트를 링크를 표시했다.
[ Counter Sink Bit 구매처 ]
 워낙 저렴한 버전이라 특별히 케이스가 없다. 딱 비트날 2개만 배송되어 왔다. 아주 날카롭지는 않지만 이리저리 굴러다니는 것이 맘에 불편해서 케이스를 제작하였다.
[ 오로지 2개의 비트날만 배송됨이 정상 ]

[ 좀더 비싼 모델의 Counter Sink Bit ]


3. 결과물

 역시나 간단한 구조라 제작 과정을 따로 소개하지 않으며, 결과물을 소개한다. 현재 주로 사용하는 Formex를 이용하였다.

[ 12, 16mm의 비트를 담는 상자 ]

[ 왼쪽의 내부 경사는 비트 고정용 ]

[  비트를 끼워 넣으면 딱 맞게 가운데 가이드 설치 ]

[ 가장 긴 변이 6cm 정도 ]

[ 뚜껑은 성냥갑 원리 !! ]

[ 내부 구조체를 밀어서 넣으면 쏙 들어간다 ]




2019년 3월 21일 목요일

NFC를 이용한 선불 교통 카드 잔액 조회기

1. 딸래미(王)의 귀환

 아직 초등학생인 딸래미가 있다. 집에서 먼(대중교통으로 40분) 학원을 다니게 되었는데, 셔틀도 없다. 학원에 갈때는 와이프가 데려다 주지만, 올 때는 내가 퇴근하면서 학원으로 가서 딸래미를 데리고 집으로 온다. 하지만 나도 직딩이라 항상 갈 수는 없는 상황이었다.  딸래미의 귀환이 걱정되기도 하고, 만일의 사태를 위하여 딸래미에게 선불 교통 카드를 사 주었다.

[ 하트빵빵 귀여운 토끼 버전의 교통카드 ]
한두번 사용해보게 했지만, 잔액을 기억 못하는 상황이라, 집에서도 손쉽게 잔액이 확인 가능하도록 리더를 만들어야 했다.

2. 모듈의 귀환

 이번에 제작을 위하여 이전에 사용한 모듈들을 귀환시켰다.  예전의 포스트에 사용한 PN532 모듈을 제일 먼저 귀환 시키고,

[ PN532를 소개한 포스트 바로 가기 ]

[ PN532 ] 

그 다음 OLED 및 ESP8266을 귀환 시켯다.
[ OLED + ESP8266을 이용한 오실로스코프 바로가기 ]


[ OLED ]


3. 제작 결과물 소개

 일단 결과물을 소개하면 아래의 이미지와 같다.
[ 나름 투명 아크릴 상판 ]

[ 측면에서 찰칵. 이번엔 배터리 없이 설계 ]

[ 전원을 연결하면 카드를 태깅하라고 궁시렁 ]

[ 좀더 신선하게 고속버스 안에서 촬영 ]

[ 카드를 가져다 대면 잔액이 표시됨 ]


수준이 좀 낮은 상태로 촬영 되었지만, 동작은 아래의 모습으로 진행된다.




4. 제작 방법 소개

납땜할 포인트가 별로 없다. 기껏해야 20-30 포인트 정도된다.  회로도 까지라고 말할 필요도 없고 아래와 같이 연결하면 된다.
[ 심플한 연결도~ ]

나는 모듈들은 모두 소켓 방식을 사용하기 때문에, ESP8266은 기판의 뒷면에 꼽을수 있는 형태로 제작되었다. NFC 나 OLED 모듈은 기판의 앞면에서 꼽는다.
   
[ 급제작으로 인한 케이블 배선의 엉성함은 참아 주시라~ ]

소스코드는 전체 공개이지만, 라이브러리는 이 포스트에 기록하지 않는다.
먼저 필요한 라이브러리는 2개이다.

PN532관련된 라이브러리는 아래의 링크에서 다운로드 가능하다.
https://github.com/adafruit/Adafruit-PN532


OLED에 한글을 출력하는 과정은 나름 껄끄롭지만, 그 전체 과정 및 라이브러리는 아래의 링크에서 다운로드 가능하다.
http://andy-power.blogspot.com/2018/08/oled.html

대략 이번 선불 교통카드 잔액 조회 기능을 만들기 위해서는 100행 정도를 코딩했으며, 코딩된 전체 내용은 아래와 같다.
/* ------------------------------------------------------
  T-Money Checker
  +-------- GPL License --------------------------------+
  do not remove contact & url
  contact :  terminal0070@gmail.com
  blog :  https://andy-power.blogspot.com/
  -------------------------------------------------------- */
#include <Arduino.h>
#include "Adafruit_PN532.h"
#include "Display_SSD1306.h"
#include "HanDraw.h"
#define OLED_RESET -1 //  S/W 리셋..사용하지 않음

// PN532 V3 SPI모드로 사용하기 위해서는 모듈의 스위치를 변경하고 VCC,GND 포함하여
// 6개의 연결이 필요하다.
// ESP8266 기준으로 정의
#define PN532_SCK  (D5) //
#define PN532_MOSI (D7) //
#define PN532_SS   (D3) //
#define PN532_MISO (D6) //

// I2C 모드를 이용하기 위해서는 아래 2 연결이 필요하다.
#define PN532_IRQ   (2// Not Use
#define PN532_RESET (0// Not connected by default on the NFC Shield

//--------------------------------------------------------------
// Global variables
//--------------------------------------------------------------
Display_SSD1306 Oled(OLED_RESET); // 화면 표시용 객체
Adafruit_PN532 nfc(PN532_SS);     // NFC 객체

//--------------------------------------------------------------
// Setup function
//--------------------------------------------------------------
void setup() {
  Serial.begin(115200);
  delay(50);

  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH); // 내장 LED 끄고
  Serial.println("Start NFC");

  nfc.begin();
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // PN532 못찾은 경우에는 다시 부팅해 버린다.!! (찾을때 까지 리부팅)
  }
  // 제대로 연결되었으면 정보를 출력한다.
  Serial.print("Found chip PN5"); Serial.println((versiondata >> 24) & 0xFF, HEX);
  Serial.print("Firmware ver. "); Serial.print((versiondata >> 16) & 0xFF, DEC);
  Serial.print('.'); Serial.println((versiondata >> 8) & 0xFF, DEC);

  // Oled I2C 방식으로 연결하고, 주소는 0x3c
  Oled.begin(SSD1306_SWITCHCAPVCC, 0x3C, false);

  // Callback 함수를 설정해 주면 필요시 호출 하여 사용함.
  HanDraw.begin(12,  
    [](void) { Oled.clearDisplay(); },// 화면 지우는 콜백함수
    [](int16_t x, int16_t y, uint16_t color) {// 1 픽셀을 그리는 콜백 함수
      Oled.drawPixel(x, y, color);   },
    [](void) { Oled.display(); } //  메모리에서 Display 표시 버퍼까지 보내는 함수
   );

  // configure board to read RFID tags
  nfc.SAMConfig();
  Serial.println("Waiting for an ISO14443A Card ...");
  HanDraw.display(); // 사실상 Oled.display() 동일....
  delay(2000);

  HanDraw.clear();
  HanDraw.setFontSize(16);
  HanDraw.drawString(1, 13, "선불 교통 카드를");
  HanDraw.drawString(1, 33, "태그해 주세요");
  HanDraw.display(); // 사실상 Oled.display() 동일...
}

//--------------------------------------------------------------
// loop function
//--------------------------------------------------------------
void loop() {
  uint8_t success;
  uint8_t responseLength = 64;
  success = nfc.inListPassiveTarget();
  if (success) {
    Serial.println("Found something!");
    // T-money 카드번호, 날짜등을 읽기 위한것
    // OLED에는 표시하지 않음
    uint8_t cardInfo[responseLength];
    uint8_t cardNumSize = 0;
    uint8_t selectApdu[] = { 0x00, 0xA4, 0x00, 0x00, 0x02, 0x42, 0x00 };
    success = nfc.inDataExchange(selectApdu, sizeof(selectApdu), cardInfo, &responseLength);
    if (success) {
      Serial.print("responseLength: "); Serial.println(responseLength);
      nfc.PrintHexChar(cardInfo, responseLength);
      if (responseLength >= 24) {
        Serial.print("card number : "); nfc.PrintHexChar(cardInfo + 8, 8);
        Serial.print("card date : ");   nfc.PrintHexChar(cardInfo + 21, 4);
      }
    }

    // 잔고 조회용
    // 조회가 완료되면 OLED 표시
    uint8_t balance[responseLength];
    uint8_t balanceApdu[] = { 0x90, 0x4C, 0x00, 0x00, 0x04 } ;
    success = nfc.inDataExchange(balanceApdu, sizeof(balanceApdu), balance, &responseLength);
    if (success) {
      Serial.print("responseLength: "); Serial.println(responseLength);
      nfc.PrintHexChar(balance, responseLength);
      if (responseLength >= 4) {
        char fpsbuf[32] = ""; // 숫자를 문자열로 바꾸어 화면에 출력할때 사용됨
        uint32_t money = balance[0] * 256 * 256 * 256 +  balance[1] * 256 * 256 +  balance[2] * 256 + balance[3];
        HanDraw.clear();
        HanDraw.drawString(2, 7, " 교통 카드 잔액 ");
        HanDraw.drawString(2, 25, "------------------");
        dtostrf((float)money, 10, 0,   fpsbuf);
        HanDraw.drawString(2, 43, fpsbuf);
        HanDraw.display();
        delay(2000);
        Serial.print("money : "); Serial.println(money);
      }
    }
  }
  else {
    HanDraw.clear();
    HanDraw.drawString(1, 13, "선불 교통 카드를");
    HanDraw.drawString(1, 33, "태그해 주세요");
    HanDraw.display(); // 사실상 Oled.display() 동일...
  }
  delay(100);
}


-2024-03-11 추가
위의 코드는 일반적인 선불 교통카드에 대한 조회 기능이다. 휴대폰의 NFC 교통카드 번호 확인은 위의 코드로 불가능하다.  nsmaster 님이 알려주신 아래의 APDU로 휴대폰의 교통카드 번호가 확인하다고 댓글을 달아 주셨다. (감사합니다.)
{0x00, 0xA4, 0x04, 0x00, 0x07, 0xD4, 0x10, 0x00, 0x00, 0x03, 0x00, 0x01, 0x00} 
집안에 안드로이드폰이 없어서 아직 확인은 못했다. 

5. 끝으로

 사실 일전에 다 연구한 모듈과 내용을 다시금 정리하고 디스플레이를 추가한 결과물이다. 조회기만을 만드는 것은 당일 저녁 딸래미를 학원에서 집까지 데려오고 나서 시작해서 그날 잠자기 전에 다 만들었다. (수 시간 정도 걸림)  예전에 NFC 모듈 연구 당시 선불교통카드에 APDU 방식으로 커멘드를 보내고 받아야 하는데, 보내야하는 커멘드를 어느 자료에서도 찾을 수가 없어서 정말 고생했다.  이 포스트에서는 관련 커멘드는 1행의 소스코드로 공개되었지만, 이 1행의 코드는 수일간 고생해서 알아낸 코드이다.  연구는 끝이 없고 시간은 적으며, 흰머리는 너무나도 빠르게 늘어간다. ㅠㅠ


3단 6핀 스위치로 DC 모터의 회전 방향을 바꾸어 보자

1. 필요는 연구의 어머니 항상 느끼는 부분이다. 필요하지 않으면 연구하지 않으며, 필요하면 연구한다. DC 모터를 조건에 따라서 정방향 또는 역방향으로 회전시켜야 하는 필요가 생겼다. 처음에는 MCU 및 Relay Switch를 이용하는 방법을 생각...