Project tutorial
Zoned Climate Control with MediaTek's LinkIt™ Smart 7688

Zoned Climate Control with MediaTek's LinkIt™ Smart 7688 © Apache-2.0

Control the temperature of the rooms you are actually in

  • 8,467 views
  • 5 comments
  • 21 respects

Components and supplies

Apps and online services

About this project

Winter is coming

When my wife and I had our first child last winter, we got an electric space heater to keep the area immediately around our baby girl nice and warm.  As we moved from room to room, we brought the heater with us, all the while thinking we were being super efficient having point-of-use climate control.  A month later we get an electricity bill twice our normal amount and realize it would have been cheaper to just heat the whole house with the gas furnace around the clock.

Winter is upon us again, so this time I upgraded to a WiFi thermostat so I can turn on the heater while I'm downstairs or warmly tucked under the covers.  This is much more convenient, but we're still heating the whole house even though most of the time we're all in one part of the house.

Work Smarter

Looking at our motion sensor logs that control our lighting, it's pretty obvious that we spend 4-5 hours downstairs as a family after work, and then go upstairs to our bedrooms around 9pm where we sleep until we leave the next morning for work.   Weekends are a little different, but Monday through Friday works like clockwork (especially with a 10 month old on a strict sleep schedule).

I've looked at HVAC systems that have multi zone temperature monitoring and wirelessly controllable duct baffles, but the hardware is very expensive and all the software looks like it was an afterthought (with little support or updates as technology gets better).  I already have some WiFi enabled temperature sensors in my house for point of use AC unit controllers and have been itching for a reason to use some small servos in a project.  All I need are WiFi connected servos that can open/close duct vents in my HVAC system...should be easy enough.

MediaTek's LinkIt™ Smart 7688  

MediaTek's new LinkIt Smart 7688 Duo HDK is a WiFi connected microprocessor running OpenWRT with an onboard arduino-compatible microcontroller.  It's perfect for this project since it has all the I/O pins needed for multiple sensors and servo motors plus WiFi capability to communicate with my existing temperature sensors.  Also, since it already has OpenWRT installed with uHTTPd, I can run the WebApp directly on the LinkIt Smart 7688 HDK for a completely self contained package.

Setting up the LinkIt Smart 7688 HDK

This is my first time using a board that has built in WiFi, so I was preparing for a steep learning curve.  Fortunately, setup is literally 3 steps:

  • Power up the Linkit Smart 7688 and connect to its WiFi access point from your computer
  • Log in to the web interface and enter the settings for your WiFi access point
  • Add the "LinkIt Smart 7688 Duo" board in the Arduino IDE

That's it! When you select the "LinkIt Smart 7688 Duo" board in the Arduino IDE you can either push your sketch via serial like every other board, or you can upload over WiFi (this will come in very handy later). The Linkit Smart 7688 getting started guide and developers guide may be helpful for you as well. 

If you want to allow the microcontroller to use the WiFi directly in your arduino sketch (which we will be doing), you just ssh into the HDK and flip a bit to enable the Arduino Yun library compatibility.  

You can just copy/paste the lines from here:

uci set yunbridge.config.disabled='0'uci commitreboot

WiFi Client and Servo Controller

Since this has built in compatibility with the Yun bridge library and uses the Arduino IDE, it's really easy to adapt existing code.  Using the bridge library, I can have the HDK poll the onboard web server for the vent configuration (either upstairs, downstairs, or whole house) and then adjust the two servos accordingly.   In the below video I had this running on a Raspberry Pi 2, but I was able to port the WebApp over to the LinkIt Smart 7688 to make it even more efficient (code included at the end).

My WebApp runs on php, so I just used opkg package manager to get it installed since it's included in OpenWRT on the LinkIt Smart 7688:

opkg install php5-cgi

I then updated the /etc/config/uhttpd file to interpret php by adding this line:

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

and restarted uHTTPd

/etc/init.d/uhttpd restart
Demo

