NodeMCU tmr.alarm always returns false - lua

I have a problem with NodeMCU, trying to start a tmr.alarm on a esp8266.
tmr.alarm never starts the timer, and always returns false.
I've tried changing the timer, and even changing the type of the alarm (AUTO, SINGLE...) but i always have the same result.
Here's part of the code, i'm trying to comunicate with a DS18B20 (OneWire temperature sensor) once every 5 seconds or so.
if not tmr.alarm(1, 5000, tmr.ALARM_AUTO, function()
-- Comunication with the sensor
end)
then print("Comunication with DS18B20 couldn't be started.") end
The output is always
Comunication with DS18B20 couldn't be started.

Don't use the old 0.9.x NodeMCU binaries from https://github.com/nodemcu/nodemcu-firmware/releases they're no longer supported and contain lots of bugs. Build a custom firmware from the dev or master branch.
I'm not aware of any timer bugs in recent versions.

Related

The effect of use_sim_time in ROS

I am trying to understand what effects does setting use_sim_time to true does specially when recording and playing a rosbag, but unfortunately the info is few and hard to understand.
I know already how to set it to true, so that is no problem.how to do it
I have done some experiments with a rosbag file I have and I noticed:
When I do rosplay play file.bag , the topic \clock is not published
When I do rosplay play file.bag --clock the topic \clock is published
I also have noticed that when I do rostopic echo \clock and I play the bag, many of the time published is the same! (what does this mean??)
And lastly I have noticed that use_sim_time has no effect on any of these results.
So what effect does setting this parameter to true have?
In order for a ROS node to use simulation time according to the /clock topic, the /use_sim_time parameter must be set to true before the node is initialized. In other words,
The ROS API used to get times ros::Time time = ros::Time::now() will retrieve time data from the /clock topic rather than using the system clock. If you turn use_sim_time off then any time values published to /clock will be ignored
If the /use_sim_time parameter is set, the ROS Time API will return time=0 until it has received a value from the /clock topic. Then, the time will only be updated on receipt of a message from the /clock topic and will stay constant between updates
More information follow: [1], [2]

Success callback function called on failure. Possible bug?

I'm working on a little project, using an ESP8266 with NodeMCU and Lua. I suspect I've found a bug, but since I'm new to Lua (and the other two too!), I'm hoping for some help in confirming if I'm right, or if I've missed something (more likely!).
The NodeMCU firmware contains a built-in SNTP client module which updates the synchronised time to a system clock (rtctime module). The success callback function seems to get called when (or possibly before) the NTP sync fails. This happens for example if the wifi is not connected, or sometimes on the first sync attempt after boot (with wifi connected). According to the doco, rtctime.get() returns zero if current time is not available; this is the result I get, further showing that the NTP sync hasn't been successful. I can't work out why the success function is being called at this point, in advance of, or instead of the failure function (as I would have expected).
The sntp module I'm referring to is here - unfortunately, the C source code was a bit over my head: https://nodemcu.readthedocs.io/en/master/en/modules/sntp/
My (minimal) code:
-- Define callback function for ntp sync success
function ntpSyncSuccess (sec, usec, server, info)
print('SNTP time sync successful!')
print("rtctime.get() returns: ", rtctime.get())
end
-- Configure and start NTP time sync with auto repeat enabled
sntp.sync("0.au.pool.ntp.org",
ntpSyncSuccess(sec, usec, server, info), --success callback
function() -- error callback
print('SNTP time sync failed!')
end,
1 -- enable autorepeat (SNTP sync every 1000 seconds (~17 min))
)
Serial output result when I boot the device and run the code (Note the 2nd and 3rd last lines):
NodeMCU custom build by frightanic.com
branch: master
commit: 11592951b90707cdcb6d751876170bf4da82850d
SSL: false
modules: cron,file,gpio,i2c,net,node,rotary,rtctime,sntp,struct,tmr,uart,wifi
build created on 2019-01-16 03:11
powered by Lua 5.1.4 on SDK 2.2.1(6ab97e9)
lua: cannot open init.lua
> print(uart.setup(0, 115200, 8, 0, 1, 1 ))
115200
> dofile("ntpTest.lua")
SNTP time sync successful!
rtctime.get() returns: 0 0 0
> SNTP time sync failed!
Just so that we can "close" this Q here (once you accept the answer). It has to be a function reference rather than a function invocation.
sntp.sync("0.au.pool.ntp.org",
ntpSyncSuccess, -- no (), no parameters
function() -- error callback

Lua script in FreeSWITCH exits bridge immediately when bypass_media = true

How do I make the script wait for the bridge to terminate before continuing when I have "bypass_media" set to true?
This snippet -
freeswitch.consoleLog("err","session before="..tostring(session:ready()).."\n")
session:execute("set","bypass_media=true")
session:execute("bridge","sofia/gateway/carrierb/12345678")
freeswitch.consoleLog("err","session after="..tostring(session:ready()).."\n")
from an audio perspective, it works perfectly with bridge_media set to either true or false, and a wireshark trace shows the audio either passing through (false) or end to end (true).
But with bypass set to true, the script continues without pausing, and the session is no longer ready (session:ready() == false).
The channel seems to go into a hibernate state, but I have housekeeping to do after the bridge is finished which I simply cannot do.
Same happens if i do the bridge in XML dialplan, immediately carries on causing my housekeeping to fire early.
FreeSWITCH (Version 1.6.20 git 43a9feb 2018-05-07 18:56:11Z 64bit)
Lua 5.2
EDIT 1 -
I can get "api_hangup_hook=lua housekeeping.lua" to work, but then I have to pass tons of variables and it fires up a new process/thread/whatever, which seems a little overkill unless that's the only way.
I have a workaround, but would still like an answer to the question if anyone has one (ie how to stop the bridge exiting immediately).
If I set this before the bridge :
session:execute("set","bypass_media=true")
session:execute("set","session_in_hangup_hook=true")
session:execute("set","api_hangup_hook=lua housekeeping.lua "..<vars>)
then "housekeeping.lua" fires when the bridge actually terminates (which is long after the script does).
In housekeeping.lua I can then do :
session:getVariable("billmsec")
and it seems to have the correct values in them, allowing me to do my housekeeping.
My problem with this is the uncertainty of playing with variables from a session that appears to have gone away from a script that fires at some point in the future.
Anyway, it'll have to do until I can find out how to keep control inside the original script.

tmr.create() fails in dirt simple code

On an ESP8266, a LUA tmr.create() fails. Just a single line of code from the nodemcu docs. I've yet to get this working; stumped; have found nothing on the 'net here or forums. Posted in several other places with no replies. Odd
Basic node commands work. And, here's the thing that's getting me: some timer functions work - for instance tmr.alarm() does - but tmr.create() doesn't.
QUESTION 1: if the tmr module is loaded, isn't the entire module loaded, not just parts of it?
When I try this one line copied directly from the NodeMCU docs, it fails:
local mytimer = tmr.create()
with the usual message, I understand to mean an object is undefined:
stdin:1: attempt to call field 'create' (a nil value)
QUESTION 2: What am I missing or doing wrong?
Nodemcu's flasher successfully sent its default
INTERNAL://NODEMCU # 0x00000
NodeMCU 0.9.5 build 20150318
The board is an Adafruit Huzzah ESP8266, not a NodeMCU board. They both use the same ESP12, I think, so that shouldn't matter (or I hope it doesn't :-/)
NodeMCU 0.9.5 build 20150318
There's your culprit. That version is ancient. create() was added much later. Build a recent version from the master branch, https://nodemcu.readthedocs.io/en/master/en/build/ (note master in the URL), and flash that one.

