Refrigerator freezer thermostat, logging, stats and display

lewisg

Senior Member
This project came out of my frustration with the refrigerator/freezer on my boat. It ran too much which was not only noisy but caused excessive battery drain. It turned out to be a two part problem, frost on the refrigerator evaporator and excessive temperatures in the enclosure were the refrigerator is located. To fix the frost problem I decided to add a heating element to the refrigerator evaporator to make a frost free refrigerator. The second problem could be solved by having fans moving air in and out of the enclosure either all the time or only when the compressor was running without using a controller. TO HECK WITH THAT! We have Picaxe! So if cooler air is available move it using fans.

Originally the project was just a monitor and fan program. When I added defrost I took over the thermostats. The original thermostats are still in place and can be back up and running by moving 4 wires. This sort of redundancy is also why I used separate inputs for the DS18B20 sensors. I can have spares but the reprogramming needed to swap might be a problem while on the water.
Code:
#picaxe 20X2

'refrigerator and freezer control program
'operates as two thermostats to control both the refig and freez compressors
'operates a heater on the refrigerator evaporator for defrosting
'operates a fan inside the refrigerator and another fan to cool the outside of the unit
'keeps statistics, min/max temps and duty cycles
'displays compressor run status, current temps and statistics on a LCD display
'logs date, time, timer, all inputs and more to a SD card


'constants
symbol RCutIn  = 98   '-1 from the desired compressor cut in:   -1C +30F (99 rescale)
symbol RCutOut = 89   '+1 from the desired compressor cut out: -12C +10F (88 rescale)
Symbol FCutIn  = 79   '-1 from the desired compressor cut in:  -20C  -4F (79 rescale)
Symbol FCutOut = 73   '+1 from the desired compressor cut out: -28C -18F (73 rescale)
symbol DefFreq = 50   'number of compressor cycles (with AC on) before defrost
symbol DefTime = 110  'length of defrost cycle, with 10 sec loop 60 = 10 minutes ADD DefFreq to desired time!
symbol LCDbaud = t9600_8
symbol LOGbaud = t9600_8

'general vars
symbol RCtemp  = b0   'refrigerator cabinet temperature sensor value
symbol REtemp  = b1   'refrigerator evaporator temperature sensor value
symbol FCtemp  = b2   'freezer cabinet temperature sensor value
symbol FEtemp  = b3   'freezer evaporator temperature sensor value
symbol HTtemp  = b4   'hold temperature
symbol BTtemp  = b5   'board temperature
symbol RcomR   = b6   'refrigerator compressor on=1 otherwise 0
symbol RDefCnt = b7   'refrigerator defrost counter
symbol FcomR   = b8   'freezer compressor on=1 otherwise 0
symbol AC      = b9   'shore power yes=1 otherwise 0

symbol Rmin    = b10  'refrig min temp
symbol Rmax    = b11  'refrig max temp
symbol Ron     = w6   'uses timer for duty cycle calcs
symbol Roff    = w7   'uses timer for duty cycle calcs
symbol Rduty   = b16  'refrig on time duty cycle

symbol Fmin    = b17  'see above
symbol Fmax    = b18
symbol Fon     = w10
symbol Foff    = w11
symbol FDuty   = b19

'display vars
symbol Tsign = b24    'current temp
symbol Ttens = b25
symbol Tones = b26
symbol Nsign = b27    'min temp
symbol Ntens = b28
symbol Nones = b29
symbol Xsign = b30    'max temp
symbol Xtens = b31
symbol Xones = b32
symbol Dxxxx = b33    'duty cycle, xxxx not displayed, used as a placeholder for bintoascii
symbol Dtens = b34
symbol Dones = b35

'DS1307 variables
symbol secs    = b36
symbol mins    = b37
symbol hour    = b38
symbol day     = b39  'day of week  1-7
symbol date    = b40  'day of month 1-31
symbol month   = b41
symbol year    = b42
symbol control = b43  'only used in sub SetClock, could be molested

'DS1307 display variables
symbol yr10    = b44
symbol yr01    = b45
symbol mo10    = b46
symbol mo01    = b47
symbol dt10    = b48
symbol dt01    = b49
symbol hr10    = b50
symbol hr01    = b51
symbol mn10    = b52
symbol mn01    = b53
symbol sc10    = b54
symbol sc01    = b55
  
'input pins
symbol RCSense = C.0    'DS18B20 in refigerator
symbol RESense = C.1    'DS18B20 on refigerator evaporator
symbol FCSense = C.2    'DS18B20 in freezer
symbol FESense = C.3    'DS18B20 on freezer evaporator
symbol HTSense = C.4    'DS18B20 in hold area (hopefully cooler air)
symbol BTSense = C.5    'DS18B20 on main board
symbol ACpwr   = pinC.6 'detect AC power for defrost cycle
  
