Homebrew Talk - Beer, Wine, Mead, & Cider Brewing Discussion Forum

Help Support Homebrew Talk - Beer, Wine, Mead, & Cider Brewing Discussion Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.

muhteeus

Well-Known Member
Joined
Sep 5, 2012
Messages
310
Reaction score
41
Location
Trophy Club
So, I started a PLC build way back when ('11-'12). The project fizzled out due to money, kids, life, etc...

In the mean time, I worked several automated builds surrounding Raspberry Pi, Python, and QT5. reef-pi and a homebrew saltwater mixing station for Aquarium use (or RODI brew water).

I spent some time researching Pi\Arduino based builds to control. These would be fun due to the integration of Controls and Interface that is more difficult on the ML1500\Advanced HMI system I designed.

So here we are. I have a working prototype of BruControl for semi-automation.

My goals are as follows:
  1. Simplify the brewday via automation to the point of keeping it fun but still engaging.
  2. Use my existing control panel from the TEB-PLC build.
  3. Hoses for now, but will eventually go to a hard plumbed system.
  4. Garage build for now, but want to approach a KAL-level "kitchen" build in terms of sophistication (e.g. wife likes it)
  5. Have fun.
As before with my build I will try to keep this open with full code, price lists, etc. I think communities like this thrive when people share. So hopefully this is something worth sharing. If all else fails it is a good point of reference for my brew-crew.
 
jrl52Dm.png
 
The Long Brew Script...
This is honestly pretty simple
I replicated the brew process from The Electric Brewery

PART 1
Code:
//    BrewBros script
//        v1.0 9/16/2019
//    Matias G.

[device setup] // setup elements with base values, disable loops, reset buttons and timers.
"System Status" Value = "Setting up devices"

//variables
new bool StartBrew
new bool StartStrike
new bool StartMash
new bool StartMashOut
new bool StartSparge
new bool StartBoil
new bool StartWhirlpool
new bool StartChill
new bool StartRack
StartBrew = False
StartStrike = False
StartMash = False
StartMashOut = False
StartSparge = False
StartBoil = False
StartWhirlpool = False
StartChill = False
StartRack = False

//elements and devices
"BK PID" Enabled = False //disable PID to prevent output
"HLT PID" Enabled = False //disable PID to prevent output
"BK Element Select" State = False
"HLT Element Select" State = False
"Water Pump" State = False
"Wort Pump" State = False
"Strike" Visibility = Hidden
"Mash" Visibility = Hidden
"MashOut" Visibility = Hidden
"Sparge" Visibility = Hidden
"Boil" Visibility = Hidden
"Whirlpool" Visibility = Hidden
"Chill" Visibility = Hidden
"Rack" Visibility = Hidden
"Step Time Alarm" Active = False

//temps
"Mash In Temp" Value = 155.0 //ballpark for mash in
"Mash Out Temp" Value = 168.0 //ballpark for mash out

//timers
reset "Step Timer"
stop "Step Timer"

//buttons
"Brew Start Btn" State = False
"Brew Start Btn" Visibility = Visible
"Strike OK Btn" State = False
"Strike OK Btn" Visibility = Hidden
"Mash Start Btn" State = False
"Mash Start Btn" Visibility = Hidden
"Sparge OK Btn" State = False
"Sparge OK Btn" Visibility = Hidden
"Boil OK Btn" State = False
"Boil OK Btn" Visibility = Hidden
"Hotbreak Btn" State = False
"Hotbreak Btn" Visibility = Hidden
"Whirlpool Btn" State = False
"Whirlpool Btn" Visibility = Hidden
"Chill OK Btn" State = False
"Chill OK Btn" Visibility = Hidden
"Rack Btn" State = False
"Rack Btn" Visibility = Hidden
"End Brew" State = False
"End Brew" Visibility = Hidden
"Done" State = False
"Done" Visibility = Hidden
"Acknowledge" Visibility = Hidden
sleep 1000

[varible def]
new value MashTemp
new time StepTime

