IoT: Make a Humidity Sensor

For absolute beginners or anyone interested in implementing IoT with sensors.

Laibah Ahmed
students x students

--

This project tutorial goes step by step into building a humidity sensor that collects data through a DHT11 sensor and then relays the information into a formatted google sheet. This project can easily be tweaked to work even without your Arduino plugged into a computer, and by sending information through wifi. No prior knowledge of how to code, use Arduinos, implement IoT, or anything in this field is necessary. To know more about what IoT is I suggest reading this article first.

What you’re going to need to buy or supply:

1x Arduino MKR1000 Wifi with Headers

1x DHT11 Humidity Sensor

2x Breadboards

Jumper Wires

A resistor (usually comes with the sensor)

USB connector wire (Any micro USB cable works too, I just used a Kindle charger.)

Before we dive into it, I highly recommend keeping a doc or somewhere you are able to take digital notes open on another tab open to write down long strings of information and other data/code we need to move from place to place.

I’m going to be splitting this tutorial into two parts just so that we can test the first part of our work before we get into the harder stuff. That way, if an issue arises we can catch it before everything’s set up and it gets harder to figure out.

Part 1: The Easier Stuff

Our information is going to be sent and recorded on google sheets.

  1. Open a new Google Sheet using your Gmail. Name the Google Sheet whatever you want and then get ready to save a long string of characters. So where the URL of the Google Sheet is you’re going to see a /d/ followed by a bunch of random letters and numbers, and then /edit. This is called the URL Key to your spreadsheet. Copy and paste that somewhere for use later.

2. Now we’re going to add some code to this sheet. To do so we need to open Google Script, also known as Gscript. Extensions > Apps Script.

Once there, name the Gscript and delete the starter code on there. I’m going to attach the code under this tutorial to keep things easy to see. Copy and paste this code into the Gscript editor. Now we only have to add in the URL Key we saved before. Copy and paste that between the single apostrophes where it says:

var id = '   '; // Spreadsheet ID

It should look like this but with your own URL Key.

3. Now that we have the code in place, we have to deploy this. To do so, click deploy on the top right corner. Deploy > New Deployment, from the pop-up tab select the gear icon in the top left corner next to where it says “Select Type”. Gear > Web App. Put any sort of description, for the second box where it says “execute as”, make sure it’s set to you with your email. For the third box where it says “who has access”, set it to anyone even anonymous. From here, click deploy on the bottom right corner.

Make sure to save the Web App URL that just popped up. Copy and paste it somewhere for use later.

4. We need something to send the information from the sensor to the google sheet, this would be called an API middleman. We’re going to use PushingBox. First, create a free account with your Gmail.

a) Click “My Services” > “Add a Service” > “CustomURl” , “Select This Service”

b) Fill in the name of the configuration with anything you want. In the second box, paste the Web App URL we saved from the Gscript. In the third box, choose the GET option.

c) Now we have to program this service. To do so, click on “My Scenarios” from the bar on the top. Name it anything you want then click the add button. Click the “Add an Action” button at the bottom > click the “Add an Action with this Service” for the service we just set. > copy and paste the code below into the box that just popped up. We are using the GET method for this data.

?humidityData=$humidityData$&celData=$celData$&fehrData=$fehrData$
&hicData=$hicData$&hifData=$hifData$

d) Copy and paste the DeviceID somewhere for later use.

5. Almost done with Part 1! We’re going to test what we’ve done so far so that we can make sure we haven’t missed anything before we move on. To do so we are going to manually input data into the sheet. Copy and paste this into your browser, but with your DeviceID that we just saved from PushingBox.

http://api.pushingbox.com/pushingbox?devid=(YOUR-DEVID-HERE)&humidityData=33&celData=44&fehrData=111&hicData=22&hifData=77

The link should look like this in your browser, except with your own DevID.

http://api.pushingbox.com/pushingbox?devid=v2F68CCD45B3890D&humidityData=33&celData=44&fehrData=111&hicData=22&hifData=77

