Hot tubs on the cheap!

One of my guys at work (Parkway Brewing) told me his neighbor had a hot tub that he wanted $50 for. How it the heck can you pass that kind of offer up? He said the pump did not work.

Me being the cheap bastard that I am (thanks Dad!) figured a new pump can’t be that expensive so off we went to pick this thing up. Turns out to be a SofTub Resort 300 (an older one but still). The price on this thing is outrageous.

We brought it home and I tore it apart to check the motor. Turns out the motor works just fine! Problem is the controller is shot. Some quick searching puts the cost way out of what I am willing to spend. Never mind that MrsProbrwr has told me the hot tub is REQUIRED!

Being the technically oriented and inquisitive person I am, I start looking into building my own controller. I make beer. I have made all kinds of temperature controllers in the past. But I wanted something more “cool” Enter the Arduino!

Now, mind you I have not programmed anything since high school and that was Apple and TRS Basic (I am old). So off I go on my favorite shopping site and I order a couple Arduino Starter kits. (here and here) because, you know, more than one is good!

On that note, This is truly a catch up post as the current version uses an Arduino Pro Micro but the original was developed and built with and Arduino UNO.

Programming is actually pretty easy and I was somewhat familiar with the interfaces from my 3d Printer builds. The following is the code I wrote to run the tub. It allows for the two speed pump and temperature control. Also turns the light on!

/* Hot Tub Control program for our Softub using a single 2 speed
    pump and passive heating of the water.
*/
// Define pins and variables
int recircpumppin = 4;
int jetpumppin = 5;
int lightspin = 7
;
int jetSW = 21;
int lightSW = 20;
int buttonUp = 19; //initialize pin for Up Button
int buttonDown = 18; //initialize pin for down button
int Jet;
int Light;
int TempUP;
int TempDN;
int Recirc_state = HIGH;
int Light_state;      // the current state of the output pin
int Light_reading;           // the current reading from the input pin
int Light_previous;    // the previous reading from the input pin
int Jet_state = LOW;
int Jet_reading;
int Jet_previous = LOW;
int curTemp;
int setTemp;

#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2);
// Data wire is plugged into port 6 on the Arduino
#define ONE_WIRE_BUS 6

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0;         // the last time the output pin was toggled
long debounce = 150;   // the debounce time, increase if the output flickers

void setup()
{
  //  Serial.begin(9600);      // open the serial port at 9600 bps

  pinMode(recircpumppin, OUTPUT);
  pinMode(jetpumppin, OUTPUT);
  pinMode(lightspin, OUTPUT);
  pinMode(jetSW, INPUT);
  pinMode(lightSW, INPUT);
  digitalWrite(recircpumppin, HIGH);
  digitalWrite(jetpumppin, LOW);
  digitalWrite(lightspin, LOW);
  //Start LCD
  lcd.init();
  lcd.backlight();
  lcd.print("RocketHound");
  lcd.setCursor(0, 1);
  lcd.print("Hot Tub Control");
  delay(5000);
  lcd.clear();

  //Set Variables
  setTemp = 100;


  // Start up the library
  sensors.begin();
}

void loop()
{
  // Read pins for buttons:
  Jet = digitalRead(jetSW);
  Light = digitalRead(lightSW);
  if (Light == HIGH)Light_Change();
  if (Jet == HIGH)Jet_ON();
  TempRead();

  /* Check to see if temperature is overheated and turn off pumps if so
   *  
   */
  if (curTemp > 104){
    digitalWrite(recircpumppin, LOW);
    digitalWrite(jetpumppin, LOW);
  }

  /* Adjust Set temperature buy pressing up and down buttons
      buttons are on two separate pins
  */
  // Increase target temp
  TempUP = digitalRead(buttonUp);
  if (TempUP == HIGH) {
    setTemp = setTemp + 1;    // If button is pushed, move Target Temp up by 1
  } else {
  }

  // Decrease target temp
  TempDN = digitalRead(buttonDown);
  if (TempDN == HIGH) {
    setTemp = setTemp - 1;   // If button is pushed, move Target Temp down by 1
  } else {
  }

  // Write recirc state based on temperature

  if (curTemp > setTemp && Jet_state == LOW)  {
    digitalWrite(recircpumppin, LOW);
  } else {
  }
  if (curTemp < setTemp && Jet_state == LOW)  {
    digitalWrite(recircpumppin, HIGH);
  } else {
  }
  /*  Serial.print(Jet);
    Serial.print("\t");
    Serial.print(Light);
    Serial.print("\t");
    Serial.print(TempUP);
    Serial.print("\t");
    Serial.print(TempDN);
    Serial.print("\t");
    Serial.print(Light_state);
    Serial.print("\t");
    Serial.println(setTemp);
  */

    delay(0);
  
}
void Jet_ON()  //turn on Jet mode and disable recirc mode
{
  Jet_reading = Jet;

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (Jet_reading == HIGH /*&& Jet_previous == LOW */ && millis() - time > debounce) {
    if (Jet_state == HIGH)
      Jet_state = LOW;
    else
      Jet_state = HIGH;

    if (Jet_state == LOW)
      Recirc_state = HIGH;
    else
      Recirc_state = LOW;
    time = millis();
  }


  digitalWrite(jetpumppin, Jet_state);
  digitalWrite(recircpumppin, Recirc_state);

  //  previous = state;
}
//  Jets_OFF();

void Light_Change()   //Turn off the lights
{
  Light_reading = Light;

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (Light_reading == HIGH && Light_previous == LOW && millis() - time > debounce) {
    if (Light_state == HIGH)
      Light_state = LOW;
    else
      Light_state = HIGH;

    time = millis();
  }

  digitalWrite(lightspin, Light_state);

  //  previous = state;                                         
}

void TempRead()
{
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  // Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures

  curTemp = sensors.getTempFByIndex(0);

  //Print to LCD
  lcd.clear();
  lcd.print("Set Temp: ");
  lcd.print(setTemp);
  lcd.write(0xDF);
  lcd.print("F");
  lcd.setCursor(0, 1);
  lcd.print("Water Temp: ");
  lcd.print(curTemp);
  lcd.write(0xDF);
  lcd.print("F");
  delay(10);
}

This is freely given but not even remotely guaranteed!

I learned a few things. The solid state relays that I used say they will run with 3-32VDC but the Arduino just doesn’t put enough out to make that happen. I used some Mosfet’s to switch 12VDC to run the SSR’s and the LED lights. The 12VDC is stepped down to 5V on the custom circuit board I built to run the logic side of the board.

I picked up some parts from Amazon (Here, Here, Here, Here, and Here Plus some more… ) and built it all into this:

After all of it I may be $300 into it now. But… I also learned a lot about programming and I can use that in other projects in the future!

Leave a Reply