スキップしてメイン コンテンツに移動

遠隔・自動操作できるようにした加湿器をさらに改造 電流(CT)センサ 使い方 ~簡易IoT家電「改」~

 

背景

今回で4度目になる加湿器の改造がメインの話になります。

以前、加湿器を遠隔・自動で操作できるように改造しました。

タイトルにもある通り、今回はCTセンサを使って改造していきたい思います。

akizukidenshi.com

何をしたいからと言うと。。。

今まで、加湿器のハード的な問題でON・OFFそれぞれの独立した信号で操作することが出来ませんでした。(元々ボタンを押すと状態を反転させているだけだったので。。。)

これにより、日時指定して自動で起動している場合だと手動で間違って電源を消してしまった場合、決まった時間に電源状態の反転信号が送られて本来使わない時間に電源が入ったままになってしまうことがありました。

例) 朝6時と夕方18時に信号を送っていたとして、18時以降には電源が落ちている状態にしたいのに18時手前に手動で電源を落として退席してしまうと、18時に電源が入って朝の6時まで切れないということになってしまいます。

今回はこれを解消するために、加湿器が稼働している否かの状態を取れるようにして、その情報を基にうまく制御していきたいと思います。

そこで使うのがCTセンサと言うことです。

これは、コンセントに刺しているコードからほぼ非接触で電流を測れるセンサになっているため、HaLakeで使用している加湿器のみに使える手法ではなく仕組みとプログラムとを理解したうえで、多少の犠牲を払えば誰でも簡単に同じようなことが出来ます。

また、多少の誤差を気にしなければ大まかな消費電力も測ることが出来ます。

消費電力が小さすぎると誤差が大きく出るため、今回の用途としては消費電力の計測には使用しませんが、気になる方はとても参考になった記事があるのでそちらを拝見してください。

qiita.com

先ほどの多少の犠牲と言いましたがセンサを使う際、コードをよく見ると二本の線でてきていることがわかりますが(見た目でわからないものもある)、このうちの一本のみをセンサで挟み込む必要があります。

はさむと言っても洗濯ばさみのようになっているセンサに通すというイメージです。

その点に目をつむれば低コストかつ一般の方でも比較的安全に使うことが出来ます。

  • 注意: 以降の記事を読んで試される方は十分に注意を払ったうえで参考にしてください。当記事を参考にしたうえで起こった事故や損害、怪我等のあらゆる問題に関して一切の責任を負いません。

少し脅しになってしまいましたが、コンセントから伸びる線を扱うため気を付けましょう。

以前の記事1以前の記事2以前の記事3を読んで頂ける分かりやすい内容になっていますので、読んで頂けると嬉しいです。

使ったもの

  1. CTセンサ
  2. ESP8266
  3. ジャンパワイヤ
  4. 加湿器
  5. 抵抗 (1KΩ程度)×5 & (33Ω) × 1
  6. ワニ口クリップ
  7. フイルムコンデンサ (μF) × 1

配線

配線は以下のようになります。

実際の配線は以下のようになります。

抵抗は1.8KΩを5つで、3.3Vを5分の1(抵抗1個に約0.66V)の分圧をするため、手元にあってサイズが小さい抵抗を使っています。

esp8266が1Vまでしか計測できないのと交流のような値が返ってくるため、0.66Vを中心に値が変動するように設定しています。本来なら1V の半分の0.5Vで設定したいのですが3.3Vや5Vからだと抵抗の値や数がややこしくなるためこれで妥協します。

esp8266で再現するときは1KΩ~10KΩ程度で同じ抵抗値を5つと別にCTセンサの負荷抵抗として33Ω程度を用意してください。

負荷抵抗として33Ωを使ったのは以下の記事を参考に抵抗値を上げると測定の感度が上がるということだったので、通常の10Ωだと消費電力が少ない時にうまく計測出来ないことがあるため、電源がONかOFFの判定がうまく出来ないと不便だったため抵抗値を上げました。

プログラム

まずは筆者の環境で動かしているプログラムです。

以下をそのまま扱う場合は

IPAddress ip(192, 168, ??, ???); //ip

固定するIPアドレスを書く環境に合わせて書き換えてください。

#include <Ticker.h>
#include <ESP8266WiFi.h>
#define ON_PIN 12
////IPアドレス固定用
IPAddress ip(192, 168, ??, ???); //ip
IPAddress subnet(255, 255, 255, 0);
////

long count = 0;
int freq = 50; //50Hz
double analogPinStatus;
double ammeter;
double dt = 0.001;

double ammeterSum = 0;
double realAmmeter = 0;
double voltage = 100.0;

void getAmmeterValue();

bool last_req_state = false;
Ticker tickerCheck(getAmmeterValue, 1, 0, MILLIS);