Check your google sheet to make sure everything is working. If not, double-check everything else from Part 1 for errors.

Part 2: The Harder Stuff

  1. Engineering the hardware. First link your two breadboards together. Put the Arduino anywhere on one side of the bottom of the breadboard, specifics don’t matter as long as you are able to work without it moving too much.

On a breadboard, the rows are all connected so electricity will pass through them. The columns are not connected. So when plugging things in, it is important to make sure they are on the right row, but the column is not of too much concern as long as it still flows the electricity as intended.

Don’t worry about pushing the pins in all the way, as long as they’re in place it should be fine.

2. Now we need 3 wires, a resistor, and a sensor.

  • Arrange the wires starting from the 45 on the breadboard going down so 45 and 46 are filled, skip 47, and put one on 48. These are going to be side by side to the sensors VCC, Data, and GND pins.
  • Bend the resistor for your ease and push in next to the wires at 45 and 46.
  • Push in the sensor next to the resistor so that the pins align with the wires we put in. Make sure that the front of the sensor, the side with the holes, is facing the wires.

3. Now we’re going to connect the wires.

The topmost wire next to the 45 should be plugged into where it says “VCC” on the Arduino. VCC is another term for 3.3v, the voltage that we are working with. It is how much power the sensor and Arduino would be using. The MKR1000 can work with both 3.3v and 5v.

The middle wire should be plugged into “11”. This is the data pin, it’s where the data would be transferred and logged from the sensor to the Arduino from the code to the sheet. You should also notice how in the code we choose DHT Pin as 11.

The last wire should be on the right side where it says “GND”. This means ground, it’s where the electricity goes away safely. I learned to make sure to use this by mistake because I didn’t use GND and the electricity just wound up going only to the sensor and overheating it. Yikes.

We’re going to set this aside for now and first get the code ready for the Arduino.

4. If you haven’t already, download the Arduino. We also need to download two libraries, these are packages that contain information on how to use different premade codes, for example, for our humidity sensor.

5. Open Arduino, it should open a blue-rimmed tab with some basic code. We need to first choose the board and port that we are going to work with. To choose the board, plug your Arduino into your device with the micro USB wire, any port works but I used the left USB one on my mac. Then, click over tools on the top left corner > board > boards manager > Arduino SAMD Boards > install. This downloads information for a bunch of boards, including the one we need to use. After you download it just close the manager and backtrack, so instead of clicking boards manager again, you hover over the Arduino SAMD Boards > Arduino MKR 1000. I’ve attached pictures to help.

6. Then we have to install the libraries that we downloaded. Tools > Manage Libraries. If they’re not already there or downloaded, download the WiFi101 and DHS Sensor Library.

Note: On the bottom right corner of the tab it should say “Arduino MKR1000 on” and then the name of your port. For me, it automatically went to the port that my Arduino was plugged into, so it says “/dev/cu.usbmodem14201”, but for if some reason it isn’t selecting you can manually choose the port from tools > port > whichever port is showing other than the Bluetooth basic option. If it still isn’t working switch ports and try the port process again.

7. Now we are going to actually code the Arduino. I will attach the code under the code for the Gscript down below. We have to customize some parts of the code.

  • Your SSID (your WiFi name)
  • Your WiFi password
  • Your DeviceID from Pushingbox

To make the code run first click the checkmark button on the top left to verify that it works, then while the Arduino is still plugged in click the Upload button. It would ask you to save the file so just save it in any name and anywhere you want.

Now to make everything come together go-to tools > serial monitor. Keep this tab open and running and you should see it updating within here, as long as it updates on the monitor it should also be updating to the google sheet!

This is the code for the GScript:

