DIY WiFi Programmable Thermostat
Re: DIY WiFi Programmable Thermostat
So did some quick tests of a power supply circuit. For a while I was thinking of more complex circuits, but have settled on using a diode bridge into a cap with an OKI-78SR switching regulator that outputs 5V and can tolerate up to 36V input. I hooked that 5V through a resistor to a LiPoly battery. This is A TEST CASE, and NOT a suggestion. You can NOT trickle charge LiPoly batteries.
The final circuit will look at the battery voltage and turn off charging when voltage on the battery hits 4.2V.
The ARMstamp can do that, but a simple comparator might be a more prudent choice. With this arrangement I think I can charge the battery with a 100 mA charging circuit.
Here is my bench test.
The final circuit will look at the battery voltage and turn off charging when voltage on the battery hits 4.2V.
The ARMstamp can do that, but a simple comparator might be a more prudent choice. With this arrangement I think I can charge the battery with a 100 mA charging circuit.
Here is my bench test.
Re: DIY WiFi Programmable Thermostat
After the experiments, I have a very preliminary schematic for the Web enabled thermostat. Still need to connect the dots, and add some bypass caps. Should be doing a layout this week.
Re: DIY WiFi Programmable Thermostat
It's winter so time to finish this project. Got the boards back, picture on the blog.
https://www.coridium.us/coridium/blog/time-for-software
After finding a mis-labeled pin the temperature measurement is working. I chose a digital temp sensor the LM71. Happy that I did as it has 14 bit accuracy vs the 10 A/D inside the ARMstamp. So it has relative high accuracy, though it can be off by absolute 4 degrees F. That just means the temperature value will have a fixed fudge factor.
https://www.coridium.us/coridium/blog/time-for-software
After finding a mis-labeled pin the temperature measurement is working. I chose a digital temp sensor the LM71. Happy that I did as it has 14 bit accuracy vs the 10 A/D inside the ARMstamp. So it has relative high accuracy, though it can be off by absolute 4 degrees F. That just means the temperature value will have a fixed fudge factor.
Re: DIY WiFi Programmable Thermostat
Making progress on firmware including LM71 and Newhaven character LCD display which uses an ST7066
Here is that test code
Here is that test code
Code: Select all
' Drive NewHaven LCD
'
' 4-bit Initialization -- interface uses GPIO 15-8 (except 12
#define E IO(13)
#define R_W IO(14)
#define PortD_I IO(15)
#define DATA_ALLIGNED 1 ' set to 1 if data bits are aligned within a nibble
#if ! DATA_ALLIGNED
#define LCDbit4 8
#define LCDbit5 9
#define LCDbit6 10
#define LCDbit7 11
'/**********************************************************/
sub LCD_P1(i)
IO(LCDbit4) = i and &H10
IO(LCDbit5) = i and &H20
IO(LCDbit6) = i and &H40
IO(LCDbit7) = i and &H80
end sub
#else
'/**********************************************************/
sub LCD_P1(i) ' this faster, but LCD slow anyway
#ifdef MULTIPLE_MASKS ' if other bits writen with mask define this
GPIO_MASK(0) = &HFFFFF0FF ' LCDbits 11-8 hold data
#endif
GPIO_MPIN(0) = i<<4
end sub
#endif
'/**********************************************************/
sub LCDeHigh()
E = 1
waitmicro(600) 'enable pulse width>= 600ns
end sub
sub LCDeLow()
E = 0
waitmicro(600) 'enable pulse width>= 600ns
end sub
sub ClockNybble()
LCDeHigh
LCDeLow
end sub
'/**********************************************************/
'
sub LCDcommand(i)
LCD_P1(i) ' put data on output
PortD_I =0 ' D/I=LOW : send instruction
R_W =0 ' R/W=LOW : Write
ClockNybble() ' Send lower 4 bits
i = i<<4 ' Shift over by 4 bits
LCD_P1(i) ' put data on output Port
ClockNybble() ' Send upper 4 bits
R_W =1 ' R/W=high -- inactive??
waitmicro(37)
end sub
'/**********************************************************/
'
sub LCDwrite(i)
LCD_P1(i) ' put data on output
PortD_I =1 ' D/I=HIGH : send data
R_W =0 ' R/W=LOW : Write
ClockNybble() ' Clock lower 4 bits
i = i<<4 ' Shift over by 4 bits
LCD_P1(i) ' put data on output Port
ClockNybble() ' Clock upper 4 bits
R_W =1 ' R/W=high -- inactive??
waitmicro(37)
end sub
sub LCDinit()
#if DATA_ALLIGNED
GPIO_MASK(0) = &HFFFFF0FF ' LCDbits 11-8 hold data
GPIO_DIR(0) OR= &H00000f00
#endif
LCD_P1(0)
wait(100) ' Wait >40msec after power is applied
LCD_P1(&H30) ' put 0x30 on the output port
wait(5) ' must wait 5ms, busy flag not available
ClockNybble() ' command 0x30 = Wake up
wait(1) ' must wait 160us, busy flag not available
ClockNybble() ' command 0x30= Wake up #2
wait(1) ' must wait 160us, busy flag not available
ClockNybble() ' command 0x30 = Wake up #3
wait(1) ' can check busy flag now instead of wait
LCD_P1(&H20) ' put 0x20 on the output port
ClockNybble() ' Function set: 4-bit interface
LCDcommand(&H20) ' Function set: 4-bit/1-line
LCDcommand(&H10) ' Set cursor
LCDcommand(&H0C) ' Display ON; cursor off
LCDcommand(&H06) ' Entry Mode set
end sub
sub backliteON
IO(47)=0 ' turn on backlight
end sub
sub backliteOFF
IO(47)=1 ' turn on backlight
end sub
sub showTEMP(degF)
LCDcommand(&H83)
LCDwrite(&H30 + degF / 10) '
LCDwrite(&H30 + degF MOD 10) '
end sub
sub showSET
LCDcommand(&H80)
LCDwrite("s") '
LCDwrite("e") '
LCDwrite("t") '
end sub
sub eraseSET
LCDcommand(&H80)
LCDwrite(" ") '
LCDwrite(" ") '
LCDwrite(" ") '
end sub
sub showON
LCDcommand(&H86)
LCDwrite("o") '
LCDwrite("n") '
end sub
sub eraseON
LCDcommand(&H86)
LCDwrite(" ") '
LCDwrite(" ") '
end sub
sub warnBAT
LCDcommand(&H85)
LCDwrite("b") '
LCDwrite("a") '
LCDwrite("t") '
end sub
' LM71 is a digital temperature sensor with 14 bit output, absolute accuracy +/- 2 C,
' each one will be calibrated
' data is internally updated every 200-300 msec -- not much need to read faster
sub LM71init
IOCON_PIO1_23 = &H82 ' SSPI1 SSEL
IOCON_PIO1_20 = &H82 ' SSPI1 SCK
IOCON_PIO1_21 = &H82 ' SSPI1 MISO
SYSCON_PRESETCTRL = 4 ' unreset SSP1
SYSCON_SYSAHBCLKCTRL OR= (1<<18) ' enable SSP1
SYSCON_SSP1CLKDIV = 24 ' 1 MHz clock to LM71
SSP1_CR0 = &H0CF ' SPI mode clock normally high capture on rise
SSP1_CPSR = 2
SSP1_CR1 = 2 ' enable SPI master mode -- should be done last
end sub
function LM71read
dim tempSample
SSP1_DR = 0 ' write causes clocks for a read
while SSP1_SR and &H10 ' check busy
' TXD(0)="." ' inserted during debug to see this bit works -- its fine
loop
while SSP1_SR and &H4 ' check data still in FIFO
tempSample = SSP1_DR ' read data register until FIFO empty
' TXD(0)="+" ' inserted during debug to see this bit works -- its fine
loop
return tempSample>>2
end function
#define tempFudge 5
function convert2degreesF (sample)
dim i
dim t as single
t = 32.5 + 0.05625 * sample - tempFudge
i = t
return i
end function
main:
LM71init
LCDinit
LCDcommand(1) 'clear display
wait(3)
backliteON
for i=1 to 5
wait(300)
x = LM71read
print 32.0 + 0.05625 * x, hex (x), hex ((x<<2) + 3), convert2degreesF(x)
showTEMP( convert2degreesF(x) )
next
showSET
wait (2000)
eraseSET
showON
wait (2000)
backliteOFF
Re: DIY WiFi Programmable Thermostat
Working through all the functions
Now on to writing code for switch debounce and function. Then check out WiFi -- will borrow most of that code from the web clock project.
In the final version will wrap it up and every minute check temp, battery and then go back to sleep. Switch operations will wake it up, display and control set temp.
Then I have to build some sort of server, either locally or on the web (the advantage of having a website) to record operations and control remotely
- smoke test - 24V AC supply OK
- temp sense OK
- LCD OK
- backlight control OK
- charge enable OK
- battery sense OK -- after I remembered the 24V AC needed to be there for that to work
- heat request OK
Now on to writing code for switch debounce and function. Then check out WiFi -- will borrow most of that code from the web clock project.
In the final version will wrap it up and every minute check temp, battery and then go back to sleep. Switch operations will wake it up, display and control set temp.
Then I have to build some sort of server, either locally or on the web (the advantage of having a website) to record operations and control remotely
Re: DIY WiFi Programmable Thermostat
Doing some power testing, yes I have a short attention span.
I tried running the ESP8266 from the incoming 24VAC switcher, but that way it draws about 20 mA from 24 VAC, which might trigger the heat system to come on. So back to the battery for that. As the WiFi takes up to 250 mA, it determines the battery size. So max discharge would mean 300 mAH minimum size, though 0.2C is standard discharge rate so 500 mAH probably a better choice.
Added an ASM_WFI command to ASMinlineBASIC.bas file to put the ARM to sleep.
Just going to sleep got the ARM current down to 10 mA, by shutting down PLLs and crystal oscillator, it was under 5 mA. Do I need to go lower? Probably not but will evaluate when I get the software farther along.
OK back to switch interrupts...
I tried running the ESP8266 from the incoming 24VAC switcher, but that way it draws about 20 mA from 24 VAC, which might trigger the heat system to come on. So back to the battery for that. As the WiFi takes up to 250 mA, it determines the battery size. So max discharge would mean 300 mAH minimum size, though 0.2C is standard discharge rate so 500 mAH probably a better choice.
Added an ASM_WFI command to ASMinlineBASIC.bas file to put the ARM to sleep.
Just going to sleep got the ARM current down to 10 mA, by shutting down PLLs and crystal oscillator, it was under 5 mA. Do I need to go lower? Probably not but will evaluate when I get the software farther along.
OK back to switch interrupts...
Re: DIY WiFi Programmable Thermostat
And now working on the buttons, here is some code that is handling the buttons using GPIO interrupts. Basically debounce is done by ignoring changes during the debounce time.
Code: Select all
''''''''''''''''''''''''''''''''''' UP / DOWN interrupts '''''''''''''''''''''''''''
'
'
#define DEBUG_BUTTONS
#define DebounceTime 20000 ' 20 msec
UPtime = 0 ' used for debounce
DOWNtime = 0 ' for now 0 value OK, but if callbacks on time ever used 0 would indicate idle
UPvalue = 0 ' debounced state of button (1 is pushed)
DOWNvalue = 0
interrupt sub UPbutton
if TIMER - UPtime > DebounceTime
UPtime = TIMER OR 1 ' make sure 0 timer value never used
if GPIO_PIN_FALL AND 1
UPvalue = 1
#ifdef DEBUG_BUTTONS
txd(0)="U"
#endif
else
UPvalue = 0
#ifdef DEBUG_BUTTONS
txd(0)="u"
#endif
endif
endif
GPIO_PIN_IST = 1 'clear the interrupt
end sub
interrupt sub DOWNbutton
if TIMER - DOWNtime > DebounceTime
DOWNtime = TIMER OR 1 ' make sure 0 timer value never used
if GPIO_PIN_FALL AND 2
DOWNvalue = 1
#ifdef DEBUG_BUTTONS
txd(0)="D"
#endif
else
DOWNvalue = 0
#ifdef DEBUG_BUTTONS
txd(0)="d"
#endif
endif
endif
GPIO_PIN_IST = 2 'clear the interrupt
end sub
sub setUPdownInt
SYSCON_SYSAHBCLKCTRL OR= (1<<19) ' enable clock to GPINT
FLEX_INT0_ISR = addressof UPbutton OR 1
FLEX_INT1_ISR = addressof DOWNbutton OR 1
GPIO_PIN_SIENR = 3 ' rise edge interrupt on pins
GPIO_PIN_SIENF = 3 ' falling edge interrupt on pins
SYSCON_PINTSEL(0) = 2
SYSCON_PINTSEL(1) = 5
VICIntEnSet0 = (1<<FLEX_INT0_IRQn) OR (1<<FLEX_INT1_IRQn)
end sub
Re: DIY WiFi Programmable Thermostat
And here is some initial code to put the CPU to sleep
not turning off the oscillators as that cuts the connection to the PC, and need that for debugging for now
not turning off the oscillators as that cuts the connection to the PC, and need that for debugging for now
Code: Select all
ST_CTRL = 5 ' disable systick interrupt
SYSCON_MAINCLKSEL = 0 'switch to IRC clock
SYSCON_MAINCLKUEN = 0 '
SYSCON_MAINCLKUEN = 1 'enable switch to IRC clock
' SYSCON_PDRUNCFG = &HE9F0 ' turn off oscilators
ASM_WFI ' go to sleep
' SYSCON_PDRUNCFG = &HE840 ' turn on oscilators
while (SYSCON_SYSPLLSTAT AND 1) = 0
loop
while (SYSCON_USBPLLSTAT AND 1) = 0
loop
#warning need to wait here for PLLs to lock
SYSCON_MAINCLKSEL = 0 'switch to PLL clock
SYSCON_MAINCLKUEN = 0 '
SYSCON_MAINCLKUEN = 1 'enable switch to IRC clock
ST_CTRL = 7 ' enable systick interrupt
print "back"
Re: DIY WiFi Programmable Thermostat
Another word on switch debounce. Turns out the code works fine for 1 switch, but the other must have some contamination, as it goes high and low while holding it down. Probably sloppy solder / cleaning technique on my part. A good reason to place switches last when building boards by hand. many switches do not tolerate board washing.
Re: DIY WiFi Programmable Thermostat
OK, I've seen all the pieces work including WiFi, though in the long run I should program that in Lua and load onto the ESP8266. Right now it just checks the time from my timer server on the Coridium web site. I am not sure how I will record data there, but it could easily query a web page to read a set temperature, Now I would be a fool if that were www.coridium.us/temp but more likely something like www.coridium.us/asdf07asdf9zvavfaf93423 ... bsb5gbbsth. Pretty hard to hack that.
While the original design works and with a big enough hammer fits into the thermostat cover. I decided to tweak the layout so it fits better.
So here is the schematic
And the new layout -- I'm getting better at using zones in KiCAD
And the KiCAD files
While the original design works and with a big enough hammer fits into the thermostat cover. I decided to tweak the layout so it fits better.
So here is the schematic
And the new layout -- I'm getting better at using zones in KiCAD
And the KiCAD files