const char* ssid = "**********";
const char* password = "**********";

WiFiServer server(80);

void setup()
{
    Serial.begin(115200);
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.config(ip, ip, subnet);
    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    
    Serial.println("WiFi connected.");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    
    server.begin();

    pinMode(ON_PIN,OUTPUT);

}

void loop(){
  tickerCheck.update();
  WiFiClient client = server.available();
  if (client) {
    Serial.println("New Client.");           
    String currentLine = "";
    while (client.connected()) {           
      if (client.available()) {             
        char c = client.read();             
        Serial.write(c);                  
        if (c == '\n') {
          if (currentLine.length() == 0) {
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html");
            client.println();
            client.print("<h1>Server OK</h1>");
            client.println();
            break;
          } else {
            currentLine = "";
          }
        } else if (c != '\r') {
          currentLine += c;
        }
        
        if (!currentLine.compareTo("x-access-key: HOGEHOGEON")){
          last_req_state = true;
          tickerCheck.start();
        }
        if (!currentLine.compareTo("x-access-key: HOGEHOGEOFF")){
          last_req_state = false;
          tickerCheck.start();
        }
      }
    }
    // close the connection:
    client.stop();
    Serial.println("Client Disconnected.");
  }
}

int sumRealAmmeter = 0;
int avg = 0;
void getAmmeterValue()
{
  analogPinStatus = analogRead(0);
  ammeter = (analogPinStatus - 680.0) * 0.7368359376 * 0.2;
  ammeterSum = ammeterSum + abs(ammeter) * dt;

  if (count % 1000 == 0){
    realAmmeter = ammeterSum;
    ammeterSum = 0;
    Serial.println(realAmmeter);
    sumRealAmmeter += realAmmeter;
  }
  if(count > 10000){
    tickerCheck.stop();
    Serial.println("ticker stop");
    avg = sumRealAmmeter / 10;
    if(avg * voltage < 400 and last_req_state){
      digitalWrite(ON_PIN,HIGH);
      delay(500);
      digitalWrite(ON_PIN,LOW);
    }else if(avg * voltage > 400 and !last_req_state){
      digitalWrite(ON_PIN,HIGH);
      delay(500);
      digitalWrite(ON_PIN,LOW);
    }
    Serial.println(avg * voltage + ":" + last_req_state);
    sumRealAmmeter = 0;
    count = 0;  
  }

  count++;
}

消費電力の測定は以下の記事を参考にプログラムを組んでいます。

qiita.com

esp系ではFlexiTimer2のライブラリが使えないのでTickerと言うesp系でも使える割り込みのライブラリを使いました。

github.com

動作としては、

  1. WiFiに接続
  2. HPPTリクエストを待つ
  3. 指定しヘッダ情報を持つリクエストが来たらその情報を基にON・OFFの制御に移る
  4. CTセンサから今の状態(ONかOFF)を10秒ほど計測
  5. リクエストと直前に計測した状態を比較してリクエスト通りの状態に変化

といった流れになります。

動作確認

動作確認は以前の記事にもあるように、Raspberry Piから送りますが、今回はESPにHTTPリクエストを送って、それを受け取ったら中身の情報(ON/OFF)によって加湿器を制御していきます。

同じプログラムを試したい方で、Raspberry Piを持っていない方もwindowsコマンドプロンプトから以下のようなコマンドを実行することによって動作します。また、192.168.??.???の部分は各環境に合わせて書き換えてください。

curl -H "x-access-key: HOGEHOGEON" http://192.168.??.???
curl -H "x-access-key: HOGEHOGEOFF" http://192.168.??.???

この二つで制御できるようにしてあります。

もちろんHOGEHOGEONやHOGEHOGEOFFのようにヘッダにのせている情報にONとOFFを付けくわえて単純に制御しています。HOGEHOGEの部分はHaLake利用者が勝手にいじれないように秘密の文字列を使用していますのでダミーが使われています。

Raspberry Piから制御する場合はRaspberry Piコマンドプロンプトで以下のように設定していきます。

crontab -e

を実行して下記を追記

00 6 * * 0,1,2,4,5,6 sudo curl -H "x-access-key: HOGEHOGEON" http://192.168.??.??
00 18 * * 0,1,2,4,5,6 sudo curl -H "x-access-key: HOGEHOGEOFF" http://192.168.??.???

cronを使うことによって指定した日時などに自動実行してくれるので便利です。

上記の設定では水曜以外の6時~18時の間で加湿器が稼働する設定になります。

おまけ(設計について)

今回は前回と同様にESP8266を使用していきますが、場合によっては制御側のハードウェアを変えることによって使い方に特化したものが作れます。

