Arduino Indoor Outdoor Temperatures

There has been many times that I’ve left the house and noticed the difference in temperature between inside and outside my home. I thought a fun project would be to combine an Arduino reading the inside temperature and the outside temperature.

I had a couple ideas on how to do this. The first involved two Arduinos, one inside and one outside, both using TMP36 sensors to monitor the temperatures. The second was a single Arduino inside that recorded the temperature using the sensor and then using the Open Weather Map API{.aioseop-link} to gain the outside temperature.

Both ideas had some pros and cons but I went for option two. It may not be as accurate as having an outside sensor but I think the data reported by the API is good enough that I could see the difference between inside and outside.

The code for this is available in a GitHub repo{.aioseop-link}.

Parts used #

Arduino Uno WiFi

TMP36 Sensor

Jumper wires

You’ll also need #

A web and database server running PHP and MySQL. In the code used this is an internal server that does not accept requests from outside of the network. If you are going to use a server open to traffic outside of your network you will need to add extra security measures to ensure that unauthorised requests cannot add data.

Setup #

Database #

Create a database and then run the SQL that is in the data.sql file. This will create a table that stores the indoor and outdoor temperatures as well as a unique id and a created at date and time.

Data receive page #

The first part of the script includes the Composer autoload file, the settings file and then uses Guzzle’s HTTP client that will be used to send a get request to Open Weather Map API.

There is then the basic security check for the key parameter in the query string.

We create a connection to the database or output the error message and exit if it was not successful.

The next section of code creates a new Guzzle HTTP client with the base uri set to the Open Weather Map API.

We then set the query string parameters to send and perform a GET request.

The response body is first converted to a string and then JSON decoded for easier use with PHP. This decoded response is a PHP object.

We now access the temperature returned by the API call and use this as our outdoor temperature reading.

The last part of the logic inserts a row into the database. To ensure that the temperature recordings are in the correct format we cast them as floats and user the number_format function to round to two decimal places.

After inserting the row into the database we return a 201 success response code to show that the row has been created.

The last part in the else statement returns a not authorised response header if the query string does not contain the key parameter or if the key parameter is incorrect.

Arduino sketch #

The first portion of code includes the library for the Arduino Uno WiFi, this allows us to use the Ciao library for sending HTTP requests. We then declare some constants that will be used when sending the request. You will need to replace the SERVER_ADDRESS and KEY to match those used on your web server for receiving the data. Finally we declare our TMP36 sensor input pin to zero.

Inside the setup function we initialise the Ciao library ready for use.

Inside our loop function we first calculate a five minute interval as this is how often we want to be taking a recording. We then set the last sampled time to zero so we get a recording on the first time in the loop.

Next we get the number of milliseconds that have passed and check if five minutes has passed since the last recording. If it has then we add five minutes to our last sampled time ready for the next recording.

Our next few lines of code take the recording from the sensor and convert it to degrees celsius.

The last part of code builds up a URI that we send to the server using the Ciao library.

Index page and chart #

The last piece of code to look at is the index.php file for the web server. This draws a line chart using the indoor and outdoor temperatures.

We first include the settings file and then make a database connection.

The SQL query gets all of the recordings in the past 24 hours and orders them oldest to newest. We then add all of these results to an array that we will use later to output as JSON.

In the head section we set some basic styling for the chart.

The body has no content, just two script tags. The first tag includes the D3 library.

The second script tag has the logic for creating the chart.

We first create a variable to hold the JSON data that we created earlier.

Then we set some variables for margins, width and height and append an SVG element to the body that will contain the chart.

The next section does some setup of a time parse in the format returned from our database and then an array of all of the temperatures so we can get the min and max values.

We then create scales for our X and Y axes using time for the X axis and a linear scale for the temperatures on the Y axis.

For the yScale domain I’ve subtracted 4 from the minimum and added 4 to the maximum so the chart had a bit of breathing room above and below the lines. We then append the axis to the chart.

The last part of the code adds the two lines to the chart and gives them slightly different classes so we can colour the lines differently.

Improving #

There are a couple of things I’d like to do to improve this.

  1. Security. To allow the data to be sent to a public facing server some more security steps than a basic key should be used.
  2. Allow different timeframes on the chart, e.g. past X hours, days or weeks. For this I’d need to group the data as showing data for every 5 minutes of an hour over 7 days would clutter a chart.