Code:
#picaxe 28X2
'
' Ports to use AXE401 as test platform
'
setfreq em64
symbol thermo_range_start=17 'start of thermostat range in degC
symbol hysteresis = 2 '2/10ths degree
symbol seroutport=c.6 'TX port
symbol serinport=c.7 'RX port
symbol heaterport=c.3 'Relay Drive - enable LED to see output
symbol temperatureport=c.4 'used for DS18B20
symbol DS18B20power = c.2 'used for DS18B20 VCC pin
symbol positive=0
symbol negative=1
symbol hoff=0
symbol hon=1
symbol baudrate=t9600_64
symbol onesecond = 8000
symbol fourseconds = 32000
'
' Variable usage
'
symbol sign =bit0
symbol heater=bit1
symbol i = b1
symbol word1 = w1 '-32768 to 32767
symbol byte1 = b2 '-128 to 127
symbol byte2 = b3
symbol word2 = w2
symbol byte3 = b4
symbol byte4 = b5
symbol bytearray = 6 'address of space for bintoascii, reserve 7 bytes b6-b13
symbol loopCounter = b14
symbol value = b15
symbol loopconvert=b16
symbol commandinput=b17
symbol setpoint = w9
symbol ii=b20
symbol type = b21
symbol currenttemp=w11
symbol wordsave=w12
'
eeprom 0,(255,255,255,255,255,255) ' set invalid status after programming
symbol valuelocation=0
Symbol maxlocation=2
symbol minlocation=4
'
start:
high DS18B20power
low heaterport
heater=hoff
pause onesecond
read valuelocation,value ' get the saved thermostat setting
if value<"A" or value>"L" then: value="A":write valuelocation,value:endif 'if invalid set to off
readtemp12 temperatureport,currenttemp 'temperature as signed word * 16
currenttemp=currenttemp+1000 ' make sure it is always positive
read maxlocation,word word1 'read in the save max and min temperatures
if word1=65535 then: write maxlocation,word currenttemp:endif 'if invalid set to current
read minlocation,word word1
if word1=65535 then: write minlocation,word currenttemp:endif
'
main:
do
owout temperatureport,%1001,($CC,$44) 'start the background temperature read
commandinput = 0: type =0 'set to no input
serin [fourseconds,skip], serinport, baudrate,("GET"), ii, ii, commandinput,ii,type,ii,value
sertxd(commandinput," ",type," ",value,cr,lf)
select commandinput
case " " 'normal read of web page with no data input
gosub sendHeader
gosub updateheater
serout seroutport, baudrate,("Content-Length: 1772",cr,lf,cr,lf)
gosub sendBeginning
gosub sendEnding
case "d" ' data returned
gosub sendHeader
if type="R" then:write valuelocation,value:endif 'change in thermostat value
gosub updateheater
if type="C" then 'reset of max/min
write maxlocation,word currenttemp
write minlocation,word currenttemp
endif
serout seroutport, baudrate,("Content-Length: 1772",cr,lf,cr,lf)
gosub sendBeginning
gosub sendEnding
else
gosub sendHeader
serout seroutport, baudrate,("Content-Length: 40",cr,lf,cr,lf)
serout seroutport, baudrate,("<html><body>Page Not Found</body></html>",cr,lf,cr,lf)
endselect
pause onesecond 'allow the temperature read to complete
skip:
owout temperatureport,%0001,($CC,$BE)
owin temperatureport,%0000,(byte1,byte2) ; read in temperature
word1=word1+1000' make sure it is always positive
currenttemp=word1 'set the current temperature
read maxlocation, word word1
if currenttemp>word1 then:write maxlocation,word currenttemp:endif
read minlocation,word word1
if currenttemp<word1 then:write minlocation,word currenttemp:endif
gosub updateheater 'update the heater even when no input
loop
'
updateheater:
word1=currenttemp-1000 '
word2=10
gosub multsignedword 'temperature as signed word * 160
word2=16
gosub divsignedword 'temperature * 10
read valuelocation,value
if value="L" then: high heaterport:heater=hon:endif
if value="A" then: low heaterport :heater=hoff:endif
if value>="B" and value<="K" then
setpoint=value-"B"+thermo_range_start*10 'setpoint * 10
setpoint = setpoint + hysteresis
if word1>setpoint then: low heaterport: heater=hoff:endif
setpoint = setpoint - hysteresis - hysteresis
if word1<setpoint then: high heaterport: heater=hon:endif
endif
return
'
sendHeader:
serout seroutport, baudrate,("HTTP/1.1 200 OK",cr,lf)
serout seroutport, baudrate,("Content-type: text/html",cr,lf)
serout seroutport, baudrate,("Connection: close",cr,lf)
return
sendBeginning:
serout seroutport, baudrate,("<html><head><title>Demo Monitor</title></head><body>")
serout seroutport, baudrate,("<form name='f1' method='get' action='d'>")
serout seroutport, baudrate,("<h2 align='left'>Demo Monitor V2.0</h2>",cr,lf)
'
serout seroutport, baudrate,("<p><TABLE BORDER='1' CELLSPACING='0' CELLPADDING='5'>")
serout seroutport, baudrate,("<TR><TD>Heating</TD>")
if heater = hon then : serout seroutport, baudrate,("<TD BGCOLOR='#ff0000'> On</TD></TR>"):endif
if heater = hoff then : serout seroutport, baudrate,("<TD BGCOLOR='#00ff00'>Off</TD></TR>"):endif
serout seroutport, baudrate,("</TABLE></p>")
'
serout seroutport, baudrate,("<p><TABLE BORDER='1' CELLSPACING='0' CELLPADDING='5'>")
serout seroutport, baudrate,("<TR><TD></TD><TD>Temperature</TD></TR>")
serout seroutport, baudrate,("<TR><TD>Current</TD><TD>")
word1=currenttemp
gosub outputtemp
serout seroutport, baudrate,("<TR><TD>Max</TD><TD>")
read maxlocation,word word1
gosub outputtemp
serout seroutport, baudrate,("<TR><TD>Min</TD><TD>")
read minlocation,word word1
gosub outputtemp
serout seroutport, baudrate,("</TABLE></p>")
serout seroutport,baudrate,("<input name='C' type='checkbox' value='R' onClick='this.form.submit()'> Reset Max/Min")
'
serout seroutport, baudrate,("<p><TABLE BORDER='1' CELLSPACING='0' CELLPADDING='5'>")
serout seroutport, baudrate,("<TR><TD>Thermostat</TD>")
for loopCounter = "A" to "L"
if loopCounter=value then
serout seroutport, baudrate,("<TD><input name='R' type='radio' checked='checked' value='",loopcounter)
else
serout seroutport, baudrate,("<TD><input name='R' type='radio' value='",loopcounter)
endif
serout seroutport, baudrate,("' onClick='this.form.submit()'> ")
loopconvert=loopcounter-"B"+thermo_range_start
bintoascii loopconvert,b6,b7,b8
if loopcounter>"A" and loopcounter<="K" then
if b7<>"0" then
serout seroutport,baudrate, (b7,b8,"°C<br></TD>")
else
serout seroutport,baudrate, (" ",b8,"°C<br></TD>")
endif
endif
if loopcounter="A" then : serout seroutport,baudrate, ("Off<br></TD>") :endif
if loopcounter="L" then : serout seroutport,baudrate, ("On<br></TD>") :endif
next loopCounter
serout seroutport, baudrate,("</TR></TABLE></p>")
'
sendEnding:
serout seroutport, baudrate,("</form></body></html>",cr,lf,cr,lf,"1234567890")
return
'
' signed arithmetic
'
' NB add and subtract can be used as normal
' the distinction between + and - is made at the output formatting stage
'
'
'
'Function multsignedword(word1 As Word, word2 As Word) As Word
'multiply word1 by word2 and return the result in word1
'
multsignedword:
sign = positive
If word1 >= $8000 Then
sign = Not sign
word1 = -word1
Endif
If word2 >= $8000 Then
sign = Not sign
word2 = -word2
Endif
word1 = word1 * word2
If sign = negative Then
word1 = -word1
Endif
return
'
'Function divsignedword(word1 As Word, word2 As Word) As Word
'divide word1 by word2 and return the result in word1
'
divsignedword:
sign = positive
If word1 >= $8000 Then
sign = Not sign
word1 = -word1
Endif
If word2 >= $8000 Then
sign = Not sign
word2 = -word2
Endif
word1 = word1 / word2
If sign = negative Then
word1 = -word1
Endif
return
'
'Proc signedwordtoasciix10
' returns a byte array starting at pointer bytearray terminated by a null
' of the numberin word1 which is 10x the actual value to give value in 1/10ths
' the number is stripped of leading zeroes
'
signedwordtoasciix10:
wordsave=word1
sign=positive
bptr = bytearray
If word1 >= $8000 Then
sign= negative
word1 = -word1
else
endif
bintoascii word1,@bptrinc,@bptrinc,@bptrinc,@bptrinc,@bptr
byte3=@bptr
@bptrinc="."
@bptrinc=byte3
@bptr=0 'denotes end of string with a null
byte3=0
bptr = bytearray
if @bptrinc="0" then ' at least one leading zero
byte3=1
if @bptrinc="0" then ' at least two leading zeros
byte3=2
if @bptrinc="0" then ' at least three leading zeros
byte3=3
endif
endif
endif
byte1=bytearray+byte3
byte2=bytearray+6
byte4=bytearray
for i= byte1 to byte2 'now move array (including trailing null) left by the number of leading zeroes
bptr=i
byte3=@bptr
bptr=byte4
@bptr=byte3
byte4=byte4+1
next i
if sign=negative then
byte1=bytearray
byte2=bytearray+6
for i= byte2 to byte1 step -1 'now move array (including trailing null) left by the number of leading zeroes
bptr=i
byte3=@bptrinc
@bptr=byte3
next i
bptr=bytearray
@bptr="-"
else
byte1=bytearray
byte2=bytearray+6
for i= byte2 to byte1 step -1 'now move array (including trailing null) left by the number of leading zeroes
bptr=i
byte3=@bptrinc
@bptr=byte3
next i
bptr=bytearray
@bptr=" "
endif
word1=wordsave
return
'
'
outputtemp: 'take temp to be output in word1
word1=word1-1000
word2=10
gosub multsignedword 'temperature as signed word * 160
word2=16
gosub divsignedword 'temperature * 10
gosub signedwordtoasciix10
bptr=bytearray
loopconvert=@bptrinc
do
serout seroutport,baudrate,(loopconvert)
loopconvert=@bptrinc
loop while loopconvert<>0
serout seroutport, baudrate,("°C</TD></TR>")
return
Bookmarks