Differential Controller source code listing

' Firmware Program for Comfile CB210 - Dual Pump - Differential Temperature Controller
'           Version 17 of 18 Feb. 2013
'
' Cubloc Studio Configuration:
'           Com Port # of Debug Terminal = that assigned by MS Windows: see Control Panel
'                             /Hardware Devices, [typically COM4].
'           Baud Rate: default 115,200, Parity: default none, Data bits: default 8
'           Cabling between PC and CB210: ordinary USB cable [used for debug only,
'                 cabling and PC un-necessary in final installation]
'
' Hardware Configuration:
'     I/O Port Usage:
'                 A0 16 = solar collector thermistor divider, A to D input;
'                 A1 17 = storage tank thermister divider, A to D input;
'                 A10 = input port, "test push button", active low; only polled right after
'                             port 30, 3 second LED goes "OFF" [ie: push during LED "ON" and hold until
'                             LED goes "OFF"] - useful for manually testing activation of pumps
'                             during installation. Push button circuit consists of a momentary SPST
'                             switch, a capacitor of 0.001 to 0.01 micro-farads across the switch
'                             contacts, one switch contact is tied to ground, the
'                             other switch contact has both a 4.7k resistor up to + 5 Volts, and a
'                             "sense wire" to input port A10.
'                 11 = output port, "main" pump "1" pwr control, 1- enable, 0- disable,
'                             drives gate of a IRF540 power FET-1 switching to ground level;
'                 12 = output port, "secondary" pump "2" pwr control, 1- enable, 0- disable,
'                             drives gate of a IRF540 power FET-2 switching to ground level;
'                 13 = output port, thermistor power, 0- enable, 1- disable,
'                             drives gate of a VN10K FET-3, turning on current at ground end;
'                 30 = CB210 onboard LED, used to blink LED on each 60 second sense loop.
'
'           Power and Grounds:
'                 The POS terminal of a lead acid auto battery [~ +13.3Vdc under charge] directly
'                       powers both circulator pumps via the interface board [note: there is no
'                       direct +13.3 Vdc connection to the CB210 processor board!], an in-line fuse
'                       is recommended at the battery + terminal [~ 7 to 10 amp.];
'                 A small 45W PV panel can be used to partially charge the battery during sunny
'                       periods, however a diode must be installed to prevent power drain during
'                       dark periods [perhaps a 5 amp. Schottky MBR560];
'                 Pump FET switch "1" controls the "main" pump and additionally powers the coil
'                       of a relay to energize the 110Vac input to a "cooler adapter" being used
'                       as a charger for the auto battery [when the main pump in energized];
'                 The auto battery +13.3Vdc feeds an LM317T voltage regulator generating
'                       +6.125 Vdc for the sensor circuit and an AN7808 8V regulator that feeds
'                       both the EXT [9 To 10 Vdc] on-board power socket connection to CB210 main
'                       board, and a 78L05 5.0V regulator for voltage reference AREF;
'                       Note: On the CB210 board, be sure to set power select switch to "EXT"!
'                 All circuit grounds, including the CB210 are directly tied to 0VDC (negative
'                       terminal of auto battery, [note: the negative pump terminals, and the
'                       negative terminal of the coil of the relay (for 110vac battery charger) are
'                       tied to FET switches (ie. not direct to ground)], [note: to avoid ground
'                       loop noise, ensure all grounds are of appropriate current handling size,
'                       and are not duplicated.]
'                 AREF the analog reference, +5.0 Vdc pin 15 [long header], is taken from 78L05
'                       +5.0 V output terminal and filtered;
'
Const Device = CB210    ' advise Cubloc Studio [& compiler] that a CB210 board is being used     
'                 Info: On power up, all I/O is set to tri-state inputs
'
' Store Constants to Program Memory [ie: to semi-permanent flash memory, thus saving RAM]
'
' analog input voltage catagory separations
Const Integer VAINP = (212,282,371,477,594,713) ' intervals of A to D integer readings.
' slope by category
Const Single SLOPE_M = (-38.09506,-29.06588,-23.02484,-19.28649,-17.42676,-17.29524,-19.07771)
' offset by category
Const Single OFFSET_B = (99.06181, 89.75561, 81.48384, 74.78804, 70.55928, 70.30456, 76.65089)
' analog input to divider voltage factor (resolution)
Const Single ATOVD = (0.004887586) ' Volts per division=5 volts/1023 reading intervals
'
' End User defined offset temperature (in deg.C) to account for line losses back from
' collector and to minimize short cycling of the pump.
'
Const Single OFFSET_T0 =(2.222)           ' deg. C. or 4.0 deg.F. main pump offset temperature
Const Single OFFSET_T1 =(3.333)           ' deg. C. or 6.0 deg.F. secondary pump offset temperature
'
' Allocate Variable Storage in RAM
'
Dim AIN As Integer                  ' dummy for analog input
Dim AIN0 As Integer                 ' analog input(0), positive integer 0 to 1023
Dim AIN1 As Integer                 ' analog input(2), positive integer 0 to 1023
Dim M As Single                     ' slope, float
Dim B As Single                     ' offset, float
Dim TEMP As Single                  ' sensed temperature in deg.C, float
Dim TEMPC0 As Single                ' solar collector temperature [main] in deg.C, float
Dim TEMPC1 As Single                ' solar collector temperature [secondary] in deg.C, float
Dim TEMPS As Single                 ' storage tank temperature in deg.C, float
Dim INDEX As Byte                   ' used for curve fit index and pump port selection
Dim INDEX2 As Byte                  ' used in manual test routine
Dim KEYPRESS As Byte                ' active low when push button depressed  
'                                                                                        
START:
Ramclear                                  ' clear all variables
                                                '
                                                ' de-activate both pumps
