はじめに
昨今、日本各地でクマの出没が社会問題となっています。人里離れた山際や農地での早期検知が求められていますが、従来のPIR(赤外線)センサーでは誤検知が多く、また山間部ではWiFiや携帯電話の電波が届かないことも少なくありません。
そこで今回は、「静止していても検知可能」「雨や霧に強い」24GHzミリ波レーダーと、「数kmの通信が可能」なLoRaを、最新のESP32-C6で制御するエッジデバイスのプロトタイプを作成しました。
このシステムの強み
- 高精度検知: 24GHzミリ波レーダー(LD2410C)により、茂みの中のわずかな動きや呼吸も捉えます
- 長距離通信: LoRaモジュールを採用することで、ネット環境のない山林からでも検知信号を飛ばせます
- 低消費電力: ESP32-C6の省電力機能により、バッテリーやソーラーパネルでの長期運用が視野に入ります
ハードウェア構成と配線
ESP32-C6の限られたピンを効率的に使い、3系統のシリアル通信とデジタル入力を両立させています。
| デバイス | ピン (ESP32-C6) | 役割 | 接続詳細 |
|---|---|---|---|
| LoRaモジュール | D5 / D4 | 通信 | SoftwareSerial (RX/TX) |
| LD2410C (レーダー) | D0 / D1 | データ | HardwareSerial1 (RX/TX) |
| LD2410C (OUT) | D2 | 即時検知 | デジタル入力 (HIGH/LOW) |
受信側は、PCとLoRaモジュールをUSBシリアルで接続しています。TeraTermやscreenなどのターミナルでモニターできます。
ソフトウェアのポイント
1. シリアルポートの三重奏
- USB Serial: 現場での設定・デバッグ用 (115200 bps)
- HardwareSerial1: レーダーからの高精度データ受信 (256000 bps)
- SoftwareSerial: LoRa経由の遠隔通報 (9600 bps)
2. LoRa通信の最適化(検知時のみ送信)
クマの検知通知はスピードと確実性が重要です。LoRaの細い帯域を無駄にしないよう、検知時のみ詳細な距離データを付与するロジックを実装しています。
if (radar.presenceDetected()) {
// クマ(対象物)検知時:距離情報を乗せて緊急送信
snprintf(statusBuf, sizeof(statusBuf),
"[ALERT] 接近検知! | OUT: %s | 移動距離: %dcm | 静止距離: %dcm",
digitalRead(PIN_OUT) ? "HIGH" : "LOW",
radar.movingTargetDistance(),
radar.stationaryTargetDistance());
} else {
// 平常時:生存確認(死活監視)用の簡易ステータス
snprintf(statusBuf, sizeof(statusBuf),
"[NORMAL] 異常なし | OUT: %s",
digitalRead(PIN_OUT) ? "HIGH" : "LOW");
}
シリアルモニターでの運用・デバッグ
- 現場確認: 5秒おきのログで、センサーが正しく距離を捉えているか確認できます。
- 設定変更: シリアルモニターからLoRaモジュールへ直接ATコマンド等を送り、通信チャンネルの調整が可能です。
おわりに
このシステムを山際の境界線(バッファゾーン)に設置することで、クマが人里に近づく前に検知し、遠隔地の管理者に通知する仕組みが構築できます。
24GHzレーダーは夜間や悪天候でも性能が落ちないため、野生動物監視において非常に強力な武器になります。
ソースコード
#include <HardwareSerial.h>
#include <SoftwareSerial.h>
#include <ld2410.h>
// --- ピン定義 ---
#define LORA_RX D5
#define LORA_TX D4
#define RADAR_RX D0 // センサーのTXと接続
#define RADAR_TX D1 // センサー의 RXと接続
#define PIN_OUT D2 // デジタル出力(OUT)ピン
// --- インスタンス作成 ---
SoftwareSerial LoRaSerial;
HardwareSerial SerialRadar(1); // LD2410用シリアル(UART1)
ld2410 radar;
void setup() {
// シリアルモニタ初期化
Serial.begin(115200);
while (!Serial) {
delay(10); // シリアルモニタの接続を待機
}
// LoRaモジュールの初期化 (9600bps)
LoRaSerial.begin(9600, SWSERIAL_8N1, LORA_RX, LORA_TX, false);
Serial.println("LoRa 準備完了 (SoftwareSerial)");
// LD2410Cレーダーの初期化 (デフォルト 256000bps)
SerialRadar.begin(256000, SERIAL_8N1, RADAR_RX, RADAR_TX);
pinMode(PIN_OUT, INPUT);
Serial.println("システム起動...");
if (radar.begin(SerialRadar)) {
Serial.println("LD2410C 接続完了");
} else {
Serial.println("LD2410C 接続失敗");
}
}
void loop() {
// PC(USBシリアル) -> LoRa
if (Serial.available()) {
yield();
LoRaSerial.write(Serial.read());
}
// LoRa -> PC(USBシリアル)
if (LoRaSerial.available()) {
Serial.write(LoRaSerial.read());
}
// レーダーデータの読み取り
radar.read();
if (radar.isConnected()) {
static unsigned long lastTime = 0;
// 5秒おきに現在の検知状態と距離を統合して表示・送信
if (millis() - lastTime > 5000) {
lastTime = millis();
char statusBuf[128];
if (radar.presenceDetected()) {
snprintf(statusBuf, sizeof(statusBuf),
"[レーダー] 検知あり | OUT: %s | 移動: %dcm | 静止: %dcm",
digitalRead(PIN_OUT) ? "HIGH" : "LOW",
radar.movingTargetDistance(),
radar.stationaryTargetDistance());
} else {
snprintf(statusBuf, sizeof(statusBuf),
"[レーダー] 検知なし | OUT: %s",
digitalRead(PIN_OUT) ? "HIGH" : "LOW");
}
Serial.println(statusBuf);
// LoRa経由で送信
LoRaSerial.println(statusBuf);
}
}
}