[user setup] //wait for brewer to setup recipe, devices, and equipment
"System Status" Value = "Waiting for brewer: Check elements, devices, recipe, and equipment."
"System Step" Value = "Brewer setup"
wait "Brew Start Btn" state == true //wait for button press that Brewer is ready
    if "Brew Start Btn" state == true
        "System Status" Value = "BEER TIME!"
        "Brew Start Btn" Visibility = Hidden
        "Strike OK Btn" Visibility = Visible
        StartBrew = True
        "Strike" Visibility = Visible
        sleep 1000
        goto "strike water"
    endif
goto "user setup"

[strike water]//add sparge water to MLT and strike water to MLT
new string strikestatus
strikestatus = "Add " + "Strike Water Amount" Value
strikestatus += " gallons of water to MLT and "
strikestatus += "Sparge Water Amount" Value
strikestatus += " gallons of water to HLT."
"System Status" Value = strikestatus
"System Step" Value = "Fill vessels with water"
wait "Strike OK Btn" state == true //wait for button press that Brewer is ready
    if "Strike OK Btn" state == true
        goto "heat strike"
    endif
goto "user setup"

[heat strike]//heat strike and sparge water to strike temp, allow 5 min for mix
new string hs1status
hs1status = "Heat strike water to " + "Mash In Temp" Value
hs1status += " °F."
"System Status" Value =  hs1status
StartStrike = True
"HLT PID" Enabled = True
"HLT PID" target = "Mash In Temp" value
"Water Pump" State = True
"Wort Pump" State = True
"HLT Element Select" State = True
"Strike OK Btn" Visibility = Hidden
"System Step" Value = "Heating strike water"
[hs1]
    if "HLT PV" Value <= "Mash In Temp" Value
        sleep 1000
        goto "hs1"
    else
        sleep 1000  
        "Step Timer" Value = 00:00:05:00
        start "Step Timer"
        goto "hs2"
    endif
new string hs2status
hs2status = "Strike water is at " + "HLT PV" Value
hs2status += " °F. Waiting 5 min to stabilize."   
"System Status" Value = hs2status
sleep 1000
[hs2]  
    if "Step Time Alarm" Active == true
        "Acknowledge" Visibility = Visible
        stop "Step Timer"
        goto "mash in"
    else
        goto "hs2"

[mash in]//prep setup and stir grains
"System Status" Value = "Add grains to MLT and mix."
"System Step" Value = "Mashing in"
"Mash Start Btn" Visibility = Visible
StartStrike = False
wait "Mash Start Btn" state == true //wait for button press that Brewer is ready
    if "Mash Start Btn" state == true
        "System Status" Value = "OATMEAL TIME!"
        sleep 1000
        goto "mash"
    endif
goto "mash in"
 
Last edited:
Brew Script PART 2

Code:
[mash]//convert ugly starches to sexy sugars
new string mashstatus
mashstatus = "Converting starches to sugars. " + "Step Timer" Value
mashstatus += " elapsed."
"System Status" Value = mashstatus
"System Step" Value = "Mashing in"
"Step Timer" Value = "Mash Timer" Value
"Mash Start Btn" Visibility = Hidden
StartMash = True
"Mash" Visibility = Visible
start "Step Timer"
sleep 1000
[m1]
    if "Step Time Alarm" Active == true
        "Acknowledge" Visibility = Visible
        stop "Step Timer"
        goto "mash out"
    else
        sleep 1000
        goto "m1"
    endif

[mash out] //heat to mashout temp
"HLT PID" target = "Mash Out Temp" value
"Wort Pump" State = False
"System Status" Value = "Start heating to 168°F."
"System Step" Value = "Mashing out"
StartMash = False
StartMashOut = True
"MashOut" Visibility = Visible
    if "HLT PV" Value < "Mash Out Temp" Value
        sleep 1000
        goto "mash out"
    else
        "Wort Pump" State = False
        "Water Pump" State = False
        sleep 1000  
        goto "sparge setup"
    endif

[sparge setup] //move hoses and ****
"System Status" Value = "Setup hoses and flow to sparge to BK."
"System Step" Value = "Setup for Sparge"
"Sparge OK Btn" Visibility = Visible
wait "Sparge OK Btn" state == true //wait for button press that Brewer is ready
    if "Sparge OK Btn" state == true
        goto "sparge"
    endif