'output pins
symbol RComRly = B.0    'relay for refigerator compressor (relay NO)
symbol FComRly = B.1    'relay for freezer compressor (relay NO)
symbol DefrRly = B.2    'relay for defrost (Switched 12VDC)
symbol RefFan  = B.3    'fan inside refrigerator (Switched 12VDC)
symbol LCD     = B.4    'arduino-direct.com LCD 1602 (apparently no longer available)
'i2c sda       = B.5    'DS1307 RTC (Chronodot V2.1)
symbol Logger  = B.6    'Seedstudio SDLogger
'i2c sda       = B.7    'DS1307 RTC
symbol CabFan  = C.7    'cabinet fan, run if cooler air is available (Switched 12VDC)


start:

  high LCD
  pause 5000

  serout LCD, LCDbaud,("$CLEAR",13)
  serout LCD, LCDbaud,("$GO 1 2",13)
  serout LCD, LCDbaud,("$PRINT *BoatThermo9*",13)
  serout LCD, LCDbaud,("$GO 2 3",13)
  serout LCD, LCDbaud,("$PRINT LG 07/05/12",13)

  high Logger
  pause 10000             'wait for logger *WHEW*
  serout Logger, LOGbaud,("*START* BoatThermo9.bas *START*",13,10) 
  serout Logger, LOGbaud,("Date,Time,Timer,RCtemp,REtemp,FCtemp,FEtemp,HTtemp,BTtemp,RcomR,RDefCnt,FcomR,AC",13,10)
  
  high RefFan
  
  'get temps, rescale and set min/max vars
  readtemp RCSense, RCtemp
  if RCTemp < 127 then
    RCTemp = RCTemp + 100
  else
    RCTemp = 128 - RCTemp + 100
  end if
  Rmin = RCtemp
  Rmax = RCtemp
  readtemp FCSense, FCtemp
  if FCTemp < 127 then
    FCTemp = FCTemp + 100
  else
    FCTemp = 128 - FCTemp + 100
  end if
  Fmin = FCtemp
  Fmax = FCtemp 
  
  i2cslave %11010000, i2cslow, i2cbyte              'set DS1307 slave address
' gosub SetClock                                    'uncomment to set RTC, set vars in sub

  settimer t1s_8

