ESP8266 nodeMCU Lua

Aus der Mikrocontroller.net Artikelsammlung, mit Beiträgen verschiedener Autoren (siehe Versionsgeschichte)
Wechseln zu: Navigation, Suche

ESP8266 nodeMCU-Boards in Lua programmieren:

=== Dieser Artikel handelt von Microcontroller-Boards die auf den ESP8266-Modulen basieren und als Firmware ausschließlich nodeMCU / Lua nutzen. Das heißt es soll ausschließlich um die Programmierung in der Scriptsprache Lua gehen.

Wer den ESP8266-Module mit Arduino-IDE oder irgendwie anders programmieren möchte möge sich auf die Seiten begeben die sich damit beschäftigen. Dieses Wiki ist ausschließlich und exklusiv für die Lua-Programmierung gedacht.

===

Wie wohl alle Wikis wird dieses im Laufe der Zeit wachsen.

Ich selbst (User StefanL38 der diese Wiki-Seite begonnen hat) bin jemand der es gerne bequem hat. Deshalb benutze ich wann immer möglich fertige Software. (Lua weil für ganz viele Protokolle wie I2C, one-wire, das bitbanging schon programmiert wurde) Sowie fertige Programme zum Firmware erzeugen und flashen.

Wer gerne über Themen wie "wie richte ich mir das Espressif NON-OS-SDK 2.x zum compilieren von ultraspezieller firmware ein" schreiben möchte möge bitte eine neue Wiki-Seite aufmachen.

Board mit der nodeMCU-Firmware flashen:

aktuelle Firmware herunterladen

Eine sehr bequeme und einfach zu bedienende Möglichkeit eine jeweils aktuelle Firmware herunterzuladen ist die Internetseite https://nodemcu-build.com/

Die Firmware nodeMCU besteht aus vielen einzelnen Modulen für die verschiedensten Anwendungsmöglichkeiten. Auf der Internetseite https://nodemcu-build.com/ kann man sich die Module auswählen die man braucht. Es wird dann von der Internetseite die entsprechende Firmware als *.bin-Datei erstellt und per Email ein Download-Link verschickt.

Firmware flashen

Zum eigentlichen Flashen empfehle ich das Programm pyflasher https://github.com/marcelstoer/nodemcu-pyflasher/releases/download/v1.0.0/NodeMCU-PyFlasher-1.0.0.exe

Es gibt eine Menge Internetanleitungen die den nodeMCU Programmer empfehlen. Diese Software nodeMCU Programmer hat bei mir nicht funktioniert. Pyflasher funktionierte tadellos.


nodeMCU-Board in den Flashmode versetzen:

Um eine neue Firmware zu flashen muss man das Board in den Flashmode versetzen. Dazu den Taster "flash" heruntergedrückt halten und dann den Reset-Taster drücken. Wenn der Reset-Taster losgelassen wird UND in diesem Moment der Flash-Taster gedrückt IST dann wird das Board in den Flashmode versetzt. Dann kann man den Flashvorgang starten.

Fallstricke die mir begegnet sind

Vermeiden nodeMCU-board in eine Endlos-Bootschleife zu versetzen:

Wenn man ein nodeMCU-Board an die Spannungsversorgung anschließt und die Firmware bootet sucht die Firmware auf dem Flashspeicher nach einer Datei mit Namen "init.lua" Wenn man sein Skript gründlich ausgetestet hat und alles funktioniert macht das auch Sinn damit man das Board durch simples "Spannung ein" und ohne USB-Verbindung zu einem PC starten kann.

Solange man an seinem Lua-Skript programmiert und es Fehler enthalten könnte ist das keine gute Idee dieser Skript-Datei den Namen "init.lua" zu geben. Wenn der Fehler zu einem crash führt kann es sein, dass das Board durch den Crash neu bootet und dann macht das board endlos booten-crashen-booten-crashen-booten-crashen usw. Die einzige Möglichkeit diesen Zustand zu beenden ist das Board neu zu flashen und dabei auch alle Skripte die man bis dahin auf den Flashspeicher geladen hat zu verlieren. Also sehr ungünstig. Deshalb so lange man programmiert dem Skript unbedingt einen anderen Namen geben.

Init.lua mit eingebautem Ausstieg:

Irgendwann muss man dann ja doch mal mit init.lua arbeiten. Dann empfehle ich die folgende Ausstiegsmöglichkeit in die init.lua-Datei einzubauen

Lua-Code

print("\n\ninit.lua starts\n\nHold Pin00 low to stop boot, you got two seconds.")
tmr.delay(2000000)
if gpio.read(3) == 0 then 
  print("...boot stopped") return 
