ESP8266 mit NodeMCU: Der Espresso-Maschinen-WLAN-Schalter.

ESP8266 mit NodeMCU: Der Espresso-Maschinen-WLAN-Schalter.

Kann man Blogartikel widmen? Bestimmt… Also ich widme diesen Artikel Raffael – einem richtig duften Typen, der mir über die Jahre immer wieder weitergeholfen hat. Hier entlang zu seinem Blog: code-bude.net

UPDATE 30.09.2015: Mit Rafaels Hilfe hab ich auch den PHP-Code und folglich die Pushbullet-Notifications zum laufen gebracht und den Artikel entsprechend aktualisiert.

UPDATE 06.10.2015: Durch meine Espresso-Statusmeldungen wurde Pushbullet etwas zugespamt. Pushbullet Channels sind hier die Lösung für mich, so werden Statusmeldungen und die eigentlichen Pushbullet-Inhalte getrennt.

Warum das ganze?

Jeden Sommer verbringt man Stunden damit, Blumen zu gießen. *Gedankenblitz* man könnte das automatisieren… Nach viel Rumgooglen setzt sich ein Plan zusammen und als Nebenprodukt wird mir das erste Mal bewusst, dass es sowas wie Arduinos gibt. Also, wie wäre es mit einem WLAN-Sensor für Bodenfeuchtigkeit und Temperatur? Teile bestellt, aber der Code dafür scheint etwas kompliziert. Und da kam mir die Idee, wie wäre es, wenn ich meine Espresso-Maschine über das WLAN anschalten könnte?! Perfektes Übungsprojekt.

Der Leser sei an dieser Stelle vorgewarnt, dass ich gar keine Ahnung von dem Ganzen hab und somit meine Lösungen etwas krud sein können. Für Tipps bin ich immer dankbar.

Es gibt viele verschiedene Möglichkeiten, den ESP8266 mit Firmware zu versehen. Ich hab mich – ohne viele Hintergedanken – für NodeMCU entschieden. Ein Lua-Interpreter für den ESP8266.

 

Mein Vorgehen

Die Idee

Meine Espresso-Maschine muss ca. 5 Min vorheizen, damit der Espresso wirklich gut schmeckt. Man muss also aufstehen, die Maschine anmachen und warten oder weiterarbeiten gehen und dann vergessen, dass man sie angemacht hat. (Deshalb hatte ich sie schon an einer 20-Min-Countdown-Schaltuhr.)

Jetzt kann ich meine Espresso-Maschine von überall über eine Website anmachen oder z.B. per Automate wenn ich morgens meinen Nachtmodus verlasse oder auch mit Sleep as Android und Tasker wenn man seinen Wecker ausmacht oder ganz klassisch einen Button drücken. Ein Relais schaltet die Maschine an, eine LED leuchtet 5 Min orange (nach Ablauf der Aufwärmzeit soll eine Pushbullet-Note versendet werden), dann 13 Min grün und dann, kurz bevor sie wieder ausgeht, 2 Min rot. Ausschalten geht auch über Website oder Button.

Ich hab eine kaputte Funkstekdose, in die soll das dann alles mal rein. Aber davon sind wir noch etwas entfernt.

Verbindung zum PC

Ich hab ein ESP8266-ESP201; nach etwas Rumprobieren und einem kaputten Netzteil (das war allerdings ein wirklich dummer Anfängerfehler) funktioniert dies für mich gut:

USB-Seriell-Wandler:

GND <-> GND
TX <-> RX
RX <-> TX
DTR <-> IO 0

Stromversorgung:

3,3 V <-> 3,3 V
IO 15 <-> GND
CHP_EX <-> 3,3 V
GND <-> GND

Anleitung NodeMCU auf den ESP8266 zu flashen:

http://www.barissanli.com/electronics/nodemcu.php

Es kann sein, dass man, nachdem man auf „Flash“ geklickt hat, die „CHP_EX <-> 3,3 V“- oder die „IO 15 <-> GND“-Verbindung nochmal rein- und rausstecken muss. (Es gibt schlaue Leute, die dafür einen Button nutzen.)

Das Programm

Die komfortabelste Art, sich mit dem ESP8266 zu verbinden, ist Esplorer.

Meine ersten Gehversuche hat dieser Artikel begleitet. Auch hilfreich ist die NodeMCU API.

Das Grundgerüst für meine init.lua hab ich von hier:

print("2 sec until execution.")
tmr.alarm( 1 , 30000 , 0 , function()end)

-- Most of the Code comes from: https://primalcortex.wordpress.com/2014/12/30/esp8266-nodemcu-and-lua-language-and-some-arduino-issues/