Hardware 

I attached the servo horn directly to the vent and fabricated an aluminum bracket to hold the servo in position with some stainless steel standoffs.  There is still a little play, so I'll be adding some zip ties to make this a little more permanent.  

Software

This build really boils down to three components:

  • Temperature sensors around the house send periodic updates to the uHTTPd web server running on the LinkIt Smart 7688.
  • A WebApp running on the LinkIt Smart 7688 that shows the current state and allows you to manually reconfigure the vents.
  • The MCU on the LinkIt Smart 7688 that controls the vents to direct warm air either upstairs or downstairs depending on the time of day.

The temp sensors are just ATtiny85s or Arduino Nanos connected to a DHT11 or DHT22 and sending that temperature/humidity information to a web server via an ESP8266 over software serial.  I have a full writeup on those sensors on here since they were originally designed and developed as phase II of my point-of-use air conditioner project (this part is completely optional, but it will give you additional metrics that can be used to tune the system and eventually automate it).

The LinkIt Smart 7688 HDK itself is in my attic connected directly to the duct vents. On the OpenWRT side a cronjob updates the vent state text file.  The MCU side running the arduino sketch checks this text file periodically and adjusts the vents accordingly.

# Open downstairs vent at 3pm on weekdays0 15 * * 1-5 /bin/echo 1 > /www/vent.txt# Open both vents at 6pm on weekdays0 18 * * 1-5 /bin/echo 0 > /www/vent.txt;# Close downstairs vent at 9pm on weekdays0 21 * * 1-5 /bin/echo 2 > /www/vent.txt;# Close upstairs vent at 9am on weekdays0 9 * * 1-5 /bin/echo 1 > /www/vent.txt;

To check the status of the vents and manually reconfigure them, I created a small WebApp that is hosted directly on the LinkIt Smart 7688.  With dyndns and port forwarding I can view and control all of this from outside the house if I need to.

Room To Improve

With the nights already getting colder, I needed to get this working ASAP so some concessions were made in the name of rapid deployment.  On the hardware side, I'll be 3d printing proper mounts for the servos since my hack-job mounts have a little play.  Also, the little RC servo I used in the demo has all plastic gears which I don't expect to last for years, so since I don't want to be climbing back in the attic anytime soon, I'm going to be swapping them out for larger servos with metal gears.

I may one day add additional WiFi connected servos to vents in each room and have them all connect back to the single LinkIt Smart 7688.  

Currently the temperature probes are only dumping the readings to a csv file so I can easily track and graph it.  It would be nice to kick on the heater early if the house is particularly cold, but my WiFi thermostat doesn't have an API yet.  I would also like to tie into my home automation system so the vents automatically adjust based on real time room occupancy derived from motion sensors rather than being entirely based on time of day (especially for weekends because of our dynamic schedules).

Code

LinkIt Smart Duo WiFi VentC/C++
This sketch uses the Bridge and HTTP Client libraries from the Arduino Yun to poll a web server and open/close HVAC vents as needed.
/* 
 Adapted from Sweep servo example 
 by BARRAGAN <http://barraganstudio.com> 
    and
 Yun HTTP Client example
 created by Tom igoe  <http://www.arduino.cc/en/Tutorial/HttpClient>
*
* Both are in the public domain.
*
*
* Code Adapted for HAI (Home Automation w/ Intelligence) by Buddy Crotty
*
* This arduino sketch relies on a web server to do all the heavy lifting.  This can be
a seperate device like a Raspberry Pi, or you can run it on the MPU side of the LinkIt Smart in
OpenWRT.
*
* The web server collects temp readings from around the house and determins where hot/cold air
needs to go based on time of day, outside weather (including forcast), and home occupancy.
*
* It then outputs 'upstairs', 'downstairs', or 'wholehouse' depending on where the air needs
to be sent.  
*/

#include <Servo.h> 
#include <Bridge.h>
#include <HttpClient.h>
 
