ESP8266, Lua ve Cep Telefonu

Ve evet beklenen gerçekleşti ve ESP8266 çipi için herkesin kullanabileceği bir yazılım arayüzü ve programlama dili kullanıcılara sunuldu. SDK gerçi daha önce çipin üreticisi olan Espressif Systems tarafından yayımlanmıştı ama çok da kullanılabilir değildi. Peter Jennings Lua script dilini kullanabilen bir firmware geliştirerek ESP8266 çipini bir kaç basamak yukarıya taşımayı başardı. İlk denemelerimde gayet kararlı ve güzel bir ortamın geliştiricilere sunulduğunu söylemek isterim. Bu IoT çalışmalarında oldukça kullanılacak bir çözüm olacağa benziyor. Daha önce Arduino kullanarak yaptığım örneği bu sefer başka hiç bir işlemci kullanmadan Lua ile ESP8266 üzerinde geliştireceğim. Sadece 5 dolarlık bir çip ile güzel bir IoT örneği yapmış olacağız. Çep telefonuna bir buttona basıldığında uyarı göndereceğiz.

Öneclikle Lua script dilini kullanabilmeniz için ESP8266 çipinin firmware’ini değiştirmemiz gerekiyor. Muhtemelen aldığınızda ESP8266 At komutlarını işleyen bir firmware ile gelecektir. ESP8266 firmware’ini yeniden yüklemek için nodemcu-flasher programına ihtiyacınız olacak. Bu programı işletim sisteminize göre aşağıdaki linklerden indirebilirsiniz.

ESP8266Flasher.exe for Win32

ESP8266Flasher.exe for Win64

ESP8266 çipine yeni Firmware yüklemek için dikkate edilmesi gereken bir husus daha var. Çipin GPIO0 bacağını GND ye çekmeniz gerekmekte. Çipile seri iletişim kurmak için daha önceki yazılarımda da belirttiğim 3.3v USB UART çeviriciyi kullanıyoruz. işte bağlantı resmi;

 

esp8266-reflash-firmware

 

Sarı yazı ilede belirtildiği gibi çipin GPIO0 pacağını GND ye sadece firmware atarken bağlıyoruz. Normal kullanımda GND ye çekmiyoruz.

Ortam ve devre bağlantısı hazır olduğuna göre ESP8266 Lua anlar hale getirebiliriz. USB UART çeviricinizi bilgisayara tanıtmışsanız bağladığınızda bir Com port oluştuğunu göreceksiniz. modencu-flasher programını açıp bu komportu seçin ve Flash(F) düğmesine basın

687474703a2f2f693635392e70686f746f6275636b65742e636f6d2f616c62756d732f75753331362f766f77737461722f4e6f64654d43552d466c61736865722d426567696e2e706e67

 

 

 

 

 

 

 

 

 

 

 

Flash yüklemesi tamamlandığında ESP8266 ile bağlantı kurmak için LuaLoader.zip programını yükleyin. Artık GPIO0 GND ye bağlı olmayacak.

LuaLoader programının görüntüsü aşağıdaki gibi

 

LuaLoader

 

 

Bu program çipile oynamanız için çok güzel bir araç. Tüm detaylarını anlatmıyorum. Vakit ayırıp kurcalayın derim.

Çok kabaca çipin GPIO2 bacağını input yapmak ve oradaki akımı okumak için aşağıdaki komutları kullanıyoruz.

gpio.mode(4,gpio.INPUT,gpio.FLOAT)

gpio.read(4)

(GPIO2 için 4 kullanıyoruz. Pinlerin isimleri ve Lua da kullanılan rakamlar tutmuyor. Maping çizelgesi burada var)

Yada aynı pini Output olarak kullanmak istersek

gpio.mode(4,gpio.OUTPUT) 

gpio.write(4,gpio.HIGH)  -- GPIO2 3.3v oldu
gpio.write(4,gpio.LOW)  -- GPIO2 0v oldu

 

 

Şimdi daha önceki yazımızda yaptığımız Cep telefonuna Push Notification yollama örneğini yapalım;

http://www.prowlapp.com/ sitesine uye olup bir API Key olusturuyorsunuz. IOS uygulamasını cep telefonunuza kuruyorsunuz.

Daha sonra aşağıdaki iki dosyayı bilgisayarınıza lua uzantısı ile kopyalayın. init.lua ESP8266 ilk olarak enerjilendirildiğinde otomatik olarak çalışır. Daha sonra init.lua dosyasındaki kod bir timer’ı her 4sn de bir ateşliyor. Bu ateşleme diğer dosyanın (interupt.lua) çalıştırılmasını sağlıyor.

