Lua: Calling functions in own module - lua

I created a module for an RTC. It looks like this:
local moduleName = ...
local M = {}
_G[moduleName] = M
---------- Local variables ---------------------
local id = 0
local address = 0x68
---------- Helper functions --------------------
local function bcdToDec(val)
local hl=bit.rshift(val, 4)
local hh=bit.band(val,0xf)
local hr = string.format("%d%d", hl, hh)
return string.format("%d%d", hl, hh)
end
local function decToBcd(val)
local d = string.format("%d",tonumber(val / 10))
local d1 = tonumber(d*10)
local d2 = val - d1
return tonumber(d*16+d2)
end
---------- Module functions --------------------
function M.Init(sda, scl)
i2c.setup(id, sda, scl, i2c.SLOW)
end
function M.PrintTime()
i2c.start(id)
i2c.address(id, address, i2c.TRANSMITTER)
i2c.write(id, 0x00)
i2c.stop(id)
i2c.start(id)
i2c.address(id, address, i2c.RECEIVER)
c=i2c.read(id, 7)
i2c.stop(id)
s = bcdToDec(string.byte(c,1))
m = bcdToDec(string.byte(c,2))
h = bcdToDec(string.byte(c,3))
time=string.format(" %s:%s:%s", h, m, s)
print(time);
end
function M.PrintDate()
i2c.start(id)
i2c.address(id, address, i2c.TRANSMITTER)
i2c.write(id, 0x00)
i2c.stop(id)
i2c.start(id)
i2c.address(id, address, i2c.RECEIVER)
c=i2c.read(id, 7)
i2c.stop(id)
s = bcdToDec(string.byte(c,1))
m = bcdToDec(string.byte(c,2))
h = bcdToDec(string.byte(c,3))
wkd = bcdToDec(string.byte(c,4))
day = bcdToDec(string.byte(c,5))
month = bcdToDec(string.byte(c,6))
year = bcdToDec(string.byte(c,7))
time=string.format(" %s.%s.%s", day, month, year)
print(time);
end
return M
I saved this file as "ds3231_m.lua". Calling functions from another file works like this:
m = require 'ds3231_m'
m.Init(2,1) --sda, scl = 2, 1
m.PrintTime()
--m.PrintDate()
package.loaded.ds3231_m = Nil
as well as
m = require 'ds3231_m'
m.Init(2,1) --sda, scl = 2, 1
--m.PrintTime()
m.PrintDate()
package.loaded.ds3231_m = Nil
But when I try calling both functions:
m = require 'ds3231_m'
m.Init(2,1) --sda, scl = 2, 1
m.PrintTime()
m.PrintDate()
package.loaded.ds3231_m = Nil
I get an error:
test.lua:4: attempt to call field 'PrintDate' (a nil value)
Can anyone tell me what is going wrong?
Thank you very much in advance!
Regards