[sparge]//collect sugars, push through HLT -> HERMS -> MT -> BK
new string spargestatus
new value preboilvol
preboilvol = "Sparge Water Amount" Value + "Strike Water Amount" Value
spargestatus = "Sparge " + "Strike Water Amount" Value
spargestatus += " gallons of strike water and "
spargestatus += "Sparge Water Amount" Value
spargestatus += " gallons of sparge water for a combined preboil volume = "
spargestatus += preboilvol
spargestatus += " gallons."
"System Status" Value = spargestatus
"System Step" Value = "Sparge to BK."
"Sparge OK Btn" Visibility = Hidden
"Sparge" Visibility = Visible
StartSparge = True
StartMashOut = False
"Step Timer" Value = "Sparge Timer" Value
start "Step Timer"
"Water Pump" State = True
"Wort Pump" State = True
sleep 1000
[sp1]
    if "Step Time Alarm" Active == true
        "Acknowledge" Visibility = Visible
        stop "Step Timer"
        goto "setup boil"
    else
        goto "sp1"
    endif

[setup boil]//move hoses again and ****
"System Status" Value = "Ensure PIDs are correct! Ensure elements are isolated!"
"System Step" Value = "Setting up for boil."
"Water Pump" State = False
"Wort Pump" State = False
"HLT PID" Enabled = False
"HLT Element Select" State = False
"HLT PID" Target = 0.0
"Boil OK Btn" Visibility = Visible
wait "Boil OK Btn" state == true //wait for button press that Brewer is ready
    if "Boil OK Btn" state == true
        goto "heat bk"
    endif
goto "heat bk"

[heat bk]//start heating to boil
"System Status" Value = "Begin heating BK for boil."
"System Step" Value = "Waiting for hotbreak."
"BK PID" Enabled = True
"BK PID" MaxOutput = 100 //user should be able to adjust this
"BK Element Select" State = True
"Hotbreak Btn" Visibility = Visible
"Boil OK Btn" Visibility = Hidden
sleep 1000
wait "Hotbreak Btn" state == true //wait for button press that Brewer is ready
    if "Hotbreak Btn" state == true
        goto "boil"
    endif
goto "boil"

[boil]//the boil really begins
"Step Timer" Value = "Boil Timer" Value
"System Status" Value = "Boil."
"System Step" Value = "Boil."
"BK PID" MaxOutput = 80 //user should be able to adjust this
"Hotbreak Btn" Visibility = Hidden
"Boil" Visibility = Visible
StartBoil = True
StartSparge = False
start "Step Timer"
sleep 1000
[b1]
    if "Step Time Alarm" Active == true
        "Acknowledge" Visibility = Visible
        stop "Step Timer"
        goto "whirlpool"
    else
        sleep 1000
        goto "b1"

[whirlpool]
"System Status" Value = "Circulate to clarify for 15 min."
"System Step" Value = "Whirlpool."
"BK PID" Enabled = False
"BK Element Select" State = False
"Wort Pump" State = True
"Whirlpool Btn" Visibility = Visible
StartBoil = False
wait "Whirlpool Btn" state == true
"Whirlpool Btn" Visibility = Hidden
"Whirlpool" Visibility = Visible
StartWhirlpool = True
"Step Timer" Value = 00:00:15:00
start "Step Timer"
[w1]
    if "Step Time Alarm" Active == true
        "Acknowledge" Visibility = Visible
        stop "Step Timer"
        goto "chill"
    else
        sleep 1000
        goto "w1"

[chill]
"System Status" Value = "Setup hoses for recirculation through plate."
"System Step" Value = "Chilling"
"Chill OK Btn" Visibility = Visible
"Wort Pump" State = False
StartWhirlpool = False
wait "Chill OK Btn" State == True
StartChill = True
"Chill" Visibility = Visible
"Chill OK Btn" Visibility = Hidden
"System Status" Value = "Recirculate wort to cool."
"System Step" Value = "Chilling"
"Wort Pump" State = True
[ch1]
if "Kettle PV" Value > 80.0
    sleep 1000
    goto "ch1"
