工業製造
産業用モノのインターネット | 工業材料 | 機器のメンテナンスと修理 | 産業プログラミング |
home  MfgRobots >> 工業製造 >  >> Manufacturing Technology >> 製造プロセス

MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御

部品と材料

部品名 数量 備考
Espressif ESP8266 ESP-01 1 温度センサーノード用 Wi-Fi モジュール
Arduino Nano R3 1 温度センサーノード制御用
Microchip ATtiny85 1 超小型温度センサーノード用
DHT22 温湿度センサー 1 高精度温湿度測定
サーボモーター (Tower Pro MG996R) 2 ダンパー開閉用 (上階/下階)
MediaTek LinkIt Smart 7688 Duo HDK 1 メインコントローラー (OpenWRT + Arduino 互換 MCU)

使用アプリとオンラインサービス

プロジェクト概要

冬の到来

第一子が生まれた昨冬、赤ちゃんの周囲を暖かく保つため電気ヒーターを購入しました。部屋を移動するたびにヒーターを持ち運び、「ポイントユース気候制御で効率的だ」と思っていました。しかし一ヶ月後の電気代は普段の 2 倍。ガスファンヒーターで家全体を 24 時間暖房する方が安かったのです。

MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御

今年も冬が来るため、Wi-Fi サーモスタットにアップグレードし、ベッドの中や階下からヒーターを操作できるようにしました。便利にはなりましたが、家族が一つのエリアにいるだけなのに家全体を暖めることには変わりありません。

賢く働く

照明制御用のモーションセンサーログを見ると、平日月〜金は実に規則的です。仕事から帰宅後、家族でリビング (下階) で 4〜5 時間過ごし、午後 9 時頃に寝室 (上階) に移動、翌朝出勤までそこで過ごします。週末はパターンが異なりますが、平日は時計仕掛けのように決まっています。

MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御
MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御

マルチゾーン温度監視とワイヤレス制御ダンパーを備えた HVAC システムを調べましたが、ハードウェアが高価で、ソフトウェアは後付け感が強く (サポートやアップデートも期待薄)。すでに家には Wi-Fi 対応温度センサー (ポイントユース エアコン制御用に自作) があり、小型サーボをプロジェクトで使いたかったのです。必要なのは「Wi-Fi 接続されたサーボで HVAC のダンパーを開閉すること」だけ。これなら簡単そうでした。

MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御

MediaTek LinkIt™ Smart 7688

MediaTek の新しい LinkIt Smart 7688 Duo HDK は、OpenWRT を搭載した Wi-Fi 接続マイクロプロセッサーに、オンボードで Arduino 互換マイクロコントローラーを備えています。このプロジェクトに最適です。複数のセンサーとサーボモーターに必要な I/O ピンと Wi-Fi 機能を備え、既存の温度センサーと通信できます。さらに、OpenWRT に標準で uHTTPd が入っているため、Web アプリを LinkIt Smart 7688 HDK 上で直接動かせ、完全なスタンドアロンパッケージが実現できます。

MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御
MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御

LinkIt Smart 7688 HDK のセットアップ

内蔵 Wi-Fi 搭載ボードは初めてで、学習曲線が急かと覚悟していましたが、セットアップは文字通り 3 ステップ で完了しました:

  1. LinkIt Smart 7688 に電源投入し、PC からその Wi-Fi アクセスポイントに接続
  2. Web インターフェースにログインし、自宅の Wi-Fi アクセスポイント設定を入力
  3. Arduino IDE に「LinkIt Smart 7688 Duo」ボードを追加

以上です! Arduino IDE でボードを選択すれば、シリアル経由でスケッチ書き込みも、Wi-Fi 経由での書き込みも可能です (後者は後で非常に便利)。公式の Getting Started ガイド と Developer Guide も参考になります。

MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御

Arduino スケッチからマイクロコントローラーが直接 Wi-Fi を使えるようにするには (今回はこれを使用)、HDK に SSH 接続してビットを反転し、Arduino Yun ライブラリ互換を有効化します。

MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御
MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御

以下のコマンドをコピペで実行:

# Yun ブリッジ有効化コマンド (詳細は公式ドキュメント参照)

Wi-Fi クライアントとサーボコントローラー

Yun Bridge ライブラリ互換があり Arduino IDE が使えるため、既存コードの移植が容易です。Bridge ライブラリを使って、オンボード Web サーバーをポーリングし、ベント設定 (上階/下階/全館) を取得して 2 つのサーボを制御します。下記動画では Raspberry Pi 2 で動かしていましたが、Web アプリを LinkIt Smart 7688 に移植してさらに効率化しました (コードは後述)。

