LoRa Arduinoガイド:SX1278 Ra-02とESP32で長距離無線通信
LoRaをArduinoで使うためのガイドです。SX1278 Ra-02の配線、SFと帯域幅の設定、送受信コード、ESP32とPicoでの使い方、3.3 Vの注意点、通信距離テスト、LoRaとLoRaWANの違いを解説します。
LoRa Arduinoのプロジェクトは、インターネットやSIMカードを使わず、わずかな電力で2枚のボード間の数kmにわたってデータを送る最も実用的な方法です。LoRa(Long Range)はSemtechが開発した無線変調方式です。SX1278を搭載した433 MHzのRa-02などの安価なモジュールで、市街地では1〜3 km、開けた場所では最大10 kmまで届きます。その代わり、速度は毎秒数百バイトから数キロビット程度です。そのため音声や動画には向きませんが、温度、湿度、水位、ドアの状態、GPS位置などの小さな測定データを遠くへ送るのに最適です。
このガイドでは、LoRaが遠くまで届く仕組み、通信距離を決めるSF・BW・CRの設定、地域に適した周波数、Ra-02とArduino Uno・ESP32・Raspberry Pi Picoの配線、LoRaライブラリを使った送受信コード、RSSIとSNRの読み取り、実際の通信距離テストを順に解説します。最後に、LoRaとLoRaWANの違い、The Things Network(TTN)、電池で数か月動く畑のセンサープロジェクトを紹介します。
LoRaとは?遠くまで届く仕組み
LoRaはチャープスペクトラム拡散(CSS)という技術を使います。各シンボルは、帯域内を周波数が一定のペースで上昇する「チャープ」として送信されます。情報はチャープが始まる周波数に埋め込まれています。受信機が入力信号に既知のチャープ波形を掛けて足し合わせると、ノイズは打ち消され、信号は蓄積されます。これにより、LoRaはノイズフロアより20 dB低い信号まで復号できます。一般的な433 MHz ASKモジュールでは信号がノイズより明らかに強い必要がありますが、LoRaはかすかな信号も読み取れます。これが、同じ出力でより遠くまで届く秘密です。
代償は時間です。チャープが長いほど受信機が集めるエネルギーが増えて通信距離は伸びますが、同じデータを送る速度は低下します。LoRaでは通信距離、速度、電池寿命が常に結び付いています。20バイトの測定データの送信には、最速の設定で約57ミリ秒、最も遠くまで届く設定で1.3秒かかります。以下の表で、LoRaとArduinoで使われるほかの無線方式を比較します。
| 項目 | LoRa(SX1278) | nRF24L01 | 433 MHz ASK | Wi-Fi(ESP32) |
|---|---|---|---|---|
| 一般的な通信距離 | 市街地で1〜3 km、開けた場所で最大10 km | 50〜100 m(PA+LNA付きで約1 km) | 20〜100 m | 50〜100 m(ルーターまで) |
| データ速度 | 0.3〜5.5 kbit/s(125 kHz) | 250 kbit/s〜2 Mbit/s | 1〜10 kbit/s | Mbit/s程度 |
| 送信時の電流 | 40〜120 mA(出力による) | 11〜12 mA | 10〜40 mA | 120〜240 mA |
| スリープ時の電流 | 1 µA未満 | 約1 µA | なし(電源オフ) | 10 µA(ディープスリープ) |
| 双方向通信 | 可能 | 可能 | 不可(送信機と受信機が別) | 可能 |
| インフラ | 不要 | 不要 | 不要 | ルーターとインターネット |
LoRaモジュール:Ra-02、RFM95、E32と一体型ボード
市販のLoRaモジュールの多くは、SemtechのSX127xシリーズのチップを使っています。SX1276の対応範囲は137〜1020 MHz、SX1278は137〜525 MHzです。そのため、433 MHzモジュールにはSX1278、868/915 MHzモジュールにはSX1276が使われています。モジュールには、SPIで通信する無線回路のみのものと、独自のプロセッサを搭載し、UART経由でシリアルポートのように使えるものの2種類があります。
| モジュール | チップ | 周波数 | インターフェース | 補足 |
|---|---|---|---|---|
| Ai-Thinker Ra-02 | SX1278 | 433 MHz | SPI | 最も安価で広く使われるタイプ。IPEXアンテナコネクター |
| Ai-Thinker Ra-01 | SX1278 | 433 MHz | SPI | スプリングアンテナ付きのRa-02派生モデル |
| HopeRF RFM95W | SX1276 | 868 / 915 MHz | SPI | LoRaWANやTTNでよく使われるモデル |
| Ebyte E32 / E220 | SX1278 / LLCC68 | 433 / 868 MHz | UART | 独自のプロセッサを搭載。ライブラリなしでシリアルポートのように動作 |
| TTGO LoRa32, Heltec LoRa 32 | ESP32 + SX1276/78 | 433 / 868 / 915 MHz | ボード上に搭載 | ESP32、LoRa、OLEDを1枚のボードに搭載 |
| Ra-02の仕様 | 値 |
|---|---|
| チップ | Semtech SX1278 |
| 周波数範囲 | 410〜525 MHz(通常は433 MHz) |
| 最大出力 | +18 dBm(約63 mW) |
| 受信感度 | 最低-141 dBm(最も狭い帯域幅の場合) |
| 電源 | 1.8〜3.7 V、通常は3.3 V |
| 電流 | 送信時約40〜120 mA、受信待機時約12 mA、スリープ時1 µA未満 |
| インターフェース | SPI(最大10 MHz)+ DIO0割り込みピン |
| アンテナ | IPEX(U.FL)コネクター。433 MHzのアンテナが必要 |
周波数は433 MHzと868/915 MHzのどちらを選ぶ?
LoRaは免許不要のISM帯で動作しますが、周波数帯は国によって異なり、それぞれ出力とデューティ比に制限があります。ヨーロッパでLoRaに使われるのは433.05〜434.79 MHzと863〜870 MHzの2つの帯域で、北米では902〜928 MHzです。LoRaWANネットワークとTTNはヨーロッパで868 MHz、米国で915 MHzを使います。一方、安価なRa-02モジュールを使う趣味の1対1通信では433 MHzがよく使われます。アンテナとチップは特定の周波数に合わせて調整されているため、購入前に使用地域の条件を確認してください。868 MHzのモジュールは433 MHzでは動作しません。
| 地域 | LoRaの周波数 | LoRaWANプラン |
|---|---|---|
| ヨーロッパ、英国、トルコ | 433 MHzと863〜870 MHz | EU868(EU433はまれ) |
| 米国、カナダ、メキシコ | 902〜928 MHz | US915 |
| ブラジル、アルゼンチン、オーストラリア | 915〜928 MHz | AU915 |
| インド | 865〜867 MHz | IN865 |
| 日本、東南アジア | 920〜923 MHz | AS923 |
| 中国 | 470〜510 MHz(および433 MHz) | CN470 |
SF・BW・CR:通信距離を決める3つの設定
LoRaの通信距離と速度は3つのパラメータで決まります。拡散率(SF)は、各シンボルを構成する「チップ」の数を決めます。SF7からSF12まで、1段階上げるごとにシンボル時間が2倍になり、約2.5 dB弱い信号まで復号できるようになりますが、電波を送信している時間もほぼ2倍になります。以下の表は帯域幅125 kHz、符号化率4/5、20バイトのパケットで計算しています。最後の列はデューティ比1%を守るために必要な、パケット間の最短待機時間です。
| SF | ビットレート | 20バイトのパケット送信時間 | おおよその感度 | 復号可能な最低SNR | デューティ比1%での待機時間 |
|---|---|---|---|---|---|
| SF7 | 5.5 kbit/s | 57 ms | -123 dBm | -7.5 dB | 6 s |
| SF8 | 3.1 kbit/s | 103 ms | -126 dBm | -10 dB | 10 s |
| SF9 | 1.8 kbit/s | 185 ms | -129 dBm | -12.5 dB | 18 s |
| SF10 | 977 bit/s | 371 ms | -132 dBm | -15 dB | 37 s |
| SF11 | 537 bit/s | 741 ms | -134 dBm | -17.5 dB | 73 s |
| SF12 | 293 bit/s | 1319 ms | -137 dBm | -20 dB | 131 s |
帯域幅(BW)は信号が占める周波数範囲の広さです。標準は125 kHzで、250 kHzと500 kHzでは速度がそれぞれ2倍と4倍になりますが、感度は3 dBと6 dB低下します。62.5 kHz以下にすると通信距離が伸びる一方、安価な水晶の周波数ドリフトの影響を受けやすくなります。符号化率(CR)は誤り訂正のために加える冗長データの割合です。4/5では4ビットごとに訂正用の1ビット、4/8では4ビットを加えます。ノイズの多い環境で役立ちますが、パケットは長くなります。ビットレートの式はRb = SF × (BW / 2^SF) × 4 / (4 + CR)です。SF9、125 kHz、4/5では9 × 125000 / 512 × 0.8 ≈ 1758 bit/sとなります。
Ra-02の配線:Arduino Uno、ESP32、Pico
Ra-02には4本のSPI信号線(SCK、MISO、MOSI、NSS)のほかに、リセットピンと割り込みピン(DIO0)が必要です。DIO0は送信完了時や新しいパケットの受信時にHIGHになり、LoRaライブラリはこれを割り込みに使います。このガイドのコードでは、モジュールのDIO1〜DIO5ピンは未接続のままで構いません。SPIに初めて触れる場合は、先にSPIとは?の記事を読んでみてください。
| Ra-02のピン | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| 3.3V | 外部3.3 Vレギュレーター | 3V3 | 3V3 (OUT) |
| GND | GND | GND | GND |
| SCK | D13(レベル変換経由) | GPIO 18 | GP18 |
| MISO | D12(直接接続) | GPIO 19 | GP16 |
| MOSI | D11(レベル変換経由) | GPIO 23 | GP19 |
| NSS | D10(レベル変換経由) | GPIO 5 | GP17 |
| RESET | D9(レベル変換経由) | GPIO 14 | GP20 |
| DIO0 | D2(直接接続、割り込みピン) | GPIO 26 | GP21 |
アンテナは配線と同じくらい重要です。Ra-02のIPEXコネクターに、433 MHz用に調整されたアンテナを取り付けます。自作も簡単です。波長は300 / 433 = 0.693メートルなので、まっすぐな17.3 cmの線で1/4波長アンテナになります(868 MHzでは8.6 cm、915 MHzでは8.2 cm)。アンテナは垂直に立て、金属の箱には入れず、両側のアンテナを同じ向き(両方とも垂直)にしてください。互いに直角になると、信号の大部分を失います。
ステップごとの解説:LoRaライブラリで送信機を作る
- Arduino IDEのライブラリマネージャを開き、LoRaと入力して、Sandeep MistryのLoRaライブラリをインストールします。
- 表のとおりにモジュールを配線し、アンテナを取り付けずに送信することは絶対に避けてください。
- 送信側のボードに以下のコードを書き込みます。ESP32かUnoかを判別し、それに合わせてピンを選びます。
- シリアルモニタを115200ボーで開くと、5秒ごとに「Gonderildi / sent」の行が表示されます。
- LoRa.begin()が失敗した場合は、配線、3.3 V電源、NSSピンとRESETピンを確認してください。
1#include <SPI.h>
2#include <LoRa.h>
3
4#if defined(ESP32)
5const int PIN_SS = 5, PIN_RST = 14, PIN_DIO0 = 26; // ESP32 (VSPI: SCK 18, MISO 19, MOSI 23)
6#else
7const int PIN_SS = 10, PIN_RST = 9, PIN_DIO0 = 2; // Uno (SCK 13, MISO 12, MOSI 11) + seviye dönüştürücü / level shifter
8#endif
9
10const long FREKANS = 433E6; // Ra-02: 433 MHz; RFM95 için 868E6 / 868E6 for an RFM95
11unsigned long sayac = 0;
12
13void setup() {
14 Serial.begin(115200);
15 LoRa.setPins(PIN_SS, PIN_RST, PIN_DIO0);
16 if (!LoRa.begin(FREKANS)) { // SX1278 bulunamadı / SX1278 not found
17 Serial.println("LoRa baslatilamadi / LoRa init failed");
18 while (true) delay(1000);
19 }
20 LoRa.setSpreadingFactor(9); // SF9: menzil ile hız dengesi / range vs speed balance
21 LoRa.setSignalBandwidth(125E3); // 125 kHz bant genişliği / bandwidth
22 LoRa.setCodingRate4(5); // hata düzeltme 4/5 / error coding 4/5
23 LoRa.setSyncWord(0xF3); // iki tarafta aynı olmalı / must match on both sides
24 LoRa.enableCrc(); // bozuk paketi ele / drop corrupted packets
25 LoRa.setTxPower(10); // 10 dBm (433 MHz bandında yasal sınır) / legal limit on 433 MHz
26 Serial.println("Verici hazir / sender ready");
27}
28
29void loop() {
30 LoRa.beginPacket();
31 LoRa.print("BG #");
32 LoRa.print(sayac); // paket numarası / packet number
33 LoRa.endPacket(); // gönderim bitene kadar bekler / blocks until sent
34 Serial.print("Gonderildi / sent #");
35 Serial.println(sayac);
36 sayac++;
37 delay(5000); // havada kalma süresine göre bekle / wait according to airtime
38}
39| 関数 | 働き |
|---|---|
| LoRa.setPins(ss, reset, dio0) | NSS、RESET、DIO0ピンを指定します。begin()の前に呼び出します |
| LoRa.begin(433E6) | モジュールを起動し、周波数をHzで設定します。チップが見つからない場合は0を返します |
| setSpreadingFactor(6–12) | SFの設定。既定値は7 |
| setSignalBandwidth(125E3) | 帯域幅。既定値は125 kHz |
| setCodingRate4(5–8) | 符号化率4/5〜4/8。既定値は4/5 |
| setSyncWord(0xF3) | 同期ワード。既定値は0x12(LoRaWANは0x34) |
| enableCrc() | パケットにCRCを追加します。ライブラリでは既定で無効です |
| setTxPower(2–20) | dBm単位の出力。既定値は17 |
| beginPacket() / print() / endPacket() | パケットを準備し、データを書き込み、送信します |
受信機:パケット、RSSI、SNRの読み取り
受信コードはループのたびにLoRa.parsePacket()で新しいパケットが届いたかを確認します。届いていればパケットのサイズが返り、LoRa.read()で内容を1バイトずつ読み取ります。また、パケット番号の抜けを数えて損失率を計算します。これは、この後で行う通信距離テストの基本になります。
1#include <SPI.h>
2#include <LoRa.h>
3
4#if defined(ESP32)
5const int PIN_SS = 5, PIN_RST = 14, PIN_DIO0 = 26;
6#else
7const int PIN_SS = 10, PIN_RST = 9, PIN_DIO0 = 2;
8#endif
9
10long sonNo = -1; // son alınan paket numarası / last packet number
11unsigned long alinan = 0, kayip = 0;
12
13void setup() {
14 Serial.begin(115200);
15 LoRa.setPins(PIN_SS, PIN_RST, PIN_DIO0);
16 if (!LoRa.begin(433E6)) {
17 Serial.println("LoRa baslatilamadi / LoRa init failed");
18 while (true) delay(1000);
19 }
20 LoRa.setSpreadingFactor(9); // verici ile aynı ayarlar / same settings as the sender
21 LoRa.setSignalBandwidth(125E3);
22 LoRa.setCodingRate4(5);
23 LoRa.setSyncWord(0xF3);
24 LoRa.enableCrc();
25 Serial.println("Alici hazir / receiver ready");
26}
27
28void loop() {
29 int boyut = LoRa.parsePacket(); // paket geldi mi? / did a packet arrive?
30 if (boyut == 0) return;
31
32 String mesaj = "";
33 while (LoRa.available()) mesaj += (char)LoRa.read();
34
35 int diyez = mesaj.indexOf('#'); // "BG #123" içinden numara / number from "BG #123"
36 long no = (diyez >= 0) ? mesaj.substring(diyez + 1).toInt() : -1;
37 if (sonNo >= 0 && no > sonNo + 1) kayip += no - sonNo - 1; // atlanan numaralar kayıp / skipped numbers are lost
38 if (no >= 0) sonNo = no;
39 alinan++;
40
41 Serial.print(mesaj);
42 Serial.print(" RSSI: ");
43 Serial.print(LoRa.packetRssi()); // dBm, -120'ye yaklaştıkça zayıf / weaker towards -120
44 Serial.print(" dBm SNR: ");
45 Serial.print(LoRa.packetSnr(), 1); // dB, eksi değerler de çözülebilir / negative values still decode
46 Serial.print(" dB kayip / lost: ");
47 Serial.print(100.0 * kayip / (alinan + kayip), 1);
48 Serial.println(" %");
49}
50RSSI(受信信号強度指標)は受信信号の強さを示す、単位dBmの負の数です。-40 dBmは非常に強く、-120 dBmは非常に弱い信号です。SNR(信号対雑音比)は、信号がノイズよりどれだけ強いかを表します。LoRaの特徴は、SNRが負でも動作することです。SF9では-12.5 dBまでパケットを復号できます。通信距離の限界に近いかを判断するときは、RSSIよりもSNRに注目してください。ノイズの多い市街地では、RSSIが-100 dBmでもSNRはすでに限界に達していることがあります。
| 指標 | 値 | 意味 |
|---|---|---|
| RSSI | -30〜-70 dBm | 非常に強い。モジュール同士が近い |
| RSSI | -70〜-110 dBm | 良好で安定した通信 |
| RSSI | -110〜-125 dBm | 弱い。SFを上げることを検討 |
| SNR | +5 dB以上 | 余裕あり。SFを下げて速度を上げられる可能性あり |
| SNR | 0〜-10 dB | LoRaの通常の動作範囲 |
| SNR | SFの限界付近(SF9では-12 dB) | 途切れる直前。SFを上げるかアンテナを改善 |
ESP32でLoRaを使う:Wi-Fiへのブリッジ