Servo upservo;      // create servo object to control upstairs servo 
Servo downservo;   // downstairs air vent damper servo            
 
int uppos = 0;      // variable to store the (upstairs) servo position 
int downpos = 0;    // downstairs servo position   
const char* host = "192.168.1.80";         // Internal IP of Home Automation Webserver
int dopenangle = 80;               // Number of degrees your servo needs to turn between open/close on the vent
int dcloseangle = 0;     
int uopenangle = 140;     
int ucloseangle = 0;     

void setup() 
{ 
  upservo.attach(9);      // Pin for Servo attached to upstairs air vent damper
  downservo.attach(10);   // Pin for Servo attached to downstairs air vent damper
  
  //start bridge to OpenWRT
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  Bridge.begin();
  digitalWrite(13, HIGH);
} 

void wholehouse()
{
  if (downpos <= dcloseangle){                                            // Make sure vent isn't already in position
   //open downstairs vent
    for(downpos = dcloseangle; downpos <= dopenangle; downpos += 1)       // Move from set close angle to open angle one step at a time
    {                                                                     
      downservo.write(downpos);                                           
      delay(20);                                                           // waits between steps until servo reaches position
    } 
  }

  if (uppos <= uopenangle) {
    //open upstairs vent
    for(uppos = ucloseangle; uppos <= uopenangle; uppos += 1)      
    {                                   
      upservo.write(uppos);              
      delay(20);                        
    }    
  }
}


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

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

void loop()
{
  HttpClient client;
  // Create and make a HTTP request:
  String cmd = "http://";
  cmd += host;
  cmd += "/vent.txt";
  client.get(cmd);
  // Read incoming bytes from the server 
  while (client.available()) {
    int c = client.read();
      if (c == '2') upstairs();
      if (c == '1') downstairs();
      if (c == '0') wholehouse();
  }
  delay(60000);
}
WiFi Temp SensorC/C++
Connected Temperature and Humidity sensor. Logs data to central Home Automation server.
/*
 *  Code Adapted for HAI (Home Automation w/ Intelligence) by Buddy Crotty
 *
 *  Sends data via HTTP GET requests to your HAI server
 *
 *  Connectivity is via software serial connection to an ESP8266 WiFi 
 *  interface already configured to connect to your wLAN,
 *  but you can uncomment out the WiFi settings to reset SSID/password
 *  
 */

const char* host = "192.168.1.80";         // Internal IP of Home Automation Webserver
const char* devID = "downstairs";           // Device ID (single word, no spaces, no special characters)
 
#include <SoftwareSerial.h>

SoftwareSerial ser(10, 11); // (RX, TX)      // Software serial for controling ESP8266 Module
                                             // Hardware serial for debugging

long utime = 300000;  // Time in between updates 
                      // 900000 = 15 minutes (for battery/solar power)
                      // 300000 = 5 minutes (for AC power)
                      // 5000 = 5 seconds (for testing)
                      // Must be longer than 10000 for ESP8266 to come out of sleep mode (battery mode)
                       
// Temperature and Humidity Sensor 
#include <DHT.h>
#define DHTPIN 2        //Pin for temp/humidity sensor
#define DHTTYPE DHT22   // DHT11, DHT22 (AM2302, or DHT21 (AM2301)
DHT dht(DHTPIN, DHTTYPE);

