NTC-thermistor incubator with Arduino

Recently, when I stuck with limited lab equipments and decided to produce some for my agricultural post-harvest related research, my eyes fixed with Arduino! This is enough to wake up my old time hobby with electronics (what I really mean was soldering, XD). I never touch them for the past 15 years. I am a total noob in this matter. Arduino recreates a new passion, just like when I learned GNU/Linux some 10 years ago. 

Last year, I purchased an Arduino UNO R3 for the purpose of learning and found this is incredibly simple to deliver solutions in my field. I do not need (and do not want too) to learn assembler or AVR languages in depth, just to produce thermocouple logger for cacao fermentation or to build a small scale DC powered incubator for example.

Arduino UNO (pic. from www.arduino.cc)


HARDWARE SETUP

Enough talking, now I proceed to the core of the article, a tutorial for NTC-thermistor incubator. In this occasion, a “brain” for incubator using negative temperature coefficient thermistor is explained, hopefully clear enough for a beginner like me. The setup is as follow: 
  1. The MCU: ATmega328P-PU chip with Arduino UNO R3 bootloader (howto burning bootloader OR burning bootloader for ATmega328 (without P)  ). 
  2. The probe: 3x  10kΩ NTC thermistors 
  3. The output: a led and a buzzer 
  4. Some electronic parts: 4x 10kΩ±5% and 1x 2.2 kΩ±5% resistors, 1x 100nF and 2x 22pF capacitors, 1x opto-isolated 5v relay module, 1x 16Mhz crystal, and some jumper cables. 
  5. The USB to serial: 1x FTDI 5v basic (that also acts as power source). 
  6. Planned electronic parts: 1x double digits 7-segment display and 2x 74HC595 chips (will be explained later in next part) 
All of these were purchased from local online shops (I live in Indonesia), i.e. SFE-electronicsiseerobot, famosastudio, geraicerdas, kedairobotklinikrobot, and many others.

At first, I followed the Arduino standalone tutorial (or from a youtube video if you like). This is the result.


To make things a litter easier, I produced homemade breakout for my triple thermistors with this schema:



Then I slowly added one component after another.
  1. FTDI basic, with pinouts connected to VCC, GND, CTS (GND), TX (pin 0), RX (pin 1), and DTR + 100nF (pin 0). 
  2. Thermistor breakout is connected to VCC, GND, pin A0, pin A1,and pin A2. 
  3. Relay is connected to VCC, GND, and pin 3. 
  4. Buzzer is connected to pin 4 and GND.
The setup is now ready to go.



PROGRAMMING

Now it comes to the interesting part: programming. Thanks to Arduino developers and community around the world. Microcontroller programming could not be more fun than before (considering I do NOT have an electronics background). You may visit the official forum, instructables, adafruit, sparkfun and too much resources to read on the net

Firstly, thermistor runs on the principle of changing resistance upon increase/decrease of environmental temperature. After some reading, I decided to use Steinhart-Hart equation (others may use lookup table), hence the codes (frankly, taken from adafruit page with some modifications) are in the two separated functions (getResistance and getTempC). Since the explanation on the Internet is quite extensive, already, I do not find any use to re-pasting them here (you may download the whole program at the end of this article).

Next step is to check whether probes are working in the expected environment (i.e. 0-70°C). Since I have triple thermistors, I can afford to lose two of them at maximum to get a temperature value. Hence, the function is called checkProbe.

#define TPin1 A0                 //Thermistor Analog Pin A0
#define TPin2 A1                 //Thermistor Analog Pin A1
#define TPin3 A2                 //Thermistor Analog Pin A2

int termostatValDivider = 0;
float termostatVal = 0.00;
int messageIndex;

void checkTempProbe()
{
  //resetting values first
  termostatValDivider = 0;
  termostatVal = 0.00;

  //if measured 0 < temperature < 70, probe in good condition, otherwise malfunction
  //TPin1
  if (getTempC(getResistance(TPin1),TPin1)>0 && getTempC(getResistance(TPin1),TPin1)<70 p="">
    termostatVal += getTempC(getResistance(TPin1),TPin1);
    termostatValDivider +=1;
  } else {
    //message index 91
    messageIndex = 91;
    //debugging
    Serial.println("Probe 1 malfunction");
  }
  //TPin2   
  if (getTempC(getResistance(TPin2),TPin2)>0 && getTempC(getResistance(TPin2),TPin2)<70 p="">
    termostatVal += getTempC(getResistance(TPin2),TPin2);
    termostatValDivider +=1;
  } else {
    //message index 92
    messageIndex = 92;
    //debugging
    Serial.println("Probe 2 malfunction");
  }
  //TPin3
  if (getTempC(getResistance(TPin3),TPin3)>0 && getTempC(getResistance(TPin3),TPin3)<70 p="">
    termostatVal += getTempC(getResistance(TPin3),TPin3);
    termostatValDivider +=1;
  } else {
    //message index 93
    messageIndex = 93;
    //debugging
    Serial.println("Probe 3 malfunction");
  }
  //get temperature from available probe(s) only
  if (termostatVal!=0 || termostatValDivider!=0) {
    termostatVal /= termostatValDivider;
  } else {
    //message index 99
    messageIndex = 99;
    //debugging
    Serial.println("All probes malfunction");
  }
}

