部品 · 読了まで20分

ArduinoでSIM800Lを使うガイド:SMS送信、リレー制御、電話の発信

ArduinoでSIM800L GSMモジュールを使う方法。4 V/2 Aの電源、LEDの点滅パターン、ATコマンド、SMSの送信、SMSでのリレー制御、電話の発信、ESP32とPicoのコードを解説します。

SIM800L GSMモジュールは、切手ほどの大きさのとても安い小型の2Gモデムで、Arduinoのプロジェクトに専用の電話回線を持たせます。マイクロSIMカードを入れれば、SMSの送受信や電話の発信ができ、GPRSで少量のデータをインターネットに送ることもできます。山小屋、温室、倉庫、車など、Wi-FiやBluetoothが届かない場所でも、SIM800LとArduinoを組み合わせれば、携帯電話の電波が届く所ならどこからでも機器を遠隔操作できます。これが最も簡単な方法です。モジュールは2本線のシリアル接続(UART)でArduinoと通信し、ATコマンドと呼ばれる短いテキストのコマンドで制御します。

とはいえ、SIM800Lは初心者を最も悩ませるモジュールの1つで、ほぼすべての問題は2つのことから生じます。不十分な電源と2Gの電波です。このガイドでは、3.4〜4.4 Vの範囲と2 Aのピーク電流に合わせた正しい給電方法、基板上のLEDの点滅速度が何を伝えているか、ATコマンドでのステップごとのテスト方法、そしてArduino UnoでSMSを送り、SMSでリレーをオン・オフし、警報が鳴ったら電話をかけてくる回路の作り方を学びます。さらにESP32、既製のTTGO T-Callボード、Raspberry Pi Picoで同じことを行い、最後にネットワーク登録の問題の解決法を表にまとめます。

ヘリカルアンテナ付きのSIM800L GSM/GPRSモジュール
SIM800Lの基板:上にコイル状のスプリングアンテナ、その横に電源用のコンデンサ、そして2列のピンヘッダーがあります。マイクロSIMのスロットは基板の裏側(下)にあります。

SIM800Lとは?どう動くのか

SIM800Lは、SIMComが作った17.8 × 15.8 mmしかないGSM/GPRSモジュールです。購入する赤い基板は、その周りにSIMスロット、アンテナ接続、状態表示LED、ピンヘッダーを加えた小さなブレイクアウト基板です。モジュールは4つのGSMバンド(850、900、1800、1900 MHz)をすべて自動でスキャンし、携帯電話と同じようにネットワークに登録したあと、シリアルポートで受け取ったコマンドを実行します。「このメッセージをこの番号に送って」「この番号に電話して」「届いたメッセージを渡して」といったものです。画面もキーパッドもない電話と考えてください。その両方の役目をArduinoが担います。MICとSPKのピンにマイクとスピーカーをつなげば、本当の音声通話もできます。

項目値
モジュールSIMCom SIM800L、2G GSM/GPRS
周波数バンドクアッドバンド:GSM 850、EGSM 900、DCS 1800、PCS 1900 MHz
電源電圧3.4〜4.4 V(推奨4.0 V)
ピーク電流最大2 A(送信時の短いパルス)
平均電流パワーダウン約0.1 mA、スリープ約1〜2 mA、待機約15 mA、音声通話130〜220 mA、GPRS 150〜450 mA(バンドとデータシートの版による)
送信出力2 W(850/900 MHz)、1 W(1800/1900 MHz)
インターフェースUARTとATコマンド。自動ボーレート検出1200〜115200
ロジックレベル出力2.8 V。RXD入力は最大3.1 V
SIMカードマイクロSIM(1.8 Vと3 Vのカード)
GPRSの速度最大85.6 kbps
動作温度-40〜+85 °C

SIM800Lのピン配置

ピン機能備考
NETアンテナ接続スプリングアンテナをここにはんだ付けする。u.FL(IPEX)ソケットがあれば外部アンテナを挿す
VCC電源(+)3.4〜4.4 V。Arduinoの5Vピンや3.3Vピンには絶対につながない
RSTハードウェアリセット105 ms以上LOWにするとモジュールが再起動する。未接続でも可
RXDモジュールのシリアル入力ボードのTXピンへ。最大3.1 V
TXDモジュールのシリアル出力ボードのRXピンへ。2.8 Vレベル
GNDグランド電源とArduinoの両方へ(共通グランド)
RING着信・SMSの通知着信でLOWになり、SMSが届くと120 msのLOWパルスを出す
DTRスリープの制御AT+CSCLK=1のとき、DTRがHIGHの間はスリープし、LOWにすると起きる
MIC+ / MIC−マイク入力エレクトレットマイク用
SPK+ / SPK−スピーカー出力小型の8 Ωスピーカーをつなげる

袋に入っているコイル状のスプリングアンテナは、基板の角にあるNETの穴にはんだ付けします。外部アンテナ用の小さなu.FL(IPEX)ソケットがある基板もあります。アンテナがないとモジュールはネットワークを見つけられず、信号強度はほぼゼロになります。屋内で受信が弱い場合は、ケーブル付きの貼り付け型GSMアンテナにすると、スプリングに比べてはっきり改善します。マイクロSIMカードは、切り欠きの角をホルダーの絵に合わせて裏のスロットに入れます。カードを入れる前に、スマホでPINの要求を無効にし、その回線でSMSと通話ができ、残高が十分あることを確認してください。

電源:3.4〜4.4 Vと2 Aのピーク電流

電源はSIM800Lで最も重要で、最も間違えやすい部分です。GSMは時分割で動いています。4.615 msの各フレームの中で、モジュールは自分の577 µsのタイムスロットの間だけ送信します。この短い瞬間に最大2 Aを引き、その直後には数十ミリアンペアに戻ります。電源がこの急な電流を供給できないと、電圧が落ちます。SIMComのデータシートによると、電圧が3.5 Vまで下がるとモジュールはシリアルポートにUNDER-VOLTAGE WARNNING(低電圧警告)を出し、3.4 V未満ではUNDER-VOLTAGE POWER DOWN(低電圧で電源オフ)を出して自ら電源を切ります(WARNNINGのつづりの誤りはメーカーのファームウェアのものです)。上側では4.3 VでOVER-VOLTAGE WARNNING(過電圧警告)が出て、4.4 Vを超えるとやはり電源が切れます。ファームウェアのバージョンによってはこの自動シャットダウンが初期状態で無効になっていて、AT+CBATCHK=1で有効にします。いずれにせよ、この範囲を外れるとモジュールは不安定になり、再起動を繰り返します。そのため、Arduinoの5VピンはSIM800Lには高すぎます。3.3Vピンは最低電圧を下回り、公式には50 mAまでしか流せません。さらにパソコンのUSBポートが供給できるのは500 mAまでです。

