Timer, inputs, and states, need some help with a project for brewing beer

Hello all,
I’m trying to build an open-source beer brewing robot (brewbot) using the arduino. There are a few that exist already, but I want to do a few things differently. I want to get the recipe from beerXML, I want to use serial+computer as my interface, I’m using a single pot brew-in-a-bag setup, and I want to use my propane and adjustable regulator to control the heat. I’ve taken a look at how others have build their brewbots (notably Brewtroller and HABS), but their code seems overly complicated to me. Also, they are using hardware controls.

At any rate, early prototypes show great promise, and I’m now working on greater automation of the system. What I need help with is understanding how I can break down a recipe into it’s control steps.
For instance, if there is 1 strike, 2 mashes, and 1 boil, that’s 4 control steps (states?). The problem is that what happens in each is a bit different.
For strike, I want to heat the water to a specified temp (say 152 degrees F), then I want to wait while I dump in some grain, then press a button and go to the next step - mash1. For mash 1, I want to hold a constant temp (150F) for a specified period of time, then go to the next step mash 2. For mash 2, I want to increase the temp to 160F, then start a timer and hold the temp for 30 minutes. Then I want to go to boil - get the temp to 212 then start a timer, stopping after 60 minutes.
During the boil, I want to set an alarm to remind me to put in my hops at certain times.

float getRecipe()
{
String steps[] = {"Strike", "Mash1", "Mash2", "Boil"};
float temps[] = {152,150,160,212};
int times[]={100,30,30,60};
int numSteps = (sizeof(steps)/sizeof(String));//number of steps

//what goes here? 

return Setpoint;
}

So, my question is how can I get the recipe info and use that in some sort of state machine, taking inputs from either millis() or SimpleTimer, and control how the program goes from state to state?

Thanks,
JR

Attached is the full program code including my pseudocode and comments to myself(for the curious).

automatedBIAB_v1.ino (7.73 KB)

Do we get any free beer if we help you ?

raschemmel: Do we get any free beer if we help you ?

Sure, but you have to travel to San Jose, CA to pick it up :)

I live in Los Gatos.

Do you have a budget ? (why would I ask such a silly question ?) Playing around with arduinos is one thing, making a food or beverage processing plant is a whole different animal, IMO, in that normally it would be sufficient to keep a count and store it in a variable but it the case of your application I would recommend you design a controls panel an implement multiple I2C (or even parallel) lcds that display the running count up or down of different processes that are under way. In addition I would recommend implementing an EMO button (the standard slap to turn off type that are available in many places, Grainger just to name one. I would recommend you use thermocouples for monitoring the temperatures and have those on dedicated displays as well. Adafruit sells an MCP31855 Breakout bd (I have one) that works reliably). You might even consider (I would recommend) some kind of hardware interlocks that are independent of the uC. Running heaters involves levels of current that you would probably want to monitor. Sparkfun sells an INA169 current shunt that may work for your application but I don't know without seeing the schematic or specs for you heater. Additionally I would recommend the use of Light Towers to indicate process status of the different control steps. You might also consider implementing a loud piezo alarm to signal an alarm state for something seriously wrong involving heater , temperature or current. I haven't looked at your code but I don't have a whole lot of programming experience so probably my contribution will be limited to hardware related issues/questions. I will look at it but don't expect anything.

Have you developed a logic flow diagram that works for all the combinations of actions in your brewing process? If not, then that would be a place to start.

Second that. For something this complex you need an algorithm (logic flow diagram).

raschemmel:
I live in Los Gatos.

In that case, drop by for a homebrew anytime! I’m in Saratoga :slight_smile:

Do you have a budget ?

Despite the aforementioned zip code, yes: cheap :slight_smile:

On the hardware side, I’m pretty well sorted.
I have two ds18b20s for temperature monitoring, I’ve got a thermocouple and flame sensor to monitor if there’s flame. If there’s no flame the gas doesn’t go on. I’m using a hot surface ignitor to light the propane - the only thing requiring any significant current, so I have an SSR for that. I don’t have an emergency button yet, but it’s on order. I had piezo buzzer ordered, but it didn’t work, so I have to get another one of those. I want to use the serial monitor because I can tie it in to Python or Processing and control from my PC, log data, and display charts. Even better I can send the ‘recipe’ info over serial straight from the XML (but that’s another forum thread).