正直、使っているESP8266は微妙な性能ではありますが、暇しているものを使っているので妥協しています。

以前で紹介したプログラムは一部の書き換えとパラメータの調製でESP32でも動作するため、わかる人は変えてやってみるのも良いでしょう。

何が微妙かと言うと、大きく以下の2点があげられます。

  1. シングルコア
  2. 電圧が1Vまでしか測れない

シングルコアだと常時測定とWiFIなどでの通信が同時に行い辛いためです。

esp8266だとWiFIのクライアントと測定を同時に行うとどちらかがおろそかになります。

理由としては以下になります。

消費電力を正確な値または、常時測定する場合は割り込み処理できっちり決まった時間おきに測定した方が計算できれいな値が取れるのと、細かい間隔で測定しないと値がずれてしまうため、割り込み処理によるWiFi関係の処理が全くされなくなってしまいます。プログラムによってはこれらを回避することもできますが、これらを考慮しないといけないため面倒になります。

また、細かい間隔というのは大雑把に言って大体0.01秒以下での間隔です。標本化定理などからこの測定間隔はおおよ出せます。

関東のコンセントからは50Hzの交流電圧が来るのでセンサからは50Hzの交流のような電圧が測定できるため、50Hzのデータを正確に測るには少なくともこの2倍の周期でセンサから値を取得しなければなりません。

ja.wikipedia.org

そのため2倍すると100Hzで、この逆数が計測間隔に当たるため1/100 = 0.01秒となります。

それに加え、センサからはノイズなどが乗るためさらに細かい周期で計測しなければ精度が悪くなってしまいます。

そのため上記で示したプログラムでは0.001秒の間隔で測定しています。(ただ増やすだけが良いのかは未検証ですが、対策にはなると考えています。)

さらに今回の内容に関しては先ほど示した2番目にある電圧の測定範囲も重要なポイントになります。

これは、

  1. CTセンサの値は電圧の変化で返ってくるため1Vの測定範囲はそもそも狭い
  2. 電源電圧3.3VをCTセンサに向けて測定範囲の1Vまで分圧するのと、電圧が交流のように返ってくるためオフセットの電圧が必要でさらに分圧するため面倒
  3. 分圧によって測定のずれも出てくる(パラメータ調整で少しはごまかせるが。。。)

そのため、リソースをリッチに使いたい場合はESP32を使用することをお勧めします。しかしESP32では3.6Vまで測定できますが、誤差が乗ると公式でも言われているため、これも注意が必要です。

精度を極めるなら外部でADコンバータなどを付ける必要がありますが、そもそもセンサ自体の精度もあるのでそこまでする必要はないと思います。

また、WiFiを使わない場合は、Arudino UNOや小さいNanoなど、その他互換機を使用すると良いでしょう。

その場合はこちらの記事を参考にするとそのままできると思います。qiita.com

まとめ

  • 自宅や工場、会社など電気を扱う場所で電源や消費電力の管理を簡単にできそう。
  • はんだ付けや直接被膜の内側である導線を触ることなく測定できるのはとても便利だがリスクは多少ある

コメント

このブログの人気の投稿

Phaser3 + Typescriptを使ってRPGゲームの基礎を作ろう!その2

前回の記事 に引き続きPhaser3+Typescriptを使って RPG の基礎を作っていきます。 この記事は前回の記事を呼んだ前提で説明していきますので、ぜひそちらを先に読むことをお勧めします。 また、今回の記事は前回よりも難易度と内容量が上がっていますが、記事の最後に作業後の リポジトリ のリンクがありますので、そちらを先にダウンロードしてそちらと比較しながら学習することができます。 前回まで作成した状態のプログラムが以下の リポジトリ からダウンロードできますので前回まででうまくいっていない方は参考にしてみてください。 github.com 最終目標(再掲) ・Phaser3とTypescriptで RPG ゲームの基礎を作る。 ・Phaser3をTypescriptで使う方法を学ぶ ・Phaser3の使い方を学ぶ 今回の目標 ・ゲームの作り方の断片を知る ・キャラの表示できるようにする ・キャラを移動できるようにする ・当たり判定をつける ・ NPC の追加してみる ・話しかけられるようにする 開発前提(再掲) ・Nodejsの環境・知識がある ・ Javascript ・Typescriptがある程度かける ・当ページ紹介の環境を試す場合はgit・ github の知識がある 使用した主要Nodeモジュール(再掲) ・typescript(Typescriptの コンパイル 用) ・phaser(フロントの Javascript 用ゲームライブラリ) ・live-server(ソースを監視してブラウザのページをリロード) ・ts-loader(webpackがTypescriptをバンドルする用)webpack(言わずと知れたモジュール依存をいい感じに解決しバンドルする) ・webpack- cli (webpackを コマンドライン で使用するのに必要) 注:各Nodeモジュールバージョンは後述 当ブログ仕様の画像素材の注意点 当ブログで使用する画像素材は『 ピポヤ倉庫 』より許可なしで無償再配布・改変が認められたものを改変して作成されたものです。 中には許可なく再配布・改変してはいけない素材もインターネット上には多く存在するのでそれらを使用するときは十分に規約を呼んでから使用しましょう。 1. キャラの表示 想定画面 今回は、はじめにキャラつまり操作