//-----------------------------------------------
//Originally published by Mogsdad@Stackoverflow
//Modified for jarkomdityaz.appspot.com
//Modified for Hackster.io by Stephen Borsay
//-----------------------------------------------
/*

GET request query:

https://script.google.com/macros/s/<gscript id>/exec?celData=data_here
----------------------------------------------------------------------

GScript, PushingBox and Arduino/ESP8266 Variables in order:

humidityDat
celData
fehrData
hicData
hifData
----------------------------------------------------
*/


/* Using spreadsheet API */

function doGet(e) {
Logger.log( JSON.stringify(e) ); // view parameters

var result = 'Ok'; // assume success

if (e.parameter == undefined) {
result = 'No Parameters';
}
else {
var id = '<YOUR_SPREADSHEET_URL_HERE';//docs.google.com/spreadsheetURL/d
var sheet = SpreadsheetApp.openById(id).getActiveSheet();
var newRow = sheet.getLastRow() + 1;
var rowData = [];
//var waktu = new Date();
rowData[0] = new Date(); // Timestamp in column A

for (var param in e.parameter) {
Logger.log('In for loop, param='+param);
var value = stripQuotes(e.parameter[param]);
//Logger.log(param + ':' + e.parameter[param]);
switch (param) {
case 'humidityData': //Parameter
rowData[1] = value; //Value in column B
break;
case 'celData':
rowData[2] = value;
break;
case 'fehrData':
rowData[3] = value;
break;
case 'hicData':
rowData[4] = value;
break;
case 'hifData':
rowData[5] = value;
break;
default:
result = "unsupported parameter";
}
}
Logger.log(JSON.stringify(rowData));

// Write new row below
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
}

// Return result of operation
return ContentService.createTextOutput(result);
}

/**
* Remove leading and trailing single or double quotes
*/
function stripQuotes( value ) {
return value.replace(/^["']|['"]$/g, "");
}

This is the code for the Arduino:

//-----------------------------------------------
//This sketch is combined from Adafruit DHT sensor and tdicola for dht.h library
// https://learn.adafruit.com/dht/overview
// https://gist.github.com/teos0009/acad7d1e54b97f4b2a88
//other Authors Arduino and associated Google Script:
//Aditya Riska Putra
//Ahmed Reza Rafsanzani
//Ryan Eko Saputro
//See Also:
//http://jarkomdityaz.appspot.com/
//
//ELINS UGM
//
//Modified for Hackster.io project for the MKR1000
//by Stephen Borsay(Portland, OR, USA)
//Since Arduino can't https, we need to use Pushingbox API (uses http)to run
//the Google Script (uses https). Alternatly use Ivan's SecureWifi encryption


#include <WiFi101.h>
#include "DHT.h"

#define DHTPIN 11 // what pin we're connected to, pin1 is 5th pin from end

// Uncomment whatever DHT sensor type you're using!
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT21 // DHT 21
//#define DHTTYPE DHT22 // DHT 22

DHT dht(DHTPIN,DHTTYPE);

const char WEBSITE[] = "api.pushingbox.com"; //pushingbox API server
const String devid = "YOUR_DEVICEID"; //device ID on Pushingbox for our Scenario

const char* MY_SSID = "YOUR SSID";
const char* MY_PWD = "YOUR WiFi PASSWORD";


int status = WL_IDLE_STATUS;
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS)


void setup() {
//Initialize serial and wait for port to open:
Serial.begin(9600);
while (!Serial)
{
; // wait for serial port to connect. Needed for native USB port only
}

// check for the presence of the shield:
if (WiFi.status() == WL_NO_SHIELD) {
Serial.println("WiFi shield not present");
// don't continue:
while (true);
}

// attempt to connect to Wifi network:
while (status != WL_CONNECTED)
{
Serial.print("Attempting to connect to SSID: ");
Serial.println(MY_SSID);
//Connect to WPA/WPA2 network.Change this line if using open/WEP network
status = WiFi.begin(MY_SSID, MY_PWD);

// wait 10 seconds for connection:
delay(10000);
}

Serial.println("Connected to wifi");
printWifiStatus();

}

