• Please visit and share your knowledge at our sister communities:
  • If you have not, please join our official Homebrewing Facebook Group!

    Homebrewing Facebook Group

BruControl: Brewery control & automation software

Homebrew Talk

Help Support Homebrew Talk:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.
I was adding a Volume a sensor to my HLT. I had had a sensor port added to the vessel. I was thinking in how I could add a volume sensor to any vessel and realized that a simple Tee on the output of the vessel could take the volume sensor. No need for a special port.
Yeah, but keep in mind if that port leads to a pump (or any other flow through it, it will misread when there is flow.
 
On the ESP-32, On the Firmware 46+ Wiring Map

Pin: 0 BruControl Port: N/A Unishie;d UUE-1 Terminal: 1-3 (VA) : DOP I could see how this could be used as a One Wire Pin, but since there is no Port associated with the Pin, how do you access Digital I/O or a PWM output with BruControl?
 
Since the Analog Pins (A0-A15) on a Mega or Grand Central are A, D types, I assume you could use them like any other Digital Out, Digital In, (or PWM on the Grand Central for Pins A, D, P)?

So you could control an SSR relay as a Digital Output as the trigger voltage?
 
So you could control an SSR relay as a Digital Output as the trigger voltage?

Yes, in theory. But keep in mind that the GC is 3.3V and can only output very little current. With either, I'd use the driver output on the UniShield - it can handle the current for any SSR or relay (just make sure the voltages match).
 
I sort of asked this question before, but am unsure if I understand correctly. Can I delete the database file if it gets too large and I don't need the data? Will it then create a new file and start logging?
 
I sort of asked this question before, but am unsure if I understand correctly. Can I delete the database file if it gets too large and I don't need the data? Will it then create a new file and start logging?
You just lose the data. Since I have so many globals, I uninstalled the SQL so I no longer get a Database. It was really slowing down the loading of BruContol (Like 10 minutes). I was deleting mine every other day. So just delete at will. It only gets rid of any stored data. BruControl is going to fix the Globals to take care of a lot of the issues with the data base.
 
You just lose the data. Since I have so many globals, I uninstalled the SQL so I no longer get a Database. It was really slowing down the loading of BruContol (Like 10 minutes). I was deleting mine every other day. So just delete at will. It only gets rid of any stored data. BruControl is going to fix the Globals to take care of a lot of the issues with the data base.
Seconding this. Mine got really large as well, so I deleted it and did away with SQL. I have my brew stats pulled from Brucontrol by Node-RED and sent to Supabase (a free database like Firebase) and Brewfather, so I can see both historical and current data when needed. Saves me from very large files files.
 
I was asked about a basic Node-RED flow to get started with using BruControl's data exchange server. I figured I'd share the sample flow code here as well. Just copy the following code, then in Node-RED, go to the menu and select Import. Paste the code and click okay, and the flow will appear. It has the inject (which starts the flow), the HTTP request to BruControl, the JSON string -> object node, and some example Javascript functions.

I set the IP address to 127.0.0.1, which means the local machine (assuming Node-RED is on the same computer as BruControl). If Node-RED is on a different system, enter the IP of the PC that BruControl is on. The port is 8000, which is BruControl's data exchange port if enabled (and with the right license).

Where you see "Temp1" (in quotes) in the function nodes, you can enter the exact name of the BruControl global you want. Between the two function nodes, I show a For/Switch method and the method to arrange the BruControl response array to a standard JSON key/value pairing, from which you can call the specific BruControl name you want (a lot faster than many iterations in a For loop). For the For/Switch method, if you want to save more values, just enter another section of the following after my "Temp1" section:

case "BC Global Name":
whateverVariable = bcGlobals.Value;
break;


You will need to sort out declaring variables and decide what you are doing with that variable (learning about Node-RED globals is a good idea). Hopefully, for those of you who have wanted to play with the data exchange, this will get you started with calling BruControl data from Node-RED.

Note that you can call specific global data with 127.0.0.1:8000/global/Global%20Name (where %20 represents a space), but that gets you one value, and if you want multiple values, you will start having a crowded screen. I say get all of the globals and sort from there in a function.

JSON:
[
    {
        "id": "7393774e6b605aaf",
        "type": "tab",
        "label": "BruControl Flow",
        "disabled": false,
        "info": "",
        "env": []
    },
    {
        "id": "28f07e072a7d90f8",
        "type": "inject",
        "z": "7393774e6b605aaf",
        "name": "Start flow",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "300",
        "crontab": "",
        "once": true,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 110,
        "y": 80,
        "wires": [
            [
                "b45926e60e401fd4"
            ]
        ],
        "info": "This starts the flow at start and at an interval of 5 minutes."
    },
    {
        "id": "b45926e60e401fd4",
        "type": "http request",
        "z": "7393774e6b605aaf",
        "name": "HTTP Request to BC",
        "method": "GET",
        "ret": "txt",
        "paytoqs": "ignore",
        "url": "http://127.0.0.1:8000/globals",
        "tls": "",
        "persist": false,
        "proxy": "",
        "insecureHTTPParser": false,
        "authType": "",
        "senderr": false,
        "headers": [],
        "x": 300,
        "y": 80,
        "wires": [
            [
                "3dc90f4b793804ba"
            ]
        ],
        "info": "This makes a HTTP GET call to BruControl's data exchange server, running on port 8000."
    },
    {
        "id": "3dc90f4b793804ba",
        "type": "json",
        "z": "7393774e6b605aaf",
        "name": "Convert JSON String to Object",
        "property": "payload",
        "action": "",
        "pretty": false,
        "x": 550,
        "y": 80,
        "wires": [
            [
                "e594e165c8a55fc7",
                "0ea11e696e11d069",
                "81eab8e2366410d3"
            ]
        ],
        "info": "This will take the msg.payload variable (a JSON string after the HTTP request) and make it a browsable object."
    },
    {
        "id": "e594e165c8a55fc7",
        "type": "debug",
        "z": "7393774e6b605aaf",
        "name": "Show Full Response JSON Data in Debug Pane",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "payload",
        "targetType": "msg",
        "statusVal": "",
        "statusType": "auto",
        "x": 900,
        "y": 120,
        "wires": []
    },
    {
        "id": "0ea11e696e11d069",
        "type": "function",
        "z": "7393774e6b605aaf",
        "name": "Example Functions 1 (For/Switch)",
        "func": "bcGlobals = msg.payload;\n\nfor (let i = 0, l = Object.keys(bcGlobals).length; i < l; i++) { //Declare i and l, set l to the length of the array (starting from 0), go as long as i is less than l, increment i by one each cycle.\n    \n    switch (bcGlobals[i].Name){ //Check each array entry by setting the path to i, with the object key being Name.\n        case \"Temp1\": //Change the words between the quotes to your BC global name\n            node.warn('Temp 1 is: ' + bcGlobals[i].Value); //If the name matches, the value shows in the debug node.\n            msg.payload = bcGlobals[i].Value; //Sets msg.payload to the value\n            break; //Then the switch stops, going to the next For iteration.\n        // default: //Nothing found, so goes to default. However, in a For loop, it will state this for EVERYOTHER BC global entry, so don't uncomment this unless you know what you are doing.\n        //     node.warn('Nothing found.');\n        //     break;\n    }  \n} \n\nreturn msg; //Returns the message, meaning msg.payload moves forward with the new value.",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 860,
        "y": 40,
        "wires": [
            []
        ]
    },
    {
        "id": "81eab8e2366410d3",
        "type": "function",
        "z": "7393774e6b605aaf",
        "name": "Example Functions 1 (Get Specific Key Value from BC Name)",
        "func": "var arr = msg.payload; //arr for array\nvar temp1;\nvar bcGlobals;\n\n//The following lines rearranges the array into a standard JSON key/value pair via a string and then makes it an object.\nbcGlobals = '{' + arr.map(function(elem){ \n    return '\"' + elem.Name + '\":\"' + elem.Value + '\"'; }).join(\",\");\nbcGlobals = bcGlobals + '}';\nbcGlobals = JSON.parse(bcGlobals);\n\n\ntemp1 = bcGlobals['Temp1']; //Sets temp1 to the value of the BC global based on the global name. Change the name accordingly.\nnode.warn('Temp1 is ' + temp1); //Shows the value in the debug pane.\n\nmsg.payload = temp1; //Sets msg.payload to the temp1 value so it can carry forward.\n\n\nreturn msg; //Returns the message, meaning msg.payload moves forward with the new value.",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 940,
        "y": 80,
        "wires": [
            []
        ]
    }
]
 
Success: My Temp Probes are working with the TF-4 with the wires between the Mega 2560 and the TF-4 roughly 4' 8". I used Cat 5 Shielded wire and did not ground the shield on either end. The only ground was between the Mega and the GND on the TF-4 next to the VCC (5v from the Mega).

This is NOT a Recommendation but I had not purchased a big enough enclosure to house the Interfaces and the TF-4 so I needed to mount it in a different enclosure. That enclosure is metal and has M12 PANEL MOUNT QDs for the temp probes (M12 Quick Disconnect Panel Mount - Male from Brewers Hardware).

View attachment 809628
Hi Oakbarn - I am in the process of educating myself with Paint 3D in order to buid a half decent background containing my brewery's layout; I really like yours. I am assuming I could copy/paste it in Paint 3D and customize it as required?

Also, I notice small buttons next to your pumps - are these controlling the ON/OFF of the pump Element? If so - how can we link Button/Switches like that to Elements such as pumps?

Lastly, the digital temp gauges look neet; how to?

Cheers!
 
Hi Oakbarn - I am in the process of educating myself with Paint 3D in order to buid a half decent background containing my brewery's layout; I really like yours. I am assuming I could copy/paste it in Paint 3D and customize it as required?

Also, I notice small buttons next to your pumps - are these controlling the ON/OFF of the pump Element? If so - how can we link Button/Switches like that to Elements such as pumps?

Lastly, the digital temp gauges look neet; how to?

Cheers!
I used MS Paint (the old version on Windows 10. I can use the one on Win 11 but it is not as easy. I have dabbled with Paint 3D but cannot see any advantage over MS Paint (although you may be able to have transparent backgrounds but I have never figured out how).

My Brewery Kettles and piping is a single file used as a background for a workspace. I kept playing with it so it would fit and allow some message boxes and a large timer be on the left. Since it is a background, any Elements you Add are on top and the background cannot be moved.

I think you are talking about the LED buttons on the Pumps. These are just standard Digital Output Elements with the Appearance.value attribute set to LED. So yes they do control the pumps natively with the exception of the Yellow Pump.

My actual Yellow Pump Element is on another Workspace where I keep a lot of things. I have one Arduino Mega that I used to create "Pseudo" Elements. They are real Digital Outs on that Interface so I can make them look and act just like the ones on my Main Brewery Interface. That interface is not wired to anything except my router. I have Two "Pseudo" Elements for my Yellow pump because I have it on another Workspace as well and I want to control the Yellow pump from either Workspace. I do that with scripting.


Again, the digital temp gauges are built into BruControl. Analog Inputs for 10KNTC Probes. The Appearance.value attribute is set to Digital Gauge.

Other value attributes are also set:

gauge.png


The small SV and PV are simply Global String Element where the values are SV or PV or TG (Target).
 
Last edited:
OK cool, I was able to sort a few things; I now have the LED button and the digital guage for temps, very nice! A few things I haven't sorted out yet, such as what is a Global and String. I think I get the difference between an Element and a Variable in a script - Elements need to be enabled and Variables are to be declared as new in a script, but I'll leave that for now.

Back to the background image, for the below PID elements,I would like to keep the names and LED button, but get rid of the displayed info (circled in red); is this possible?
1676725921582.png
 
To get rid of the switch, click the "i" then go to Appearance>Enable Button Visibility>Never

To get rid of the "i" simply click the lock button in the upper right corner.
 
To get rid of the switch, click the "i" then go to Appearance>Enable Button Visibility>Never

To get rid of the "i" simply click the lock button in the upper right corner.
OK great, switch is gone. For the "i", I'm unable to find the lock button; is it in the "appearance" tab somewhere?
 
..... A few things I haven't sorted out yet, such as what is a Global and String. I think I get the difference between an Element and a Variable in a script - Elements need to be enabled and Variables are to be declared as new in a script, but I'll leave that for now.

?
Some general information:


  1. This is always a WORK In Progress
  2. Both Global Elements and a BruControl Variables are a type of variable.
  3. A Variable is like a place holder or container of some snippets of data. In a lot of cases, you use a variable because you are going to use it more than once.

Dictionary:

variable

noun
1: a quantity that may assume any one of a set of values
a symbol representing a variable
2: something that is variable
a factor in a scientific experiment that may be subject to change

In computers, a variable is a place to hold some snippet of data.


From Wikipedia:
What is a Variable?
Variables are used to store information to be referenced and manipulated in a computer program. They also provide a way of labeling data with a descriptive name, so our programs can be understood more clearly by the reader and ourselves. It is helpful to think of variables as containers that hold information. Their sole purpose is to label and store data in memory. This data can then be used throughout your program.

  1. Both of the terms are generally used in talking about variables in any computer language and they are similar in meaning to most computer languages. Most computer languages have local Variables and Global ones.
  2. All variables and Global Elements have some common attributes (properties) in BruControl:
    1. Type (Basically what kind of Data can it have)
      1. Boolean = True or False
      2. Value = a number
      3. String = Text (even if you put numbers here they are still text and not values)
      4. Time = a time
      5. DateTime = a Date and Time
    2. Scope: Where can they be used:
      1. Variables are script specific in Scope. It can only be used within the SAME Single Script where it was declared (created).
      2. Global Element is global in Scope. It can be used in any script.

  1. Persistent: Means how long the variable lasts.
Variables in BruControl are script persistent. That means as long as the script is running, the variable will last. You can clear the variable with a script command and kill it. You can also “assign” a value to a Variable so that it is available the next time you want to use it. If you have a Variable where you enter the data from the computer screen within BruControl, the data you entered is gone when the script is no longer running.

Global Elements are persistent and non volatile. They will be there even if you close BruControl and then reopen it the next day or next month.

Persistent refers to the container and not the data. The data can be changed at any time. If you do not change the data in a Global Element, it will still have that value when you open BruControl again.
4. The biggest differences between a Global Element and Variables are:
a. Scope
b. Persistent
c . Global Elements are used for DATA EXCHANGE (requires Professional License).
 
I just received my SM6004 Flow Meters; does this shematic make sense?

1676914891422.png
 

Attachments

  • SM6004.png
    SM6004.png
    62.4 KB
Some general information:


  1. This is always a WORK In Progress
  2. Both Global Elements and a BruControl Variables are a type of variable.
  3. A Variable is like a place holder or container of some snippets of data. In a lot of cases, you use a variable because you are going to use it more than once.

Dictionary:

variable

noun
1: a quantity that may assume any one of a set of values
a symbol representing a variable
2: something that is variable
a factor in a scientific experiment that may be subject to change

In computers, a variable is a place to hold some snippet of data.


From Wikipedia:
What is a Variable?
Variables are used to store information to be referenced and manipulated in a computer program. They also provide a way of labeling data with a descriptive name, so our programs can be understood more clearly by the reader and ourselves. It is helpful to think of variables as containers that hold information. Their sole purpose is to label and store data in memory. This data can then be used throughout your program.

  1. Both of the terms are generally used in talking about variables in any computer language and they are similar in meaning to most computer languages. Most computer languages have local Variables and Global ones.
  2. All variables and Global Elements have some common attributes (properties) in BruControl:
    1. Type (Basically what kind of Data can it have)
      1. Boolean = True or False
      2. Value = a number
      3. String = Text (even if you put numbers here they are still text and not values)
      4. Time = a time
      5. DateTime = a Date and Time
    2. Scope: Where can they be used:
      1. Variables are script specific in Scope. It can only be used within the SAME Single Script where it was declared (created).
      2. Global Element is global in Scope. It can be used in any script.

  1. Persistent: Means how long the variable lasts.
Variables in BruControl are script persistent. That means as long as the script is running, the variable will last. You can clear the variable with a script command and kill it. You can also “assign” a value to a Variable so that it is available the next time you want to use it. If you have a Variable where you enter the data from the computer screen within BruControl, the data you entered is gone when the script is no longer running.

Global Elements are persistent and non volatile. They will be there even if you close BruControl and then reopen it the next day or next month.

Persistent refers to the container and not the data. The data can be changed at any time. If you do not change the data in a Global Element, it will still have that value when you open BruControl again.
4. The biggest differences between a Global Element and Variables are:
a. Scope
b. Persistent
c . Global Elements are used for DATA EXCHANGE (requires Professional License).
Thanks for these explanation Oakbarn; I anticipate coming up with a few more queries as I continue with my scripting. I have a few scripts working now (Boil -over Control, HLT Fill and electric elements dry fire protection). After building the control panel and hooking up the various electrical devices, I find the scripting part - which is totally new to me- makes the Brucontrol a WOW software. I can see me sleeping at night with an automated mash infusion happening at the same time so I can save some time during my long brewdays..!!
 
Yes it requires 24VDC to power it and the resistor as mentioned above. If you are going to measure TEMPS above I believe 175F you will want to use a 232 OHM resistor on OUTPUT 1 so you don't burn out the A Input on the board
 
Feeding the SM6004 with +24VDC, 250 ohm resistor in series with the output 2.. makes sense?
To clarify further you would place on one side of the resistor Output 2 and Analog PIN on UNISHEILD and GROUND the other side of the resistor.
 
Back
Top