0

Sous Vide window question
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Sous Vide window question

by adum on Thu Dec 12, 2013 3:16 pm

The default window in the example source code is 10 seconds. So the relay will change twice every ten seconds, most of the time. That means 720 switches per hour. The Powerswitch tail 2 is only rated for 100k switches before it breaks. So after 140 hours, it will stop. Given that some recipes for sous vide take a good 50 hours of cooking, I'm thinking I'll have to get a new switch every three meals!

So, my question is: has anyone tried longer window values with any success? I'm cooking with a big slow cooker, which responds very slowly, obviously. I'm thinking it might be hard to tune the PID with bigger windows. (My autotune pretty much failed even with the current window, giving values of kP400, kI1.5, and kD0, which oscillates). I would think that ideally, a window of a minute should be able to sustain a steady temp. Or maybe the 100k switches doesn't really break the relay in typical use?

Thanks!
adum
 
Posts: 3
Joined: Thu Dec 12, 2013 2:01 pm

Re: Sous Vide window question

by adafruit on Thu Dec 12, 2013 5:07 pm

in use, the 'thermal mass' of the hot pot is so large that it only turns on and off right as it first hits the heating point, then it only clicks on and off maybe once every 5-10 minutes. You can update the project to an SSR or buy a commercial off-the-shelf solution if you are going to be using it a lot and the switching concerns you

adafruit
 
Posts: 12149
Joined: Thu Apr 06, 2006 4:21 pm
Location: nyc

Re: Sous Vide window question

by adafruit_support_bill on Thu Dec 12, 2013 6:23 pm

The current 10-second window works well for several models of rice cooker tested. I have done many hundred hours of cooking with the prototype from the tutorial. Slow-cookers and crock-pots have more thermal mass and might do well with a longer TPO window. But as noted by Adafruit, once pre-heated, the heating phases tend to be fairly short. Since there is no active cooling, and most cookers are reasonably well insulated, the passive cooling phase takes longer than the active heating phase.

SSRs are a good option to eliminate the clicking and contact life issues. But that involves working directly with 120V AC and is beyond the comfort & safety zone for many of our customers.

adafruit_support_bill
 
Posts: 70488
Joined: Sat Feb 07, 2009 10:11 am

Re: Sous Vide window question

by adum on Fri Dec 13, 2013 2:04 pm

Thanks very much for your replies. I'm almost completely new to electronics, so I'm pretty sure that SSRs would be a bad choice for me!

I think what I'm seeing is that my controller hasn't entered the "passive cooling" phase yet. Looking at the code, the relay is guaranteed to turn on every ten seconds as long as onTime is more than 1%. What I'm inferring from your comments, and correct me please if I'm wrong, is that with a correctly tuned PID, there should be relatively long periods of onTime being under 1%.

My problem is therefore my tuning. What I'm seeing is that the temp is almost always slightly under the setpoint. I'll keep working on my tuning until I can get it heating a little higher. So far I've tried three tunings:
Default: 850, 0.5, 0.1
Autotuned: 400, 2.3, 0.0
Fuceye's settings: 1603, 0.30, 0.1 (he has almost the same cooker as me: viewtopic.php?f=22&t=42245&p=232037&hilit=sous#p232037)

The default actually worked best. Anyway, I'll keep trying new values until I get something that works. Thanks for pointers.
adum
 
Posts: 3
Joined: Thu Dec 12, 2013 2:01 pm

Re: Sous Vide window question

by adafruit_support_bill on Fri Dec 13, 2013 2:12 pm

What I'm seeing is that the temp is almost always slightly under the setpoint.