Web アプリは PHP で動作するため、OpenWRT の opkg パッケージマネージャーでインストール:

opkg update
opkg install php7 php7-cgi

/etc/config/uhttpd に以下を追加して PHP インタープリターを有効化:

list interpreter ".php=/usr/bin/php-cgi"

uHTTPd を再起動:

/etc/init.d/uhttpd restart

ハードウェア

サーボホーンをダンパーに直接取り付け、アルミブラケットを製作してサーボをステンレススペーサーで固定しました。まだわずかな遊びがあるため、タイラップでより永久的に固定する予定です。

MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御
MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御

ソフトウェア

この構成は主に 3 コンポーネントで構成されます:

MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御

温度センサーノードは ATtiny85 または Arduino Nano に DHT11/DHT22 を接続し、ESP8266 経由でソフトウェアシリアル通信により Web サーバーにデータ送信します。これらは元々「ポイントユース エアコンプロジェクト」の第 2 段階として開発したものです (詳細は別記事参照。この部分はオプションですが、システムチューニングと将来的な自動化に役立つメトリクスが得られます)。

LinkIt Smart 7688 HDK 自体は屋根裏に設置し、ダクトベントに直接接続。OpenWRT 側で cron ジョブがベント状態テキストファイルを更新。MCU 側の Arduino スケッチがこのファイルを定期的にチェックし、それに従ってベントを調整します。

ベント状態の確認と手動再設定のため、LinkIt Smart 7688 上で直接ホストされる小さな Web アプリを作成。Dynamic DNS とポートフォワーディングで外出先からも閲覧・制御可能です。

改善の余地

夜が冷え込んできたため、急ピッチで動作させる必要があり、迅速な展開のためにいくつか妥協しました。

ソースコード

LinkIt Smart Duo WiFi Vent (C/C++)

Arduino Yun の Bridge と HTTP Client ライブラリを使用し、Web サーバーをポーリングして HVAC ベントを開閉します。

/* Sweep サーボ例 (BARRAGAN) と Yun HTTP Client 例 (Tom Igoe) を改変
   両方ともパブリックドメイン
   HAI (Home Automation w/ Intelligence) 用に Buddy Crotty が改変

   このスケッチは Web サーバーに重い処理を任せる。
   Web サーバーは別デバイス (Raspberry Pi 等) でも、LinkIt Smart の MPU 側 (OpenWRT) でも可。

   Web サーバーは家中の温度読み取りを収集し、時間帯、外気予報、在宅状況に基づき
   どこに冷暖房風を送るべきか判断し、'upstairs', 'downstairs', 'wholehouse' のいずれかを出力。
*/

#include <Servo.h>
#include <Bridge.h>
#include <HttpClient.h>

Servo upservo;    // 上階用サーボ
Servo downservo;  // 下階用サーボ
int uppos = 0;    // 上階サーボ位置
int downpos = 0;  // 下階サーボ位置

const char* host = "192.168.1.80";  // ホームオートメーション Web サーバー内部 IP

int dopenangle = 80;   // 下階ベント開角度
int dcloseangle = 0;   // 下階ベント閉角度
int uopenangle = 140;  // 上階ベント開角度
int ucloseangle = 0;   // 上階ベント閉角度

void setup() {
    upservo.attach(9);    // 上階ベントダンパー用サーボピン
    downservo.attach(10); // 下階ベントダンパー用サーボピン
    pinMode(13, OUTPUT);
    digitalWrite(13, LOW);
    Bridge.begin();       // OpenWRT とのブリッジ開始
    digitalWrite(13, HIGH);
}

void wholehouse() {
    if (downpos <= dcloseangle) {
        for (downpos = dcloseangle; downpos <= dopenangle; downpos++) {
            downservo.write(downpos);
            delay(20);
        }
    }
    if (uppos <= uopenangle) {
        for (uppos = ucloseangle; uppos <= uopenangle; uppos++) {
            upservo.write(uppos);
            delay(20);
        }
    }
}

void downstairs() {
    if (downpos <= dopenangle) {
        for (downpos = dcloseangle; downpos <= dopenangle; downpos++) {
            downservo.write(downpos);
            delay(20);
        }
    }
    if (uppos >= ucloseangle) {
        for (uppos = uopenangle; uppos >= ucloseangle; uppos--) {
            upservo.write(uppos);
            delay(20);
        }
    }
}

