In a previous project, I created a system that would control my air conditioner and keep it below a certain temperature by turning on and off a relay. You can see that here: https://www.hackster.io/amerch92/air-conditioner-controller-1426fa. One of the final things I had in that project was to log data to Google Sheets to see how well my air conditioner kept the temperature cool. I used IFTTT to do that logging. IFTTT works pretty well when it's logging one row every couple of hours or even when it's logging once every couple minutes but IFTTT starts to break down when it's logging once every couple of seconds. I wanted to create a system that could log directly to a Google Sheet in as direct a way as possible. I wanted to be able to monitor how my air conditioner is working across the room and I wanted to use the Grid-EYE to do it. I wanted to log directly into a Google Spreadsheet and use the Helium platform so that I could eventually expand this to control the temperature in each room relative to the air conditioner.
Getting StartedThe first thing to do is go through the Helium dashboard guide: https://www.helium.com/dev/dashboard
After that, go through the Raspberry Pi guide: https://www.helium.com/dev/hardware_libraries/raspberry_pi
I used a Raspberry Pi 2 B+ for this project and it worked perfectly. I didn't have to do any modifications in order for the Helium atom to work correctly. I knew I wouldn't need WiFi after the project was configured correctly (thanks to Helium) so I figured I wouldn't use a Raspberry Pi that had WiFi built in.
1.0. Setting up Google Cloud PlatformIf you don't have one already, create a Google Cloud platform account at cloud.google.com.
Create a new project.
Click on the three bar icon on the top left and go to APIs & Services and then select Dashboard.
Select ENABLE APIS AND SERVICES
Search for Google Sheets API
Enable Google Sheets API
Select Credentials on the left-hand side.
Click Create credentials and then select API key. The API key will be useful for communicating between GCP and the sheet that you are trying to log to.
Save this API key into a file named api_key.json with the structure:
{
"key": "adsfsflkjfoiwjlkfio156dasf31"
}
Click Create credentials and then Service account key.
In the pop up select New service account.
Name your service account whatever you'd like and once done, select Create.
A file will be saved to your desktop. Rename this file credentials.json.
Select the three bar in the top left corner and select IoT Core.
Create a device registry.
Name your Registry ID whatever you would like. Select us-central1 as the region. Create a topic under Select a Cloud Pub/Sub topic.
Name that topic whatever you would like and click CREATE.
Select CREATE.
You should see your registry has been created.
If asked, enable the API.
Select Google Cloud IoT Core.
Enter a relatively short Registry ID and us-central1 as the Region. us-central1 may look to be already filled in but you have to make sure that you type it in. Enter in the private key inside the credentials.json file that was created in 1.2 that starts with "-----BEGIN PRIVATE KEY. Select create.
Name your channel name and then select create.
Create a new Google Sheet. In the URL of that sheet, note the extension after /d/ : https://docs.google.com/spreadsheets/d/
14XN6XuXXXXjJN4OS_Kl31551MA-BAVzmqVI
/
Select Share in the top right corner.
Inside the credentials.json file, select the client-email address and enter it in the People section. Make sure they have editing privileges. Select Done.
Create a folder and place the credentials.json as well as api-key.json in that folder. Create a file called Index.js.
Inside Index.js put the following code (also found in the attachments):
const {google} = require('googleapis');
exports.subscribe = (event, callback) => {
// The Cloud Pub/Sub Message object.
const pubsubMessage = event.data;
// We're just going to log the message to prove that
// it worked.
console.log(Buffer.from(pubsubMessage.data, 'base64').toString());
var jwt = getJwt();
var apiKey = getApiKey();
var spreadsheetId = 'Your Spreadsheet ID';
var range = 'A1';
if (Buffer.from(pubsubMessage.data, 'base64').toString().includes(",")){
dataArray = Buffer.from(pubsubMessage.data, 'base64').toString().split(",");
var row = dataArray
} else {
var row = [Buffer.from(pubsubMessage.data, 'base64').toString()];
}
appendSheetRow(jwt, apiKey, spreadsheetId, range, row);
// Don't forget to call the callback.
callback();
};
function getJwt() {
var credentials = require("./credentials.json");
return new google.auth.JWT(
credentials.client_email, null, credentials.private_key,
['https://www.googleapis.com/auth/spreadsheets']
);
}
function getApiKey() {
var apiKeyFile = require("./api_key.json");
return apiKeyFile.key;
}
function appendSheetRow(jwt, apiKey, spreadsheetId, range, row) {
const sheets = google.sheets({version: 'v4'});
sheets.spreadsheets.values.append({
spreadsheetId: spreadsheetId,
range: range,
auth: jwt,
key: apiKey,
valueInputOption: 'RAW',
resource: {values: [row]}
}, function(err, result) {
if (err) {
throw err;
}
else {
console.log('Updated sheet: ' + result.data.updates.updatedRange);
}
});
}
Install npm onto your computer, navigate to the folder with the files you just saved and then enter the following command:
npm install googleapis@27 --save
Zip all of those files together and then go back to your Google Cloud Platform main page and navigate to Cloud Functions:
Create a new function.
Select Zip from Cloud Storage and upload the zip file you just created. Browse for Cloud Storage location and create a new Bucket. Name it whatever you would like. Once you are done, select Save.
If you followed the tutorial on Helium correctly, you should have a a script that looks like:
from helium_client import Helium
helium = Helium("/dev/serial0")
helium.connect()
channel = helium.create_channel("test")
channel.send("hello from Python")
Run this script with
sudo python testHelium.py
If this works correctly you should see something like this on the Helium channel (the size of the packed may be a different size):
Go to your project's Google Cloud Platform and navigate to the Logs Viewer. You should see something like this:
You should also see hello from Python on your Google Sheet:
The Grid-EYE sensor has an 8x8 array that will record 64 individual infrared temperatures. We are going to use this to compare the outside temperature and the indoor temperature. To use the Grid-EYE sensor, turn off the Raspberry Pi and connect the sensor:
This is what my setup looked like - not pretty but it does work.
Once connected. Install the sensor by following this tutorial from Adafruit: https://learn.adafruit.com/adafruit-amg8833-8x8-thermal-camera-sensor/raspberry-pi-thermal-camera
5.1 Sending current tempsTake the original code that was written and run it. Over time, this is what the system will record:
The first image is me putting my hand over the sensor (hotter than normal temperature). The second is me doing a peace sign over the sensor. The third is me removing my hand completely from the sensor. The Error Checks is just an internal verification that the system worked correctly. If I sum the column, the sum should match the error check. The order of transmission is:
- Start Transmission
- The first column tells you how many parts there are and then the rest of the columns are the data
- The sum is sent as an error check
- End Transmission
This will continue on as long as the script is running.
5.2. Getting temperature dataI didn't need to get the entire range in order to do some analysis so I settled for just the minimum value of each column of the Grid-EYE. I also wanted to record the time. I accomplished both of these with this code:
from helium_client import Helium
# Grid-EYE library is Adafruit_AMG88xx
from Adafruit_AMG88xx import Adafruit_AMG88xx
# This is used so that the device doesn't just constantly send
from time import sleep
# numpy is used to do math
import numpy as np
# configure sensor to be the Grid-EYE
sensor = Adafruit_AMG88xx()
# datetime is for logging
from datetime import datetime
# this is in the tutorial
helium = Helium("/dev/serial0")
helium.connect()
# the channel that I used was named test
channel = helium.create_channel("test")
# infinite loop
while(1):
# tempList reads in the Pixels in a length 64 list
tempList = sensor.readPixels()
# convert from C to F
tempList = np.multiply(tempList,1.8)+32
# create a resultArray which is an 8x8 array
resultArray = np.reshape(np.asarray([tempList]),(8,8))
# create a minArray that takes the minimum value of each column
minArray = np.amin(resultArray, axis=0)
# send the current time along with the minArray spaced with commas
channel.send(datetime.now().strftime('%Y-%m-%d %H:%M:%S') + ',' + ','.join(str(x) for x in minArray))
# sleep for 20 seconds
sleep(20)
Here's a demo of the system working and logging correctly
6.0. Future DevelopmentFrom here, I want to create some housing to encase the Raspberry Pi and sensors. I'm going to vary the position of the system until the temperature readings are the most different.
Overall, I'm very satisfied with the capabilities of the Helium platform and I look forward to continuing development with this system.
Comments