Nodejs ile Arduino
|
Konu içeriğinde anlatılan Nodejs Seri Port kütüphanesi yenisi ile güncellenmiştir. Konu sonundaki github linkinden yeni yazılıma ulaşabilirsiniz.
Merhabalar…
Bu konuda nesnelerin interneti kapsamında çokça kullanılmaya başlanan Nodejs’ e, Nodejs ile server kurmaya ve kütüphaneler yardımı ile basit bir uygulamaya yer vereceğiz. Öncelikle Node JS’ in ne olduğuna değinelim.
Node JS Javascprit V8 Motoru’ nu kullanan non-blocking yapıda bir V8 kütüphanesidir. Non- Blocking yapıda olmasının diğer platformlara bir çok avantajı ve dezavantıjı bulunmaktadır. Bu yapının en önemli avantajı işlemi bitirmeye çalışan Thread’ ın işlemci performansını en iyi şekilde kullanmaya çalışmasıdır ki bu da bize gömülü sistemlerde çokça avataj sağlar. Ancak non blocking yapı, iki işlemi paralel gerçekleştirmek istediğimiz zaman iki ayrı javascript dosyası oluşturup bunları birbiri ile ilişkilendirerek kullanmamıza neden olacaktır. Bunu uygulamayı aşağıda gördüğünüzde üstte kurduğum cümle kadar zor olmadığını göreceksiniz.. :)
Eğer Local ağda çalışacaksınız Node Js gerçekten çok kolay kullanıma sahip bir yapıdır. Ancak Local ağ dışında bir sunucuya veri aktarmak için sadece Nodejs kullanmaya çalışıyorsanız bence yanlış yoldasınız. Global ağ kullanımı için internet iletişim protokollerini çok iyi biliyor olmanız gereklidir. Oysaki firebase gibi cloud tabanlı yapıları Nodejs ile birlikte kullanmak bu iş için son derece kolaylık sağlayacaktır.
Şimdi gelelim local ağda kullanmak üzere yapacağımız basit bir uygulamaya. Bu uygulamada bazı framework’ ler kullanacağız. Peki ya framework nedir? Framework kütüphanelerin biraz daha büyük halidir. Kütüphane bir iş için özelleşmişken framework bir çok işi bir arada yapabilir. Buna en basit örnek internette de sıkça karşılaşabileceğiniz sınıfların bir araya gelmesi ile oluşan yapı namespace ise, namespace’ lerin bir ara gelmesi ile oluşan yapı framework’ tur. Peki biz hangi framework leri kullanacağız?
-Express
-Socket.io
–Serialport
Express bir backend framework’ udur. Oluşturacağımız sitenin backend kısmı yani server kısmı bu framework içerisinde bulunur. Bu framework olmadan da biz server’ i oluşturabilirdik. Ancak işlemlerimiz biraz daha karmaşık ve zor olurdu. Detaylı dokümantasyona buradan ulaşabilirsiniz.
Socket.io ,frontend ile backend’ in haberleşmesini sağlayan framework’ tur. Alternatifleride bulunmaktadır. Adın da anlaşıldığı gibi server ile client arası socket oluşturur.
Serialport ise seri port üzerinden bağlı olan bir cihaz ile oluşturacağımız server’ ın haberleşmesini sağlayan framework’ tur.
Kütüphanelerden de anlaşıldığı gibi yapmak istediğimiz uygulama arduino gibi seri port ta bağlı bir denetleyiciden okuğumuz veriyi web sitesine yazacağız.
Arduino için gereken koda linkten ulaşabilirsiniz. Bunu siz ihtiyacınıza göre değiştirebilirsiniz.
Şimdi gelelim javascript kısmına. Öncelikle gerekli tanımlamarı yapalım.
var express = require('express'); //express framework unu çağırdık var app = express(); var http = require('http').Server(app); //http serverı çağırıp express a bağladık var path = require('path'); //serverin kurulu olduğu dizine ulaşmak için //bu kütüphaneyi kullandık var socket = require('socket.io')(http); //socket' imizi http server a bağladık var port = 3000; //kullanacağımız portu belirledik
Bu işlemlerden bi aşağıdaki fonksiyonu kullanmalıyız.
app.use(express.static(path.join(__dirname)));
Bu fonksiyon server’ ın bulunduğu dizinde html dosyasının istediği ek dosyaları (css, resim ve alt klasörler) client’ e gönderir. Daha sonra client’ in serverdan hangi dizini istediğini ve ona göre html dosyası gönderme işlemini yapalım.
app.get('/', function(req ,res) { res.sendfile (__dirname + '/index.html'); //index.html dosyasını client' e '/' //isteği üzerine gönderdik });
Bu fonksiyon yardımı ile adres çubuğuna “www.elektrobot.net/” yazıldığında gönderilecek html dosyasını belirleyebiliriz.
Bunu yaptıktan sonra port’ u bulup Arduino’ ya bağlanalım. Bu aşamadan sonra işlemler kalıp olarak ilerlediği için parça parça anlatmayacağım. Kodu biraz incelemeniz halinde yorum satırları yardımı ile de rahatça anlaşılabilir.
Bazı arkadaşlardan portun açılmaıdğı şeklinde bazı geri bildirimler aldım. Bunun en büyük sebebi portu açabilmek izin vermiyor olmanızdır. Bu izni bu şekilde porta verebilirsiniz.
sudo chmod a+x /dev/tty*
NOT: Bu nodejs de kullanılan bir fonksiyon değil bash komutudur. Yani ubuntu işletim sisteminde terminalden girmelisiniz!!! En sondaki tty* ifadesi tüm portlara izin verilmesini sağlar. Arduino’ nun bağlı olduğu portu biliyorsanız tty* ifadesini port ismi ile değiştirerek sadece o porta izin verilmesini sağlayabilirsiniz.
Şimdi koda geçebiliriz.
var com = require("serialport"); //seri port kütüphanesini çağırdık var portName = "/dev/ttyACM0"; //default port adı var serialPort; var ledDurum = false; //var olan portları arayıp sonuncuya bağlandık //eğer bağlantı hatası alıyorsanız bu kısmı silin ve portu kendiniz girin com.list(function (err, ports) { ports.forEach(function(port) { //console.log(port.comName); portName = port.comName; }); }); //eğer üstteki kodda hata ile karşılaşırsanız burayı kendinize göre değiştirin //portName = /dev/ttyACM0 //portun bulunabilmesi için 1 sn gecikme verdik setTimeout(function(){ serialPort = new com.SerialPort(portName, { baudrate: 9600, parser: com.parsers.readline('\r\n') }); //hata varsa hatayı gösterdik yoksa porta bağlandık serialPort.on('open',function(error) { if(error) console.log("failed to open" + error); else console.log('Port open'); }); }, 1000);
Ben uygulamada bütün kodu tek bir javascript dosyasında toplayacağım. Ancak siz daha büyük projeler de bu dosyası ayrı bir javascript dosyasında çalıştırarak sanki bir kütüphaneymiş gibi server’ ın kuluru olduğu javascript dosyasından çağırabilirsiniz. Bunun için “module.exports” ile fonksiyonları dışarıdan kullanılabilir hale getirebilirsiniz ki benim tavsiyem bu şekilde kullanamızdan yanadır. Çünkü sürekli olmasını istediğiniz işlemlerde (döngüler) bütün işlemi tek bir javascript toplamanız sorun oluşturacaktır. Çünkü yukarıda da belirttiğimiz Node Js non-blolcking yapıdadır ve siz herhangi bir sonsuz döngü tanımlarsanız diğer işlemler aksayacaktır.
Bağlantımızı yapıp veri alış verişine hazır hale geldikten sonra socket bağlantısını oluşturabiliriz. Bunu aşağıdaki şekilde basitçe yapabiliriz.
socket.on('connection', function(io){ console.log("Biri baglandı"); //led butonuna basılmışsa led durumunu değiştir io.on('_led', function(){ //client ten gelen _led isimli event console.log("Butonuna basıldı"); if(serialPort.isOpen()) { serialPort.write("#\n"); //arduino ya led yanması için # gönderdik ledDurum = !ledDurum; io.emit('_ledRes', ledDurum == true ? "Led yandı" : "Led sondu"); } }); //pot butonuna basılmışsa pottaki değeri okuyup geri dön io.on('_pot', function(){ //client ten gelen _pot isimli event console.log("Butona basıldı"); if(serialPort.isOpen()) { serialPort.write("$\n"); //arduino ya A0 dan veri okuması için $ gönderdik serialPort.on('data', function(_data) { io.emit('_potRes', _data); //client e geri arduino dan data //gönderdik }); } }) });
Not: Örnekte “$” ve ” #” işaretleri ile arduino’ ya işlem yaptırma benim arduino için yazdığım kod ile ilgilidir. Siz bunları kendinize göre değiştirebilirsiniz(1,2, a, s, !, * …. yapabilirsiniz). Yani siz arduino’ ya benim verdiğim programı yüklemezseniz yada ona benzer bir iletişim kurmazsanız # ve $ işaretini seri porttan göndermeniz ile herhangi bir işlem gerçekleşmeyecektir.
Burada soketlerde kullanılan ‘_led’, ‘_pot’, ‘_ledRes’, ‘_potRes’ tamamen benim atamış olduğum isimlerdir. Bunları soketlere verdiğimiz isimler olarak düşünebilirsiniz. Eğer ki siz bir soket bağlantısı oluşturmak istiyorsanız server ve client’ te aynı isimli soketiniz olmalıdır. Aksi taktirde iletişim kuramazlar.
‘connection’ socket.io’ da tanımlı bağlanma event’ idir. Birisi sokete bağlandığında varsa bu event çağrılır ve içerisindeki işlemler gerçekleştirilir. Farklı event’ ler için socket’io‘ nun sitesine bakabilirsiniz.
“on” socket.io’ da tanımlı uyanma fonksiyonudur. “emit” ise gönderme fonksiyonudur. Yani siz ’emit’ ile gönderdiğiniz bir değeri client yada server tarafından on ile almanız gereklidir.Tersi şekilde kullanılmazlar. Farklı fonksiyonlar için socket.io‘ nun sitesine bakabilirsiniz.
Son olarak da portu dinlemeye başladık.
http.listen(port,function(){ console.log("Listeining: ", port); });
Server kısmındaki kodun tamamına buradan ulaşabilirsiniz.
Web (client) kısmında ise haberleşme için sadece javascript kısmını göstereceğim. Siz HTML ve CSS ‘ i istediğiniz gibi düzenleyebilirsiniz.
var socket = io.connect("http://localhost:3000"); //pot butonu basılmışsa _pot event i gönderdik function potFunction() { socket.emit('_pot', { }); } //led butonunas basılmışsa _led event i gönderdik function ledFunction() { socket.emit('_led', { }); } //A0 daki değeri geri okuduk socket.on('_potRes', function(_data) { document.getElementById('potDeger').innerHTML = _data; }); //ledin durumunu geri okuduk socket.on('_ledRes', function(_data){ document.getElementById('led').innerHTML = _data; });
Client kısmındaki kodun tamamına buradan ulaşabilirsiniz.
Server kısmındaki kodun tamamına buradan ulaşabilirsiniz.
İşlemler gördüğünüz üzere son derece basit. Farklı işlemler için istediğiniz gibi özelleştirebilir ve istediğiniz yerde kullabilirsiniz. Buna en güzel okulumuz araç takımı ile yaptığımız aracın telemetri sisteminde buna benzer bir yapı kullanarak verileri internet ortamına aktardık ve her yerden erişilebilir hale getirdik. Tabi bu firebase’ i öğrenmeden önceydi.. :)
Umarım yardımcı olabilmişimdir.
Teşekkürler..
Merhaba
Ben arduino kullanımı değil de sadece seri porttaki bir teraziden senkronize veri almak istiyor. VB.Net te bu işlemi yapabilmeme rağmen asp.net te yaptığımda client’ın seri portuna ulaşamıyorum. Bunu node.js ile yapabilir miyim? node.js ile seri port listesi ve seri porttaki veriyi web sayfasında client üzerinde çalıştırabilir miyim?
Merhaba, .Net framework leri ile çalışmadım ve bilgi sahibi değilim. Ancak NodeJs ile bu işlemi senkron veya asenkron olarak rahatlıkla gerçekleştirebilirsiniz. Sadece teraziden gelen verinin formatını biliyor olmanız gerekir. Gerisi bu veriyi parçalama yeteneğinize kalmıştır.
İyi çalışmalar dilerim..
Cevabınız için çok teşekkür ederim. Gelen verinin formatını biliyorum local de çalıştırdım zaten. Node.js ile seri portları listeleme ve okuma için örnek var mı elinizde? .net uyarlamasını bir şekilde yapmaya çalışırım.
İyi çalışmalar dilerim.
Merhaba, bağlantıdan istediğiniz örneğe ulaşabilirsiniz. Ek sormak istediğiniz şeyler olursa baser61061@gmail.com adresinden sorarsanız sevinirim. İyi çalışmalar dilerim…
Merhaba elektronik sayaçları rs485 portu veya optik porttan okumam gerekli yardımcı olabilirmisiniz veya ticari olarak bu tarz işler ile uğraşan birine yönlendirebilirmisiniz?
Merhaba, Bhasettiğiniz sayaçları nodejs ile okumanız mı gerekli yoksa herhangi bir mikrodenetleyici ile okumanız mı? İkincisi için basit bir rs485 ttl dönüştücüyü Arduino’ ya bağlamanız yeterlidir.(Arduino ile okuma yaptığınızı varsayarsak) İlki için Nodejs çalıştırılabilir bir gömülükart ve ya bilgisayar kullanmanız gerekecek bu durumda rs485 den usb dönüştürücü kullanmanız gerekir. Gerisi normal usb den okuma şeklinde olacaktır. Diğer sorularınız için mail üzerinden ulaşabilirsiniz. İyi çalışmalar dilerim..
Merhaba;
Node.js ile arduinodan kendi server’uma nasıl veri gönderip server tarafında da bunu nasıl yakalayabilirim?
Merhaba, geç dönebildiğim için kusura bakmayın biraz yoğun bir dönemdeyim. Lakin yorumu yazdığınız konu zaten istediğiniz işlemi gerçekleştirmiyor mu. Yada özel olarak yapmak istediğiniz bir şey daha mı var? Sorularınızı baser61061@gmail.com adresine gönderirseniz daha erken dönüş yapmaya çalışabilirim. İyi çalışmalar dilerim…
yazı için teşekkürler. Burada arduinoya seriport üzerinden veri gönderip led in yakıp söndürebiliyoruz. Ok çok güzel ben bunun yanında birde arduinodan seri port üzerinden veri okumak istiyorum. Örneğin html sayfamda nem göstergesi ve bir led kontrol butonu olmasını istiyorum. bunu ayrı ayrı yapabiliyorum fakat tek bir server üzerinde yapamadım bilginiz var mı bu konuda. seri porta hem veri gönderip hem de aynı anda nasıl okuyabilirim. İyi günler.
Merhaba, dikkat ederseniz yazılımda sadece led yakıp söndürülmüyor. Bir buton ile led yanıp söndürülebilirken diğer buton ile potansiyometre değeri çağrılabiliyor. Siz bu potansiyometre değerini çağırma işlemini javascript’ te buton click eventinden çıkartıp bir interval ile belirli aralıklarla çağırırsanız zaten istediğiniz şeyi yapmış olacaksınız. Sadece potansiyometre değeri yerine Arduino’ da size lazım olan değişkeni yazdırmanız gerekecektir. İyi çalışmalar dilerim…