void setup() {
  Serial.begin(9600);
  ser.begin(9600);
  //ser.listen();

  /*
  // Uncomment to reset WiFi settings
    delay(1000);
    ser.println("AT+CWMODE=1");
    ser.println("AT+CWJAP=\"SSID\",\"Password\"");
  */
 
  ser.println("AT+RST");        // Reset ESP8266 since arduino was reset
  
  delay(10);
  dht.begin();                  // Start DHT
  
  Serial.println("Giving everything a chance to warm up");          //wait 25 seconds for WiFi to connect
  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();

    //Temp and Humidity  
    float t = dht.readTemperature(true);
    int h = dht.readHumidity();
    float hi = dht.computeHeatIndex(t, h);

// Output values being sent to ThingSpeak
  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 connection
  String cmd = "AT+CIPSTART=\"TCP\",\"";
  cmd += host;             
  cmd += "\",80";
  ser.println(cmd);
    delay(1000); 
  if(ser.find("Error")){
    Serial.println("AT+CIPSTART error");
    return;
  }
  else{
  }

  // prepare GET string
  String getStr = "GET /tempupdate.php?ID=";
  getStr += devID;
  getStr += "&field1="; //Temp
  getStr += t;
  getStr += "&field2="; //Humidity
  getStr += h;
  getStr += "&field3="; //Heat Index
  getStr += hi;
  getStr += "\r\n\r\n";

  Serial.print("Sending data URL: ");
  Serial.println(getStr);

  // send data length
  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");        // alert user
  }

Serial.print("Next update in ");
Serial.print(utime / 1000);
Serial.println(" seconds");

delay(utime);         //wait between updates
    
}
Vent.phpPHP
Check status and manually override the vent configuration.
<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:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #599bb3), color-stop(1, #408c99));
        background:-moz-linear-gradient(top, #599bb3 5%, #408c99 100%);
        background:-webkit-linear-gradient(top, #599bb3 5%, #408c99 100%);
        background:-o-linear-gradient(top, #599bb3 5%, #408c99 100%);
        background:-ms-linear-gradient(top, #599bb3 5%, #408c99 100%);
        background:linear-gradient(to bottom, #599bb3 5%, #408c99 100%);
        filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#599bb3', endColorstr='#408c99',GradientType=0);
        background-color:#599bb3;
        -moz-border-radius:20px;
        -webkit-border-radius:20px;
        border-radius:20px;
        display:inline-block;
        cursor:pointer;
        color:#ffffff;
        font-family:Arial;
        font-size:100px;
        font-weight:bold;
        /*padding:13px 80px;*/
        padding: 50px 200px;
        text-align: center;
        text-decoration:none;
        text-shadow:0px 5px 0px #3d768a;
}
.myButton:hover {
        background:-webkit-gradient(linear, left top, left bottom, color-stop(0.05, #408c99), color-stop(1, #599bb3));
        background:-moz-linear-gradient(top, #408c99 5%, #599bb3 100%);
        background:-webkit-linear-gradient(top, #408c99 5%, #599bb3 100%);
        background:-o-linear-gradient(top, #408c99 5%, #599bb3 100%);
        background:-ms-linear-gradient(top, #408c99 5%, #599bb3 100%);
        background:linear-gradient(to bottom, #408c99 5%, #599bb3 100%);
        filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#408c99', endColorstr='#599bb3',GradientType=0);
        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 WebAppJSON
Manifest file so chrome on Android opens up the vent controller as a web app.
{
  "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"
}

Schematics

WiFi Temp Sensor
ATtiny85 or Arduino Nano pulling temps from a DHT11/22 and WiFi connected with an ESP8266.
Wifi temp sensor

Comments

Similar projects you might like

OH HAI! on Windows 10 IoT Core

Project in progress by BuddyC

  • 12,531 views
  • 3 comments
  • 48 respects

Alexa Based Smart Home Monitoring

Project tutorial by Adithya TG

  • 16,641 views
  • 19 comments
  • 47 respects

Home Smart Home

Project tutorial by Syed Sanoor

  • 68,551 views
  • 10 comments
  • 193 respects

WiFi IR Blaster

Project tutorial by BuddyC

  • 85,675 views
  • 43 comments
  • 89 respects

IR Controller for Air Conditioner

Project in progress by BuddyC

  • 32,436 views
  • 8 comments
  • 22 respects

IoT arduino ESP Garage Door opener (UD)

Project in progress by David Smerkous

  • 10,859 views
  • 6 comments
  • 16 respects
Add projectSign up / Login