Arduino Mega 2560でSMS経由のDHT22温度読み取りシステム
必要な部品と用品
| 部品 | 数量 | 備考 |
|---|---|---|
| Arduino Mega 2560 | 1 | |
| DHT22温度センサー | 1 | |
| SIM800L | 1 | |
| 抵抗 10kΩ | 1 | |
| ブレッドボード(汎用) | 1 | |
| ジャンパーワイヤ(汎用) | 1 |
このプロジェクトについて
こんにちは。このプロジェクトはもっと大きなプロジェクトの一部です。この部分で多くの問題に直面し、最終的に解決策を見つけたので、コミュニティと共有して皆さんのプロジェクトの助けになればと思います。
プロジェクト概要
ArduinoにSMSを送信し、自宅の温度を取得します。
ソフトウェア
SIM800Lモジュールには「Seeeduino_GPRS-master」ライブラリを使用しました。MEGAで動作させるため、「sim800.h」ライブラリの以下の行を変更しました:
#define SIM800_TX_PIN 8
#define SIM800_RX_PIN 7
をTX_PIN 10とRX_PIN 11に変更。ライブラリを「SoftwareSerial」からMegaのシリアルポート(Serial3)に変更するのは難しかったので、簡単な方法を取りました。
問題
基本的に私のコードは、「DHT.h」と「Seeeduino_GPRS-master」の2つのライブラリのサンプルをコピペしたものです。問題は、「gprs.h」の例では決められたメッセージを引用符で送信する方法しか示されておらず、温度センサーからのfloat型変数値を送信する方法がわかりませんでした。これは「GPRS_SIM900-master」や「SIM800L-master」など他のライブラリでも同様でした。
ウェブで解決例を数週間探しましたが見つかりません。同じ問題で困っているフォーラム投稿を見つけましたが、回答が得られていません。あの迷える魂たちがこの投稿を見つけてくれることを願っています。
解決策
float値をStringに変換し、さらにStringをchar配列に変換するだけです。シンプル!
コードスニペット
MyString = String(temp, 0); // floatをStringに変換
MyString = (MyString + " Degrees C"); // 単位追加
// Stringをchar配列に変換開始
int str_len = MyString.length() + 1; // 長さ(ヌル終端用に+1)
char char_array[str_len]; // 文字配列(バッファ)準備
MyString.toCharArray(char_array, str_len); // コピー
// Stringをchar配列に変換終了
gprs.sendSMS("04++++++++", char_array); // 電話番号とテキストを指定
配線
SIMモジュールへの電源供給にはULTRAFIRE 18650バッテリーを使用。後で電圧レギュレーターを回路に追加予定。このチュートリアルを参照。
参考資料
- https://www.ayomaonline.com/programming/quickstart-sim800-sim800l-with-arduino/
- https://www.sparkfun.com/datasheets/Sensors/Temperature/DHT22.pdf
ライブラリ
コード
DHT_SIMPosting.ino (Arduino)
"InTemp"というSMSを送信すると温度を要求し、Arduinoが摂氏で返信します。
// Example testing sketch for various DHT humidity/temperature sensors // Written by ladyada, public domain #include "DHT.h" #define DHTPIN 2 #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 //#define DHTTYPE DHT21 // DHT 21 (AM2301) // センサーのピン1(左)を+5Vに接続 // センサーのピン2をDHTPINに接続 // センサーのピン4(右)をGNDに接続 // ピン2(データ)からピン1(電源)に10K抵抗を接続 DHT dht(DHTPIN, DHTTYPE); #include#include #define TIMEOUT 5000 GPRS gprs; bool ITemp = false; float temp; String MyString; #define LED_PIN 13 bool ledStatus; // SIM800からのシリアル出力の最後の行を保持 char currentLine[500] = ""; int currentLineIndex = 0; // メッセージ通知が見つかり、次の行が実際のSMSメッセージ内容の場合true bool nextLineIsMessage = false; void Reply() { // 関数開始 Serial.println("GPRS - Send SMS Test ..."); gprs.preInit(); delay(1000); while(0 != gprs.init()) { delay(1000); Serial.print("init error\r\n"); } Serial.println("Init success, start to send SMS message..."); if (ITemp == true) { float t = dht.readTemperature(); temp = t; ITemp = false; } MyString = String(temp, 0); // floatをStringに変換 MyString = (MyString + " Degrees C"); // Stringをchar配列に変換開始 int str_len = MyString.length() + 1; char char_array[str_len]; MyString.toCharArray(char_array, str_len); // Stringをchar配列に変換終了 gprs.sendSMS("04++++++++", char_array); // 電話番号とテキスト } // 関数終了 void setup() { Serial.begin(9600); Serial.println("DHTxx test!"); dht.begin(); gprs.preInit(); delay(1000); while(0 != gprs.init()) { delay(1000); Serial.print("init error\r\n"); } // SMSモードをASCIIに設定 if(0 != gprs.sendCmdAndWaitForResp("AT+CMGF=1\r\n", "OK", TIMEOUT)) { ERROR("ERROR:CNMI"); return; } // 新着SMSメッセージ通知のリスニング開始 if(0 != gprs.sendCmdAndWaitForResp("AT+CNMI=1,2,0,0,0\r\n", "OK", TIMEOUT)) { ERROR("ERROR:CNMI"); return; } Serial.println("Init success"); } void loop() { delay(2000); // 測定間隔を数秒空ける // 温度/湿度読み取りには約250msかかる // センサー読み取り値は最大2秒前のもの(非常に遅いセンサー) float h = dht.readHumidity(); float t = dht.readTemperature(); Serial.print("Humidity: "); Serial.print(h); Serial.println(" %\t"); Serial.print("Temperature: "); Serial.print(t); Serial.println(" *C "); SIM(); } void SIM() { digitalWrite(LED_PIN, ledStatus); Serial.println("Looking for SMS"); // SIM800からシリアル出力がある場合 if(gprs.serialSIM800.available()) { char lastCharRead = gprs.serialSIM800.read(); // \rまたは\nに達するまで文字を読み取り(行末) if(lastCharRead == '\r' || lastCharRead == '\n') { String lastLine = String(currentLine); // 最後の行が+CMT(新着SMS通知)で始まる場合 if(lastLine.startsWith("+CMT:")) { Serial.println(lastLine); nextLineIsMessage = true; } else if (lastLine.length() > 0) { if(nextLineIsMessage) { Serial.println(lastLine); // メッセージ内容を読み取り、SMS内容に応じてステータス設定 if(lastLine.indexOf("InTemp") >= 0) { Serial.println("InTemp"); ITemp = true; Reply(); } nextLineIsMessage = false; } } // 次の行読み取り用にchar配列をクリア for(int i = 0; i < sizeof(currentLine); ++i) { currentLine[i] = (char)0; } currentLineIndex = 0; } else { currentLine[currentLineIndex++] = lastCharRead; } } }
回路図

製造プロセス
- 温度制御ファンサーキット:メディア家具冷却用DIYリレーシステム
- 5ドルI2C温度センサーで作るRaspberry Pi温度ロガー
- Raspberry Pi 2でDS18B20温度センサー読み取りガイド
- Raspberry PiとDS18B20によるプロフェッショナルな温度監視
- Raspberry PiでMaxim 1-WireセンサーとDS2482 I2Cブリッジを用いた温度測定
- Raspberry Piでサーバークローゼットの温度を正確に監視
- 初心者向けIoTチュートリアル:Raspberry Piから温度データをストリーミング
- Raspberry Piでネットワーク対応ラボ気象観測所を構築
- Raspberry Pi、MCP9808、InfluxDB、Grafanaで作る家庭温度モニター
- Windows IoT Core搭載RoverをRaspberry Pi 2で構築 - 初心者から上級者まで
- AuGe12:プレミアム金基軟ろう合金