As far as a control flow diagram, it’s actually reasonably simple because each ‘state’ follows the next in progression - it will never go from boil to mash or mash to strike. The tricky bit is the inputs for going from one state to the next are different for each state.

So here’s how I"m thinking about it.

beginning state - everything off. Load in recipe data. remain off until button is pressed on PC and sends serial packet.
press button
State 1 (Strike) - light fire and heat water to specified temperature. sound alarm. When specified temp has been reached and alarm has sounded, button press sends to next state. The need for button press is to give time to add grain while holding temperature.
button press
State 2 (mash) - maintain temperature for starch conversion for specified period of time. There will be at least one mash step. After the time has been reached, if there is more than one mash step, switch to mash 2. If there isn’t another mash, sound alarm then continue to boil after button press.
State 2.1 (mash) -maintain temperature for starch conversion for specified period of time. After the time has been reached, if there is more than two mash steps, switch to mash 3. If there isn’t another mash, sound alarm then continue to boil after button press. (button press is to allow time to remove grain)
button press
State 3 (boil) - heat to boiling, maintain boil for specified period of time. Sound alarm at predetermined periods of time to remind me to add hops. After specified boil time has elapsed, turn off the burner.
State 4 - everything off. No timers

I guess if I have to boil my question down to the essence, it’s “how should I change states, do I need a Finite State Machine, or is ‘swich(case)’ good enough?”, and “how best to implement the best solution”?

Thanks,
JR
PS Zoomkat, your servo test microseconds sketch was super helpful for in the early stages of prototyping. Since I’m not using a standard servo, it’s a little tricky to find where the rotation for the valve starts and stops for the servo’s rotation. So, thanks :slight_smile:

PPS here’s one of my earlier tests. At this point I was just controlling the temp with the servo, no other automation, so I had to light the flame manually (which isn’t the smartest thing in the world).

Have figured out how you're going to do the timers ? FSM- I think this is definitely worth a try. Assuming you already have the cooking hardware can you test the FSM using just water and a stopwatch ? (monitoring the temps) Are you planning to use serial prints or lcds to monitor the timers and temps ?

raschemmel: Have figured out how you're going to do the timers ?

Not really :) that's part of this exercise, though.

FSM- I think this is definitely worth a try. Assuming you already have the cooking hardware can you test the FSM using just water and a stopwatch ? (monitoring the temps)

that's my plan, testing with water is good enough for testing.

Are you planning to use serial prints or lcds to monitor the timers and temps ?

serial to Python or Processing . I'm trying to avoid the overhead of lcds for now.

What overhead ? They're like $6 a piece. You could get six of them for $40. If they're I2C , that's four wires each with two of the wires connecting to the same pins on all six lcd and the same for the power wires. They're address based. You can get some LEXAN sheet from TAP plastics on the Alemeda and get the rectangular holes cut out (either there or somewhere else) , drill and tap the mounting holes your self and build a control panel box with all your electronics in it and connectors on the side. If you don't want to mess with the job of epoxying the pieces together for the box you can use small cabinet L brackets from home depot and drill and tap the mounting holes . You can mount your 5V power supply , your arduino , all your electronics in the box and put a 120v AC Jack (like on a PC) for the power plug. You get power connector from Halted Specialty Surplus for the all the heater connections. Are you going to seal your DS18B20's in EPOXY ? Are you busing all the DS18B20's together ?

Have figured out how you're going to do the timers ?

This isn't the right section of the forum for timer questions because it is beyond the scope of Project Guidance so you might want to post a list of all the times in the Programming section . You can post in Mechanics and Power for help controlling the heaters.

In my opinion the overhead of LCDs is not their cost, but the extra work involved in connecting them and programming them. I see many sketches here where the problem is completely obscured by LCD code.