ESP32はLoRaを最も簡単に使えるボードです。ピンはもともと3.3 Vで、3V3ピンはモジュールに必要な電流を供給でき、VSPIバス(GPIO 18、19、23)をそのまま使えます。上記の送受信コードは、変更せずにESP32でコンパイルできます。#if defined(ESP32)の行でNSS = 5、RESET = 14、DIO0 = 26が選ばれます。DIO0をGPIO 2ではなくGPIO 26につなぐのは、GPIO 2がチップの起動方法に影響するストラッピングピンだからです。ESP32の真価はブリッジとしての働きにあります。畑のセンサーからLoRaで届いたデータを、Wi-Fi経由でWebページ、MQTTサーバー、Telegramへ転送できます。TTGO LoRa32やHeltec LoRa 32などのボードには、ESP32、LoRaチップ、OLEDディスプレイが1枚に搭載されています。ピン番号は異なるため、ボードの回路図を確認してください。
Raspberry Pi PicoでLoRaを使う(MicroPython)
PicoではRa-02をSPI0バス(GP16 MISO、GP18 SCK、GP19 MOSI、GP17 NSS)に接続します。公式のmicropython-libリポジトリにはSX127xチップ向けのLoRaドライバがあり、Thonnyのパッケージマネージャかmpremote mip install lora-sync lora-sx127xでインストールできます。ドライバには設定を辞書形式で渡します。SF、帯域幅、同期ワードがArduino側と一致していれば、Picoは上記のArduino送信機からのパケットを問題なく読み取れます。ドライバはSNRをチップのレジスタに格納された値、つまりdB値の4倍で返すため、コードでは4で割っています。Ra-02のアンテナはチップのPA_BOOST出力につながっているので、tx_antの設定は必ず「PA_BOOST」にしてください。そうしないと、送信が非常に弱くなります。
1from machine import Pin, SPI
2from lora import SX1278 # mip: lora-sync + lora-sx127x paketleri / packages
3import time
4
5lora_cfg = {
6 "freq_khz": 433000, # Ra-02: 433 MHz
7 "sf": 9, # Arduino tarafıyla aynı / same as the Arduino side
8 "bw": "125", # kHz
9 "coding_rate": 5, # 4/5
10 "preamble_len": 8,
11 "syncword": 0xF3,
12 "tx_ant": "PA_BOOST", # Ra-02 anteni PA_BOOST çıkışında / Ra-02 antenna is on PA_BOOST
13 "output_power": 10, # dBm
14}
15
16spi = SPI(0, baudrate=2_000_000, sck=Pin(18), mosi=Pin(19), miso=Pin(16))
17modem = SX1278(spi=spi, cs=Pin(17), dio0=Pin(21), reset=Pin(20), lora_cfg=lora_cfg)
18
19while True:
20 paket = modem.recv(timeout_ms=10000) # 10 sn dinle / listen for 10 s
21 if paket and paket.valid_crc:
22 # snr kayıtta 4 katı tutulur / snr is stored as 4x in the register
23 print(bytes(paket), "RSSI:", paket.rssi, "dBm SNR:", paket.snr / 4, "dB")
24 elif paket:
25 print("CRC hatali paket / bad CRC")
26 else:
27 print("Paket yok / no packet")
28 time.sleep_ms(10)
29通信距離テスト:LoRaは何kmまで届く?
実際の通信距離を知るには、テストするしかありません。自宅の窓辺や屋根に送信機を置き、受信機をノートパソコン、またはモバイルバッテリーで動かすESP32 + OLEDに接続します。離れながらRSSI、SNR、損失率を記録してください。損失率が10%を超えるか、SNRがSFの限界に近づくと、実用的な通信距離の限界です。違いの原因が分かるように、1回のテストで変えるのはSF、アンテナ、高さなどのうち1つだけにします。2地点間の直線距離は、スマホの地図アプリで測れます。
| 環境 | 一般的な通信距離(Ra-02、SF9〜SF12、簡単なアンテナ) | 決め手となる要因 |
|---|---|---|
| 屋内、建物内 | 数フロア、100〜500 m | コンクリートの壁と金属 |
| 建物が密集した市街地 | 1〜3 km | 建物、見通しがないこと |
| 郊外、村 | 3〜6 km | 木と低い建物 |
| 開けた田園、畑 | 5〜10 km | アンテナの地上高 |
| 見通しのよい丘の頂上同士 | 15 km以上 | 地球の曲率とアンテナ利得 |
- アンテナを高くする:通信距離を伸ばすうえで、アンテナの高さほど効果的なものはありません。高さを1メートルから5メートルにすると、見通し距離は何倍にも伸びます。
- 適切なアンテナを使う:モジュールに付属する小さなスプリングアンテナは手軽ですが、効率はよくありません。17.3 cmの1/4波長ワイヤーアンテナや屋外用ホイップアンテナにすると、はっきりした差が出ます。
- SFを上げる:SF9からSF12にすると約8 dBの改善が得られ、開けた場所では距離がおおむね2倍以上になります。
- 帯域幅を狭くする:125 kHzから62.5 kHzに下げると3 dB改善しますが、2つのモジュールの水晶の周波数ドリフトが問題になることがあります。
- フレネルゾーンを空ける:見通しがよく見えても、2本のアンテナ間にある楕円形の領域に木や建物が入ると信号が弱まります。アンテナを少し高くすると解消できます。
- 電源にも注意する:送信時の急な電流増加で、余裕のない3.3 Vラインの電圧が下がり、モジュールがリセットされることがあります。電源に100 µFのコンデンサを追加してください。
LoRaとLoRaWANの違い:TTNとは?
この2つの用語はよく混同されます。LoRaは無線変調方式、つまり物理層だけを指します。2つのモジュールが直接パケットを送り合い、どの機器が何を誰に送るかは自分で決めます。このガイドの例はすべて1対1のLoRa通信です。LoRaWANはLoRaの上に構築されたネットワークプロトコルです。機器(エンドノード)は近くのゲートウェイにパケットを送り、ゲートウェイはインターネット経由でネットワークサーバーに渡し、そこからアプリケーションにデータが届きます。LoRaWANは機器の識別、AES-128暗号化、周波数とSFの自動調整(ADR)、デューティ比の規則を自動で処理します。
| 項目 | LoRa(1対1通信) | LoRaWAN |
|---|---|---|
| 層 | 無線のみ(物理層) | 無線 + ネットワークプロトコル(MAC) |
| インフラ | モジュール2つで十分 | ゲートウェイとネットワークサーバーが必要 |
| 暗号化 | なし。自分で追加 | AES-128、必須 |
| Arduinoライブラリ | LoRa(Sandeep Mistry) | MCCI LoRaWAN LMIC, RadioLib |
| ヨーロッパでの周波数 | 433 MHzか868 MHzを自由に選択 | EU868のチャネルプラン |
| 適した用途 | 自宅の庭、2つの建物間、リモコン | 市全体のセンサーネットワーク、多数の機器 |
The Things Network(TTN)は、ボランティアが設置したゲートウェイで構成される、無料のコミュニティ型LoRaWANネットワークです。近くにTTNゲートウェイがあれば、自分でゲートウェイを作らなくても、機器を登録してインターネット上でデータを読めます。無料利用にはフェアユースポリシーがあり、1台あたりの合計送信時間は1日約30秒、ダウンリンクメッセージは1日最大10件です。TTNはヨーロッパでEU868、米国でUS915を使うため、433 MHzのRa-02は適していません。TTNには使用地域に合ったRFM95か、LoRaWAN対応の完成済みモジュールを用意してください。近くにゲートウェイがなければ、1対1のLoRa通信のほうがはるかに簡単です。
プロジェクト:電池で動く畑と庭のセンサー

LoRaの代表的な用途は、電源やWi-Fiのない畑や、庭の奥にある温室からデータを取得することです。以下のESP32コードは土壌水分を測り、「T1,42,37」(ノードID、パケット番号、水分率)の形式で小さなパケットを送信します。その後、LoRaモジュールとESP32の両方をスリープさせ、10分後に再び起動します。センサーには測定中だけGPIO 25から給電するため、スリープ中は電流を消費せず、抵抗式センサーでは電極の腐食も抑えられます。センサーのキャリブレーションは土壌水分センサーの記事、ディープスリープの詳細はESP32のディープスリープの記事で解説しています。自宅の受信機には上記の受信コードを使い、カンマで値を分割できます。
1#include <SPI.h>
2#include <LoRa.h>
3
4const int PIN_SS = 5, PIN_RST = 14, PIN_DIO0 = 26;
5const int NEM_PIN = 34; // toprak nem sensörü AO (yalnız giriş pini) / soil sensor AO (input-only pin)
6const int SENSOR_GUC = 25; // sensörü yalnız ölçerken besle / power the sensor only while measuring
7const int KURU = 3000, ISLAK = 1200; // kendi sensörünle kalibre et / calibrate with your sensor
8const uint64_t UYKU_US = 10ULL * 60 * 1000000; // 10 dakika / 10 minutes
9
10RTC_DATA_ATTR uint32_t paketNo = 0; // derin uykuda korunur / kept during deep sleep
11
12void setup() {
13 pinMode(SENSOR_GUC, OUTPUT);
14 digitalWrite(SENSOR_GUC, HIGH);
15 delay(200); // sensör otursun / let the sensor settle
16 int ham = analogRead(NEM_PIN);
17 digitalWrite(SENSOR_GUC, LOW);
18 int nem = constrain(map(ham, KURU, ISLAK, 0, 100), 0, 100); // % nem / % moisture
19
20 LoRa.setPins(PIN_SS, PIN_RST, PIN_DIO0);
21 if (LoRa.begin(433E6)) {
22 LoRa.setSpreadingFactor(10); // uzak tarla için daha yüksek SF / higher SF for a distant field
23 LoRa.setSignalBandwidth(125E3);
24 LoRa.setSyncWord(0xF3);
25 LoRa.enableCrc();
26 LoRa.setTxPower(10);
27 LoRa.beginPacket();
28 LoRa.print("T1,"); // düğüm kimliği / node id
29 LoRa.print(paketNo++);
30 LoRa.print(",");
31 LoRa.print(nem); // ör. "T1,42,37" / e.g. "T1,42,37"
32 LoRa.endPacket();
33 LoRa.sleep(); // SX1278 uykuda 1 uA altı / under 1 uA asleep
34 }
35 esp_sleep_enable_timer_wakeup(UYKU_US);
36 esp_deep_sleep_start(); // 10 dk sonra setup() baştan başlar / setup() restarts after 10 min
37}
38
39void loop() {}
40電池寿命を見積もってみましょう。ノードは10分(600秒)ごとに約0.5秒間起動し、その間の平均消費電流は約100 mAです。スリープ中は、ESP32のモジュール単体とRa-02を合わせて約15 µAを消費します。平均電流は(0.5 × 100)/ 600 + 0.015 ≈ 0.1 mAです。2000 mAhの18650電池なら、理論上は20,000時間、つまり2年以上持ちます。実際には電池の自己放電やレギュレーターの損失で短くなります。注意点として、ESP32 DevKitの完成済みボードはUSBシリアル変換チップやレギュレーターを搭載しているため、スリープ中も数ミリアンペア消費することがあります。スリープ電流が5 mAなら、同じ電池でも17日まで短くなります。長く動かすには、自己消費電流の小さいレギュレーターかモジュール単体を使ってください。電池寿命計算ツールで、自分の値を使って計算できます。
LoRaのプロジェクトアイデア
- 離れた水タンクの水位:水位センサーで離れたタンクにどれだけ水があるかを測り、自宅に送信します。
- 郵便受けの通知:庭の門にある郵便受けが開いたことをリードスイッチで検出し、室内のディスプレイに表示します。
- ミツバチの巣箱のはかり:HX711ロードセルで巣箱の重さを1日に数回送信します。
- GPSトラッカー:NEO-6M GPSで数km離れた自転車や動物を追跡します。
- 温室の環境監視:温室の温湿度をLoRaで受信し、しきい値を超えたら自宅で警告を出します。
- 自作ゲートウェイ:1台のESP32で複数のLoRaセンサーのデータをWi-Fiに転送し、スマホで確認します。
よくある間違いと対処法
| 症状 | 考えられる原因 | 対処法 |
|---|---|---|
| 「LoRa init failed」(LoRaの初期化に失敗) | SPI配線、NSSピン、RESETピンの間違い、または電源なし | 配線とsetPins()の値を確認し、3.3 Vを測定 |
| 送信側は送っているのに受信側で何も受信しない | 周波数、SF、BW、CR、同期ワードの不一致 | 両側の設定を完全に一致させる |
| モジュールが熱くなる、またはまったく動かない | 5 Vで給電した、または5 V信号を入力した | 3.3 V電源とレベル変換モジュールを使う。モジュールが壊れている可能性あり |
| 送信時にボードがリセットされる | 3.3 Vラインが急な電流増加に対応できない | 専用のレギュレーターを使い、電源に100 µFのコンデンサを追加 |
| 数メートルしか届かない | アンテナがない、または周波数の違うアンテナを使用 | 433 MHzアンテナを取り付ける。アンテナなしの送信はPAを壊すおそれあり |
| パケットの文字が化ける | CRCが無効で、ノイズで破損したパケットを受け入れている | 両側でenableCrc()を呼び出す |
| 一部のパケットが届かない | パケット送信が頻繁すぎて電波が衝突している | 電波の送信時間に応じてパケット間隔を広げる |
LoRaモジュールは、Arduinoプロジェクトを家の外の畑や庭、隣の建物へ広げる最も安価な方法です。適切な周波数とSF、よいアンテナを使えば、数km先で電池で数か月動くセンサーを作れます。短い距離で高速にデータを送るなら、nRF24L01やESP-NOWのほうが適しているかもしれません。BlueGraysアプリには、2台のArduino間の一方向・双方向通信、スマート水やり、ESP32のディープスリープのプロジェクトが、ステップごとの回路図とコード付きで用意されています。これらにLoRaを追加して発展させられます。
よくある質問
LoRaモジュールはどのくらい遠くまで届きますか?
Ra-02のようなSX1278モジュールに簡単なアンテナを付けた場合、通常は市街地で1〜3 km、開けた場所で5〜10 km届きます。アンテナを高く設置し、見通しがよければ15 km以上も可能です。通信距離は主にアンテナの高さ、品質、SFの設定で決まります。
LoRaとLoRaWANの違いは何ですか?
LoRaは無線変調方式だけを指し、2つのモジュールが直接パケットを送り合います。LoRaWANはLoRa上に構築されたネットワークプロトコルです。機器がゲートウェイに送信し、データはインターネット経由でネットワークサーバーに届きます。暗号化や機器管理はプロトコルが処理します。自宅の庭にはLoRa、市全体のネットワークにはLoRaWANが向いています。
LoRaの周波数は433、868、915 MHzのどれを使えばよいですか?
使用する地域によります。ヨーロッパは433 MHzと863〜870 MHz(LoRaWANではEU868)、北米は902〜928 MHz(US915)を使い、ほかの地域にはAU915やAS923などのプランがあります。使用する帯域に合ったモジュールとアンテナを購入し、地域の出力とデューティ比の制限を守ってください。
LoRaモジュールを5 VのArduinoにつなげますか?
直接はつなげません。SX1278は3.3 Vのチップで、5 Vの信号を加えると壊れます。Arduino Unoで使うには、SCK、MOSI、NSS、RESETの信号線にレベル変換モジュールを入れ、別の3.3 Vレギュレーターから給電してください。ESP32とRaspberry Pi Picoは3.3 Vで動作するため、直接接続できます。
LoRaで音声や画像を送れますか?
実用上はできません。LoRaのデータ速度は帯域幅125 kHzで約0.3〜5.5キロビット毎秒で、デューティ比の規則によって送信頻度も制限されます。小さな写真でも数分かかります。LoRaはセンサーの測定値、位置、状態メッセージなどの小さなデータ向けに設計されています。
拡散率(SF)とは何ですか?どの値を使えばよいですか?
SFはLoRaの各シンボルを送信する時間を決めます。SF7からSF12まで、1段階上げるごとに通信距離が伸びますが、データ速度は半分になり、電池消費も増えます。最初はSF9がバランスのよい設定です。距離が足りなければSFを上げ、近距離で速度が必要ならSF7まで下げます。送信側と受信側は同じSFを使う必要があります。
この記事を読んだ後に作れるプロジェクト
全プロジェクトを見る
2台のArduinoで一方向通信
2台のArduinoを1本のワイヤーで通信させます。一方のボタンを押すともう一方のLEDが点灯し、もう一度押すと消灯します。送信側のボードがボタンの押下を短いメッセージで伝え、受信側のボードはそのメッセージを受け取るとLEDの点灯と消灯を切り替えます。機器同士が情報を伝える仕組みを、最もシンプルな形で確かめられます。

2台のArduinoで双方向通信
2台のArduinoをケーブルでつないで通信します。片方のボタンを押すともう片方のライトが点灯し、もう一度押すと消灯します。両方のボードで同じプログラムを動かすので、どちらからでもメッセージを送受信できます。ボード同士でメッセージをやり取りする仕組みを、シンプルな構成で学べます。

スマート水やりステーション
旅行中も植物が枯れないよう、自動で水やりをするシステムです。土壌水分センサーで土の湿り具合を測定し、乾燥するとArduinoが給水ポンプを数秒間動かして、青いライトを点灯させます。水分が適切なときは緑のライトが点灯します。土がひどく乾燥すると、赤いライトが点滅し、ブザーが鳴って知らせます。

ESP32のディープスリープで節電(OLED + RTC RAMカウンター)
ESP32のディープスリープモードは、CPUとほとんどの周辺機器を停止し、消費電流を約10 µAまで抑えます。電池で動くIoT機器に欠かせない機能です。このプロジェクトでは、タイマー(15秒)、外部ピン(EXT0、ボタンはGPIO 33)、タッチ(T0/GPIO 4)の3種類の復帰方法を使います。RTC_DATA_ATTRを付けた変数はディープスリープ中も保持され、起動回数、タイマーによる復帰回数、ボタンによる復帰回数を継続して記録できます。復帰するたびにSSD1306 OLEDディスプレイに復帰理由と回数を表示します。