MQTT on ESP8266 with NodeMCU - problems with publishing

I'm building a battery powered IoT device based on ESP8266 with NodeMCU.
I use mqtt to periodically perform measurements and publish results.
I know, that to allow network stack running, I should avoid tight loops and rely on callback functions. Therefore it seemed to me that the right organization of my measurement code should be:
interval=60000000
function sleep_till_next_sample()
node.dsleep(interval)
end
function close_after_sending()
m:close()
sleep_till_next_sample()
end
function publish_meas()
m:publish("/test",result,1,0,close_after_sending)
print("published:"..result)
end
function measurement()
-- The omitted part of the function accesses
-- the hardware and places results
-- in the "result" variable
m = mqtt.Client("clientid", 120, "user", "password")
m:connect("172.19.1.254",1883,0, publish_meas)
end
The init.lua ensures, that the node has connected to the WiFi AP (if not, it retries up to 20 times, and if no connection is established, it puts the node on sleep until the next measurement time).
After WiFi connection is done, it calls the measurement function.
The interesting thing is, that the above code doesn't work. There are no errors displayed in the console, but the mqtt broker does not receive published messages.
To make it working, i had to add additional idle time, by adding timers in the callback functions.
The finally working code looks like below:
interval=60000000
function sleep_till_next_sample()
node.dsleep(interval)
end
function close_after_sending()
m:close()
tmr.alarm(1,500,0,function() sleep_till_next_sample() end)
end
function publish_meas()
m:publish("/test",result,1,0,function() tmr.alarm(1,500,0,close_after_sending) end)
print("published:"..result)
end
function measurement()
-- The omitted part of the function accesses
-- the hardware and places results
-- in the "result" variable
m = mqtt.Client("clientid", 120, "user", "password")
m:connect("172.19.1.254",1883,0, function() tmr.alarm(1,500,0, publish_meas) end)
end
The above works, but I'm not sure if it is optimal. To conserve the battery power I'd like to minimize the time before the node is put on sleep after the measurement is completed and results published.
Is there any better way to chain the necessary calls to m:connect, m:publish, m:close and finally node.dsleep so, that the results are correctly published in the minimal time?
Perhaps this was solved by more recent firmware. I am working through a problem that I thought might be somewhat explained by this issue, so tried to reproduce the problem as described.
My simplified test code is substantially similar; it calls dsleep() from the PUBACK callback of mqtt.Client.publish():
m = mqtt.Client("clientid", 120, "8266test", "password")
m:lwt("/lwt", "offline", 0, 0)
function main(client)
print("connected - at top of main")
m:publish("someval",12345,1,0, function(client)
rtctime.dsleep(SLEEP_USEC)
end)
end
m:on("connect", main)
m:on("offline", function(client) is_connected = false print ("offline") end)
m:connect(MQQT_SVR, 1883, 0, mainloop,
function(client, reason) print("failed reason: "..reason) end)
and when run, does successfully publish to my MQTT broker.
I am using:
NodeMCU custom build by frightanic.com
branch: master
commit: 81ec3665cb5fe68eb8596612485cc206b65659c9
SSL: false
modules: dht,file,gpio,http,mdns,mqtt,net,node,rtctime,sntp,tmr,uart,wifi
build built on: 2017-01-01 20:51
powered by Lua 5.1.4 on SDK 1.5.4.1(39cb9a32)

Resources