DIY WiFi Programmable Thermostat

Post details of your projects here.
basicchip
Posts: 1090
Joined: Fri Oct 19, 2012 2:39 am
Location: Weeki Watchee, FL
Contact:

Re: DIY WiFi Programmable Thermostat

Post by basicchip »

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.
pwr24ac2.jpg
pwr24ac2.jpg (170.18 KiB) Viewed 16870 times



basicchip
Posts: 1090
Joined: Fri Oct 19, 2012 2:39 am
Location: Weeki Watchee, FL
Contact:

Re: DIY WiFi Programmable Thermostat

Post by basicchip »

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.
thermo1.jpg
thermo1.jpg (110.66 KiB) Viewed 16866 times

basicchip
Posts: 1090
Joined: Fri Oct 19, 2012 2:39 am
Location: Weeki Watchee, FL
Contact:

Re: DIY WiFi Programmable Thermostat

Post by basicchip »

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.
thermoSW1.jpg
thermoSW1.jpg (172.33 KiB) Viewed 16246 times

basicchip
Posts: 1090
Joined: Fri Oct 19, 2012 2:39 am
Location: Weeki Watchee, FL
Contact:

Re: DIY WiFi Programmable Thermostat

Post by basicchip »

Making progress on firmware including LM71 and Newhaven character LCD display which uses an ST7066

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




basicchip
Posts: 1090
Joined: Fri Oct 19, 2012 2:39 am
Location: Weeki Watchee, FL
Contact:

Re: DIY WiFi Programmable Thermostat

Post by basicchip »

Working through all the functions
  • 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

basicchip
Posts: 1090
Joined: Fri Oct 19, 2012 2:39 am
Location: Weeki Watchee, FL
Contact:

Re: DIY WiFi Programmable Thermostat

Post by basicchip »

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...

basicchip
Posts: 1090
Joined: Fri Oct 19, 2012 2:39 am
Location: Weeki Watchee, FL
Contact:

Re: DIY WiFi Programmable Thermostat

Post by basicchip »

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


basicchip
Posts: 1090
Joined: Fri Oct 19, 2012 2:39 am
Location: Weeki Watchee, FL
Contact:

Re: DIY WiFi Programmable Thermostat

Post by basicchip »

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

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"

basicchip
Posts: 1090
Joined: Fri Oct 19, 2012 2:39 am
Location: Weeki Watchee, FL
Contact:

Re: DIY WiFi Programmable Thermostat

Post by basicchip »

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.

basicchip
Posts: 1090
Joined: Fri Oct 19, 2012 2:39 am
Location: Weeki Watchee, FL
Contact:

Re: DIY WiFi Programmable Thermostat

Post by basicchip »

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
thermoNU1.jpg
thermoNU1.jpg (456.92 KiB) Viewed 16167 times
And the new layout -- I'm getting better at using zones in KiCAD

thermoNU2.jpg
thermoNU2.jpg (160.54 KiB) Viewed 16167 times
And the KiCAD files
thermo2kicad.zip
(31.99 KiB) Downloaded 494 times

Post Reply