M5Stackで、においセンサー(TGS2450)を使ってみる。(LCDに表示編)

今回は、においセンサー(TGS2450)から取得したデータをM5Stackの LCD にグラフ表示をしていきます。 今回主に使用したもの M5Stack 10Ω抵抗 5本 Pch  MOSFET  2SJ334(スイッチとして利用) M5StackSideBB(ブレッドボード) M5Stackのピンはそのままだと配線するとき手間がかかるかと思いますので、今回はM5StackSideBBを利用しました。 ブレッドボードも付いているので、手軽に電子工作できるので個人的にオススメです。 SideBB for M5Stack www.switch-science.com 諸注意 本ブログのプログラムはArduinoIDEまたはPlatformIOでM5Stackの開発ができる状態であること前提のものですので、各自導入をお願いします。 過去に Windows のArduinoIDEで M5Stackの開発環境を構築する記事 があるので、参考にしてください。 においセンサー(TGS2450)について 今回使用したセンサーは 秋月電子通商 で購入できます。 http://akizukidenshi.com/catalog/g/gP-00989/ akizukidenshi.com TGS2450には4つのピンがあり、使用するのはそのうちの3本でヒーターを温めるピン、センサー情報を得るピン、GNDがあります。 ここで注意したいのは、ヒーター電圧は1.6Vと記述されているのでM5Stackで利用するときは分圧して3.3Vを1.6V近くまでに降圧することをお勧めします。 TGS2450のセンサーは可変抵抗になっており、データシートには5.62kΩ〜56.2kΩの間を抵抗が変化し、においが強いとより低くなると記述されていました。 よって、センサーの値をM5Stackで取得するにはセンサー抵抗と外部に接続する任意の値の抵抗による分圧回路によって求めることができます。 TGS2450の動作方法は、250ms周期でセンサーに電圧を5ミリ秒on、245ミリ秒offの状態にしてヒーターは8ミリ秒on、242ミリ秒offにすることで値を取得します。 配線 においセンサーとM5Stackの配線 上の図が配線図です。 30Ωの抵抗は10Ωの抵抗を三つ直列に接続して作成しました。 また、上部の抵抗10Ω二

Phaser3 + Typescriptを使ってRPGゲームの基礎を作ろう!その1

今回はPhaser3とTypescriptを使って簡単な RPG ゲームを作る方法を紹介していきます。 内容はPhaser3およびゲーム作りについての記事なので、Nodejsの周辺モジュールなどの説明は一部省いての説明になりますのでご了承ください。 またこの記事では Phaser2 ではなく Phaser3 を使用するので注意してください。 この記事は二部構成になりますので、この記事を読んだ際はぜひ次の記事も読むことをお勧めします。 最終目標 ・Phaser3とTypescriptで RPG ゲームの基礎を作る。 ・Phaser3をTypescriptで使う方法を学ぶ ・Phaser3の使い方を学ぶ 今回の目標 ・開発環境を整える ・Phaser3の開発構成を知る ・スタート画面を作る ・マップ表示をさせる 開発前提 ・Nodejsの環境・知識がある ・ Javascript ・Typescriptがある程度かける ・当ページ紹介の環境を試す場合はgit・ github の知識がある 使用した主要Nodeモジュール ・typescript(Typescriptの コンパイル 用) ・phaser(フロントの Javascript 用ゲームライブラリ) ・live-server(ソースを監視してブラウザのページをリロード) ・ts-loader(webpackがTypescriptをバンドルする用)webpack(言わずと知れたモジュール依存をいい感じに解決しバンドルする) ・webpack- cli (webpackを コマンドライン で使用するのに必要) 注:各Nodeモジュールバージョンは後述 1. 最低限の開発環境の準備 今回最低限の環境を整えるために、『Typescript + Phaser3』の開発テンプレートを github リポジトリ で公開しました。 以下からZIPをダウンロードするか、 git clone コマンドで各自環境に展開してみてください。 ここから先は リポジトリ のプログラムを元に説明していきます。 github.com 展開するとファイル構造は以下のようになっているかと思われます。 注: 他にもファイルやフォルダがあるかと思われますが、表記されているのは今回使うものになっています。 - src/ (これから書くプログラムの保存領域)