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