Gerrit Niezen

Building a wireless temperature sensor for a growhouse

I have a tiny growhouse standing outside that I've used for seedlings in the past, and potentially want to use for growing veggies hydroponically in the future. It occurred to me that I don't know how hot or cold it gets inside.

Given that it is standing against the side of the house, it gets a lot of sunlight at certain times of day and almost nothing at other times. When I know it's warm outside I open up the flap to make sure it doesn't get too hot, but I'd like to know exactly how hot it gets.

I've worked with DS18B20 temperature sensors in the past, so I knew that they are ubiquitous and pretty easy to work with. You can buy the bare chip, but I went with the waterproof version at the end of a 3 metre lead from Amazon for £3.99 including P&P. The reason for getting a temperature sensor on a lead is so that I could keep the prototype (with microcontroller on a breadboard) inside the house connected to power and just run the lead outside through the window, so that it's the only part that needs to be waterproof.

I then had to decide which microcontroller to use. Originally I wanted to use my C.H.I.P. from Next Thing Co. but it looks like they recently went bust, so I dediced to give the ESP8266 chip a try. There are a bunch of NodeMCUs at my local hackspace available for less than a fiver, and they seem like a pretty neat prototyping platform, as it's breadboard-compatible and then just plugs into USB. I've tried using the built-in Lua interpreter in the past, but I found it to be a bit flaky so decided to go down the Arduino Core route instead.

I took me forever to get the basic DS18B20 Arduino code example to work. It turns out that I had my wires swapped: There are two types of DS18B20 sensors with red, yellow and green wires and I had the less common type where the yellow wire instead of the green one is ground. One good thing came out of this: On that page describing the sensor types I discovered that there is an ESP8266 port of Espruino, which would allow me to write actual JavaScript code, not “NodeJS-like” code which is actually Lua[1].

Man, was this a game changer. Espruino has great example code, and a simple web-based editor which allows you to connect to the device over WiFi and update your code over the air (OTA) almost instantly. Compared to the Arduino Core where it can take quite long to update your code over USB, this felt magical. I know Arduino Core has OTA capability too, but I haven't tried it yet.

So, without further ado, here is the code I use to connect to the temperature sensor, cobbled together from various Espruino examples. It takes a sensor reading every minute (in Celsius) and runs a web server that displays a temperature graph. It also toggles the on-board LED when it takes a reading. I specifically did not want to use an IoT platform/service, as they don't tend to stay around for long and the ESP8266 is perfectly capable of running its own web server:

var wifi = require('Wifi');
var http = require('http');

var led = Pin(NodeMCU.D4); // on-board LED
var toggle = 1;
var ow = new OneWire(NodeMCU.D3); // data pin connected to D3
var sensor = require("DS18B20").connect(ow);
var history = new Float32Array(30); // store 30 readings

function updateLed(){
digitalWrite(led, toggle);
toggle=!toggle;
}

setInterval(function() {
updateLed();

var temp = sensor.getTemp();
console.log(temp);
// move history back
for (var i=1; i<history.length; i++)
history[i-1]=history[i];
// insert new history at end
history[history.length-1] = temp;
}, 60000);

function onPageRequest(req, res) {
'<body><canvas id="canvas" width="200" height="200" style="border:1px solid #888;"></canvas><script>');
res.write('var d='+JSON.stringify(history)+';'+
'var c=document.getElementById("canvas").getContext("2d");'+
'c.moveTo(0,100 - (d[0]-d[d.length-1])*10);'+
'for (i in d) {'+
'var x = i*200/(d.length-1); var y = 100 - (d[i]-d[d.length-1])*10;'+
'c.lineTo(x, y);'+
'if (i % 5 === 0) c.fillText(Number.parseFloat(d[i]).toFixed(1),x,y - 2);}'+
'c.stroke()'+
'</script>');
res.end('</body></html>');
}

function onInit() {
wifi.restore();
http.createServer(onPageRequest).listen(80);
console.log("Server created at " + wifi.getIP().ip);
}

onInit();


What's also great about Espruino is that it saves your WiFi credentials separately on the flash memory, which means you don't accidentally expose them in your example code. 😉

1. which is where NodeMCU gets its name from ↩︎