Wireless Remote Monitor and Controller

matherp

Senior Member
#1
Based on the work of Ibenson with the TLG10UA03, I've developed a generic PCB to allow building fully engineered web accessible monitoring and controlling applications.

The sample code provided in the next post is designed to work on an AXE401 for development rather than the version for the PCB but the only differences are the port assignments.
The example code uses one DS18B20 as a remote thermostat. The themostat temperature can be set remotely and the web page displays the current temperature as well as the max/min which can be reset remotely. The code uses serin/serout to talk to the UART but the PCB connects using the HW RX/TX pins so hardware serial comms can be used as required.

The PCB takes a 20 pin picaxe and allows direct connection of the TLG10UA03 wifi card and has up to 6 off 3-pin ports for flexible I/O (input or output with optional pullups and series resistors) as well as a 4-pin i2c port with built in pull-ups. The ports have power and ground supplied. The board uses one of the cheap and readily available LM2596 Low Ripple DC-DC Converter Step Down Power Supply modules which can be set to the preferred bus voltage, 3.3V in the case of boards using the TLG10UA03 wifi card, allowing the use of any DC supply up to 40V without worrying about overheating a linear regulator. All components are through hole except the resistors where the large ansd easily soldered 1206 SMD parts are used.

A ICSP port is also available if you want to use a raw PIC rather than a picaxe. A relay drive is provided using a BCX38c (or 2n2222 etc.) with the relay positive power selectable between the input voltage or the bus voltage.

The PCB is about 50mm X 70mm and is shown in a home produced 3D printed box with a 16A mains relay connected in a second isolated "printed" box.

The TLG10UA03 set up is simple, starting from its default, the communication type is set to TCP server and the wifi is set up to talk with your router. I then use dyndns.org to set up a web address that links to the dynamic IP address supplied by my ISP. The router is then set to port forward an external port to the wifi uart (50000 is the default)

Being lazy, I buy the DS18B20 ready wired and sealed from Sure Electronics. These can then be used indoor or out and are available with lead lengths up to 10m.

The circuit shown in the schematic is my V1.0. It was developed in DesignSpark and the PCBs were made by IteadStudio.

I've subsequently improved the circuit design to allow a 14M2 or 20-pin picaxe and optional RC filtering of inputs and also to allow the use of an ERF board instead of the wifi uart for local communications. These boards will also have a 16A relay and power connections on an extension that can be cut off if not required. I'm waiting on the boards to arrive and once tested can publish details if anyone is interested. I'm also playing with a capacitive dropper power supply to allow direct mains input.

If you want to have a look at the system live you can try http://matherp.dyndns.org:50000
I'll try and leave it up over the next few days. You can press the buttons without fear of anything bad happening :)

Any questions or comments appreciated as always.

circuit.jpg P1040365.jpg
 
Last edited:

matherp

Senior Member
#2
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,"&deg;C<br></TD>")
  	else
  		serout seroutport,baudrate, (" ",b8,"&deg;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,("&deg;C</TD></TR>")
return
 
#5
I am interested in making the Ciseco XRF 900 MHZ wireless RF receiver circuit that can detect the signal broadcast from Collett Communications Snowmobile Groomer Warning Beacon (GWB) device that transmit at 900 MHZ - Channel 1 to illuminate an LED to provide a heads up as to the potential danger of a grooming in the vicinity while traveling the snowmobile trails.

www.collettcommunicator.com/

What GWB signal information do I need to configure this radio or would it be plug and play to receive the (GWB) signal on Channel 1? Also what is required to convert the reception of the GWB only signal to trigger an LED warning light to alert me that a snowmobile groomer is in the area to avoid a collision?

Thanking you in advance,

Paul Wilkie - Volunteer
Wellston, MI 49689
Wellston Winter Trails and Promotions
wellstonwintertrails.com/
Located in the heart of the beautiful Manistee National Forest
734 550 6763
 
Top