Inside PrintTime (and PrintDate) you're doing m = something. That does overwrite your m from m = require(...).
You should use locals in those functions:
function M.PrintTime()
i2c.start(id)
i2c.address(id, address, i2c.TRANSMITTER)
i2c.write(id, 0x00)
i2c.stop(id)
i2c.start(id)
i2c.address(id, address, i2c.RECEIVER)
local c=i2c.read(id, 7)
i2c.stop(id)
local s = bcdToDec(string.byte(c,1))
local m = bcdToDec(string.byte(c,2))
local h = bcdToDec(string.byte(c,3))
local time=string.format(" %s:%s:%s", h, m, s)
print(time);
end
That way, you won't be editing any globals. Also do the same for PrintDate.
(If you did other_name_than_m = require(...) you wouldn't have noticed, but print(m) would still print a number, the amount of minutes from something)

Related

How to get over the 32 bits for storing numbers like - 2,147,483,647 to 2,147,483,647

I try to fix some old Basewars script for Gmod amd there is something i tried to fix but i dont know what i am missing there. Basicly its about a Bank script. This Bank could original store a amount of 2 Billion $. I would like to expand that storage amount to 1 Quadtrillion.
So Basicly the Basewars Gamemode allows players to have an high amount of money up to 10^18 $
= 1 Quintillion. I looked up into https://wiki.garrysmod.com/page/Category:number
so basicly lua uses double-precision floating-point format. So lua uses 32 bits for storing numbers and that means the number can be from a range of
-2,147,483,647 to 2,147,483,647.
The Basewars Gamemode uses a Function to make out of 10^18
= 1 Quintillion
function BaseWars.NumberFormat(num)
local t = BaseWars.LANG.Numbers
for i = 1, #t do
local Div = t[i][1]
local Str = t[i][2]
if num >= Div or num <= -Div then
return string.Comma(math.Round(num / Div, 1)) .. " " .. Str
end
end
return string.Comma(math.Round(num, 1))
end
The Gamemode is using that faction to convert the amount of money.
and here is the BaseWars.LANG.Numbers:
BaseWars.LANG = {}
BaseWars.LANG.__LANGUAGELOOK = {}
BaseWars.LANG.__LANGUAGELOOK.ENGLISH = {
Numbers = {
[5] = {10^6, "Million"},
[4] = {10^9, "Billion"},
[3] = {10^12, "Trillion"},
[2] = {10^15, "Quadtillion"},
[1] = {10^18, "Quintillion"},
},
CURFORMER = CURRENCY .. "%s",
CURRENCY = CURRENCY,
}
So i know that this function does work but i dont get it, how the variable num can be that high!
Why do i know what it does work ?
Here is what i tried and it manipulated the Capacity up to 1 Quadtrillion but at the point i manipluated a other Problem came up and i do not know what i do wrong!
Here how it was Original:
ENT.Capacity = 2000000000 --Max money in the bank. Can be bugs if it is more than 2000000000 (2 bil)
ENT.Money = 0
ENT.MaxPaper = 0
local Clamp = math.Clamp
function ENT:GSAT(slot, name, min, max)
self:NetworkVar("Int", slot, name)
local getVar = function(minMax)
if self[minMax] and isfunction(self[minMax]) then return self[minMax](self) end
if self[minMax] and isnumber(self[minMax]) then return self[minMax] end
return minMax or 0
end
self["Add" .. name] = function(_, var)
local Val = self["Get" .. name](self) + var
if min and max then
Val = Clamp(tonumber(Val) or 0, getVar(min), getVar(max))
end
self["Set" .. name](self, Val)
end
self["Take" .. name] = function(_, var)
local Val = self["Get" .. name](self) - var
if min and max then
Val = Clamp(tonumber(Val) or 0, getVar(min), getVar(max))
end
self["Set" .. name](self, Val)
end
end
function ENT:StableNetwork()
self:GSAT(2, "Capacity")
self:GSAT(3, "Money", 0, "GetCapacity")
self:GSAT(4, "Paper", 0, "MaxPaper")
self:GSAT(5, "Level", 0, "MaxLevel")
end
function ENT:ThinkFunc() --This Funtion is to auto collect all the Money of Printers
for k, v in pairs( ents.FindByClass( "bw_printer_*" ) ) do
if v:CPPIGetOwner() == self:CPPIGetOwner() then
if self:GetMoney() < self.Capacity then
local allmoney = v:GetMoney()
v:TakeMoney(allmoney)
self:AddMoney(allmoney)
end
end
end
for k, v in pairs( ents.FindByClass( "bw_base_moneyprinter" ) ) do
if v:CPPIGetOwner() == self:CPPIGetOwner() then
if self:GetMoney() < self.Capacity then
local allmoney = v:GetMoney()
v:TakeMoney(allmoney)
self:AddMoney(allmoney)
end
end
end
end
if CLIENT then
local Cp = self:GetCapacity()
local money = tonumber(self:GetMoney()) or 0
local cap = tonumber(Cp) or 0
local moneyPercentage = math.Round( money / cap * 100 ,1)
draw.DrawText( moneyPercentage .."%" , fontName .. ".Huge", w - 4-430, 71+610, self.FontColor, TEXT_ALIGN_CENTER)
local currentMoney = BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(money)
local maxMoney = BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(cap)
local font = fontName .. ".Big"
if #currentMoney > 16 then
font = fontName .. ".MedBig"
end
if #currentMoney > 20 then
font = fontName .. ".Med"
end
local fh = draw.GetFontHeight(font)
local StrW,StrH = surface.GetTextSize("")
local moneyW,moneyH = surface.GetTextSize(currentMoney)
draw.DrawText(currentMoney.. " / " .. BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(cap) , font,
w/2 - StrW/2-225 , (font == fontName .. ".Big" and 106 or 105 + fh / 4)+675, self.FontColor, TEXT_ALIGN_CENTER)
end
Here the changes i did:
removed line:
local cap = tonumber(Cp) or 0
added
local cap = 10^15
if self:GetMoney() < cap then
ENT.Capacity = 2000000000 --Max money in the bank. Can be bugs if it is more than 2000000000 (2 bil)
local cap = 10^15
ENT.Money = 0
ENT.MaxPaper = 0
local Clamp = math.Clamp
function ENT:GSAT(slot, name, min, max)
self:NetworkVar("Int", slot, name)
local getVar = function(minMax)
if self[minMax] and isfunction(self[minMax]) then return self[minMax](self) end
if self[minMax] and isnumber(self[minMax]) then return self[minMax] end
return minMax or 0
end
self["Add" .. name] = function(_, var)
local Val = self["Get" .. name](self) + var
if min and max then
Val = Clamp(tonumber(Val) or 0, getVar(min), getVar(max))
end
self["Set" .. name](self, Val)
end
self["Take" .. name] = function(_, var)
local Val = self["Get" .. name](self) - var
if min and max then
Val = Clamp(tonumber(Val) or 0, getVar(min), getVar(max))
end
self["Set" .. name](self, Val)
end
end
function ENT:StableNetwork()
self:GSAT(2, "Capacity")
self:GSAT(3, "Money", 0, "GetCapacity")
self:GSAT(4, "Paper", 0, "MaxPaper")
self:GSAT(5, "Level", 0, "MaxLevel")
end
function ENT:ThinkFunc() --This Funtion is to auto collect all the Money of Printers
for k, v in pairs( ents.FindByClass( "bw_printer_*" ) ) do
if v:CPPIGetOwner() == self:CPPIGetOwner() then
if self:GetMoney() < cap then
local allmoney = v:GetMoney()
v:TakeMoney(allmoney)
self:AddMoney(allmoney)
end
end
end
for k, v in pairs( ents.FindByClass( "bw_base_moneyprinter" ) ) do
if v:CPPIGetOwner() == self:CPPIGetOwner() then
if self:GetMoney() < cap then
local allmoney = v:GetMoney()
v:TakeMoney(allmoney)
self:AddMoney(allmoney)
end
end
end
end
if CLIENT then
local Cp = self:GetCapacity()
local money = tonumber(self:GetMoney()) or 0
local moneyPercentage = math.Round( money / cap * 100 ,1)
draw.DrawText( moneyPercentage .."%" , fontName .. ".Huge", w - 4-430, 71+610, self.FontColor, TEXT_ALIGN_CENTER)
local currentMoney = BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(money)
local maxMoney = BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(cap)
local font = fontName .. ".Big"
if #currentMoney > 16 then
font = fontName .. ".MedBig"
end
if #currentMoney > 20 then
font = fontName .. ".Med"
end
local fh = draw.GetFontHeight(font)
local StrW,StrH = surface.GetTextSize("")
local moneyW,moneyH = surface.GetTextSize(currentMoney)
draw.DrawText(currentMoney.. " / " .. BaseWars.LANG.CURRENCY .. BaseWars.NumberFormat(cap) , font,
w/2 - StrW/2-225 , (font == fontName .. ".Big" and 106 or 105 + fh / 4)+675, self.FontColor, TEXT_ALIGN_CENTER)
end
So now if you i look into the game it looks like this:
and now i have the problem that when it collects money it does it up to 2 billion and if i try to change
local money = tonumber(self:GetMoney()) or 0
to
local money =self:GetMoney()
i get straight -2.1 Bil
or i tried to change the min max values:
function ENT:GSAT(slot, name, min, max)
self:NetworkVar("Int", slot, name)
local getVar = function(minMax)
if self[minMax] and isfunction(self[minMax]) then return self[minMax](self) end
if self[minMax] and isnumber(self[minMax]) then return self[minMax] end
return minMax or 0
end
self["Add" .. name] = function(_, var)
local Val = self["Get" .. name](self) + var
if min and max then
Val = Clamp(tonumber(Val) or 0, getVar(min), 10^15)
end
self["Set" .. name](self, Val)
end
self["Take" .. name] = function(_, var)
local Val = self["Get" .. name](self) - var
if min and max then
Val = Clamp(tonumber(Val) or 0, getVar(min), 10^15)
end
self["Set" .. name](self, Val)
end
end
Basicly these lines:
Val = Clamp(tonumber(Val) or 0, getVar(min), 10^15)
if i run the game the Bank will just collect the money up to 2 Bill and then it goes to -2.1Bil. And at that point i dont know why and when a value does go buggy like it self sets to -2.1 Bil. does math.Round create this bug or do funktion return only return full integer ?
thx for any help
Because the network variable that the bank uses is an integer, it will only be able to store $(2^31-1) through $-(2^31-1). Try changing it to a networked float:
-- ...
function ENT:GSAT(slot, name, min, max)
-- self:NetworkVar("Int", slot, name), changes into:
self:NetworkVar("Float", slot, name)
-- ...
But, beware as the more money players accumulate the less precision will be put into those numbers.

Error in function rembuff:floor() in lua code file: attempt to call method 'floor' (a nil value)

In Machine Translation Dataset I have successfully pre-trained my model in Lua. Now I move to train my model.
But I get the error in a Lua file in the function rembuff:floor()
Error: Attempt to call method 'floor' (a nil value)
This is that specific function :
function MarginBatchBeamSearcher:nextSearchStep(t, batch_pred_inp, batch_ctx, beam_dec, beam_scorer,gold_scores, target, target_w, gold_rnn_state_dec, delts, losses, global_noise)
local K = self.K
local resval, resind, rembuff = self.resval, self.resind, self.rembuff
local finalval, finalind = self.finalval, self.finalind
self:synchDropout(t, global_noise)
-- pred_inp should be what was predicted at the last step
local outs = beam_dec:forward({batch_pred_inp, batch_ctx, unpack(self.prev_state)})
local all_scores = beam_scorer:forward(outs[#outs]) -- should be (batch_l*K) x V matrix
local V = all_scores:size(2)
local mistaken_preds = {}
for n = 1, self.batch_size do
delts[n] = 0
losses[n] = 0
if t <= target_w[n]-1 then -- only do things if t <= length (incl end token) - 2
local beam_size = #self.pred_pfxs[n]
local nstart = (n-1)*K+1
local nend = n*K
local scores = all_scores:sub(nstart, nstart+beam_size-1):view(-1) -- scores for this example
-- take top K
torch.topk(resval, resind, scores, K, 1, true)
-- see if we violated margin
torch.min(finalval, finalind, resval, 1) -- resind[finalind[1]] is idx of K'th highest predicted word
-- checking that true score at least 1 higher than K'th
losses[n] = math.max(0, 1 - gold_scores[n][target[t+1][n]] + finalval[1])
-- losses[n] = math.max(0, - gold_scores[n][target[t+1][n]] + finalval[1])
if losses[n] > 0 then
local parent_idx = math.ceil(resind[finalind[1]]/V)
local pred_word = ((resind[finalind[1]]-1)%V) + 1
mistaken_preds[n] = {prev = self.pred_pfxs[n][parent_idx], val = pred_word}
delts[n] = 1 -- can change.....
else
-- put predicted next words in pred_inp
rembuff:add(resind, -1) -- set rembuff = resind - 1
rembuff:div(V)
--if rembuff.floor then
rembuff:floor()
I am unable to rectify this error :
Please help !

esp8266 & ws2812 lua script hangs after the http request

I have written a LUA script whereby the color of the ws2812 changes when I call a url.
It is so that the ESP hangs when you first call the URL (http://IPADDRESS/?color=green&key=rpi). The color will be switched, but after that depends the ESP.
I've tried a lot. I do not know how to solve my problem. Connected is the PixelRing (ws2812) to D4 (gpio2).
Do you have a solution idea?
local SSID = "*******"
local SSID_PASSWORD = "******"
LED_COUNT = 12
SECRET_KEY = "rpi"
local buffer = nil
--ws2812.init()
function wait_for_wifi_conn ( )
tmr.alarm (1, 1000, 1, function ( )
if wifi.sta.getip ( ) == nil then
print ("Waiting for Wifi connection")
else
tmr.stop (1)
print ("ESP8266 mode is: " .. wifi.getmode ( ))
print ("The module MAC address is: " .. wifi.ap.getmac ( ))
print ("Config done, IP is " .. wifi.sta.getip ( ))
ws2812.init()
buffer = ws2812.newBuffer(LED_COUNT, 3)
end
end)
end
function connect(conn)
print("c2", conn);
conn:on ("receive",
function (cn, req_data)
if req_data:find('^GET /.* HTTP/1.1') ~= nil then
local key = string.match(req_data, "key=(%a+)")
local color = string.match(req_data, "color=(%a+)")
if key == SECRET_KEY then
local r, g, b = nil, nil, nil
if color == "red" then
r = 255
g = 0
b = 0
elseif color == "blue" then
r = 0
g = 0
b = 255
elseif color == "green" then
r = 0
g = 255
b = 0
end
if r ~= nil then
tmr.alarm(2, 100, tmr.ALARM_SINGLE, function()
--buffer = ws2812.newBuffer(LED_COUNT, 3);
buffer:fill(g,r,b); -- grb not rgb
print(buffer)
--ws2812.init()
ws2812.write(nil, buffer)
end)
end
end
end
-- Close the connection for the request
cn:on("sent",function(c) print("c0", c);c:close() end)
cn:send("<h1> Hello, NodeMcu.</h1>")
-- Close the connection for the request
--cn:on("sent",function(cnn) cnn:close() end)
end)
--conn:send("<h1> Hello, NodeMcu.</h1>")
end
wifi.setmode(wifi.STATION)
wifi.sta.config {ssid=SSID, pwd=SSID_PASSWORD}
wifi.sta.autoconnect(1)
wait_for_wifi_conn()
svr = net.createServer(net.TCP, 30)
if svr then
svr:listen (80, connect)
end
Thanks for Help =)

Convert Table string to the actual table

local t = "{{2173,1},{2160,5}}"
print(#t) -- 19?? wrong
How to convert to appear in numbers?
local t = {{2173,1},{2160,5}}
print(#t) -- 2 correct
You can run the string through load or loadstring (depending on your Lua version), which will return the table you are looking for:
local t = "{{2173,1},{2160,5}}"
t = (loadstring or load)("return "..t)()
print(#t) -- 2
Here is an ad hoc solution for the input you gave:
local s = "{{2173,1},{2160,5}}"
local t = {}
local n = 0
for a,b in s:gmatch("(%d+),(%d+)") do
n = n + 1
t[n] = {a,b}
end
for k,v in ipairs(t) do print(k,v[1],v[2]) end

Lua - Error Attempt to perform arithmetic on field '?' -- This occurs at the end of the for loop

I'm developing a program for the Ti-nspire CX CAS calculator and at the time of execution it indicates an error on line 52, this is presented at the end of the for loop in the "area" function.
Sorry for my English.
local coX = {0,2,2,0}
local coY = {0,0,2,0}
local xmax = 2
local ymax = 2
-- Matriz de coordenadas para función "on.paint(gc)"
function conCoor(x,y)
local nx = x
for i=1, #x do
table.insert(nx,i*2,y[i])
end
return nx
end
-- Valor absoluto
function math.abs(valor)
if valor < 0 then
valor = valor*(-1)
end
return valor
end
-- Inercia del polígono respecto el eje X
function inerciex(x,y)
local E = 0
local z =0
for i = 1, #x-1 do
E = (x[i+1]-x[i])*(y[i+1]+y[i])*((y[i+1])^2+(y[i])^2)
z = E + z
end
return math.abs(z/12)
end
-- Inercia del polígono respecto el eje Y
function inerciey(x,y)
local E = 0
local z =0
for i = 1, #x-1 do
E = (y[i+1]-y[i])*(x[i+1]+x[i])*((x[i+1])^2+(x[i])^2)
z = E + z
end
return math.abs(z/12)
end
-- Área del poligono
function area(x,y)
local A = 0
local z = 0
for i = 1, #x-1 do
A = (y[i]*x[i+1]-x[i]*y[i+1])
z = A + z
end -- Line 52, the line in question
return math.abs(z/2)
end
-- Centro de masa del polígono (eje x)
function centroix(x,y)
local Ac = area(x,y)
local z = 0
local cx = 0
for i = 1, #x-1 do
cx = (x[i]+x[i+1])*(x[i]*y[i+1]-x[i+1]*y[i])
z = cx + z
end
return z/(6*Ac)
end
-- Centro de masa del polígono (eje y)
function centroiy(x,y)
local Ac = area(x,y)
local z = 0
local cx = 0
for i = 1, #x-1 do
cx = (y[i]+y[i+1])*(x[i]*y[i+1]-x[i+1]*y[i])
z = cx + z
end
return z/(6*Ac)
end
-- Escala de figura
function escala(xmax,ymax)
local sc = 0
if xmax > ymax then
sc = 81/xmax
else
sc = 81/ymax
end
return math.floor(sc)
end
-- Coordenadas del origen en pantalla
function oriDispX(x,y,xmax,ymax)
return math.floor(212 + (-1)*centroix(x,y)*escala(xmax,ymax))
end
function oriDispY(x,y,xmax,ymax)
return math.floor(105 + (-1)*centroiy(x,y)*escala(xmax,ymax))
end
-- Cambio de coordenadas real
function coorCamb(x,y,xmax,ymax)
-- Escalado de coordenadas
local escx = x
local escy = y
local orix = oriDispX(escx,escy,xmax,ymax)
local oriy = oriDispY(escx,escy,xmax,ymax)
for i = 1, #escx do
escx[i] = math.floor(escx[i]*escala(xmax,ymax))
escy[i] = math.floor(escy[i]*escala(xmax,ymax))
end
-- Cambio de coordenadas
for i = 1, #escx do
escx[i] = escx[i] + orix
escy[i] = escy[i] + oriy
end
return conCoor(escx,escy)
end
function on.paint(gc)
local ox = oriDispX(coX,coY,xmax,ymax)
local oy = oriDispY(coX,coY,xmax,ymax)
local c = coorCamb(coX,coY,xmax,ymax)
gc:drawPolyLine(c)
gc:drawLine(ox-3,oy,ox+3,oy)
gc:drawLine(ox,oy-3,ox,oy+3)
gc:fillArc(ox-1,oy-1,2,2,0,360)
gc:fillArc(212-1,105-1,2,2,0,360)
gc:drawString(tostring(area(coX,coY)),10,10)
platform.window:invalidate()
end
More specifically, the error occurs here:
function area(x,y)
local A = 0
local z = 0
for i = 1, #x-1 do
A = (y[i]*x[i+1]-x[i]*y[i+1])
z = A + z
end -- Line 52, the line in question
return math.abs(z/2)
end
Your code assumes both X and Y arrays are of equal size (because you use i index for both X and Y array), or at least Y never smaller than X. i index, however, runs from 1 to the size of X array which will be invalid for Y array of smaller size.
So, if the Y array is smaller than the X array, you get that error. And, here's the proof:
function area(x,y)
local A = 0
local z = 0
for i = 1, #x-1 do
A = (y[i]*x[i+1]-x[i]*y[i+1])
z = A + z
end
return math.abs(z/2)
end
print(area({1,2,3},{4,5,6})) -- OK
print(area({1,2,3},{4,5})) -- ERROR
The solution was to initialize the variables and tables at the beginning of the whole script and then call the new values ​​using "var.recall" inside the on.paint function.

Resources