else
    "Wort Pump" State = False
    sleep 1000
    goto "rack"

[rack]
"System Status" Value = "Setup hoses to go through plate to fermenter."
"System Step" Value = "Rack to Ferm."
"Rack Btn" Visibility = Visible
StartChill = False
wait "Rack Btn" state == true //wait for button press that Brewer is ready
    if "Rack Btn" state == true
        goto "racking"
    endif
goto "rack"

[racking]
"Rack Btn" Visibility = Hidden
StartRack = True
"Rack" Visibility = Visible
"System Status" Value = "Transferring wort to fermenter. When empty press 'End Brew' to stop."
"System Step" Value = "Rack to Ferm."
"End Brew" Visibility = Visible
"Wort Pump" State = True
wait "End Brew" state == true //wait for button press that Brewer is ready
    if "End Brew" state == true
        goto "done"
    endif
goto "end brew"

[done]
"System Status" Value = "Press Done to reset."
"System Step" Value = "Brew Complete!"
StartRack = False
"Done" Visibility = Visible
"End Brew" Visibility = Hidden
"Wort Pump" State = False
StartBrew = False
wait "Done" state == true //wait for button press that Brewer is ready
    if "Done" state == true
        goto "device setup"
    endif
goto "device setup"

Some cleanup likely needs to be done. My wait for user input steps work fine with just the wait command.... Also some errors throughout as far as spelling etc.

I want to work on Addition Timers, recipe import, and PFD displays by step.
 
Last edited:
2 Super Dumb Scripts that do what I need them to

Alarm Silence
Code:
//poor man alarm reset
"Acknowledge" State = False
[start]
if "Acknowledge" State == True
    "Step Time Alarm" Active = False
    sleep 1000
    "Acknowledge" State = False
    "Acknowledge" Visibility = Hidden
    goto "start"
else
    goto "start"

ELEMENT OUTPUTS
Code:
[loop]
"BK Element" State = "BK Element Select" State
"HLT Element" State = "HLT Element Select" State
goto "loop"
 
Since your SSR’s are inside, they will need access to air. I would separate them from the contactors right next to them to allow air to get to them.

Also, good intent to separate the high and low voltage stuff.
 
Since your SSR’s are inside, they will need access to air. I would separate them from the contactors right next to them to allow air to get to them.

Also, good intent to separate the high and low voltage stuff.

Yeah I wish I got a larger panel. Not sure where to move the SSRs? I planned to install the intake fan close to them. I think I could move the contactors the the second DIN rail.

24q6Glk.png
 
You could move the SSRs to a heatsink mounted on the side or top of the enclosure.

I saw this done on Kal's build as well. I have a gland plate I could easily modify to install sinks.... I just don't want to run 10awg across the panel and down. The sides are too crowded as well. I will see if there is something easier.
 
I just realized that my main contactor and breaker are sized for 25A. Sigh.

Ordered 32A breaker and 63A contactor from Electric Brewing Supply.
 
240VAC and 120VAC wiring prints. I didn't put the SSRs in yet... have to generate the MEGA2560 in AutoCAD...
 

Attachments

  • eHerms-001.pdf
    102.5 KB · Views: 95
I am stalled out since my last drill battery died. I lack a few holes in the panel and some threaded taps for a couple pieces of wireway. I also have to cut for L6-30, L5-15, XLR, USB, ETHERNET, and a few general use holes for IO

Then we are on to wiring, painting, and assembly.
 
Hopefully this is accurate. From what I have been reading I can pass 5V to the board via the 5V pin on the MEGA.

DawRJvl.png

wmmhwzX.png

NwS5FqF.png
 

Attachments

  • eHerms-000.pdf
    122.3 KB · Views: 56
  • eHerms-001.pdf
    126.4 KB · Views: 41
  • eHerms-002.pdf
    22 KB · Views: 42
  • eHerms-003.pdf
    19.2 KB · Views: 43
Comments:
1. Why spa panel? In your main breaker panel, put the GFCI there.
2. In your box you have a 32A breaker... is that the max power you will use? If it is a 50A feed (with 6 AWG wire), why not skip the breaker and allow for the full 50A (simultaneous elements)?
3. Not a requirement, but I'd personally use SSR's for any 120V loads like your pumps or contactor coils.
4. I honestly can't say I've looked exhaustively... It's proper to use labels, but hard & time consuming (for me) to cross check the bus lines by label.
 