That is typical for a strictly "proportional" controller (That's the 'P' in PID). To correct the offset, you can bump up the integral (Ki) a little bit.

One problem with increasing the integral is that you will get more overshoot at startup. The current version I am running has a preheat phase that doesn't let the integral term build up while coming up to temperature. It has been working pretty well for me so far. If you want to give it a try, let me know how it goes:

Code: Select all | TOGGLE FULL SIZE
//-------------------------------------------------------------------
//
// Sous Vide Controller
// Bill Earl - for Adafruit Industries
//
// Based on the Arduino PID and PID AutoTune Libraries
// by Brett Beauregard
//------------------------------------------------------------------

// PID Library
#include <PID_v1.h>
#include <PID_AutoTune_v0.h>

// Libraries for the Adafruit RGB/LCD Shield
#include <Wire.h>
#include <Adafruit_MCP23017.h>
#include <Adafruit_RGBLCDShield.h>

// Libraries for the DS18B20 Temperature Sensor
#include <OneWire.h>
#include <DallasTemperature.h>

// So we can save and retrieve settings
#include <EEPROM.h>

// ************************************************
// Pin definitions
// ************************************************

// Output Relay
#define RelayPin 7

// One-Wire Temperature Sensor
// (Use GPIO pins for power/ground to simplify the wiring)
#define ONE_WIRE_BUS 2
#define ONE_WIRE_PWR 3
#define ONE_WIRE_GND 4

// ************************************************
// PID Variables and constants
// ************************************************

//Define Variables we'll be connecting to
double Setpoint;
double Input;
double Output;

volatile long onTime = 0;

// pid tuning parameters
double Kp;
double Ki;
double Kd;

// EEPROM addresses for persisted data
const int SpAddress = 0;
const int KpAddress = 8;
const int KiAddress = 16;
const int KdAddress = 24;

//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);

// 10 second Time Proportional Output window
int WindowSize = 10000;
unsigned long windowStartTime;

// ************************************************
// Auto Tune Variables and constants
// ************************************************
byte ATuneModeRemember=2;

double aTuneStep=500;
double aTuneNoise=1;
unsigned int aTuneLookBack=20;

boolean tuning = false;
boolean preheat = false;

PID_ATune aTune(&Input, &Output);

// ************************************************
// DiSplay Variables and constants
// ************************************************

Adafruit_RGBLCDShield lcd = Adafruit_RGBLCDShield();
// These #defines make it easy to set the backlight color
#define RED 0x1
#define YELLOW 0x3
#define GREEN 0x2
#define TEAL 0x6
#define BLUE 0x4
#define VIOLET 0x5
#define WHITE 0x7

#define BUTTON_SHIFT BUTTON_SELECT

unsigned long lastInput = 0; // last button press

byte degree[8] = // define the degree symbol
{
 B00110,
 B01001,
 B01001,
 B00110,
 B00000,
 B00000,
 B00000,
 B00000
};

const int logInterval = 10000; // log every 10 seconds
long lastLogTime = 0;

// ************************************************
// States for state machine
// ************************************************
enum operatingState { OFF = 0, SETP, RUN, TUNE_P, TUNE_I, TUNE_D, AUTO};
operatingState opState = OFF;

// ************************************************
// Sensor Variables and constants
// Data wire is plugged into port 2 on the Arduino

// 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);

// arrays to hold device address
DeviceAddress tempSensor;

// ************************************************
// Setup and diSplay initial screen
// ************************************************
void setup()
{
   Serial.begin(9600);

   // Initialize Relay Control:

   pinMode(RelayPin, OUTPUT);    // Output mode to drive relay
   digitalWrite(RelayPin, LOW);  // make sure it is off to start

   // Set up Ground & Power for the sensor from GPIO pins

   pinMode(ONE_WIRE_GND, OUTPUT);
   digitalWrite(ONE_WIRE_GND, LOW);

   pinMode(ONE_WIRE_PWR, OUTPUT);
   digitalWrite(ONE_WIRE_PWR, HIGH);

   // Initialize LCD DiSplay

   lcd.begin(16, 2);
   lcd.createChar(1, degree); // create degree symbol from the binary
   
   lcd.setBacklight(VIOLET);
   lcd.print(F("    Adafruit"));
   lcd.setCursor(0, 1);
   lcd.print(F("   Sous Vide!"));

   // Start up the DS18B20 One Wire Temperature Sensor

   sensors.begin();
   if (!sensors.getAddress(tempSensor, 0))
   {
      lcd.setCursor(0, 1);
      lcd.print(F("Sensor Error"));
   }
   sensors.setResolution(tempSensor, 12);
   sensors.setWaitForConversion(false);

   delay(3000);  // Splash screen

   // Initialize the PID and related variables
   LoadParameters();
   myPID.SetTunings(Kp,Ki,Kd);

   myPID.SetSampleTime(1000);
   myPID.SetOutputLimits(0, WindowSize);

  // Run timer2 interrupt every 15 ms
  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;

  //Timer2 Overflow Interrupt Enable
  TIMSK2 |= 1<<TOIE2;
}

// ************************************************
// Timer Interrupt Handler
// ************************************************
SIGNAL(TIMER2_OVF_vect)
{
  if (opState == OFF)
  {
    digitalWrite(RelayPin, LOW);  // make sure relay is off
  }
  else
  {
    DriveOutput();
  }
}

// ************************************************
// Main Control Loop
//
// All state changes pass through here
// ************************************************
void loop()
{
   // wait for button release before changing state
   while(ReadButtons() != 0) {}

   lcd.clear();

   switch (opState)
   {
   case OFF:
      Off();
      break;
   case SETP:
      Adjust_Sp();
      break;
    case RUN:
      Run();
      break;
   case TUNE_P:
      TuneP();
      break;
   case TUNE_I:
      TuneI();
      break;
   case TUNE_D:
      TuneD();
      break;
   }
}

// ************************************************
// Initial State - press RIGHT to start
// ************************************************
void Off()
{
   myPID.SetMode(MANUAL);
   lcd.setBacklight(0);
   digitalWrite(RelayPin, LOW);  // make sure it is off
   lcd.print(F("    Adafruit"));
   lcd.setCursor(0, 1);
   lcd.print(F("   Sous Vide!"));
   uint8_t buttons = 0;
   
   while(!(buttons & (BUTTON_RIGHT)))
   {
      buttons = ReadButtons();
   }
   // Prepare to transition to the RUN state
   sensors.requestTemperatures(); // Start an asynchronous temperature reading

   //turn the PID on
   myPID.SetMode(AUTOMATIC);
   windowStartTime = millis();
   opState = RUN; // start control
}

// ************************************************
// Setpoint Entry State
// UP/DOWN to change setpoint
// RIGHT for tuning parameters
// LEFT for OFF
// SHIFT for 10x tuning
// ************************************************
void Adjust_Sp()
{
   lcd.setBacklight(TEAL);
   lcd.print(F("Set Temperature:"));
   uint8_t buttons = 0;
   while(true)
   {
      buttons = ReadButtons();

      float increment = 0.1;
      if (buttons & BUTTON_SHIFT)
      {
        increment *= 10;
      }
      if (buttons & BUTTON_LEFT)
      {
         opState = RUN;
         return;
      }
      if (buttons & BUTTON_RIGHT)
      {
         opState = TUNE_P;
         return;
      }
      if (buttons & BUTTON_UP)
      {
         Setpoint += increment;
         delay(200);
      }
      if (buttons & BUTTON_DOWN)
      {
         Setpoint -= increment;
         delay(200);
      }
   
      if ((millis() - lastInput) > 3000)  // return to RUN after 3 seconds idle
      {
         opState = RUN;
         return;
      }
      lcd.setCursor(0,1);
      lcd.print(Setpoint);
      lcd.print(" ");
      DoControl();
   }
}

// ************************************************
// Proportional Tuning State
// UP/DOWN to change Kp
// RIGHT for Ki
// LEFT for setpoint
// SHIFT for 10x tuning
// ************************************************
void TuneP()
{
   lcd.setBacklight(TEAL);
   lcd.print(F("Set Kp"));

   uint8_t buttons = 0;
   while(true)
   {
      buttons = ReadButtons();

      float increment = 1.0;
      if (buttons & BUTTON_SHIFT)
      {
        increment *= 10;
      }
      if (buttons & BUTTON_LEFT)
      {
         opState = SETP;
         return;
      }
      if (buttons & BUTTON_RIGHT)
      {
         opState = TUNE_I;
         return;
      }
      if (buttons & BUTTON_UP)
      {
         Kp += increment;
         delay(200);
      }
      if (buttons & BUTTON_DOWN)
      {
         Kp -= increment;
         delay(200);
      }
      if ((millis() - lastInput) > 3000)  // return to RUN after 3 seconds idle
      {
         opState = RUN;
         return;
      }
      lcd.setCursor(0,1);
      lcd.print(Kp);
      lcd.print(" ");
      DoControl();
   }
}

// ************************************************
// Integral Tuning State
// UP/DOWN to change Ki
// RIGHT for Kd
// LEFT for Kp
// SHIFT for 10x tuning
// ************************************************
void TuneI()
{
   lcd.setBacklight(TEAL);
   lcd.print(F("Set Ki"));

   uint8_t buttons = 0;
   while(true)
   {
      buttons = ReadButtons();

      float increment = 0.01;
      if (buttons & BUTTON_SHIFT)
      {
        increment *= 10;
      }
      if (buttons & BUTTON_LEFT)
      {
         opState = TUNE_P;
         return;
      }
      if (buttons & BUTTON_RIGHT)
      {
         opState = TUNE_D;
         return;
      }
      if (buttons & BUTTON_UP)
      {
         Ki += increment;
         delay(200);
      }
      if (buttons & BUTTON_DOWN)
      {
         Ki -= increment;
         delay(200);
      }
      if ((millis() - lastInput) > 3000)  // return to RUN after 3 seconds idle
      {
         opState = RUN;
         return;
      }
      lcd.setCursor(0,1);
      lcd.print(Ki);
      lcd.print(" ");
      DoControl();
   }
}

// ************************************************
// Derivative Tuning State
// UP/DOWN to change Kd
// RIGHT for setpoint
// LEFT for Ki
// SHIFT for 10x tuning
// ************************************************
void TuneD()
{
   lcd.setBacklight(TEAL);
   lcd.print(F("Set Kd"));

   uint8_t buttons = 0;
   while(true)
   {
      buttons = ReadButtons();
      float increment = 0.01;
      if (buttons & BUTTON_SHIFT)
      {
        increment *= 10;
      }
      if (buttons & BUTTON_LEFT)
      {
         opState = TUNE_I;
         return;
      }
      if (buttons & BUTTON_RIGHT)
      {
         opState = RUN;
         return;
      }
      if (buttons & BUTTON_UP)
      {
         Kd += increment;
         delay(200);
      }
      if (buttons & BUTTON_DOWN)
      {
         Kd -= increment;
         delay(200);
      }
      if ((millis() - lastInput) > 3000)  // return to RUN after 3 seconds idle
      {
         opState = RUN;
         return;
      }
      lcd.setCursor(0,1);
      lcd.print(Kd);
      lcd.print(" ");
      DoControl();
   }
}

// ************************************************
// PID COntrol State
// SHIFT and RIGHT for autotune
// RIGHT - Setpoint
// LEFT - OFF
// ************************************************
void Run()
{
   // set up the LCD's number of rows and columns:
   lcd.print(F("Sp: "));
   lcd.print(Setpoint);
   lcd.write(1);
   lcd.print(F("C : "));

   SaveParameters();
   myPID.SetTunings(Kp,Ki,Kd);

   uint8_t buttons = 0;
   while(true)
   {
      setBacklight();  // set backlight based on state

      buttons = ReadButtons();
      if ((buttons & BUTTON_SHIFT)
         && (buttons & BUTTON_RIGHT)
         && (abs(Input - Setpoint) < 0.5))  // Should be at steady-state
      {
         StartAutoTune();
      }
      else if (buttons & BUTTON_RIGHT)
      {
        opState = SETP;
        return;
      }
      else if (buttons & BUTTON_LEFT)
      {
        opState = OFF;
        return;
      }
     
      DoControl();
     
      lcd.setCursor(0,1);
      lcd.print(Input);
      lcd.write(1);
      lcd.print(F("C : "));
     
      float pct = map(Output, 0, WindowSize, 0, 1000);
      lcd.setCursor(10,1);
      lcd.print(F("      "));
      lcd.setCursor(10,1);
      lcd.print(pct/10);
      //lcd.print(Output);
      lcd.print("%");

      lcd.setCursor(15,0);
      if (preheat)
      {
        lcd.print("P");
      }
      else if (tuning)
      {
        lcd.print("T");
      }
      else
      {
        lcd.print(" ");
      }
     
      // periodically log to serial port in csv format
      if (millis() - lastLogTime > logInterval) 
      {
        Serial.print(Input);
        Serial.print(",");
        Serial.println(Output);
      }

      delay(100);
   }
}

// ************************************************
// Execute the control loop
// ************************************************
void DoControl()
{
  // Read the input:
  if (sensors.isConversionAvailable(0))
  {
    Input = sensors.getTempC(tempSensor);
    sensors.requestTemperatures(); // prime the pump for the next one - but don't wait
  }
 
  if (tuning) // run the auto-tuner
  {
     if (aTune.Runtime()) // returns 'true' when done
     {
        FinishAutoTune();
     }
  }
  else // Execute control algorithm
  {
    if (Setpoint - Input > 3)
    {
      preheat = true;            // suppress control until within range
      Output = WindowSize;
    }
    else
    {
      preheat = false;
      myPID.Compute();
    }
  }
 
  // Time Proportional relay state is updated regularly via timer interrupt.
  onTime = Output;
}

// ************************************************
// Called by ISR every 15ms to drive the output
// ************************************************
void DriveOutput()

  long now = millis();
  // Set the output
  // "on time" is proportional to the PID output
  if(now - windowStartTime>WindowSize)
  { //time to shift the Relay Window
     windowStartTime += WindowSize;
  }
  if((onTime > 100) && (onTime > (now - windowStartTime)))
  {
     digitalWrite(RelayPin,HIGH);
  }
  else
  {
     digitalWrite(RelayPin,LOW);
  }
}