電源の選択肢使える?詳細
1セルの3.7 V LiPoまたは18650リチウムイオン電池はい、最も簡単満充電で4.2 V。セルが3.6〜3.7 Vに下がるまでは余裕で動き、それ以下では送信のバーストで電源が切れることがある。2 Aを出せる1000 mAh以上を選び、TP4056で充電する
LM2596降圧(バック)モジュールはい、アダプターで動かすプロジェクトに7〜12 Vのアダプターから4.0〜4.1 Vに設定する。最大3 Aを供給できる
5 V入力のSIM800L基板(例:「SIM800L V2」)はい、基板の説明に従えば基板上の回路が電圧を下げる。それでも2 Aを出せる5 V電源が必要
Arduinoの5Vピンいいえ4.4 Vの上限を超え、モジュールが電源オフになるか壊れる。USBでは2 Aを供給できない
Arduinoの3.3Vピンいいえ3.4 V未満で、電流もまったく足りない。モジュールが起動しないか再起動を繰り返す
AMS1117などの3.3 Vレギュレーターいいえ3.3 Vの出力はモジュールの最低電圧を下回る
LM2596
LM2596
18650リチウムイオン電池
18650リチウムイオン電池
TP4056
TP4056
LM2596を使う場合は、SIM800Lをつなぐ前に、テスターで測りながらトリマーで出力を4.0〜4.1 Vに合わせてください。工場出荷時に何Vに設定されているかはわかりません。12 Vの入力に近い出力だと、SIM800Lは最初の1秒で壊れます。電池で動かす場合は、TP4056充電モジュールでセルを充電し、逆につながないよう注意してください。SIM800Lの基板には逆接続保護がありません。
VCCとGNDの間に、470〜1000 µFの低ESR電解コンデンサと100 nFのセラミックコンデンサを、モジュールのピンのできるだけ近くに入れてください。SIMCom自身のリファレンス設計でも、低ESRの100 µF以上が推奨されています。コンデンサが電源の代わりに2 Aのパルスを供給し、電圧の落ち込みを防ぎます。仕組みはコンデンサとは?で説明しています。電源の配線は短く太くし、ブレッドボードのばね接点に2 Aを流さないようにし、モジュールのGNDは必ずArduinoのGNDにつないでください。

LEDは何を伝えている?点滅パターンの意味

LEDの動作意味対処
消灯モジュールが動いていない電源とVCC–GNDの極性を確認し、電圧を測る
約1秒に1回(64 ms点灯、800 ms消灯)動作中だがネットワークに未登録最初の10〜60秒は正常。それ以上続くならSIM、PIN、アンテナ、2Gの電波を確認する
約3秒に1回(64 ms点灯、3000 ms消灯)ネットワークに登録済みSMSと通話の準備ができている
とても速い、約1秒に3回(64 ms点灯、300 ms消灯)GPRSのデータ接続中インターネット接続が確立している
数回点滅して消え、また始まる電圧が落ちてモジュールの電源が切れているより強い電源、大きなコンデンサ、短く太い配線を使う

LEDを診断ツールとして使う習慣を付けましょう。コードを書く前にモジュールが3秒に1回の点滅に切り替わるのを確認できれば、考えられる問題の半分はすぐに除外できます。モジュールが何分も1秒に1回の点滅を続けるなら、ソフトウェアをいじっても意味がありません。まず下のネットワーク登録のセクションを確認してください。最大の電流パルスは、モジュールが初めて基地局と通信する登録の瞬間に来ます。電源が弱いと、まさにそのときにモジュールの電源が切れ、また最初から繰り返します。

SIM800LとArduinoの配線とロジックレベル

SIM800LはUARTでArduinoと通信し、データ線は交差させます。モジュールのTXDピンはボードのRXピンへ、モジュールのRXDピンはボードのTXピンへつなぎます。Arduino Unoの唯一のハードウェアシリアルポート(D0とD1)は、USBでのコードの書き込みとシリアルモニタに使われているので、モジュールはSoftwareSerialでD2とD3につなぎます。9600ボーなら確実に動きます。ESP32とPicoではソフトウェアシリアルは不要で、ハードウェアUARTを使います。シリアル通信の基本はUARTシリアル通信のガイドにあります。

SIM800LのピンArduino UnoESP32Raspberry Pi Pico
VCC外部の4.0 V(+)外部の4.0 V(+)外部の4.0 V(+)
GNDGND + 電源(−)GND + 電源(−)GND + 電源(−)
TXDD2(SoftwareSerialのRX)GPIO 16(RX2)GP1(UART0のRX)
RXDD3、10 kΩ + 15 kΩの分圧回路を通すGPIO 17(TX2)、1 kΩ + 5.6 kΩの分圧回路を通すGP0(UART0のTX)、1 kΩ + 5.6 kΩの分圧回路を通す
RST未接続でも可未接続でも可未接続でも可
NETアンテナアンテナアンテナ
データシートによると、SIM800LのRXD入力が受け付けるのは最大3.1 Vです。UnoのD3ピンは5 Vを出すので、間に分圧回路を入れます。D3 → 10 kΩ → RXD、RXD → 15 kΩ → GNDで約3.0 Vになります。ネットでよく見る10 kΩ + 20 kΩの分圧回路は3.3 Vになります。たいていは動きますが、メーカーの上限を少し超えています。ESP32とPicoの3.3 V出力には、SIMComが推奨する直列1 kΩ + GNDへの5.6 kΩの抵抗で約2.8 Vになります。逆方向では、Unoはモジュールの2.8 VのTXD信号を通常正しく読めますが、Unoのデータシートでは5 V動作時のHIGHに3.0 Vが求められています。常設の作品では、双方向のレベル変換モジュールが最もすっきりした解決法です。

ATコマンドでの最初のテスト

  1. 表のとおりにモジュールを配線し、アンテナを付け、PINの要求を無効にしたマイクロSIMを入れます。
  2. 電源を入れてLEDを観察します。数秒間1秒に1回点滅したあと、3秒に1回の点滅に切り替わるはずです。
  3. 下のブリッジ用スケッチをArduinoに書き込みます。SoftwareSerialはArduino IDEに付属しているので、追加のライブラリは不要です。
  4. シリアルモニタを開き、速度を9600ボーに、改行の設定をCRおよびLF(Both NL & CR)にします。
  5. ATと入力してEnterを押します。モジュールは自動ボーレート検出でこちらの速度に合わせます。最初の数回は返事がないこともあるので、OKが表示されるまで繰り返してください。
  6. 次に、下の表のコマンドで、SIMカード、信号強度、ネットワーク登録を1つずつ確認します。