end
print("dofile('MyLuaCode.lua')")
dofile ("MyLuaCode.lua")

gpio-pin drei ist (zumindest auf dem nodeMCU-board V1.0) mit dem Flash-Taster verbunden. Das heißt wenn man direkt nach dem Anschließen der Spannungsversorgung (durch USB-Kabel bzw. nach einem Druck auf den Reset-Taster, den Flash-Taster heruntergedrückt hält, wird das Skript "init.lua" ohne Aufruf des Skriptes "MyLuaCode.lua" beendet. Damit vermeidet man das Lockout mit boot-crash-boot-crash...

Sein eigenes Programm schreibt man dann in die Datei "MyLuaCode.lua".

IDEs und serielle Kommunikationsprogramme

esplorer

ESP-lorer IDE zum erstellen von nodeMCU-Lua-Skript-Dateien: == esplorer ist eine JAVA-basierte IDE zum Schreiben von Lua-Skripts und sonstigen Steuern des nodeMCU-Boards Download hier: https://esp8266.ru/esplorer/#download

LuaLoader

Neben esplorer gibt es auch noch den LuaLoader das ist ein speziell auf nodeMCU zugeschnittenes Terminalprogramm allerdings ohne Script-Editor. Download https://github.com/GeoNomad/LuaLoader Bei https://benlo.com/esp8266/ gibt es eine Version 0.91 (wo auch immer der website-Besitzer die herhat).



Das Software-Konzept der nodeMCU-Firmware verstehen:

Für Leute die noch fast gar keine Ahnung vom Programmieren haben ist die folgende Erklärung unter Umständen anspruchsvoll zu verstehen. Meine Meinung zu so einem Wiki: Man muss immer einen Kompromiss machen zwischen den Polen erkläre die fundamentalsten Grundlagen was ein Bit und ein Byte ist und "mit Fachausdrücken um sich werfen auf höchstem Niveau". Dabei kann man es nie allen recht machen. Dem einen ist es zu ausführlich der andere versteht nur Bahnhof. Nun ja wer große Schwierigkeiten beim Verstehen hat möge im Forum nachfragen oder eine andere Webseite finden die die Grundlagen "weiter unten" erklärt.

Die nodeMCU-Firmware ist auf eine bestimmte Art und Weise interaktiv. Man kann bestimmte Skripte "starten" und diese Skripte laufen dann quasi "im Hintergrund" und man kann noch weitere Dinge tun. Diese Beschreibung ist jetzt nur halbrichtig. Diese Skripte laufen nämlich nicht die ganze Zeit sondern werden nur in bestimmten gleichmäßigen Zeitabständen jeweils neu gestartet. (Programmierung über einen sogenannten Timer)

Eine weitere Möglichkeit ist Skriptteile nur dann auszuführen wenn ein bestimmtes Ereignis eintritt. Ereignis meint in diesem Zusammenhang zum Beispiel das Board arbeitet als Mini-Webserver und bekommt eine Anfrage (=Ereignis) von einem Browser "ey schick mir mal deine Webseitendefinition rüber" oder auf der angezeigten Webseite wird ein Button geklickt.

Ist die nächste "Startzeitpunkt" noch nicht erreicht bzw. tritt das Ereignis nicht ein wird auch der entsprechende Skriptteil nicht ausgeführt und in der Zwischenzeit hat die Firmware Zeit auf den PC zu "hören" ob denn über das USB-Kabel ein Befehl ankommt.


Lua-Skript Mini-Webserver mit dem man zwei GPIO-Pins ein/ausschalten kann

Webserver was ist das? Hat wohl etwas mit Internet zu tun - aber was genau ist ein "Webserver"? Nun in diesem Falle ist es eine winzig kleine Internetseite die nur eine Überschrift und vier Klick-Buttons enthält. Es geht ja auch nur um das Demonstrieren einer bestimmten Funktionalität.

Beim Austesten des Lua-Scriptes bin ich auch auf die eine oder andere "Falle" gestoßen. Das Script in der hier präsentierten Form hat schon einige Tests hinter sich und einige elementare Fehlermöglichkeiten werden abgefangen. Ich halte es aber für ziemlich wahrscheinlich, dass wenn man nur wild genug "herumtobt" immer noch Fehler finden wird oder das Script komisch reagiert oder abstürzt. Wenn jemand so etwas hinbekommt unbedingt im Forum posten. Ich (User StefanL38) bin immer daran interessiert meine Programme und Skripte zu verbessern.

Der Code enthält recht viele Kommentare. Im Konzept von nodeMCU werden die Skriptdateien im Flashrom als ASCI-Code gespeichert. Das bedeutet auch die Kommentare verbrauchen Speicher. Nun ich stehe da auf dem Standpunkt so lange noch Platz im Speicher ist kann man das Script gut lesbar gestalten und mit Kommentaren versehen. Wenn der Speicher einmal knapp werden sollte kann man immer noch Kommentare löschen.

Im Skript wird ein sogenannter Timer verwendet. Timer haben den Vorteil, dass sie die CPU nicht komplett auslasten wie zum Beispiel eine while-do oder repeat until-Schleife. Bei der Verwendung einer sehr schnellen repeat-until-Schleife in diesem Script ist mir das Board komplett abgestürzt und hat neu gebootet. Daher die Konstruktion mit einem Timer.

Der vorgeschalte Timer sorgt dafür, das das Board Zeit bekommt sich über WLAN mit dem Router zu verbinden. Erst wenn diese Verbindung steht kann man den Webserver "aktivieren" Wenn der Server aktiviert wird bevor die WLAN-Verbindung zum Router steht hängt der Webserver in der Luft und funktioniert dann doch nicht. Die Verbindung zum Router muss nach jedem Reset, Restart oder Spannungsversorgung neu anschliessen neu aufgebaut werden. Das dauert einige Sekunden. Das Skript enthält auch so einige Ausgaben über die serielle Schnittstelle die ich zum Debuggen gebraucht habe. Ich habe die Zeilen im Code gelassen damit man bei Modifizierung des Skriptes den Programmablauf besser nachvollziehen kann. Debug-Zeilen Rauslöschen geht schneller als Reinschreiben.

Achtung der Spam-Filter dieser Wiki-Software mag keinen html-Quellcode

Ich habe das Lua-Skript hier zum downloaden bereitgestellt:

ESP8266 nodeMCU Lua-Script Democode Mini-Webserver zum Ein-/Ausschalten von zwei GPIO-Pins

hier das Lua-Script ohne den html-code

wifi.setmode(wifi.STATION)
wifi.sta.config("Die SSID von deimem Router","Dein Passwort")

tmr.alarm(0, 1000, 1, function ()
   print("connecting..")
   print("wifi.sta.status()" .. wifi.sta.status())
   if wifi.sta.status() == 5 then
     print("Connected to network ")
     print("IP: " .. wifi.sta.getip())
     SetUpWebServer()
     tmr.stop(0)
   end  
end) -- of tmr.alarm(0, 1000, 1, function ()


function SetUpWebServer()

  print("enter function SetUpWebServer()")
  print("IP: " .. wifi.sta.getip())
  
  led1 = 3
  led2 = 4
  gpio.mode(led1, gpio.OUTPUT)
  gpio.mode(led2, gpio.OUTPUT)
  print("gpio.mode(led2, gpio.OUTPUT)")
  srv=net.createServer(net.TCP)
  print("srv=net.createServer(net.TCP)")
  
  srv:listen(80,function(conn)
    conn:on("receive", function(client,request)
      print("conn:on('receive'")
      local buf = "";
      local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
      if(method == nil)then
          _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
          print("string.find(request..)")
      end
      
      local _GET = {}
      
      if (vars ~= nil)then
          for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
              _GET[k] = v
          end
          print("local get for k...")
      end
      
      print("direkt vor buf = buf.. ESP8266 Web Server<")

hier müsste der html-Code stehen den der Webserver an den aufrufenden Broswer sendet
aber diese Wiki-Software hält das für Spam. Deshalb fehlt er hier.
Man kann sich das komplette Lua-Skript hier herunterladen

http://nodemcu-userforum.forumprofi.de/index.php?page=Thread&postID=19#post19

      print("direkt nach buf = buf ..ESP8266 Web Server<")
      
      local _on,_off = "",""
      if(_GET.pin == "ON1")then
        gpio.write(led1, gpio.HIGH);
        
      elseif(_GET.pin == "OFF1")then
        gpio.write(led1, gpio.LOW);
        
      elseif(_GET.pin == "ON2")then
         gpio.write(led2, gpio.HIGH);
         
      elseif(_GET.pin == "OFF2")then
        gpio.write(led2, gpio.LOW);
      end
      
      print("direkt vor client:send(buf);")
      client:send(buf);
      print("direkt nach client:send(buf);")
      print("direkt vor client:close();")
      client:close();
      print("direkt nach client:close();")
      collectgarbage();
      
    end)   -- of conn:on
    
    print("hinter end on connect")
  
  end) -- of srv:listen(80,function(conn)

end -- of function SetUpWebServer()


Viel Spaß beim ausprobieren. Wenn Fragen auftauchen im Forum posten