Adafruitで売っているNFCタグの反応距離まとめ

f:id:miso_engine:20180907173921j:plain
RFID / NFC : Adafruit
Adafruit、いくつかNFCタグを売っていて、それぞれのサイズは分かるんだけど反応距離が分からないのでまとめた。リーダーはAdafruitの"PN532 NFC/RFID controller breakout board - v1.6"。USBシリアル変換を刺したらPCからnfcpyで直接扱えます。どうぞご査収ください。
PN532 NFC/RFID controller breakout board / Adafruit

Mac <-> micro:bitをBLEによるUARTで通信する

今回、Macmicro:bit(mbed)のBLEによるUART通信を試みたので、記録に残しとく。Mac側はPython
www.youtube.com

micro:bit

上記公式サイトだとポーリングによる手法しか載っておらず、イベントを利用したコールバックのほうがそれっぽいかなと思って実装してみた。

仕様- 3バイト送られてくる毎にコールバック

  • 送られきたバイト列を文字列としてディスプレイに表示
main.cpp
#include "MicroBit.h"
#include "MicroBitUARTService.h"

MicroBit uBit;
MicroBitUARTService *uart;

void onConnected(MicroBitEvent)
{
    uBit.display.printAsync("C");
    
    uart->eventAfter(3);
}

void onDisconnected(MicroBitEvent)
{
    uBit.display.printAsync("D");
}

void onDataReceived(MicroBitEvent)
{
    uint8_t buf[3];
    uart->read(buf, 3);
    char* cbuf = (char*) buf;
    uBit.display.scrollAsync(ManagedString(cbuf));
    
    uart->eventAfter(3);
}

int main()
{
    uBit.init();
    
    uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_CONNECTED, onConnected);
    uBit.messageBus.listen(MICROBIT_ID_BLE, MICROBIT_BLE_EVT_DISCONNECTED, onDisconnected);
    uBit.messageBus.listen(MICROBIT_ID_BLE_UART, MICROBIT_UART_S_EVT_HEAD_MATCH, onDataReceived);
    
    uart = new MicroBitUARTService(*uBit.ble, 32, 32);
    uBit.display.printAsync("U");
    
    release_fiber();
}
config.json
{
    "microbit-dal": {
        "bluetooth": {
            "enabled": 1,
            "open": 1,
            "whitelist": 0,
            "pairing_mode": 0,
            "advertising_timeout": 0,
            "tx_power": 0,
            "dfu_service": 0,
            "event_service": 0,
            "device_info_service": 1
        },
        "gatt_table_size": "0x600"
    }
}

ハマりどころとしては以下3つ。

  • イベント発火元がMICROBIT_ID_BLE_UART
  • eventAfterは1度呼ばれたら終わりなので毎回メソッド呼び出す必要がある
  • オフラインコンパイル時にconfig.jsonはプロジェクトのルートに置かないと反映されない

Mac

仕様

  • BLEのdevice nameに"micro:bit"が含まれているデバイスに接続
  • 複数台に接続
  • 5秒ごとに3文字のランダムな大文字アルファベットを送信
# coding: utf-8

import atexit
import time
import uuid
import sys
import random

import Adafruit_BluefruitLE
from Adafruit_BluefruitLE.services import UART

# Define service and characteristic UUIDs used by the UART service.
UART_SERVICE_UUID = uuid.UUID('6E400001-B5A3-F393-E0A9-E50E24DCCA9E')
TX_CHAR_UUID      = uuid.UUID('6E400002-B5A3-F393-E0A9-E50E24DCCA9E')
RX_CHAR_UUID      = uuid.UUID('6E400003-B5A3-F393-E0A9-E50E24DCCA9E')

microbits = dict()
known_devices = set()

ble = Adafruit_BluefruitLE.get_provider()
ble.initialize()

def main():
    ble.clear_cached_data()
    ble.list_adapters()
    ble.list_devices()
    
    adapter = ble.get_default_adapter()
    adapter.power_on()
    print('Using adapter: {0}'.format(adapter.name))
    print('Disconnecting any connected UART devices...')
    ble.disconnect_devices([UART_SERVICE_UUID])
    time.sleep(1.0)

    adapter.start_scan()
    atexit.register(adapter.stop_scan)
    print('Searching for UART devices...')
    
    txs = []
    rxs = []
    counter = 0
    
    while True:
        found = set(ble.find_devices())
        new = found - known_devices
        for device in new:
            print('Found devices: {0} [{1}]'.format(device.name, device.id))
            if device.name is not None and "micro:bit" in device.name:
                print('Connect to microbit')
                device.connect()
                device.discover([UART_SERVICE_UUID], [TX_CHAR_UUID, RX_CHAR_UUID])
                uart = device.find_service(UART_SERVICE_UUID)
                txs.append(uart.find_characteristic(RX_CHAR_UUID))
                rxs.append(uart.find_characteristic(TX_CHAR_UUID))
        known_devices.update(new)
        time.sleep(1.0)
        
        if len(txs) > 0:
            counter += 1
            if counter % 5 == 0:
                for tx in txs:
                    value = ""
                    for i in range(3):
                        value += chr(random.randrange(65,90))
                    print(value)
                    tx.write_value(value)

ble.run_mainloop_with(main)

みんなのPython 第4版

みんなのPython 第4版

oscpyの使い方

GitHub - kivy/oscpy: An efficient OSC implementation compatible with python2.7 and 3.5+
Python2.7でもちゃんと使えてまだコードが読めるレベルのOSCライブラリを探したら、記事執筆時点ではoscpyぐらい。ただ、githubのREADMEが間違ってたので、使い方のサンプル載せときます。大変簡単です。*1

from oscpy.server import OSCThreadServer
from oscpy.client import OSCClient

try:
    print('Starting osc server...')
    osc_server = OSCThreadServer()
    osc_client = OSCClient('localhost', 10000)
    sock = osc_server.listen(port=8000, default=True)
    
    @osc_server.address(b'/m')
    def callback(*values):
    	print(values)
    	osc_client.send_message(b'/m', [0, 200, "Hello World"])

    while True:
        pass

finally:
    osc_server.stop(sock)

*1:もったいないので後でプルリク送るかも