블루투스를 이용해서 쉘에 접근할 수 있는 방법이 있다고 해서 정리해봄.


와이파이를 제대로 사용할 수 없는 등의 환경에 유용할 것 같은데.. 마냥 편하진 않다. 느리기도 하고...


0. bluetoothd 실행 옵션

bluez 5 부터 일부 커맨드라인 툴들이 deprecated 되었다.

hciconfig 는 바로 지원을 하는 것 같은데, SPP 추가를 위한 sdptool 이 작동하지 않음.


sudo vi /lib/systemd/system/bluetooth.service

ExecStart=/usr/lib/bluetooth/bluetoothd -C

데몬파일을 열어서 이렇게 수정해주자.(마지막에 -C 옵션 추가)



sudo systemctl daemon-reload
sudo systemctl restart bluetooth

그 후 블루투스 서비스를 재시작해주면 된다.



1. SP profile 추가

RPi 의 블루투스 프로파일에 SPP, Serial Port Profile 을 추가해야한다.


sudo sdptool add SP

위 명령어로 추가 가능. 재부팅, 서비스를 재시작 등을 하면 없어진다.

이 작업을 자동으로 해주고 싶으면,

블루투스 데몬 파일(/lib/systemd/system/bluetooth.service)에 아래와 같이 추가해줘도 됨.


ExecStartPost=/usr/bin/sdptool add SP

# 데몬 파일을 수정해줬으면 리붓하거나 reload & restart 해주자.
sudo systemctl daemon-reload
sudo systemctl restart bluetooth


추가가 되었는지는 아래와 같이 확인할 수 있다.


sudo sdptool browse local
(...)
Service Name: Serial Port
Service Description: COM Port
Service Provider: BlueZ
Service RecHandle: 0x10005
Service Class ID List:
  "Serial Port" (0x1101)
Protocol Descriptor List:
  "L2CAP" (0x0100)
  "RFCOMM" (0x0003)
    Channel: 1
Language Base Attr List:
  code_ISO639: 0x656e
  encoding:    0x6a
  base_offset: 0x100
Profile Descriptor List:
  "Serial Port" (0x1101)
    Version: 0x0100



2. 다른 장치에서 파이를 검색 가능하게 설정


# Page Scan & Inquiry Scan
sudo hciconfig hci0 piscan 
#OR
sudo btmgmt connectable on
sudo btmgmt discov yes

# Page Scan (기본값)
sudo hciconfig hci0 pscan
#OR
sudo btmgmt connectable on
sudo btmgmt discov no

# Scan 비활성화
sudo hciconfig hci0 noscan 
#OR
sudo btmgmt connectable off
sudo btmgmt discov no

Scan 을 활성화해두면 명령어로 재부팅 전까지 다른 장치의 블루투스 스캔에 응답할 수 있다.


Page Scan(connectable) 은 이미 서로 알고 있는, 즉 페어링된 적이 있는 기기와 연결하는 방식이고

Inquiry Scan(discoverable) 은 서로 모르는 기기가 연결하기 위한 방법이다.

(즉, 처음 연결이 필요할때만 Inquiry Scan 모드를 활성화해주면 된다.)


hciconfig hci0 명령어로 확인해보면 각 PSCAN ISCAN 키워드로 활성화 상태를 알려주고,

btmgmt info 명령어로 확인해본다면 current settings에 discoverable 이 있는지로 Inquiry Scan 활성화 여부를 확인할 수 있다.




3. RFCOMM 실행, 서비스화

RFCOMM 을 통해서 시리얼 연결을 터미널로 연결한다.



#rfcomm watch [dev] [channel] [cmd]
#    watch: listen 과 동일하지만, 자식 프로세스가 종료되거나 클라이언트와 연결이 끊길 경우 다시 listening 시작함.
sudo rfcomm watch hci0 1 getty rfcomm0 115200 vt100

이 명령어를 실행하면 다른 장치에서 블루투스로 파이에 연결했을때 터미널로 연결해준다.

특정 계정 자동 로그인을 해주고 싶다면 마지막에  -a <사용자> 를 추가해주자.

sudo rfcomm watch hci0 1 getty rfcomm0 115200 vt100 -a pi


이 명령어를 매번 실행해줄 수 없으므로, 이것도 데몬화한다.

/etc/systemd/system/rfcomm.service 파일을 아래와 같이 만들어 준다.



[Unit]
Description=RFCOMM service
After=bluetooth.service
Requires=bluetooth.service

[Service]
ExecStart=/usr/bin/rfcomm watch hci0 1 getty rfcomm0 115200 vt100

[Install]
WantedBy=multi-user.target


이후 아래 명령어로 활성화 해주면 끝.



sudo systemctl daemon-reload
sudo systemctl enable rfcomm # 자동실행 활성화
sudo systemctl start rfcomm # 시작



4. Mac 에서 연결

시스템 환경설정 - Bluetooth 에서 검색해서 연결할 수 있다.

일단 연결하면 기기 등록 후 잠깐 연결됨 상태이다가 바로 연결 안 됨 상태로 바뀔텐데 상관없음.



ls /dev/cu.*
(out)/dev/cu.MALS    /dev/cu.SOC    /dev/cu.Bluetooth-Incoming-Port
(out)/dev/cu.[hostname]-SerialPort


