Don't attempt any project which uses household current unless you are capable! You could burn the place down!! Or even toast your cat! Be sure to follow your local electrical code.
I took a 40 watt incandescent light bulb, put it in a appropriate socket and mounted it inside a piece of heavy walled pipe. I capped both end of the pipe and poked several small holes to let the heat escape. I made sure there was more than
one inch clearance between the bulb and pipe inner wall. Using the appropriate wiring, I connected up a robotdyne module to the esp. If the temperature gets too hot or too cold, the esp will send me a text warning on the phone.
The beauty of the dimmer function is that the bulb always has a "soft start" and will have a very long life. The code also provides more or less heat with more or less temperature spread. Its not just on/off. Its progressive.
See the Project Text/email alert for text setups
Code: [Local Link Removed for Guests]
'Annex Cat House Thermostat/heater v.4 40W lightbulb
dimmer.stop
pause 10
onHtmlReload create_page
onhtmlchange update
'file.save "/tmpset.txt", str$(5) 'XXXXXXXXXXXXXXXXXXXX uncheck this for the first run so it creates a txt file
PWR = 0 ' variable for dimmer intensity
gosub create_page
timer0 2000, update
wait
create_page:
cls
autorefresh 2000
D4 = 2 ' sensor input
setp = val(file.read$("/tmpset.txt"))
curr = val(TEMPR$(D4,1))*(1.05) ' 1.05 is calibration if needed
curr1 = 99 'displayed sensor reading if sensor issue
PWR = 0
DIMMER.SETUP 4, 5 , 0, 1 'ZC signal io4 , Output pulse io5 , short io13 to io4
DIMMER.LIMITS 1300, 8300 'actual min/max delay in triac firing
pause 10
stat$ = "Heat is off"
ltmp = 0 'low temp warning variable
htmp = 0 'high temp warning variable
phoneN = 12345678910 'phone number for alert text XXXXXXXXXXXXXXXXXXXXX
qsbutt$ = "background-color:white;text-align:center;display:block;width:130px;height:50px;font-size:15;font-weight:bold;box-shadow: 3px 3px black;border-radius:5px;line-height: 1"
txtbstat$ = "background-color:white;text-align:center;display:block;width:160px;height:26px;font-size:15;font-weight:bold"
txtbsetp$ = "background-color:white;text-align:center;display:block;width:54px;height:42px;font-size:30;font-weight:bold"
txtbcurr1$ = "background-color:white;text-align:center;display:block;width:54px;height:42px;font-size:30;font-weight:bold"
A$ = ""
A$ = A$ + |<!DOCTYPE html><html><body><style>|
A$ = A$ + |body {background-color: black;}|
A$ = A$ + |p {font-size:24px;}|
A$ = A$ + |</style>|
A$ = A$ + |<table align='center' width='300' height='100' bgcolor='lightgreen' border='1' cellpadding='8'>|
A$ = A$ + |<th>|
A$ = A$ + |<p>Cat House Temperature</p></th></center>|
A$ = A$ + |<th><center>|
A$ = A$ + textbox$(curr1, "txt1")
A$ = A$ + |</th></center>|
A$ = A$ + cssid$("txt1", txtbcurr1$)
A$ = A$ + |</table>|
A$ = A$ + |<table align='center' width='300' height='100' bgcolor='red' border='1' cellpadding='8'>"|
A$ = A$ + |<center><th>|
A$ = A$ + |<p>Thermostat<br>is Set At</p>|
A$ = A$ + |</th></center>|
A$ = A$ + |<th><center>|
A$ = A$ + textbox$(setp, "txt2")
A$ = A$ + |</th></center>|
A$ = A$ + cssid$("txt2", txtbsetp$)
A$ = A$ + |</table>|
A$ = A$ + |<center>|
A$ = A$ + |<p><font color = 'white', font size = '4'>Type Desired Temp. in Above Window<br>or select a Quick Button below</font></p>|
A$ = A$ + |</center>|
A$ = A$ + |<table align='center' width='300' bgcolor='red' border='1' cellpadding='5'>|
A$ = A$ + |<center><th>|
A$ = A$ + button$("<b><big>Quick set to 5 deg.</big><b/>", Qset5, "but1")
A$ = A$ + |</th></center>|
A$ = A$ + cssid$("but1", qsbutt$)
A$ = A$ + |<center><th>|
A$ = A$ + button$("<b><big>Quick set to 10 deg.</big><b/>", Qset10, "but2")
A$ = A$ + |</th></center>|
A$ = A$ + cssid$("but2", qsbutt$)
A$ = A$ + |</table>|
A$ = A$ + |<table align='center' width='300' bgcolor='lightblue' border='1' cellpadding='8'>|
A$ = A$ + |<td><center>|
A$ = A$ + |<b><big>Heater Status</big></b>|
A$ = A$ + |</center><center>|
A$ = A$ + textbox$(stat$, "txt3")
A$ = A$ + cssid$("txt3", txtbstat$)
A$ = A$ + |</center></td></table>|
A$ = A$ + |<br><center>|
A$ = A$ + button$("<b><big>Refresh Page if Needed</big><b/>", freshweb)
A$ = A$ + button$("<b><big>Turn OFF</big><b/>", offf)
A$ = A$ + |</center></table></body></html>|
HTML A$
A$ = ""
return
hheat:
'wlog "high heat"
stat$ = "Heat is On High"
if curr < -10 gosub alert_low 'if temp low, go to alert
return
off2:
'wlog "Off"
stat$ = "Heat is now OFF"
DIMMER.BRIGHTNESS PWR
if curr > 25 gosub alert_high ' if temp high, go to high_alert
return
Qset10:
setp = 10
return
Qset5:
setp = 5
return
update:
curr = val(TEMPR$(D4,1))*(1.05) ' 1.05 is calibration if needed
'wlog "actual temp -> " ;curr
'wlog "set temp " ;setp
if setp <= -1 or setp > 30 then let setp = val(file.read$("/tmpset.txt")) 'if temp has been set out of normal range, it defaults to last setting
if (setp <> val(file.read$("/tmpset.txt"))) and (setp < 30) and (setp > -1) then file.save "/tmpset.txt", str$(setp) 'writes last acceptable setting to memory
if curr < 40 and curr > -40 then curr1 = int(curr) 'int gives no decimal xxxxxxxxxxxxxxxx use this line to calibrate eq. int(curr) - 5
setp = val(file.read$("/tmpset.txt"))
PWR = (setp - curr) * 100 / 3 ' linear increase in power with linear decrease in temp drop from set point (3 deg span)
If PWR < 0 then let PWR = 0
If PWR > 100 then let PWR = 100
DIMMER.BRIGHTNESS int(PWR)
pause 100
if PWR = 100 then gosub hheat
if PWR < 100 and PWR > 0 then stat$ = "Heat is On"
if PWR = 0 then gosub off2
return
freshweb:
dimmer.stop
gosub create_page
return
alert_low:
ltmp = ltmp + 1
if ltmp < 450 return
ltmp = 0
EMAIL.SETUP "smtp.gmail.com", 465, "joeblow@gmail.com", "mypassss" 'replace with your login / password
print EMAIL ("joeblow@gmail.com", "phoneN@msg.telus.com", "Title : Thermostat", "Cat house is below -5")
pause 100
'wlog "low message sent"
return
alert_high:
htmp = htmp + 1
if htmp < 450 return
htmp = 0
EMAIL.SETUP "smtp.gmail.com", 465, "joeblow@gmail.com", "mypassss" 'replace with your login / password
print EMAIL ("joeblow@gmail.com", "phoneN@msg.telus.com", "Title : Thermostat", "Cat house is above 25")
pause 100
'wlog "high message sent"
return
offf:
dimmer.stop
timer1 0
cls
A$ = ""
A$ = A$ + |<!DOCTYPE html><html><body><style>|
A$ = A$ + |body {background-color: black;}|
A$ = A$ + |p {font-size:36px;}|
A$ = A$ + |</style>|
A$ = A$ + |<br><center>|
A$ = A$ + button$("<b><big>Boot Up Thermostat</big><b/>", stopme)
A$ = A$ + |</center></table></body></html>|
HTML A$
onHtmlReload offf
refresh
return
stopme:
dimmer.stop
cls
reboot