-- Constants
SSID    = "SSID" 
APPWD   = "password"
CMDFILE = "Switch.lc"   -- File that is executed after connection

-- Some control variables
wifiTrys     = 0      -- Counter of trys to connect to wifi
NUMWIFITRYS  = 200    -- Maximum number of WIFI Testings while waiting for connection

-- Change the code of this function that it calls your code.
function launch()
  print("Launch!")
  print("Connected to WIFI!")
  print("IP Address: " .. wifi.sta.getip())
  dofile(CMDFILE)
end

function checkWIFI() 
  if ( wifiTrys > NUMWIFITRYS ) then
    print("Sorry. Not able to connect")
  else
    ipAddr = wifi.sta.getip()
    if ( ( ipAddr ~= nil ) and  ( ipAddr ~= "0.0.0.0" ) )then
      -- lauch()        -- Cannot call directly the function from here the timer... NodeMcu crashes...
      tmr.alarm( 1 , 500 , 0 , launch )
    else
      -- Reset alarm again
      tmr.alarm( 0 , 2500 , 0 , checkWIFI)
      print("Checking WIFI..." .. wifiTrys)
      wifiTrys = wifiTrys + 1
    end 
  end 
end

print("-- Starting up! ")

-- Lets see if we are already connected by getting the IP

ipAddr = wifi.sta.getip()
if ( ( ipAddr == nil ) or  ( ipAddr == "0.0.0.0" ) ) then
  -- We aren't connected, so let's connect
  print("Configuring WIFI....")
  wifi.setmode( wifi.STATION )
  wifi.sta.config( SSID , APPWD)
  wifi.sta.autoconnect(1)
  print("Waiting for connection")
  tmr.alarm( 0 , 2500 , 0 , checkWIFI )  -- Call checkWIFI 2.5S in the future.
else
 -- We are connected, so just run the launch code.
 tmr.stop(0)
 launch()
end
-- Drop through here to let NodeMcu run

Das eigentliche Programm:

-- Variable to display the current state
status = "off"

print("Switch start")

-- Turn the LED off.
pwm.setup(6, 100, 1000)
pwm.start(6)
pwm.stop(6)
pwm.setup(7, 100, 0)
pwm.start(7)
pwm.stop(7)
pwm.setup(5, 100, 300)
pwm.start(5)
pwm.stop(5)

-- Setup the Button
PIN_BUTTON = 1 -- GPIO5
TIME_ALARM = 150 -- Frequency of polling
gpio.mode(PIN_BUTTON, gpio.INPUT, gpio.PULLUP)
button_status = "off"
button_state = 0

-- Button function
-- unless pushed button_state_new is 1
function buttonHandler()
 button_state_new = gpio.read(PIN_BUTTON)
 -- If Button is pressed and hasen't been pressed before, call on(), else call off
 if (button_state == 0 and button_state_new == 0) then
 print("Button on")
 on()
 elseif (button_state == 1 and button_state_new == 0) then
 print("Button off")
 off()
 end
end

tmr.alarm(6, TIME_ALARM, 1, buttonHandler)

-- WLAN is checked every 100000 ms
function connected()
 print("Verbindung wird überprüft")
 ipAddr = wifi.sta.getip()
 if ( ( ipAddr == nil ) or ( ipAddr == "0.0.0.0" ) ) then
 -- We aren't connected, so let's connect
 print("Verbindung wird wiederhergestellt")
 wifi.setmode( wifi.STATION )
 wifi.sta.config( SSID , APPWD)
 wifi.sta.autoconnect(1)
 else
 print("Verbindung stabil")
 end
end

tmr.alarm(2, 100000, 1, connected)
 

 -- Setup PIN 2 an for Relay on GPIO4
gpio.mode(2, gpio.OUTPUT)


-- HTTP-Stuff
srv = net.createServer (net.TCP, 30)

srv:listen(80,function(conn)
 conn:on("receive", function(client,request)
 local buf = "";
 local _, _, method, path, vars = string.find(request, "([A-Z]+) (.+)?(.+) HTTP");
 if(method == nil)then
 _, _, method, path = string.find(request, "([A-Z]+) (.+) HTTP");
 end
 local _GET = {}
 if (vars ~= nil)then
 for k, v in string.gmatch(vars, "(%w+)=(%w+)&*") do
 _GET[k] = v
 end
 end
 buf = buf.."<h1> Café Faultier</h1>";
 buf = buf.."<p>Status: "..status.."</p><br>";
 buf = buf.."<p>Espresso-Maschine <a href=\"?pin=ON1\"><button>ON</button></a>&nbsp;<a href=\"?pin=OFF1\"><button>OFF</button></a></p>";
 local _on,_off = "",""
 if(_GET.pin == "ON1")then
 -- Send Pushbullet Notification. Only if switched on via HTTP
 conn=net.createConnection(net.TCP, 0) 
 conn:on("receive", function(conn, payload) print(payload) end )
 conn:connect(80,"192.168.2.4")
 conn:send("GET /iot/pushit.php?title=Espresso&msg=Maschine%20ist%20an HTTP/1.1\r\nHost: 192.168.2.4\r\nConnection: close\r\nAccept: */*\r\n\r\n")
 on()
 elseif(_GET.pin == "OFF1")then
 off()
 end
 client:send(buf);
 client:close();
 collectgarbage();
 end)
end)

