The sous vide user interface allows you to set cooking temperatures and make adjustments to the PID tuning parameters. It is implemented as a simple state machine. Each state implements a user interface 'screen'. State machines are often used in semi-complex microcontroller projects where you want to do a lot of configuring and activities in the correct order.

The shield buttons are used to navigate between the different screens. After a period of inactivity, a timeout returns the system to the "Run" screen to display the current set-point (the temperature we desire) and current temperature of the bath. The states are as shown in the diagram below:
Each state is implemented as a function that is called by the main loop based on the opState variable. To change states, a state function sets opState to the new state and returns to the main loop.

If you're working on a project that has a lot of stuff going on, drawing a state machine can be really useful to keep your head straight!
// ************************************************
// Main Control Loop
//
// All state changes pass through here
// ************************************************
void loop()
{
   // wait for button release before changing state
   while(ReadButtons() != 0) {}

   lcd.clear();

   Serial.println(opState);

   switch (opState)
   {
   case OFF:
      Off();
      break;
   case SETP:
      Tune_Sp();
      break;
    case RUN:
      Run();
      break;
   case TUNE_P:
      TuneP();
      break;
   case TUNE_I:
      TuneI();
      break;
   case TUNE_D:
      TuneD();
      break;
   }
}
Each state function is responsible for updating the display and monitoring button presses. In addition to navigating between screens, buttons presses are also used to modify the control parameters. For example, the Tune Setpoint state uses the UP and DOWN keys to modify the setpoint as shown in the diagram and in the code below.

The 5th button on the shield is used as a 'shift' key. When pressed simultaneously with the UP or DOWN keys, it increments or decrements by 10 instead of just 1. The other tuning screens work the same way.
// ************************************************
// Setpoint Entry State
// UP/DOWN to change setpoint
// RIGHT for tuning parameters
// LEFT for OFF
// SHIFT for 10x tuning
// ************************************************
void Tune_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);
      DoControl();
   }
}

This guide was first published on Jun 10, 2013. It was last updated on Mar 08, 2024.

This page (User Interface) was last updated on May 25, 2013.

Text editor powered by tinymce.