最近では、ガーデニングと名前を変えて園芸ブームのようです。育成する品種によって、温度、湿度、日当たり、風通し、水やり、肥料などの要素を上手にコントロールしていく必要があり奥が深いものです。本章では、KARACRIXを使用して温度、水やりを制御するシステムの構築を行います。基本機能に加えて、KARACRIXの画像記録機能を活用して植物の生育の画像記録を行なうと同時に、ブロードバンドによるインターネット環境を活用して生育の状況を定時にEメールの添付画像で取得できる高機能なシステムになっています。また、温度が上限を超えた場合に警報をEメールで発信する機能も付加しています。
本章は、AI(アナログ)とIMG(画像)オブジェクトを扱った制御プログラムの応用例です。
またここでは、UNIX系システムの基本機能としての複数の処理を同時に並行して行なうマルチタスク処理を、アプリケーションのレベルで実感していただくことも目標にしています。
システム構成は、温度、湿度、日射量をセンサで取得して、換気扇のON/OFF制御を行います。画像入力用のCCDカメラとEメール送信を行うためのブロードバンド接続用の環境を用意して、温度が換気扇でコントロールできる上限値を超えた場合には警報ブザーを鳴らすと共に、Eメールで警報メールを発信します。植物の生育過程を画像記録すると同時に、毎日定時にEメールで観察画像を受け取ることができます。
計測制御ユニットには、KCXH-IOB30RTAを使用しています。このユニットは、8点のアナログ入力が可能なアナログデジタルI/O装置ですが、ここでは、温度、湿度、光の3点のセンサ入力を使用します。
温度センサは、半導体センサのLM35DZ(NS社製)です。0〜100℃を1℃当たり10mVの電圧出力をおこなうもので、25℃では250mV(0.25V)が出力されます。
湿度センサには、相対湿度検出型の高分子センサでCHS-UGS(TDK製)です。このセンサは、相対湿度0〜100%で1Vを出力するもので直線性もすぐれておりアンプ内蔵で扱いやすいものです。
光センサは、Cds素子を使用しています。光量に応じて抵抗値が変化しますが、これを約0-2.5V以内の電圧変化に変換して取り込んでいます。Cdsの特性に応じて負荷抵抗を適当に選択して下さい。
写真6.1 センサの接続
温度制御は、換気扇で行います。換気扇の電源をリモコンコンセントから供給して、ON/OFFを行います。リモコンコンセントへの制御端子を計測制御ユニットにつなぎます。
|
|
水やりの制御は、市販の園芸用給水ポンプ((株)カクダイ “みずやりくん” 5029)で行うことにします。この製品には、元々1日2回まで自動給水できるコントローラが付属していますが、KARACRIXでコントロールするため付属コントローラはあえて使用しません。給水ポンプの部分だけ使用しています。この給水ポンプはDC6V駆動で、今回は写真6.5のような簡単な電池ボックスに単一乾電池4本をいれ電源供給してみました。
写真6.4 給水ポンプ |
|
センサ、アクチュエータからの配線は、KCXH-IOB30RTAの端子台に接続しています。端子台とKCXH-IOB30RTAの入出力コネクタ間は、フラットケーブルで接続しています。
写真6.6 端子台とKCXH-IOB30RTAの配線
CCDカメラは、NTSC信号形式の出力を持つものを入手してPCのビデオキャプチャカードまでビデオケーブルを配線する必要があります。また、カメラの電源が別途必要になりますので設置場所まで電源の配線も必要です。ここでは、ビデオ信号と電源を一緒に供給できるケーブルを使用しました。カメラは、秋葉原やホームセンターなどで入手できる小型CCDカメラを使用しています。
CCDカメラからの画像入力で植物の生育の様子を監視します。ビデオキャプチャカードのデバイスドライバは、正しく設定されているものとします。
写真6.7 CCDカメラ |
|
システムの全体配線図を以下に示します。
図6.2 システム配線図
計測制御ユニットとPCをHUBを使用して接続している例を写真6.9に示します。
ブロードバンドルーターは、10/100BASE-TのHUB内臓でインターネットからアクセスするための仮想サーバー機能を持っているものを想定しています。KARACRIXサーバPC機、KCXH-IOB30RTAとの接続は、10/100BASE-Tのケーブルで接続します。ADSLモデムとブロードバンドルーター、NTT回線の接続の仕方は、本マニュアル「1章 基礎知識」を参考にして下さい。
ここでは、「温度センサ」「湿度センサ」「光センサ」「換気扇」「警報ブザー」「水やりポンプ」「観察用CCDカメラ」をオブジェクトとして扱います。
各オブジェクトに名前をつけておきましょう。 また、これらのオブジェクトの種類も分類しておきます。
|
|
|
|
温度センサ | aif01 | 室内温度 | AI.f(アナログ実数値入力) |
湿度センサ | aif02 | 室内湿度 | AI.f(アナログ実数値入力) |
光センサ | aif03 | 日射量 | AI.f(アナログ実数値入力) |
換気扇 | bo01 | 換気扇 | BO(バイナリ出力) |
警報ブザー | bo02 | 警報ブザー | BO(バイナリ出力) |
水やりポンプ | bo03 | 給水ポンプ | BO(バイナリ出力) |
観察用CCDカメラ | img01 | CCDカメラ | IMG(イメージ入力) |
「温度センサ」「湿度センサ」「光センサ」をaif01〜aif03に割り当てます。オブジェクト名、フォーマット、単位、上限値、下限値を変更します。フォーマットは、監視パネル上で表示される数値表示形式です。C言語の
printf文の書式フォームと同様の設定イメージです。 単位は、計測データの性質に合わせて設定します。
上限値、下限値は、各種センサの計測値のレンジを入力します。ここで使用した温度センサ「LM35D」の計測レンジは、0〜100℃ですので上限値に100、下限値に0を設定します。
また湿度センサ「CHS-UGS」の計測レンジは、0〜100%ですので上限値に100、下限値に0を設定します。
光センサの出力電圧は、0-2.5Vを取るように抵抗値を適当に調整しています。今回使用したものは4.7kΩを2本使用して分圧して取り込んでいます。Cdsは光の量に対してリニアな特性ではありませんので、実用的に使用するには補正回路を組む必要がありますが、本例では値に厳密な意味を持たせず目安程度に考えて入力電圧0〜2.5Vで表示することにして上限値に2.5、下限値に0を設定しました。
アクチュエータの「警報ブザー」「換気扇」「水やりポンプ」をbo01〜bo03に割り当て、オブジェクト名、フォーマットを変更します。
観察用CCDカメラは、img01に割り当てています。
以上で、登録は終了です。
ここで、以上の設定をシステムに反映させるために、「オブジェクト登録」画面で“END”ボタンを選択して「メインメニュー」へ戻り、KARACRIXコンソールの “RST”ボタンを選択してKARACRIXをリセットさせて下さい。しばらくするとKARACRIXが自動的に再起動されます。
[バイナリ出力]
|
[アナログ入力]
|
画像記録方式には、ワンウェイ記録とエンドレス記録の2方式がありますが、本章のシステムでは植物の生育を観察記録として保存しますので、ワンウェイ記録を選択して下さい。(KaracrixBuilderユーザーズマニュアル 「16章 システム環境の設定」→「16.5 画像記録方式の設定」参照)
図6.4 画像記録方式の設定例
また、観察画像の記録のタイミングは“サンプリング時間設定”で決めることができますが、今回は、記録のタイミングをプログラムから任意にコントロールしてみましょう。プログラムからコントロールするために“自動制御記録ボタン”を選択して下さい。以下に設定例を示します。
図6.5 画像記録設定を自動制御記録モードに設定
「制御プログラム登録」画面を選択して、計測制御通信プログラムの編集を行います。 計測制御ユニットKCXH-IOB30RTA用の、計測制御通信プログラムの編集については、本マニュアル「3章 テストシステムで学ぶKARACRIX入門」で紹介していますのでそちらを参照してください。
●計測制御通信プログラムの編集
計測制御ユニットのIPアドレスとポート番号を編集します。(本マニュアル3章
参照)
センサの入力電圧のレンジを調整します。
センサ入力レンジ | オブジェクトのレンジ | |
温度センサ | 0〜1V | 0〜100℃ |
湿度センサ | 0〜1V | 0〜100%(CHS-UGSの場合有効範囲5〜95%) |
光センサ | 0〜2.5V | 0〜100% |
通信プログラムのレンジ調整部を下記のように編集することでセンサの入力レンジを合わせます。これは、KCXH-IOB30RTAの入力レンジの設定を0-2.5Vで初期化して設定している場合です。KCXH-IOB30RTAの入力精度は、アナログデータの取込み周波数により変わりますがデフォルトでは、16ビットの精度になっています。
以下の例では、CH1、CH2に温度、湿度センサを接続する場合、0〜1Vの入力電圧を2.5倍してフルレンジ2.5Vのスケールに換算しています。
CH3は入力電圧が0〜2.5Vで来るように調整していますので、パーセント表示するための処理だけ行っています。
/* CH1アナログ値の取込(0〜1Vレンジ) */ aidata = strtol( ai1chanel, (char **)NULL, 10 ); aival = (float)aidata / (float)65536 * 2.5 * 100.; ← センサの入力レンジの計算 kcxobj_stat_fwt( objid_aif01, aival ); /* CH2アナログ値の取込(0〜1Vレンジ) */ aidata = strtol( ai2chanel, (char **)NULL, 10 ); aival = (float)aidata / (float)65536 * 2.5 * 100.; kcxobj_stat_fwt( objid_aif01, aival ); /* CH3アナログ値の取込(0〜2.5Vレンジ) */ aidata = strtol( ai3chanel, (char **)NULL, 10 ); aival = (float)aidata / (float)65536 * 100.; kcxobj_stat_fwt( objid_aif01, aival );
編集をしたら、“コンパイル”ボタンを押してプログラムの実行モジュールを作成します。正常にコンパイルが終了したら“ENT”ボタンで「制御プログラム登録」画面に戻ります。
監視パネルをつぎのように作成しました。
監視パネルの作成手順については本マニュアル4章を参考にして下さい。
図6.6 水やりシステム監視パネル(上:CAD画面 下:監視パネル)
本システムでは、室内温度を計測して設定温度によって換気扇をON/OFF制御する温度制御、設定上限温度を超えている場合に警報ブザーを鳴らしかつEメールを送信する温度上限警報制御、毎日決められた時刻に植物に水やりを行う水やり制御、毎日決められた時刻に指定アドレスに観察画像を添付したEメールを送信する定時Eメール送信制御、そして毎日決められた時刻に画像記録を行う定時画像記録制御の5つの処理を構成してみたいと思います。
かなりたくさんの機能を盛り込んでいますので、1本のプログラムで構成すると複雑になることが予想されます。そこで今回は、機能ごとにタスクをわけて構成する手法を取りました。機能別にタスクを独立させることにより各プログラムがシンプルになり、システム全体の見通しも良くなります。また、修正やデバックも機能別に行うことができるようなるため容易になります。
タスク1 | ctl02 | 園芸水やりシステム起動プログラム |
タスク2 | ctl03 | 温度制御プログラム |
タスク3 | ctl04 | 温度上限警報制御プログラム |
タスク4 | ctl05 | 水やり制御プログラム |
タスク5 | ctl06 | 定時Eメール送信制御プログラム |
タスク6 | ctl07 | 定時画像記録制御プログラム |
園芸水やりシステム起動プログラム(タスク1)は、機能毎に独立して同時並行して動作するタスク2〜6を一度に起動させる親タスクとして機能します。
図6.7に全体フローを、図6.8、6.9、6.10、6.11、6.12に各処理のフローを示します。
図6.8 温度制御処理フロー図 |
図6.9 上限温度警報制御処理フロー図 |
図6.10 水やり制御処理フロー図 |
図6.11 定時Eメール制御処理フロー図 |
|
それでは、処理フロー図をもとにプログラミングをしてみましょう。
「メインメニュー」から “制御プログラム”ボタンを選択して「制御プログラム登録」画面を表示して下さい。
タスク1の園芸水やりシステム起動の登録は、No.2 のctl02オブジェクトに、
タスク2の温度制御プログラムの登録は、No.3 のctl03オブジェクトに、
タスク3の温度上限警報プログラムの登録は、No.4 のctl04オブジェクトに、
タスク4の水やり制御プログラムの登録は、No.5 のctl05オブジェクトに、
タスク5の定時Eメール送信プログラムの登録は、No.6 のctl06オブジェクトに
タスク6の定時画像記録プログラムの登録は、No.7 のctl07オブジェクトにそれぞれ登録してください。
図6.13 制御プログラム登録
以下で、各タスクの主要部分についてアルゴリズムの説明をしていきます。
● 園芸水やりシステム起動プログラム [タスク1(objid=ctl02)]
21-25行目で、温度制御(ctl03)、温度上限警報(ctl04)、水やり制御(ctl05)、定時Eメール送信(ctl06)
、定時画像記録(ctl07)の各プログラムオブジェクトIDを取得しています。
29-33行目で、これらプログラム起動しています。また、起動されたプログラムは、本起動プログラムとは無関係に独立して同時並列稼動(マルチタスク処理)していきます。
37行で本プログラムは終了し役割を終えます。
1 2 /*= [タスク1(objid=ctl02)] 各プログラム(タスク)起動用プログラム =*/ 3 4 #include5 6 main( argc, argv ) 7 int argc; 8 char *argv[]; 9 { 10 int ondo_ctl_objid; /* 温度制御プログラム起動オブジェクトID */ 11 int ondo_alm_objid; /* 温度上限警報プログラム起動オブジェクトID */ 12 int mizu_ctl_objid; /* 水やり制御プログラム起動オブジェクトID */ 13 int email_ctl_objid; /* 定時Eメール送信プログラム起動オブジェクトID */ 14 int gazou_ctl_objid; /* 定時画像記録プログラム起動オブジェクトID */ 15 16 /* KARACRIXライブラリの初期化(先頭に必須) */ 17 kcxinit( argc, argv ); 18 19 20 /* プログラムオブジェクトIDの取得 */ 21 ondo_ctl_objid = kcxobj_open( "ctl03" ); 22 ondo_alm_objid = kcxobj_open( "ctl04" ); 23 mizu_ctl_objid = kcxobj_open( "ctl05" ); 24 email_ctl_objid = kcxobj_open( "ctl06" ); 25 gazou_ctl_objid = kcxobj_open( "ctl07" ); 26 27 28 /* コンパイル済のプログラム(オブジェクト)の起動 */ 29 kcxobj_stat_iwt( ondo_ctl_objid, 1 ); 30 kcxobj_stat_iwt( ondo_alm_objid, 1 ); 31 kcxobj_stat_iwt( mizu_ctl_objid, 1 ); 32 kcxobj_stat_iwt( email_ctl_objid, 1 ); 33 kcxobj_stat_iwt( gazou_ctl_objid, 1 ); 34 35 /* 上記オブジェクトを起動したら本プログラム終了 */ 36 37 }
● 温度制御プログラム [タスク2(objid=ctl03)]
25-27行目では、初期設定としてファンを停止させてます。
25 fan_objid = kcxobj_open( "bo01" ); 26 fan_status = OFF; 27 kcxobj_sndistat_tokcx( fan_objid, fan_status );
● 温度上限警報プログラム [タスク3(objid=ctl04)]
42-51行目では、ブザーをONにするタイミングで、温度異常のメールを送信しています。
42 if( buzzer_status == OFF ){ 43 /* 1.ブザーが停止中だったら起動操作(スタック) */ 44 buzzer_status = ON; 45 kcxobj_sndistat_tokcx( buzzer_objid, buzzer_status ); 46 /* 2.同時に警報のEメールを送信する */ 47 /* 送信アドレス例として、tarou@yyy.xx.jp 題名は、温度異常 */ 48 /* 電文(almtext)には現在温度を付加するとしました */ 49 sprintf( almtext,"現在温度= %5.2f °C ですよ", temperature_currentval ); 50 kcxsnd_email_text( "tarou@yyy.xx.jp","","","温度異常",almtext ); 51 }
● 水やり制御プログラム [タスク4(objid=ctl05)]
38-40行目では、設定時間かどうかの判断に開始と終了の時刻を1日のトータル秒に換算しています。0時が0で、23時59分59秒が86399となります。現在時間を秒にし、これが設定された時間内かどうかで給水かどうかを判断しています。
37 /* 予め給水開始と終了時間を1日のトータル秒に計算しておく(時間の判断容易) */ 38 kyuusui_start_time_sec = ( 3600 * kyuusui_start_hour ) 39 + ( 60 * kyuusui_start_minute ); 40 kyuusui_end_time_sec = kyuusui_start_time_sec + kyuusui_pump_on_sec; 44 /* 現在の年月日時分秒を取得 */ 45 kcxtim_whattime( &jikan ); 46 47 current_time_sec = ( 3600 * jikan.tm_hour ) 48 + ( 60 * jikan.tm_min ) + jikan.tm_sec; 49
● 定時Eメール送信プログラム [タスク5(objid=ctl06)]
42行目は、記述するメール本文の行数を設定しています。例えば30行書きたい場合には、mtext
= 30;となります。本プログラム例では、(2)と記述してありますが、この( )は2を強調したいために用いただけで他意はありません。
44行目のmalloc関数で、引数で示された半角文字数の長さ分のメモリ領域を確保しています。これを、mtext[i]に割り当てて使用します。
46行目は、メールに添付したいコマンド(ファイル)分の数を設定します。
40 /* メール送信関数に使うバッファメモリの取得(mtexts=本文,aptexts=添付分) */ 41 /* ※送信したい文字列の行数だけmalloc()させるものでKARACRIX関数仕様です*/ 42 mtexts = (2); 43 for( i = 0;i < mtexts; i++ ){ 44 mtext[i] = (char *)malloc( 64+1 ); 45 } 46 aptexts = (2); 47 for( i = 0;i < aptexts; i++ ){ 48 aptext[i] = (char *)malloc( 64+1 ); 49 }
75-81行目で、メール送信します。
72 if( email_send_flag == ON ){ 73 /* 送信アドレス例として、tarou@yyy.xx.jp 題名は、定時報告 */ 74 /* 電文(almtext)には現在時間と送信回数を付加するとしました */ 75 sprintf( mtext[0], "現在時刻= %d日 %d時 %d分 %d秒", 76 jikan.tm_mday,jikan.tm_hour,jikan.tm_min,jikan.tm_sec); 77 sprintf( mtext[1],"メール回数は %d 回目ですよ", ++repcount ); 78 strcpy( aptext[0], "mon 1 " ); /*No.1の監視パネル画像添付指示 */ 79 strcpy( aptext[1], "tre 1 " ); /*No.1のトレンドグラフ画像添付指示 */ 80 kcxsnd_email_texts_appends( "tarou@yyy.xx.jp","","","定時報告", 81 mtext, mtexts, aptext, aptexts ); 82 /* Eメールを同じ時間内に連続送信しない為の簡単な遅延(sleep)処置 */ 83 sleep( 60 /*1分*/ ); 84 }
● 定時画像記録プログラム [タスク6(objid=ctl07)]
17行目は、記録する画像のクオリティ(画質)を設定しています。ここでは、100の最高画質にしています。画質を上げるほど記録画像ファイルのサイズが大きくなります。
15 /* 記録画質を決める */ 16 kcximg_quality_set( 100 ); 17
27行目で、画像記録を行っています。引数の2は、ワンショットモード(一回記録)の場合にセットします。
26 /* 毎時0分に1回(ワンショット)記録する */ 27 kcximg_recctl_set( 2 );
登録した全てのプログラムをコンパイルして、実行ファイルが作成できたら実行してみます。「制御プログラム登録」画面に戻って下さい。
●プログラムを実行する
園芸水やりシステムを実行する前に、計測制御通信プログラムが実行されていることを確認します。実行されていないときは、実行しておきます。
No.2のctl02オブジェクト「園芸水やりシステム起動」プログラムの“実行”欄をクリックすると、「実行ダイアログ」が表示されますので“YES(実行)”ボタンを選択します[図6.14]。
図6.14 タスク自動起動プログラムの実行
ctl02の実行後、ctl03、ctl04、ctl05、ctl06、ctl07のプログラムが次々と自動起動されればタスクの実行は取り合えず成功です。後は、各アプリケーション処理が正常か確認してください。
図6.15 ユーザープログラムの実行
プログラムで画像記録の設定を行いましたので、保存されている記録画像を再生してみましょう。
図6.16 記録画像の再生
定時Eメールによる観察データの受信画面の例を以下に示します。
図6.17 定時Eメールよる受信画面(本文)
図6.18 定時Eメールよる受信画面(添付画像)
1 2 /*= [タスク1(objid=ctl02)] 各プログラム(タスク)起動用プログラム =*/ 3 4 #include5 6 main( argc, argv ) 7 int argc; 8 char *argv[]; 9 { 10 int ondo_ctl_objid; /* 温度制御プログラム起動オブジェクトID */ 11 int ondo_alm_objid; /* 温度上限警報プログラム起動オブジェクトID */ 12 int mizu_ctl_objid; /* 水やり制御プログラム起動オブジェクトID */ 13 int email_ctl_objid; /* 定時Eメール送信プログラム起動オブジェクトID */ 14 int gazou_ctl_objid; /* 定時画像記録プログラム起動オブジェクトID */ 15 16 /* KARACRIXライブラリの初期化(先頭に必須) */ 17 kcxinit( argc, argv ); 18 19 20 /* プログラムオブジェクトIDの取得 */ 21 ondo_ctl_objid = kcxobj_open( "ctl03" ); 22 ondo_alm_objid = kcxobj_open( "ctl04" ); 23 mizu_ctl_objid = kcxobj_open( "ctl05" ); 24 email_ctl_objid = kcxobj_open( "ctl06" ); 25 gazou_ctl_objid = kcxobj_open( "ctl07" ); 26 27 28 /* コンパイル済のプログラム(オブジェクト)の起動 */ 29 kcxobj_stat_iwt( ondo_ctl_objid, 1 ); 30 kcxobj_stat_iwt( ondo_alm_objid, 1 ); 31 kcxobj_stat_iwt( mizu_ctl_objid, 1 ); 32 kcxobj_stat_iwt( email_ctl_objid, 1 ); 33 kcxobj_stat_iwt( gazou_ctl_objid, 1 ); 34 35 /* 上記オブジェクトを起動したら本プログラム終了 */ 36 37 }
1 2 /*= [タスク2(objid=ctl03)] 温度制御プログラム =*/ 3 4 #include5 6 #define ON (1) /* BOオブジェクト起動用 */ 7 #define OFF (0) /* BOオブジェクト停止用 */ 8 9 main( argc, argv ) 10 int argc; 11 char *argv[]; 12 { 13 int temperature_objid; /* 温度センサーのオブジェクトID */ 14 float temperature_currentval; /* 温度センサーの状態を格納 */ 15 float temperature_funon_val; /* 警戒温度設定値 */ 16 float temperature_funoff_val; /* 警戒温度設定解除値 */ 17 int fan_objid; /* ファンのオブジェクトID */ 18 int fan_status; /* ファンの状態を格納 */ 19 20 /* KARACRIXライブラリの初期化(先頭に必須) */ 21 kcxinit( argc, argv ); 22 23 /* オブジェクトIDの取得とファン初期停止の操作 */ 24 temperature_objid = kcxobj_open( "aif01" ); 25 fan_objid = kcxobj_open( "bo01" ); 26 fan_status = OFF; 27 kcxobj_sndistat_tokcx( fan_objid, fan_status ); 28 29 /* 制御パラメータの設定 */ 30 temperature_funon_val = 30.0; /* ファンON 温度[℃] */ 31 temperature_funoff_val = 28.0; /* ファンOFF温度[℃] */ 32 33 while( 1 ){ /* 監視制御ループ */ 34 35 /* 現在の温度を取得 */ 36 kcxobj_stat_frd( temperature_objid, &temperature_currentval ); 37 38 /* 警戒設定温度を越えたら --> ファン起動 */ 39 if( temperature_currentval > temperature_funon_val ){ 40 41 if( fan_status == OFF ){ 42 /* ファンが停止中だったら起動操作(スタック) */ 43 kcxobj_sndistat_tokcx( fan_objid, ( fan_status = ON ) ); 44 } 45 } 46 47 /* 警戒設定解除温度より下がったら --> ファン停止 */ 48 if( temperature_currentval < temperature_funoff_val ){ 49 50 if( fan_status == ON ){ 51 /* ファンが起動中だったら停止操作(スタック) */ 52 kcxobj_sndistat_tokcx( fan_objid, ( fan_status = OFF ) ); 53 } 54 } 55 56 /* 必須:CPUを1分停止させる(負荷を和らげる為) */ 57 sleep(60); 58 59 }/*while*/ 60 61 }
リスト6.3 園芸水やり(温度上限警報)システムプログラムリスト
1 2 /*= [タスク3(objid=ctl04)] 温度上限警報プログラム =*/ 3 4 #include5 6 #define ON (1) /* BOオブジェクト起動用 */ 7 #define OFF (0) /* BOオブジェクト停止用 */ 8 9 main( argc, argv ) 10 int argc; 11 char *argv[]; 12 { 13 int temperature_objid; /* 温度センサーのオブジェクトID */ 14 float temperature_currentval; /* 温度センサーの状態を格納 */ 15 float temperature_email_buzzeron_val; /* 警戒温度設定値 */ 16 float temperature_email_buzzeroff_val; /* 警戒温度設定解除値 */ 17 int buzzer_objid; /* ブザーのオブジェクトID */ 18 int buzzer_status; /* ブザーの状態を格納 */ 19 char almtext[64]; /* Eメール電文 */ 20 21 /* KARACRIXライブラリの初期化(先頭に必須) */ 22 kcxinit( argc, argv ); 23 24 /* オブジェクトIDの取得とブザー初期停止の操作 */ 25 temperature_objid = kcxobj_open( "aif01" ); 26 buzzer_objid = kcxobj_open( "bo02" ); 27 buzzer_status = OFF; 28 kcxobj_sndistat_tokcx( buzzer_objid, buzzer_status ); 29 30 /* 制御パラメータの設定 */ 31 temperature_email_buzzeron_val = 38.0; /* ブザーON 温度[℃] */ 32 temperature_email_buzzeroff_val = 36.0; /* ブザーOFF温度[℃] */ 33 34 while( 1 ){ /* 監視制御ループ */ 35 36 /* 現在の温度を取得 */ 37 kcxobj_stat_frd( temperature_objid, &temperature_currentval ); 38 39 /* 警戒設定温度を越えたら --> ブザーON */ 40 if( temperature_currentval > temperature_email_buzzeron_val ){ 41 42 if( buzzer_status == OFF ){ 43 /* 1.ブザーが停止中だったら起動操作(スタック) */ 44 buzzer_status = ON; 45 kcxobj_sndistat_tokcx( buzzer_objid, buzzer_status ); 46 /* 2.同時に警報のEメールを送信する */ 47 /* 送信アドレス例として、tarou@yyy.xx.jp 題名は、温度異常 */ 48 /* 電文(almtext)には現在温度を付加するとしました */ 49 sprintf( almtext,"現在温度= %5.2f °C ですよ", temperature_currentval ); 50 kcxsnd_email_text( "tarou@yyy.xx.jp","","","温度異常",almtext ); 51 } 52 } 53 54 /* 警戒設定解除温度より下がったら --> ブザー停止 */ 55 if( temperature_currentval < temperature_email_buzzeroff_val ){ 56 57 if( buzzer_status == ON ){ 58 /* 1.ブザーが起動中だったら停止操作(スタック) */ 59 buzzer_status = OFF; 60 kcxobj_sndistat_tokcx( buzzer_objid, buzzer_status ); 61 /* 2.同時に警報解除のEメールを送信する */ 62 /* 送信アドレス例として、tarou@yyy.xx.jp 題名は、温度異常解除 */ 63 /* 電文(almtext)には現在温度を付加するとしました */ 64 sprintf( almtext,"現在温度= %5.2f °C ですよ", temperature_currentval ); 65 kcxsnd_email_text( "tarou@yyy.xx.jp","","","温度異常解除",almtext ); 66 } 67 } 68 69 /* 必須:CPUを1分停止させる(負荷を和らげる為) */ 70 sleep(60); 71 72 }/*while*/ 73 74 }
1 2 /*= [タスク4(objid=ctl05)] 水やり制御プログラム =*/ 3 4 #include5 6 #define ON (1) /* BOオブジェクト起動用 */ 7 #define OFF (0) /* BOオブジェクト停止用 */ 8 9 main( argc, argv ) 10 int argc; 11 char *argv[]; 12 { 13 struct tm jikan; /* 時間データを格納する構造体 */ 14 int current_time_sec; /* 一日の時間を秒に変換 */ 15 int kyuusui_start_hour; /* 給水開始時間(時)の設定 */ 16 int kyuusui_start_minute; /* 給水開始時間(分)の設定 */ 17 int kyuusui_pump_on_sec; /* 給水時間(秒)の設定 */ 18 int kyuusui_start_time_sec; /* 給水開始時間を秒に変換 */ 19 int kyuusui_end_time_sec; /* 給水終了時間を秒に変換 */ 20 int waterpump_objid; /* ポンプのオブジェクトID */ 21 int waterpump_status; /* ポンプの状態を格納 */ 22 23 /* KARACRIXライブラリの初期化(先頭に必須) */ 24 kcxinit( argc, argv ); 25 26 /* オブジェクトIDの取得と給水ポンプ初期停止の操作 */ 27 waterpump_objid = kcxobj_open( "bo03" ); 28 waterpump_status = OFF; 29 kcxobj_sndistat_tokcx( waterpump_objid, waterpump_status ); 30 31 /* 制御パラメータの設定 */ 32 kyuusui_start_hour = 10; /* 給水開始[時]:0から23まで */ 33 kyuusui_start_minute = 0; /* 給水開始[分]:0から59まで */ 34 kyuusui_pump_on_sec = 30; /* 給水時間[秒]:日をまたがないものとした */ 35 /* またぐ場合一工夫必要 */ 36 37 /* 予め給水開始と終了時間を1日のトータル秒に計算しておく(時間の判断容易) */ 38 kyuusui_start_time_sec = ( 3600 * kyuusui_start_hour ) 39 + ( 60 * kyuusui_start_minute ); 40 kyuusui_end_time_sec = kyuusui_start_time_sec + kyuusui_pump_on_sec; 41 42 while( 1 ){ /* 監視制御ループ */ 43 44 /* 現在の年月日時分秒を取得 */ 45 kcxtim_whattime( &jikan ); 46 47 current_time_sec = ( 3600 * jikan.tm_hour ) 48 + ( 60 * jikan.tm_min ) + jikan.tm_sec; 49 50 if(( current_time_sec >= kyuusui_start_time_sec ) && 51 ( current_time_sec <= kyuusui_end_time_sec ) ){ 52 53 /* 給水設定時間以内だったら --> ポンプ起動 */ 54 if( waterpump_status == OFF ){ 55 /* 給水ポンプがOFFだったらON */ 56 kcxobj_sndistat_tokcx( waterpump_objid, ( waterpump_status = ON ) ); 57 } 58 59 }else{ 60 61 /* 給水設定時間以外だったら --> ポンプ停止 */ 62 if( waterpump_status == ON ){ 63 /* 給水ポンプがONだったらOFF */ 64 kcxobj_sndistat_tokcx( waterpump_objid, ( waterpump_status = OFF ) ); 65 } 66 67 } 68 69 /* 必須:CPUを1秒停止させる(負荷を和らげる為) */ 70 sleep(1); 71 72 }/*while*/ 73 74 }
1 2 /*= [タスク5(objid=ctl06)] 定時Eメール送信プログラム =*/ 3 4 #include5 6 #define ON (1) /* BOオブジェクト起動用 */ 7 #define OFF (0) /* BOオブジェクト停止用 */ 8 9 main( argc, argv ) 10 int argc; 11 char *argv[]; 12 { 13 struct tm jikan; /* 時間データを格納する構造体 */ 14 int email_send_flag; /* Eメール送信フラグ */ 15 int email_start_hour_1; /* 1回目のEメール送信時刻(時) */ 16 int email_start_minute_1; /* 1回目のEメール送信時刻(分) */ 17 int email_start_hour_2; /* 2回目のEメール送信時刻(時) */ 18 int email_start_minute_2; /* 2回目のEメール送信時刻(分) */ 19 int email_start_hour_3; /* 3回目のEメール送信時刻(時) */ 20 int email_start_minute_3; /* 3回目のEメール送信時刻(分) */ 21 int i,repcount; /* Eメール送信回数カウンタ */ 22 char *mtext [10]; /* Eメール本文バッファポインタ */ 23 char *aptext[10]; /* Eメール添付バッファポインタ */ 24 int mtexts,aptexts; /* 本文添付バッファ数 */ 25 26 /* KARACRIXライブラリの初期化(先頭に必須) */ 27 kcxinit( argc, argv ); 28 29 /* 制御パラメータの設定 */ 30 email_start_hour_1 = 8; /* 8時 時刻[時]:0から23まで */ 31 email_start_minute_1 = 0; /* 30分 時刻[分]:0から59まで */ 32 email_start_hour_2 = 12; /* 12時 時刻[時]:0から23まで */ 33 email_start_minute_2 = 30; /* 30分 時刻[分]:0から59まで */ 34 email_start_hour_3 = 17; /* 17時 時刻[時]:0から23まで */ 35 email_start_minute_3 = 0; /* 0分 時刻[分]:0から59まで */ 36 37 /* メール送信回数をカウントするメモリを0クリアする */ 38 repcount = 0; 39 40 /* メール送信関数に使うバッファメモリの取得(mtexts=本文,aptexts=添付分) */ 41 /* ※送信したい文字列の行数だけmalloc()させるものでKARACRIX関数仕様です */ 42 mtexts = (2); 43 for( i = 0;i < mtexts; i++ ){ 44 mtext[i] = (char *)malloc( 64+1 ); 45 } 46 aptexts = (2); 47 for( i = 0;i < aptexts; i++ ){ 48 aptext[i] = (char *)malloc( 64+1 ); 49 } 50 51 while( 1 ){ /* 監視制御ループ */ 52 53 /* 現在の年月日時分秒を取得 */ 54 kcxtim_whattime( &jikan ); 55 56 /* Eメール送信時刻の検査 */ 57 email_send_flag = OFF; 58 if(( jikan.tm_hour == email_start_hour_1 ) && 59 ( jikan.tm_min == email_start_minute_1 ) ){ 60 email_send_flag = ON; 61 } 62 if(( jikan.tm_hour == email_start_hour_2 ) && 63 ( jikan.tm_min == email_start_minute_2 ) ){ 64 email_send_flag = ON; 65 } 66 if(( jikan.tm_hour == email_start_hour_3 ) && 67 ( jikan.tm_min == email_start_minute_3 ) ){ 68 email_send_flag = ON; 69 } 70 71 /* Eメールの送信 */ 72 if( email_send_flag == ON ){ 73 74 /* 送信アドレス例として、tarou@yyy.xx.jp 題名は、定時報告 */ 75 /* 電文(almtext)には現在時間と送信回数を付加するとしました */ 76 sprintf( mtext[0], "現在時刻= %d日 %d時 %d分 %d秒", 77 jikan.tm_mday,jikan.tm_hour,jikan.tm_min,jikan.tm_sec); 78 sprintf( mtext[1],"メール回数は %d 回目ですよ", ++repcount ); 79 strcpy( aptext[0], "mon 1 " ); /*No.1の監視パネル画像添付指示 */ 81 strcpy( aptext[1], "tre 1 " ); /*No.1のトレンドグラフ画像添付指示 */ 82 83 kcxsnd_email_texts_appends( "tarou@yyy.xx.jp","","","定時報告", 84 mtext, mtexts, aptext, aptexts ); 85 86 /* Eメールを同じ時間内に連続送信しない為の簡単な遅延(sleep)処置 */ 87 sleep( 60 ); /*1分*/ 88 } 89 90 /* 必須:タスクを10秒停止させる(CPU負荷を和らげる為) */ 91 sleep(10); 92 93 }/*while*/ 94 95 }
リスト6.6 園芸水やり(定時画像記録)システムプログラムリスト
1 2 /*= [タスク6(objid=ctl07)] 定時(毎時)画像記録プログラム =*/ 3 4 #include5 6 main( argc, argv ) 7 int argc; 8 char *argv[]; 9 { 10 struct tm jikan; /* 時間データを格納する構造体 */ 11 12 /* KARACRIXライブラリの初期化(先頭に必須) */ 13 kcxinit( argc, argv ); 14 15 /* 記録画質を決める */ 16 kcximg_quality_set( 100 ); 17 18 while( 1 ){ /* 監視制御ループ */ 19 20 /* 現在の年月日時分秒を取得 */ 21 kcxtim_whattime( &jikan ); 22 23 if(( jikan.tm_hour == 0 ) && 24 ( jikan.tm_min == 0 ) ){ 25 26 /* 毎時0分に1回(ワンショット)記録する */ 27 kcximg_recctl_set( 2 ); 28 29 /* 同じ時間内に連続画像記録させない為の簡単な遅延(sleep)処置 */ 30 sleep( 60 ); /*1分*/ 31 32 }else{ 33 34 /* 必須:タスクを1秒停止させる(CPU負荷を和らげる為) */ 35 sleep(1); 36 37 } 38 39 40 }
Copyright(C) All Rights Reserved. by S.I.Soubou,Inc.