サーバールームのエアコンが2回連続して故障し、その後数日間にわたって部屋が過熱した後、その部屋の温度を監視することについて疑問が生じました。 IPMI制御インターフェースを使用して、サーバーに組み込まれた温度センサーから毎日(毎時/毎分)温度を監視することが可能です。 しかし、この場合、この場合、すべてをより良く自動化することが可能であるという否定的な認識を発揮する人的要因があります。 たまたま、マイクロコントローラのような非常に興味深いことに興味を持つようになったので、MKを使用した自動化タスクは、世界に役立つプロジェクトで蓄積された知識を実現する新しい興味深い機会でした。
使用されるデバイスとツールの一般的なスキーム。
基礎として、Arduinoボードの1つを採用することが決定されました。 中国のカウンターパートの価格は低く、必要なMKストラップはすべてモジュールに既にコンパクトに配置されています。 もともとは、Arduino Pro + DHT22を使用することを目的としていました。 Arduino Pro-最も安価で、最小ですが、非常に機能的なボードとして。 DHT22-このセンサーは、安価なDS18B20とは対照的に、湿度も検出できるためです。 そして、それは私たちにとっても役に立つでしょう。 おもしろい偶然のために、サーバールームはトイレの隣にあります。トイレは、たとえば温度を上げることなく、周囲のすべてをあふれさせることができます。
このスキームでは、臨界温度または湿度を超える場合、MCはツイストペアケーブル(長さ約70m)を介してIT部門のオフィスに信号を送信する必要がありました。 さて、ここで彼らはブザーを鳴らし、近づいている黙示録を警告するあらゆる方法でマルチカラーLEDを点滅させています。 残念ながら、この単純なソリューションは、サーバールームとオフィスの間に(中間ハブのない)直接回線がないため、不適切であることが判明しました。
デバイスの最初のバージョンの写真:
次に、arduinoをUSB経由でコンピューターに接続し、UART経由で温度と湿度のデータを送信することにしました。 つまり、より洗練されたArduino Nano(MKで16 MHzのATMega328が必要)が必要です。 彼女はWindows 7で動作するコンピューターと通信する必要がありました。このコンピューターには、プログラムのサーバー部分をインストールする必要があります。温度と湿度。 当時、私はこのOS用のプログラムを書くためのツールを持っていなかったので、Windows用のソフトウェアを書くのに便利な環境を備えた人気のあるプログラミング言語にすぐに精通しなければなりませんでした。 私はC#に落ち着きました。 実際、MKのファームウェアはAVR Studio 6 Cで書かれています。
そのため、プロジェクトの実装中にDHT22センサーのCコードの例に関する情報を見つけられなかったため、この記事では彼との共同作業に集中することにしました。 また、記事の最後に、ソースへのすべてのリンクと、同様の問題を解決するために使用されるツールがあります。
DHT22センサーの操作について簡単に説明します。
主なパラメーター: | |
---|---|
電圧 | 3.3-6 V |
測定オプション | 湿度0-100%; -40〜80℃の温度 |
測定精度 | 湿度+ -2%(最大+-5%); 温度+ -0.5C |
測定時間 | 約2秒 |
ここで、MKのプログラムでは、約1秒ごとにセンサーに問い合わせます。 それは私のために働きます。 調査で問題が発生し始めたら、この期間を2秒に増やしてください。
弟のデータシートのピン配置と接続図:
センサーデータラインは4.7kΩ抵抗を介して電源に接続されます。つまり、センサーがサイレントまたは破損/欠落している場合、ライン上に論理ユニットが存在します。 センサーからの応答を受信するには、18 msでデータラインを地面に押し付ける必要があります。
センサーが応答すると、データの送信を開始します。 各ビットの送信は、50μsの低レベルで始まります。
合計で、40ビットまたは5バイトが送信されます。 データは、最上位バイトの最上位ビットから送信されます。
バイト5-湿度値の上位バイト 。
バイト4-湿度値の低バイト。
バイト3-温度値の上位バイト 。
バイト2-温度値の下位バイト。
バイト1-チェックサム。
さて、デバイス図:
センサーデータバスは、アルデュインのD2レッグに接続されています。 電源LEDがD4レッグに接続されています。 ちなみに、点滅している場合は、初期化中にセンサーがテストに合格しなかったこと、つまり検出されなかったことを意味します。
ファームウェアコードに移動します。
最初に、モジュールの簡単な説明。
UART_ATMEGA328.h
これは、UARTを介してメッセージを送受信するための機能を備えたモジュールです。 ちなみに、関数void send_int_Uart(int i)
含まれています。 整数の2バイトの符号付き数値を受け取り、それを文字列に変換して、UART経由で転送します。 この関数が使用されている場所を探しないでください-このプロジェクトでは役に立ちませんでした。
DHT11-22_def.h
センサー接続設定用のマクロが含まれています。 使用されるセンサーのモデルは、 _DHT22
またはその簡易バージョン_DHT11
ます。 センサーが接続されているポート、DDR、およびPIN。 そして、データラインが接続されているピン番号。 これらのマクロは、次のモジュールで使用されます。
DHT11-22.h
DHT22またはDHT11センサーを操作するための機能が含まれています。
DHT11-22_def.hモジュールコード:
#define _DHT22 /* . _DHT11 _DHT22. */ #define _PORT_DHT PORTD #define _DDR_DHT DDRD #define _PIN_DHT PIND #define _PINNUM_DHT 2 /* 0 */
DHT11-22.hモジュールコード:
#define F_CPU 16000000UL #include "DHT11-22_def.h" #define _MASK_DHT ( 0b00000001 << _PINNUM_DHT ) #define _PIN_DHT_GET ( (_PIN_DHT & _MASK_DHT)>>_PINNUM_DHT ) #define _PORT_DHT_SET(x) ( ((x)==0) ? (_PORT_DHT&= ~_MASK_DHT) : (_PORT_DHT|= _MASK_DHT) ) #define _DDR_DHT_SET(x) ( ((x)==0) ? ( _DDR_DHT&= ~_MASK_DHT) : ( _DDR_DHT|= _MASK_DHT) ) static unsigned char checkSum, packDHT[5]= {0,0,0,0,0}, dhtHighDuration=0, minLevel=0, maxLevel=0, dhtSplitLevel=0; static float temperature, humidity; float getTemp() { return temperature; } float getHum() { return humidity; } unsigned char getCheckSum() { return checkSum; } unsigned char getMinLevel() {return minLevel; } unsigned char getMaxLevel() {return maxLevel; } unsigned char getDhtSplitLevel() {return dhtSplitLevel; } static char initDHT() { // , 0. char dhtErr=0; _DDR_DHT_SET(1); _PORT_DHT_SET(0); _delay_ms(19); asm("cli"); _DDR_DHT_SET(0); _PORT_DHT_SET(1); _delay_us(10); if (!_PIN_DHT_GET) dhtErr = 1; _delay_us(22); if ( (_PIN_DHT_GET)&&(!dhtErr) ) dhtErr = 2; _delay_us(88); if ( (!_PIN_DHT_GET)&&(!dhtErr) ) dhtErr = 3; _delay_us(77); if ( (_PIN_DHT_GET)&&(!dhtErr) ) dhtErr = 4; return dhtErr; } static void DhtMinMaxCalc() { // . dhtSplitLevel. dhtHighDuration= 0; // , . while ( !_PIN_DHT_GET ) _delay_us(1); while ( _PIN_DHT_GET ) { _delay_us(1); dhtHighDuration++; } if (minLevel > dhtHighDuration) minLevel= dhtHighDuration; else if (maxLevel < dhtHighDuration) maxLevel= dhtHighDuration; } unsigned char calibrateDHT() { // dhtSplitLevel. 1, 0. if ( initDHT() ) { // asm("cli"); asm("sei"); return 0; } for ( char bit=0; bit < 40; bit++) DhtMinMaxCalc(); asm("sei"); dhtSplitLevel= (minLevel + maxLevel) / 2; // dhtSplitLevel - , , , 1. return 1; } static char getDhtBit() { // . dhtHighDuration= 0; // , . while ( !_PIN_DHT_GET ) _delay_us(1); while ( _PIN_DHT_GET ) { _delay_us(1); dhtHighDuration++; } if ( dhtHighDuration < dhtSplitLevel ) return 0; return 1; } //############################################### #if defined _DHT11 static void calcResults() { // humidity, temperature, checkSum DHT11. temperature= packDHT[2]; humidity= packDHT[0]; checkSum= packDHT[4]; } //############################################### #elif defined _DHT22 static void calcResults() { // humidity, temperature, checkSum DHT22. temperature= packDHT[3]*0.1 + (packDHT[2] & 0b01111111)*25.6; if (packDHT[2] & 0b10000000) temperature*= -1; humidity= packDHT[1]*0.1 + packDHT[0]*25.6; checkSum= packDHT[4]; } #endif //############################################### unsigned char readDHT() { // 1, , 0. if ( initDHT() ) { // asm("cli"); asm("sei"); return 0; } for (unsigned char byte=0; byte < 5; byte++) { // . packDHT[byte] = 0; for ( char bit=0; bit < 8; bit++) packDHT[byte]= (packDHT[byte] << 1) | getDhtBit(); } asm("sei"); calcResults(); return 1; }
コードに関するコメント。
1.チェックサム分析を追加しませんでしたが、変数checkSum
に保存します。
2.データバスの高レベル期間の期間を計算して受信ビットの値を決定するとき、MKタイマーを使用せずに実行することを決定しました。 しかし、彼は最短の高レベル期間(ビット0が送信されるとき)と最長の高レベル期間(ビット1が送信されるとき)の間の算術平均値を含むdhtSplitLevel
変数を計算する、 unsigned char calibrateDHT()
関数を追加しました。 さらに、この変数は、センサーへの後続の呼び出し中にデータビットの値を決定するために使用されます。
3.プロジェクトで安価なDHT11センサーを使用するには、 DHT11-22_def.h
代わりにDHT11-22_def.hモジュールで指定する必要があります。 確かに、彼との仕事は彼の不在のためにテストに失敗しました。
使用例:
int main() { // ... char st[6]; _delay_ms(999); calibrateDHT(); while(1) { _delay_ms(999); if ( !readDHT() ) continue; itoa( getTemp(), st, 10); // st . // st UART, LCD - ... itoa( getHum(), st, 10); // st . // st UART, LCD - ... } }
最後に、結果のデバイスの写真とビデオ:
リソース:
- arduinoに.hexを記録するには、プログラムXloader v1.00を使用しました
- デバッグおよびテスト中にUARTを介してメッセージを送受信するには、 Br @ y ++のプログラムTerminal v1.9bを使用しました
- Arduino Nano(ATMega328、16 MHz)用の既製ファームウェア、Windows用のサーバーとクライアント、および回路基板( リンク )
- ファームウェアコード
- サーバーコード
- 顧客コード