2012年12月09日

外出先で自宅エアコン電源制御(その4)

 さて、いよいよCGIの話です。CGIと言えばPerlと思われがちですが、実はC言語でCGIを書くことも可能です。ハードウェア制御もあるのでC言語で全部書こうと思いました。しかし、適材適所を意識するとC言語とPerlを組み合わせたほうがよさそうです。

 今回は、ハードウェア制御部はC言語で、Web画面部はPerlで書きます。Perlからsystem関数でハードウェア制御部を呼び出すイメージです。

 とうことで、今回はハードウェア制御部だけの話を書きます。CGIは次回に。。。

 ソースは以下のようになります。コマンドを実行することで電源制御命令を出します。HA端子的に言えば電源制御パルスを出すということですね。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <time.h>

#define DEV_NAME "/dev/ttyUSB1" // デバイスファイル名
#define BAUD_RATE B38400 // RS232C通信ボーレート
#define BUFF_SIZE 512 // 適当

// シリアルポートの初期化
int serial_init(int fd)
{
int ret;
struct termios tio;
memset(&tio,0,sizeof(tio));
tio.c_cflag = CS8 | CLOCAL | CREAD;
tio.c_cc[VTIME] = 0;
// ボーレートの設定
ret=cfsetispeed(&tio,BAUD_RATE);
if(ret!=0)return ret;
ret=cfsetospeed(&tio,BAUD_RATE);
if(ret!=0)return ret;
// デバイスに設定を行う
ret=tcsetattr(fd,TCSANOW,&tio);
if(ret!=0)return ret;
}

int main(int argc,char *argv[]){
int fd;

// デバイスファイル(シリアルポート)オープン
fd = open(DEV_NAME,O_RDWR);
if(fd<0){
// デバイスの open() に失敗したら
perror(argv[1]);
printf("open error.\n");
exit(1);
}

// シリアルポートの初期化
if(serial_init(fd)<0){
printf("serial init error.\n");
}

unsigned char buffer[BUFF_SIZE];
memset(buffer,0,BUFF_SIZE);
write(fd,buffer,BUFF_SIZE);

close(fd);
return 0;
}


 ポイントとしては、シリアルポートもファイルI/Oとして扱うことでしょうか。ファイル関連システムコールだけでは扱えない部分はtcsetattr()などを用いています。

 前回の説明では、300bpsで3バイト送信しておりましたが、このソースでは38400bpsで512バイト送信しています。何故かというと、うまく300bpsに設定できなかったからです。シェルから実行する分には300bpsに設定できていたのですが、CGIから実行すると無視されてしまいます。なんかしらのセキュリティの設定のせいだとは思うのですが、セキュリティを外すよりは、あきらめて初期値の38400bpsのままにしちゃうほうが安全かなと思った次第です。

 38400bpsで100msのパルスを出すには384バイト送信すればいいのですが、512バイト送信しています。これはもう気分だけの問題です。エアコン側との相性もあると思うので、自作される場合は調整してみてください。

 もう一つ、入力側の制御コマンドを示します。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <termios.h>
#include <time.h>
#include <sys/ioctl.h>

#define DEV_NAME "/dev/ttyUSB1" // デバイスファイル名

int main(int argc,char *argv[]){
int fd;

// デバイスファイル(シリアルポート)オープン
fd = open(DEV_NAME,O_RDWR);
if(fd<0){
// デバイスの open() に失敗したら
perror(argv[1]);
printf("open error.\n");
exit(1);
}

int lstat;
ioctl( fd, TIOCMGET, &lstat );
if( lstat & TIOCM_DSR ){
printf("1\n");
}else{
printf("0\n");
}
close(fd);
return 0;
}


 実行すると、エアコンのON/OFF状態を標準出力に出します。ONなら1、OFFなら0です。これのポイントも、ファイルI/Oとして扱う点ですかね。まったく同じですね。

 入力も出力もまとめて1本のプログラムにして、引数で動作を変えるほうがよいかもしれません。デバイスファイル名が2か所に出てくるのが気持ち悪いですしね。

 しかし、引数のパースが面倒なので、別々のプログラムにしてしまいました。別々のプログラムのほうが読みやすいのではないかと思います。

posted by tech4u at 17:45| Comment(0) | 電子工作 | このブログの読者になる | 更新情報をチェックする

2012年11月24日

