As the title says... Chat on...

User avatar
By timg11
#76621 I came across Lua NodeMCU on ESP8266 throughthis article on a simple Web Clock .

I've got it to run as-is, but as I get into making modification and debugging I have several questions about the code. I'm familiar with programming in general, but have never used Lua. I understand that Lua is a programming language in its own right, but perhaps there are some special approaches to coding and program structure needed for the NodeMCU environment that I need to understand? For example:

1) The code makes extensive use of function form "dofile("sourcefile.lua"), instead traditional function calls functionname(parameter). Is there a reason for this in the NodeMCU environment?

2) The code uses constructs like this to control timing and sequencing:
tmr.alarm(0, 1000, 0, function()
statement1
statement2
...
end )

Again is there a reason for this type of structure? e.g. perhaps CoRoutinesare not supported in NodeMCU?

3) I have been using LuaLoader 0.91 to upload and debug. It has a number of issues, including a seeming inability to run serial faster than 9600 bps. Even for small files, this makes the upload process quite slow. I see that there has been no updates in 2 years. Is there another IDE or environment that is now more current and active for NodeMCU development with the ESP8266 WeMOS D1 mini type of modules?
User avatar
By marcelstoer
#76623 The best answer to all your questions is our NodeMCU Lua developer FAQ at https://nodemcu.readthedocs.io/en/lates ... eloper-faq. It's a long read, very long actually, but it's such a treasure trove of wisdom that it's well worth every minute you spend with it.

So, I'll keep it short here.

timg11 wrote:1) The code makes extensive use of function form "dofile("sourcefile.lua"), instead traditional function calls functionname(parameter). Is there a reason for this in the NodeMCU environment?


-> It's the sibling of require() and serves two purposes: organizing code in different files, runtime optimization as per the FAQ "How do I minimise the footprint of running application?"

timg11 wrote:2) The code uses constructs like this to control timing and sequencing:
tmr.alarm(0, 1000, 0, function()
statement1
statement2
...
end )

Again is there a reason for this type of structure? e.g. perhaps CoRoutinesare not supported in NodeMCU?


The NodeMCU programming model is similar to that of Node.js, only in Lua. It is asynchronous and event-driven. Many functions, therefore, have parameters for callback functions.

The main standard Lua libraries core, coroutine, string and table are implemented.

NodeMCU is based on the Espressif NON-OS SDK which describes itself as

"Due to a lack of operating system, the nonOS SDK does not schedule tasks or preempt the user functions.
The non-OS SDK is most suitable for use in event-driven applications. As there is no RTOS overhead, the non-OS SDK does not impose stack size restrictions or execution time slots on any user functions. "

Details at https://www.espressif.com/sites/default ... df#page=17

timg11 wrote:3) I have been using LuaLoader 0.91 to upload and debug. It has a number of issues, including a seeming inability to run serial faster than 9600 bps. Even for small files, this makes the upload process quite slow. I see that there has been no updates in 2 years. Is there another IDE or environment that is now more current and active for NodeMCU development with the ESP8266 WeMOS D1 mini type of modules?


https://nodemcu.readthedocs.io/en/latest/en/upload/

In case you haven't done so please build a recent version of the firmware before you do anything serious with it as per https://nodemcu.readthedocs.io/en/latest/en/build/
User avatar
By timg11
#76853 In my example code that relies on multiple .lua files that call each other with dofile("somefile.lua") structures,
I'm confused about variable scope. I read the FAQthat said "...by default any variable that is referenced and not previously declared as local is global..."

I'm seeing different behavior. Consider files foo.lua and bar.lua. In foo.lua there is a statement dofile("bar.lua").

Code in bar.lua sets a global variable that gets referenced in foo. if the variables are declared at the top of bar.lua (as "globalvar=0"), the reference in foo.lua gets a panic from a nil value. But if I move the declarations to foo.lua, then the variables are nil when referenced in bar.lua.

What am I missing? What are the rules for global-scope variables that persist between "dofile"?