이렇게 /dev/cu.[hostname]-SerialPort 장치가 추가되어 있다. 추가가 안되어있다면 SP profile 이 제대로 추가가 안된 상태임.


이 장치를 열면 되는데, screen 으로 열 수 있다.


screen /dev/cu.[hostname]-SerialPort 115200


왜 그런건진 잘 모르겠는데, 이 상태에선 일부 출력(ssh 로그인이라던가..)이 client 의 쉘이 아니라, rfcomm을 실행한 쉘에 출력이 된다.

hyphen 옵션을 주고 다시 로그인해주면 해결됨.

su pi -


윈도우 사이즈도 제대로 반영이 안된다는 것 같은데, 이 경우에는 ssh localhost 로 해결된다고.



5. 다른 장치에서 연결

알아서 블루투스 시리얼 연결을 시도해보자... 일반적으로 많이 하는 SPP 연결방법과 동일해서 레퍼런스가 많을 듯.


윈도우는 모르겠고, 안드로이드에서는 관련 앱이 많을 것이고, iOS 에서는 안되는 것으로 안다.


SPP 말고 다른 프로파일로 어찌 만들어본다면 가능할 것 같긴 한데.. 일단 나는 맥에서만 연결이 되면 되기 때문에 나머진 생략.


참고

https://www.reddit.com/r/raspberry_pi/comments/6nchaj/guide_how_to_establish_bluetooth_serial/

USBISP MK2 http://www.devicemart.co.kr/1077889



AVR 프로그래머를 하나 구매하였는데, 펌웨어와 드라이버가 좀 까다로운 듯...
판매사에서 제공하는 가이드를 보면 사용하는 프로그램의 버전과 호환성이 상당히 까다롭다..


그래도 가이드가 잘 나온 편이니 하라는대로 하면 되겠지만... 나는 맥에서 사용하고 싶었음.

잘 이해가 안가서 해결하는데 상당히 오랜 시간이 걸렸고, 정확한 인과관계가 맞지 않을 수도 있지만,,, 여튼 해결했다.

참고로 내가 구매한건 Olimex 사에서 만든 AVR-ISP-MK2 의 호환 혹은 동일 모델이다.


