Arduino:家電製品のIR制御

こんにちはhabrachitatel! 私の名前はコンスタンティンであり、プログラマーです。つまり、スマートホームシステムのプログラミングに携わっています。

この分野での4年間の仕事で、ホームオートメーションの問題を解決するための多くの興味深いコントローラーとソフトウェアを試す機会がありました。 私が対処しなければならなかった最も興味深いデバイスの1つは、IP2IRシリーズのグローバルキャッシュデバイスです。 その目的は、クライアントからテキストコマンドを受信し、赤外線スペクトルのLEDを介して送信することです。

このようなデバイスを使用すると、一度にいくつかの方法でユーザーの生活が簡素化されます。



もちろん、このようなおもちゃは人生を簡素化しますが、私の記憶が適切であれば、3つのデバイスを管理するGlobalCacheは約6000〜7000ルーブルの費用がかかります。 非常に人道的な価格設定ではないため、このようなデバイスを独自に実装することが決定されました。



正直に言うと、このアイデアは長い間存在していましたが、私は回路設計者やMKプログラマーの経験がありません。一般的に、これらの考慮事項から、Arduinoプラットフォームは独自の開発環境で選択されました。 ウェブのオープンスペースを検索すると、IRRemoteと呼ばれる既成のソリューションが得られました。このモジュールが明らかに必要なものではなく、単一の出力で動作するように調整されていることを発見したとき、どのように発想しましたか? 。



理論は単純ですが、メーカーは独自のプロトコルを使用してコマンドを記述するのが好きですが、すべて同じデータ転送の原則に基づいています。 一部のサイトでは、デバイスのコマンドをHEXまたはProntoHEX形式で見つけることができますが、これは基本的に同じものです。

HEX形式のコマンドは次のとおりです。0000FREQ CNT1 CNT2 ON_1 OFF1 ON_2 OFF2 ON_n OFFn。

一番下の行は次のとおりです。

  1. 0000は常に4つのゼロですが、ここでは最初の2つのゼロを使用してコードの繰り返し回数を置き換えます。2番目の2つのゼロはarduinoの出力番号になります。 したがって、コード010D-コマンドを2回繰り返し、出力13(LEDが組み込まれたもの)に送信します。
  2. FREQ-基準信号周波数。 通常、35〜40 kHzの範囲で、巧妙に記述されています-36 kHz = 0073 = 115、10進数115が36 kHzの周波数を与える理由はあまり明確ではありません。これは4145 / FREQのように計算できるとしか言えません。
  3. CNT1は最も必須の部分ではありません。無視します。
  4. CNT2-下のリンクに興味がある人は無視します。
  5. ON-しかし、これはデータです。 これは、IRダイオードで「点滅」するときの基準周波数での周期の数です。
  6. OFF-これは、レッグで論理ゼロを維持する期間の数です。


この理論を注意深くお読みにならないように、上記を簡単に説明します。

赤外線信号の理論の図

さて、理論を理解したら、プログラミングを始める時です。新しい獣を使い始めたときに生じたすべての困難については説明しません。おそらく、以下から始めます。

arduino環境の一部として、特別な機能トーン(ピン、周波数、持続時間)があり、入力/出力ポートで信号を生成します-タイマー割り込みを使用して、特定の周波数でデューティサイクルが50%の長方形の「波」です。

この機能を使用して、作業バージョンをすばやく作成し、結果の精度を高めたかったので、Tone.cppファイルを\ Arduino \ hardware \ arduino \ cores \ arduino \ディレクトリにコピーし、IR_Gen.cppに名前を変更しました。 次に、結果のファイルで、不足している変数を宣言し、不要な変数を削除しました。 トーン関数はstartIR(周波数)関数に変更されました。この関数はどこにも宣言されておらず、このファイル内でのみ使用できます。

以前のトーン()(startIR())を呼び出すsendIR(char ir_string [])およびsendLastIR()の2つの宣言された関数が追加されましたが、変調を開始する前に、sendIRに渡される行がセットであることを確認してくださいこのために、ParseIRString関数がオンになったIRコマンドのデータ。データがIRコマンドの形式と一致しない場合はゼロを返し、データが一致する場合は基準周波数の値を返します。 文字列の解析がどのように発生するかが明確になるように、念のためコードを提供します。