To call the function is pretty basic.

void loop() {
  //resetting message index
  messageIndex=0;
 
  //check probe, if failed, switch mode
  checkTempProbe();

  //debugging
  //Serial.println(termostatVal);
  ….
}

The rest is to create an action function based on temperature reading, i.e. I wanted a range of temperature in between 27-33°C.

#define heatingTime 5000         //heatingTime to let heater warms up
#define coolingTime 10000        //coolingTime to maintain temperature at range.
#define upperTemp 33             //max allowed temperature
#define lowerTemp 27             //min allowed temperature
int led = 13;
int buzz = 4;

void loop() {
  …
  //main program 
  if (messageIndex==99) {
    //thermistor probes failure
    action(99);
  } else if (termostatVal>upperTemp) {
    action(1);
  } else if (termostatVal
    action(2);
  } else {
    action(0);
  } 
}

//heater action
void action(int mode)
{
  //debugging
  Serial.print("Action mode: ");Serial.println(mode);
 
  if (mode==99) {
    //all thermistor failures
    //buzing
    buzzing(messageIndex);
    //blinking
    blinking(messageIndex);

  }  else if (mode==1) {
    //message 11
    messageIndex = 11;
    //debugging
    Serial.print("termostat value:"); Serial.print(termostatVal); Serial.print((char)176); Serial.println("C, Heater OFF");
    Serial.print("ALERT: "); Serial.print(termostatVal); Serial.print((char)176); Serial.println("C: temperature too high!");


    //heater OFF
    digitalWrite(relayPin,relay_OFF);

    //buzzer ON
    buzzing(messageIndex);
    //blinking ON
    blinking(messageIndex);
      
  } else if (mode==2) {
    //message 12
    messageIndex = 12;
    //debugging
    Serial.print("termostat value:"); Serial.print(termostatVal); Serial.print((char)176); Serial.println("C, Heater ON");
    Serial.print("ALERT: "); Serial.print(termostatVal); Serial.print((char)176); Serial.println("C: temperature drop!");
  
    //heater ON
    digitalWrite(relayPin,relay_ON);

    //buzzer ON
    buzzing(messageIndex);
    //blinking ON
    blinking(messageIndex);

  } else {
    //message 10, all good
    messageIndex = 10;
    //debugging
    Serial.print("termostat value:"); Serial.print(termostatVal); Serial.print((char)176); Serial.println("C, Heater REGULATED");
   
    //cooling first then heating
    digitalWrite(relayPin,relay_OFF);
    delay(coolingTime);   
    //heater ON for predefined time
    digitalWrite(relayPin,relay_OFF);
    delay(heatingTime);

    //blinking ON
    blinking(messageIndex);
  } 
}

//blink action
void blinking(int mode)
{
  if (mode==11) {
    //blinking, high temp
    for (int i=0;i<5 i="" p="">
      digitalWrite(led, HIGH);   
      delay(200);               
      digitalWrite(led, LOW);    
      delay(200);               
    }
  } else if (mode==12) {
    //blinking, low temp
    for (int i=0;i<5 i="" p="">
      digitalWrite(led, HIGH);   
      delay(500);               
      digitalWrite(led, LOW);    
      delay(500);               
    }
  } else if (mode==99) {
    //blinking all probes malfunction
    for (int i=0;i<10 i="" p="">
      digitalWrite(led, HIGH);   
      delay(100);               
      digitalWrite(led, LOW);    
      delay(50);               
    }
  } else {
    //blinking, normal
    digitalWrite(led, HIGH);   
    delay(500);               
    digitalWrite(led, LOW);    
    delay(500);               
  }
}

//buzzer action
void buzzing(int mode)
{
  if (mode==11) {
    //buzzing, high temp
    for (int i=0;i<5 i="" p="">
      digitalWrite(buzz, 100);   
      delay(200);               
      digitalWrite(buzz, 0);    
      delay(200);               
    }
  } else if (mode==12) {
    //buzzing, low temp
    for (int i=0;i<5 i="" p="">
      digitalWrite(buzz, 50);   
      delay(500);               
      digitalWrite(buzz, 0);    
      delay(500);               
    }
  } else if (mode==99) {
    //buzzing all probes malfunction
    for (int i=0;i<10 i="" p="">
      digitalWrite(buzz, HIGH);   
      delay(100);               
      digitalWrite(buzz, LOW);    
      delay(50);                
    }
  } else {
    //no buzzing
  }
}

All are (almost) done, except for readable message with double digits 7-segment. You may download the code from here.  No github account yet :(.

TIME FOR FUN

Lets connect the FTDI to a USB port.



SNEAKPEAK

Part 2: Multi buttons input for single Arduino analog pin


Part 3: Integrating double digits 7-segment (coming soon)





Enjoy!

Comments

Popular posts from this blog

Merakit Destilator Bioetanol Sederhana (1)

DHT11 incubator with I2C LCD (part 1)

LM35 Incubator with LCD 16x2 on Arduino