C++ (Arduino IDE)
1#include <SoftwareSerial.h>
2
3SoftwareSerial sim800(2, 3);        // RX = D2 (SIM800L TXD), TX = D3 (SIM800L RXD, bölücüyle / via divider)
4
5void setup() {
6  Serial.begin(9600);               // Seri Monitör hızı / Serial Monitor speed
7  sim800.begin(9600);               // SIM800L bu hıza kendini ayarlar / SIM800L autobauds to this rate
8  Serial.println(F("AT yaz ve Enter'a bas / Type AT and press Enter"));
9}
10
11void loop() {
12  if (Serial.available()) sim800.write(Serial.read());   // bilgisayar → modül / PC → module
13  if (sim800.available()) Serial.write(sim800.read());   // modül → bilgisayar / module → PC
14}
コマンド返答の例意味
ATOKモジュールが動作していて、ボーレートが合っている
AT+CPIN?+CPIN: READYSIMの準備ができている。SIM PINと出たら、PINを無効にするかAT+CPIN="1234"を送る
AT+CSQ+CSQ: 18,0信号強度0〜31(99 = 不明)。10以上で十分
AT+CREG?+CREG: 0,11 = 登録済み、5 = 登録済み(ローミング)、2 = 検索中、3 = 拒否
AT+COPS?+COPS: 0,0,"OPERATOR"通信事業者の名前
AT+CBC+CBC: 0,82,4012電源電圧(ミリボルト、この例では4.012 V)
AT+GSN15桁の番号モジュールのIMEI
AT+CCID19〜20桁の番号SIMカードのシリアル番号(ICCID)。カードが読めていることを示す
AT+CMGF=1OKSMSのテキストモード
AT+CMGS="+905551112233">メッセージの本文を待つ。Ctrl+Z(26)で送信
AT+CNMI=1,2,0,0,0OK届いたSMSを保存せず、そのままシリアルポートに出力する
ATD+905551112233;OK音声通話を発信する(末尾の;が必須)
ATA / ATHOK着信に応答する / 電話を切る
AT+CLIP=1OK着信時、+CLIPの行で発信者の番号を表示する
AT+IPR=9600OK自動ボーレート検出をやめて速度を9600ボーに固定する。そのあとAT&Wを送ると恒久的になる
AT+CMEE=2OKエラーを番号ではなく説明的なテキストで報告する

AT+CSQの返答の最初の数値はdBmに換算できます。dBm ≈ −113 + 2 × 値です。たとえば18なら約−77 dBmで、かなり良好です。10未満は弱く、5未満ではSMSさえ届きにくい信号です。99という返答は、モジュールがまだ測定できていないことを意味します。AT+CBCコマンドは電源の問題を見つけるのに最適です。待機中は約4.0 Vなのに、SMSの送信中や通話中に電源が切れるなら、問題は間違いなく電源の電流容量です。初期設定の自動ボーレートモードでは、モジュールは起動時に何も出力しません。AT+IPR=9600で速度を固定しAT&Wで保存すると、設定が不揮発メモリに記録され、モジュールは電源を入れるたびにRDY、+CFUN: 1、+CPIN: READYで準備完了を知らせるようになります。

ネットワークに登録されない?2Gの電波、SIM、IMEI

SIM800Lが使うのは2G(GSM/GPRS)のネットワークだけで、3G、4G、5Gには対応していません。2Gは多くの国で姿を消しつつあります。米国では最後の2Gネットワークが2026年8月に停止し、オーストラリアとスイスは何年も前に2Gを停止しました。フランスの事業者は2026年末までに停止し、ドイツではTelekomが2028年を目標にしています。日本と韓国はそもそもGSMを一度も使っていません。英国では事業者が2Gをもっと長く残すとしていて、最終的な停止は遅くとも2033年まで、トルコでは2029年に停止する予定です。2Gがない地域では、どれだけうまく給電してもSIM800Lは登録できません。そうした地域では、SIM7600やA7670のような4G LTEモジュールか、SIM7080GのようなLTE-M/NB-IoTモジュールが必要です。日本で作る場合も、技適を取得したLTE系のモジュールを選んでください。登録の問題を調べるときは、次の順番で進めます。

  • その場所に2Gはある?スマホのモバイルネットワークの設定で、優先するネットワークの種類を2Gのみにし、同じSIMカードで電話をかけてみてください。スマホが2Gでネットワークを見つけられなければ、SIM800Lも見つけられません。
  • SIMカードは読めている?AT+CCIDが番号を返し、AT+CPIN?が+CPIN: READYを返すはずです。エラーが出たら、カードを正しい向きで入れ直してください。ナノSIMをアダプターに入れて使っている場合は、アダプターが接点を不均一に押していないか確かめてください。
  • 信号は十分強い?AT+CSQは10以上が必要です。アンテナをはんだ付けするか外部アンテナを付け、モジュールを窓の近くに移します。
  • 登録を拒否されている?AT+CREG?が0,3を返すなら、ネットワークがモジュールを拒否しています。回線が無効になっているか、機器のIMEIがブロックされている可能性があります。
  • IMEIの登録:IMEIが登録されていない機器をブロックする国もあります。たとえばトルコでは、登録せずに海外から持ち込んだ機器は猶予期間のあとに遮断されます。AT+GSNでモジュールのIMEIを読み、そうした国にいる場合は、IMEI登録済みのモジュールを扱う国内の販売店で購入してください。
  • 電源は十分?登録の瞬間にモジュールが再起動するなら、問題はネットワークではなく電源です。上の電源のセクションに戻ってください。

ArduinoでSMSを送る

SMSを送るには、まずAT+CMGF=1でテキストモードに切り替えます。次にAT+CMGS="+905551112233"を送ります。番号は国番号付きで書くのが最も確実です(例の+90はトルコの国番号です。日本は+81、英国は+44、米国は+1のように使います)。モジュールはメッセージの本文を待っていることを示す>のプロンプトを返します。本文を入力したら、EnterではなくCtrl+Zの文字(ASCII 26、0x1A)を送ります。ネットワークがメッセージを受け付けると、モジュールは+CMGS: 12のような参照番号に続けてOKを返します。この確認には数秒、信号が弱いと最大60秒かかることがあります。下のスケッチはモジュールと同期し、ネットワークへの登録を待ってから、SMSを1通送ります。PHONEの行に自分の番号を入れてください。

