Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
documents:de4000:de4000script [2022/01/24 16:24] rocky [1. ] |
documents:de4000:de4000script [2022/01/25 16:22] (current) twebster |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | Scripting Reference Manual | + | =====DE-4000 |
- | DE-4000 | + | |
- | Form DE-4000 SRM 06-20 | + | |
+ | There is a delicate balance between providing a system that has capabilities that can be configured through a fixed set of options, and one that can be extended and expanded with custom programming. In designing the DE-4000 control system, the choice was made to provide a system where most applications can be met with simple configuration, | ||
- | DE-4000 SCRIPTING REFERENCE MANUAL | + | Lua is often referred to as a scripting language. |
- | + | ||
- | One overarching capability that allows | + | |
- | systems and the customer needs of innovation is scripting. A scripting language, | + | |
- | cleverly named Lua, is embedded into the DE-4000 system. It operates | + | |
- | mainly meaning that it does not need additional tools to convert | + | |
- | machine | + | |
- | runs. Therefore it is an “interpreted” language and runs all of the time when you ask it. | + | |
Lua comes with a background of being robust, fast, and geared towards embedded | Lua comes with a background of being robust, fast, and geared towards embedded | ||
applications, | applications, | ||
Line 44: | Line 37: | ||
- | ===== - ===== | + | ===== - Choose “Global” from menu on left side of screen |
- | Choose “Global” from menu on left side of screen | + | {{: |
- | ===== - ===== | ||
- | In the Sub-Menu on the Left side select “Scripts” | ||
- | ===== - ===== | + | ===== - In the Sub-Menu on the Left side select “Scripts” |
- | Select one of the page icons under one of the 4 script options to open editor | + | {{: |
- | ===== - ===== | ||
- | | ||
- | <markdown>### DE4000 Lua Script API | + | ===== - Select one of the page icons under one of the 4 script options to open editor ===== |
+ | {{: | ||
+ | |||
+ | ===== - Scripting can be entered into the editor ===== | ||
+ | {{: | ||
+ | |||
+ | |||
+ | **Scripting Windows and examples** | ||
+ | |||
+ | **Master Script** | ||
+ | {{: | ||
+ | Primary scripting functions can be written in this section. | ||
+ | |||
+ | **Example: | ||
+ | <code lua> | ||
+ | local suction = get_channel_val(1, | ||
+ | local discharge1 = get_channel_val(1, | ||
+ | diff = discharge1 - suction | ||
+ | set_sVirt(“Difference”, | ||
+ | </ | ||
+ | |||
+ | The first line gets the channel value from Terminal board 1 Input 1 and stores it | ||
+ | in local variable named suction. | ||
+ | The second line gets the channel value from Terminal board 1 Input 3 and stores | ||
+ | it in local variable named discharge1. | ||
+ | The third line takes the discharge1 pressure and subtracts the suction pressure | ||
+ | and stores it in the global variable named diff (NOTE: Any value that you want to | ||
+ | access from another scripting section must be stored in a global variable. This is | ||
+ | used most in calling values into Modbus registers as explained below). | ||
+ | The fourth line copies the value from diff and stores it into the Virtual status | ||
+ | channel named “Difference” This channel can be displayed on the Dashboard. | ||
+ | |||
+ | **Control Script** | ||
+ | {{: | ||
+ | The Control Script section is used to override the default control | ||
+ | strategy found on the Global/ | ||
+ | control script (found in attached appendix) can be copied into this | ||
+ | section and then modified to change the control functionality as well | ||
+ | as add additional control loops beyond the default 2. | ||
+ | |||
+ | {{: | ||
+ | |||
+ | **Modbus Script** | ||
+ | {{: | ||
+ | The Modbus Script section is used to move data into and out of | ||
+ | Modbus registers | ||
+ | |||
+ | {{: | ||
+ | |||
+ | <code lua> | ||
+ | defaultModbus() | ||
+ | set_modbus(300, | ||
+ | </ | ||
+ | |||
+ | The first line pulls in the factory set Modbus mapping | ||
+ | The second line moves the value from the global variable named diff into the | ||
+ | 40300 Modbus Register | ||
+ | |||
+ | ==== - DE4000 Lua Script API ==== | ||
+ | < | ||
+ | **CUSTOM FUNCTIONS FOR SCRIPTING** | ||
--- | --- | ||
Line 306: | Line 355: | ||
</ | </ | ||
+ | ==== - Master Control Script ==== | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | When you enter a control setup under the Global Control page the code that runs is called MasterControl. | ||
+ | |||
+ | If you wish to modify this functionality you can copy this code into the Control Script editor and{{ : | ||
+ | |||
+ | |||
+ | <file lua [enable_line_numbers=" | ||
+ | local rampRate1 = get_gbl(" | ||
+ | local rampRate2 = get_gbl(" | ||
+ | local dischTerm = tonumber_def(get_gbl(" | ||
+ | local dischChan = tonumber_def(get_gbl(" | ||
+ | local suctTerm = tonumber_def(get_gbl(" | ||
+ | local suctChan = tonumber_def(get_gbl(" | ||
+ | local suctMin = tonumber_def(get_gbl(" | ||
+ | local recycleMin = tonumber_def(get_gbl(" | ||
+ | local recycleMax = tonumber_def(get_gbl(" | ||
+ | local suctSp = tonumber_def(get_gbl(" | ||
+ | local dischMax = tonumber_def(get_gbl(" | ||
+ | local dischSp = tonumber_def(get_gbl(" | ||
+ | local outputTerm = tonumber_def(get_gbl(" | ||
+ | local outputChan = tonumber_def(get_gbl(" | ||
+ | local recycleTerm = tonumber_def(get_gbl(" | ||
+ | local recycleChan = tonumber_def(get_gbl(" | ||
+ | local speedRevAct = tonumber_def(get_gbl(" | ||
+ | local recycleRevAct = tonumber_def(get_gbl(" | ||
+ | local outputLow = tonumber_def(get_gbl(" | ||
+ | local outputLow2 = tonumber_def(get_gbl(" | ||
+ | local outputHigh = tonumber_def(get_gbl(" | ||
+ | local outputHigh2 = tonumber_def(get_gbl(" | ||
+ | local spSuctType = get_gbl(" | ||
+ | local spDischType = get_gbl(" | ||
+ | local suctPIDPFactor = tonumber_def(get_gbl(" | ||
+ | local suctPIDIFactor = tonumber_def(get_gbl(" | ||
+ | local suctPIDDFactor = tonumber_def(get_gbl(" | ||
+ | local dischPIDPFactor = tonumber_def(get_gbl(" | ||
+ | local dischPIDIFactor = tonumber_def(get_gbl(" | ||
+ | local dischPIDDFactor = tonumber_def(get_gbl(" | ||
+ | local recycleCtrl = false | ||
+ | local recycleSuctionRev = false | ||
+ | local recycleDischargeRev = false | ||
+ | if recycleChan > 0 and recycleTerm > 0 then | ||
+ | recycleCtrl = true | ||
+ | end | ||
+ | |||
+ | local dischPct = 100 | ||
+ | local suctPct = 100 | ||
+ | |||
+ | |||
+ | local dischOutput = 0 | ||
+ | local suctOutput = 0 | ||
+ | local rSuctOutput = 0 | ||
+ | local rDischOutput = 0 | ||
+ | local minLoad = 0 | ||
+ | local maxLoad = 100 | ||
+ | local minRecycle = 0 | ||
+ | local maxRecycle = 100 | ||
+ | local speedTarget = get_sGbl(" | ||
+ | local recycleTarget = get_sGbl(" | ||
+ | |||
+ | function map_range(rangeLow, | ||
+ | if input <= rangeLow and input <= rangeHigh then | ||
+ | return 0 | ||
+ | end | ||
+ | if input >= rangeLow and input >= rangeHigh then | ||
+ | return 100 | ||
+ | end | ||
+ | local rangeDiff = math.abs(rangeLow - rangeHigh) | ||
+ | local min = math.min(rangeLow, | ||
+ | local retval = math.abs(input - min) / rangeDiff * 100 | ||
+ | if retval > 100 then retval = 100 end | ||
+ | if retval < 0 then retval = 0 end | ||
+ | return retval | ||
+ | end | ||
+ | |||
+ | local suct = false | ||
+ | local suctVal = 0 | ||
+ | if tonumber_def(get_gbl(" | ||
+ | if suctTerm > 0 and suctChan > 0 then | ||
+ | suctVal = get_channel_val(suctTerm, | ||
+ | suct = true | ||
+ | end | ||
+ | end | ||
+ | |||
+ | |||
+ | if suct then | ||
+ | if spSuctType == " | ||
+ | local suctDiff = suctSp - suctMin | ||
+ | if suctDiff == 0 then suctDiff = 1 end | ||
+ | if suctVal < suctSp then | ||
+ | local suctErr = suctSp - suctVal | ||
+ | suctPct = suctErr / suctDiff | ||
+ | if suctPct > 1 then suctPct = 1 end | ||
+ | if suctPct < 0 then suctPct = 0 end | ||
+ | suctOutput = (1 - suctPct) * 100 | ||
+ | else | ||
+ | suctOutput = 100 | ||
+ | end | ||
+ | else | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | local suctPidOutput = doPid(" | ||
+ | suctOutput = suctPidOutput | ||
+ | end | ||
+ | else | ||
+ | suctOutput = 100 | ||
+ | end | ||
+ | |||
+ | |||
+ | local disch = false | ||
+ | local dischVal = 0 | ||
+ | if tonumber_def(get_gbl(" | ||
+ | if dischTerm > 0 and dischChan > 0 then | ||
+ | dischVal = get_channel_val(dischTerm, | ||
+ | disch = true | ||
+ | end | ||
+ | end | ||
+ | if disch then | ||
+ | if spDischType == " | ||
+ | local dischDiff = dischMax - dischSp | ||
+ | if dischDiff == 0 then dischDiff = 1 end | ||
+ | if dischVal > dischSp then | ||
+ | local dischErr = dischVal - dischSp | ||
+ | dischPct = dischErr / dischDiff | ||
+ | if dischPct > 1 then dischPct = 1 end | ||
+ | if dischPct < 0 then dischPct = 0 end | ||
+ | dischOutput = (1 - dischPct) * 100 | ||
+ | else | ||
+ | dischOutput = 100 | ||
+ | end | ||
+ | else | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | local dischPidOutput = doPid(" | ||
+ | dischOutput = dischPidOutput | ||
+ | end | ||
+ | else | ||
+ | dischOutput = 100 | ||
+ | end | ||
+ | |||
+ | | ||
+ | local minOutput = 100 | ||
+ | local winning = 0 | ||
+ | if suctOutput < minOutput then | ||
+ | minOutput = suctOutput | ||
+ | winning = 1 | ||
+ | end | ||
+ | if dischOutput < minOutput then | ||
+ | minOutput = dischOutput | ||
+ | winning = 2 | ||
+ | end | ||
+ | |||
+ | if suctOutput == dischOutput then | ||
+ | winning = 0 | ||
+ | end | ||
+ | |||
+ | if winning == 0 then | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | end | ||
+ | |||
+ | if winning == 1 then | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | end | ||
+ | if winning == 2 then | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | set_gbl(" | ||
+ | end | ||
+ | |||
+ | local recycleMinOutput = minOutput | ||
+ | |||
+ | local manOutput = 0 | ||
+ | --******************************************************************** | ||
+ | local manMode = 0 | ||
+ | local manTerm = tonumber_def(get_gbl(" | ||
+ | local manChan = tonumber_def(get_gbl(" | ||
+ | if manTerm > 0 and manChan > 0 then | ||
+ | local manInput = get_channel_val(manTerm, | ||
+ | if manInput > 0.5 then | ||
+ | manMode = 0 | ||
+ | set_sVirt(" | ||
+ | else | ||
+ | manMode = 1 | ||
+ | set_sVirt(" | ||
+ | end | ||
+ | else | ||
+ | if get_sVirt(" | ||
+ | manMode = 0 | ||
+ | else | ||
+ | manMode = 1 | ||
+ | end | ||
+ | end | ||
+ | |||
+ | --if manMode == 1 and get_state() == 8 then | ||
+ | local manSpeed = get_sVirt(" | ||
+ | local idleSpeed = get_gbl(" | ||
+ | local lowSpeed = get_gbl(" | ||
+ | local highSpeed = get_gbl(" | ||
+ | local maxSpeed = get_gbl(" | ||
+ | local diff = highSpeed - lowSpeed | ||
+ | if diff < 0 then diff = 0 end | ||
+ | local maxDiff = maxSpeed - idleSpeed | ||
+ | if maxDiff < 0 then maxDiff = 0 end | ||
+ | |||
+ | if get_sVirt(" | ||
+ | local si = get_gbl(" | ||
+ | local sip = get_param(" | ||
+ | if sip ~= 0 then si = sip end | ||
+ | manSpeed = manSpeed + (si * get_sVirt(" | ||
+ | set_sVirt(" | ||
+ | end | ||
+ | |||
+ | if get_sVirt(" | ||
+ | set_sVirt(" | ||
+ | set_sVirt(" | ||
+ | end | ||
+ | |||
+ | if get_sVirt(" | ||
+ | set_sVirt(" | ||
+ | set_sVirt(" | ||
+ | end | ||
+ | |||
+ | if manMode == 1 then | ||
+ | local manSpeedTerm = tonumber_def(get_gbl(" | ||
+ | local manSpeedChan = tonumber_def(get_gbl(" | ||
+ | if manSpeedTerm > 0 and manSpeedChan > 0 then --*** USE SPEED POT TO SET SPEED | ||
+ | local speedInput = tonumber(get_channel_val(manSpeedTerm, | ||
+ | local speedPct = (speedInput / 5) * 100 | ||
+ | if speedPct > 100 then speedPct = 100 end | ||
+ | if speedPct < 0 then speedPct = 0 end | ||
+ | manOutput = speedPct | ||
+ | manSpeed = math.floor((speedPct / 100) * diff + lowSpeed + 0.5) | ||
+ | else -- Use ManualSpeed to set speed | ||
+ | manOutput = ((manSpeed - lowSpeed) / diff) * 100.0 | ||
+ | if manOutput < 0 then manOutput = 0 end | ||
+ | if manOutput > 100 then manOutput = 100 end | ||
+ | end | ||
+ | minOutput = manOutput | ||
+ | else | ||
+ | --speedTarget = | ||
+ | local stRpm = (speedTarget/ | ||
+ | if stRpm < lowSpeed then stRpm = lowSpeed end | ||
+ | if stRpm > highSpeed then stRpm = highSpeed end | ||
+ | manSpeed = math.floor(stRpm) | ||
+ | end | ||
+ | |||
+ | if manSpeed < lowSpeed then | ||
+ | manSpeed = lowSpeed | ||
+ | end | ||
+ | if manSpeed > highSpeed then | ||
+ | manSpeed = highSpeed | ||
+ | end | ||
+ | |||
+ | set_sVirt(" | ||
+ | |||
+ | |||
+ | |||
+ | --******************************************************************** | ||
+ | |||
+ | |||
+ | local output1 = 0 | ||
+ | local output2 = 0 | ||
+ | if spSuctType == " | ||
+ | output1 = map_range(outputLow, | ||
+ | set_sVirt(" | ||
+ | output2 = map_range(outputLow2, | ||
+ | set_sVirt(" | ||
+ | local hasRPM = idleSpeed > 0 and lowSpeed > 0 and highSpeed > 0 and maxSpeed > 0 | ||
+ | if outputTerm and outputChan then | ||
+ | if hasRPM then | ||
+ | local speedRpm = output1 / 100 * (highSpeed - lowSpeed) + lowSpeed | ||
+ | speedTarget = (speedRpm - idleSpeed) / (maxSpeed - idleSpeed) * 100 | ||
+ | else | ||
+ | speedTarget = output1 | ||
+ | end | ||
+ | end | ||
+ | if recycleTerm and recycleChan then | ||
+ | set_ao_val(recycleTerm, | ||
+ | end | ||
+ | |||
+ | if get_state() == 9 then | ||
+ | speedTarget = get_sGbl(" | ||
+ | if speedTarget > 0 then speedTarget = speedTarget - rampRate1 end | ||
+ | if speedTarget < 0 then speedTarget = 0 end | ||
+ | end | ||
+ | if get_state() < 8 then speedTarget = 0 end | ||
+ | set_sGbl(" | ||
+ | set_ao_val(outputTerm, | ||
+ | set_sVirt(" | ||
+ | |||
+ | if hasRPM then | ||
+ | local sRpm = (speedTarget/ | ||
+ | set_sVirt(" | ||
+ | end | ||
+ | |||
+ | |||
+ | |||
+ | else | ||
+ | |||
+ | -- Remember that minOutput is 0 - 100 pct of lowSpeed <-> highSpeed | ||
+ | -- We need to convert this to 0 - 100 pct of idleSpeed <-> maxSpeed | ||
+ | local suctPct = map_range(outputLow, | ||
+ | local speedRpm = suctPct / 100 * (highSpeed - lowSpeed) + lowSpeed | ||
+ | minOutput = (speedRpm - idleSpeed) / (maxSpeed - idleSpeed) * 100 | ||
+ | |||
+ | |||
+ | |||
+ | if minOutput <= speedTarget then | ||
+ | speedTarget = speedTarget - rampRate1 | ||
+ | if speedTarget < minOutput then speedTarget = minOutput end | ||
+ | else | ||
+ | speedTarget = speedTarget + rampRate1 | ||
+ | if speedTarget > minOutput then speedTarget = minOutput end | ||
+ | if speedTarget > maxLoad then speedTarget = maxLoad end | ||
+ | end | ||
+ | if speedTarget > maxLoad then speedTarget = maxLoad end | ||
+ | if speedTarget < minLoad then speedTarget = minLoad end | ||
+ | |||
+ | if recycleCtrl then | ||
+ | local recyclePct = map_range(outputLow2, | ||
+ | if recyclePct <= recycleTarget then | ||
+ | recycleTarget = recycleTarget - rampRate2 | ||
+ | if recycleTarget < recyclePct then recycleTarget = recyclePct end | ||
+ | else | ||
+ | recycleTarget = recycleTarget + rampRate2 | ||
+ | if recycleTarget > recyclePct then recycleTarget = recyclePct end | ||
+ | end | ||
+ | if recycleTarget > maxRecycle then recycleTarget = maxRecycle end | ||
+ | if recycleTarget < minRecycle then recycleTarget = minRecycle end | ||
+ | local recycleOutput = recycleTarget | ||
+ | if get_state() < 8 then | ||
+ | recycleTarget = 0 | ||
+ | end | ||
+ | if recycleRevAct == 1 then | ||
+ | recycleOutput = 100 - recycleOutput | ||
+ | end | ||
+ | set_ao_val(recycleTerm, | ||
+ | set_sGbl(" | ||
+ | set_sVirt(" | ||
+ | end | ||
+ | |||
+ | if get_state() == 9 then | ||
+ | speedTarget = get_sGbl(" | ||
+ | if speedTarget > 0 then speedTarget = speedTarget - rampRate1 end | ||
+ | if speedTarget < 0 then speedTarget = 0 end | ||
+ | end | ||
+ | if get_state() < 8 then speedTarget = 0 end | ||
+ | set_sGbl(" | ||
+ | set_ao_val(outputTerm, | ||
+ | set_sVirt(" | ||
+ | local sRpm = (speedTarget/ | ||
+ | set_sVirt(" | ||
+ | |||
+ | |||
+ | end | ||
+ | |||
+ | </ |