NodeMCU ile Lua ve MicroPython

 


NodeMCU, üzerinde ESP8266-12E/F modülünü içeren bir geliştirme kartıdır. Daha önce bu kartı Arduino IDE ile programlayarak modbus TCP slave yapmıştık. Bacak özellikleri, usb sürücü yükleme gibi detaylar için o yazıya bakabilirsin.

Kartın fiyatı oldukça düşük 3$ civarında bulunabiliyor. Daha gelişmiş özelliklere sahip ESP32 ise 6$ civarında piyasada bulunabiliyor. NodeMCU, Arduino IDE dışında Lua ve Micropython ile de programlanabiliyor. Dosya sisteminin kolay bir şekilde kullanılması ve utf-8 formatını desteklediğinden Micropython ortamı daha çok hoşuma gitti. Diğer taraftan örneğin kartı, tcp-seri port çevirici yapan Lua kodu (tcp2uart.luagerçekten işe yarıyor. Benzer bir kodu Micropython için internette bulamadım. 

Gereken dosya kurulumlarını Windows 10 ortamında yaptım ama dosyalar Linux veya Mac ortamına da kurulabiliyor. Kart üzerinde wifi, seri port, GPIO, I2C, SPI, PWM, ADC gibi özellikler bulunuyor. Cihaz, access point veya station modunda çalışabiliyor. Access point modunda, cihaza bilgisayarın wifi’si ile bağlanabilirsin ama internet bağlantısı yoktur. Station modunda, cihaz, mevcut access point'e bağlanarak internete çıkabilir demek oluyor.


ESP'ye Lua firmware yükleme

Kartı ilk aldığınızda içinde Lua firmware yüklü olabilir. Arduino IDE ile programladığınızda, IDE bu firmware'i siliyor. Neyse ki tekrar yüklenebiliyor. esptools.rar dosyasını videonun açıklamasından veya buradan indirebilirsin.. İndirilen dosyanın içinde Lua'nın eski firmware'i var. Daha yeni firmware indirmek için https://nodemcu-build.com/ sitesini kullanabilirsin. Bu sitede email adresini verirsen seçtiğin modüllerle derlenmiş .bin dosyası sana mail atılıyor. Lakin yeni firmware ile bazı komutların kullanımı değişmiş gözüküyor. Yeni firmware ile ilgili güncel dökümantasyon, https://nodemcu.readthedocs.io/en/release/ sitesinde bulunuyor. İnternette bulunan kodlarda daha çok eski firmware kullanıldığından, eski firmware'i kullanmak daha mantıklı olabilir. Örnek bazı kodlara buradan bakabilirsin.

ESP8266Flasher.exe ile firmware dizininde bulunan dosyayı cihaza yükleyebilirsin. Operation sekmesinde kartın bağlı olduğu com portu seçmen gerekiyor. (Aygıt yöneticisinden bakabilirsin) Config sekmesinde de .bin dosyasını seçtikten sonra, Flash butonuna tıklaman gerekiyor.




Artık ESPlorer.jar dosyasına çift tık yaparak cihaza bağlanabiliriz. Öncesinde bilgisayarda Java yüklü değilse yüklemek gerekiyor. Resimdeki gibi eski firmware'i yüklediysen ESPlorer'da baud 9600 seçilmelidir. Baud ve com port seçildikten sonra kart üzerinde RST (reset) butonuna basınca aşağıdaki görüntü gelmelidir. (nodemcu-build sitesinden indirilen güncel firmware'ler için baud 115200 olmalıdır)





Lua programlama ortamımız hazır...




Lua örnek kodlar

Aşağıdaki kodu, ESPlorer'da soldaki pencereye yapıştır. Ardından, sol altta bulunan Send to ESP butonuna tıkla. Kod, karta yüklenecek ve dahili led yanıp sönmeye başlayacaktır. Kartta RST butonuna basarsak program tekrar çalışmaz. Programın, cihaz açıldığında otomatik olarak çalışması için yine sol altta bulunan Save to ESP butonuna basıyoruz. Ardından dosya ismi olarak init.lua yazıyoruz. Ve Save butonuna basıyoruz. Save penceresinde hangi dizinin seçildiği önemli değil, program, cihaza yazılacaktır.


flag=0
pin=4
gpio.mode(pin,gpio.OUTPUT)
tmr.alarm(1,1000,tmr.ALARM_AUTO,function()
    if flag==0 then
       flag=1
       gpio.write(pin,gpio.LOW)
       print("LED_ON")
    else
       flag=0
       gpio.write(pin,gpio.HIGH)
       print("LED_OFF")
    end
 end)

Sağdaki pencere, terminal ekranı gibi davranır. Burada her saniye cihaz, LED_ON, LED_OFF yazılarını basacaktır. init.lua dosyasını silmek için soldaki pencereye file.remove("init.lua") komutunu girip Send to ESP butonuna basabiliriz. Yukarıdaki kod, yeni firmware ile hata verecek, çalışmayacaktır. Yeni firmware için kod, aşağıdaki gibi olmalıdır.



flag=0
pin=4
gpio.mode(pin,gpio.OUTPUT)
tmr.create():alarm(1000,tmr.ALARM_AUTO,function()
    if flag==0 then
       flag=1
       gpio.write(pin,gpio.LOW)
       print("LED_ON")
    else
       flag=0
       gpio.write(pin,gpio.HIGH)
       print("LED_OFF")
    end
 end)

Lua'da pinler, kart üzerinde yazdığı gibidir. Dahili led, D4 pinine bağlıdır. Micropython'da ise D4 yerine, GPIO02 yani 2 nolu pin kullanılır. (En üstteki resime bakın)

print(tmr.time()) komutu ile cihazın kaç saniyedir açık olduğu bilgisini alabilirsin. print(node.flashsize()) komutu, flash hafızanın toplam kapasitesini byte olarak verecektir. NodeMCU'da bunun 4MB olduğunu göreceksin. Çift tire (--) ile satırlara yorum ekleyebilirsin.. Lua'da string'ler immutable olur yani değiştirilemezler.


a = "one string"
b = string.gsub(a, "one", "another") --> change string parts
print(a) --> one string
print(b) --> another string

a = "hello"
print(#a) --> 5
print(#"good bye") --> 8

a = "Hello"
print(a .. " World") --> hello world

a = string.rep("abc", 3)
print(a) -->abcabcabc

a = string.lower("A Long Line!")
print(a) --> a long line!

a = "[in brackets]"
print(string.sub(a, 2, -2)) -->in brackets

a = "A"
print(string.byte(a)) -->65

a = 65
print(string.char(a)) -->A

print(string.find("hello world", "world")) -->7	11

print(string.gsub("hello world", "l", ".")) -->he..o wor.d  3

a={}
for i = 1, 1000 do a[i] = i*3 end
print(a[9]) -->27

Aşağıdaki kod ile ESP, access point modunda çalışacaktır... Wifi isminde bir ağ oluşacaktır. Bu ağa bilgisayar ile bağlanın. Komut isteminde ipconfig 
yazınca, bilgisayarına bir ip verildiğini görebilirsin.


wifi.setmode(wifi.SOFTAP)
cfg={}
cfg.ssid="Wifi"
cfg.pwd="pass1234" 
cfg.save=true
wifi.ap.config(cfg)

Send to ESP butonuna tıklayıp bu kodu ESP'ye gönderdin sanırım. Aşağıdaki tcp2uart.lua kodunu cihaza yollayın. Hercules ile ESP'de 9100 nolu porta bağlantı yapınca, Hercules ile yollanan bilginin, seri porttan yani ESPlorer terminal ekranından geri geldiğini görebilirsin. (Kartı, usb kablo kullanmadan, Vin pinine 5V bağlayarak besleyebilirsin. Yine usb kablo kullanmadan, RX, TX, GND pinleri ile seri portu kullanabilirsin)



do
  uart.setup(0, 9600, 8, 0, 1, 0)
  local sv = net.createServer(net.TCP, 60)
  local global_c = nil
  sv:listen(9100, function(c)
    if global_c~=nil then
      global_c:close()
    end
    global_c = c
    c:on("receive",function(_, pl)	uart.write(0, pl) end)
  end)

  uart.on("data", 4, function(data)
    if global_c ~= nil then
      global_c:send(data)
    end
  end, 0)
end




Güncel firmware ile çalışan ESP'de çalışan Lua ortamının TLS/SSL özelliği aktif edilebiliyor. Banka web siteleri gibi bu özelliğe sahip web sitelerine güvenli (şifrelenmiş) bir şekilde girebiliyoruz. Bu sayede ESP, örneğin https:// ile başlayan https://tools.aimylogic.com/api/now?tz=Asia/Istanbul gibi bir sayfadan gelen cevabı alabiliyor. Linke tıklarsanız, internet tarayıcısında, Türkiye tarih ve saatini json formatında göreceksin. Eski firmware’de TLS özelliği yok. Güncel firmware edinmek için Nodemcu-build sitesine girip 
TLS/SSL support kutusunu tıklaman gerekiyor. Böylece gelen firmware'de bu modül aktif olacaktır. Bu özellik, bildiğim kadarıyla bilgisayarda çalışan PureBasic tarafından bile desteklenmiyor...



srv = tls.createConnection()
srv:on("receive", function(sck, c) 
  --print(c)  
  datetime = string.sub(c,string.find(c,"format")+11,string.find(c,"timestamp")-3)
  print(datetime)
  srv:close()
end)
srv:on("connection", function(sck, c)
  -- Wait for connection before sending.
  sck:send("GET /api/now?tz=Asia/Istanbul "..
           "HTTP/1.1\r\nHost: tools.aimylogic.com\r\nAccept: */*\r\n\r\n")
end)
srv:connect(443,"tools.aimylogic.com")

ESP'ye bu kodu yüklemeden önce onu station moduna alıp internete çıkışını sağlamak gerekiyor
... (ESP'ye reset attığımızda veya kapanıp açıldığına wifi bilgisi kaybolmuyor) Kod, json bilgisini web sitesinden alıp, içinden anlık tarih ve saat bilgisini terminale basacaktır. Programcılık dilinde bu işleme HTTP request deniyor. Bu kadar Lua yeter diyelim.



ESP'ye MicroPython firmware yükleme

Öncelikle Python'nun sitesinden kurulum dosyasını indirip, bilgisayara kurmak gerekiyor. Buradan ESP8266-12F (NodeMCU) için gereken .bin dosyasını indiriyoruz. (en üstte yanında latest yazan) ESP32 için farklı dosya indirmek gerekir. Şuan için en güncel olanı ESP8266_GENERIC-20241129-v1.24.1.bin dosyasıdır. İndirilen dosyanın adını ESP8266.bin olarak değiştir. Bu dosyanın, İndirilenler dizininde olduğunu farzediyorum. Komut istemini açarak aşağıdaki komutları yazın. (cd komutunu ve com port numarasını kendinize göre düzenleyin)


pip install esptool
esptool --port COM3 erase_flash
cd C:\Users\x\Downloads
esptool --port COM3 write_flash --flash_size=detect -fm dio 0x00000 ESP8266.bin

Böylece, Micropython, ESP'ye yüklenmiş olacaktır. https://thonny.org/ sitesinden thonny IDE programını indirip kurun. Tools --> Options menüsüne interpreter sekmesinde ESP8266 seçildiğinde, thonny, ESP ile otomatik olarak bağlantı kuracaktır.



Resmin alt sağ köşesinde gördüğün gibi ESP'ye bağlı olan com portu kendisi buldu. Bende View menüsünde Files ve Shell işaretli durumdadır. Artık, Shell penceresinden direk python komutlarını verebiliriz. Soldaki Files penceresinde cihazın içindeki dosyalar gösterilir. boot.py dosyası açılışta çalıştırılır. main.py dosyasını tanımlarsak o da açılışta çalışacaktır. 

Sağdaki, üstünde untitled yazan pencereye program yazıp çalıştırabiliriz. Programı yazıp F5 e basınca veya Run butonuna tıklayınca program çalışacaktır. Programı yazdık, ardından Save butonuna tıklarsak karşımıza bir soru çıkacaktır. Bilgisayara mı yoksa Micropython cihaza mı kaydedeyim ? şeklinde. Micropython cihazı seçip, dosya adı verirsek örneğin test.txt gibi, dosya ESP'ye kaydedilecek ve soldaki Files penceresinde gösterilecektir.

Üç satırlık program sayesinde, aşağıda cihazın çalışma frekansı, Shell penceresine 80MHz olarak basılmıştır. Files penceresinde, Micropython device yanındaki üç çizgiye tıklayıp ardından storage space seçeneğine tıklarsak cihaz içindeki boş hafıza miktarı gösterilecektir. Micropython firmware, 1MB alan kapladığından, geriye 3MB boş alan kalmıştır.

Shell penceresinde import machine yazıp ardından help(machine) yazarsak machine modülünün ilgili metodları, Shell penceresinde listelenecektir. Ayrıca dökümantasyon için sitesini ziyaret edebilirsin. 




MicroPython örnek kodlar

Micropython'un ESP8266 ile ilgili marifetlerini, sürücülerini görmek için quickreference sayfasına bakabilirsin.

Yorum satırları # sembolü ile belirtilir. En üstteki resimde GPIO numaraları verilmiştir. Kart üstündeki dahili LED, 2 nolu GPIO'ya bağlıdır. Yani resimde GPIO02 olarak belirtilmiştir. Aralarında boş satırlar bırakılarak farklı kod örnekleri aşağıda listelenmiştir. (Hepsini birden çalıştırmaya çalışma, sırayla çalıştır demek istiyorum)



# kart üzerindeki LED yanar GPIO2
import machine
pin=machine.Pin(2, machine.Pin.OUT)
pin.value(0)

# GPIO4 giriş pini olarak tanımlandı
# Dahili pull up nedeniyle ekrana 1 basar
# Pini GND ye değdirirsek 0 basar
from machine import Pin
p4 = Pin(4,Pin.IN,Pin.PULL_UP)
a = p4.value()
print(a)

# lib.py olarak ESP'ye kaydet
def yaz(): 
    print("merhaba")

# lib.py yi çağır
import lib
lib.yaz()

# ESP'de dosya oluşur
f = open("data.txt","w") # "a" append yapıyor
f.write("merhaba")
f.close()

# lib2.py içine kaydet
def kaydet(file,data):
    file.write(str(data))
    file.write("\n")

# lib2.py yi çağır
import lib2
f = open("veri.txt","w")
lib2.kaydet(f,99)
lib2.kaydet(f,19)
f.close()

# Dahili LED yanıp söner
from machine import Pin
from time import sleep
led = Pin(2, Pin.OUT)
while True:
   led.value(0)  #led.off()
   sleep(0.5)
   led.value(1)  #led.on()
   sleep(0.5)

# Timer kullanımı
deger = 10
from machine import Timer
tim1 = Timer(1)
tim1.init(period = 1000,mode=Timer.PERIODIC,callback = lambda t:print(deger)) #veya ONE_SHOT

# Analog digital çevirici, A0 pini kullanımı
# bu pine 0-3.3V arası bağlanabilir
# ekrana 4-1024 arasında değeri basar
from machine import Pin,ADC
from time import sleep
pot = ADC(0)
while True:
    pot_value = pot.read()
    print(pot_value)
    sleep(1)

# dahili LED yanıp söner
from machine import Pin,PWM
pwm0 = PWM(Pin(2))
pwm0.freq(1)
pwm0.duty(512)


MicroPython network bağlantısı

Firmware yüklendiğinde ESP, kendiliğinden wifi access point olarak çalışır. Varsayılan wifi parolası micropythoN dur. ESP'nin internete çıkması gerekmiyorsa bu şekilde de kullanılabilir. İnternete çıkabilmesi için ESP'yi station moduna sokmak gerekir. ESP'yi station olarak ağa bağlamak için boot.py dosyası aşağıdaki gibi düzenlenebilir.. Böylece ESP, her açıldığında otomatik olarak ağa bağlanacaktır.

# This file is executed on every boot (including wake-boot from deepsleep)
#import esp
#esp.osdebug(None)
import os, machine
#os.dupterm(None, 1) # disable REPL on UART(0)
import gc
#import webrepl
#webrepl.start()
gc.collect()
#
import network
station = network.WLAN(network.STA_IF)
if not station.isconnected():
    print("\n\nconnecting to network...")
    station.active(True)
    station.connect("kendi_wifi_ağımız","ağ_şifresi")
    while not station.isconnected():
        pass
print("My IP address : ",station.ifconfig()[0])

Thonny'de Shell penceresinde aldığı ip numarası yazılacaktır. boot.py dosyasında mevcut olan üstteki satırlara dokunmadık.. Thonny'de View-->Variables menüsüne girince network ve station objelerinin tanımlandığını görebiliriz.


MicroPython HTTP GET request

Bu kodu tcp client kodu olarak da düşünebiliriz. İnternet tarayıcı, bir web sitesine girince, gelen cevabı ekranda gösterir. Tarayıcı ile https://micropython.org/ks/test.html linkine tıklayın. Test It's working if you can read this! diye bir cevap gelecektir. Şimdi aynı şeyi ESP ile yapıyoruz. Kodu buradan aldım. 

def http_get(url):
    import socket
    _, _, host, path = url.split('/', 3)
    addr = socket.getaddrinfo(host, 80)[0][-1]
    s = socket.socket()
    s.connect(addr)
    s.send(bytes('GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n' % (path, host), 'utf8'))
    while True:
        data = s.recv(100)
        if data:
            print(str(data, 'utf8'), end='') #print without newline
        else:
            break
    s.close()

Bu kodu çalıştır.. Thonny'de View-->Variables menüsüne girince http_get fonksiyonunun tanımlandığını görebiliriz. Şimdi shell penceresinde http_get('http://micropython.org/ks/test.html') komutunu girince aşağıdaki cevap html olarak internetten ESP'ye gelecektir.


        

Test

It's working if you can read this!


TCP-RS232 çevirici

Bu program ile ESP'yi ethernet-seri port çevirici yaptım. Wifi'den gelen bilgi, seri porta aktarılacaktır. boot.py dosyasına eklediğimiz, station kodlarını çıkaralım. MicroPython isimli wifi ağına bilgisayar ile bağlanalım. ESP, tcp server olarak çalışacak, client bağlantısı kabul edecektir. Bunun için Hercules programında TCP Client sekmesini kullanabiliriz. Seri port tarafına da ESP'nin D4 pini (TXD 1) ve GND pinini alarak bir usb-seri çevirici bağlıyoruz. Çevirici üstündeki jumper'ı 3.3V a almayı unutma. Seri portu dinlemek için de yine Hercules'in Serial sekmesini kullanıyoruz.






from machine import UART
import socket
uart = UART(1, 115200) #ESP8266 D4 pini
#D4 pini ve GND yeterli olacaktır

addr = socket.getaddrinfo('0.0.0.0', 9100)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)

while True:
    cl, addr = s.accept()
    print('client connected from', addr)
    cl_file = cl.makefile('rwb', 0)
    while True:
        #satır sonunda LF veya CRLF olmalıdır
        line = cl_file.readline()
        #son satır sadece CRLF ise client
        #bağlantısı koparılır
        if line == b'\r\n':
            break
        uart.write(line)
    cl.close()
    
#sablon = """
#!A1#DC#IMSR100/40#RX0#ERN/1//0#R0/0
#T5#J5#YN102/0/35///AĞIRLIK: @agirlik KG#G#Q1#G
#"""
#string = sablon.replace('@agirlik','65')
#uart.write(string)

Yorumlar

Bu blogdaki popüler yayınlar

VBA - Mscomm (seri port) ile veri loglama

RJ45 2 - Novexx barkod yazıcıya, S7-1200 plc ile etiket yazdırma

Köpüğü alınmış Windows AtlasOS