Leave the LCDs until you have a working system.

To learn about the timing process I suggest you write a short sketch which uses a few LEDs to simulate the different phases of the process. Write the initial code with short timings of a few seconds per step so that you can easily run through the whole process without needing a coffee break :). When it works you can increase the timings.

In case it hasn't been mentioned look at the technique in the Blink Without Delay example sketch. I have written a more extensive example here.

I have several LEDs with a resistor soldered to one leg and an extra piece of wire (the same length as the resistor) soldered to the other. I can plug them directly into the Uno or into a breadboard for quick and dirty testing.

...R

I guess if I have to boil my question down to the essence, it's "how should I change states, do I need a Finite State Machine, or is 'swich(case)' good enough?", and "how best to implement the best solution"?

You can use the FSM library, but you can just as well make your own system with switch case. Take a look at the library and see if you like it. Personally I'd stick to switch - YMMV. Search the forums - the subject has been discussed many times and you'll find example code - some of it relating to brewing.

Best solution? Without wishing to be awkward, it's very hard to say - what do you mean by best? Shortest, clearest, safest, easiest to understand, most adaptable? I really wouldn't worry much about this part until you have something working - it'll be a lot clearer to you then what at least makes a good solution for [u]you[/u]. Best can wait.

Robin2: In my opinion the overhead of LCDs is not their cost, but the extra work involved in connecting them and programming them. I see many sketches here where the problem is completely obscured by LCD code.

@ raschemmel, that's exactly what I mean by overhead. I don't want to do the programming since I'm not using it as my main control interface, though I may at some point in the future. Eventually, I may move on to a web interface with RasPi, in which case I'll need a local monitor in case the web goes down. For now, though, I'm all about the serial.

Leave the LCDs until you have a working system.

To learn about the timing process I suggest you write a short sketch which uses a few LEDs to simulate the different phases of the process. Write the initial code with short timings of a few seconds per step so that you can easily run through the whole process without needing a coffee break :). When it works you can increase the timings.

In case it hasn't been mentioned look at the technique in the Blink Without Delay example sketch. I have written a more extensive example here.

I have several LEDs with a resistor soldered to one leg and an extra piece of wire (the same length as the resistor) soldered to the other. I can plug them directly into the Uno or into a breadboard for quick and dirty testing.

...R

Thanks, that sounds like a good solution, I'll give that a try.

Are you going to seal your DS18B20's in EPOXY ? Are you busing all the DS18B20's together ?

I've got some stainless probe ds18b20s http://www.ebay.com/itm/3m-Digital-Thermal-Tank-Sensor-Horizontal-DS18B20-/230699845438 I am bussing them together onto a single digital pin

Search the forums - the subject has been discussed many times and you'll find example code - some of it relating to brewing.

I did some searching, but didn't see anything. I'll have another look - perhaps I'm looking in the wrong place/keywords?

Has anyone taken a look at the code I linked before? Any thoughts on the code, generally? Thanks for the feedback, JR

I am bussing them together onto a single digital pin

Do you have a 4.7k ohm pullup resistor to +5V on the output pin of the sensor ?

I am in San Jose too... also an avid brewer, working on a system of my own, as well as a kegbot. I sent you a private message but not sure if it went thru, should grab a beer sometime and talk about brewing. :)

I didn't get it.

For strike, I want to heat the water to a specified temp (say 152 degrees F), then I want to wait while I dump in some grain, then press a button and go to the next step - mash1. For mash 1, I want to hold a constant temp (150F) for a specified period of time, then go to the next step mash 2. For mash 2, I want to increase the temp to 160F, then start a timer and hold the temp for 30 minutes. Then I want to go to boil - get the temp to 212 then start a timer, stopping after 60 minutes.

It seems to me that if the process is purely sequential, then conditional or switch/case methods would be easier to use and follow. Push buttons (or serial commands) for “next >”, “< prev” could allow the operator to go 1 step forward or back in the process.

Just some food for thought … “beer for thought?”.

I think millis() could be useful..