void upstairs() {
    if (uppos <= uopenangle) {
        for (uppos = ucloseangle; uppos <= uopenangle; uppos++) {
            upservo.write(uppos);
            delay(20);
        }
    }
    if (downpos >= dcloseangle) {
        for (downpos = dopenangle; downpos >= dcloseangle; downpos--) {
            downservo.write(downpos);
            delay(20);
        }
    }
}

void loop() {
    HttpClient client;
    String cmd = "https://";
    cmd += host;
    cmd += "/vent.txt";
    client.get(cmd);

    while (client.available()) {
        int c = client.read();
        if (c == '2') upstairs();
        if (c == '1') downstairs();
        if (c == '0') wholehouse();
    }
    delay(60000); // 1分ごとにポーリング
}

WiFi 温度センサー (C/C++)

温湿度センサー接続。ホームオートメーションサーバーにデータ記録。

/* HAI (Home Automation w/ Intelligence) 用に Buddy Crotty が改変
   HTTP GET リクエストで HAI サーバーにデータ送信
   接続性: ESP8266 WiFi モジュールへソフトウェアシリアル接続
   (予め自宅 wLAN に接続設定済みであること)
   WiFi 設定リセット用コードもコメントアウトで同梱
*/

const char* host = "192.168.1.80";  // HAI Web サーバー内部 IP
const char* devID = "downstairs";   // デバイス ID (英数字のみ、スペース/特殊文字不可)

#include <SoftwareSerial.h>
SoftwareSerial ser(10, 11); // (RX, TX) ESP8266 制御用
// ハードウェアシリアルはデバッグ用

long utime = 300000; // 更新間隔
// 900000 = 15分 (バッテリー/ソーラー駆動時)
// 300000 = 5分 (AC 電源時)
// 5000 = 5秒 (テスト時)
// ESP8266 がスリープから復帰するには 10000ms 以上必要 (バッテリー駆動時)

// 温湿度センサー
#include <DHT.h>
#define DHTPIN 2
#define DHTTYPE DHT22  // DHT11, DHT22 (AM2302), DHT21 (AM2301) から選択
DHT dht(DHTPIN, DHTTYPE);

void setup() {
    Serial.begin(9600);
    ser.begin(9600);
    
    /* WiFi 設定リセット用 (必要時のみアンコメント)
    delay(1000);
    ser.println("AT+CWMODE=1");
    ser.println("AT+CWJAP=\"SSID\",\"Password\"");
    */
    
    ser.println("AT+RST"); // Arduino リセットに合わせ ESP8266 もリセット
    delay(10);
    dht.begin();
    
    Serial.println("Giving everything a chance to warm up");
    Serial.println("|-------------------------|");
    Serial.print("|");
    for (int x = 0; x < 25; x++) {
        Serial.print("#");
        delay(1000);
    }
    Serial.println("|");
    Serial.println("Done");
}

float t = 0; int h = 0; float hi = 0;

void loop() {
    Serial.println();
    
    // 温湿度取得
    t = dht.readTemperature(true); // 華氏で取得
    h = dht.readHumidity();
    hi = dht.computeHeatIndex(t, h); // 熱指数
    
    // 送信値デバッグ出力
    Serial.print("Temperature: "); Serial.print(t); Serial.print(" *F\t");
    Serial.print("Heat Index: "); Serial.print(hi); Serial.println(" *F");
    Serial.print("Humidity: "); Serial.print(h); Serial.println("%\t");
    Serial.print("...connecting to "); Serial.println(host);
    
    // TCP 接続
    String cmd = "AT+CIPSTART=\"TCP\",\"";
    cmd += host; cmd += "\",80";
    ser.println(cmd);
    delay(1000);
    
    if (ser.find("Error")) {
        Serial.println("AT+CIPSTART error");
        return;
    }
    
    // GET リクエスト文字列作成
    String getStr = "GET /tempupdate.php?ID=";
    getStr += devID;
    getStr += "&field1="; getStr += t;      // 温度
    getStr += "&field2="; getStr += h;      // 湿度
    getStr += "&field3="; getStr += hi;     // 熱指数
    getStr += "\r\n\r\n";
    
    Serial.print("Sending data URL: "); Serial.println(getStr);
    
    // データ長送信
    cmd = "AT+CIPSEND=";
    cmd += String(getStr.length());
    ser.println(cmd);
    
    if (ser.find(">")) {
        ser.print(getStr);
        Serial.println("Success!");
    } else {
        ser.println("AT+CIPCLOSE");
        Serial.println("Connection Failed");
    }
    
    Serial.print("Next update in ");
    Serial.print(utime / 1000);
    Serial.println(" seconds");
    delay(utime);
}

