※ 最低限のメモのようなもので、資料としてちゃんと整えておりません。あくまで参考までに。。
✅ UHF を一言でいうと
「遠くまで飛びやすい電波の周波数帯」
Wi-Fi、Bluetooth、携帯電話、UHF帯RFID などがここに含まれる。
📡 電波帯の分類
| 名称 | 周波数帯 | 特徴 |
|---|---|---|
| LF | 低周波(kHz) | 近距離・金属環境に強い |
| HF | 13.56MHz | Suica・MIFARE(RC522)など。近距離。 |
| UHF | 860–960MHz | 数m〜十数m読める RFID。物流で使うやつ。 |
| SHF | 2.4GHz, 5GHz | Wi-Fi、Bluetooth |
🚚 UHF RFID
研究・業界で “UHF” と言うとほぼ UHF帯 RFID のことを指す。
周波数は国ごとに違う:
- 日本:920 MHz帯
- US:915 MHz帯
👉 特徴(HF:13.56MHz とは完全に別物)
- 読み取り距離:数m 〜 20m
- 大量タグの同時読み取りが得意(数百タグ一気に読む)
- アパレル・物流・棚卸しで主流
- 反射・金属で性能が変わる
例:ZARA や UNIQLO の商品タグがこれ。
🆚 HF (13.56MHz, MIFARE, RC522) と UHF の違い
| 項目 | HF (13.56MHz) | UHF RFID (920MHz) |
|---|---|---|
| 距離 | 数cm〜10cm | 数m〜20m |
| 読み取り | 基本1枚ずつ | 大量同時読み取りが得意 |
| 方向性 | 弱い(アンテナ近距離) | 方向性が強い(直線で飛ぶ) |
| 用途 | Suica, 学生証, NFC | 物流、棚卸し、入退室管理、大規模トラッキング |
R200チップのものを使いました
https://ja.aliexpress.com/item/1005005244081462.html?spm=a2g0o.order_list.order_list_main.5.705d585aRGT1hK&gatewayAdapt=glo2jpn
ChatGPTに相談だとダメそうでした。
以下あたりのYouTubeを参考にしました
Download: https://tinyurl.com/r200-sdk-en-7z
上記でダウンロードできたものを使っていじってみました
ざっくり言うと、
- YPD-R200 は UHF RFID(R200)モジュールで、
- UART(シリアル) でしゃべるタイプなので、
- M5StickC Plus2 とは「5V電源 + GND + TX/RX 4本」でつなげばOK、
- プロトコルは R200 系モジュール用の既存コードをほぼ流用できます。GitHub+1
以下、「とりあえずタグIDをシリアルに吐かせる」までの最低限セットを書きます。
1. ハード接続(配線)
1-1. 電源まわり
GitHub の R200 解説によると、この系統のモジュールは
「中身は 3.3V 動作だが、3.3V ピンだけだと電流が足りないことがあるので **VIN は 5V 供給推奨、
UART は 3.3V レベルで接続せよ」GitHub
と書かれています。
なので M5StickC Plus2 とは、だいたい次のように結線するのが無難です:
| YPD-R200 側 | M5StickC Plus2 側 |
|---|---|
| VIN / VCC (5V) | 5V ピン |
| GND | GND |
| TXD | GPIO26 (M5StickC Plus2 の RX2) |
| RXD | GPIO0 (M5StickC Plus2 の TX2) |
- M5StickC/Plus 系では、USB シリアル以外の UART2 が G26(RX2)/G0(TX2) に出ているという情報があります。jhalfmoon.com
- UART レベルはどちらも 3.3V なので、レベル変換は不要(ただし、使っている YPD-R200 ボードが「TTL UART」と明記されていることは一応確認しておいた方が安全)。
もしモジュール側に
- EN / ENable
- BEEP / BUZZER
- WIEGAND など
のピンがあっても、まずは VIN/GND/TX/RX だけつないで動作確認でOKです。
2. 最低限のテストスケッチ(M5StickC Plus2 + YPD-R200)
前提
- Arduino IDE で M5StickC Plus2 ボードが動く状態
- ライブラリ:
M5StickCPlus2(あなたが普段使ってるやつ)を想定
#include <M5StickCPlus2.h>
/*************************************************************
* ベンダ提供 ReadMulti コマンド(複数回読み)をそのまま使用
* 10バイトで構成された「タグを読め」という指令
*************************************************************/
unsigned char ReadMulti[10] = {
0XAA, 0X00, 0X27, 0X00, 0X03,
0X22, 0XFF, 0XFF, 0X4A, 0XDD
};
/*************************************************************
* 状態管理用変数(ベンダコードと同じ)
*************************************************************/
unsigned int timeSec = 0; // 一定時間ごとにコマンド送信するカウンタ
unsigned int timemin = 0; // 秒が溜まったらインクリメントされるカウンタ
unsigned int dataAdd = 0; // 受信データ位置(何バイト目か)
unsigned int incomedate = 0; // 受信した1バイト
unsigned int parState = 0; // パラメータ判定ステート
unsigned int codeState = 0; // コード判定ステート
/*************************************************************
* RFID モジュール用 UART(Serial2)
* 配線:
* YPD-R200 TXD → M5 G26 (RX2)
* YPD-R200 RXD → M5 G0 (TX2)
*************************************************************/
HardwareSerial RfidSerial(2);
/*************************************************************
* 最後に取得した EPC を画面表示するためのバッファ
*************************************************************/
String lastEpc = "";
void setup() {
/***********************************************************
* M5StickC Plus2 初期化
***********************************************************/
auto cfg = M5.config();
M5.begin(cfg);
// 画面設定
M5.Display.setRotation(1); // 横向き
M5.Display.setBrightness(120); // 輝度
M5.Display.fillScreen(BLACK); // 画面クリア
M5.Display.setTextSize(2);
M5.Display.setCursor(0, 0);
M5.Display.println("YPD-R200 TEST");
/***********************************************************
* USB シリアル(PC デバッグ用)
***********************************************************/
Serial.begin(115200);
Serial.println("\nM5StickC Plus2 + YPD-R200");
/***********************************************************
* RFID モジュール用 UART2 初期化
* ※多くの YPD-R200 は 115200bps、違えば 9600 に変更
***********************************************************/
RfidSerial.begin(115200, SERIAL_8N1, 26, 0);
Serial.println("RFID UART2 started");
/***********************************************************
* 起動時に一発だけ読み取りコマンドを送る
***********************************************************/
RfidSerial.write(ReadMulti, 10);
Serial.println("Send first ReadMulti");
}
void loop() {
/***********************************************************
* 一定時間ごとに ReadMulti を送信する(元コード準拠)
* ベンダコードのタイマーロジックを再現している
***********************************************************/
timeSec++;
if (timeSec >= 50000) { // 適当な間隔(50,000ループ後)
timemin++;
timeSec = 0;
if (timemin >= 20) { // さらに20回たまると送信
timemin = 0;
Serial.println("Send ReadMulti");
RfidSerial.write(ReadMulti, 10);
}
}
/***********************************************************
* RFID モジュール 受信処理
* ベンダ提供サンプルロジックに忠実
***********************************************************/
while (RfidSerial.available() > 0) {
// 1バイト受信
incomedate = RfidSerial.read();
/*********************************************************
* フレーム解析(AA 02 22 ... DD)
* 02 → コマンドコード
* 22 → パラメータ
*********************************************************/
// 受信したバイトが 0x02(コマンドコード)で、まだ開始状態でない
if ((incomedate == 0x02) && (parState == 0)) {
parState = 1; // コマンドコードを受信した状態へ
}
// 次に 0x22(コマンドパラメータ)が来たら EPC 解析開始
else if ((parState == 1) && (incomedate == 0x22) && (codeState == 0)) {
codeState = 1;
dataAdd = 3; // 「4バイト目」からデータが始まるため3から開始
}
// EPC データを読み取り中
else if (codeState == 1) {
dataAdd++; // 何バイト目かを追跡
/*******************************************************
* RSSI(信号強度): 6バイト目
*******************************************************/
if (dataAdd == 6) {
Serial.print("RSSI: ");
Serial.println(incomedate, HEX);
}
/*******************************************************
* PC コード(7・8バイト目)
*******************************************************/
else if ((dataAdd == 7) || (dataAdd == 8)) {
if (dataAdd == 7) {
Serial.print("PC: ");
Serial.print(incomedate, HEX);
} else {
Serial.print(" ");
Serial.println(incomedate, HEX);
}
}
/*******************************************************
* EPC 本体(9〜20 バイト目)
*******************************************************/
else if ((dataAdd >= 9) && (dataAdd <= 20)) {
// 始めの一回のみヘッダ表示+EPCバッファ初期化
if (dataAdd == 9) {
Serial.print("EPC: ");
lastEpc = "";
}
// シリアルに 16進で出力
Serial.print(incomedate, HEX);
Serial.print(" ");
// EPC バッファに追加
char buf[4];
snprintf(buf, sizeof(buf), "%02X ", incomedate);
lastEpc += String(buf);
}
/*******************************************************
* EPC の終端付近 → 状態リセット
*******************************************************/
else if (dataAdd >= 21) {
Serial.println(); // 改行
// 状態を初期化(次のフレームに備える)
dataAdd = 0;
parState = 0;
codeState = 0;
// EPC が取得できたときのみ画面表示
if (lastEpc.length() > 0) {
M5.Display.fillRect(0, 30, 240, 100, BLACK);
M5.Display.setCursor(0, 30);
M5.Display.setTextSize(2);
M5.Display.println("EPC:");
M5.Display.setTextSize(1);
M5.Display.setCursor(0, 50);
M5.Display.println(lastEpc);
}
}
}
/*********************************************************
* 想定外のデータが来た場合 → 状態リセット
*********************************************************/
else {
dataAdd = 0;
parState = 0;
codeState = 0;
}
}
/***********************************************************
* ボタンAで画面クリア
***********************************************************/
if (M5.BtnA.wasClicked()) {
M5.Display.fillScreen(BLACK);
M5.Display.setCursor(0, 0);
M5.Display.setTextSize(2);
M5.Display.println("YPD-R200 TEST");
lastEpc = "";
Serial.println("--- display cleared ---");
}
// 負荷軽減
delay(1);
}
動作チェック
あまりちゃんとチェックしていませんが、タグを動かすと反応します。数m離れていても認識してました。