C++ (Arduino IDE)
1#include <SoftwareSerial.h>
2
3SoftwareSerial sim800(2, 3);                // RX = D2 ← SIM TXD, TX = D3 → SIM RXD
4const char PHONE[] = "+905551112233";      // kendi numaran, uluslararası biçimde / your number, international format
5
6// ok gelirse 1, ERROR gelirse -1, süre dolarsa 0 / 1 on ok, -1 on ERROR, 0 on timeout
7int waitReply(const char *ok, unsigned long timeoutMs) {
8  const char *err = "ERROR";
9  byte m1 = 0, m2 = 0;
10  unsigned long start = millis();
11  while (millis() - start < timeoutMs) {
12    if (!sim800.available()) continue;
13    char c = sim800.read();
14    Serial.write(c);                        // modülün cevabını göster / show the module's reply
15    m1 = (c == ok[m1]) ? m1 + 1 : (c == ok[0] ? 1 : 0);
16    if (ok[m1] == '\0') return 1;
17    m2 = (c == err[m2]) ? m2 + 1 : (c == err[0] ? 1 : 0);
18    if (err[m2] == '\0') return -1;
19  }
20  return 0;
21}
22
23// Şebeke kaydını bekle: +CREG: 0,1 (ev ağı) ya da 0,5 (dolaşım) / wait for registration: home or roaming
24bool waitForNetwork(unsigned long timeoutMs) {
25  unsigned long start = millis();
26  while (millis() - start < timeoutMs) {
27    sim800.println("AT+CREG?");
28    String reply = "";
29    unsigned long t = millis();
30    while (millis() - t < 1000) {
31      while (sim800.available()) reply += (char)sim800.read();
32    }
33    Serial.print(reply);
34    if (reply.indexOf("+CREG: 0,1") >= 0 || reply.indexOf("+CREG: 0,5") >= 0) return true;
35    delay(2000);
36  }
37  return false;
38}
39
40bool sendSms(const char *number, const char *text) {
41  sim800.print("AT+CMGS=\"");
42  sim800.print(number);
43  sim800.print("\"\r");
44  if (waitReply(">", 5000) != 1) return false;   // metin istemi gelmedi / no text prompt
45  sim800.print(text);
46  sim800.write(26);                               // Ctrl+Z (0x1A): mesajı gönder / send the message
47  return waitReply("+CMGS:", 60000) == 1;         // ağ onayı 60 sn sürebilir / network ack may take 60 s
48}
49
50void setup() {
51  Serial.begin(9600);
52  sim800.begin(9600);
53  delay(3000);                                    // modül açılsın / let the module boot
54
55  bool alive = false;
56  for (byte i = 0; i < 10 && !alive; i++) {       // otomatik baud için birkaç kez AT / several ATs for autobaud
57    sim800.println("AT");
58    alive = (waitReply("OK", 1000) == 1);
59  }
60  if (!alive) {
61    Serial.println(F("\nModul cevap vermiyor / Module not responding"));
62    return;
63  }
64
65  sim800.println("AT+CMGF=1");                    // SMS metin modu / SMS text mode
66  waitReply("OK", 1000);
67
68  Serial.println(F("\nSebeke bekleniyor / Waiting for network"));
69  if (!waitForNetwork(60000)) {
70    Serial.println(F("Sebekeye kayit olunamadi / Not registered"));
71    return;
72  }
73
74  if (sendSms(PHONE, "BlueGrays: SIM800L calisiyor!")) Serial.println(F("\nSMS gonderildi / SMS sent"));
75  else Serial.println(F("\nSMS gonderilemedi / SMS failed"));
76}
77
78void loop() {
79  if (sim800.available()) Serial.write(sim800.read());   // sonraki mesajları göster / show later messages
80}

スケッチのwaitReply()関数は、期待する返答(OK、>、+CMGS:)とERRORという語を探しながら、モジュールから来る文字をすべてシリアルモニタに表示するので、各コマンドの結果がわかります。waitForNetwork()は、+CREGの返答が0,1(ホームネットワーク)か0,5(ローミング)になるまで待ちます。登録前に送ったSMSは失敗するからです。テキストモードのSMSは最大160文字です。Arduino IDEで入力した文字はUTF-8でエンコードされるので、アクセント付きの文字や日本語のような非ラテン文字は文字化けして届きます。コードの例のような半角英数字のASCIIテキストだけを使ってください。

SMSは1通ごとにお金がかかります。SMSを送るコードを条件なしでloop()に入れてはいけません。1秒に1回発生する不具合があれば、数分で何百通ものメッセージと高額な請求になります。警報のように繰り返すイベントには、millis()で2通のメッセージの間に待ち時間を設けてください。方法はmillis()とdelay()の違いのガイドにあります。

SMSでリレーを制御し、電話で切り替える

届いたメッセージを読むにはAT+CNMI=1,2,0,0,0を使います。この設定では、モジュールは新しいSMSをSIMカードに保存せず、2行でそのままシリアルポートに出力します。1行目は+CMT: "+905551112233","","26/10/30,14:05:12+12"のように、送信者の番号と時刻を含みます(末尾の+12は15分単位のタイムゾーンで、UTC+3を表します。日本なら+36、つまりUTC+9です)。2行目にはメッセージ本文が入ります。下のスケッチは、「ROLE AC」(リレーをオン)、「ROLE KAPA」(リレーをオフ)、「DURUM」(状態)というメッセージでD7のリレーモジュールを制御し、各コマンドのあとに返信のSMSを送り、自分の番号からのメッセージだけを受け付けます。もちろん、コード内でコマンドをON、OFF、STATUSに変えても構いません。さらにAT+CLIP=1のおかげで、自分の番号からモジュールに電話をかけると、着信は応答されずに拒否され、リレーが切り替わります。応答されない通話には料金がかからないので、これ以上安い遠隔スイッチはありません。ネットワークによっては、送信者の番号を国際形式ではなく国内形式(0から始まる)で渡すことがあります。コマンドが無視される場合は、シリアルモニタで+CMTの行を見て、OWNERを同じ形式で書いてください。

