A "kegerator" that can keep my beer cold and allow me to ferment my beer at precise temperatures using a MIMO (state space) control design.
Adobe Portable Document Format - 2.48 MB - 09/09/2018 at 22:04
Simple schematic showing wiring within the project box.
Portable Network Graphics (PNG) - 90.67 kB - 09/02/2018 at 21:06
Kicad files for the Teensy interface board.
Zip Archive - 1.47 MB - 08/15/2018 at 00:36
PDF of the schematic for the Teensy interface board.
Adobe Portable Document Format - 189.73 kB - 08/15/2018 at 00:35
The next step in designing my "most complicated freezer closed loop control system" was to create a linear observer.
For my system model I have three temperatures I am currently measuring and I want to get rid of the temperature probe that measures the sidewall of the freezer! Why, you might ask, would you go through this extra complicated step and decrease the reliability of your system by increasing complexity?
1.) Because I can.
2.) So I can learn.
Just to point this out: One of my coworkers built a kegerator recently. He purchased a ~$60 box that hangs on his wall that his freezer plugs into and has a temperature probe that he can stick either in a carboy or next to one of his kegs to control the temperature of the freezer. It most likely uses some simple PID control algorithm. I just want to put that out there so that everyone realizes the ridiculous level of complexity I am adding into what could be a very simple control system…
With that out of the way, the two textbooks I am referencing are:
Feedback Control Systems (Franklin, Powell), fourth edition
Control System Design, An introduction to State-Space Methods (Friedland), First Edition
I designed my linear observer using the example 7A in Friedland. (See page 264 if interested.) Chapter 7 in Franklin also helped as well. I attached my math as a design file named “Linear Observer Design Sept 9 2018.pdf for those who are interested in taking a quick review.
I then proceeded back to Matlab and Simulink to see if my observer actually worked.
The first step was to validate operation in the continuous time domain. I setup a quick model. See below.
The simulation results tuned beautifully when I placed the two closed loop poles at 0.001 rad/s.
However as I moved the two poles further into the right half plane (i.e. faster response) the estimated value for the freezer wall would converge fast but started to have noticeable noise. See below fora plot with poles at 0.005 rad/s.
Close up image below.
For initial system design I selected a pole at 0.001 rad/s. I then converted by continuous time model into the digital domain. I selected a sampling time of 1 second. Matlab has a nice “c2d” function that I avoided. I ended up quickly coding the conversion algorithm documented in chapter 8 (pg. 676) in Franklin and using c2d to check my work. I then setup a new simulink model to validate that I didn’t mess anything up. The simulink model is below. It gave exactly the same results as the continuous time model.
I then wrote the code for the state space algorithm in Matlab. I did this so that I could quickly plot the results of the coded algorithm prior to coding them into the teensy controller. I am glad I did as I quickly caught some typo errors that would have had me scratching my head. As you will also notice it takes approximately 30 to 60 minutes for the freezer wall temperature estimate to converge to the measured value. This is a LOT of time between troubleshooting. Code is below for those interested.
% ----- Digital Code Verification ----- t = 0:Ts:time_cool(end); Te = my_interp(external_temp_cool,t); Tc = my_interp(carboy_temp_cool,t); Tf = my_interp(fridge_temp_cool,t); fridge_on = my_interp(fridge_on_cool,t); Tc_e = zeros(size(t)); Tf_e = zeros(size(t)); %Tc_e(1) = Te(1); %Tf_e(1) = Te(1); for loop = 1:(length(t)-1) [Tf_e(loop+1), Tc_e(loop+1)] = observer_algorithm(Ad,Bd,Fd,Ld,Tf_e(loop),Tc_e(loop),Tc(loop+1),fridge_on(loop+1),Te(loop+1)); end plot(t,Tc,'b'); hold on plot(t,Tc_e,'g'); plot(t,Tf,'r'); plot(t,Tf_e,'b'); plot(t,Te,'k'); title('Freezer Temperatures (Matlab Code)'); legend('Carboy (Measured)','Carboy (Estimated)','Freezer (Measured)','Freezer (Estimated)','External (Measured)'); xlabel('Time (sec)'); ylabel('C'); hold off
The function "observer...Read more »
With the freezer in the garage and the control system operating I started the next phase of the project: system modeling.
I filled the carboy with 26.9 kg of tap water. I then placed a temperature probe in the thermowell within the carboy, a temperature probe on the wall of the freezer and left a temperature probe out external to the freezer.
I then recorded four data files: Twice with the freezer cooling the carboy and twice allowing the carboy to warm up.
The model that I developed for the system is below. It is an “electrical equivalent” model representing heat transfer between the ambient environment, the freezer and the carboy. (Note the funny symbol for q is a current source pointed away from Tf to ground.)
Cc is the heat capacity of water in the carboy.
Cf is the heat capacity of the freezer.
q is the heat collected by the freezer.
R1 is the thermal resistance between the freezer and the ambient external environment.
R2 is the thermal resistance between the freezer and the carboy.
Te is the ambient external temperature.
Tf is the temperature of the freezer wall (measured from the inside of the freezer).
Tc is the internal temperature of the carboy.
The differential equations for the model are below.
By measuring Tc, Tf and Te I was able to calculate Cc, Cf, q, R1 and R2. (I used Matlab and Simulink to run the simulations (version r2017b). I am more than happy to upload the files for others to use if interested. Matlab now offers a "hobby" edition of the matlab software for about $45. Add on modules such as simulink are an additional $45. I think they have been watching everyone migrate to Python.)
First I simulated the carboy temperature using the freezer wall temperature I measured. This let me simplify my model to only R2 and Cc. I assumed a Cc of ~50000 J/C using a specific heat of 4.18 kJ/(kg C). I was then able to tune R2 so that when simulating Tc using Tf, R2 and Cc my simulated Tc match the measured Tc. The simplified model is below.
Cc = 50000
R2 = 0.65
The simulation results and images of my simulink models are below.
As you can see the simulated Tc matches the actual measured Tc very closely. The time axes is in seconds.
I then setup a simulink model for the larger system with Te and q as the inputs. I then tuned the values for R1, Cf and q to align my simulation with my the measured Tc and Tf. Results from the simulation are below.
R1 = 1.6
Cf = 5000
q = 156*pwm_percentage
It works! It is very exciting again! I finished all this work over the weekend and then did a little dance around the table. I also noticed that my wife is very impressed with milestones in my projects. She usually celebrates with some eye rolls and “that is vey nice honey” statements. I take that as high praise indeed!
Next time update I should be able to provide feedback on development of my state space closed loop control algorithm! (Also very exciting!)
I have successfully moved my project to the garage! And it works.
I wrote software for the Raspberry Pi to log temperatures and status from the teensy uC. I have uploaded my current revisions of Teensy and the Python code I am using the Raspberry Pi. The teensy is currently set up on an with a hard interrupt every 60 seconds and transmits temperatures, output of the scale at the bottom of the freezer and general status to the RPi for logging. The teensy is currently programmed to turn on the freezer for five minutes out of every 20 minutes. This is a 25% PWM cycle and is working like a charm.
I placed a carboy filled with water in the freezer and I am using the temperatures recorded to model the system. In my next update I will add details on the mathematical model of the system and the values I have calculated.
I have been working on this project for the last month. This first post is intended to document my progress.
I have purchased a small top open freezer and placed it in my garage. (Make/Model: Idylis 7.1 cu ft chest freezer) I will be using this freezer to regulate the temperature of my keg/carboy. I live in Texas so it is hot the majority of the time. Initially I am planning on focusing my efforts on controlling the temperature of my freezer to cool my beer/carboy as needed. The electronics I have designed will allow me to integrate a heating coil at a later date (i.e. in the winter!)
I purchased a small household scale and ripped out the electronics and soldered a cable to the wheatstone bridge scale elements. (Make/Model: Taylor 7042T) The scale will sit in the bottom of the freezer and I will use it to calculate how much beer is in my keg as well as the specific gravity of my brew as it ferments. To get the required resolution of the beer as it ferments I designed a unique analog circuit that implements a differential amplifier with a 12 bit digital to analog converter and 8 bit analog to digital converter to give a combined 20 bit resolution on the output of the scale. I will update this page with information on my circuit design shortly.
I am using a Teensy as the micro controller to implement my control algorithm. I have designed a custom interface board that allows my to plug my Teensy into the analog/digital circuitry to read my scale and four temperature sensors as well as be powered and communicate with a raspberry pi 3+. The four temperature sensors each have a three wire digital interface. (Make/Model: Maxim Integrated, DS18B20+)
The Teensy will do the real time control of turning on and off the freezer to stabilize at an optimum temperature. One of the temperature sensors will go into a thermowell that sticks down into my fermenting beer. Another sensor will be integrated into an elastic strap that will go onto my keg once my beer is brewed. Either of these temperature sensors will be the temperature input into my control system. A third temperature sensor will measure the ambient temperature in my garage. This will be the "disturbance" input. The fourth temperature sensor will measure the ambient temperature in my project box that will be mounted on the wall and contain my electronics.
Because I have two temperature inputs into my control system I will be able to teach myself how to implement a state space "MIMO" control algorithm. (Super exciting!!!) :-)
The project box uses a din rail that I have mounted onto the metal plate in the back of a "Bussman" box. On the din rail I have attached a 5V power supply (3A) that I am using to power my raspberry pi and Teensy micro controller and two 5V fans that circulate outside air through the project box. I have two solid state relays that allow me to turn on and off 120V power. (Make/Model: Inkbird SSR-25DA) One of the solid state relays will provide power to the freezer the other I am going to use to power a heating coil (when it gets cold outside).
That is about it for now: The circuit to interface with the scale and temperature sensors has been designed and fabricated onto a OSHPark PCB. The pcb has been integrated into the project box and connected to my Raspberry Pi. I can read from all temperature sensors and the scale and turn on power to either output.
Now I need to program the thing: My plan is to initially use the Raspberry Pi to provide a direct interface to the Teensy. The Teensy will be programmed to do nothing other than read temperatures, the scale and turn on and off the freezer on command. The Raspberry Pi is being programmed to act as a TCP/IP converter so that temperature/scale...Read more »