DIY CO2 Incubator - Arduino and Circuits
Updated: Aug 17, 2021
The electronics and code are embarrassingly primitive. In general terms, an Arduino UNO simply monitors temperature and CO2 content and turns on/off the heaters or open/closes the solenoid valve as necessary to maintain the various setpoints. I am 100% sure the whole setup can be improved and made more efficient (some areas for improvement are listed later on). However, even though this embodiment is pretty dumb it works and mammalian cells can be grown and differentiated
The Arduino is essentially operating four simple circuits:
Control of a 12V DC fan.
Reading temperature sensors.
Reading the CO2 sensor.
Relay control to supply 12V to the heaters (on/off) or to the solenoid (open/closed).
That’s it! Below these circuits will be described. It is recommended to build/test each circuit before throwing it all on a single board. Here, the whole thing was prototyped on a breadboard and then locked down on perfboard. Depending on your setup, this is probably a good ideas as the current draw by heaters can be high and may eventually damage your breadboard.
IMPORTANT NOTE: In the breadboard images below I have not shown the 12V power supply. However, you will need it! Using a DC barrel adaptor, connect a 12V supply to one set of rails and the Arduino 5V to the other (with common ground). In the images I indicate which set of rails the 12V supply should be connected to.
PWM DC Fan Control
Components needed: 1x TIP120 transistor, 1x 1kOhm resistor, 1x 100uF cap, 12V DC Fan, 12V power supply
This is a very common setup. You can visit this Instructable for more info. In the current Arduino code the fan is connected to a PWM Pin, however, the fan is always on so PWM control is not really being exploited. You could just run the fan off the 12V supply and remove any Arduino control completely. In potential redesigns of the setup it might useful to have the fan come on at certain times, or change speed, etc. For this small box setup, I found that having the fan continuously on helped to keep the atmosphere well mixed and the temperature fairly stable.
Circuit for PWM Fan Control
Reading the Temperature Sensors
Components needed: 2x DS18B20 sensor (or as many as you like), 1x 4.7kOhm resistor.
For temperature I decided on using two DS18B20 sensors wired parasitically. Below is a circuit for two sensors, however the wiring to add as many sensors as you like is very simple (follow the link in the previous sentence). In general, the outer legs of each sensor (legs 1 & 3) are wired together and then to ground. Data is collected on the middle leg of each sensor. These are wired together and then to 5V via a 4.7 kOhm resistor. In this specific example, readings are made from Pin 12 of the Arduino which is wired to leg 2 of one of the sensors. Each sensor identifies itself automatically on the bus and data from individual sensors is easily recorded.
Circuit for reading two DS18B20 Temperature Sensors
To use the sensors in the Arduino you will need the OneWire and Dallas Temperature Control Libraries. The test code provided here is for two sensors and the data is being collected on Pin 12. Its is straightforward to change the code for a single sensor, or to add more.
Reading the CO2 Sensor
Components needed: 1x GC-0017 CO2 Sensor.
For CO2 sensing I decided to employ an NDIR based sensor from co2meter.com (GC-0017, 0-20%). There are only 4-pins we care about on the sensor (GND, 3.3-5.5VDC, Rx, Tx) and its very easy to hook up.
Luckily an Arduino library was developed for this CO2 sensor so I didn't have to do much work to get it up and running. I recommend reading this forum which has the library and some example code (also maintained on github a big shoutout to DirtGambit and Rob Tillaart for developing this). I am currently using the 1.0 version of the library on page 1 of the forum with no problems. If you decide to add more CO2 sensors to your setup you just need to define more software serial ports.
To convince myself the library and Arduino were working, I made sure measurements from the Arduino matched values obtained by the official company software. I also checked the calibration by exposing the sensor to a commercial premix of 5%/95% CO2/Air gas from BOC. Upon exposure to the 5% CO2 premixed gas I obtained CO2 readings from 3 different sensors. To do this I placed each sensor inside of an airtight container with a gas inlet and a syringe acting as an small outlet. Under pressure, I flooded the premixed gas into the box and started recording. For each sensor I made three 180sec recordings and then averaged all 9 measurements together to produce the plot below. On average, exposure to a commercial premixed gas of 5%/95% CO2/Air, resulted in a stable CO2 reading of 5.01±0.15%. This is well within the noise characteristics of the sensor. Not bad.
Relay Control over the Heaters and Solenoid
Components needed: 1x 2N2222 transistor, 1x 1kOhm resistor, 1x 1N4007 diode, SPDT relay, 12V power supply.
I employed two identical relay switches to supply 12V power to the heaters or the solenoid. The pictures and code here are for a single relay, so you will have to double up. I am using a pretty standard SPDT relay from sparkfun which is very easy to setup. This one is the 5-pin variety so note that the wring will change very slightly for 6-pin SPDT relays. There are also lots of pre-built relay modules out there that are simple to implement.
Controlling a relay is very easy. Setting an Arduino digital pin HIGH allows one to employ a transistor to trigger the relay switch with 5V from the Arduino. Once the switch has been triggered, 12V power can supply your load. Setting the digital pin LOW closes the switch. Therefore, the relays can be used to selectively supply power to a heater or to a solenoid.
After testing and prototyping all the circuits together on a breadboard I locked it down on some perfboard. Check the full arduino code and the picture below to see what pins I used for reading/controlling everything. Depending on how much power your heaters consume, perfboard is probably a good idea. Breadboards arent rated to handle a lot of current and can be damaged. I also soldered some 18AWG wire onto the 12V rails of my perfboard (power rails closest to the Arduino in the pic below) and over the relay supplying my heaters. I had lots of headers lying around so I threw some on the board to make connecting/disconnecting all the sensors/hardware and 12V power supply a little easier.
General Arduino control/sensor pin layout without showing the details of the individual circuits.
Control and Performance
The Arduino control code is currently setup to measure the average temperature across the two DS18B20 sensors and turn the heaters on if the average falls below the setpoint. The heating is controlled in two ways. If the temperature is lower than 98% of the setpoint (for example, 36°C with a setpoint of 37°C) the heaters come on continuously. If the temperature is greater than 98% of the setpoint (for example, 36.5°C with a setpoint of 37°C) the heaters turn on for only 1sec and another reading is made. This cycle continues until the setpoint is reached. This approach allows the system to step up to the setpoint and minimize overshooting.
CO2 control is managed in a similar fashion. When the CO2 content of the incubator drops below 80% of setpoint (for example 3.5% with a setpoint of 5%), the solenoid opens allowing CO2 to rapidly fill the incubator. If the CO2 level is above 80% of the setpoint (for example 4.5% with a setpoint of 5%), the solenoid only opens for 0.2 sec, closes and another reading is taken. This cycle continues until the setpoint is reached. This approach allows the CO2 content to step up to the setpoint and minimizes over-shooting.
All the parameters (setpoint, thresholds, relay on times) modulating the control of the system are defined by the user. The default values in the Arduino control code work well for the incubator being described here. Values for the Temperature and CO2 setpoints (36.9 and 4.8, respectively), thresholds (0.98 and 0.8, respectively) and on times (1000 and 200, respectively) were chosen to achieve a stable reading of 37°C and 5% CO2. These parameters are defined at the beginning of the control code. It is extremely important that the user experiments and determines the best values to use. These values will depend very much on the size/shape of the incubator, pressure/flow rate of the CO2, type of heating and heat sinks, etc.
Using this setup, an experiment was then performed in which the temperature and CO2 content of the incubator was measured over time. A second Arduino connected to a data logging shield, a DS18B20 temperature sensor and another CO2 sensor was placed on the middle of the DIY incubator after it had been running for at least a day. The door was closed and the incubator was allowed to stabilize for three hours. At this point the Arduino was switched on and began logging temperature and CO2 every 5 seconds. After 10 minutes, the door was opened for 15 seconds and closed again. The recording then continued for several hours. As a comparison, the same experiment was performed on a fairly standard sized commercial incubator (170L volume). This is ~10 times larger than the DIY incubator. The same set of sensors were placed in the middle of the incubator. As well, the CO2 and temperature sensors were checked against known samples (water bath with analog thermometer and a 5% CO2 premixed gas from BOC).
Temperature recovery and stability of a standard commercial incubator (top curve) and the DIY incubator (bottom curve).
In the data above, it is clearly visible that opening the door results in a small but sudden drop in temperature by ~1°C in both incubators. Given that the commercial incubator possesses a number of temperature stabilization strategies (heated door, water jacket, etc) it was surprising the temperature drop was identical to the DIY incubator. On the other hand, due to its small volume, the DIY incubator displayed a significantly faster recovery time compared to the commercial incubator. However, both incubators recover and hold the temperature at 37°C after opening/closing the door with an acceptable temperature fluctuation of ~1°C.
CO2 recovery and stability of a standard commercial incubator (top curve) and the DIY incubator (bottom curve).
Opening the door of either incubator results in a rapid decrease in CO2, approaching regular atmospheric levels. Surprisingly, the recovery time of both incubators was observed to be quite similar, however the DIY incubator did tend to display a small overshoot. What is clear from the data, is that the commercial incubator was able to maintain a more stable CO2 content over time. The DIY incubator displays fluctuations of about ±0.2% (in other words, ~4% of the target value of 5%). In this case, the average stabilized CO2 level in the middle of the incubator was ~4.9%.
However, of great concern was the fact that the CO2 content in the middle of a commercial incubator was routinely less than 5%. This is very much due to their large size and an apparently poor ability to properly mix the gas. In the data above, the CO2 content was ~3.9% on average, which was highly consistent with ~5 other makes/models that were examined. In one case, a commercial incubator was observed to maintain a CO2 level of ~6%. Taken together, this represents a deviation of ~20% (or more in some cases) away from the target of 5% CO2 content.
Conclusions: Although the DIY incubator has some room for improvement (described in the Possible Improvements section), it actually performs very well compared to commercial incubators that can easily be a factor of 15 or 20 higher in price. Most importantly however, mammalian cells (mouse cell lines and primary human cells) did not appear to be affected by the small CO2 fluctuations that were observed in the DIY system. These cells exhibited normal proliferation dynamics, morphologies and the ability to undergo complex biological processes. These findings are described in the next section.