init.lua

wifi.sta.autoconnect(1)
print("gnexlab")
gpio.mode(4,gpio.INPUT,gpio.FLOAT)
tmr.alarm(0,6000,1,function() dofile("interupt.lua") end)

 

interupt.lua 

function push(level)
conn = nil
conn = net.createConnection(net.TCP, 0)

conn:on("receive", function(conn, payload)
success = true
print(payload)
end)
conn:on("connection", function(conn, payload)
print('\nConnected')
conn:send("GET /publicapi/add?apikey=7b0fcbc142b12c30f474c4a5c8258b6e3d9f51ad&application=ESP8266&event=Button+pressed&priority=0 HTTP/1.1\r\n"
.."Host: prowl.weks.net\r\n"
.."Accept: */*\r\n"
.."User-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n"
.."\r\n")
end)

-- when disconnected, let it be known
conn:on("disconnection", function(conn, payload) print('\nDisconnected') end)

conn:connect(80,'209.20.89.148')

tmr.delay(500000)

end

if gpio.read(4) == 0 then push(0) end

Bu iki dosyayı lua uzantılı olarak text dosyası formatında bilgisayarınıza yazdıktan sonra LuaLoader programındaki UploadFile buttonuna basarak bu iki dosayayı ESP8266 ya yükleyin.

Gelelim doanıma

esp8266_lua1_bb

 

 

Devreyi bu şekilde yapın ve çalıstırın Butona bastığınızda Cep telefonuna mesaj geldıgını göreceksiniz.

Uygulama alanları ile ilgili fikirlerinizi bekliyorum. En basitinden kapıya bağlayıp bir readröle kullanıp açıldığında cep telefonuna mesaj gelmesini sağlayabilirsiniz.

Bir çok sensör bağlamak mümkün. Iot Serüvenlerimiz Gnexlab da devam edecek.

 

 

Kaynaklar

ESP8266 İlk Denemeler

ESP8266 modülü ile ilgili genel bilgileri burada vermiştik. Şimdi ilk deneme çalışmaları ile ilgili sizleri bilgilendirmek istiyorum. Bu çip ile iletişim kurmak için seri bağlantı yapmak ve bu bağlantıdan AT komutları ile çiple haberleşmek gerekmekte. Bunu bir çok şekilde yapmak mümkün. Ben ilk olarak çipi tanımak amacıyla USB UART bir cevirici ile bağlantı kurarak çipi kurcalamaya başladım. Elimde daha önceden seeedstudio dan aldığım bir USB UART çevirici vardı. Aşağıda resmini görebilirsiniz.

 

photo 2 (4) photo 1 (6)

 

 

 

 

 

 

 

Baktım seeedstudio da halen buna benzer modüller var. Dikkat edilmesi gereken 3.3v olan modeli kullanmak. esp8266 modülümüz 3.3v olduğundan 5v ürünler kullanmamaya dikkat edilmesi gerekmekte.

ESP8266 wifi modülünü bacak bağlantılarını verelim.

 

4262791411877023544

 

USB UART modlü ile ESP8266 Wifi modülünü bağlarken;

USB UART modülü   ————    ESP8266 Wifi modülü

vcc ———————————–vcc

gnd———————————–gnd

rx————————————-txd

tx————————————-rxd

Bir önemli bağlantı da CH_PD bağlantısını modülün vcc sine bağlamak gerekmekte ben basitce bir tel lehimledim.

Bağlantıları tamamladığımıza göre modül ile ilk iletişimlerimizi kuralım. Ben bilgisayar olarak MAC kullandığım için Terminal den screen komutu ile bir haberleşme terminali açtım. Komut şöyle:

screen /dev/tty.usbserial-A800BQZZ 115200

Windows kullanıcıları için Realtherm bir seçenek olabilir. Dikkat etmeniz gereken usb modülün driverını kurmak, doğru com porta 115200 baud hızla bağlanmak. Bundan sonra terminalden şu komutları göndererek esp8266 ile haberleşebilirsiniz. (Gönderilen komutların başına > işareti koyuyorum bunları terminale biz yazıp enterliyoruz diğer mesajlar modülün geri gönderdikleri onları da italik yapıyorum.)

>AT+RST

  

OK

  

ets Jan  8 2013,rst cause:4, boot mode:(3,7)

  

wdt reset

  

load 0x40100000, len 24444, room 16

  

tail 12

  

chksum 0xe0

  

ho 0 tail 12 room 4

  

load 0x3ffe8000, len 3168, room 12

  

tail 4

  

chksum 0x93

  

load 0x3ffe8c60, len 4956, room 4

  

tail 8

  

chksum 0xbd

  

csum 0xbd

  

ready

Bu reset komutu en sonda ready mesajını alıyorsanız herşey yolunda gidiyor demektir.

Ben ev wifi networküme bağlanmak için aşağıdaki komutu kullandım.

>AT+CWJAP="NNetwork","xxxx"

OK

siz de wifi isim ve passwordünüzü bu şekilde modüle tanıtmalısınız.

Bunun gibi bir çok AT komut seti var bunların tamamını buradan görebilirsiniz.

AT komut setleri ile modüle her istediğinizi yaptırmanız mümkün mesela mevcut wifi modüllerini ve sinyal güçlerini listeletebilirsiniz.

ya da bir web servarına bağlanabilirsiniz.

Peki bu AT komut setlerini gerçek hayatta nasıl modüle gönderebiliriz? Tabiki bir mikro işlemci ile. Aslında esp8266 modülü hem mikro işlemci hem de wifi radio modülü bu çipi direkt programlayarak başka bir mikro işlemciye ihtiyaç kalmadan kullanmak mümkün. Ben bu işlemciyi programlamak yerine herkesin daha aşina olduğu Arduino yu devreye sokarak bir uygulama yaptım. Biraz ondan bahsedeyim.

Mikro işlemci için bir Arduino Mega kullandım. Birden fazla UART a sahip olduğundan bir uart ile ciple haberleşip diğeri ile ekrana debug mesajları yollamak mümkün oluyor.

Kullandığım programı aslında buradan buldum. Biraz modifiye ederek aşağıdaki şekli verdim.

 

#define SSID "NNetwork"
#define PASS "B1065f26C847" // My luggage has the same combination!
#define DEST_HOST "localhost"
#define DEST_IP "192.168.1.2"
#define TIMEOUT 5000 // mS
#define CONTINUE false
#define HALT true

// #define ECHO_COMMANDS // Un-comment to echo AT+ commands to serial monitor

// Print error message and loop stop.
void errorHalt(String msg)
{
 Serial.println(msg);
 Serial.println("HALT");
 while(true){};
}

// Read characters from WiFi module and echo to serial until keyword occurs or timeout.
boolean echoFind(String keyword)
{
 byte current_char = 0;
 byte keyword_length = keyword.length();
 
 // Fail if the target string has not been sent by deadline.
 long deadline = millis() + TIMEOUT;
 while(millis() < deadline)
 {
 if (Serial1.available())
 {
 char ch = Serial1.read();
 Serial.write(ch);
 if (ch == keyword[current_char])
 if (++current_char == keyword_length)
 {
 Serial.println();
 return true;
 }
 }
 }
 return false; // Timed out
}

// Read and echo all available module output.
// (Used when we're indifferent to "OK" vs. "no change" responses or to get around firmware bugs.)
void echoFlush()
 {while(Serial1.available()) Serial.write(Serial1.read());}
 
// Echo module output until 3 newlines encountered.
// (Used when we're indifferent to "OK" vs. "no change" responses.)
void echoSkip()
{
 echoFind("\n"); // Search for nl at end of command echo
 echoFind("\n"); // Search for 2nd nl at end of response.
 echoFind("\n"); // Search for 3rd nl at end of blank line.
}

// Send a command to the module and wait for acknowledgement string
// (or flush module output if no ack specified).
// Echoes all data received to the serial monitor.
boolean echoCommand(String cmd, String ack, boolean halt_on_fail)
{
 Serial1.println(cmd);
 #ifdef ECHO_COMMANDS
 Serial.print("--"); Serial.println(cmd);
 #endif
 
 // If no ack response specified, skip all available module output.
 if (ack == "")
 echoSkip();
 else
 // Otherwise wait for ack.
 if (!echoFind(ack)) // timed out waiting for ack string 
 if (halt_on_fail)
 errorHalt(cmd+" failed");// Critical failure halt.
 else
 return false; // Let the caller handle it.
 return true; // ack blank or ack found
}