-- Create the color orange with PWM
function orange()
 print("Aufwärmen")
 status = "Aufwärmen"
 pwm.setup(6, 100, 1000)
 pwm.start(6)
 pwm.setup(7, 100, 0)
 pwm.start(7)
 pwm.setup(5, 100, 300)
 pwm.start(5)
end

-- Create the color red with PWM
function green()
 -- Send Pushbullet Notification
 conn=net.createConnection(net.TCP, 0) 
 conn:on("receive", function(conn, payload) print(payload) end )
 conn:connect(80,"192.168.2.4")
 conn:send("GET /iot/pushit.php?title=Espresso&msg=Maschine%20ist%20aufgewaermt HTTP/1.1\r\nHost: 192.168.2.4\r\nConnection: close\r\nAccept: */*\r\n\r\n")
 print("Betrieb")
 status = "Betrieb"
 pwm.stop(6)
 pwm.stop(7)
 pwm.setup(5, 100, 500)
 pwm.start(5)
end

-- Create the color red with PWM
function red()
 print("Bald aus")
 status = "Bald aus"
 pwm.stop(5)
 pwm.stop(7)
 pwm.setup(6, 100, 500)
 pwm.start(6)
end

-- Turn off relay and LEDs, set button_count to 0
function off()
 button_state = 0
 button_status = "off"
 gpio.write(2, gpio.LOW)
 pwm.stop(5)
 pwm.stop(7)
 pwm.stop(6)
 tmr.stop(3)
 tmr.stop(4)
 tmr.stop(5)
 button_count = 0
 status = "off"
 print("off end")
end


-- Turn on relay, LEDs and Timer. Set button_state = 1
function on()
 button_state = 1
 button_status = "on"
 gpio.write(2, gpio.HIGH)
 orange()
 tmr.alarm(3, 300000, 0, green)
 tmr.alarm(4, 1080000, 0, red)
 tmr.alarm(5, 1200000, 0, off)
 status = "on"
 print("on end")
end

Meinen Code findet man auch bei Github.

Push Notification

Alles läuft soweit, aber ahnungslose Ilans wollen gerne immer mehr lernen. Mir ist aufgefallen, dass es doch genial wäre, wenn man eine Notification bekommt, wenn die Maschine aufgewärmt ist. Pushbullet nutze ich seit langem, um mir Notifications von meinem Handy auf dem PC anzeigen zu lassen. Vielleicht ist da was möglich. Es scheint so zu sein, dass der ESP8266 die Pushbullet API nicht direkt nutzen kann (die technischen Gründe dafür hab ich nicht so ganz verstanden).

Man könnte Daten unverschlüsselt an einen Thinkspeak-Account schicken und von dort eine Pushbullet Notification schicken.

Eine andere Möglichkeit ist, dies über ein PHP-Skript von einem lokalen Server aus zu machen. Was ein Anreiz, PHP zu lernen! Wild rumgegoogelt, gelernt, was eigentlich GET-Requests sind, PHP-Pushbullet-Library gefunden, über cURL und Composer gelernt, wild rumprobiert und es funktioniert noch nicht. Rafael hatte eine einfachere Lösung für das Problem, ganz ohne Library usw. gefunden und sie funktioniert fantastisch.

Hier mein Code:

<?php 
$title = $_GET["title"];
$msg = $_GET["msg"];
shell_exec("curl -u API-TOKEN: https://api.pushbullet.com/v2/pushes -d channel_tag="CHANNEL-NAME" -d type=note -d title=\"".$title."\" -d body=\"".$msg."\" "); 
?>

 

Nun kann ich über  „<raspberrypi-ip>/pushit.php?title=“Titel“&msg=“Nachricht““ beliebige Nachrichten als Pushbullet-Notification verschicken.

 

Jubiläums-Selfies
Venedig - Tag 1: Ab nach Venedig!

Kommentar verfassen