Så – som nevt i et tidligere innlegg har jeg bygget en provisorisk temperaturkontroll for gjæringsskapet mitt.
Den gjør vel omtrent havlparten av jobben som en STC-1000 gjør, og koster mer å bygge pluss at man må ha en apache/mysql-server stående, men det har vi vel alle?
Riggen betår av
1 stk NodeMCU fra Kjell & Co
1 stk ds18b20 1-wire temperatursensor
1 stk relekort 10A250V, for eksempel dette – selv gikk jeg for 2 releer, da det sørget for to-fase brudd i varmekildens strømtilførstel.
NodeMCU må settes opp mot nettverk, dette kan gjøres på flere måter, men jeg valgte å sette den opp som en klient med statisk ip, uten DNS.
Filnavn: networking.lua
--connect network wifi.setmode(wifi.STATION) wifi.sta.config("din ssid","ditt wpa2 passord") wifi.sta.setip({ip="ip-adresse",netmask="subnet-maske",gateway="gateway-adresse"})
I tillegg fant jeg et bibliotekskrevet av Peter Scargill som håndterte ett stk ds18b20-sensor uten noe hassle
Filnavn: ds18b20.lua
-------------------------------------------------------------------------------- -- DS18B20 one wire module for NODEMCU -- LICENCE: http://opensource.org/licenses/MIT -- Vowstar <vowstar@nodemcu.com> -- Dramatic simplification: Peter Scargill -------------------------------------------------------------------------------- -- Set module name as parameter of require local modname = ... local M = {} _G[modname] = M -------------------------------------------------------------------------------- -- Local used modules -------------------------------------------------------------------------------- -- Table module local table = table -- String module local string = string -- One wire module local ow = ow -- Timer module local tmr = tmr -- Limited to local environment setfenv(1,M) -------------------------------------------------------------------------------- -- Implementation – you don’t get any shorter than this -------------------------------------------------------------------------------- function readNumber(pin) ow.setup(pin) ow.reset(pin) ow.write(pin, 0xCC, 1) ow.write(pin, 0xBE, 1) data = nil data = "" for i = 1, 2 do data = data .. string.char(ow.read(pin)) end t = (data:byte(1) + data:byte(2) * 256) / 16 if (t>100) then t=t-4096 end ow.reset(pin) ow.write(pin,0xcc,1) ow.write(pin, 0x44,1) return t end -- Return module table return M
Serverside laget jeg en php som returnerte <maxtemp> og <mintemp> i en særs forenklet xml – jeg kalte den for reg.php
reg.php har også fuksjonaliteten som poster currentTemp til mySQL-basen beer og tabellen dataLogger
filnavn reg.php
<?php $scurrTemp = $_GET['currTemp']; $srelayState = $_GET['relayState']; $sqlServer = "localhost"; $sqlUser = "username"; //byttes ut med din mysql bruker $sqlDB = "beer"; //koble til databaseserver $dbhandle = mysql_connect($sqlServer, $sqlUser,"mypassword") or die("Klarte ikke koble til $sqlServer"); // Koble til riktig database $selected = mysql_select_db($sqlDB, $dbhandle) or die("Klarte ikke åpne $sqlDB"); $sql = "INSERT INTO datalogger (currTemp, relayState) VALUES(".$scurrTemp.",".$srelayState.")"; mysql_query($sql); echo "<maxtemp>28</maxtemp>"; echo "<mintemp>26</mintemp>" ?>
datalogger-tabellen ser slik ut
mysql> describe datalogger; +-------------+--------------+------+-----+-------------------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+--------------+------+-----+-------------------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | currTemp | decimal(7,4) | NO | | NULL | | | relayState | int(1) | NO | | NULL | | | tidsstempel | timestamp | NO | | CURRENT_TIMESTAMP | | +-------------+--------------+------+-----+-------------------+----------------+
Også til slutt lua-koden for polling og posting av temperatur.
Det er nok sikkert veldig tydelig at lua ikke er et språk jeg påstår jeg behersker.
Filnavn; beercontrol13.lua
--- Beercontroller by tdegerdalen --- version 0.13 --- uses ds18b20.lua by Peter Scargill --- uses networking.lua to configure wifi and static ip --- --- todo: relaybug at startup (see below) --- todo2: enable more sensors and average between them --- --- --- note; to avoid memory issues this script should be compiled before run maxTemp = 20 minTemp = 18 currTemp = 0 relayState = 0 --define pin for one 1-wire dallas tempsensor. sensorPin = 7 --define pins to control relay, set them to output --relay module attached kicks in when pulled low --bug: relay kicks in a few millisecs at boot - might fix it witch capacitator relay1pin = 3 relay2pin = 4 gpio.mode(relay1pin,gpio.OUTPUT) gpio.mode(relay2pin,gpio.OUTPUT) gpio.write(relay1pin,gpio.HIGH) gpio.write(relay2pin,gpio.HIGH) --- triggers --- every 5 seconds, poll tempsensor --- every 30 seconds, post to net and get temperature thresholds tmr.alarm(1, 5000, 1, function() pollTemp() end ) tmr.alarm(2, 30000, 1, function() postData() end ) --- functions below function pollTemp() t=require("ds18b20") currTemp = t.readNumber(sensorPin) print(currTemp) print("maxtemp", maxTemp) if currTemp > maxTemp and relayState == 1 then relayOff() end if currTemp < minTemp and relayState == 0 and currTemp ~= -0.0625 then relayOn() end if currTemp == -0.0625 then relayOff() end t = nil ds18b20 = nil package.loaded["ds18b20"]=nil end function postData() conn=net.createConnection(net.TCP, 0) conn:on("connection",function(conn, payload) conn:send("GET /beer/reg.php?currTemp="..currTemp.."&relayState="..relayState.." HTTP/1.1\r\n".. "Host: 10.0.0.2\r\n".. "Accept: */*\r\n".. "User-Agent: Mozilla/4.0 (compatible; esp8266 Lua;)".. "\r\n\r\n") end) conn:on("receive", function(conn, payload) tStreng,maxTempStart = string.find(payload,"<maxtemp>") maxTempEnd, tStreing = string.find(payload,"</maxtemp>") maxTempStart = maxTempStart + 1 maxTempEnd = maxTempEnd - 1 maxTempDeg = string.sub(payload, maxTempStart, maxTempEnd) tStreng,minTempStart = string.find(payload,"<mintemp>") minTempEnd, tStreing = string.find(payload,"</mintemp>") minTempStart = minTempStart + 1 minTempEnd = minTempEnd -1 minTempDeg = string.sub(payload, minTempStart, minTempEnd) print(minTempDeg, maxTempDeg) maxTemp = tonumber(maxTempDeg) minTemp = tonumber(minTempDeg) maxTempDeg = nil minTempDeg = nil conn:close() end) conn:connect(80,'10.0.0.2') end function relayOn() relayState = 1 print("RelayOn") gpio.write(relay1pin,gpio.LOW) gpio.write(relay2pin,gpio.LOW) end function relayOff() relayState=0 print("RelayOff") gpio.write(relay1pin,gpio.HIGH) gpio.write(relay2pin,gpio.HIGH) end