外出先で自宅エアコン電源制御(その3)

 今回はUSB-マルチI/Oの話をしようと思います。

 パソコンから外付け回路を制御するに当たり、I/Fを何にするかは悩むところです。一昔前であればパラレルポート(プリンタポート)を使うのがリーズナブルで定番でした。プリンタがUSB接続やネットワーク接続が当たり前になった頃は空き端子になり、ちょっとした回路をつなぐにはちょうどいい端子でした。しかし、空き端子になるということは需要が無いということで、最近のパソコンにはパラレルポートが付いてません。

 今は、USB-マルチI/Oチップを使うのが常識になっていると思われます。

 しかし、今回はあえてUSB-シリアル(RS-232C)変換チップを使います。理由は、ドライバ導入で苦労しなさそうという点です。最近のOSであれば、LinuxでもFreeBSDでもとりあえず挿せば動くだろいうということです。

 今回買ってきたのは、秋月電子の K-01977 です。これを使用した場合、信号のタイミングはRS-232Cですが、信号レベルはCMOSレベルのままです。今回の用途では、レベル変換されると余計面倒になるのでこのキットが最適です。USB接続モノでは最安なんじゃないかと思います。

 単純なパルス出力をしたいので、コレのRTSかDTRを出力に使います。という予定でした。しかし失敗です。

 何が失敗かというと、変換チップのリセット時に出力が不定となるからです。つまり、勝手にエアコンの電源がON/OFFされてしまう恐れがあるということです。変換チップのリセットをしなければよいのですが、パソコン再起動時にももちろんリセットされてしまいます。これを避けるのが運用の条件とするのはちょっと厳しいです。

 そこで、TxDを出力に使うことにしました。TxDはリセット時もHレベルのままです。

 TxDはご存じのとおり、シリアル信号出力です。それをパルス出力に使えるのか?

 大丈夫です。TxDはデータが無いときが1で、データはデータ通り0か1が送られます。ということは、0x00(つまり、8bitオール0)を送ると、長めのパルスになります。通信速度を遅くすれば、さらに長くなります。

 そこで、300bpsに設定して0x00を送ってみました。が、結果はエアコンが反応したりしなかったりです。

 ここで、300bpsで0x00を送った時のパルス幅を考えてみましょう。

 RS-232Cの通信では、スタートビットとストップビットが付きます。スタートビットが0でストップビットが1です。ストップビットはパルス幅が1ビット分、1.5ビット分、2ビット分とか選べるのですが、普通は1ビットと設定します。まあ、なんにせよ、スタートビットの1ビットとデータ部の8ビットが送られることになり、9ビット幅のパルスが出ることになります。9ビットが300bpsで送られます。ということは、1/300*9=0.03秒がパルス幅になります。

 これで、不安定だったので、3倍にしてみました。0x00を3回連続で送ってみます。すると、確実にエアコンのON/OFFが可能になりました。

 ストップビットの分の逆パルスが2回出ちゃうことになります。図にすると以下のようになります。

airconcon_timing.png

 逆パルスがあるものの、とりあえず動いているので問題なしということにしておきます。

 入力について書き忘れましたが、こちらは単純に DSR を使います。

 次回はCGIの話を書こうと思います。

posted by tech4u at 23:26| Comment(0) | 電子工作 | このブログの読者になる | 更新情報をチェックする

2012年10月14日

外出先で自宅エアコン電源制御(その2)

 今回はHA端子とフォトカプラの話をしようと思います。

 HA端子は、物理的なコネクタは、XHと呼ばれる2.5mmピッチのコネクタのようです。千石電商から通販で買えます。この記述だけで購入できる方を、読者想定としています。

 一般的な蛇の目基板の2.54mmとはピッチが若干異なりますが、4Pぐらいだとピッチ変換基板を使うことなく実装することができます。

 物理層(?)は解決しましたが、電流値はどんぐらいなのか、パルス幅はどんぐらいなのか、グーグル先生に聞いても出てきません。どうも、規格書を買わないと見れないような感じです。
 作成に当たり、そこが一番のネックでした。

 そこで! 規格書を買おうと思いました。が、やめました。テキトーに作ってみます。

 フォトカプラは、昔買った TLP521-2 が家にあったので、それを採用します。抵抗は、なんとなく気分で1kΩを使います。ちなみにI/O電圧は3.3Vを使ってます。電圧が5Vでも、抵抗1kΩのままで動いちゃうんじゃないかと思います。

 こーゆーのは、電流が少ない順(抵抗値が大きい順)に、動作しない→動作不安定→安定動作→電気代が無駄→壊れる となります。フォトカプラの場合は、安定動作の中にも、省電力狙いと高速反応狙いとがあるので、どっちも気にしないのであれば、安定動作の範囲は結構広いです。そういう根拠から、抵抗値はテキトーでよいということになります。

 というわけで回路図はこんな感じです。

airconcon_circuit.png

 実態配線図は、、、なくても作れる方を読者想定としています。

 パルス幅は100msぐらいです。33msだと反応したりしなかったりだったので、その3倍にしてみました。なぜ最初に33msを試したのかは、次回のマルチI/Oの話で書こうと思います。
posted by tech4u at 18:52| Comment(0) | 電子工作 | このブログの読者になる | 更新情報をチェックする
×

この広告は90日以上新しい記事の投稿がないブログに表示されております。