How to have currentMilis and previousMillis like arduino in Lua script - lua

I am writing an extremely simple script in Lua using simcom GPU.
It will count how many times a led flashing and return a string correspond to counter number. So far i have using os.clock() to do the job but the result is not as I expected.
function counter()
local t1 = os.clock()
while (ReadADC1() > 98) do
local t2 = os.clock()
local dt = t2 - t1
t1 = t2
local ledValue = ReadADC1()
if ((ledValue >= OnThreshHold) and (dt < 1)) then -- if led is on for less than 1 second
ledCounter = ledCounter + 1
--vmsleep(100)
elseif ((ReadADC1() < OnThreshHold) and (dt > 2.3)) then-- if led is off for more than 2 second
ledCounter = 0;
--vmsleep(100)
else
ledCounter = ledCounter
end
--print (ledValue,"\r\n")
end
print(ledCounter,"\r\n")
--return ledCounter
end
For this case, if i use this counter() function, it only work if the value from ReadADC() is input for short time then stop. It wont work if adc read continuously flow of data.
In arduino, the solution is extremely easy since you can use currentmillis and previousMillis to determine time pass between flashes. So in lua, do we have anything similar ?

Related

Reliable way of getting the exact decimals from any number

I'm having problem returning spesific amount of decimal numbers from this function, i would like it to get that info from "dec" argument, but i'm stuck with this right now.
Edit: Made it work with the edited version bellow but isn't there a better way?
local function remove_decimal(t, dec)
if type(dec) == "number" then
for key, num in pairs(type(t) == "table" and t or {}) do
if type(num) == "number" then
local num_to_string = tostring(num)
local mod, d = math.modf(num)
-- find only decimal numbers
local num_dec = num_to_string:sub(#tostring(mod) + (mod == 0 and num < 0 and 3 or 2))
if dec <= #num_dec then
-- return amount of deciamls in the num by dec
local r = d < 0 and "-0." or "0."
local r2 = r .. num_dec:sub(1, dec)
t[key] = mod + tonumber(r2)
end
end
end
end
return t
end
By passing the function bellow i want a result like this:
result[1] > 0.12
result[2] > -0.12
result[3] > 123.45
result[4] > -1.23
local result = remove_decimal({0.123, -0.123, 123.456, -1.234}, 2)
print(result[1])
print(result[2])
print(result[3])
print(result[4])
I tried this but it seems to only work with one integer numbers and if number is 12.34 instead of 1.34 e.g, the decimal place will be removed and become 12.3. Using other methods
local d = dec + (num < 0 and 2 or 1)
local r = tonumber(num_to_string:sub(1, -#num_to_string - d)) or 0
A good approach is to find the position of the decimal point (the dot, .) and then extract a substring starting from the first character to the dot's position plus how many digits you want:
local function truncate(number, dec)
local strnum = tostring(number)
local i, j = string.find(strnum, '%.')
if not i then
return number
end
local strtrn = string.sub(strnum, 1, i+dec)
return tonumber(strtrn)
end
Call it like this:
print(truncate(123.456, 2))
print(truncate(1234567, 2))
123.45
1234567
To bulk-truncate a set of numbers:
local function truncate_all(t, dec)
for key, value in pairs(t) do
t[key] = truncate(t[key], dec)
end
return t
end
Usage:
local result = truncate_all({0.123, -0.123, 123.456, -1.234}, 2)
for key, value in pairs(result) do
print(key, value)
end
1 0.12
2 -0.12
3 123.45
4 -1.23
One could use the function string.format which is similar to the printf functions from C language. If one use the format "%.2f" the resulting string will contain 2 decimals, if one use "%.3f" the resulting string will be contain 3 decimals, etc. The idea is to dynamically create the format "%.XXXf" corresponding to the number of decimal needed by the function. Then call the function string.format with the newly created format string to generate the string "123.XXX". The last step would be to convert back the string to a number with the function tonumber.
Note that if one want the special character % to be preserved when string.format is called, you need to write %%.
function KeepDecimals (Number, DecimalCount)
local FloatFormat = string.format("%%.%df", DecimalCount)
local String = string.format(FloatFormat, Number)
return tonumber(String)
end
The behavior seems close to what the OP is looking for:
for Count = 1, 5 do
print(KeepDecimals(1.123456789, Count))
end
This code should print the following:
1.1
1.12
1.123
1.1235
1.12346
Regarding the initial code, it's quite straight-forward to integrate the provided solution. Note that I renamed the function to keep_decimal because in my understanding, the function will keep the requested number of decimals, and discard the rest.
function keep_decimal (Table, Count)
local NewTable = {}
local NewIndex = 1
for Index = 1, #Table do
NewTable[NewIndex] = KeepDecimal(Table[Index], Count)
NewIndex = NewIndex + 1
end
return NewTable
end
Obviously, the code could be tested easily, simply by copy and pasting into a Lua interpreter.
Result = keep_decimal({0.123, -0.123, 123.456, -1.234}, 2)
for Index = 1, #Result do
print(Result[Index])
end
This should print the following:
0.12
-0.12
123.46
-1.23
Edit due to the clarification of the need of truncate:
function Truncate (Number, Digits)
local Divider = Digits * 10
local TruncatedValue = math.floor(Number * Divider) / Divider
return TruncatedValue
end
On my computer, the code is working as expected:
> Truncate(123.456, 2)
123.45

Calling a lua function at random time intervals in love2d

So basically I want to call a function in lua at random time intervals in love2d. Iam clueless of how to do this so any help is appreciated.
local t = math.random(MIN, MAX);
function love.update(dt)
t = t - dt
if t <= 0 then
FUNCTION()
t = math.random(MIN, MAX);
end
end
try:
function love.load()
Time = math.random(1, (max number here))
end
function love.update(dt)
Time = Time - dt
if Time < 0 then
-- magic
Time = math.random(1, (max number here))
end
end

How to run code whenever a value reaches a multiple of 50 in lua

Pretty simple, dont really have any code to give but just as an example:
local n = 0
local clock = os.clock
function sleep(n)
local t0 = clock()
while clock() - t0 <= n do end
end
while True do
sleep(1)
n = n + 1
(code to run when 'n' is a multiple of 50)
print("n is a multiple of 50")
end
Pretty simple, Any help appreciated!
not to wait for a long time, I took a small values:
local function sleep (a)
local sec = tonumber(os.clock() + a)
while os.clock() < sec do
end
end
local n = 0
while true do -- true~=True
sleep(1)
n = n + 1
print(n)
if n%5==0 then
print(n," - n is a multiple of 5")
end
if n>=10 then break end
end
and more: you need to wait for the result, when the script finishes working, such a feature of the Lua interpreter.

Rate limiting with lua

We have implemented redis based rate limiting for our web service which has been taken from here. I am duplicating the relevant code here.
local limits = cjson.decode(ARGV[1])
local now = tonumber(ARGV[2])
local weight = tonumber(ARGV[3] or '1')
local longest_duration = limits[1][1] or 0
local saved_keys = {}
-- handle cleanup and limit checks
for i, limit in ipairs(limits) do
local duration = limit[1]
longest_duration = math.max(longest_duration, duration)
local precision = limit[3] or duration
precision = math.min(precision, duration)
local blocks = math.ceil(duration / precision)
local saved = {}
table.insert(saved_keys, saved)
saved.block_id = math.floor(now / precision)
saved.trim_before = saved.block_id - blocks + 1
saved.count_key = duration .. ':' .. precision .. ':'
saved.ts_key = saved.count_key .. 'o'
for j, key in ipairs(KEYS) do
local old_ts = redis.call('HGET', key, saved.ts_key)
old_ts = old_ts and tonumber(old_ts) or saved.trim_before
if old_ts > now then
-- don't write in the past
return 1
end
-- discover what needs to be cleaned up
local decr = 0
local dele = {}
local trim = math.min(saved.trim_before, old_ts + blocks)
for old_block = old_ts, trim - 1 do
local bkey = saved.count_key .. old_block
local bcount = redis.call('HGET', key, bkey)
if bcount then
decr = decr + tonumber(bcount)
table.insert(dele, bkey)
end
end
-- handle cleanup
local cur
if #dele > 0 then
redis.call('HDEL', key, unpack(dele))
cur = redis.call('HINCRBY', key, saved.count_key, -decr)
else
cur = redis.call('HGET', key, saved.count_key)
end
-- check our limits
if tonumber(cur or '0') + weight > limit[2] then
return 1
end
end
end
I am trying to figure out the meaning of the comment -- don't write in the past
I don't see how a case would be possible where old_ts is greater than now
I have put logs all over the lua code but without any success.
At maximum old_ts can be equal to saved.trim_before which in turn can be equal to now if precision is 1 and blocks is 1. But not greater .
It would be helpful if someone has insights on it.
If you look at the gist provided in the article
https://gist.github.com/josiahcarlson/80584b49da41549a7d5c
There is comment which asks
In over_limit_sliding_window_lua_, should
if old_ts > now then
at here be
if old_ts > saved.block_id then
And I agree to this, the old_ts is supposed to have the bucket and when the bucket jumps to the next slot, that is when old_ts will be greater then than the block_id

How to time interval between event in lua

I am writing a simple script in lua. If the LED is on, it will increment the counter by 1. If the led is off for more than 1 seconds, it reset the counter.
So how exactly do we time event like that in lua ?
This is what i have and been testing multiple ways so far.
function ReadADC1()
local adc_voltage_value = 0
adc_voltage_value = tonumber(adc.readadc()) * 2 -- 0.10 --get dec number out of this -- need to know where package adc come from
--convert to voltage
adc_voltage_value = adc_voltage_value *0.000537109375 --get V
adc_voltage_value = math.floor(adc_voltage_value *1000 +0.5) --since number is base off resolution
--print (adc_voltage_value)
return adc_voltage_value
end
-- end of readADC1() TESTED
function interval()
local counter1 =0
ledValue = ReadADC1()
if (ledValue >= OnThreshHold) then
ledStatus = 1
t1=os.time()
else
ledStatus = 0
t2 = os.time()
end
--counter1 =0
for i=1,20 do
if (ledStatus == 1) then -- if led is off for more than 1 second, reset counter = 0
counter1 = counter1 + 1
elseif ((ledStatus ==0 and ((os.difftime(os.time(),t2)/100000) > 1000))) then -- increment counter when led is on
counter1 = 0
end
end
print (counter1)
end
I know for sure the logic for interval is wrong since os.time return a huge number (i assume it in psecond instead of second).
Any suggest or solution is welcome. I tried vmstarttimer and vmstoptimmer before this but not sure how it work.
EDIT:
function counter()
local ledValue = ReadADC1()
local t1 = os.clock()
while true do
local t2 = os.clock()
local dt = t2 - t1
t1 = t2
if ((ledValue < OnThreshHold) and (dt < 1)) then -- if led is off for less than 1 second
ledCounter = ledCounter + 1
elseif ((ledValue < OnThreshHold) and (dt > 1)) then-- if led is off for more than 1 second
ledCounter = 0;
else
ledCounter = ledCounter
end
print (ledCounter)
end
end
Ultimately, it will be return ledCounter instead of print counter since I will plug the value of counter to another function that will print a message correspond to the number of counter
You could use os.clock which returns your programs runtime since start in seconds.
Returns an approximation of the amount in seconds of CPU time used by the program.
Source
This function could be used in this way.
local t1 = os.clock() -- begin
local t2 = os.clock() -- end
local dt = t2 - t1 -- calulate delta time
-- or looped
local t1 = os.clock() -- begin
while true do
local t2 = os.clock() -- end
local dt = t2 - t1 -- calulate delta time
t1 = t2 -- reset t1
-- use dt ...
end
-- or wait for time elapsed
-- runs until 1 second passed
local t1 = os.clock()
while (os.clock() - t1) < 1 do
-- do stuff while dt is smaller than 1
-- could even reset timer (t1) to current to
-- repeat waiting
-- t1 = os.clock() | ...
end
-- logic for your example
function counter()
local time = os.clock()
local lastLedOn = false
local counter = 0
while true do
if os.clock() - time > 1.0 then
break
end
if getLedValue() == on then -- replace
time = os.clock()
if not lastLedOn then
lastLedOn = true
counter = counter + 1
-- print(counter) | or here if you want to print repeatedly
end
end
end
print(counter)
end -- was unable to test it

Resources