ESP32動体検知アラーム(PIR + ブザー + LED + Telegram)
PIRセンサーが動きを検知するとブザーとLEDを作動させ、同時にTelegramで持ち主に即座に通知するスマート防犯アラームです。アラームが繰り返される頻度を抑えるため、30秒のクールダウン(待ち時間)を設けています。この仕組みはPIRの検知が正しいかを確認したり、誤検知をなくしたりするものではありません。家の防犯、ガレージの監視、倉庫や作業部屋などに使えます。ESP32-CAMなら写真付きの通知を追加でき、通常のESP32 DevKit V1ではテキストで通知します。

ESP32温度データロガー(DHT22 + DS1307 RTC + microSD + OLED)
ESP32で日時付きの温度・湿度記録システムを作ります!DHT22で1分ごとに温度と湿度を読み取り、DS1307 RTCから取得した日時とともにmicroSDカードへCSV形式で記録します。OLEDには最新の温度を大きな文字で表示し、湿度のパーセント値、日時、総記録数も表示します。SDカードの/temp_log.csvファイルはExcel、Google Sheets、Pythonのpandasで開いて分析できます。温室の監視、家や部屋の温度管理、実験室のデータ収集、食品の保管環境や養蜂箱の監視に適しています。

BluetoothでスマートフォンからLEDを操作
スマートフォンで部屋の照明をつけたり消したりするための、小さな練習です。Bluetoothモジュールがスマートフォンから送られた文字をArduinoに伝えます。ある文字で赤いLEDが、別の文字で緑のLEDが点灯し、同じ文字を小文字で送ると消灯します。無線操作の仕組みを、ごくシンプルな形で学べます。
ほかの記事
BlueGraysアプリ
この回路をスマホでステップごとに作る
回路図、コード、部品リストを1つの画面で確認できます。Arduino、ESP32、Picoのプロジェクトを200件以上用意しています。

