I wrote this code to interface the gsm module, can anyone check the code and give me some propositions ?
hex1= '0x1A';
function delay_s(delay)
delay = delay or 1
local time_to = os.time() + delay
while os.time() < time_to do end
end
uart.alt(1);
uart.setup(0, 9600, 8, uart.PARITY_NONE, uart.STOPBITS_1, 1)
uart.write(0,"AT+IPR=9600\n")
for j = 1, 10 do
uart.write(0, "AT\n")
end
delay_s(1000)
uart.write(0, "AT\n")
delay_s(1000)
uart.write(0, 'AT+CSCS="GSM"\n')
delay_s(1000)
uart.write(0, 'AT+CMGF=1\n')
delay_s(1000)
uart.write(0, 'AT+CMGS="+21654102832"\n')
delay_s(1000)
uart.write(0, " Salut tout le mond !!!\n")
delay_s(1000)
uart.write(0, hex1)
delay_s(1000)
This code won't even run on NodeMCU because the standard Lua os.time() will fail since the os module is not available. I suggest you dig into http://nodemcu.readthedocs.io/en/latest/en/lua-developer-faq/#how-is-nodemcu-lua-different-to-standard-lua.
Besides, even if it were available os.time() has 1 second resolution.
The returned value is a number, whose meaning depends on your system. In POSIX, Windows, and some other systems, this number counts the number of seconds since some given start time (the "epoch").
Hence, your delay_s(1000) would delay execution for 1000 seconds. Doing that with busy-waiting is...not optimal.
You probably want to use the tmr module instead.
uart.alt(x);
0 - standard pins
1 - alternate the pins
You havent specify which pins you are gonna use for the communication, or else use uart.alt(0); for standard pins
Related
I know my question would sound silly but I'm new to Lua so I'm trying to make the best practice as I can.
function wait(n)
local start = os.time()
repeat until os.time() > start + n
end
function hi(x)
while x do
print("Hi")
wait(.5)
end
end
hi(true)
For example, I want to turn off the function "hi" after running for 6 seconds and re-enable it after stopping for 2 seconds, how can I do it? Thank you so much!
Try this changes...
function wait(n)
local start = os.clock()
repeat until os.clock() > start + n
end
function hi(x)
for i = 1, x do
print("Hi")
wait(.5)
end
end
hi(4) -- With the hardcoded wait(.5) this will end after 2s
One warning.
Lua is fast so wait() will run in high performance mode.
Let it run by hi(120) for a minute will also run your fans in high cooling mode.
...it is better to have a more CPU friendly wait/sleep.
Easy Peasy with LuaJIT: https://luajit.org/ext_ffi_tutorial.html
This is my attempt to make a Logitech high-precision delay, accurate to 1ms.
Why do you need high precision delay? Because starting with Win10 release 2004, Logitech Sleep(1) is actually sleeps for 15.6ms, so you might need a more precise Sleep() to preserve the original (Win10 1909) behavior of your old scripts.
function Sleep3(time)
local a = GetRunningTime()
while GetRunningTime()-a < time do
end
end
Is Sleep3() accuracy really equals to 1ms?
Logitech GetRunningTime() just invokes WinAPI function GetTickCount
As you can see from the doc,
The resolution of the GetTickCount function is limited to the resolution of the system timer, which is typically in the range of 10 milliseconds to 16 milliseconds
In other words, the values returned by GetRunningTime() are not sequential integers.
When you call GetRunningTime() in a loop, you will receive something like the following:
0,0,0,...,0,15,15,15,...,15,31,31,..,31,46,46,...
This means it is unable to make 1ms-precision delay by using GetRunningTime().
The actual precision of Sleep3() is 15ms, as usual Sleep() has.
function OnEvent(event,arg)
if event == "MOUSE_BUTTON_PRESSED" and arg == 4 then
a = GetRunningTime()
for i = 1,1000,1 do
Sleep(1)
end
OutputLogMessage((GetRunningTime() - a) / 1000)
end
end
I am using a sensor similar to hall effect sensor to count the number of interrupts. After some random time, usually after it has been ON for 1-2 hours it resets and followed by random resets at random intervals.
counter = 0;
sampletime = 0;
lastrisetime = tmr.now()
pin = 2
do
gpio.mode(pin, gpio.INT)
local function rising(level)
-- to eliminate multiple counts during a short period (.5 second) difference is taken
if ((tmr.now() - lastrisetime) > 500000) then
lastrisetime = tmr.now();
end
-- when tmr.now() resets to zero this takes into account that particular count
if ((tmr.now() - lastrisetime) < 0) then
lastrisetime = tmr.now();
end
end
local function falling(level)
if ((tmr.now() - lastrisetime) > 500000) then
-- Only counted when the pin is on falling
-- It is like a sine curve so either the peak or trough is counted
counter = counter + 1;
print(counter)
lastrisetime = tmr.now();
sampletime = lastrisetime;
end
-- when tmr.now() resets to zero this takes into account that particular count
if ((tmr.now() - lastrisetime) < 0) then
lastrisetime = tmr.now();
counter = counter + 1;
print(counter)
end
end
gpio.trig(pin, "up", rising)
gpio.trig(pin, "down", falling)
end
This is the error I get on CoolTerm, also I checked for memory every couple of hours and you can see the results there.
NodeMCU 0.9.6 build 20150704 powered by Lua 5.1.4
> Connecting...
connected
print(node.heap())
22920
> print(node.heap())
22904
> print(node.heap())
22944
> print(node.heap())
22944
> 2. .print(node.heap())
22944
> print(node.heap())
22944
> ∆.)ç˛.䂸 ã ¸#H7.àåË‘
NodeMCU 0.9.6 build 20150704 powered by Lua 5.1.4
> Connecting...
connected
print(node.heap())
21216
> F.)ç˛.¶Ùå¶1.#H .ÊÍ
NodeMCU 0.9.6 build 20150704 powered by Lua 5.1.4
> Connecting...
connected
H!໩.ä‚D.ã ¸å¶H.åb‘
NodeMCU 0.9.6 build 20150704 powered by Lua 5.1.4
> Connecting...
connected
print(node.heap())
22904
> print(node.heap())
21216
>
Thank you for taking the time to read this. Appreciate your input.
Possible watchdog timer issue.
In your interrupt service routine looks like you are waiting too much.
Better to remove timing operations from there, just set a flag and in another loop, check the flag status and complete your timing operations.
NodeMCU 0.9.6 build 20150704 powered by Lua 5.1.4
The first thing really is to use a recent version of the NodeMCU firmware. 0.9.x is ancient, contains lots of bugs and is no longer supported. See here https://github.com/nodemcu/nodemcu-firmware/#releases
lastrisetime = tmr.now()
The real issue is that tmr.now() rolls over at 2147 seconds I believe. I learned about this when I worked on a proper debounce function.
-- inspired by https://github.com/hackhitchin/esp8266-co-uk/blob/master/tutorials/introduction-to-gpio-api.md
-- and http://www.esp8266.com/viewtopic.php?f=24&t=4833&start=5#p29127
local pin = 4 --> GPIO2
function debounce (func)
local last = 0
local delay = 50000 -- 50ms * 1000 as tmr.now() has μs resolution
return function (...)
local now = tmr.now()
local delta = now - last
if delta < 0 then delta = delta + 2147483647 end; -- proposed because of delta rolling over, https://github.com/hackhitchin/esp8266-co-uk/issues/2
if delta < delay then return end;
last = now
return func(...)
end
end
function onChange ()
print('The pin value has changed to '..gpio.read(pin))
end
gpio.mode(pin, gpio.INT, gpio.PULLUP) -- see https://github.com/hackhitchin/esp8266-co-uk/pull/1
gpio.trig(pin, 'both', debounce(onChange))
i've started using nodemcu on esp8266.
I've connected esp with hc-sr04 (ultrasound sensor for distance measurement).
hc-sr04 need to receive high state for trig pin for 10us. After that hc send high state of echo pin. The time of the high state from echo pin can be different (depends of distance). The time is counted in us.
The problem is that this time from echo pin is incorrect (IMHO). I'm not sure but is this possible that tmr. from nodemcu is not as precise as it should? And why there is so big difference between times in each loop?
My code and below you will find time printings from code:
gpio.write(3,gpio.LOW)
gpio.mode(3,gpio.OUTPUT)
gpio.write(4,gpio.LOW)
gpio.mode(4,gpio.INT)
time=0
flag=0
i=1
function startDis(level)
time=tmr.now()
end
function endDis(level)
time=tmr.now()-time
flag=0
end
function trigger()
gpio.write(3,gpio.HIGH)
tmr.delay(10)
gpio.write(3,gpio.LOW)
flag=1
end
gpio.trig(4,'up',startDis)
gpio.trig(4,'down',endDis)
// ---------THIS PART HAS BEEN CHANGED--------
while i<10 do
if flag==0 then
trigger()
end
tmr.delay(1000000)
print(time)
i=i+1
end
//--------------- TO ------------
tmr.alarm(0,2000,1,function()
print(time)
print(i)
if flag==0 then
trigger()
end
i=i+1
if i==10 then tmr.stop(0) end
end)
Code prints:
0
440184038
1999856
442183990
4000221
444184055
6000175
446184287
7999686
Thanks for clues and solutions.
Petre, I'll do this as an answer because it doesn't fit into a quick comment. :(
You need to read some of the other discussion in the FAQ on how the overall SDK schedules tasks. You are assuming in your code that something like this happens:
<every 2mSec>
print(time)
print(i)
if flag==0 then
gpio.write(3,gpio.HIGH)
time=tmr.now()
tmr.delay(10)
gpio.write(3,gpio.LOW)
time=tmr.now()-time
flag=0
flag=1
end
i=i+1
if i==10 then tmr.stop(0) end
where in in reality what happens is closer to:
<every 2mSec task starts>
print(time)
print(i)
if flag==0 then
gpio.write(3,gpio.HIGH)
<H/W interupts calls low level GPIO which books up callback>
time=tmr.now()
tmr.delay(10)
<H/W interupts calls low level GPIO which books down callback>
gpio.write(3,gpio.LOW)
flag=1
end
i=i+1
if i==10 then tmr.stop(0) end
<task ends>
<possible TCP and other tasks run>
<up trigger is delivered>
time=tmr.now()
<task ends>
<possible TCP and other tasks run>
<down trigger is delivered>
time=tmr.now()-time
flag=0
<task ends>
The Esp8266 SDK is not a real Real Time O/S; it is event driven. It's your mindset that needs to get reorientated.
Using the tmr.delay() this way is the correct use, but you need HW test tools such as an oscilloscope or logic analyser to check what the actual delay is because you need to add in the time to process the Lua instructions.
Or even put the tmr.now() calls inline.
The real usecase for the trigger is where you have an input connected to a sensor such as a mechanical open/close detector and this avoids the need to poll it.
I'm currently working on a simple 'guess the number' game using Lua. I'm programming through an app on my iPad called TouchLua+. One of the game modes is you have a certain amount of time to guess the number. I thought that to do this, I would create a coroutine that counts down from the given time. For some reason, I can't input a number while the coroutine is running. Can anyone help? Here is what I have so far.
target = math.random(1, 100)
coroutine.resume(coroutine.create(function()
for i = 1, roundTime do
sleep(1000)
sys.alert("tock")
end
lose = true
coroutine.yield()
end))
repeat
local n = tonumber(io.read())
if (n > target) then
print("Try a lower number.\n")
elseif (n < target) then
print("Try a higher number.\n")
else
win = true
end
until (lose or win)
return true
Coroutines are not a form of multiprocessing, they are a form of cooperative multithreading. As such, while the coroutine is running, nothing else is running. A coroutine is meant to yield control back to the caller often, and the caller is meant to resume the coroutine so the coroutine can continue where it yielded. You can see how this will appear to be parallel processing.
So in your case you would want to yield from inside the loop, after a small sleep time:
co = coroutine.create(function()
for i = 1, roundTime do
sleep(1)
sys.alert("tock")
coroutine.yield()
end
lose = true
end)
Unfortunately, you can't interrupt io.read(), which means the above is of no use. Ideally you would want a "io.peek" function so you could do the following:
while coroutine.status(co) ~= "dead" do
coroutine.resume(co)
if io.peek() then -- non-blocking, just checks if a key has been pressed
... get the answer and process ...
end
end
I am not aware of a non-blocking keyboard IO in Lua. You could create a C extension that exposes some of C non-blocking keyboard input to Lua, assuming that TouchLua+ supports C extensions. I doubt it, given that it is an iOS app.
It doesn't appear that there is a time loop or callbacks or such, and couldn't find docs. If you have option of creating a text box where user can enter answer and they have to click accept then you can measure how long it took. If there is a time loop you could check time there and show message if run out of time. All this is very easy to do in Corona, maybe not possible in TouchLua+.