unsigned int ParseIRString(char IRString[]){ byte xBool = 0; unsigned int bInt = 0; ir_data_array_length = 0; unsigned int IR_Frequency = 0; unsigned int IR_String_Length = 1024; char Separator = ' '; unsigned int i = 5; char bChArr[4] = {0}; byte NumSys = 16; ir_out_pin = 255; if(IRString[0]=='s'){ //    Global Cache ir_out_pin = (((IRString[7]-48)*3)-(3-(IRString[9]-48)))-1; bChArr[0] = IRString[19]; bChArr[1] = IRString[20]; bChArr[2] = IRString[21]; bChArr[3] = '\r'; ir_repeat_count = StrToInt(bChArr,10)-1; Separator = ','; i = 13; NumSys = 10; }else{ //    HEX bChArr[0] = IRString[3]; bChArr[1] = IRString[4]; bChArr[2] = '\r'; ir_out_pin = StrToInt(bChArr,16); bChArr[0] = IRString[0]; bChArr[1] = IRString[1]; ir_repeat_count = StrToInt(bChArr,16); } if ((ir_out_pin>13)||(ir_out_pin<0)){return 0;} for (i; i<IR_String_Length; i++){ if((IRString[i]>='a')&&(IRString[i]<='f')){IRString[i]-=32;} //UpperCase if((IRString[i] != Separator)&&(IRString[i] != '\r')){ // ,    if((IRString[i]>47)&&(IRString[i]<58)){ //   bInt = bInt * NumSys + (IRString[i] - 48); //  }else{ if ((IRString[i]>='A')&&(IRString[i]<='F')&&(NumSys==16)){//  A  F bInt = bInt * NumSys + (IRString[i] - 55); //  }else{ return 0; } } }else{ if(IR_Frequency==0){ if(NumSys==16){ //  HEX IR_Frequency = (4145/bInt)*1000; //   }else{ // Global Cache IR_Frequency = bInt; //   } xBool++; }else{ if(xBool>2){ ir_data_array[ir_data_array_length]=bInt*2; //  ir_data_array_length++; }else{ xBool++; } } bInt = 0; if(IRString[i] == '\r'){Serial.println(IR_Frequency,DEC); return IR_Frequency;} } } }
      
      





次に、目的のためにタイマー割り込みを修正します。その結果、次のようになります。

 ISR(TIMER2_COMPA_vect){ if (ir_data_array[ir_data_current_step] > 0){ if(ir_data_current_step%2==0){ *timer2_pin_port ^= timer2_pin_mask; // }else{ *timer2_pin_port &= ~(timer2_pin_mask); //  } ir_data_array[ir_data_current_step]--; }else{ ir_data_array[ir_data_current_step] = ir_data_buffer; ir_data_current_step++; ir_data_buffer = ir_data_array[ir_data_current_step]; } if (ir_data_current_step == ir_data_array_length){ if(ir_repeat_count>0){ ir_repeat_count--; ir_data_current_step = 0; }else{ stopIR(tone_pins[0]); } } }
      
      







この祭典の最後に、Arduino.hファイルで、新しく作成された関数byte sendIR(char ir_string [])を宣言する必要があります。 バイトsendLastIR(); そして出来上がり、それは帽子です。 その結果、家庭用電化製品を制御する既製のツールを含む、少し拡張されたarduino環境ができました。

誰もが開発環境で何かを修正することを好むわけではないことを知っていますが、正直なところ、それはより便利であり、最終的には、サードパーティのモジュールによって単純に行われることを妨げるものはありません。



関連情報:

グローバルキャッシュWebサイト

グローバルキャッシュデバイスAPI PDF

トーン機能に関するロシアのヘルプ

好奇心のために約束したように、ext。 赤外線管理に関する情報

有名なIRRemoteライブラリ



All Articles