Let’s heat things up with Dash DAQ! With this application, we use Python to monitor and manage a PID controller connected to a water heater 🔥
Play with the demo app, and keep reading to learn how we did it!
We used our PID controller (center-left) to manage a simple water heater (right). The water temperature, measured by the thermocouple in the water heater, is the PID controller’s input. In response to the temperature input, the controller outputs 10 VDC pulses to a DC-AC solid state relay (center-right), which acts as a switch between the water heater and its 110 VAC power source (upper left). Thus, the water heater only heats (or cools) when the temperature varies from a desired setpoint, entered in the GUI on your laptop (bottom left).
If you are curious about the hardware or need some help, check out the Omega CN32PT-440-DC user manual here.
The Dash DAQ app
The GUI components of our app allow the user to accomplish several tasks. In this post, we’ll focus on the first three of the following:
- read and display the water temperature
- change the refresh rate of the graph
- manually or automatically tune PID gains
- choose whether the controller is heating or cooling
- change the thermocouple type and sensitivity (known as “filter rate”)
To write our Python code, first we need to import some libraries. We use MinimalModbus, Pandas, NumPy, Dash DAQ, datetime, and Plotly libraries.
There are three data types used with the device’s Modbus communications protocol: single 16 bit register, dual 32 bit register, and IEEE floating point values. We’ll talk about these later.
The app layout
Dash DAQ’s versatile UI components make the app layout easy to put together. Check out the block of code below, containing the Dash DAQ StopButton and Indicator components, plus an HTML title element.
The app callbacks
The output mode of the PID controller is easily controlled with Dash callbacks. You can control whether the output is off, or triggered by the PID, with this short block of code.
Using the MinimalModbus library, the command
ser.write_register writes an enumerated value to a single 16-bit register (indicated as
1025 in the code), telling the device what output mode to be in.
We also use a callback to read the temperature from the thermocouple. By reading the 32-bit register (indicated as
528 in the code), we receive the current temperature reading from the PID controller. The temperature value can be sent to other GUI components, such as the Dash DAQ LEDDisplay.
To control the rate at which we receive and display the temperature data, we use a Dash core component, Interval, which is called
"graph-interval" in the code.
This PID controller comes with an auto-tune option, to automatically set the proportional, integral, and derivative gains of your device. It’s important to note that auto-tune does not work with all systems, and you may have to manually configure the PID parameters of the controller. We can do this with our app.
In the code below,
ser.write_register(579 ... ) force-starts the auto-tune process. In this callback, we can see all the different data types that we mentioned above, which are used to communicate with the PID controller’s Modbus protocol.
ser.write_float(686 ...) writes an IEEE float to register 686. The value of
max_rate is the result of another callback, called
"max-rate-auto", which retrieves the user’s input for this setting from the GUI.
ser.write_long(674 ...) writes to a 32-bit register. The value of
autotune_timeout is the result of another callback, which retrieves whatever the user entered in the GUI as the auto-tune timeout value.
This app shows you the possibilities Dash DAQ offers for creating interactive GUIs to control and read all sorts of hardware.