Vent.php (PHP)

ベント状態確認と手動オーバーライド用 Web インターフェース。

<html>
<head>
<style>
.myButton {
    -moz-box-shadow: 0px 10px 14px -7px #276873;
    -webkit-box-shadow: 0px 10px 14px -7px #276873;
    box-shadow: 0px 10px 14px -7px #276873;
    background: linear-gradient(to bottom, #599bb3 5%, #408c99 100%);
    background-color: #599bb3;
    border-radius: 20px;
    display: inline-block;
    cursor: pointer;
    color: #ffffff;
    font-family: Arial;
    font-size: 100px;
    font-weight: bold;
    padding: 50px 200px;
    text-align: center;
    text-decoration: none;
    text-shadow: 0px 5px 0px #3d768a;
}
.myButton:hover {
    background: linear-gradient(to bottom, #408c99 5%, #599bb3 100%);
    background-color: #408c99;
}
.myButton:active { position: relative; top: 1px; }
</style>
<link rel="manifest" href="manifest.json">
</head>
<body>
<div align="center">
<a href="vent.php?zone=2" class="myButton">Upstairs Only</a><br><br>
<a href="vent.php?zone=0" class="myButton">Whole House</a><br><br>
<a href="vent.php?zone=1" class="myButton">Downstairs Only</a>
<br><br>

<?php
$myfile = fopen("vent.txt", "r") or die("Unable to open file!");
$status = fgets($myfile);
if ($status != "") print "<h1>Vents currently open for ";
if ($status === "0") print "the Whole House";
if ($status === "1") print "Downstairs Only";
if ($status === "2") print "Upstairs Only";
print "<br>";
fclose($myfile);

if ($_GET["zone"] == "");
else {
    $myfile = fopen("vent.txt", "w+") or die("Unable to open file!");
    if ($_GET["zone"] != "") print "<h1>Sending command to open vents for ";
    if ($_GET["zone"] === "0") print "the Whole House";
    if ($_GET["zone"] === "1") print "Downstairs Only";
    if ($_GET["zone"] === "2") print "Upstairs Only";
    print "</h1>";
    fwrite($myfile, $_GET['zone']);
    fclose($myfile);
}
?>
</div>
</body>
</html>

LinkIt Smart Vent Android WebApp (JSON マニフェスト)

Chrome on Android でベントコントローラーを Web アプリとして開くためのマニフェスト。

{
  "name": "LinkIt Smart Vent",
  "icons": [
    { "src": "LinkIt_icon_36.png", "sizes": "36x36", "type": "image/png", "density": 0.75 },
    { "src": "LinkIt_icon_48.png", "sizes": "48x48", "type": "image/png", "density": 1.0 },
    { "src": "LinkIt_icon_128.png", "sizes": "128x128", "type": "image/png", "density": 1.0 },
    { "src": "LinkIt_icon_192.png", "sizes": "192x192", "type": "image/png", "density": 1.0 }
  ],
  "start_url": "vent.php",
  "display": "standalone",
  "orientation": "portrait"
}

回路図

ATtiny85 または Arduino Nano で DHT11/22 から温度取得、ESP8266 で Wi-Fi 接続。

MediaTek LinkIt™ Smart 7688 を用いたスマートゾーニング気候制御

製造プロセス

  1. QR・RFID・体温検知統合アクセス制御システム(Raspberry Piベース)
  2. スマート貯金箱を作ろう:Arduino Nanoでコインアクセプターを制御
  3. 自作Arduino TVリモコン:電池駆動・3Dプリントケース・省電力設計
  4. ArduinoでBluetooth経由でLEDを制御 – シンプルDIYガイド
  5. Arduino Nanoとジョイスティックで2軸ステッピングモーターを制御:Visuinoで簡単プログラミング
  6. Windows 10 CortanaでBluetooth経由でArduinoのLEDを制御
  7. 品質管理の向上:3Dプリント工具が製造精度を高める
  8. GÖPEL、ユニバーサルロボットのUR10e協働ロボットで自動車品質管理を強化
  9. スマートな調達:AIと人間の洞察(HI)を融合させる
  10. Millport SmartLathez 1740 CNC旋盤 – 精度とパワー
  11. DATA MODUL、スマートWi-Fi制御搭載23.1インチ超薄型TFTディスプレイを発表