// ************************************************
// Set Backlight based on the state of control
// ************************************************
void setBacklight()
{
   if (tuning)
   {
      lcd.setBacklight(VIOLET); // Tuning Mode
   }
   else if (abs(Input - Setpoint) > 1.0) 
   {
      lcd.setBacklight(RED);  // High Alarm - off by more than 1 degree
   }
   else if (abs(Input - Setpoint) > 0.2) 
   {
      lcd.setBacklight(YELLOW);  // Low Alarm - off by more than 0.2 degrees
   }
   else
   {
      lcd.setBacklight(WHITE);  // We're on target!
   }
}

// ************************************************
// Start the Auto-Tuning cycle
// ************************************************

void StartAutoTune()
{
   // REmember the mode we were in
   ATuneModeRemember = myPID.GetMode();

   // set up the auto-tune parameters
   aTune.SetNoiseBand(aTuneNoise);
   aTune.SetOutputStep(aTuneStep);
   aTune.SetLookbackSec((int)aTuneLookBack);
   tuning = true;
}

// ************************************************
// Return to normal control
// ************************************************
void FinishAutoTune()
{
   tuning = false;

   // Extract the auto-tune calculated parameters
   Kp = aTune.GetKp();
   Ki = aTune.GetKi();
   Kd = aTune.GetKd();

   // Re-tune the PID and revert to normal control mode
   myPID.SetTunings(Kp,Ki,Kd);
   myPID.SetMode(ATuneModeRemember);
   
   // Persist any changed parameters to EEPROM
   SaveParameters();
}