Out 11,0                                  ' initialize Port 11 to output & turn off main pump "1"
Wait 25                                   ' short wait to stabilize EMF transient
Out 12,0                                  ' initialize Port 12 to output & turn off secondary pump"2"
INDEX = 0                           ' initialize flag to both pumps OFF
INDEX2 = 0                          ' initialize manual push button index
Input 10                                  ' initialize Port 10 (push button) to input
'
Wait 2000                           ' wait 2 sec for Debug Terminal program to load
Debug "CB210 Differential Temperature Control For ",Cr
Debug "      BIS $1k Solar Water Heater,",Cr
Debug "Source File: CB210_diff_version_017 of 18 Feb 2013.",Cr,Cr
'
CONTINUE:                           ' entry point to 60 second endless loop
Out 30,1                                  ' enable 3 second looping run indicator LED(CB210 board)
Wait 3000                           ' for manual test, depress push button when LED "ON",
Out 30,0                                  ' and withdraw when LED goes "OFF"
'
' Manual test of proper pump operation [useful for checking for syphon loss or leaks]
'
KEYPRESS = Keyin(10,10) ' check status of push button
If KEYPRESS = 0 Then          ' if pushed, cycle pump states
      Select Case INDEX2
                  Case 0
                        INDEX = 1
                     Debug "Push Button Depressed: Engaging Main Pump",Cr
                  Case 1
                        INDEX = 2
                        Debug "Push Button Depressed: Engaging Both Pumps",Cr
                  Case 2
                        INDEX = 0
                        Debug "Push Button Depressed: Disabling Both Pumps",Cr
      End Select
      INDEX2 = INDEX
      Goto ACTIVATION         ' manual activation of pumps
