PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : LuaScript will nicht so wie ich möchte... ;)



oderlachs
22.03.2018, 15:12
Hallo Freunde !

Mein nächster Roboter soll mit NodeMCU + Motordriver gesteuert werden. Nun habe ich mich ein wenig mit Lua befasst und mal 1,2 Scripte geschrieben.
Also eine "init.lua" und einen "blink.lua" die von der init aufgerufen wird.
Die grosse Überraschung liegt darin , dass die LED 3mal blinkt und dann wird ein Reset im Chip ausgelöst...und das ganze beginnt von vorn.
Ich muss gestehen das das es meine ersten "Arbeiten" mit LUA und NodeMCU sind.
Aber ich kann mir den Ablauf einfach nicht erklären oder ich habe die Programmierung mit Lua Skripten total falsch verstanden :(

Hier mal der Code beider Dateien , die ich mittels ESP Explorer hochlade.




//--version: NodeMCU 0.9.5 build 20150318 powered by Lua 5.1.4

// Datei: lua.init:

print("\n")
print("ESP8266 Started")
print("\n")
print("ESP8266-Robot")
print("by")
print("Oderlachs")
dofile('blink.lua')

//++++++++++++++++++++++++++++++++++++++++++++++

Datei: blink.lua :

LED_PIN = 2
US_TO_MS = 1000

gpio.mode(LED_PIN, gpio.OUTPUT)

while true do
gpio.write(LED_PIN, gpio.HIGH)
tmr.delay(500 * US_TO_MS)
gpio.write(LED_PIN, gpio.LOW)
tmr.delay(500 * US_TO_MS)

end


Mache ich vielleicht bei meiner ganzen Denkweise etwas falsch ??? Die init.lua wird doch richtig abgearbeitet....auch ein Fehler in der while - Schleife hätte ich noch akzeptiert, aber ein Reset(??),
da kann ich mir nix drunter vorstellen, woran das liegt.

Vielleicht hat ja Bitte wer einen Hinweis der helfen kann...

Gruss und Dank
Gerhard

Klebwax
22.03.2018, 23:20
Es gibt eine kurze und eine lange Antwort. Zuerst die kurze: das tmr.delay() ist Schuld.

In der Doku steht dazu


Busyloops the processor for a specified number of microseconds.

This is in general a bad idea, because nothing else gets to run, and the networking stack (and other things) can fall over as a result. The only time tmr.delay() may be appropriate to use is if dealing with a peripheral device which needs a (very) brief delay between commands, or similar. Use with caution!

Und jetzt die längere Antwort. Auf dem ESP läuft ein kooperatives Multitasking System. Neben dem Netzwerkstack und anderen Tasks ist der Luainterpreter nur eine weitere. Eine Task in einem kooperativen System darf den Prozessor aber nicht blockieren. Tut eine Task es aber doch, schlägt auf dem ESP der Watchdog zu und löst einen Reset aus. Das ist das, was du beobachtest.

Programme auf dem lua NodeMCU müssen anders aufgebaut werden, als man das sonst so macht. Die klassische "while(1)" Schleife gibt es nicht, sie würde das System blockieren. Die Funktionen, die das System ausführen soll, werden ereignissgesteuert ausgeführt. Als Beispiel: über W-Lan kommt eine Nachricht, sie wird interpretiert und umgesetzt. Ein Inputpin ändert seinen Zustand, es wird die passende Funktion aufgerufen. Findet man für seinen Zweck kein passendes Ereigniss, kann man einen Timer aufsetzen, der die Funktion startet. Wenn du die Doku zum NodeMCU System mit lua durchgehst, findest überall Stellen, wo du deine Funktionen als Callbacks eintragen kannst.

Solche Ereignissgesteuerten System sind (besser waren) bei Anwenderprogrammen eher selten. Bei Programmen, die mit einer GUI laufen, sind sie aber üblich. Ein System ohne GUI ist die Javascript Umgebung ohne Browser, genannt node.js. Die Verwendung von node bei NodeMCU ist nicht zufällig. Hier mal etwas zu einlesen (https://nodemcu.readthedocs.io/en/dev/en/lua-developer-faq/), es wird aber als alleinige Literatur nicht reichen.

Nun zu deinem Beispiel. Du möchtest einen Pin toggeln eine LED blinken lassen. Dazu ist es als erstes nötig, den passenden Pin als Output zu konfigurieren.
LED_PIN = 2
gpio.mode(LED_PIN, gpio.OUTPUT)

Dann setzt du einen Timer auf, der eine Funktion aufruft, wenn er abgelaufen ist.

Hier das mal im Zusammenhang


LED_PIN = 2
gpio.mode(LED_PIN, gpio.OUTPUT)

ticker = tmr.create()
ticker:register(1000, tmr.ALARM_AUTO, function ()
if(gpio.read(LED_PIN) then
gpio.write(LED_PIN. 0)
else
gpio.write(LED_PIN, 1)
end
end)
ticker:start()


Wenn du diesen Code z.B. mit dofile geladen hast, wird deine LED im Takt des Timers blinken. Auf der Konsole hast du wieder den Lua-Prompt. Mit den Funktionen aus dem Timer-Modul könntest du jetzt interaktiv die Tickerzeit verändern oder den Timer auch abschalten. Statt das interaktiv zu tun, könnte das natürlich auch im Callback beim Empfang eines W-Lan Paketes passieren.

Ich hab zwar einen ESP hier an meinem Rechner, aber keinen freien IO mit LED. Der Code ist also nicht getestet.

MfG Klebwax

PS: in lua wird ein einzeiliger Kommentar mit "--" aufgemacht, ein mehrzeiliger startet mit "--[[" und endet mit "--]]". "//" gehört nicht in lua-Code

oderlachs
23.03.2018, 08:51
Hallo Klebwax, vielen ,vielen herzlichen Dank !!

Das ist genau die Erklärung, die ich brauchte und mir auch den Grund des Resets erkennen lässt. :)

Das mit den "//" beim Kommentar hatte ich wegen der Code-Formatierung hier im Forum gemacht, sonst hätte ich nur "--" geschrieben.
Ich wusste nicht wie "--" hier Interpretiert wird bei der Anzeige an...ich "Schussel" hatte doch gar nicht an die Vorschau gedacht.
Mit knapp unter 70 an Jahren hat man schon mal ein "Speicherleck";)

Mit besten Dank und Grüssen

Gerhard

Nachtrag :
Es ist doch um "krumme Drähte" gerade zu biegen....:mad: ;)
Klebwax, dein Bsp. Code " tmr.create() " passt nicht zu meiner LUA-Version....aber nun weiss ich erst mal den Werdegang....

Nachtrag2:
Warum musste ich mich auch auf die Klammer nach dem " if " fokusieren...:mad: ja man ist eben auf c/c++ eingestellt


-- BlinkLED an GPIO2
-- Vorlage: https://roboindia.com/tutorials/esp8266-led-blinking-lua
local pin = 4 -- GPIO02
local status = gpio.LOW
local duration = 300 -- alle 300ms wechseln

gpio.mode(pin, gpio.OUTPUT)
gpio.write(pin, status)


tmr.alarm(0, duration, 1, function ()
if status == gpio.LOW then
status = gpio.HIGH
else
status = gpio.LOW
end

gpio.write(pin, status)
end)


Nichtdestotrotz gehen die Beispiele aus meinem Ebook "Howto to program ESP8266.." auch nicht....