// ************************************************
// Check buttons and time-stamp the last press
// ************************************************
uint8_t ReadButtons()
{
  uint8_t buttons = lcd.readButtons();
  if (buttons != 0)
  {
    lastInput = millis();
  }
  return buttons;
}

// ************************************************
// Save any parameter changes to EEPROM
// ************************************************
void SaveParameters()
{
   if (Setpoint != EEPROM_readDouble(SpAddress))
   {
      EEPROM_writeDouble(SpAddress, Setpoint);
   }
   if (Kp != EEPROM_readDouble(KpAddress))
   {
      EEPROM_writeDouble(KpAddress, Kp);
   }
   if (Ki != EEPROM_readDouble(KiAddress))
   {
      EEPROM_writeDouble(KiAddress, Ki);
   }
   if (Kd != EEPROM_readDouble(KdAddress))
   {
      EEPROM_writeDouble(KdAddress, Kd);
   }
}

// ************************************************
// Load parameters from EEPROM
// ************************************************
void LoadParameters()
{
  // Load from EEPROM
   Setpoint = EEPROM_readDouble(SpAddress);
   Kp = EEPROM_readDouble(KpAddress);
   Ki = EEPROM_readDouble(KiAddress);
   Kd = EEPROM_readDouble(KdAddress);
   
   // Use defaults if EEPROM values are invalid
   if (isnan(Setpoint))
   {
     Setpoint = 60;
   }
   if (isnan(Kp))
   {
     Kp = 850;
   }
   if (isnan(Ki))
   {
     Ki = 0.5;
   }
   if (isnan(Kd))
   {
     Kd = 0.1;
   } 
}