C++ (Arduino IDE)
1#include <SoftwareSerial.h>
2
3SoftwareSerial sim800(2, 3);                 // RX = D2 ← SIM TXD, TX = D3 → SIM RXD
4const byte RELAY_PIN = 7;                    // röle modülü IN / relay module IN
5const bool RELAY_ON = HIGH;                  // düşük seviyeli modülde LOW yap / set LOW for active-low modules
6const char OWNER[] = "+905551112233";        // komut kabul edilen tek numara / the only accepted number
7
8char line[100];                              // gelen satır tamponu / incoming line buffer
9byte lineLen = 0;
10bool bodyNext = false;                       // sonraki satır SMS metni mi? / is the next line the SMS text?
11bool fromOwner = false;
12bool relayState = false;
13
14int waitReply(const char *ok, unsigned long timeoutMs) {
15  const char *err = "ERROR";
16  byte m1 = 0, m2 = 0;
17  unsigned long start = millis();
18  while (millis() - start < timeoutMs) {
19    if (!sim800.available()) continue;
20    char c = sim800.read();
21    Serial.write(c);
22    m1 = (c == ok[m1]) ? m1 + 1 : (c == ok[0] ? 1 : 0);
23    if (ok[m1] == '\0') return 1;
24    m2 = (c == err[m2]) ? m2 + 1 : (c == err[0] ? 1 : 0);
25    if (err[m2] == '\0') return -1;
26  }
27  return 0;
28}
29
30bool sendSms(const char *number, const char *text) {
31  sim800.print("AT+CMGS=\"");
32  sim800.print(number);
33  sim800.print("\"\r");
34  if (waitReply(">", 5000) != 1) return false;
35  sim800.print(text);
36  sim800.write(26);                          // Ctrl+Z: gönder / send
37  return waitReply("+CMGS:", 60000) == 1;
38}
39
40void setRelay(bool on) {
41  relayState = on;
42  digitalWrite(RELAY_PIN, on ? RELAY_ON : !RELAY_ON);
43}
44
45void handleCommand(char *text) {
46  for (char *p = text; *p; p++) *p = toupper(*p);       // büyük harfe çevir / convert to upper case
47  if (strstr(text, "ROLE AC")) {
48    setRelay(true);
49    sendSms(OWNER, "Role ACILDI / Relay ON");
50  } else if (strstr(text, "ROLE KAPA")) {
51    setRelay(false);
52    sendSms(OWNER, "Role KAPANDI / Relay OFF");
53  } else if (strstr(text, "DURUM")) {
54    sendSms(OWNER, relayState ? "Role ACIK / Relay ON" : "Role KAPALI / Relay OFF");
55  }
56}
57
58void handleLine() {
59  Serial.println(line);
60  if (bodyNext) {                            // +CMT satırından sonraki satır SMS metnidir / the line after +CMT is the SMS text
61    bodyNext = false;
62    if (fromOwner) handleCommand(line);
63  } else if (strncmp(line, "+CMT:", 5) == 0) {
64    fromOwner = (strstr(line, OWNER) != NULL);           // gönderen kontrolü / sender check
65    bodyNext = true;
66  } else if (strncmp(line, "+CLIP:", 6) == 0 && strstr(line, OWNER) != NULL) {
67    sim800.println("ATH");                   // aramayı reddet, ücret yazılmaz / reject the call, nothing is charged
68    setRelay(!relayState);                   // her çağrıda aç-kapa / toggle on every call
69  }
70}
71
72void setup() {
73  pinMode(RELAY_PIN, OUTPUT);
74  setRelay(false);
75  Serial.begin(9600);
76  sim800.begin(9600);
77  delay(3000);
78  for (byte i = 0; i < 10; i++) {            // otomatik baud eşleşmesi / autobaud sync
79    sim800.println("AT");
80    if (waitReply("OK", 1000) == 1) break;
81  }
82  const char *initCmds[] = {"ATE0", "AT+CMGF=1", "AT+CNMI=1,2,0,0,0", "AT+CLIP=1"};
83  for (byte i = 0; i < 4; i++) {
84    sim800.println(initCmds[i]);             // yankı kapalı, metin modu, SMS'i ilet, arayanı göster / echo off, text mode, push SMS, caller ID
85    waitReply("OK", 1000);
86  }
87  Serial.println(F("\nHazir / Ready"));
88}
89
90void loop() {
91  while (sim800.available()) {
92    char c = sim800.read();
93    if (c == '\r') continue;
94    if (c == '\n') {                         // satır tamamlandı / line complete
95      line[lineLen] = '\0';
96      if (lineLen > 0) handleLine();
97      lineLen = 0;
98    } else if (lineLen < sizeof(line) - 1) {
99      line[lineLen++] = c;
100    }
101  }
102}
コードの要素役割
ATE0エコーをオフにし、送ったコマンドをモジュールが繰り返さないようにする。届く行がすっきりする
AT+CNMI=1,2,0,0,0新しいSMSを、+CMTの行とその直後のメッセージ本文としてシリアルポートに出力する
AT+CLIP=1着信時、RINGのあとに+CLIPの行で発信者の番号を知らせる
strstr(line, OWNER)許可された番号が行に含まれているか確認する。ほかの番号からのコマンドは無視する
toupper()テキストを大文字に変え、「role ac」と「ROLE AC」を同じものとして扱う
ATH着信に応答せずに終える
RELAY_ONLOWレベルで動作する(アクティブLOWの)リレーモジュールではLOWにする
リレーで商用電源(230 Vや120 V。日本の商用電源は100V(50/60Hz)です)を切り替える場合は、機器のプラグを抜いた状態で配線し、高電圧側には決して触れないでください。経験がなければ、まずLEDや12 Vの負荷で試してください。また、SMSに表示される送信者の番号は偽装できることも覚えておいてください。ドアロックやボイラーのような重要なものを制御する場合は、自分だけが知っているパスワードをコマンドに加え(たとえば「ROLE AC 4827」)、コードでもそれを確認してください。

SIM800Lで電話をかける:警報が鳴ったら電話させる

電話をかけるには、ATDコマンドのあとに番号とセミコロンを書きます。ATD+905551112233;です。末尾のセミコロンは音声通話を示します。忘れるとモジュールはデータ通話を始め、音声通話はつながりません。相手が着信を拒否するか通話が終わると、モジュールはNO CARRIERかBUSYを出力します。誰も出なければNO ANSWER、ネットワークがなければNO DIALTONEです。ATHでいつでも通話を終えられます。警報の場合、鳴っている電話はSMSよりずっと注意を引きます。下のスケッチは、D4のPIR人感センサーが反応するとSMSを送り、そのあと最大20秒間スマホを鳴らし、2回の警報の間を2分空けます。

C++ (Arduino IDE)
1#include <SoftwareSerial.h>
2
3SoftwareSerial sim800(2, 3);                 // RX = D2 ← SIM TXD, TX = D3 → SIM RXD
4const byte SENSOR_PIN = 4;                   // PIR çıkışı / PIR output
5const char OWNER[] = "+905551112233";        // aranacak numara / number to call
6const unsigned long RING_MS = 20000;         // en fazla 20 sn çaldır / ring for at most 20 s
7const unsigned long COOLDOWN_MS = 120000;    // iki alarm arası 2 dk; açılışta da 2 dk bekler / 2 min between alarms, also after power-up
8unsigned long lastAlarm = 0;
9
10int waitReply(const char *ok, unsigned long timeoutMs) {
11  const char *err = "ERROR";
12  byte m1 = 0, m2 = 0;
13  unsigned long start = millis();
14  while (millis() - start < timeoutMs) {
15    if (!sim800.available()) continue;
16    char c = sim800.read();
17    Serial.write(c);
18    m1 = (c == ok[m1]) ? m1 + 1 : (c == ok[0] ? 1 : 0);
19    if (ok[m1] == '\0') return 1;
20    m2 = (c == err[m2]) ? m2 + 1 : (c == err[0] ? 1 : 0);
21    if (err[m2] == '\0') return -1;
22  }
23  return 0;
24}
25
26bool sendSms(const char *number, const char *text) {
27  sim800.print("AT+CMGS=\"");
28  sim800.print(number);
29  sim800.print("\"\r");
30  if (waitReply(">", 5000) != 1) return false;
31  sim800.print(text);
32  sim800.write(26);                          // Ctrl+Z: gönder / send
33  return waitReply("+CMGS:", 60000) == 1;
34}
35
36void callOwner() {
37  sim800.print("ATD");
38  sim800.print(OWNER);
39  sim800.println(";");                       // sondaki ; sesli arama demektir / the trailing ; means a voice call
40  waitReply("NO CARRIER", RING_MS);          // açıp kapatırsan erken biter / ends early if you answer and hang up
41  sim800.println("ATH");                     // aramayı sonlandır / hang up
42  waitReply("OK", 2000);
43}
44
45void setup() {
46  pinMode(SENSOR_PIN, INPUT);
47  Serial.begin(9600);
48  sim800.begin(9600);
49  delay(3000);
50  for (byte i = 0; i < 10; i++) {            // otomatik baud eşleşmesi / autobaud sync
51    sim800.println("AT");
52    if (waitReply("OK", 1000) == 1) break;
53  }
54  sim800.println("AT+CMGF=1");               // SMS metin modu / SMS text mode
55  waitReply("OK", 1000);
56}
57
58void loop() {
59  if (digitalRead(SENSOR_PIN) == HIGH && millis() - lastAlarm > COOLDOWN_MS) {
60    lastAlarm = millis();
61    Serial.println(F("Hareket! / Motion!"));
62    sendSms(OWNER, "ALARM: Hareket algilandi / Motion detected");
63    callOwner();
64  }
65  while (sim800.available()) Serial.write(sim800.read());
66}

