// Hi! Barb here: this is a quick and dirty implementation of a refrigeration compressor + evaporator fan(s) controller.
// I wrote this code to run it on an attiny45 that I was able to solder on the back of a 5V relay inside the refrigerator's
// control panel. This code relies on an external thermostat already doing its work and is not meant to manage internal
// temperature. It is written to make sure the compressor can get a minimum rest-time between cycles as to not overheat.
// This relay and attiny are connected in series with the main thermost's relay, so that they only function when it's calling.
// With this in mind, we assume the thermostat has just called for cooling every time the attiny is booted and leave the
// compressor running. After a set period of s (timerMAX) the compressor is switched off.
// In order to aid thermal transfer and maximize COP while using butane as refrigerant, the system needs to have a higher
// average temperature. Due to this reason, a fan is fitted between the fridge and freezer compartments to move air between
// the two. The fan is turned on after fanStartDelay to prevent rapid heating of the freezer and turned back on when the
// timer hits fanStopAdvance to allow for further freezer sub-cooling.

// Last updated: 05/03/24

bool disable = 0;               // bool to store compressor disable status
int timer = 0;                  // active countdown timer, between timerMax and 0
const int timerMAX = 1500;      // (countdown in seconds)
int relayPin = 0;               // compressor relay output pin (active LOW)
int fanPin = 1;                 // fan MOSFET output pin (active HIGH)
const int fanStartDelay = 60;   // fan turn-on delay in seconds
const int fanStopAdvance = 30;  // fan turn-off advance in seconds (before the compressor stops, allows to sub-cool the freezer)

void setup() {
  // put your setup code here, to run once:

  // firstly, we initialize the needed outputs
  pinMode(relayPin, OUTPUT);
  pinMode(fanPin, OUTPUT);
  // then we set them low to keep the compressor on and the fans off at boot
  digitalWrite(relayPin, LOW);
  digitalWrite(fanPin, LOW);
  // lastly, we set the timer at maximum so that the loop starts counting down
  timer = timerMAX;
}

void loop() {
  // put your main code here, to run repeatedly:

  // fan control logic:
  // only enable fans after the compressor has been running for a while
  if (timer == (timerMAX - fanStartDelay) && disable == 0) {
    // enable fan(s) after set delay if the compressor is not disabled
    digitalWrite(fanPin, HIGH);
  }
  else if (timer == fanStopAdvance && disable == 0) {
    // disable when we are about to stop the compressor
    digitalWrite(fanPin, LOW);
  }
  else {
    // do nothing
  }

  // compressor control logic
  if (timer > 0 && disable == 0) {
    // when compressor is active, countdown moves at 1s/cycle
    timer--;
  }
  
  else if (timer > 0 && disable == 1) {
    // when compressor is off, countdown moves at (1/5)s/cycle (5 times faster!)
    timer = timer - 5;
  }
  
  else if (timer == 0) {
    // reset countdown timer to max once 0 is reached
    timer = timerMAX;
    
    // relay control logic: warning! LOW = active!
    if (disable == 0) {
      disable = 1;
      digitalWrite(relayPin, HIGH);
    }
    else if (disable == 1) {
      disable = 0;
      digitalWrite(relayPin, LOW);
    }
  }
  
  else {
    // protect against underflow or bitflip: if no condition applies, reset to safe values
    timer = 0;
    disable = 0;
    digitalWrite(fanPin, LOW);
  }
  
  // now wait 1s so that we can roughly count time using the timer variable
  // this is a stopping delay, kinda bad, but we don't have any inputs, hence it shouldn't matter!
  delay(1000);
}