void loop() {

// Wait between measurements.
delay(10000);

//prefer to use float, but package size or float conversion isnt working
//will revise in future with a string fuction or float conversion function

int humidityData = dht.readHumidity();
// Read temperature as Celsius (the default)
int celData = dht.readTemperature();
// Read temperature as Fahrenheit (isFahrenheit = true)
int fehrData = dht.readTemperature(true);

// Check if any reads failed and exit early (to try again).
if (isnan(humidityData) || isnan(celData) || isnan(fehrData))
{
Serial.println("Failed to read from DHT sensor!");
return;
}

// Compute heat index in Fahrenheit (the default)
int hifData = dht.computeHeatIndex(fehrData, humidityData);
// Compute heat index in Celsius (isFahreheit = false)
int hicData = dht.computeHeatIndex(celData, humidityData, false);

Serial.print("Humidity: ");
Serial.print(humidityData);
Serial.print(" %\t");
Serial.print("Temperature: ");
Serial.print(celData);
Serial.print(" *C ");
Serial.print(fehrData);
Serial.print(" *F\t");
Serial.print("Heat index: ");
Serial.print(hicData);
Serial.print(" *C ");
Serial.print(hifData);
Serial.println(" *F\n");

Serial.println("\nSending Data to Server...");
// if you get a connection, report back via serial:
WiFiClient client; //Instantiate WiFi object, can scope from here or Globally

//API service using WiFi Client through PushingBox then relayed to Google
if (client.connect(WEBSITE, 80))
{
client.print("GET /pushingbox?devid=" + devid
+ "&humidityData=" + (String) humidityData
+ "&celData=" + (String) celData
+ "&fehrData=" + (String) fehrData
+ "&hicData=" + (String) hicData
+ "&hifData=" + (String) hifData
);

// HTTP 1.1 provides a persistent connection, allowing batched requests
// or pipelined to an output buffer
client.println(" HTTP/1.1");
client.print("Host: ");
client.println(WEBSITE);
client.println("User-Agent: MKR1000/1.0");
//for MKR1000, unlike esp8266, do not close connection
client.println();
Serial.println("\nData Sent");
client.stop();
}
}


void printWifiStatus() {
// print the SSID of the network you're attached to:
Serial.print("SSID: ");
Serial.println(WiFi.SSID());

// print your WiFi shield's IP address:
IPAddress ip = WiFi.localIP();
Serial.print("IP Address: ");
Serial.println(ip);

// print the received signal strength:
long rssi = WiFi.RSSI();
Serial.print("signal strength (RSSI):");
Serial.print(rssi);
Serial.println(" dBm");
}

End Results!

Once the code is running and sending data to the google sheets it should look something like this:

  • Column A: The date the data was retrieved.
  • Column B: Humidity Data
  • Column C: Temperature in Celsius
  • Column D: Temperature in Farenheit
  • Column E: Heat Index in Celsius
  • Column F: Heat Index in Farenheit

The sensor and the code for the sensor grab the extra data as well, but to be specific, we are mainly looking at the humidity data from column B.

  • Some data retrieved might show random big numbers or incorrect data, if it switches between the incorrect and correct data it is just an error occurring from the sensor being slow. I am working on finding a solution to make sure the irregular data does not show next time though. Regardless, the real info should be accurate and constant if all the instructions were followed correctly.

We’re providing opportunities for the next generation of student thinkers, inventors, and learners, to publish their thoughts, ideas, and innovation through writing.
Our writers span from all areas of topics — from Growth to Tech, all the way to Future and World.
So if you feel like you’re about to jump into a rabbit hole of reading these incredible articles, don’t worry, we feel the same way. ;)
That’s why studentsxstudents is the place for getting your voice heard!
Sounds interesting? Why not join us on this epic journey?

--

--

Interested in the causes & effects of ocean acidification. Currently researching the impact of sulfate sludge discharge from the maritime industry.