スケッチは電源投入後の最初の2分間も沈黙します。これでPIRセンサーが温まる時間と、家を出る時間ができます。電話に出れば通話がつながります。SIM800LのMICとSPKのピンにエレクトレットマイクと小型の8 Ωスピーカーをつなげば、機器を通して話せます。着信に自動で応答するには、RINGの行が見えたらATAを送るだけです。通話中、モジュールは平均130〜220 mAを引き、やはり2 Aのピークがあります。SMSでは問題ない電源でも通話中に電源が切れる場合は、より大きなコンデンサかより強い電源を使ってください。

ESP32とTTGO T-CallボードでSIM800Lを使う

ESP32ではSoftwareSerialは不要で、3つあるハードウェアUARTの1つを好きなピンに割り当てられます。上のUno用スケッチをESP32で動かすには、SoftwareSerialの行を削除して代わりにHardwareSerial sim800(2);と書き、setup()でsim800.begin(9600, SERIAL_8N1, 16, 17);を使います。残りのコードはそのまま動きます。ESP32は3.3 Vで動くので、TXの線には1 kΩ + 5.6 kΩの分圧回路があれば十分です。SIM800LをESP32と同じ弱い電源から給電すると、2 AのパルスでESP32の電圧も下がり、ボードは「Brownout detector was triggered」(ブラウンアウトの検出)エラーで再起動します。2つのボードは別々の電源から給電し、GNDだけを共通にしてください。このエラーはESP32のブラウンアウトのガイドで詳しく解説しています。

配線を省きたいなら、LilyGO TTGO T-CallボードはESP32とSIM800モデムを1枚の基板にまとめています。ESP32-WROVER-Bモジュール、SIM800L(ロットによっては同じファミリーのSIM800H)、SIMカードスロット、LiPo電池のコネクター、そして電池を充電してモデムに必要な電流を供給するIP5306電源管理チップを載せています。モデムは外部ピンではなく、特定のESP32のGPIOでオン・オフされるので、普通のSIM800L用スケッチはそのままではT-Callで動きません。

LilyGO TTGO T-Call ESP32 SIM800ボード
TTGO T-Call:表にESP32-WROVER-BとSIM800モデム、裏にSIMカードスロットとLiPo電池のコネクターがあります。
T-CallのdefineGPIO機能
MODEM_PWRKEY41秒間のLOWパルスでモデムをオンにする
MODEM_RST5モデムのリセット。HIGHに保つ
MODEM_POWER_ON23HIGHにするとモデムの電源が入る
MODEM_TX27ESP32からモデムのRXD入力へ
MODEM_RX26モデムのTXD出力からESP32へ
I2C SDA / SCL21 / 22IP5306電源チップ(アドレス0x75)
LED13基板上のユーザーLED
C++ (Arduino IDE)
1#include <Wire.h>
2
3// LilyGO TTGO T-Call SIM800L (IP5306'lı sürüm) pinleri / pins of the IP5306 version
4#define MODEM_PWRKEY     4
5#define MODEM_RST        5
6#define MODEM_POWER_ON  23
7#define MODEM_TX        27      // ESP32 TX → modem RX
8#define MODEM_RX        26      // ESP32 RX ← modem TX
9#define I2C_SDA         21
10#define I2C_SCL         22
11#define IP5306_ADDR   0x75      // güç yönetim yongası / power management chip
12
13HardwareSerial &modem = Serial1;
14const char OWNER[] = "+905551112233";
15
16// Pille çalışırken IP5306 kendini kapatmasın / keep the IP5306 boost on when running from battery
17bool setPowerBoostKeepOn() {
18  Wire.beginTransmission(IP5306_ADDR);
19  Wire.write(0x00);             // SYS_CTL0 yazmacı / SYS_CTL0 register
20  Wire.write(0x37);             // boost keep-on biti açık / boost keep-on bit set
21  return Wire.endTransmission() == 0;
22}
23
24// token gelirse true; ERROR ya da süre dolarsa false / true on token, false on ERROR or timeout
25bool waitFor(const char *token, unsigned long timeoutMs) {
26  String reply = "";
27  unsigned long start = millis();
28  while (millis() - start < timeoutMs) {
29    while (modem.available()) reply += (char)modem.read();
30    if (reply.indexOf(token) >= 0) break;
31    if (reply.indexOf("ERROR") >= 0) break;
32  }
33  Serial.print(reply);
34  return reply.indexOf(token) >= 0;
35}
36
37bool at(const char *cmd) {
38  modem.println(cmd);
39  return waitFor("OK", 2000);
40}
41
42bool registered() {
43  modem.println("AT+CREG?");
44  return waitFor("+CREG: 0,1", 1000);       // ev şebekesine kayıtlı / registered on the home network
45}
46
47bool sendSms(const char *number, const char *text) {
48  modem.printf("AT+CMGS=\"%s\"\r", number);
49  if (!waitFor(">", 5000)) return false;
50  modem.print(text);
51  modem.write(26);                           // Ctrl+Z: gönder / send
52  return waitFor("+CMGS:", 60000);
53}
54
55void setup() {
56  Serial.begin(115200);
57  Wire.begin(I2C_SDA, I2C_SCL);
58  Serial.println(setPowerBoostKeepOn() ? "IP5306 OK" : "IP5306 yok / not found");
59
60  pinMode(MODEM_RST, OUTPUT);
61  pinMode(MODEM_PWRKEY, OUTPUT);
62  pinMode(MODEM_POWER_ON, OUTPUT);
63  digitalWrite(MODEM_RST, HIGH);             // reset bırakılmış / reset released
64  digitalWrite(MODEM_POWER_ON, HIGH);        // modemin beslemesini aç / switch on the modem supply
65  digitalWrite(MODEM_PWRKEY, HIGH);
66  delay(100);
67  digitalWrite(MODEM_PWRKEY, LOW);           // PWRKEY 1 sn düşük: modem açılır / PWRKEY low for 1 s: modem starts
68  delay(1000);
69  digitalWrite(MODEM_PWRKEY, HIGH);
70
71  modem.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
72  delay(3000);
73
74  for (int i = 0; i < 10 && !at("AT"); i++) delay(500);   // otomatik baud / autobaud
75  at("AT+CMGF=1");                           // SMS metin modu / SMS text mode
76  at("AT+CNMI=1,2,0,0,0");                   // gelen SMS'i seri porta ver / push incoming SMS to the UART
77
78  unsigned long start = millis();
79  while (!registered() && millis() - start < 60000) delay(2000);
80
81  if (sendSms(OWNER, "TTGO T-Call hazir / ready")) Serial.println("\nSMS gonderildi / sent");
82}
83
84void loop() {
85  while (modem.available()) Serial.write(modem.read());   // gelen SMS ve aramalar / incoming SMS and calls
86  while (Serial.available()) modem.write(Serial.read());  // Seri Monitör'den AT komutu / AT commands from the monitor
87}