* 참고로 내가 젤 헤맸던 부분인데, 맥에서 시리얼 포트로 잡히지 않는다! (/dev/cu.usbmodem###, /dev/tty.usbmodem###, /dev/ttyUSB0 등)

이렇게 잡히는 사람도 있는 것 같은데, 나의 경우엔 시리얼 포트가 생성되지 않았지만 사용이 가능했다. (물론 시스템 리포트 등으로 확인시 정상 인식)

아마 mcu에 부트로더 등을 올려야지만 인식이 되는게 아닐까.. 싶다.


1. CrossPack 설치

맥에서 AVR 크로스 컴파일 용으로 CrossPack (https://www.obdev.at/products/crosspack) 이라는 개발킷이 존재한다.
다운받아서 설치해주자.

CrossPack is a development environment for Atmel’s AVR® microcontrollers running on Apple’s Mac OS X, similar to AVR Studio on Windows. It consists of the GNU compiler suite, a C library for the AVR, the AVRDUDE uploader and several other useful tools.


2. AVRDUDE 패치

컴파일된 바이너리를 avr로 업로드할때 사용되는 avrdude...
뭐가 문제인지는 모르겠지만, CrossPack 에서 설치해주는 avrdude 6.0.1 버전은 호환이 되지 않는다.

5 버전을 사용하거나, 6 이상 버전에 패치를 적용해주어야 한다.
작성시점 기준으론 5.11.1 혹은 6.3 버전.

avrdude 의 소스코드는 http://download.savannah.gnu.org/releases/avrdude/ 에서 다운받을 수 있다.


의존성 설치

Homebrew 를 이용해서 의존성을 먼저 설치해주자.
(참고로 homebrew 에서 avrdude 최신버전(6.3)을 제공하지만, 마찬가지로 패치가 필요해서 작동하지 않는다.)

brew install libusb libelf libftdi0 libhid

참고로 위 패키지들을 설치하지 않아도 진행은 가능하나, 컴파일된 바이너리 사용시
avrdude was compiled without usb support. 라고 뜨면서 실질적으로 사용이 불가능하다.


컴파일에 필요한 패키지도 설치하자.
brew install autoconf automake


AVRDUDE 5

위 주소에서 5 버전 소스코드를 다운받고 압축을 해제하자. 나의 경우엔 avrdude-5.11.1.tar.gz

해당 폴더로 이동한 후 다음 명령어들을 차례로 입력해준다.

./bootstrap
./configure
make

이후 make install 을 해주면 /usr/local/bin/avrdude 로 바이너리를 옮겨준다. (다른 것도 몇개 같이 옮김)


AVRDUDE 6

마찬가지로 위 주소에서 6 버전 소스코드를 다운받는다.

폴더로 이동한 후 Olimex 에서 제공하는 패치(https://www.olimex.com/Products/AVR/Programmers/AVR-ISP-MK2/resources/endpointdetect_pass1.patch) 도 다운.

cat endpointdetect_pass1.patch | patch -p0 

위 명령어로 패치를 진행한다. (사실 난 안해봐서 안될 수도.)


이미 패치된 코드도 https://github.com/brettyhale/AVR-OSX-and-Olimex-ISP-MK2 여기서 내려받을 수 있다.


이후 컴파일은 위 AVRDUDE 5 와 같은 순서로 진행하면 됨.


작동 확인

avrdude를 컴파일한 후 해당 디렉토리에서
./avrdude -n -vvv -c avrispmkii -p atmega128 -P usb -C ./avrdude.conf
로 잘 작동하는지 테스트해볼 수 있다.

*MCU 가 atmega128 이 아니면 적당히 수정해주자.


잘 작동한다면 아래 접어둔 것과 같은 로그가 표시된다



3. USBISP MK2 펌웨어 교체

나는 헤매는 과정에서 진행했는데, 만약 판매사가 처음부터 이 펌웨어로 발송을 해준다면 진행할 필요가 없다.

여튼 맥에서 사용하기 위해선 libusb+avrdude용 USBISP 펌웨어로 교체가 필요하다.


펌웨어는 마찬가지로 Olimex 의 홈페이지에서 다운로드 가능.
https://www.olimex.com/Products/AVR/Programmers/AVR-ISP-MK2/open-source-hardware


Software 쪽에 보면 Firmware files and drivers for older AVR/Atmel Studio and/or Arduino/AVRDUDE 항목이 있다.
직링은 여기 - https://www.olimex.com/Products/AVR/Programmers/AVR-ISP-MK2/resources/AVR-ISP-MK2-Firmware-WindowsDrivers.zip


압축을 풀면 Firmware_Drives/FIRMWARE-FOR-AVRDUDE-LIBUSB/libUSB-AVRISP-MKII.hex 파일이 있다.
해당 파일을 USBISP MK2 에 업로드 해주면 된다.


방법은 내가 구매한 제품 기준으로,

1. 플라스틱 케이스를 벗긴다.

2. JP1 의 스위치(?)를 Normal 에서 Up 으로 변경하고 컴퓨터와 연결

3. dfu-programmer 컴파일 및 사용 (http://blog.iolate.kr/257) 게시글을 참고하여 펌웨어 업로드 진행
        나의 경우 기기종류는 AT90USB162

4. JP1 스위치를 다시 원상태로 돌리기

하면 끝.



4. 프로젝트 생성, 컴파일, 업로드

CrossPack 에서 설치된 avr-project 명령어로 프로젝트 템플릿을 생성할 수 있다.
avr-project FirstProject

이러면 아래와 같이 프로젝트를 생성해준다.

FirstProject
├── firmware
│   ├── Makefile
│   └── main.c
└── FirstProject.xcodeproj

xcode 프로젝트로 생성해주는 것 같은데... 난 그냥 커맨드라인에서 계속 작업했음.

firmware/main.c 파일을 작성하면 된다.


컴파일을 하기 전에 Makefile 을 수정...

20, 21번째 라인에서 DEVICE, CLOCK 을 내가 사용하는 mcu 에 맞게 수정해준다.

나는
DEVICE     = atmega128
CLOCK      = 16000000

이렇게 수정했음.

FUSES 도 
FUSES      = -U hfuse:w:0xd9:m -U lfuse:w:0xff:m
로 수정하였는데 퓨즈비트를 자세히 모르니 패스.


Programmer 쪽도 수정을 해줘야하지만, Makefile의 주석이 권장하는 방법대로 하자.

~/.avrduderc 파일을 생성하고

default_programmer = "avrispmkii";
default_serial = "usb";

이렇게 입력해준다.


이후 make 로 컴파일,

혹은 make flash 로 컴파일 및 업로드 할 수 있다.

make fuse 가 퓨즈비트 설정인 것 같지만 난 안써봤음.


잘 작동하면 성공!


Atmel 칩에 펌웨어를 업로드를 할때 사용할 수 있는 dfu-programmer.

윈도우는 Flip 을 사용한다지만, Flip이 맥을 지원하지 않는다.

공식 홈페이지는
https://dfu-programmer.github.io/


brew에 있는 것 같다.

brew install dfu-programmer 로 설치.


소스코드를 다운받아 컴파일/설치하고 싶다면 아래 참고.


펌웨어 업로드는 아래 명령어를 차례로 사용하면 된다.

sudo dfu-programmer 기기종류 erase
sudo dfu-programmer 기기종류 flash 펌웨어파일.hex
sudo dfu-programmer 기기종류 reset

아두이노를 많이 사용하다보니, 아두이노말고 AVR 보드를 구매해서 직접 사용해보고 싶었다.



일단 우노와 동일한 ATMEGA328P-PU 사용해보기로 결정.


원랜 아두이노 회로에 포함되어 있던 캐패시터나 크리스탈 등등이 필요해지는데.. 모르니 열심히 구글링을 해서 찾아보았다.



우선 circuito.io 라는 멋진 사이트를 발견! ATMEGA328P-PU 를 선택하면 위와 같이 회로를 구성해준다.


FTDI나 어댑터 같은건 생략을 하고, 디바이스마트에서 해당 부품을 찾아보았다.


 종류

상세 

 갯수

 개당 가격

 링크 (디바이스마트)

 MCU

 ATMEGA328P-PU

 1

 3,000

 http://www.devicemart.co.kr/1059191

 저항

 10kΩ ±1% 1/4W

 1

 20

 http://www.devicemart.co.kr/2034

 크리스탈

 16MHz 20pF 

 1

 -

 -

 크리스탈 

 16MHz 18pF

 1  http://www.devicemart.co.kr/72
 세라믹 캐패시터

 22pF

 2

 15

 http://www.devicemart.co.kr/1378

 세라믹 캐패시터

 20pF

 2 15 http://www.devicemart.co.kr/1379
 세라믹 캐패시터

 100nF(0.1uF)

 2

 30

 http://www.devicemart.co.kr/1343

 전해 캐패시터

 1uF / 50V

 1

 20

 http://www.devicemart.co.kr/1315

 리니어 레귤레이터

 L7805 LDO 5V 1.5A

 1 - -

 리니어 레귤레이터

 L7805CV

 1 759 http://www.devicemart.co.kr/1026440



동일하거나 최대한 비슷한 것을 골라보았음.

circuito.io 에 나온 부품이 없거나 기타 이유로 대체 선택한 부품은 하늘색으로 칠해두었다.

가격은 구매갯수에 따라 조금 다를 수 있음.

또한 최소 구매 갯수때문에 실질 지출 또한 달라질 수 있고 + 부가세 10% 붙여야함.


크리스탈은 해당 부품이 없어서 대체선택이고, 22pF 캐패시터와 LDO를 왜 저렇게 선택했는지는 아래 내용 참고.



자, 이러면 대충 4,300원이면 제대로 작동하게 하나 만들 수 있다.


그런데 디바이스마트 아두이노 호환보드를 보면 ATMEGA328P 를 사용하는 프로미니나 나노가 3100~4500원에 판매되고 있다....

하... 해보지 말까...



세라믹 캐패시터

크리스탈의 경우 circuito.io 에 나온 크리스탈은 Load Capacitance 가 20pF 인데, 디바이스마트에는 18pF 밖에 없었음.

찾아보니 계산식은 아래와 같았다. 


CL = (Cext * Cext) / (Cext + Cext) + Cint + Cstray

Cext = 2 * (CL - Cint - Cstray)


참고1: http://forum.arduino.cc/index.php?topic=23397.msg176828#msg176828

참고2: http://dokkodai.tistory.com/98


각각이 뭔지 자세한 설명은 나도 모르니 패스하고,(ㅠㅠ)

CL이 20pF 일때 역산을 해보고, 그를 통해 18pF 일때 Cext 를 계산해보면 20pF 가 되는 것 같았다.

별 차이 없어보이지만, 난 뭐가뭔지 잘 모르니까 일단 둘 다 구매했다. 써보면 알겠지...



리니어 레귤레이터

L7805 는 검색해보면 종류가 다양한데..

일단 패키지 종류가 딱 티가 나니 먼저 나눠보도록 하자.


TO-220FP의 FP는 풀팩, 히트싱크가 없고 풀몰딩으로 완전히 절연된 패키지라고 한다.

어떤 장단점이 있는지 잘 모르겠으니 그냥 TO-220 선택.



그러면 디바이스마트에 L7805(CV, ACV, CV-DG, ABV) 4개...의 제품이 나오는데..


L7805 의 개량으로 L7805C, L7805AB/AC 시리즈가 있다. L7805 는 더이상 판매되지 않는 듯?

L7805AB/AC 는 데이터시트 상으로 TJ 값에 따라 나뉘는데.. 테스트 온도 환경이 아닐까 싶고

L7805AB는  -40 ~ 125°C, L7805AC는 0 ~ 150°C 라고... 으..응...

참고로 L7805C 는 -55 ~ 150°C


다른 데이터 항목은 잘 모르겠지만, Output Voltage 의 min/max 범위가 L7805AB/AC 가 L7805C 에 비해 아주 조금 더 좁다.

더 정밀하다는 소리겠지...?


그리고 dimension 에 따른 파트번호가 나뉘면서 V가 끝에 붙는다.(다른 기호면 크기가 조금 다를 수 있음)

L7805C -> L7805CV

L7805AB/AC -> L7805ABV, L7805ACV


이렇게 나뉘니, L7805CV-DG 빼곤 차이점에 대한 궁금증이 해결.

CV-DG 는 귀찮으니 그러려니 하고 패쓰...


결과적으로, 별 차이 없다.

제일 저렴한 L7805CV 를 선택하도록 하자(?)


워낙 잘못된 방법이 소개된 글이 많아 고생을 하여 작성.

Raspberry PI Zero W, Jessie 기준이다.


TX, RX 핀은 구글에 검색하면 이미지가 많이 나오니 핀 배열을 참고하자.


검색을 해보면 텍스트 파일을 수정하거나 데몬을 끄고 켜는 등의 작업이 많은데 다 필요없다.


$ sudo raspi-config


Interfacing Options

-> Serial

-> Would you like a login shell to be accessible over serial? <No>

-> Would you like the serial port hardware to be enabled? <Yes>


이렇게만 해주면 boot 설정 변경 등을 알아서 해주며 재부팅이 필요할 경우 재부팅까지 묻는다.


이 후 /dev/ttyS0 파일스트림을 사용하면 된다. /dev/ttyAMA0 이 아님!


블루투스 데몬이나 시리얼 서비스 등등을 바꿔야한다는 글들이 많지만 다 필요없으니 참고.



Python 에서 시리얼 통신

아래 방법 중 하나로 serial 라이브러리 설치


sudo python -m pip install pyserai
sudo apt install python-serial (Python3 의 경우엔 python3-serial)



import serial
ser = serial.Serial('/dev/ttyS0', 9600, timeout=3)

ser.readline().strip().decode('utf-8')
ser.write(b'TEST\n')
ser.write('TEST\n'.encode('utf-8')


serial 변수 생성 이후 open 하고 싶다면,


ser = serial.Serial(timeout=3)
ser.port = '/dev/ttyS0'
while True:
	try:
		ser.open()
		if ser.is_open: break
		time.sleep(1)
	except: pass



참고

class serial.Serial:
	__init__(port=None, baudrate=9600, bytesize=EIGHTBITS, 
		parity=PARITY_NONE, stopbits=STOPBITS_ONE, timeout=None, 
		xonxoff=False, rtscts=False, write_timeout=None, dsrdtr=False, 
		inter_byte_timeout=None, exclusive=None)


Long Range 의 약자인 LoRa.

저전력 장거리 통신이 가능한 프로토콜로, 국내에선 SK가 LoRaWAN 망을 구축하여 서비스 중이다.


LoRaWAN 은 LoRA PHY, 즉 물리적 통신 프로토콜을 기반으로 암호화, 노드 관리 등을 가능케하는 프로토콜이다.


SK의 LoRaWAN 는 비용도 들고 이래저래 번거로운 점이 많았고, 일단 LoRa 모듈 자체를 사용해보고 싶었다.

(SK LoRa 모듈도 가지고 있기 때문에 언젠가 기회가 있다면 테스트를...)



aliexpress 에서 구매한 sx1276 모듈. 내가 구매한 링크는 여기.

한국에서는 915MHz 를 사용하면 된다.


구매하면 구매자가 친절히 이런저런 데이터시트 등을 메일로 보내주는데.. 딱히 필요없었다.

내가 구매한 17년도 12월엔 $16.48/2개 였는데, 글 작성 시점에는 $13.11/2개 정도.


송수신이 가능하므로 2개 이상이 있으면 된다.


LG01-S 등 LoRa Gateway 같은 것도 판매는 하는데, 얘들은 그냥 LoRa 모듈과 인터넷 연결을 편하게 해뒀을 뿐 꼭 필요한건 아니니 당장은 필요없음.




핀간격이 빵판용이 아니라 납땜이 좀 많이 귀찮다.

SPI 통신을 사용하며, 전원과 수신용 인터럽트 핀(DIO0)까지 총 8개가 필요하다.

인터럽트 핀을 생략한다면 7개 핀으로 가능.


동봉된 안테나까지 납땜을 하면 완성!



나는 두개의 아두이노 UNO 와 연결을 하였고,

LoRa 모듈의 작동 전압은 3.3v 이지만, 그동안 경험상 전원만 3.3v 에 물려주면 별 문제가 없었으니 그냥 진행했다.


Arduino Uno 

 LoRa sx1276

GND

GND 

 13

SCK

 12

MISO 

 11

MOSI 

 10

NSS 

 2

DIO0 

 3.3V

VCC 

 8

NRESET 


검색해보니 5v circuit 출력 3.3v circuit 입력의 경우에만 전압 조정을 해주면 된다고 하던데 난 저항 등을 달았을 경우 오히려 작동이 안되어서 전부 바로 연결하였음.


아두이노 라이브러리는 Sandeep Mistry의 LoRa 를 사용하였다. Arduino 라이브러리 매니저에 있지만,

링크는 https://github.com/sandeepmistry/arduino-LoRa


코드야 예제코드가 잘 만들어져이으니 참고하면 됨.


나의 경우 송신/수신 나눠서 테스트를 하였고, 송신부가 두번째 LoRa.endPacket() 이 무한 blocking 되는 문제가 있었다.

그냥 모듈 두개를 서로 바꿔주니 해결이 되었음.. 아마 납땜과정에서 모듈 하나가 송신이 안되는 불구가 된 듯하다ㅠㅠㅠ




거리 테스트..

송신기를 건물 안에 두니 밖으로 나가면 바로 안되어서, 야외에 두고(71m 거리 태그가 있는 곳) 움직여보았다.


안테나가 별로인건지, 내가 잘못 납땜한건지 여튼 저 정도 거리까지만 수신이 되었음...ㅠ

송신기를 좀 높은 곳에 두고 안테나를 잘 세팅한다면.... 더 잘되지 않을까 기대를 해본다.


일단 통신이 되긴 했으니 만족!

자판기를 만들고 싶어서, 일단 지폐인식기를 구해보았다.


일반적으로 아두이노 관련 제품을 파는 쇼핑몰에서는 구할 수 없고, 오락기나 자판기 부품을 판매하는 업체 등에서 구할 수 있는데

중고나라에 자주 올라오니 중고나라에서 구매하는 것도 좋은 방법.


나는 마침 중고나라에 올라온 GBK-PS500 이라는 제품을 구매하였는데, 기억은 안나지만 개당 2만원 정도에 구매했던 것 같다.



이렇게 생긴 친구이며, 좌측에 MOLEX 53015 10P 커넥터가 달려있고, 우측에 있는 DIP 스위치로 신호 출력방식, 지폐 권종 등을 조절할 수 있다.


문제는 중고로 샀더니 정말 제품만 덜렁왔고... 커넥터에 맞는 케이블을 구하기가 어려웠다.

그러다 모 쇼핑몰에서 동일 제품을 판매하는걸 발견했고, 옵션 상품에 케이블을 판매하길래 전화로 별도 구매 성공!

링크는 여기 http://smartpon4989.com/item.php?ct_id=18&id=F154916030


다만 전원과 VEND1 출력만 연결된 3선 케이블이라고 한다.

3개만으로도 작동을 하니까 파는거겠지.. 하면서 일단 받았다.


전원 연결을 하면 지폐인식이 매우 잘 되는건 확인.

이제 신호를 받아야하니 이전에 사뒀던 DSO138 에 물려서 확인해보았다.




(내가 쓸줄 몰라서 그러는건지.. 뭔가 이쁘게 딱 보이진 않았지만...)

사진에 보이다시피 펄스가 주기적으로 계속 나오다가, 지폐가 입력되면 100 ms 동안 LOW 신호가 1000원 단위로 출력되는 구조였다.

앞에서 얘기했듯이 DIP 스위치로 1000원 당 펄스 횟수(1~10,11,12,15,20)를 조절할 수 있고, 펄스길이(100ms / 50ms)도 조정가능함.

지폐가 인식이 안되어서 반환이 되었는지, 현재 지폐 인식 중인지 등의 정보도 받을 수 있는 것 같지만 선이 연결 안되어있으니 일단 패쓰.

아날로그 신호다 보니 노이즈가 들어오면 돈이 잘못 인식될 수도 있을.. 것 같지만 3선밖에 없어서 검증루틴 같은걸 추가하기도 곤란하다. 그냥 배선을 잘 해두는 수밖에.


여튼 아두이노 코드로는 간략히 아래와 같이 작성하였다.

(이제보니 purseIn 이라는 내장 함수가 있네... 다음에 깔끔하게 고쳐보는걸루...)



100ms 의 경우 만원권 등을 넣었을때 그만큼 인식에 시간이 걸리기 때문에, 50ms 로 줄여도 된다. 그 경우엔 조건문을 조금 수정해야할 듯.


여튼 일단 잘 됨!


추가로, LCD 같은 부품을 사용해서 아두이노가 loop 한번 돌때 걸리는 시간이 길어진다면, 펄스 신호를 제대로 체크할 수 없기 때문에 제대로 작동하지 않을 수도 있다. 알..아서 잘 해결해보자ㅎㅎ



+ INHIBIT 포트를 LOW 로 주면 지폐를 받지 않는다.

ESCROW 는 모르겠음

예전에 학교 학생회관에 DID(디지털 정보 디스플레이, Digital Information Display) 느낌으로 라즈베리파이와 모니터로 만들어서 설치한 적이 있었는데,

그 당시엔 pygame 으로 이미지를 순차 디스플레이 하는 방법을 사용했었지만 좀 구린 점이 있었고...

다른 쓸만한 방법을 발견해서 업데이트.


우선 목적은 정해진 이미지들을 순차적으로 전체화면으로 보여주고, 전원이 켜지자마자 바로 이미지를 보여주는 모드로 들어가야함. 그냥 디지털 액자 생각해도 된다.


Raspberry Digital Signage 이라는 커스텀 OS 가 있길래, 이걸 사용하려 했는데 유료 플랜이 아니면 실사용이 어려울 정도로 기능 제약이 있음. chromium 을 사용해서 만들었다는 점에 아이디어를 얻어서 좀더 찾아봤다.


직접 chromium-browser 를 실행하는 방법도 있었지만,, 이래저래 귀찮은 와중에 딱 이런 목적으로 만들어진

FullPageOS (github) 를 발견.


추가적인 나의 상황은, 네트워크가 불안정한 환경. 즉 이미지 수정을 오프라인으로 해줘야한다.

여러가지 방법이 있겠지만, boot 파티션에 남는 약 20MB 정도의 용량을 활용하기로 결정.

boot 파티션을 웹 루트 하위에 심볼릭 링크를 건 다음, php 스크립트로 이미지 목록을 가져와서 뿌려지는 방식을 사용하였다.


1. FullPageOS 설치

당연히 젤 처음해야할 작업.

직접 컴파일할 필요는 없으니 이미지는 http://unofficialpi.org/Distros/FullPageOS/ 여기서 다운.


메모리카드에 만드는 방법은 여러가지 방법이 있으니 알아서 해주자.

Mac 에서 설치디스크 만들기 (Flashing Image)


2. 일단 네트워크가 되는 환경에서 작업!

만든 php 스크립트를 업로드 해야하니... 다른 방법도 있겠지만 그냥 파이를 부팅한 다음에 네트워크에 물리는 방법이 편하다.

ssh 는 기본적으로 활성화이니 무선 네트워크 설정 혹은 유선랜을 물리자. 기본 호스트네임은 fullpageos.local


와이파이 설정은 라즈비언과 조금 다르게 부트파티션에 fullpageos-wpa-supplicant.txt 파일이 있다. 수정해주자.


3. php 스크립트 집어넣고 심볼릭 링크.

fullpageos 에 기본적으로 lighttpd 와 php 등이 설치되어 있다.

/var/www/html 이 기본 루트. 다른거를 굳이 지워줄 필요는 없으니 did 폴더 정도 만들어주자.

그리고 boot 파티션에 images 폴더를 만들고, 이것도 심볼릭 링크 생성.


$ sudo mkdir /var/www/html/did

$ sudo mkdir /boot/images

$ sudo ln -s /boot/images /var/www/html/did/images


(만든 스크립트는 나중에 수정으로 업로드 예정)


4. 실행될 웹주소 수정

/boot/fullpageos.txt 파일을 수정하면 된다. boot 파티션에 있기 때문에 컴퓨터에서 바로 수정도 가능


$ sudo bash -c 'echo "http://localhost/did/" > /boot/fullpageos.txt'


5. 이미지 파일 넣기

컴퓨터에 연결해서 파일을 넣거나, 지금은 네트워크가 연결된 상황이니 /boot/images 에 이미지를 넣어주자.


6. 재부팅

왠지 서비스를 재시작하는 방법이 있을 것 같지만, 잘 모르겠으니 그냥 재부팅.

한 15초 정도 부팅이 지나면 바로 이미지들이 재생되기 시작한다.


대충 jquery 로 짜면서 fade out 효과를 줬는데.. 조금 버벅인다ㅠ

인터넷 연결이 상시되는 환경이면 애초에 온라인 상의 웹에 바로 물리고 주기적으로 새로고침되게 짜는 것도 좋다.

----------------------------------------------------------------------------

[목차]

1. IoT 사물 / 인증서 / 정책 생성

2. Python + paho-mqtt 를 사용하여 주제 구독, 게시 및 테스트

3. AWS Lambda에 연결하고 텔레그램 봇 메시지 보내기

----------------------------------------------------------------------------


2. Python + paho-mqtt 를 사용하여 주제 구독, 게시 및 테스트


AWS IoT 용 파이썬 패키지도 있는 것 같았지만, 메서드명도 괴랄하고 어떻게 쓰는지 한눈에 안보여서 사용하지 않았다.

Prepare your Raspberry Pi to work with AWS IoT (Getting started with IoT #2)

글을 참고하여, 작성해보았는데, 잘되어서 걍 이거 쓸 듯.


테스트용 AWS MQTT 클라이언트 사용

우선 AWS 에서 MQTT 테스트용 클라이언트를 제공한다.

일단 임의로 test/1 토픽을 구독해본다



구독할 토픽 이름을 임의로 설정하고, 주제 구독을 누른다. 와일드카드(+) 도 사용가능하다.




그럼 이런 화면이 나오는데, 좌측에 구독 중인 주제들이 보이고, 구독한 주제에 대해 메시지가 있으면 하단에 표시된다.




구독하고 있는 주제로 바로 게시도 가능하니, 해볼 경우 이렇게 나온다.



라즈베리파이 + Python

(사실 꼭 라즈베리일 필요는 없다. 나도 처음 해볼 땐 파이에서 했지만, 지금은 맥에서 그냥 진행.)


특정 버전 이상의 ssl 이 필요하지만, 내 기억에 파이에 기본으로 설치되어 있었던 것으로 기억한다.

파이썬3 기준으로 할거니 2로 쓰고 싶으신 분은 알아서 필요한 부분을 수정.


pip 이 없다면 이것부터 설치

$ curl https://bootstrap.pypa.io/get-pip.py | sudo python3


paho-mqtt 설치

$ sudo python3 -m pip install paho-mqtt


Python 코드는 아래처럼 작성하면 된다. 적당히 mqtt.py 정도로 만들자.

대충 mqtt 연결을 수립하고, 연결되면 test/2 주제를 구독하기 시작하며,

test/2 주제로 메시지가 게시되면 json 으로 load 해서 message 키의 값을 출력하는 코드이다.




--------------------------------------------------

[유의사항]

1.  클라이언트 생성자에 clean_session 인자가 있는데, True(기본값)로 해야한다. False 로 할시 AWS 에서 연결을 끊어버린다.

2. publish 할때 retain 인자는 False(기본값)로 해야한다. True 로 보내면 마찬가지로 AWS 에서 연결을 끊어버린다.

3. 같은 아이디로 두개 이상이 연결되면 둘 다 연결이 종료된다.

4. AWS IoT 에서 qos 0 은 "0번 이상 전달"을 의미한다. qos 2 는 지원되지 않는다.


* 자세한건 AWS IoT 메시지 브로커 - 프로토콜 문서 참고.

--------------------------------------------------



publish 도 테스트해보려고 메인 루프는 주석처리 해뒀으니, 인터프리터 모드로 실행

$ python3 -i mqtt.py



정상적으로 연결되었을 경우 connected 로그가 뜬다.


혹시 ssl.SSLError: [SSL: SSLV3_ALERT_CERTIFICATE_UNKNOWN] sslv3 alert certificate unknown

같은 에러가 뜬다면, AWS 에서 인증서를 활성화하지 않은 경우니 활성화해주고 다시 시도해보자.


이후 아래쪽에 주석 처리 해둔대로 publish 를 시도해보면


>>> payload = json.dumps({'action': 'test'})

>>> mqtt_client.publish('test/1', payload, qos=1)



이렇게 아까 열어둔 mqtt 테스트 클라이언트에서 정상적으로 publish 된 것을 확인할 수 있다.


마찬가지로 파이에서 구독하고 있는 test/2 주제로 게시하면, 파이에서 on_message 함수가 실행되어 로그가 찍히는걸 확인할 수 있다.


메시지는 꼭 json 일 필요는 없다. 코드를 보면 알겠지만, 보낼땐 dump 하고 받을땐 load 한다. 다만 걍 json 을 쓰자..ㅋㅋ

그냥 나보고 만들어라고 하면 http 리퀘스트 만으로 어떻게 퉁쳤겠지만... 다른 사람의 서비스 제작을 도와줄 필요가 있었다.

최대한 AWS 의 솔루션을 사용하는게 향후 유지관리에도 좋을 것이고, AWS IoT 를 써보고도 싶었고, 서버->디바이스 요청도 쉽게 보낼 수 있게 되니, 한번 써보고 정리하는 글. 사실 친구놈 보라고 쓰는거다 휘수야 보고 있니


우선 AWS IoT 에 대한 특징 같은건 다른 글에 많으니 다 생략하고 내가 찾는데 시간이 걸렸거나, 관심이 있는 부분만 기술한다.

즉 mqtt 가 뭔지, 주제 구독이 뭔지 이런건 생략.


이번 글의 목표는, 라즈베리파이에서 mqtt 주제를 publish, subscribe 해보고 라즈베리파이에서 publish 된 주제를 통해 aws lambda 함수를 실행시켜서 텔레그램 알림을 받는 것 까지.


----------------------------------------------------------------------------

[목차]

1. IoT 사물 / 인증서 / 정책 생성

2. Python + paho-mqtt 를 사용하여 주제 구독, 게시 및 테스트

3. AWS Lambda에 연결하고 텔레그램 봇 메시지 보내기

----------------------------------------------------------------------------


1. [AWS 콘솔] IoT 사물 / 인증서 / 정책 생성



AWS 에서 IoT 대시보드로 이동한 후 좌측 관리 - 사물 - 사물 등록



지금은 한개만 등록할거니 단일 사물 생성.




관리의 편의성을 위해 유형이나 그룹 등등을 설정할 수 있지만, 지금은 필요없다. 이름만 적당히 생성하고 다음으로 넘어가자.

이 이름은 thing name 이자 client id 로 사용된다.




ioT 디바이스를 인증하고 암호화 통신을 위해 사용하는 인증서를 선택해야한다.

이미 만든 인증서가 있다면 그걸 사용해도 되지만 없을테니 이 창이 뜰텐데, 권장하는 방법을 쓰자! ㅋㅋㅋ




적혀있듯이 퍼블릭 키와 프라이빗 키는 이 창이 지나가면 다시는 받을 수 없다.

혹시나 못 받았다면 인증서를 새로 만들면 되니 부담은 안가져도 되지만, 잘 가지고 있도록 하자.


활성화는 말 그대로 이 인증서를 사용가능하게 할건지 설정하는건데, 조금 있다가 해도 된다.


정책은 아마 만들어진 정책이 없을테니, 0개 선택으로 두고 일단 넘어가면 된다.




IoT 디바이스가 어떠한 작업을 할 수 있는지 그 권한을 설정하는 정책(Policy)를 만들어야 한다.

참고로 이 정책은 개별 디바이스가 아니라 인증서에 연결된다.


즉, 같은 디바이스라도 사용하는 인증서에 따라 정책이 달라진다.

물론 인증서와 디바이스도 AWS 콘솔에서 연결 작업은 해줘야하지만.


IoT 대시보드 좌측 메뉴에서 보안 - 정책을 찾아가자.



이름을 적당히 설정해주고, 권한을 넣어주자.


작업 항목에는 

iot:Publish / Subscribe / Connect / Receive / UpdateThingShadow / GetThingShadow / DeleteThingShadow

7개 항목이 있지만 지금은 귀찮으니 와일드카드 * 로 사용.

다른건 이름만 봐도 알겠는데 Connect와 Receive 는 왜 있는지 모르겠다.. 나중에 찾아봐야지


리소스 ARN 은 토픽이나 shadow의 리소스 arn 을 넣으면 된다.

arn:aws:iot:<REGION>:<USER ID>:topic/<TOPIC NAME>

의 형태. 참고로 "토픽 이름"에서 와일드카드는 * 이 아니라 + 다.


일단은 테스트 목적이니 이것도 대충 와일드카드로 만들자




그 다음, 정책을 인증서에 연결해줘야 한다.

디바이스에 정책을 연결하는게 아님을 주의.


인증서 메뉴에서 아까 만든 인증서에 방금 만든 정책을 연결해주자.


아까 생성할때 활성화를 안했다면 여기서 활성화를 해줄 수 있다. 나중되면 까먹을테니 지금 활성화 ㄱㄱ





마지막으로 좌측 하단 설정에 들어가서 엔드포인트 URL 을 확인한다.


+ Recent posts