Controlling an IOT power relay and BME280 sensor with PowerShell on a Raspberry Pi

7 minute read

I have a problem, well probably lots of them, but today we are going to talk about one in particular: my AC unit does not have a thermostat. It is old enough that it just has a 1 to 11 dial for controlling the temperature, but if you leave it on, the fan stays engaged regardless of the AC actually running. It does feel cool to ‘crank it to eleven’ (har har), but it would feel cooler to not waste electricity. Plus I don’t want to sit around and figure out what temperature each number correlates too. I’m too lazy for that.

Background

Hello my tasty Raspberry Pi

So I had one of these useless little computers lying around that is supposed to be able to do just anything. I’ve got Pi-Hole running at home and love it, so I brought one to the office to set up and run Pi-Hole here as well. You might be thinking why can’t I just run Pi-Hole on a VM? Well, because it is not as cool to run Pi-Hole on a VM. That is dumb and unadventurous!

Then I remembered something, at the PowerShell summit the PowerShell team did a demo of the PowerShell-IOT module that was able to interface with a BME280 temperature sensor connected to a Raspberry Pi. Now if only I could control the power…

I’ve got the power! … Control

Now I’m not a hardware guy, I literally soldered for the first time in my life while doing this project, so I had to find something simple. Luckily for me, I was saved by the IOT Power Relay. It is a dead simple on/off power relay. Sure I didn’t know how to turn it on or off, but I know that the PowerShell-IOT module has GPIO pin control.

Prerequisites

I should also mention that I did order some male-female jumper wires as well, so when the BME280 and the power relay arrived, I was able to wire everything up.

Raspberry Pi setup

If you’ve never set up a Raspberry Pi before, use Raspbian, specifically the latest version, Raspbian stretch. Write the .img file to an SD card, I use Win32 Disk Imager to do so.

Enable SSH on first boot

If you are like me, you don’t have an extra monitor with HDMI lying around. So to enable SSH on the first boot of your Pi, add a file to the root of your SD card that is just called: ssh.

When your Pi boots up, find the IP address and SSH to it. The default credentials are:

Username: pi
Password: raspberry

Install PowerShell core

These lines are straight from the Microsoft Docs. Please check them to see if there have been any updates since this was written

# Install prerequisites
sudo apt-get install libunwind8

# Grab the latest tar.gz
wget https://github.com/PowerShell/PowerShell/releases/download/v6.0.2/powershell-6.0.2-linux-arm32.tar.gz

# Make folder to put powershell
mkdir ~/powershell

# Unpack the tar.gz file
tar -xvf ./powershell-6.0.2-linux-arm32.tar.gz -C ~/powershell

# Run following to create a symbolic link
sudo ln -s ~/powershell/pwsh /usr/bin/pwsh

Now to start PowerShell core, just issue the following command:

sudo pwsh

Install the PowerShell IOT library

This step is quite simple, once you have PowerShell core running, run the following command:

Install-Module Microsoft.PowerShell.IOT

Now you can access GPIO pins using Set-GPIOPin and Get-GPIOPin, amoung other things.

Install the BME280 module

Before we install the BME280 module, we need to enable the I2C interface on the Raspberry Pi:

sudo raspi-config # this will open the config tool
5 - Interfacing options
P5 - I2C
Would you like ARM I2C interface to be enabled -> Yes

To interact with the BME280, we just need to install Microsoft’s example BME280 module for it. Using the instructions straight from their README:

git clone https://github.com/PowerShell/PowerShell-IoT.git
Import-Module ./PowerShell-IoT/Examples/Microsoft.PowerShell.IoT.BME280

Wiring everything up

BME280

Follow the wiring guide in the example BME280 module’s README to connect your BME280. I also recommend soldering it for a reliable connection.

IOT Power Relay

For wiring the IOT Power Relay, I had to make an educated guess (remember, my first time using the GPIO pins!). I found a really cool Pinout site and also used Microsoft’s example LED module for reference. I ended up connecting the positive to physical pin 11 (GPIO Pin 0) and the negative to physical pin 14, a ground.

To interact with the IOT Power Relay using PowerShell, we just need to set the GPIO pin 0:

Set-GPIOPin 0 high # turns the 'normally off' ports, on. Does the opposite for the 'normally on' ports.
Set-GPIOPin 0 low # turns the 'normally off' ports off. Does the opposite for the 'normally on' ports.

I’m using the ‘normally off’ ports on my IOT Power Relay because if the Pi fails for some reason, my AC will turn off instead of staying powered on.

Party time

Now we should be able to get data from the BME280 using Get-BME280Data:

Import-Module ./PowerShell-IoT/Examples/Microsoft.PowerShell.IoT.BME280 #in case you forgot
Get-BME280Data

Temperature Pressure Humidity
----------- -------- --------
      22.98    667.9    72.84

Manage the AC

So the last thing we need to do is to write a script to enable and disable the AC based on temperature. Here’s what I came up with for my situation:

#requires -modules IOTRelay
Import-Module ./PowerShell-IoT/Examples/Microsoft.PowerShell.IoT.BME280
$highTemp = 24
$lowTemp = 20
$pin = 0
Set-GPIOPin -Id $pin -Value low #starting with AC off
$ACon = $false
While($true){
    $tempData = Get-BME280Data
    Write-Output "$((get-date).tostring()): Temperature at $($tempData.Temperature)"
    If($ACon){
        If($tempData.Temperature -le $lowTemp){ #if temp is at or below $lowtemp
            Write-Output 'Turning AC off'
            Set-GPIOPin -Id $pin -Value low #turn AC off
            $ACon = $false
        }
    }Else{ #AC is off
        If($tempData.Temperature -ge $highTemp){ #if temp is at or above $hightemp
            Write-Output 'Turning AC on'
            Set-GPIOPin -Id $pin -Value high #turn AC on
            $ACon = $true
        }
    }
    Start-Sleep -Seconds 60
}

This turns my AC on when the temp hits 24 celsius and then off when it hits 20 celsius.

You’ll notice that I never use Get-GPIOPin to retrieve the current state of the pin, that is because doing so will cause the pin to revert to low. So instead I store the state of the AC in the $ACon variable.

Final steps

A few things would make this amazingly better:

  • Setting this to run as a cron job and of course on boot
  • Graphing the data in an RRD (think Cacti)
  • Remote control. Though this is not a priority for me since it is designed to just run itself.
  • Putting the code in Github. Duh! I’ll update this when it is. Give me a day or two.

Leave a Comment