これらのピンは、IP5306を載せたLilyGOのT-Call SIM800L版のものです。AXP192電源チップの版では電源チップを別のコードで設定し、SIM800C版ではモデムの電源ピンがGPIO 25です。基板に印刷された版の日付とメーカーのピン表を確認してください。setPowerBoostKeepOn()関数はIP5306のレジスタ0x00に0x37を書き込み、電池で動いているときに負荷が軽いとチップが自分で電源を切ってしまうのを防ぎます。パソコンのUSBだけで給電したときに登録の瞬間にモデムの電源が切れる場合は、LiPo電池もつないでください。電池が2 Aのパルスをまかないます。ESP32-WROVERではGPIO 16と17が内部のPSRAMに使われているので、モデムは26と27につながっています。HTTPリクエストやMQTTのようなGPRSの処理には、TinyGSMライブラリがTINY_GSM_MODEM_SIM800のdefineでこのボードに対応しています。

Raspberry Pi PicoとMicroPythonでSIM800Lを使う

Raspberry Pi Picoでは、モジュールをUART0につなぎます。SIM800LのTXDをGP1へ、RXDを1 kΩ + 5.6 kΩの分圧回路を通してGP0へつなぎ、GNDを共通にします。PicoのVBUSピンや3V3ピンではSIM800Lに給電できないので、ここでもモジュールは外部の4 V電源から給電します。下のMicroPythonのコードは、Arduinoのリレーの例と同じ仕事をします。SMSでGP15のリレーをオン・オフし、返信を送ります。to_text()関数はノイズで壊れたバイトを捨ててASCII文字だけを残すので、デコードのエラーでプログラムが止まることはありません。追加のライブラリは不要です。Thonnyでの動かし方がわからなければ、先にMicroPythonの基本のガイドを読んでください。

MicroPython
1from machine import UART, Pin
2import time
3
4# GP0 (TX) → SIM RXD (1k + 5,6k bölücü / divider), GP1 (RX) ← SIM TXD
5sim = UART(0, baudrate=9600, tx=Pin(0), rx=Pin(1), timeout=100, timeout_char=50)
6relay = Pin(15, Pin.OUT, value=0)              # röle modülü IN / relay module IN
7OWNER = "+905551112233"                        # yetkili numara / authorised number
8
9def to_text(raw):
10    # yalnız ASCII karakterleri al / keep ASCII characters only
11    return "".join(chr(b) for b in raw if 9 < b < 128)
12
13def wait_for(token, timeout_ms):
14    # token ya da ERROR gelene kadar oku / read until token or ERROR
15    buf = ""
16    t0 = time.ticks_ms()
17    while time.ticks_diff(time.ticks_ms(), t0) < timeout_ms:
18        if sim.any():
19            buf += to_text(sim.read())
20            if token in buf:
21                return True
22            if "ERROR" in buf:
23                return False
24    return False
25
26def at(cmd, timeout_ms=2000):
27    sim.write(cmd + "\r\n")
28    return wait_for("OK", timeout_ms)
29
30def send_sms(number, msg):
31    sim.write('AT+CMGS="{}"\r'.format(number))
32    if not wait_for(">", 5000):
33        return False
34    sim.write(msg)
35    sim.write(b"\x1a")                         # Ctrl+Z: gönder / send
36    return wait_for("+CMGS:", 60000)
37
38for _ in range(10):                            # otomatik baud eşleşmesi / autobaud sync
39    if at("AT", 1000):
40        break
41at("ATE0")                                     # yankıyı kapat / echo off
42at("AT+CMGF=1")                                # SMS metin modu / SMS text mode
43at("AT+CNMI=1,2,0,0,0")                        # gelen SMS'i UART'a ver / push incoming SMS to the UART
44print("Hazir / Ready")
45
46body_next = False
47from_owner = False
48while True:
49    raw = sim.readline()
50    if not raw:
51        continue
52    line = to_text(raw).strip()
53    if not line:
54        continue
55    print(line)
56    if body_next:                              # +CMT'den sonraki satır SMS metni / line after +CMT is the text
57        body_next = False
58        cmd = line.upper()
59        if not from_owner:
60            continue
61        if "ROLE AC" in cmd:
62            relay.value(1)
63            send_sms(OWNER, "Role ACILDI / Relay ON")
64        elif "ROLE KAPA" in cmd:
65            relay.value(0)
66            send_sms(OWNER, "Role KAPANDI / Relay OFF")
67        elif "DURUM" in cmd:
68            send_sms(OWNER, "Role ACIK / ON" if relay.value() else "Role KAPALI / OFF")
69    elif line.startswith("+CMT:"):             # yeni SMS başlığı / new SMS header
70        from_owner = OWNER in line
71        body_next = True

SIM800Lのプロジェクトアイデア

  • SMSで知らせる防犯警報:PIRやドアセンサーが動きを検知するとSMSを送り、そのあと電話をかけてくるシステムです。詳しくはArduinoのホーム警報システムのガイドを参照してください。
  • ガス漏れの警告:家に誰もいなくても、MQ-2ガスセンサーがしきい値を超えたらスマホにSMSが届きます。
  • SMSで返事をするGPSトラッカー:NEO-6M GPSモジュールを使い、「LOCATION」というメッセージにGoogleマップのリンクで答える車や自転車のトラッカーです。
  • 遠隔での水やり:庭や市民農園向けに、土壌水分センサーの値をSMSで知らせ、「WATER」というメッセージでポンプを動かすシステムです。
  • 温度の見張り番:温室、鶏小屋、冷凍庫が範囲を外れたら警告を送るDS18B20の回路です。
  • 電話で開くガレージのドア:登録した番号から電話が来たときだけリレーを1秒間動かす、無料のリモコンです。
  • 停電の通知:商用電源が切れても電池で動き続け、「Power cut」(停電)のSMSを送る小さな回路です。

ネットワークにつながらない、SMSが送れない:よくある問題と解決法