// ************************************************
// Write floating point values to EEPROM
// ************************************************
void EEPROM_writeDouble(int address, double value)
{
   byte* p = (byte*)(void*)&value;
   for (int i = 0; i < sizeof(value); i++)
   {
      EEPROM.write(address++, *p++);
   }
}

// ************************************************
// Read floating point values from EEPROM
// ************************************************
double EEPROM_readDouble(int address)
{
   double value = 0.0;
   byte* p = (byte*)(void*)&value;
   for (int i = 0; i < sizeof(value); i++)
   {
      *p++ = EEPROM.read(address++);
   }
   return value;
}

adafruit_support_bill
 
Posts: 70488
Joined: Sat Feb 07, 2009 10:11 am

Re: Sous Vide window question

by adum on Fri Dec 13, 2013 2:52 pm

Oh, yes, I'm already using your preheat version. It's definitely better :) In fact, even your 3 degree preheat window is more than I need for my setup.

I'll try increasing the Ki and seeing what happens -- I suppose that's what the autotune hinted at. Thanks!
adum
 
Posts: 3
Joined: Thu Dec 12, 2013 2:01 pm

Re: Sous Vide window question

by bbm3 on Fri Jul 25, 2014 11:08 pm

Bill,
Your revised preheat code works very well.
I have tested it with a number of different systems and always maintains +/- 0.1 degrees C, typically +/- 0.0 C.
I do not use auto tune.

