Quentin Posted March 31, 2023 Share Posted March 31, 2023 I am trying to setup a PID loop with 5 different temperatures setpoints and 5 distinct durations for each setpoint. How do you suggest I proceed? The goal is to basically have a 5 setpoint entries on the page0 and 5 duration entries. The PID is controlling a relay that truns On/Off a heat pad. I am reading the temperature from a K-type thermocouple. I am using a labjack U6 Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted March 31, 2023 Share Posted March 31, 2023 You aren't talking about a PID loop but rather a ramp and soak, albeit presumably a steep (instant) ramp. The PID portion is totally separate and is just designed to maintain the current setpoint. You should start there. Create a variable to hold your current setpoint and setup a PID loop or script to control the relay to maintain the desired temperature. Note that with a relay, unless it is solid state you will likely NOT want to use PID, but instead do a simple thermostatic control. For PID to be effective it really needs an analog output, which can be achieved with a relay through PWM, but that is not advised with mechanical relays as they can't really handle the rapid switching, especially under load. Once you have it controlling at a particular setpoint, you can create two variables to hold the 5 target setpoints and durations. These are separate to the actual current setpoint that your loop is controlling to. Those two variables will be arrays, in your case with 5 elements each. So, for example, if the you wanted to step up from 25 to 45 in 5 degree increments with a duration of 60 seconds each as a default, you would do: global tempSPs = {25,30,35,40,45} global tempDuration = {60,60,60,60,60} (Note that you could use seqadd() and fill() functions instead of hard coding, but the above is clearer). You can then access any particular SP or duration using subsetting. So, the 3rd setpoint is: tempSPs[2] (everything is numbered from 0). Then you just need to create a sequence that ramps it. It is a rather simple sequence. Let's assume your control loop is using a global variable called "curSP" as the current setpoint it is controlling to. Then the sequence to (instantaneous) ramp and soak is simply: for (private i = 0, i < numrows(tempSPs), i++) curSP = tempSPs[i] delay(tempDuration[i] endfor Quote Link to comment Share on other sites More sharing options...
Quentin Posted March 31, 2023 Author Share Posted March 31, 2023 Thank you for the clairifications. Sorry I am very new to this... I confirm that I am using an SSR relay. Would it be possible to read in those setpoints and durations from the page0? And then how could I communicate with my relay to ask it to stop/restart when it has reach the setpoint in question. Would I write the script in the sequence or in the PID loop - event script? Example: Trying to reach 115 degrees and stay there for 2min, then 125 degrees and stay there for 3 min, then 135 degrees and stay there for 4min, then back to 120 and stay there for 5min and back to 110degrees and stay there for 5min with the minimum amount of overshoot. I have attached my .ctl Test2.ctl Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted March 31, 2023 Share Posted March 31, 2023 The script I provided will handle the ramp/soak which is what you describe in your example. My script, however, uses seconds, not minutes. You can use screen controls to edit the variables, tempSPs[0], tempSPs[1] etc, and tempDuration[0], tempDuration[1]... I do not recommend using edit boxes on the main page of any HMI (see ). You can use regular variable value controls with the Set To action. Separately you need to figure out the control. SSR means you could do PWM but you should figure out whether you really need it and a PID loop, or if a simple thermostatic control would work. That script would be as simple as: global tempHyst = 1 while(1) if (TC[0] > curSP) relay_control = 0 endif if (TC[0] < curSP - tempHyst) relay_control = 1 endif delay(1) endwhile This script should keep you within a degree of your SP (the tempHyst variable). Considering thermocouples have an accuracy of about +/- 1 degree C, you are probably good. To get tighter control you would first need to make sure your thermocouple was well calibrated and then you'd have to implement some PWM, again possible just in script instead of a PID. I personally find that most temperature control applications are easier to manage with simple scripts than PID. Quote Link to comment Share on other sites More sharing options...
Quentin Posted April 3, 2023 Author Share Posted April 3, 2023 Great, thank you! Two follow up questions: 1/ Where do I write this script? Sequence (which thread priority... PID?) or PID loop/ event tab? global tempHyst = 1 while(1) if (TC[0] > curSP) relay_control = 0 endif if (TC[0] < curSP - tempHyst) relay_control = 1 endif delay(1) endwhile 2/ Where can I read in the temperature setpoints from the page0 button/ set to as you suggested? How can IU communicate with the blue box/ "set point" input or do I have to add these directly from a sequence loop? If so can the button create a variable or I would have to create a distinct channel to store all of these values like in the exemple below? global tempSPs = {Temp1[0],Temp2[0],Temp3[0],Temp4[0],Temp5[0]} global tempDuration = {time1[0],time2[0],time3[0],time4[0],time5[0]} Quote Link to comment Share on other sites More sharing options...
Quentin Posted April 3, 2023 Author Share Posted April 3, 2023 More precisely, how can I use the PID built-in feature with multiple temperature setpoints? A simple ramp and soak as presented above is not satisfactory for my application... Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted April 4, 2023 Share Posted April 4, 2023 First decide. Do you want to use the built in PID or just do a thermostat? Remember, if you are going to do PID you will have to implement a PWM on that relay. A PID loop does not work well with simply on / off. Quote Link to comment Share on other sites More sharing options...
Quentin Posted April 4, 2023 Author Share Posted April 4, 2023 No I confirm that I need to implement a PID loop/ PWM in order to control more precisely the temperature of my casting ptocess Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted April 4, 2023 Share Posted April 4, 2023 OK. So first you'll need to get the digital output to work correctly per your other post. Once you have that you'll want to get a PWM setup. That is relatively straight forward in software, but you might consider using the LabJack's PWM feature of its counter. If so, refer to 10.5.1 of the DAQFactory - LabJack Application Guide PDF included with the DAQFactory download. For software PWM, I'm going to assume you are going to stick with the name "relay_control" for your output channel. In that case you will want to create a sequence. Call it, say, PWMRelayController: global relay_control_PWM = -100 // -100 to 100 while(1) relay_control = (systime() % 1) * 200 < (relay_control_PWM+100) delay(0.02) endwhile This gives a PWM with a period of 1 second and a resolution of 50 steps, which is probably plenty. You can mark this sequence Auto-Start and just let it run all the time. Then, you can change the new relay_control_PWM variable from -100 (always off) to 100 (always on) or anywhere in between and it will PWM the relay. The easiest way to see this is to create a graph of relay_control vs time. I chose -100 to 100 because those are the best numbers for the PID loop. The Output Channel of your PID loop will be the variable relay_control_PWM. Once you have that working, you can work on the PID loop. The process variable will be TC[0] or whichever channel has the temperature reading you are controlling. The output channel will be Relay_control_pwm as I mentioned. For now, set the setpoint manually to a single value, say 10. You can change it and hit Apply and it will update. We will work on doing your Ramp/Soak later. It is important that you get this part working first before making things more complicated. For anyone who wants to understand the logic of the PWM script I provided, specifically the 3rd line: (systime() % 1) returns a number between 0 and 1 corresponding to the decimal part of the current second. This gets multiplied by 200 to get it into the full range of relay_control_PWM (which as I mentioned should go from -100 to 100 because that is what the PID loop likes), so a number from 0 - 200 depending on when in the second the code gets executed. We then compare it to our current relay_control_PWM setting which we shift by 100 to make also 0-200. DAQFactory boolean is similar to other languages, where 1 is true, and 0 is false, so the result of that comparison sends a 0 or 1 to the actual relay output. Quote Link to comment Share on other sites More sharing options...
Quentin Posted April 5, 2023 Author Share Posted April 5, 2023 Ok so I changed it a little bit to make it simple. We determined we actually don't need the PWM at all. Now how do you suggest i setup multiple setpoints/ durations? Test2_debug.ctl Quote Link to comment Share on other sites More sharing options...
Quentin Posted April 5, 2023 Author Share Posted April 5, 2023 Could i set an series maybe using a button- "set to" action and then have my sequence loop iterate through each value for the delay in time1: Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted April 5, 2023 Share Posted April 5, 2023 Yes, that is what I did in my first post of this thread. CurSP would then be specified as the Set point of the PID loop. Quote Link to comment Share on other sites More sharing options...
Quentin Posted April 5, 2023 Author Share Posted April 5, 2023 Great! Like this then? Or do i need to setup globals first? while(1) for (private i = 0, i < numrows(tempSPs), i++) curSP = tempSPs[i] if(Out < 0) Relay_control[0] = 0 delay(0.02) else Relay_control[0] = 1 delay(0.02) endif delay(SPduration[i]) endfor endwhile Quote Link to comment Share on other sites More sharing options...
Quentin Posted April 5, 2023 Author Share Posted April 5, 2023 I would also like to have a live time gage to indicate the live delay, would that be possible to display on my page0? Quote Link to comment Share on other sites More sharing options...
Quentin Posted April 5, 2023 Author Share Posted April 5, 2023 Test2_debug.ctl Quote Link to comment Share on other sites More sharing options...
Quentin Posted April 5, 2023 Author Share Posted April 5, 2023 Found issue, my process variable dissapeared for no reason on PID1 but is present on PID2... Quote Link to comment Share on other sites More sharing options...
Quentin Posted April 6, 2023 Author Share Posted April 6, 2023 New issue, the if loop control the relay will only run once per for loop. i.e. it will iterate through the for loop run the if loop once and then wait for the delay to be completed. for (private i = 0, i < numrows(tempSPs), i++) curSP = tempSPs[i] if(Out < 0) Relay_control[0] = 0 delay(0.02) else Relay_control[0] = 1 delay(0.02) endif delay(tempDuration[i]) ?tempSPs[i] ?tempDuration[i] endfor What is required is for the if loop to actually run continuously during the whole delay of the for loop, would this work? for (private i = 0, i < numrows(tempSPs), i++) curSP = tempSPs[i] private startTime = systime() private elapsedTime = 0 while (elapsedTime < tempDuration[i]) if(Out < 0) Relay_control[0] = 0 delay(0.02) else Relay_control[0] = 1 delay(0.02) endif elapsedTime = systime() - startTime endwhile delay(tempDuration[i]) ?tempSPs[i] ?tempDuration[i] endfor Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted April 6, 2023 Share Posted April 6, 2023 You'd be best served by simply putting the relay control part inside its own sequence inside its own while() loop and just run that at the same time. Alternatively, you could just use the Event of the PID and control the relay directly. The other possibility is to put a Conversion on relay_control. It would just be: Value >= 0 Then if you set relay_control to any value > 0 it will turn on, but if you set it to any value < 0 it will turn off. Then you don't need the loop, the if() or even the Out channel and can simply have the PID update relay_control directly. Quote Link to comment Share on other sites More sharing options...
Quentin Posted April 11, 2023 Author Share Posted April 11, 2023 Ok great. Do you have an explaination for the issue of the process variable not showing up in the PID event graph/ figure? see Posted Wednesday at 11:15 PM Quote Link to comment Share on other sites More sharing options...
AzeoTech Posted April 11, 2023 Share Posted April 11, 2023 No idea, but that graph is just like the regular trend graph component on your pages. You can open its properties by double clicking on the center of it. Then check for three expressions. They all will start with "PID.PID1." and then you'll have PVHistory, OVHistory and SPHistory. Also check the axis scaling. As a side note, these variables, PID.PID1.PVHistory etc, are globally available so you can create your own graph of the PID parameters and their history on your own pages. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.