そのような需要がある場合、DHT22を使用して定期的に温度と湿度を検出し、結果をGSMモジュール付きの指定された携帯電話に送信します。
Arduinoの場合、DHT22を使用して温度と湿度を検出することは難しくありません。チップのシリアルポートを介してGSM ATコマンドを送信することも非常に簡単です。最も重要な技術的ポイントは、ArduinoでプレーンテキストのメッセージコンテンツをPDUにエンコードする方法です。しかし、この作品はArduinoの長所ではありません。実装するには複雑すぎる記事をインターネットで見つけました。
コードを簡略化するために、送信するショートメッセージのコンテンツを他の方法で「テンプレート」として事前に保存し、送信時にコンテンツの一部のみを置き換えることはできますか?
たとえば、テキストメッセージの形式は次のようにのみ指定できるとします。
温度:12.3 ℃;湿度:45.6%
(これらの中で、実際の測定値に応じて動的に変更できるのは温度値と湿度値のみであり、これらの値は負の数にすることはできません。小数点以下1桁を予約する必要があり、整数部分は0〜99の値の範囲を取ります)
C#で書かれたコードのピースがこのメッセージを生成所有する:(スペースで読みやすくするため、実際にはありません)
089 168 BADCFEHGJIFK 11000D9168 badcfehgjiFk 0008FF 26 6E295EA6FF1A 0031 0032 002E 0033 00202103FF1B6E7F5EA6FF1A 0034 0035 002E 0036 0020FF05
53
厚い下付き文字で部品を説明してください。「BADCFEHGJIFK」はコード化されたSMSセンター番号を指し、「badcfehgjiFk」はコード化された受信機の携帯電話番号を指します。元のセンター番号はABCDEFGHIJK(11桁、86プレフィックスは不要)であり、元の受信携帯電話はabcdefghijk(11桁、同じ86プレフィックスは不要)です。コーディング規則は非常にシンプルで、携帯電話番号の長さが単数の場合は、末尾にFを追加して2つにまとめ、奇数ビットと偶数ビットの位置を入れ替えます。ABCDはBADCになります。例:上海ユニコムのSMSセンターの番号は13010314500であるため、エンコード後は3110304105F0になり、このテキスト文字列は実際の送信の代わりに使用されます。
53は、at + cmgs = XXコマンドを送信するときに使用する必要があるものです。サンプルのSMSでは、この値は53として計算されます。温湿度の整数部が一桁の場合、値は49、一桁、二桁は51となります。もう1つ注意すべき点は、0008FFの後の26(ユーザー情報の長さ)です。温度と湿度の整数部が一桁の場合は22、一桁二桁は24になります。
残りは扱いやすいです。ノート0031 0032 002E 0033および0034 0035 002E 0036。この記事の例では、これは単純で大まかな置換関係と見なすことができます。0030は「0」、0031は「1」、0032は「2」に対応します。。。類推すると、0039は「9」に対応します。002Eは小数点に相当します。したがって、これはコード化された12.3および45.6です。
このようにして、SMSの一般的なフレームワークを設定し、実際のコンテンツを値に応じてカスタマイズして、シリアルポート経由で送信できます。
AT + CSCS = "GSM"は
正常に "OK"を返します
AT + CMGF = 0は
正常に "OK"を返します
AT + CMGS = lengthは
正常に ">"を返します(数値スペースより大きい)これで
PDU形式のメッセージを送信し、最後に送信できます0x1Aはターミネータとして使用されます。OKに正常に戻り、プロセス全体が終了します。
テストとして、この記事では、最初に戻り値が脳なしで送信されるかどうかに関係なく、各シリアルポートの送信が成功することを前提としています。
// DHT sensor library by Adafruit
// 库管理中搜索上述库,安装后直接使用
#include "DHT.h"
#define DHT22_PIN A0 // DHT22的数据线接A0
#define DHTTYPE DHT22
#define LEDPIN 13
DHT dht(DHT22_PIN, DHTTYPE);
String codedCenterNumber = "3110304105F0"; // 编码后的上海联通
String codedMPNumber = "31********F0"; // 编码后的接收短信手机号码
void setup() {
pinMode(LEDPIN, OUTPUT);
digitalWrite(LEDPIN, HIGH);
dht.begin();
// 亮5.5秒灯以示正在初始化
// 然后灭灯
Serial.begin(115200, SERIAL_8N1);
delay(5000);
Serial.println("at");
delay(500);
Serial.flush();
digitalWrite(LEDPIN, LOW);
}
int i = 0;
void loop() {
if (i == 1)
{
float t = dht.readTemperature();
float h = dht.readHumidity();
SendSMS(t, h);
}
i++;
// 修改此判断数值以改变发送频次
if (i == 60)
i = 1;
delay(60000);
}
// =======================
void SendSMS(float tVal, float hVal)
{
String cmgs = "";
String smsPDU = "";
if (tVal < 10.0 && hVal < 10.0)
{
cmgs = "AT+CMGS=49";
smsPDU = GetPDU(codedCenterNumber, codedMPNumber, GetPDUFormatValue(tVal), GetPDUFormatValue(hVal), "22");
}
if (tVal >= 10.0 && hVal >= 10.0)
{
cmgs = "AT+CMGS=53";
smsPDU = GetPDU(codedCenterNumber, codedMPNumber, GetPDUFormatValue(tVal), GetPDUFormatValue(hVal), "26");
}
if ((tVal < 10.0 && hVal >= 10.0) || (tVal >= 10.0 && hVal < 10.0))
{
cmgs = "AT+CMGS=51";
smsPDU = GetPDU(codedCenterNumber, codedMPNumber, GetPDUFormatValue(tVal), GetPDUFormatValue(hVal), "24");
}
digitalWrite(LEDPIN, HIGH);
Serial.println("AT");
delay(500);
Serial.flush();
Serial.println("AT+CSCS=\"GSM\"");
delay(500);
Serial.flush();
Serial.println("AT+CMGF=0");
delay(500);
Serial.flush();
Serial.println(cmgs); //
delay(500);
Serial.flush();
Serial.print(smsPDU);
delay(500);
Serial.flush();
Serial.write(0x1a);
delay(500);
Serial.flush();
digitalWrite(LEDPIN, LOW);
}
/*
// 如您喜欢,可以直接拨打手机
// 当然,通话是不可能通话的
void CallMP(String MP)
{
digitalWrite(LEDPIN, HIGH);
Serial.println("at");
delay(500);
Serial.flush();
Serial.println("atd" + MP);
delay(500);
Serial.flush();
digitalWrite(LEDPIN, LOW);
}
*/
// 短信中心和手机号码都不需要加86前缀
String GetPDU(String codedCenterNumber, String codedMpNumber, String tValue, String hValue, String len)
{
String rtn = "";
rtn += "089168";
rtn += codedCenterNumber;
rtn += "11000D9168";
rtn += codedMpNumber;
rtn += "0008FF" + len + "6E295EA6FF1A";
rtn += tValue;
rtn += "00202103FF1B6E7F5EA6FF1A";
rtn += hValue;
rtn += "0020FF05";
return rtn;
}
// 数值转变为PDU需要的形式
String GetPDUFormatValue(float val)
{
String rtn = "";
String v = String(val, 1);
for (int i = 0; i < v.length(); i++)
{
char c = v.charAt(i);
switch (c)
{
case '0':
rtn += "0030";
break;
case '1':
rtn += "0031";
break;
case '2':
rtn += "0032";
break;
case '3':
rtn += "0033";
break;
case '4':
rtn += "0034";
break;
case '5':
rtn += "0035";
break;
case '6':
rtn += "0036";
break;
case '7':
rtn += "0037";
break;
case '8':
rtn += "0038";
break;
case '9':
rtn += "0039";
break;
case '.':
rtn += "002E";
break;
default:
break;
}
}
return rtn;
}
最終的な効果を図に示します。