End If                                    ' otherwise continue down
KEYPRESS = 1                        ' set flag to inactive
'
' power up the thermistor sensors so they can be read
'
Out 13, 0                           ' enable thermistor via LM317 & VN10K FET (active low)
Wait 600                                  ' wait 0.6 second for voltage pulse to stabilize
'
' input the average of ten analog voltage samples from storage tank thermistor
AIN1 = Tadin(1)
If (AIN1 > 901 Or AIN1 < 168) Then
Debug "Storage Temp. Out of Range, check wiring: ",Dec AIN1, Cr
End If
AIN = AIN1
Debug "tank sense raw: ",Dec AIN,", "
Gosub CONV_TO_C                     ' convert storage reading to Celsius
TEMPS = TEMP                              '
Debug "tank sense: ",Fp(TEMPS,3,2)," deg. C.",Cr
'
' input the average of ten analog voltage samples from solar collector thermistor
'
AIN0 = Tadin(0)
If (AIN0 > 1022 Or AIN0 < 140) Then
Debug "Collector Temp. Out of Range, check wiring: ",Dec AIN0, Cr
End If
AIN = AIN0
Debug "coll sense raw: ",Dec AIN,", "
Gosub CONV_TO_C                           ' convert collector reading to Celsius
Debug "coll sense: ",Fp(TEMP,3,2)," deg. C.",Cr,Cr
TEMPC0 = TEMP - OFFSET_T0(0)  ' collector must be warmer by 2.222 deg.C
                                                            '   due to line losses
TEMPC1 = TEMP - OFFSET_T1(0)  ' collector must be warmer by 3.333 deg.C
                                                            '   to justify using secondary pump too!
'                                        
Out 13, 1                                       ' disable power to thermistor via VN10K FET-3 to
                                                            ' reduce error causing heating effect on thermistors
'
If (TEMPC0 > 75 Or TEMPS > 65) Then
      ' turn both pumps on to either keep collector from overheating beyond
      ' 75 deg. C. due to stagnation or to eventually cool the overly hot
      ' storage tank down to 65 deg.C
      Debug "Caution: Overheating!! Pumps ON!!",Cr
      INDEX = 2
      Else
            If TEMPC1 > TEMPS Then
                  ' flag need for both pumps
                  INDEX = 2
            Else
                  If TEMPC0 > TEMPS Then
                  ' flag need for pump1 (main pump)
                  INDEX = 1
                  Else
                  ' flag need to turm off pumps
                  INDEX = 0
                  End If
            End If
End If
'
ACTIVATION:
Select Case INDEX
                  Case 0
                              Out 11,0          ' turn off main pump "1"
                              Wait 25           ' short wait to stabilize EMF transient
                              Out 12,0          ' turn off secondary pump"2"
                  Case 1
                              Out 11,1          ' turn on main pump "1"
                  Case 2
                              Out 11,1          ' turn on main pump "1"
                              Wait 25           ' short wait to stabilize EMF transient
                              Out 12,1          ' turn on secondary pump "2"
End Select
Wait 25                                         ' short wait to stabilize EMF transient                    
'
Wait 56330                                ' main loop wait of a little over 56 seconds
                                                      ' (thus approx. 60 second total loop time)
'
Goto CONTINUE                             ' endless loop around for another temperature comparison
'
' subroutine to convert AIN an integer A to D reading, to a Celsius float
'
CONV_TO_C:
' select appropriate slope m and offset b parameters
      If AIN <= VAINP(0) Then
            INDEX = 0
      Elseif AIN <= VAINP(1) Then
            INDEX = 1
      Elseif AIN <= VAINP(2) Then
            INDEX = 2
      Elseif AIN <= VAINP(3) Then
            INDEX = 3
      Elseif AIN <= VAINP(4) Then
            INDEX = 4
      Elseif AIN <= VAINP(5) Then
            INDEX = 5
      Else
            INDEX = 6
      End If
'
' grab the appropriate slope and offset
      M = SLOPE_M(INDEX)
      B = OFFSET_B(INDEX)
'
' convert a 10 bit A to D reading (single) to degrees Celsius (single)
      TEMP = (AIN * ATOVD(0) * M) + B     ' convert reading to Celsius
      Return
'
' Copyright Gord Scale, Adolphustown Schoolhouse, February 2013.
' Permission is granted for non-commercial use by individuals implementing a
' Khanh master/slave and other variants of builditsolar.com "$1k Domestic Hot"
' Water Systems.  Use at Own Risk.  There are no warranties of any type.