1. 딸래미(王)의 귀환
아직 초등학생인 딸래미가 있다. 집에서 먼(대중교통으로 40분) 학원을 다니게 되었는데, 셔틀도 없다. 학원에 갈때는 와이프가 데려다 주지만, 올 때는 내가 퇴근하면서 학원으로 가서 딸래미를 데리고 집으로 온다. 하지만 나도 직딩이라 항상 갈 수는 없는 상황이었다. 딸래미의 귀환이 걱정되기도 하고, 만일의 사태를 위하여 딸래미에게 선불 교통 카드를 사 주었다.![]() |
| [ 하트빵빵 귀여운 토끼 버전의 교통카드 ] |
2. 모듈의 귀환
[ 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}
집안에 안드로이드폰이 없어서 아직 확인은 못했다.