1. Old panel. The Spa panel is cheaper at $80-90. If I didn't have so many dual pole breakers in my breaker box I would just replace the whole thing.
2. No need for 50A at the moment, but I wanted the ability to go bigger in the future, though I guess I could wire this for back to back right away? I don't plan on doing more than 10 gallon single batches any time soon.
3. I had the board laying around. I prefer SSRs over coils. I may replace these in the long run.
4. The bus lines just follow the pages, L-R and page to page. But I feel you.

Thanks for taking the time to look over this!
 
You could move the SSRs to a heatsink mounted on the side or top of the enclosure.
this is what I did for my 3bbl controller (ignore the contactor/breaker placement in the pic I ended up replacing all non UL listed contactors and rearranging all of this after this photo)
20180430_082639.jpg
I used NO/NC relays as well as ssrs in conjuntion with dual pole contactors for safety and to make sure only certain components can be on at one time. Also Ive had ssrs fail and stick in the on position..
 
Last edited:
20180822_173734.jpg
found a newer pic... as you can see its always better to go bigger than you think you need on a panel.. it gets crowded.. Itt will be even more so after next week as I have 2 70" long 4000w cartridge heaters for my new rims setup for faster ramping.

BTW you can find brand name quality UL listed stuff on ebay cheaper. or you can get the same exact rebranded generics your ordering now at about 2/3 the cost.. the CE certified contactor in my first pic were about $7 each shipped for DP and $5 for SP.. They worked fine but since mine is being used in a brewery it needed the components (above 50v) to all be UL listed.. I did have to ad diodes to the contactor coils because of noise.
 
Last edited:
View attachment 647585 found a newer pic... as you can see its always better to go bigger than you think you need on a panel.. it gets crowded.. Itt will be even more so after next week as I have 2 70" long 4000w cartridge heaters for my new rims setup for faster ramping.

BTW you can find brand name quality UL listed stuff on ebay cheaper. or you can get the same exact rebranded generics your ordering now at about 2/3 the cost.. the CE certified contactor in my first pic were about $7 each shipped for DP and $5 for SP.. They worked fine but since mine is being used in a brewery it needed the components (above 50v) to all be UL listed.. I did have to ad diodes to the contactor coils because of noise.

Thank you for this! I have been dying to see inside of your nano setup for awhile!

I honestly will need a larger panel to keep things isolated and provide the protection I want to include. I am using the remains of my old project that had 2 panels so the AC and DC components were isolated in 2 boxes. In addition, BruControl (as a best practice) requires many different DC sources. So once I get this build up and running, I will quickly be planning the Phase 2 upgrade (finances pending).

Your panels are beautiful by the way!
 
Thank you for this! I have been dying to see inside of your nano setup for awhile!

I honestly will need a larger panel to keep things isolated and provide the protection I want to include. I am using the remains of my old project that had 2 panels so the AC and DC components were isolated in 2 boxes. This was easy because the PLC panel was used and was essentially pre-wired and marshalled. I will only be using 1 panel for BruControl

In addition, BruControl (as a best practice) requires many different DC sources. So once I get this build up and running, I will quickly be planning the Phase 2 upgrade (finances pending).

Your panels are beautiful by the way!
 
2 Super Dumb Scripts that do what I need them to

Alarm Silence
Code:
//poor man alarm reset
"Acknowledge" State = False
[start]
if "Acknowledge" State == True
    "Step Time Alarm" Active = False
    sleep 1000
    "Acknowledge" State = False
    "Acknowledge" Visibility = Hidden
    goto "start"
else
    goto "start"

ELEMENT OUTPUTS
Code:
[loop]
"BK Element" State = "BK Element Select" State
"HLT Element" State = "HLT Element Select" State
goto "loop"

Hi there,
I am just a beginner trying to find my way around.
I find your post immensely helpful and educational.

Would you copy paste/ attach your latest version of the code.?
 
Back
Top