I suggest your changes be the standard code distributed by Adafruit.

Thanks,
-Bill B

bbm3
 
Posts: 13
Joined: Sun Jul 06, 2008 9:09 pm

Re: Sous Vide window question

by adafruit_support_bill on Sat Jul 26, 2014 5:37 am

Great! Thanks for the feedback. I believe I will do that.

adafruit_support_bill
 
Posts: 70488
Joined: Sat Feb 07, 2009 10:11 am

Re: Sous Vide window question

by lowsecmail on Tue Aug 19, 2014 12:37 pm

Hi Bill,

Thanks for writing such a great bit of code. Very easy to understand and follow, and amazingly formatted. Makes me feel embarrassed in comparison.

A quick hardware related question. You mention in order to effectively use auto-tune, you should bring the unit up to within .5° of Setpoint.

How do you manage that when you're bypassing the unit's temperature control and relying on the PID?

Do you simply let the unit heat up and when you see the actual temperature reading get close, hit the auto-tune buttons?

thanks again for such a great project

lowsecmail
 
Posts: 3
Joined: Tue Aug 19, 2014 12:31 pm

Re: Sous Vide window question

by adafruit_support_bill on Tue Aug 19, 2014 12:49 pm

I let it come up to temp using the default parameters, then invoke the auto-tune. In some cases, if the temp is coming up too rapidly, it might overshoot the setpoint. This seems to be more of an issue with slow-cookers with their additional thermal mass. In this case, you should wait until the temperature settles back down close to the setpoint before invoking the auto-tune.

adafruit_support_bill
 
Posts: 70488
Joined: Sat Feb 07, 2009 10:11 am

Re: Sous Vide window question

by franklin97355 on Tue Aug 19, 2014 3:31 pm

You can also add hot water or cold until the temperature is correct and then use auto tune. That's how I did It as I didn't want to wait for the pot to heat on its own.

franklin97355
 
Posts: 19445
Joined: Mon Apr 21, 2008 2:33 pm
Location: Lacomb, OR.

Re: Sous Vide window question

by lowsecmail on Tue Aug 19, 2014 3:43 pm

Thanks for the advice guys. All very good ideas. I'll give both a shot. I'm actually using the setup for an espresso machine boiler, so I'm hoping to expand on what I learn tuning a crock-pot and applying it to a sealed boiler system.

lowsecmail
 
Posts: 3
Joined: Tue Aug 19, 2014 12:31 pm

Re: Sous Vide window question

by dziustas1 on Mon Nov 24, 2014 5:42 pm

Hi, does anyone tried to change this code using it with MAX6675 or MAX31855 chips and K type thermocouples?

dziustas1
 
Posts: 1
Joined: Mon Nov 24, 2014 5:37 pm

Re: Sous Vide window question

by adafruit_support_bill on Mon Nov 24, 2014 6:02 pm

It should work. Just be careful to insulate the thermocouple. Those thermocouple amps will not work with a grounded junction.

adafruit_support_bill
 
Posts: 70488
Joined: Sat Feb 07, 2009 10:11 am

Re: Sous Vide window question

by ibucky on Sun Dec 07, 2014 11:25 pm

Bill - sorry for being dense, what do you mean by insulate the thermocouple? I just got done building the Sous Vide as a xmas present for my wife and the whole time I'm thinking 'I don't think I need to change much to make this same system work with the K type thermocouples for my BBQ smoker other than connect a Fan instead of the pig tail.' A project I started sometime again and never finished... Anyway - I don't follow what you mean by insulate the thermocouples - you mean the shrink wrap on the ends?

Also am I missing something or is the only way to change the cook temp is to change the setpoint? Can you change the cook temp via the buttons?

Thank you for this tutorial

ibucky
 
Posts: 112
Joined: Wed Jan 11, 2012 10:40 pm

Please be positive and constructive with your questions and comments.