症状考えられる原因解決法
ATと入力してもまったく返事がないTXDとRXDが逆、共通GNDがない、改行の設定が違う、または自動ボーレート検出が同期していないTXDをD2につなぎ、GNDを共通にし、CRおよびLFを選んでATを何回か送る
意味不明な文字が出るボーレートの不一致、またはロジックレベルがぎりぎりシリアルモニタとスケッチの両方を9600にし、レベル変換モジュールを使う
LEDが数回点滅して消え、モジュールが再起動する登録中に電圧が3.4 V未満に下がっている2 Aを出せる電源、1000 µFのコンデンサ、短く太い配線
シリアルポートにUNDER-VOLTAGE POWER DOWNが出る電源が3.4 V未満に下がった電池を充電するか、降圧モジュールの出力を4.0〜4.1 Vにする
OVER-VOLTAGE WARNNINGまたはOVER-VOLTAGE POWER DOWN電圧が4.3〜4.4 Vを超えている出力を4.0 Vに下げる。モジュールを5 Vには絶対につながない
LEDが1秒に1回の点滅を続けるアンテナがない、SIMが読めない、PINが有効、またはその地域に2Gがないアンテナを付け、AT+CPIN?とAT+CSQで確認し、スマホで2Gの電波を確かめる
+CREG: 0,3が返ってくるネットワークへの登録が拒否された回線が有効か、IMEIがブロックされていないか確認する
SMSが+CMS ERRORで失敗する残高がない、番号の形式が違う、またはSMSセンターの番号がない残高を確認し、番号を国番号付きで書き、AT+CSCA?でSMSセンターを確認する
SMSの送信中にArduinoがリセットされるSIM800LとArduinoが同じ弱い電源を共有している電源を分け、GNDだけを共通にする
届いたSMSがシリアルポートに表示されないAT+CNMIを設定していない、またはモジュールの再起動で設定が消えたsetupの中でAT+CMGF=1とAT+CNMI=1,2,0,0,0を送る
問題がコードにあるのかハードウェアにあるのかを最も早く見分けるには、3.3 VのUSB-TTL変換モジュールでモジュールをパソコンに直接つなぎ、ATコマンドを手で入力します。トラブルシューティング中はAT+CMEE=2を送ってください。モジュールが「+CME ERROR: 10」ではなく「+CME ERROR: SIM not inserted」(SIMが入っていない)のような読めるエラーメッセージを表示するようになります。

正しく給電し、2Gの電波がある場所で使えば、SIM800Lは何キロも離れた所からArduinoのプロジェクトにアクセスする最も安い方法です。しっかりした4 Vの電源、大きなコンデンサ、そしていくつかのATコマンドがあれば十分です。ほかの無線の選択肢と比べたい場合は、無線通信モジュールのガイドを見てください。BlueGraysアプリには、人感センサーの警報、ガス・炎の警報、商用電源のランプ制御、スマート水やり、Telegram通知付きのESP32警報など、SIM800Lで簡単に拡張できるプロジェクトが、回路図とステップごとのコード付きで揃っています。

よくある質問

SIM800Lに必要な電圧は?5Vにつないでもいい?

SIM800Lは3.4〜4.4 Vで動き、推奨は4.0 Vです。Arduinoの5Vピンにつなぐと、モジュールは過電圧で電源が切れるか、壊れます。1セルのLiPoか18650電池、または4.0 Vに設定したLM2596を使ってください。電源は2 Aの短いパルスにも耐えられる必要があります。

SIM800Lは2026年でもまだ使える?

2Gのネットワークがまだ動いている地域でだけ使えます。2Gは米国、オーストラリア、スイスで停止され、フランスは2026年末までに停止します。ドイツ、英国、トルコには今のところまだ2Gがあります。日本ではGSMが一度も使われていないので使えません。長期のプロジェクトを作る前に事業者の2Gの計画を確認し、そうでなければ4G LTEモジュールを選んでください。

SIM800Lがネットワークにつながらないのはなぜ?

最もよくある原因は、不十分な電源、アンテナがない、PINが有効なSIMカード、その地域に2Gの電波がないことです。AT+CSQで信号を、AT+CPIN?でSIMを、AT+CREG?で登録状態を確認してください。登録中にモジュールが再起動するなら、問題は間違いなく電源です。

SIM800LのLEDの点滅パターンの意味は?

1秒に1回の点滅は、モジュールが動いているもののネットワークに未登録であることを、3秒に1回の点滅は登録済みでSMSと通話の準備ができていることを意味します。とても速い点滅はGPRSのデータ接続中です。LEDが数回点滅して消える場合は、電圧の低下でモジュールが再起動しています。

SIM800Lはインターネットにつなげる?

はい、GPRSで最大85.6 kbpsでデータを送受信でき、センサーのデータをサーバーに送る、HTTPリクエストを送る、MQTTを使うといった用途には十分です。事業者のAPN設定を入力する必要があり、TinyGSMライブラリを使うと作業が楽になります。ただし、画像や大きなファイルには遅すぎます。

SIM800Lの代わりに何を使える?

2Gが停止された国や停止予定の国では、SIM7600やA7670のような4G LTEモジュールか、SIM7080GのようなLTE-M/NB-IoTモジュールを使ってください。ATコマンドの多くは似ているので、SMSや通話のコードは少しの変更で移植できます。同じファミリーのSIM800Cや旧型のSIM900も似たコマンドを使いますが、やはり2G専用です。

全プロジェクトを見る
DHT11で温度と湿度を測定
#55中級

DHT11で温度と湿度を測定

部屋の温度は何度で、空気は湿っているでしょうか、それとも乾燥しているでしょうか?DHT11センサーが温度と湿度を測定し、Arduinoが2行のLCDディスプレイに値を表示して、数秒ごとに更新します。センサーに異常があればエラーメッセージが表示されます。自分だけの小さな気象観測装置を作る第一歩です。

4.7(47)
73
ESP32動体検知アラーム(PIR + ブザー + LED + Telegram)
#145上級
プレミアム

ESP32動体検知アラーム(PIR + ブザー + LED + Telegram)

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

0.0(0)
9
人感センサーで動きを検出
#24初級
プレミアム

人感センサーで動きを検出

誰かが部屋に入ると知らせる、シンプルな見張り役です。人感センサーが人体から放出される熱を捉え、Arduinoは動きがある間LEDを点灯させ、動きが止まると消灯させます。玄関先で自動点灯する照明や、警報システムの基本となる仕組みです。

4.6(47)
67
炎・ガスセンサーで警報
#52上級
プレミアム

炎・ガスセンサーで警報

ガスが漏れたり炎が出たりすると、すぐに知らせる小さな見張り役です。ガスセンサーは空気中のガスを、炎センサーは火の光を監視します。異常がないときは緑色のLEDが点灯し、どちらかが危険を検出すると、赤色のLEDの点滅とブザーの断続音で警報を出します。危険がなくなるまで警報は続きます。

4.8(52)
67
ボタンを押している間だけ220V電球を点灯
#19上級
プレミアム

ボタンを押している間だけ220V電球を点灯

ボタンを押している間は実際の220ボルトの電球が点灯し、離すとすぐに消灯します。Arduinoの小さな信号では電球を直接点灯できないため、電気で動くスイッチであるリレーを間に入れ、電球の回路を開閉します。ボードで家庭の照明を操作するための第一歩です。家庭用電源を扱う際は十分に注意し、不安がある場合は詳しい人に手伝ってもらってください。

4.4(30)
38
リモコンで220V電球を点灯・消灯
#21上級
プレミアム

リモコンで220V電球を点灯・消灯

ソファに座ったまま、テレビのリモコンで家庭の電球を点灯・消灯します。Arduinoがリモコンから届く目に見えない光の信号を読み取り、電源ボタンを押すとリレーを動かして電球を点灯させ、消音ボタンを押すと消灯させます。家庭用電源を扱うため、配線は大人と一緒に、必ずプラグを抜いた状態で行ってください。

4.4(22)
30
スマート水やりステーション
#83上級
プレミアム

スマート水やりステーション

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

5.0(42)
57