main:

  readi2c 0,(secs,mins,hour,day,date,month,year)
  
  bcdtoascii year,yr10,yr01
  bcdtoascii month,mo10,mo01
  bcdtoascii date,dt10,dt01
  bcdtoascii hour,hr10,hr01
  bcdtoascii mins,mn10,mn01
  bcdtoascii secs,sc10,sc01

  readtemp RCSense, RCtemp
  readtemp RESense, REtemp
  readtemp FCSense, FCtemp
  readtemp FESense, FEtemp
  readtemp HTSense, HTtemp
  readtemp BTSense, BTtemp
  
  if HTtemp < BTtemp then   'get cooler air if available
    high CabFan
  else
    low CabFan
  end if
  
  AC = ACpwr                'shore power? 1 if yes

  serout Logger, LOGbaud,(mo10,mo01,"/",dt10,dt01,"/",yr10,yr01,",",hr10,hr01,":",mn10,mn01,":",sc10,sc01,",")
  serout Logger, LOGbaud,(#timer, ",")
  serout Logger, LOGbaud,(#RCTemp,",",#RETemp,",",#FCtemp,",",#FEtemp,",",#HTtemp,",",#BTtemp,"," ,#RcomR,",",#RDefCnt,",",#FcomR,",",#AC,13,10)
  
  sertxd("RC: ",#RCTemp," RE: ",#RETemp," RRun: ",#RcomR," RDefCnt: ",#RDefCnt," * FC: ",#FCTemp," FE: ",#FETemp," FRun: ",#FcomR," AC: ",#AC,13,10)  
' sertxd("A RC: ",#RCTemp," Rmin: ",#Rmin," Rmax: ",#Rmax," * FC: ",#FCTemp," Fmin: ",#Fmin," Fmax: ",#Fmax,13,10)

  'rescale temps to get linear integer set across zero degrees C
  'after rescale 10C=110 -10C=90
  if RCTemp < 127 then          'refrig cabinet
    RCTemp = RCTemp + 100
  else
    RCTemp = 128 - RCTemp + 100
  end if
  if RETemp < 127 then          'refrig evaporator
    RETemp = RETemp + 100
  else
    RETemp = 128 - RETemp + 100
  end if  
  if FCTemp < 127 then          'freezer cabinet
    FCTemp = FCTemp + 100
  else
    FCTemp = 128 - FCTemp + 100
  end if    
  if FETemp < 127 then          'freezer evaporator
    FETemp = FETemp + 100
  else
    FETemp = 128 - FETemp + 100
  end if    

  gosub RDisplay                'update the refrigerator line on the LCD
  gosub FDisplay                'update the freezer line on the LCD
  
  if RDefCnt < DefFreq then     'operate the refrigerator compressor
    if RETemp > RCutIn then
      if RcomR = 0 then         'runs once at start of refrig compressor cycle
        if AC = 1 then
          RDefCnt = RDefCnt + 1 'increment defrost counter
        end if
        Roff = timer - Roff     'duty cycle calcs
        if Ron > 0 then
          Roff = Ron + Roff
          Ron = Ron * 100
          Rduty = Ron / Roff
        end if
        Ron = timer
      end if
      if RDefCnt < DefFreq then 'prevent short cycle!
        high RComRly            'turn on compressor
        RcomR = 1
      end if
    elseif RETemp < RCutOut then
      low RComRly
      if RcomR = 1 then         'runs once at end of refrig compressor cycle
        Ron = timer - Ron       'set duty cycle vars
        Roff = timer      
      end if
      RcomR = 0 
    end if
  else                          'defrost
    low RComRly                 'be SURE compressor and refrigerator internal fan are off
    RcomR = 0   
    low RefFan  
    if REtemp < 101 then        'run heater until 1 degree above freezing
      high DefrRly
    else
      low DefrRly 
    end if
    RDefCnt = RDefCnt + 1       'use counter as a timer
    if RDefCnt > DefTime then
      RDefCnt = 0
      high RefFan
    end if
  end if  
  
  if FETemp > FCutIn then       'operate the freezer compressor
    high FComRly
    if FcomR = 0 then           'runs once at start of freezer compressor cycle               
      Foff = timer - Foff       'duty cycle calcs
      if Fon > 0 then
        Foff = Fon + Foff
        Fon = Fon * 100
        Fduty = Fon / Foff
      end if
      Fon = timer   
    end if
    FcomR = 1
  elseif FETemp < FCutOut then
    low FComRly
    if FcomR = 1 then           'runs once at end of freezer compressor cycle
      Fon = timer - Fon
      Foff = timer
    end if
    low FComRly
    FcomR = 0
  end if

  pause 9000                    '10 sec total loop time
  
goto main
'*** CONTINUED NEXT POST ***
Sub procedures are in next post
 
Last edited:

lewisg

Senior Member
More refrig/freez

IMG_8192.jpgIMG_8169.jpg

The first photo shows the refrigerator compressor running with a current temp of 35, minimum of 33, maximum of 42 and a duty cycle of 46%. The second line shows the freezer compressor isn't running with a current temp of 0, minimum temp of -3, maximum of 5 and a duty cycle of 60%. In normal use the programming plug would be removed.

The second photo shows the inside of the display box. The SD card is inserted through a slot in the box and sits flush with the plastic. If you didn't know it was there you wouldn't see it. Ribbon cable and .1" header connectors are a favorite of mine. With a little heat shrink the make nice single conductor attachments. The ribbon cable is secured with a good sized piece of double stick foam tape which is barely visible in the photo.

Sorry there is no schematic. With Picaxe it is so easy for me to build straight to board so none exist. All the interfacing circuits are right out of the very excellent manuals 1,2&3.

The subs:
Code:
'*** CONTINUED FROM LAST POST ***
RDisplay:

  'if new refrigerator temp < min stored, save new Rmin
  if RCtemp < Rmin then
    Rmin = RCtemp
  end if
  
  'if new refrigerator temp > max stored, save new Rmax
  if RCtemp > Rmax then
    Rmax = RCtemp
  end if  

  'convert refigerator temperatures to ascii digits
   ptr = 0
  @ptr = RCtemp
  gosub RescaledDS18B20toF
  ptr = 1
  Tsign = @ptr
  ptr = 0
  bintoascii @ptr, Dxxxx, Ttens, Tones    'Dxxxx is a placeholder, no hundreds needed

   ptr = 0
  @ptr = Rmin
  gosub RescaledDS18B20toF
  ptr = 1
  Nsign = @ptr
  ptr = 0
  bintoascii @ptr, Dxxxx, Ntens, Nones

   ptr = 0
  @ptr = Rmax
  gosub RescaledDS18B20toF
  ptr = 1
  Xsign = @ptr
  ptr = 0
  bintoascii @ptr, Dxxxx, Xtens, Xones
  
  'convert refrigerator duty cycle to ascii     
  bintoascii Rduty, Dxxxx, Dtens, Dones
    
  'display refrigerator stats
  if RcomR = 1 then
    serout LCD, LCDbaud,("$GO 1 1",13)
    serout LCD, LCDbaud,("$PRINT R",Tsign, Ttens, Tones," ",NSign, Ntens, Nones,"~",XSign, Xtens, Xones," ",Dtens, Dones,"%",13)
'   serout Logger, LOGbaud,("R",Tsign, Ttens, Tones,"C ",NSign, Ntens, Nones,"~",XSign, Xtens, Xones," ",Dtens, Dones,"%")   
  else
    serout LCD, LCDbaud,("$GO 1 1",13)
    serout LCD, LCDbaud,("$PRINT .",Tsign, Ttens, Tones," ",NSign, Ntens, Nones,"~",XSign, Xtens, Xones," ",Dtens, Dones,"%",13)
'   serout Logger, LOGbaud,(" ",Tsign, Ttens, Tones,"C ",NSign, Ntens, Nones,"~",XSign, Xtens, Xones," ",Dtens, Dones,"%")   
  end if
  
return


FDisplay:

  'if new freezer temp < min stored, save new Fmin
  if FCtemp < Fmin then
    Fmin = FCtemp
  end if
  
  'if new freezer temp > max stored, save new Fmax
  if FCtemp > Fmax then
    Fmax = FCtemp
  end if  

  'convert freezer temperatures to ascii digits
   ptr = 0
  @ptr = FCtemp
  gosub RescaledDS18B20toF
  ptr = 1
  Tsign = @ptr
  ptr = 0
  bintoascii @ptr, Dxxxx, Ttens, Tones    'Dxxxx is a placeholder, no hundreds needed

   ptr = 0
  @ptr = Fmin
  gosub RescaledDS18B20toF
  ptr = 1
  Nsign = @ptr
  ptr = 0
  bintoascii @ptr, Dxxxx, Ntens, Nones

   ptr = 0
  @ptr = Fmax
  gosub RescaledDS18B20toF
  ptr = 1
  Xsign = @ptr
  ptr = 0
  bintoascii @ptr, Dxxxx, Xtens, Xones
    
  'convert freezer duty cycle to ascii
  bintoascii Fduty, Dxxxx, Dtens, Dones

  'display freezer stats
  if FcomR = 1 then
    serout LCD, LCDbaud,("$GO 2 1",13)
    serout LCD, LCDbaud,("$PRINT F",Tsign, Ttens, Tones," ",NSign, Ntens, Nones,"~",XSign, Xtens, Xones," ",Dtens, Dones,"%",13)
'   serout Logger, LOGbaud,(" F",Tsign, Ttens, Tones,"C ",NSign, Ntens, Nones,"~",XSign, Xtens, Xones," ",Dtens, Dones,"%",13,10)  
  else
    serout LCD, LCDbaud,("$GO 2 1",13)
    serout LCD, LCDbaud,("$PRINT .",Tsign, Ttens, Tones," ",NSign, Ntens, Nones,"~",XSign, Xtens, Xones," ",Dtens, Dones,"%",13)
'   serout Logger, LOGbaud,("  ",Tsign, Ttens, Tones,"C ",NSign, Ntens, Nones,"~",XSign, Xtens, Xones," ",Dtens, Dones,"%",13,10)  
  end if

return


RescaledDS18B20toF:

  if @ptr = 82 then       '0F
    ptr = 1
    @ptr = " "
    ptr = 0 
    @ptr = 0
  else if @ptr < 82 then  'below 0F
    ptr = 1 
    @ptr = "-"
    ptr = 0
    @ptr = @ptr * 9 / 5
    @ptr = 148 - @ptr 
  else                    'above 0F
    ptr = 1 
    @ptr = "+"
    ptr = 0
    @ptr = @ptr * 9 / 5
    @ptr = @ptr - 148
  endif

Return


RescaledDS18B20toC:

  if @ptr = 100 then      '0C
    ptr = 1
    @ptr = " "
    ptr = 0 
    @ptr = 0
  else if @ptr < 100 then 'below 0C
    ptr = 1 
    @ptr = "-"
    ptr = 0
    @ptr = 100 - @ptr 
  else                    'above 0C
    ptr = 1 
    @ptr = "+"
    ptr = 0
    @ptr = @ptr - 100
  endif


Return


SetClock:
  'day is day of week Sun=1, Mon=2...
  'download program 70 sec before desired time
  day     = $04
  year    = $13
  month   = $06
  date    = $19
  hour    = $02
  mins    = $35
  secs    = $00
  control = %00010000 ; Enable output at 1Hz
  writei2c 0,(secs,mins,hour,day,date,month,year,control)
return
The display can operate in either F or C by just changing the last character in all instances of gosub RescaledDS18B20toF from F to C. Both subs are included.

Info on how I rescaled the temps can be found here: DS18B20 and crossing zero
 
Last edited:

lewisg

Senior Member
Board pix

Since there is no schematic here are board pix. NB - the heatsink on the regulator wasn't installed in the pix. You will need one!
IMG_8164.jpgIMG_8165.jpg

The Chronodot is removed so you can see the AC detect relay.
 
Top