Guidance on Arduino-controlled fermentation chamber

I'm putting together a fermentation chamber (made from a chest freezer) for home brewing, and I'll be adding an Arduino to monitor and control the temperature. I'm fronting the Arduino with a Raspberry Pi, not unlike the BrewPi system, just simpler. Currently, my plan of attack is to set a timer interrupt that triggers every 1 or 5 minutes to sample and report the temperature (from a DS18B20 sensor), and the main loop will wait for input from the serial interface for commands such as "set temp 60". Since the sampling will be done far more often than sending commands, it seems like I should have the interrupt processor trigger on serial input, not the timer, but everything I'm reading suggests that using an ISR for reading serial data is a Bad Idea(r)(tm).

Can anyone provide some input on what I'm planning, and any other (possibly better) ways I could go about it?

jwbernin:
Since the sampling will be done far more often than sending commands, it seems like I should have the interrupt processor trigger on serial input,

Strange idea. All serial input is stored in an serial input buffer by the Arduino core library. The core library uses interrupts to do so. You than can retrieve the serial input by "Serial.read()" at any time without any additional interrupt programming.

jwbernin:
not the timer,

Timer? Strange idea. The Arduino core library uses Timer0 to provide some timing functions for you like millis() or micros(). That's all you need.

jwbernin:
but everything I'm reading suggests that using an ISR for reading serial data is a Bad Idea(r)(tm).

Interrupt programming is used where it is needed, and NOT where things just get more and more complicated when using additional interrupts.

jwbernin:
Can anyone provide some input on what I'm planning, and any other (possibly better) ways I could go about it?

Here is some example framework which provided two "tasks" in the loop():

  • handle_serial_input();
  • send_temperature_samples();

The handle_serial_input() task will handle serial input lines which are ending with a end-of-line character. So if testing with the serial monitor be sure to set either "Carriage Return" or "Both NL&CR" as the line ending option. If a line with three parameters is detected, the input will be seperated at the space characters and printed seperately to serial.

The send_temperature_samples() function will send a fake message once per 5 minutes to serial.

char* serialInput()
{ // reads commands from Serial, return char pointer to command if detected
  static char buf[31];
  int count;
  if (!Serial.available()) return NULL; // no command, return NULL pointer
  delay(31); // small delay ==> wait for all chars of the command to arrive
  memset(buf,0,sizeof(buf)); // clear command buffer
  count=0;  // clear number of chars in the command
  while (Serial.available()) // while there is some Serial input ready
  {
    char c=Serial.read();  // read one char
    if (count<sizeof(buf)-1 && c>=32) // does the char fit in the command buffer?
    {
      buf[count]=c; // Yes, insert char in command buffer
      count++; // count the char
    }
  }  
  return buf; // return pointer to command buffer
}


void handle_serial_input()
{
  char* command= serialInput();  // char pointer pointing to the command buffer
  if (command!=NULL) // command ready
  { 
    char *device= strtok(command," ");
    char *action= strtok(NULL," ");
    char *parameter= strtok(NULL," ");
    Serial.print("RECEIVED: ");
    if (parameter>NULL)
    {
      Serial.print(device);Serial.print(" | ");
      Serial.print(action);Serial.print(" | ");
      Serial.print(parameter);
    }
    else Serial.print(" ERROR");  
    Serial.println();
  }
}


#define SAMPLEINTERVAL 5*60000L  // 5 minutes a 60000 milliseconds
void send_temperature_samples()
{
  static unsigned long lastSampleSent;
  if (millis()-lastSampleSent>=SAMPLEINTERVAL)
  {
    lastSampleSent+=SAMPLEINTERVAL;
    Serial.println("Send temperature sample (FAKE VERSION)");
  }
}



void setup() {
  Serial.begin(9600);
  Serial.println("*** Good night and good luck ***");
  Serial.println();
}

void loop() {
  handle_serial_input();
  send_temperature_samples();
}