User Tools

Site Tools


useful_programs

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Next revisionBoth sides next revision
useful_programs [2020/02/21 13:46] – [Debug printing] emozolyakuseful_programs [2021/02/12 10:15] – [Processing double float numbers] emozolyak
Line 153: Line 153:
             Lp = ad / 2 ; Rp = Lp ; INFO("even parts, L R = " .. Lp .. s .. Rp)             Lp = ad / 2 ; Rp = Lp ; INFO("even parts, L R = " .. Lp .. s .. Rp)
         else          else 
-            Lp = math.floor(ad / 2) ; Rp = Lp + 1 ; INFO("not even L R " .. Lp .. s .. s .. Rp)+            Lp = math.floor(ad / 2) ; Rp = Lp + 1 ; INFO("not even L R " .. Lp .. s .. Rp)
         end          end 
         return (((d > 0) and {s1, s:rep(Lp) .. s2 .. s:rep(Rp)})          return (((d > 0) and {s1, s:rep(Lp) .. s2 .. s:rep(Rp)}) 
Line 181: Line 181:
    
             if (#h_row ~= #v_row) then              if (#h_row ~= #v_row) then 
-                ERROR("Inconsistent header and value rows in DBGnew!")+                ERROR("Inconsistent header and value rows in DBG!")
                 INFO("h_row:" .. tc(h_row)) ; INFO("v_row" .. tc("v_row"))                 INFO("h_row:" .. tc(h_row)) ; INFO("v_row" .. tc("v_row"))
                 return                  return 
Line 228: Line 228:
   end    end 
  
 +</code>
 +
 +For complex tables print, you can use the following function:
 +<code lua>
 +function tprint(t, indent)
 +    if not indent then indent = 0 end 
 +    for k, v in pairs(t) do 
 +        local formatting = string.rep(' ', indent) .. k .. ': '
 +        if type(v) == "table" then 
 +            ERROR(formatting) 
 +            tprint(v, indent + 1) -- recursive call 
 +        else
 +            if type(v) == "boolean" then 
 +                v = v and "TRUE" or "FALSE"
 +            end 
 +            ERROR(formatting .. v) 
 +        end 
 +    end -- for 
 +end -- tprint 
 </code> </code>
  
Line 608: Line 627:
 To determine intermediate positions, a calculated value is used, determined from the characteristics of the 'full path time', which can also be determined experimentally.   To determine intermediate positions, a calculated value is used, determined from the characteristics of the 'full path time', which can also be determined experimentally.  
  
-Below is a variant of 3-point control for a valve with 2 limit switches. +Below is a variant of 3-point control for a valve withoutlimit switches. 
  
 <code lua> <code lua>
-function main (userId)+function valveControl(v) 
 +     
 +    local FULL_PATH_TIME = R(v .. "pathTime") ; local KOEF = 100 / FULL_PATH_TIME 
 +    local HOMING_DELAY = R(v .. "homingDelay") * 60 * 60 -- get seconds from hours  
          
-       -- copy desired Tfeed to valve PID target temp. +    local auto, autoOpenCmd, autoCloseCmd, now =  
-    ( "HeatDistribution.targetTemperature",  ( "recalcFeedTemp" ))     +          TRUE("auto_mode"), TRUE(v .. "openCmd")TRUE(v .. "closeCmd"), os.time() 
 +                     
 +local motionTmr = function() -- calc. path quant passed from last call 
  
-now = os.time() -- global +    local quant = 0 
 +    if (autoOpenCmd or autoCloseCmd) then  
 +          quant = (now - R(v .. "motionTmr")) * KOEF ; SET(v .. "valveStatus") -- opening  
 +           
 +          if autoCloseCmd  then   
 +              quant quant * (-1)          -- closing  
 +              UpdReg(v .. "valveStatus", 2)  
 +          end  
 +    else  
 +          RESET(v .. "valveStatus") 
 +          quant = 0  
 +    end  -- if motion  
 +    UpdReg(v .. "motionTmr", now)     -- remember last call  
 +    return quant 
 +end -- motionTmr 
  
-local manOpenCmd, manCloseCmd = R("manOpenCmd"), R("manCloseCmd"    -- manual run flags +    local pos Limiter(Round(R(v .. "curPosition")) + motionTmr(), 0, 100) 
-local autoOpenCmd, autoCloseCmd R("autoOpenCmd"), R("autoCloseCmd") -- cmds to control valve +    local sp = R(.. "posSetpoint" 
-local openSw, closeSw = (R("valveOpenSw"== 1) , (R("valveCloseSw") == 1) +
-local pullUpFlag, pullDownFlag = (R("pullUpFlag") == 1 ), (R("pullDownFlag") == 1 )  ;  +
- +
-local curPosition = Round(R("valveCurPos") + MotionTimer(autoOpenCmd, autoCloseCmd, "Tmr5")) ; DEBUG("curPosition calc. as "..curPosition) +
- +
-                -- filtering cur position and check limit sw +
-if (curPosition >= 100) or openSw then  +
-    curPosition = 100  +
-        if openSw then  +
-            W ("pullUpFlag"1 ) +
-            pullUpFlag = true  +
-        end  +
-end  +
- +
-if ((curPosition < 0) or closeSw) then  +
-    curPosition = 0  +
-        if closeSw then  +
-            W ("pullDownFlag"1 )  +
-            pullDownFlag = true  +
-        end  +
-end  +
-                            -- pulling +
-if (curPosition == 100) and not (openSw) and not pullUpFlag then  +
-    curPosition = 99  ;                                             DEBUG(" pulling up")  +
-end  +
-if (curPosition == 0 ) and not (closeSw) and not pullDownFlag then  +
-    curPosition = 1   ;                                             DEBUG(" pulling down")  +
-end  +
- +
-W ("valveCurPos", curPosition) -- renew current position +
- +
-                                    -- AUTO MODE ----  +
-local valveSp = R ( "valveSp" )  ;                                     DEBUG("valveSp  "..valveSp)                                      +
-local positionError = (curPosition - valveSp)    +
- +
-if (positionError ~= 0) and ( autoOpenCmd ~= 1) and (autoCloseCmd ~= 1) then  +
-    -- reset pulling flags befor start  +
-    W ("pullDownFlag, 0 ); W ("pullUpFlag", 0) +
-end  +
- +
-if ( R ( "distribAutoMode") == 1) then +
          
-    W ("manOpenCmd"0 ) -- clear manual cmds +    local uShootoShoot = (pos < sp)(pos > sp
-    W ("manCloseCmd"0    +
          
-    if (positionError == 0)  then  +    local homingOut TRUE(v .. "homingTmr_out") 
-        W ("autoOpenCmd", 0 ) +    local homing Timer(not homingOut, HOMING_DELAY, FULL_PATH_TIME * 2, v .. "homingTmr") 
-        W ("autoCloseCmd", 0)  +    if not homingOut and homing then  
-    elseif (positionError > 0)   then  +        AddInfoMessage("Started homing for valve " .. v)
-                                    DEBUG("GO DOWN because positionError "..positionError) ; DEBUG(" math.abs error <= 0."..math.abs(positionError)) +
-        W ("autoOpenCmd",) +
-        W ("autoCloseCmd", 1) -- GO DOWN +
-         +
-    elseif (positionError < 0)  then  +
-                                    DEBUG("GO UP because positionError = "..positionError) ; DEBUG(" math.abs error <= 0.5 "..math.abs(positionError)) +
-        W ("autoOpenCmd", 1 ) -- GO UP +
-        W ("autoCloseCmd", 0)  +
-    else  +
-                                    DEBUG("Undefined if !!! in valve control ")+
     end      end 
-                                  --- MANUAL MODE -----  
-else                 
-                                  -- just copy manual cmd to valve auto cmd 
-    W ("autoOpenCmd", manOpenCmd ) 
-    W ("autoCloseCmd", manCloseCmd) 
          
-     if not openSw then  +    OUT(auto and uShoot and not homing or (not auto and TRUE(v .. "manOpenCmd")), v .. "openCmd") 
-        W ("autoOpenCmd", manOpenCmd )  +    OUT(auto and oShoot or homing or (not auto and TRUE(.. "manCloseCmd")) .. "closeCmd") 
-    else  +    UpdReg(.. "curPosition", pos)
-        W ("manOpenCmd", 0 ) +
-        W ("autoOpenCmd",) +
-        W ("valveCurPos"100) -- renew position after open limit sw +
-    end  +
-    if not closeSw then  +
-        W ("autoCloseCmd", manCloseCmd)  +
-    else  +
-        W ("manCloseCmd", 0)  +
-        W ("autoCloseCmd", 0)  +
-        W ("valveCurPos", 0) -- renew position after close limit sw +
-    end  +
-    +
-end  +
- +
-end -- main  +
- +
-function MotionTimer(openCmd, downCmd, tmrAlias) +
- +
-local FULL_PATH_TIME = 180 -- sec. full path time +
-local KOEF = 100 / FULL_PATH_TIME +
-local quant = 0  +
---[[                 bool        string  +
-remembers start time +
-recalc. micro path from the previous call if was in motion +
-adds micro path to current position  +
---                                                  open = true                                       ]]  +
-    local motion = { flag = ((openCmd == 1) or (downCmd == 1)), dir = (openCmd == 1), lastTimeStamp = R(tmrAlias)} +
-    DEBUG(" motion.flag = "..tostring(motion.flag).." dir  "..tostring(motion.dir)..os.date("%c"lastTimeStamp))  +
-    local outAlias = tmrAlias.."_out" +
-    local curTmrState = (R(outAlias) == 1) ; DEBUG("cur "..tmrAlias.." State =  "..tostring(curTmrState)) +
-                                                 +
-    if motion.flag then  +
-      quant = (now - R(tmrAlias)) * KOEF +
-          if not motion.dir then  +
-              quant = quant * (-1)  +
-          end  +
-                                                     DEBUG("quant calculated as = "..quant) +
-      W (outAlias, 1) -- "in motionflag +
-                                                     +
-    else  +
-                    DEBUG("no motion lasts = ") +
-      W (outAlias0  +
-      quant = 0  +
-    end  -- if +
          
-(tmrAliasnow)     -- rememeber last call time  +    DBG("auto sp pos autoOpenCmd autoCloseCmd uShoot oShoot ", '|',  
-return quant +           auto, sp, Round(pos, 1), autoOpenCmd, autoCloseCmd, uShoot, oShoot) 
- +end
-end -- function +
 </code> </code>
  
Line 833: Line 769:
             return false -- nothing happened              return false -- nothing happened 
 end -- P_TRIG  end -- P_TRIG 
 +
 +-- multiple ids or aliases read, returns table, have to be unpack() 'ed
 +-- usage: v1, v2, v3... = unpack(mRead(1, 2, 3, ...))
 +function mRead(...) 
 +     local results = {} 
 +     for i = 1, #arg do 
 +         local param = arg[i]
 +        --  INFO("processing " .. param .. " paramter")
 +          results[i] = GetReg(param)
 +     end 
 +     if (#results == 1) then 
 +         return results[1]
 +     else 
 +         return results
 +     end 
 +end 
 </code> </code>
  
Line 925: Line 877:
 </code> </code>
  
 +===== Curve handler =====
 +Library
 +<code lua - curves.lib>
 +function GetCurveValue ( curve_register, x_to_find_y  )
 +    --[[   
 +    --Curve handler 
 +    INPUT:
 +        Put curve register as first argument and X coordinate as second.
 +    OUTPUT:
 +        Get as result status if it is inside curve range of outside(false) and the Y value as second output argument
 +    
 +    EXAMPLE:
 +        curve_status, value = GetCurveValue( "curve_for_current_hour", current_hour )
 +    --]]
 +    table = cjson.decode( R ( curve_register ) )
 +    -- inRangeCurve( table, x_to_find_y )
 +    for _, value in ipairs( table ) do --piecewise handler inside range of the curve
 +        if ( value.range[1] <= x_to_find_y and x_to_find_y < value.range[2] ) then 
 +            -- in_range_status, index_curve_piece, y = true, index, curveLinearCalc( x_to_find_y, value.k, value.b )
 +            in_range_status, y = true, ( x_to_find_y * value.k + value.b )
 +            return in_range_status, y
 +        end
 +    end
 +    if  x_to_find_y < table[1].range[1] then -- behaivior for outside left-sided
 +        -- in_range_status, index_curve_piece, y = false, 1, curveLinearCalc( table[1].range[1], table[1].k*0, table[1].b ) --table[1].b
 +        in_range_status, index_curve_piece, y = false, 1, ( table[1].range[1] * table[1].k + table[1].b ) --table[1].b
 +        return in_range_status, y
 +    elseif x_to_find_y > table[#table].range[2] then -- behaivior for outside right-sided
 +        -- in_range_status, index_curve_piece, y = false,#table,curveLinearCalc( table[#table].range[2], table[#table].k, table[#table].b ) --table[#table].b
 +        in_range_status,  y = false,#table,( table[#table].range[2] * table[#table].k + table[#table].b)
 +        return in_range_status, y
 +    end
 +
 +    return in_range_status,
 +end
 +</code>
 +Example of usage:
 +<code lua - curves getter>
 +include "curves.lib"
 +
 +function main (userId)
 +
 +    local t = os.date("*t", os.time()) 
 +    current_hour = tonumber(t.hour)
 +    curve_status, y = GetCurveValue( "curve_for_current_hour", current_hour )
 +    WriteReg("value_for_current_hour", y) 
 +
 +end
 +</code>
 +
 +===== Processing double float numbers =====
 +
 +<code lua>
 +function d2float(n)  ----------------------- CONVERT DOUBLE FLOAT TO FLOAT ---------------------------
 +
 + local function getBits(input_num, length)  -- get number as table of bits 
 + -- works with number and len 
 + local tab = {}         
 + local max_i = length - 1                 
 + local remainder = input_num            -- rem of bitwise weighing 
 +   
 + for i = max_i, 0, -1 do
 + local bit_ = (remainder - 2^i >= 0) and '1' or '0'
 + table.insert(tab, bit_)           
 + end 
 + return tab
 + end 
 +
 + local function getNumberFromTab(tab, start, length)  -- get a number from table 
 + local result_str = ""
 +
 + for i = start, (start + length - 1) do 
 + result_str = result_str .. tostring(tab[i])
 + end 
 + return tonumber(result_str,2)
 + end 
 +
 + local NaN = tonumber("11111111111111111111111111111111", 2)
 + local result_tab = {} 
 +
 + -- get a table of "0" & "1"
 +   if (type(n) == "number") then 
 + result_tab = getBits(n, 64) 
 +   elseif (type(n) == "table") then 
 + local tmpS = ''
 + for i = 1, #n do 
 + tmpS = tmpS .. table.concat(getBits(n[i],8))
 + end 
 +  
 + for j=1, #tmpS do 
 + table.insert(result_tab, string.sub(tmpS, j, j))
 + end 
 + else 
 + ERROR("Unknown type for the d2float!")
 + end 
 +
 + local sign, exp, mantissa = 0, 0, 0
 + local fraction_table = {} -- fraction part table 
 +
 + sign = ((result_tab[1] == "1") and -1) or 1     -- get sign 
 + exp = getNumberFromTab(result_tab, 2, 11)       -- get exp 
 +
 + for i = 13, 64 do 
 + table.insert(fraction_table, result_tab[i]) -- mantissa
 + end 
 +
 + for j = 1, 52 do 
 + if (fraction_table[j]== "1") then 
 + mantissa = mantissa +(2 ^(-1 * j))    -- calc. mantissa by summing individual bits 
 + end 
 + end 
 + mantissa = mantissa + 1
 + local result_num = sign * (2 ^ (exp - 1023)) * mantissa
 +
 + ----------------------------------------- exceptions ----------------------------------
 + if exp == 0 then -- subnormals
 +    result_num = sign*(2^(-1022))*(mantissa-1)
 + end 
 +
 + if exp == 0x7ff then -- nan 
 +    result_num = NaN;
 + end 
 +   
 +   return result_num
 +end 
 +</code>
  
useful_programs.txt · Last modified: 2024/05/27 13:23 by emozolyak

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki