Autostat : a Remote Thermostat

3,929

22

1

The question you are probably asking is "why are you making another remote thermostat?"

The answer to that question is, I had to, and the market smart thermostats are too expensive.

Fair warning, this is "proof-of-concept" build that would require a few extra outputs to actually control your thermostat, but the core is in place and can be modified depending on your specific circumstance. Also, this is still a work in progress, so expect a few updates and changes (especially to the Matlab code)

To get started I want to warn you, this requires three programs (one of them is pretty expensive), quite a few libraries and support packages for the programs, and you need to have them all speak to each other. Its a headache. With that warning out of the way lets get started with the materials.

Hardware

  • arduino nano
  • arduino uno (or another nano, I just used the uno because I had one laying around)
  • assorted jumper cables, some male/male and two sets of three joined male/female jumpers
  • 433MHz radio frequency(RF) receiver, I used the MX-05V
  • 433MHz RF transmitter, I used the MX-FS-03V
  • DHT11 high accuracy thermometer and humidity sensor (the one I used is installed on a three prong chip with the required resistors already installed)
  • breadboard (if you don't want to solder this all together)
  • a phone with GPS (iPhone 8 in this case, but I've also used a Galaxy S8)
  • 3D printed container (not really necessary, any container will work or none at all)

Software

  • Matlab from MathWorks (I have the 2018a edition, but I've used 2017a-b editions as well)
  • Matlab mobile installed on your phone
  • arduino support package for Matlab
  • iPhone sensor package for Matlab
  • arduino IDE
  • RadioHead support packages and libraries of the arduino IDE
  • DHT11 library for arduino IDE
  • python 3.7 (make sure the pyserial library or serial library is installed, which it should be for version 3.4 or newer)

Step 1: Putting It All Together

First of all I would suggest you do a few arduino tutorials dealing with the RF transmitters just to make sure that your parts are working and the wiring is correct. There are plenty of examples available, with the code included (for those of us out there that know little to nothing about C and C++).

Follow the wiring diagrams below to get the arduino and sensors assembled. One thing to keep in mind while wiring up the arduinos is that the data ports I used are not required but recommended.

IF you do decide to change the data ports you use, you just need to define the pins in your code. Personally, I think it's easier to stick with the default ports that the arduino libraries recognize.

And just to be clear, the nano and uno are interchangeable, but I used the nano for the transmitter side of the project to reduce the size of the temperature monitor.

Side note: the green contraption holding the nano is the 3D printed container.

Step 2: Receiver

Step 3: Transmitter

Step 4: The Code

Once the wiring is finished you need to get all the programs running and the libraries installed (if you haven't already), I'll just assume you have, you need to start up Matlab and run the iPhone support package. Both your phone and Matlab need to be on the same wifi network at this point.

In the command window of Matlab write:

connector on

This will prompt you to enter a five digit password that you will use to connect on your iPhone. Make sure you remember the password. When you have entered the password Matlab will display some information, including your IP address. Use this in the next step, which comes from the instructions from the "Getting started with sensors" help menu in Matlab mobile.

  • Follow these steps to send sensor data to MathWorks Cloud or a computer:
  • If you are sending sensor data to a computer and if it is not already installed, download and install the MATLAB Support Package for Apple iOS Sensors in MATLAB.
  • Connect MATLAB Mobile to MathWorks Cloud or a computer using Settings.
  • Create mobiledev object in MATLAB(on your computer), for example: >> m = mobiledev
  • Select one or more sensors and tap Start.

Follow these steps to log sensor data locally on your device:

  • On the Sensors screen, select the sensors that you wish to collect data from.
  • Select Log.
  • Tap the Start button.
  • When you are done collecting data, tap the Stop button.
  • In the pop-up, enter the name of sensor log.
  • Repeat steps 1-5 if needed.

This section will be referred back to in Part 4, so no need to actually start collecting data yet. Just keep your phone handy and Matlab mobile ready.

Now you need to create a folder somewhere in you computer to house the Matlab code files. You'll have four separate files, two for the background functions (.m files) and one Matlab code file for the GUI (.mlapp),.

First is the mass calculation for the air in your house (this lets Matlab know how long it takes to heat/cool your house)

function [Mass]= CalcMass(T_ins,P_out,Chng_dir)
runCalc=0;
Tmp_start=T_ins;
time_start=clock;
time_end = 0
while runCalc <= 1
    if T_ins==(Tmp_start+(7*Chng_dir))
        time_end=clock;
        PwrCntr = 0;
        runCalc=0;
    else PwrCntr = P_out;
        runCalc=runCalc+0.1
    end
end
time_diag= time_end-time_start
Mass=(P_out*time_diag)/7.035

And the second one:

function [timestamps, pwr_usage]= dist_cntrl(Lat_in,Lon_in,P_out,r_pref,speed,T_pref,mass)

AutoStat = 1;
i = 1;
while AutoStat == 1
    time_start=clock;
    m = mobiledev;
    t = csvread('values.csv',0,1);
    t= t(i);
    timestamps= [0,0,0,0,0,0];
    pwr_usage = 0;
    i = i+1;
   format longg;
   
    %haversine formula for calculating distance based on latitude and
    %longintude
    a_hav=(sind((m.Latitude-Lat_in)./2)).^2+cosd(Lat_in).*cosd(m.latitude).*(sind((m.Longitude-Lon_in)./2)).^2;
    c_hav= 2.*atan2d(sqrt(a_hav),sqrt(1-a_hav));
    d_hav= 6371.*c_hav;
    Dist=d_hav.*1000;
    
    %estimates your time to return
    time_rtn=(Dist-r_pref)./speed;
    
    %calculates the necessary thermostat setting based on power out put of
    %air conditioner and airmass of the home. 
    calcTmp_set=((-1.*P_out.*time_rtn)./(mass.*(1.005)))+T_pref;
    
    %determines whether the current thermostat setting needs to be changed
    if round(calcTmp_set) ~= round(t)
        timeACon = clock;
        PwrCntr = P_out;
        timeACon= timeACon + clock-time_start;
        cost=P_out*timeACon*rate;
        
    else
        PwrCntr = 0
        
        
    end 
    timestamps(end+1,[1:6]) = clock;
    pwr_usage(end+1,1)= PwrCntr;
    pause(5)
 
   
end
end

Both of these files are Matlab functions. You will not need to access them unless you plan on modifying them for specific needs, since you will be calling them from the GUI. Save both files separately, the first one as CalcMass.m and the second as dist_cntrl.m, those will be the names that the GUI code uses to call the functions, so unless you want to edit the rest of the code below, stick with the naming convention.

Before you get into the GUI code, you need to open the app designer for Matlab, which you can open by navigating in the Matlab menu bar, or by my favorite method which is entering the following command in the Matlab command window:

appdesigner

Once the app designer is open open a new app file (.mlapp) and delete all of the default code from the code window. Then replace all of it with the following and hit the run button.

classdef Control_1 < matlab.apps.AppBase

% Properties that correspond to app components
    properties (Access = public)
        UIFigure                     matlab.ui.Figure
        TabGroup                     matlab.ui.container.TabGroup
        SetupTab                     matlab.ui.container.Tab
        RunDiagnosticButton          matlab.ui.control.Button
        EnergyEfficiencyRatingEditFieldLabel  matlab.ui.control.Label
        EnergyEfficiencyRatingEditField  matlab.ui.control.NumericEditField
        PowerOutputRatingEditFieldLabel  matlab.ui.control.Label
        PowerOutputRatingEditField   matlab.ui.control.NumericEditField
        AvgLocalSpeedEditFieldLabel  matlab.ui.control.Label
        AvgLocalSpeedEditField       matlab.ui.control.NumericEditField
        DesiredDistancefromHouseEditFieldLabel  matlab.ui.control.Label
        DDFH                         matlab.ui.control.NumericEditField
        TemperatureDirectionSwitchLabel  matlab.ui.control.Label
        TemperatureDirectionSwitch   matlab.ui.control.Switch
        TempSettingsTab              matlab.ui.container.Tab
        Temperature1SpinnerLabel     matlab.ui.control.Label
        Temperature1Spinner          matlab.ui.control.Spinner
        Temperature2SpinnerLabel     matlab.ui.control.Label
        Temperature2Spinner          matlab.ui.control.Spinner
        Switch                       matlab.ui.control.Switch
        EditFieldLabel               matlab.ui.control.Label
        tempnow                      matlab.ui.control.NumericEditField
        GaugeLabel                   matlab.ui.control.Label
        Gauge                        matlab.ui.control.Gauge
        SavingsTab                   matlab.ui.container.Tab
        UIAxes                       matlab.ui.control.UIAxes
        ThisMonthCostEditFieldLabel  matlab.ui.control.Label
        ThisMonthCostEditField       matlab.ui.control.NumericEditField
        TotalSavingsEditFieldLabel   matlab.ui.control.Label
        TotalSavingsEditField        matlab.ui.control.NumericEditField
    end
    methods (Access = private)
        % Value changed function: tempnow
        function tempnowValueChanged(app, event)
            temp = app.tempnow.Value;
            temp=randi([60,90],1,50)
            app.Gauge.Value = 0
            for i = length(temp)
                app.Gauge.Value= temp(i)
                pause(1)
            end
        end
        % Value changed function: TemperatureDirectionSwitch
        function TemperatureDirectionSwitchValueChanged(app, event)
            way = app.TemperatureDirectionSwitch.Value;
            way= uint8(way)
            way = length(way)
            if way == 4
                Chng_dir = -1;
            else
                Chng_dir = 1;
            end
            Chng_dir;
        end
        % Value changed function: DDFH
        function DDFHValueChanged(app, event)
            r_pref = app.DDFH.Value;
            
        end
        % Value changed function: AvgLocalSpeedEditField
        function AvgLocalSpeedEditFieldValueChanged(app, event)
            speed = app.AvgLocalSpeedEditField.Value;
            
        end
        % Value changed function: PowerOutputRatingEditField
        function PowerOutputRatingEditFieldValueChanged(app, event)
            value = app.PowerOutputRatingEditField.Value;
            
        end
        % Value changed function: EnergyEfficiencyRatingEditField
        function EnergyEfficiencyRatingEditFieldValueChanged(app, event)
            value = app.EnergyEfficiencyRatingEditField.Value;
            
        end
        % Button pushed function: RunDiagnosticButton
        function RunDiagnosticButtonPushed(app, event)
             way = app.TemperatureDirectionSwitch.Value;
            way= uint8(way)
            way = length(way)
            if way == 4
                Chng_dir = -1;
            else
                Chng_dir = 1;
            end
            T_ins = app.tempnow.Value
            P_out = app.PowerOutputRatingEditField.Value
            CalcMass1(T_ins,P_out,Chng_dir)
        end
        % Value changed function: Temperature1Spinner
        function Temperature1SpinnerValueChanged(app, event)
            value = app.Temperature1Spinner.Value;
            
        end
        % Value changed function: Temperature2Spinner
        function Temperature2SpinnerValueChanged(app, event)
            value = app.Temperature2Spinner.Value;
            
        end
        % Value changed function: Switch
        function SwitchValueChanged(app, event)
            m = mobiledev;
            Lat_in = m.Latitude
            Lon_in = m.Longitude
            P_out = 0;
            r_pref = app.DDFH.Value;
            T_pref = app.Temperature1Spinner.Value;
            speed = m.Speed;
            mass = 200;
            speed = app.AvgLocalSpeedEditField.Value;
            Auto_Stat = app.Switch.Value;
            dist_cntrl(Lat_in,Lon_in,P_out,r_pref,T_pref,speed,mass)
        end
    end
    % App initialization and construction
    methods (Access = private)
        % Create UIFigure and components
        function createComponents(app)
            % Create UIFigure
            app.UIFigure = uifigure;
            app.UIFigure.Position = [100 100 640 480];
            app.UIFigure.Name = 'UI Figure';
            % Create TabGroup
            app.TabGroup = uitabgroup(app.UIFigure);
            app.TabGroup.Position = [1 1 640 480];
            % Create SetupTab
            app.SetupTab = uitab(app.TabGroup);
            app.SetupTab.Title = 'Setup';
            % Create RunDiagnosticButton
            app.RunDiagnosticButton = uibutton(app.SetupTab, 'push');
            app.RunDiagnosticButton.ButtonPushedFcn = createCallbackFcn(app, @RunDiagnosticButtonPushed, true);
            app.RunDiagnosticButton.FontWeight = 'bold';
            app.RunDiagnosticButton.Position = [465 78 103 23];
            app.RunDiagnosticButton.Text = 'Run Diagnostic';
            % Create EnergyEfficiencyRatingEditFieldLabel
            app.EnergyEfficiencyRatingEditFieldLabel = uilabel(app.SetupTab);
            app.EnergyEfficiencyRatingEditFieldLabel.HorizontalAlignment = 'right';
            app.EnergyEfficiencyRatingEditFieldLabel.Position = [8 425 135 22];
            app.EnergyEfficiencyRatingEditFieldLabel.Text = 'Energy Efficiency Rating';
            % Create EnergyEfficiencyRatingEditField
            app.EnergyEfficiencyRatingEditField = uieditfield(app.SetupTab, 'numeric');
            app.EnergyEfficiencyRatingEditField.Limits = [0 100];
            app.EnergyEfficiencyRatingEditField.ValueChangedFcn = createCallbackFcn(app, @EnergyEfficiencyRatingEditFieldValueChanged, true);
            app.EnergyEfficiencyRatingEditField.HorizontalAlignment = 'center';
            app.EnergyEfficiencyRatingEditField.Position = [158 425 100 22];
            % Create PowerOutputRatingEditFieldLabel
            app.PowerOutputRatingEditFieldLabel = uilabel(app.SetupTab);
            app.PowerOutputRatingEditFieldLabel.HorizontalAlignment = 'right';
            app.PowerOutputRatingEditFieldLabel.Position = [18 328 118 22];
            app.PowerOutputRatingEditFieldLabel.Text = 'Power Output Rating';
            % Create PowerOutputRatingEditField
            app.PowerOutputRatingEditField = uieditfield(app.SetupTab, 'numeric');
            app.PowerOutputRatingEditField.Limits = [0 Inf];
            app.PowerOutputRatingEditField.ValueChangedFcn = createCallbackFcn(app, @PowerOutputRatingEditFieldValueChanged, true);
            app.PowerOutputRatingEditField.HorizontalAlignment = 'center';
            app.PowerOutputRatingEditField.Position = [151 328 100 22];
            % Create AvgLocalSpeedEditFieldLabel
            app.AvgLocalSpeedEditFieldLabel = uilabel(app.SetupTab);
            app.AvgLocalSpeedEditFieldLabel.HorizontalAlignment = 'right';
            app.AvgLocalSpeedEditFieldLabel.Position = [27 231 100 22];
            app.AvgLocalSpeedEditFieldLabel.Text = 'Avg. Local Speed';
            % Create AvgLocalSpeedEditField
            app.AvgLocalSpeedEditField = uieditfield(app.SetupTab, 'numeric');
            app.AvgLocalSpeedEditField.Limits = [0 70];
            app.AvgLocalSpeedEditField.ValueChangedFcn = createCallbackFcn(app, @AvgLocalSpeedEditFieldValueChanged, true);
            app.AvgLocalSpeedEditField.HorizontalAlignment = 'center';
            app.AvgLocalSpeedEditField.Position = [142 231 100 22];
            % Create DesiredDistancefromHouseEditFieldLabel
            app.DesiredDistancefromHouseEditFieldLabel = uilabel(app.SetupTab);
            app.DesiredDistancefromHouseEditFieldLabel.HorizontalAlignment = 'right';
            app.DesiredDistancefromHouseEditFieldLabel.Position = [24 129 100 28];
            app.DesiredDistancefromHouseEditFieldLabel.Text = {'Desired Distance '; 'from House'};
            % Create DDFH
            app.DDFH = uieditfield(app.SetupTab, 'numeric');
            app.DDFH.Limits = [0 50];
            app.DDFH.ValueChangedFcn = createCallbackFcn(app, @DDFHValueChanged, true);
            app.DDFH.HorizontalAlignment = 'center';
            app.DDFH.Position = [139 135 100 22];
            % Create TemperatureDirectionSwitchLabel
            app.TemperatureDirectionSwitchLabel = uilabel(app.SetupTab);
            app.TemperatureDirectionSwitchLabel.HorizontalAlignment = 'center';
            app.TemperatureDirectionSwitchLabel.Position = [410 343 124 22];
            app.TemperatureDirectionSwitchLabel.Text = 'Temperature Direction';
            % Create TemperatureDirectionSwitch
            app.TemperatureDirectionSwitch = uiswitch(app.SetupTab, 'slider');
            app.TemperatureDirectionSwitch.Items = {'Up', 'Down'};
            app.TemperatureDirectionSwitch.ValueChangedFcn = createCallbackFcn(app, @TemperatureDirectionSwitchValueChanged, true);
            app.TemperatureDirectionSwitch.Position = [449 380 45 20];
            app.TemperatureDirectionSwitch.Value = 'Up';
            % Create TempSettingsTab
            app.TempSettingsTab = uitab(app.TabGroup);
            app.TempSettingsTab.Title = 'Temp. Settings';
            % Create Temperature1SpinnerLabel
            app.Temperature1SpinnerLabel = uilabel(app.TempSettingsTab);
            app.Temperature1SpinnerLabel.HorizontalAlignment = 'center';
            app.Temperature1SpinnerLabel.Position = [66 363 76 28];
            app.Temperature1SpinnerLabel.Text = {'Temperature '; '#1'};
            % Create Temperature1Spinner
            app.Temperature1Spinner = uispinner(app.TempSettingsTab);
            app.Temperature1Spinner.Limits = [60 90];
            app.Temperature1Spinner.ValueChangedFcn = createCallbackFcn(app, @Temperature1SpinnerValueChanged, true);
            app.Temperature1Spinner.Position = [157 346 100 68];
            app.Temperature1Spinner.Value = 60;
            % Create Temperature2SpinnerLabel
            app.Temperature2SpinnerLabel = uilabel(app.TempSettingsTab);
            app.Temperature2SpinnerLabel.HorizontalAlignment = 'center';
            app.Temperature2SpinnerLabel.Position = [66 248 76 28];
            app.Temperature2SpinnerLabel.Text = {'Temperature '; '#2'};
            % Create Temperature2Spinner
            app.Temperature2Spinner = uispinner(app.TempSettingsTab);
            app.Temperature2Spinner.Limits = [60 90];
            app.Temperature2Spinner.ValueChangedFcn = createCallbackFcn(app, @Temperature2SpinnerValueChanged, true);
            app.Temperature2Spinner.Position = [157 230 100 70];
            app.Temperature2Spinner.Value = 60;
            % Create Switch
            app.Switch = uiswitch(app.TempSettingsTab, 'slider');
            app.Switch.Items = {'1', '0'};
            app.Switch.ValueChangedFcn = createCallbackFcn(app, @SwitchValueChanged, true);
            app.Switch.FontName = 'Nyala';
            app.Switch.FontSize = 28;
            app.Switch.Position = [522 21 74 32];
            app.Switch.Value = '0';
            % Create EditFieldLabel
            app.EditFieldLabel = uilabel(app.TempSettingsTab);
            app.EditFieldLabel.HorizontalAlignment = 'right';
            app.EditFieldLabel.Position = [374 291 25 22];
            app.EditFieldLabel.Text = '';
            % Create tempnow
            app.tempnow = uieditfield(app.TempSettingsTab, 'numeric');
            app.tempnow.Limits = [60 89];
            app.tempnow.ValueChangedFcn = createCallbackFcn(app, @tempnowValueChanged, true);
            app.tempnow.HorizontalAlignment = 'center';
            app.tempnow.FontSize = 26;
            app.tempnow.Position = [409 230 133 117];
            app.tempnow.Value = 60;
            % Create GaugeLabel
            app.GaugeLabel = uilabel(app.TempSettingsTab);
            app.GaugeLabel.HorizontalAlignment = 'center';
            app.GaugeLabel.Position = [225 32 42 22];
            app.GaugeLabel.Text = 'Gauge';
            % Create Gauge
            app.Gauge = uigauge(app.TempSettingsTab, 'circular');
            app.Gauge.Limits = [60 90];
            app.Gauge.MajorTicks = [60 65 70 75 80 85 90];
            app.Gauge.Position = [185 69 120 120];
            app.Gauge.Value = 60;
            % Create SavingsTab
            app.SavingsTab = uitab(app.TabGroup);
            app.SavingsTab.Title = 'Savings';
            % Create UIAxes
            app.UIAxes = uiaxes(app.SavingsTab);
            title(app.UIAxes, 'Savings')
            xlabel(app.UIAxes, 'Month and Year')
            ylabel(app.UIAxes, 'Money')
            app.UIAxes.PlotBoxAspectRatio = [1 0.606666666666667 0.606666666666667];
            app.UIAxes.Color = [0.9412 0.9412 0.9412];
            app.UIAxes.Position = [146 219 348 237];
            % Create ThisMonthCostEditFieldLabel
            app.ThisMonthCostEditFieldLabel = uilabel(app.SavingsTab);
            app.ThisMonthCostEditFieldLabel.HorizontalAlignment = 'center';
            app.ThisMonthCostEditFieldLabel.Position = [439 96 94 22];
            app.ThisMonthCostEditFieldLabel.Text = 'This Month Cost';
            % Create ThisMonthCostEditField
            app.ThisMonthCostEditField = uieditfield(app.SavingsTab, 'numeric');
            app.ThisMonthCostEditField.Limits = [0 Inf];
            app.ThisMonthCostEditField.ValueDisplayFormat = '$%7.2f';
            app.ThisMonthCostEditField.HorizontalAlignment = 'center';
            app.ThisMonthCostEditField.Position = [417 39 137 58];
            % Create TotalSavingsEditFieldLabel
            app.TotalSavingsEditFieldLabel = uilabel(app.SavingsTab);
            app.TotalSavingsEditFieldLabel.HorizontalAlignment = 'right';
            app.TotalSavingsEditFieldLabel.Position = [111 96 77 22];
            app.TotalSavingsEditFieldLabel.Text = 'Total Savings';
            % Create TotalSavingsEditField
            app.TotalSavingsEditField = uieditfield(app.SavingsTab, 'numeric');
            app.TotalSavingsEditField.Limits = [0 Inf];
            app.TotalSavingsEditField.ValueDisplayFormat = '$%9.2f';
            app.TotalSavingsEditField.HorizontalAlignment = 'center';
            app.TotalSavingsEditField.Position = [88 39 137 58];
        end
    end
    methods (Access = public)
        % Construct app
        function app = Control_1
            % Create and configure components
            createComponents(app)
            % Register the app with App Designer
            registerApp(app, app.UIFigure)
            if nargout == 0
                clear app
            end
        end
        % Code that executes before app deletion
        function delete(app)
            % Delete UIFigure when app is deleted
            delete(app.UIFigure)
        end
    end
end

You'll probably get an error, which is no problem. Just close the GUI that was generated after you pressed run, we'll be gathering the rest of the necessary programs and data in a moment.

Since Matlab is set up we can move on to python. First, run the python program either from your command prompt (on windows) or by using the .exe file in your python folder. Make sure that all the appropriate libraries are installed by using the import command.

import serial

import time

import csv


These are the three libraries you'll need to start off, though we'll be making our own library soon. If there was some sort of error with these commands, go back and make sure the libraries are installed and are in the Lib folder in the python folder. Next we'll be generating what I have called pythonlogger library. This name is not necessary, you can call it whatever you want, its just the name of the python file (.py) that you create.

Open a text editor, I use Sublime3 but notepad works just fine, and enter this code.

 def pythonprint():

import pythonlogger

import serial

import time

import csv

ser = serial.Serial('COM8')  # COM8 is the arduino serial port, this will likely be different for each user, i.e. check your serial port in the arduino IDE

ser.flushInput()

while True:

	try:    ser_bytes = ser.readline()    print(ser_bytes)  

		with open("test_data.csv","a") as f:

			writer = csv.writer(f,delimiter=",")           # sets the data to be entered as comma-seperated   

			writer.writerow([time.time(),ser_bytes])   #writes data to test_data.csv

	except:

		print("Error Occured")

		break

Save the text as "insert the name of the library you want".py in the Lib folder. Also note that the def pythonprint() line defines the name of the function you are going to call, so you can change that to def "insert name you want for your function"(). When the library is saved we can move on to the arduino code.

Open up the arduino IDE and open two new sketch windows. Save those two sketch files somewhere convenient, the name of these files doesn't matter. Then delete all the default code and replace it with the following.

For the receiving arduino:

#include <RadioHead.h>
#include <RH_ASK.h> 
#include <RH_Serial.h>
#include <SPI.h> // this is not used but needed to compile

RH_ASK driver;
struct dataStruct{   float temp;
}myData;
void setup()
{
Serial.begin(9600); // Debugging only
	if (!driver.init())
		Serial.println("init failed"); }

void loop()
{
	uint8_t buf[RH_ASK_MAX_MESSAGE_LEN];
	uint8_t buflen = sizeof(buf);
	if (driver.recv(buf, &buflen)) // Non-blocking

{

	int i;
	// Message with a good checksum received, dump it.
	//driver.printBuffer("Got:", buf, buflen);
	memcpy(&myData, buf, sizeof(myData));
	Serial.println("");
	Serial.print(myData.temp);

}

}

P.S. the //driver.printBuffer.... etc line is test code. No need to worry about it unless your doing diagnositcs and want to figure out if you are actually receiving data.

For the transmitter arduino

#include <RadioHead.h>
#include <RH_Serial.h>
#include <RH_ASK.h>
#include <SPI.H>  // this is not used but needed to compile<br>#include 
#include <DHT11.h>


int pin=4;
DHT11 dht11(pin);
RH_ASK driver;

struct dataStruct{
 float temp;
}myData;

byte tx_buf[sizeof(myData)] = {0}; 

//So arguments are bitrate, transmit pin (tx),  

//receive pin (rx), ppt pin, isInverse. The last 2 are not used.void setup()

{     

	Serial.begin(9600);    // Debugging only
	if (!driver.init())
        	Serial.println("init failed");

}

void loop()
{     
	int err;
	float temp, humi;
	uint8_t msg;
	if((err=dht11.read(humi, temp))==0)
	myData.temp = temp;
	memcpy(tx_buf, &myData, sizeof(myData) );
	byte zize=sizeof(myData);

{
	Serial.println(myData.temp);
	driver.send((uint8_t *)tx_buf, zize);
	driver.waitPacketSent(); //halt execution until all data has been sent
	delay(2000); //wait 2 seconds

	} 

}

The include commands should be enough, but if you have any issues later with the data transfer you might want to look in the RadioHead library folder and include the remainder of the file names, in the same format.

Step 5: Making It Work

Now that we have all the code together and the arduino's assembled, we can hook up the arduino to your computer and load the code. Make sure you send the correct code to the receiving and transmitting microcontrollers. You can have both of the arduinos connected to your computer while this is running but you'll have to make sure you have the correct port selected moving forward, or you can disconnect the transmitting arduino and power it from some other source once the code is uploaded.

Speaking of which, you should select the port which is connected to your receiving arduino from the IDE tools menu now and run python.

Don't open the serial monitor while you're doing this, python can't read the serial while the monitor is open. Once python is open call the pythonprint function as follows.

pythonlogger.pythonprint()

This will start the data collection from the arduino serial port. If you open your python folder now, you'll see that a new .csv file has been created called "test_data.csv", that holds all of the time and temperature information. This will be the file that Matlab accesses to do all of its calculations and controls.

Another warning: don't open test_data.csv while the data is being accessed or written. If you do, the python and/or the Matlab code will crash and send back an error.

If you do decide to open the .csv later, you'll notice that the time column is just a very large string of numbers. That is because the time.time() command writes the number of seconds since January 1st, 1970.

At this point python should be printing the temperature data it is reading from the serial port. It should look something like:

b'25.03'/r/n

Don't worry about the extra characters, the Matlab code indexes for the middle five values in the second column of the .csv file.

Now that all of the supporting programs are working and data is being collected we can start collecting GPS data from the Matlab mobile program that was setup earlier and run the Matlab GUI code. Once you are in the sensor tab of Matlab mobile, select GPS and hit the start button.

If you are new to Matlab mobile refer back to step 4 and look at the screen shots above. If you are still having issues, make sure that you are connected to the computer you selected earlier (in the settings tab) and use the link from the "connector on" command to check that Matlab is online.

Step 6: Using the Program

There are multiple things going on in the background in this system. Temperature data is being collected and logged by arduino and pyton, Matlab is collecting GPS data from your phone and running calculations to see how far away you are from your house and setting your thermostat based off of all that information. Where you come in is providing your preferences.

Run the Matlab GUI code. Open the .mlapp file and look at the first tab. You'll need to gather the information for this yourself, the efficiency and power rating of your heating/cooling unit can usually be found on the unit itself, and your average speed is just a good estimate of how fast you drive. Once the values are inputted, hit the "Run Diagnostic" button and the program controls your thermostat to gather information about your house.

Move on to the next menu.

Step 7: Temperature Control

This menu allows you to select you preferred temperature while your at home and away. Set Temperature #1 to your comfortable temperature, and Temperature #2 to a high or low value that is safe for your home (make sure you don't set it to 100 degrees while you have dogs at home, etc.).

Step 8: Historical Data

Finally you can watch how much money your saving by using the automatic control. This essentially estimates how much energy would be used if your thermostat was set to your preferred temperature 24/7, then subtracts your actual energy used.

Good luck building.

Share

    Recommendations

    • Make it Glow Contest 2018

      Make it Glow Contest 2018
    • Toys Contest

      Toys Contest
    • PCB Contest

      PCB Contest

    Discussions

    0
    None
    seamster

    8 weeks ago

    Good write up, thanks for sharing your steps!