Pioreactor dev log #13 - Heating improvements

Pioreactor dev log #13 - Heating improvements

🔥 This week (month?) we look at some recent improvements to our internal heating system.

Introduction

Each Pioreactor has built-in heating and temperature sensors. I emphasize temperature sensors, since I've used enough hot plates to not trust a graduated knob to have any reliability. With a combination of heating and temperature sensors, the Pioreactor is able to keep a set temperature for the culture, regardless of the Pioreactor variations in the construction, ambient temperature, etc.

Why even include heating in the first place? Can't users just place their bioreactors in an incubator (after all, they are small enough). Our goal is to make the Pioreactor as accessible as possible, and frankly, not everyone has access to incubators - most people don't infact. I don't. So providing built-in heating gives users another piece of equipment.

Furthermore, a very common experiment is to vary the temperature of a culture and watch its growth response. With built-in heating, it's trivial to set up a cluster of Pioreactors, each set to a different temperature, and let it run. No need for N incubators.

How heating works on the Pioreactor

An aluminum PCB is at the base of the Pioreactor sleeve, see Figure 1. This PCB contains a temperature sensor, a Hall sensor (used for stirring RPM), and resistors. The resistors do nothing but convert current into heat (resistive heating), up to 5W, controlled via a PWM. The Pioreactor software reads the current temperature, and varies the PWM to establish the correct temperature. We opted to have the temperature sensor outside the liquid (as opposed to an in-situ sensor as this significantly reduces any contamination problems.

Figure 1. Left: Placement of the PCB in the Pioreactor sleeve. Right: cut-away view.

But there's a problem: the temperature sensor on the PCB is giving the temperature of the PCB - not the vial on top! And the PCB is the source of the heat, so it's always going to give a (often significantly) higher value than the temperature of the vial. How do we solve this?

Physics + statistics

First, we can build a model of our system: An high thermally conductive aluminum body, tightly touching a much-less thermally conductive glass-water body. There exists an ambient temperature, that is lower than both the aluminum and the glass-water bodies' temperatures. Imagine there is no active heat source on the aluminum body. One can set up a system of differential equations to model this, but in the end, the temperature of the aluminum looks like a sum of two exponentials, plus ambient temperature. The two exponentials relate to the rate of temperature decay in the two bodies. From this equation, we can "rewind" time to the initial time=0 and recover the temperatures of the bodies initially. 

$$T_{\text{(temp sensor)}}(t) = T_{\text{(ambient temp)}} + T_{\text{(PCB temp at 0)}}\exp{(-at)} +T_{\text{(glass-water temp at 0)}}\exp{(-bt)}$$

Okay, so how is this applied in the Pioreactor? We periodically turn off any heating, and start recording frequently from the temperature sensor. From this recorded time series, we can fit, using least-squares, the above equation, which has 4 unknowns. Once fit, we can infer the temperature of the glass-water body (the vial) easily. Figure 2 shows an example of this: 

Figure 2. The blue dots represent data from the temperature sensor. We fit a sum-of-two-exponentials to it, and from this, we can infer the temperature of the vial during that time period.

A tradeoff is how long to pause heating for in order to get enough data to accurately fit to the equation: too little data, and our inference is too inaccurate (but we can perform the cycle of heating-and-collecting very quickly). At some point, we collect enough data that an additional data point doesn't really make a difference. Currently, we collect data for 2.5 minutes as this seemed like a good balance. This 2.5m, plus the 1.5m time for heating, is 4 minutes, so we calculate a new temperature to the Pioreactor every 4 minutes. Later, I think we can replace the least squares fit with a machine-learning model, and hopefully reduce the amount of data needed. 

Why not use X?

It often comes down to price or convenience. As mentioned previously, as in-situ probe would create contamination concerns. Using a IR thermal camera to measure the glass would work, but would likely be the most expensive part of the system. A temperature every 4 minutes is usually enough for evenly reasonably complex tasks. Consider the following chart, where we varied the target temperature and recorded the Pioreactor's response:

Figure 3. Varying the target temperature, and letting the Pioreactor adjust. We adjust the PWM using a PID controller, however we are being extra conservative here in our PID parameters. We really don't want to overshoot the target temperature (as this could harm the culture), so we take care to never do that. This does mean a slower convergence though.

With the Python API, we can also program custom temperature patterns in the vials. Below is an example of the Pioreactor following a sinusoidal target temperature. 

Figure 4. The Pioreactor following a sinusoidal target temperature.

Though the above is mostly a demonstration, it's likely that some users will want some changing temperatures to mimic a new environment, or to understand how the culture responds to changing temperatures. 

Conclusion

We are pretty happy with the current state of temperature and heating in the Pioreactor. Stay tuned for more!