// Connect to the specified wireless network.
boolean connectWiFi()
{
 String cmd = "AT+CWJAP=\""; cmd += SSID; cmd += "\",\""; cmd += PASS; cmd += "\"";
 if (echoCommand(cmd, "OK", CONTINUE)) // Join Access Point
 {
 Serial.println("Connected to WiFi.");
 return true;
 }
 else
 {
 Serial.println("Connection to WiFi failed.");
 return false;
 }
}

// ******** SETUP ********
void setup() 
{
 Serial.begin(115200); // Communication with PC monitor via USB
 Serial1.begin(115200); // Communication with ESP8266 via 5V/3.3V level shifter
 
 Serial1.setTimeout(TIMEOUT);
 Serial.println("ESP8266 Demo");
 
 delay(2000);

 echoCommand("AT+RST", "ready", HALT); // Reset & test if the module is ready 
 Serial.println("Module is ready.");
 echoCommand("AT+GMR", "OK", CONTINUE); // Retrieves the firmware ID (version number) of the module. 
 echoCommand("AT+CWMODE?","OK", CONTINUE);// Get module access mode. 
 
 // echoCommand("AT+CWLAP", "OK", CONTINUE); // List available access points - DOESN't WORK FOR ME
 
 echoCommand("AT+CWMODE=1", "", HALT); // Station mode
 echoCommand("AT+CIPMUX=1", "", HALT); // Allow multiple connections (we'll only use the first).

 //connect to the wifi
 boolean connection_established = false;
 for(int i=0;i<5;i++)
 {
 if(connectWiFi())
 {
 connection_established = true;
 break;
 }
 }
 if (!connection_established) errorHalt("Connection failed");
 
 delay(5000);

 //echoCommand("AT+CWSAP=?", "OK", CONTINUE); // Test connection
 echoCommand("AT+CIFSR", "", HALT); // Echo IP address. (Firmware bug - should return "OK".)
 //echoCommand("AT+CIPMUX=0", "", HALT); // Set single connection mode
}

// ******** LOOP ********
void loop() 
{
 // Establish TCP connection
 String cmd = "AT+CIPSTART=0,\"UDP\",\""; cmd += DEST_IP; cmd += "\",80";
 if (!echoCommand(cmd, "OK", CONTINUE)) return;
 delay(2000);
 
 // Get connection status 
 if (!echoCommand("AT+CIPSTATUS", "OK", CONTINUE)) return;

 // Build HTTP request.
 cmd = "Hi from Arduino long message test from the wifi modul hello"; //cmd += DEST_HOST; cmd += ":80\r\n\r\n";
 
 // Ready the module to receive raw data
 if (!echoCommand("AT+CIPSEND=0,"+String(cmd.length()+1), ">", CONTINUE))
 {
 echoCommand("AT+CIPCLOSE", "", CONTINUE);
 Serial.println("Connection timeout.");
 return;
 }
 
 // Send the raw HTTP request
 echoCommand(cmd, "OK", CONTINUE); // GET
 
 
 
 
 
 // Loop forever echoing data received from destination server.
 while(true)
 while (Serial1.available())
 Serial.write(Serial1.read());
 
 errorHalt("ONCE ONLY");
}

 

Burada gördüğünüz gibi bir UDP bağlantısı yapıyoruz. Daha sonra Node.js ile yazdığım çok basit bir UDP server ile haberleşeceğiz. İşte Node.js kodu böyle;

 

var PORT = 80;
var HOST = '192.168.1.2';

var dgram = require('dgram');
var server = dgram.createSocket('udp4');

server.on('listening', function () {
    var address = server.address();
    console.log('UDP Server listening on ' + address.address + ":" + address.port);
});

server.on('message', function (message, remote) {
    console.log(remote.address + ':' + remote.port +' - ' + message);

});

server.bind(PORT, HOST);

Node.js ile karşılaşmayanlara duyrulur javascriptin serverda çalışan şekli mutlaka vakit ayırıp bakın. Arkasında Google var ve çok gelecek vaadediyor.

Bağlantılar için benim setup ım aşağıdaki gibi:

photo (12)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Bord üzerinde bir TTL çevirici kullandım (kırmızı olan). Bunun nedeni daha önce söylediğim gibi modül 3.3v ile çalışıyor. Arduino mega çıkışları 5v. Bu voltajı modüle zarar vermemek için düşürüyoruz. İlgilenen arkadaşlar olursa daha ayrıntılı şemalar verebilirim.

Bu da çalıştırma videosu: