Üzerinde çalıştığım Mantarhane otomasyonu için özellikle istenen Co2 ölçümü üzerine epey bir araştırdıktan sonra MH-Z16 5000PPM lik sensörünü seçtim ve nihayetinde elime geçti ve biraz bızıkladıktan sonra ( biraz dediğime bakmayın aşağıda değineceğim sebeplerden dolayı 3 gün uğraştım ) çalışır hale getirebildim.
En büyük sıkıntı protonda basit kod örneklerinin olmayışı.Çoğunluk ile ardunio için hazır kütüphaneleri mevcut.Ben proton basic te donanımsal usart ile haberleştim.
Sensörden biraz bahsetmek istiyorum.Aslında datasheeti biraz kurcaladığınızda çok basit bir kullanımının olduğunu göreceksiniz...
Sensör kısaca NDIR dedikleri mantık ile çalışıyor.İç yapısında IR ışık kaynağı karşısında da alıcı kısımları mevcut bu alıcı kısımlarında önünde anladığım kadarı ile CO2 moleküllerini görecek 4.3um bir filitre mevcut..Teknolojisini fazla kurcalamadım zira evde yapabileceğimiz bir şey değil alıp kullanacağız mecburen..
Sensörün anladığım kadarı ile birkaç versiyonu mevcut.Benim elimdekinin sadece MH-Z16 olduğunu ve 5000ppm e kadar ölçüm yaptığını biliyorum.
NOT: Sensörü sipariş etmeden önce max. ölçüm aralığınızı bilmelisiniz fabrikasyon ayarlı max. sınırlı geliyor mesela 1000ppm e kadar ölçüm yapacaksanız siz yine 2000ppm felan alın derim benim max. 2000ppm gibi bir değer okumam gerekli ben ne olur ne olmaz diye 5000ppm aldım.
Sensörün besleme voltajı +5v.Üzerinde 1 adet PWM çıkışı ve Analog voltaj çıkışı ve USART serial haberleşme mevcut..
En basiti usart üzerinden direk değer okumak bana kalırsa.
NOT: resimdeki gibi V2.4 olan versiyonda Serial pinler TTL 5V.Ben elimdeki sensörün versiyonunu bilmediğim için araya çevirici yapmıştım.
Bu şekilde çalışıyor.Riski göze alıp rx tx pinlerini direk pic'in ayaklarına bağladığımda da çalıştığını gözlemledim.Sorun olmadı.
Pin bağlantısı yukarıdaki gibidir.Yeniliyorum.RX TX pinlerini ilk olarak TTL seviyesinde çalıştırmayın.En azından işlemcinin tx çıkışını gerilim bölücü direnç ile sensöre girin derim.
Evet yavaş yavaş en eylenceli yere doğru geliyoruz.. :P
Sensöre belirli komutları göndermemiz gerekiyor ve bununda bir sırası var.Yukarıdaki resim birazdan anlatacağım sıralamada BYTE2 ye verilen değerin karşılığında sensörün ne yapacağını anlatıyor.
Yani 0x86 gönderirseniz sensör co2 miktarını ölçüp serial olarak gönderiyor.Diğerlerini hiç denemedim.Kalibrasyon işlemlerine hiç kalkışmadım çünki elimde kalibrasyon yaparken kullanacağım doğruluğuna inandığım bir CO2 metre şuan için yok.
Tabi sensöre kafamıza göre veri gönderemiyoruz.Üretici firmanın belirlediği bir sıralama var sensör bu sıralamada beklediği dataları alırsa geri dönüş yapıyor.
Bunu kodda anlatmak gerekirse :
CO2_SENSOR_OKU:
DelayMS 10
HSerOut2 [$FF,$01,$86,$00,$00,$00,$00,$00,$79]
Return
Yani yukarıdaki resimdeki gibi sırası ile sensöre okuma yaptırmak için 18F24K22 nin 2. usartından sensöre gönderiliyor.
Sonrasında sensörden geri yanıt geliyor.Bu o kadar hızlı ki arada bir zaman gecikmesi vs. koymamışlar.Bu adamı gıcık ediyor.Bundan dolayı ben okuma işlemini usart interrupt ile yaptırıyorum ki gelen bilgiyi kaçırmıyım.Bunu yaparken de döngü ve ana program içinde uzun süreli bekleme komutları kullanmamaya dikkat ediyorum.Malum basic'in en muhim olayıda bu :P
Gerisini kod ile anlatmak gerek...:
Device=18F24K22
Xtal=20
All_Digital=TRUE
TRISA=0
PORTA=0
TRISB=%10000000
PORTB=0
'*****************/ 16X20 LCD /***************
Declare Hserial_Baud = 9600 ' Set baud rate to 9600
Declare Hserial_RCSTA = %10010000 ' Enable continuous receive
Declare Hserial_TXSTA = 100000 ' Enable transmit and asynchronous mode ' LCD İÇİN KULLANILACAK
Declare Hserial_Clear = On ' Clear the buffer before receiving
Declare Hserial2_Baud = 9600
Declare Hserial2_RCSTA = %10010000 ' Enable continuous receive
Declare Hserial2_TXSTA = 100000 ' Enable transmit and asynchronous mode ' DIGER HABERLEŞME İÇİN KULLANILACAK
Declare Hserial2_Clear = On ' Clear the buffer before receiving
RCSTA1.4 = 1 'Continuous Receive Enabled
RCSTA2.4 = 1 'Continuous Receive Enabled
'Symbol PEIE2 = INTCON2.6 'Peripheral(çevresel) interrupt enable bit usart kesmesi için
'Symbol GIE2 = INTCON2.7 'global interrupt enable
Symbol RCIE2 = PIE3.5 'Receiver interrupt enable bit
Symbol RCIF2 = PIR3.5 'Receiver interrupt flag
Symbol PEIE = INTCON.6 'Peripheral(çevresel) interrupt enable bit usart kesmesi için
Symbol GIE = INTCON.7 'global interrupt enable
Symbol RCIE = PIE1.5 'Receiver interrupt enable bit
Symbol RCIF = PIR1.5 'Receiver interrupt flag
' PIR1.5 ve PIR3.5
On_Interrupt GoTo KESME 'Hardware Interrupt oluştuğunda int etiketine dallan
GIE=0
PEIE=0
'********************************
Symbol CO2_ANALOG_INPUT = PORTA.0
Symbol BUZZER = PORTA.3
Low BUZZER
Symbol LED = PORTA.2
Output LED
Low LED
'******************/ DEGISKEN TANIMLAMALARI /**********************
Dim USART2_DATA[15] As Byte
Dim NEXTION_BILGI As Byte
NEXTION_BILGI=0
Dim A As Word
Dim CO2 As Word
Dim SAYAC As Byte
Dim BYTE_0 As Byte
Dim BYTE_1 As Byte
Dim BYTE_4 As Byte
Dim BYTE_5 As Byte
Dim BYTE_6 As Byte
Dim BYTE_7 As Byte
Dim CHECKSUM As Byte
CHECKSUM=0
BYTE_0=0
BYTE_1=0
BYTE_4=0
BYTE_5=0
BYTE_6=0
BYTE_7=0
USART2_DATA=0
SAYAC=0
CO2=0
A=0
'*************************/ ANA PROGRAM /*****************************
GoSub MELODI
ACILIS_BEKLE:
For A=0 To 3500
DelayMS 5
Next
GoSub MELODI
RCIE2=1
PEIE=1
GIE=1
BASLA:
For A=0 To 500
DelayMS 5
' Gas concentration= high level *256+low level
' CO2 = USART_DATA[3]* 256 + USART_DATA[2]
If SAYAC>8 Then GoSub MELODI : SAYAC=0 : GoSub BUFFER_BOSALT : GoSub CO2_GONDER : USART2_DATA=0
If NEXTION_BILGI=$10 Then GoSub MELODI : GoSub CAL_ON : NEXTION_BILGI=0
If NEXTION_BILGI=$20 Then GoSub MELODI : GoSub CAL_OFF : NEXTION_BILGI=0
Next
GoSub CO2_SENSOR_OKU
GoTo BASLA
'*****************/ KESME /**********************
KESME:
Context Save
GIE=0
PEIE=0
If RCIF=1 And RCIF2 =1 Then NEXTION_BILGI=0 : USART2_DATA=0 : GoTo EXIT
If RCIF=1 Then EKRAN_INTERUPT
If RCIF2=1 Then SENSOR_INTERUPT
GoTo EXIT
'*************/yenı/**************************
EKRAN_INTERUPT:
NEXTION_BILGI = RCREG1 : GoTo EXIT
SENSOR_INTERUPT:
USART2_DATA[SAYAC] = RCREG2 : SAYAC=SAYAC+1 : NEXTION_BILGI=0 : GoTo EXIT
'******************************************
EXIT:
GIE=1
PEIE=1
RCIF2=0
RCIF=0 'General interrupt enable bit
Context Restore
End
'**********************/ MELODI /*******************************
MELODI:
High BUZZER
DelayMS 38
Low BUZZER
DelayMS 80
High BUZZER
DelayMS 14
Low BUZZER
DelayMS 50
Return
'*************
CO2_SENSOR_OKU:
DelayMS 10
HSerOut2 [$FF,$01,$86,$00,$00,$00,$00,$00,$79]
Return
CAL_OFF:
DelayMS 10
HSerOut2 [$FF,$01,$79,$00,$00,$00,$00,$00,$86]
Return
CAL_ON:
DelayMS 10
HSerOut2 [$FF,$01,$79,$A0,$00,$00,$00,$00,$E6]
Return
SET_2000PPM:
DelayMS 10
HSerOut2 [$FF,$01,$99,$00,$00,$00,$07,$D0,$8F]
Return
SET_10000PPM:
DelayMS 10
HSerOut2 [$FF,$01,$99,$00,$00,$00,$27,$10,$2F]
Return
CO2_GONDER:
HSerOut ["n0.val=",Dec5 CO2,$ff,$ff,$ff] 'BURADA KALDIK
Return
'*************************************
BUFFER_BOSALT:
BYTE_0 = USART2_DATA[0]
BYTE_1 = USART2_DATA[1]
CO2.HighByte = USART2_DATA[2]
CO2.LowByte = USART2_DATA[3]
BYTE_4 = USART2_DATA[4]
BYTE_5 = USART2_DATA[5]
BYTE_6 = USART2_DATA[6]
BYTE_7 = USART2_DATA[7]
CHECKSUM=USART2_DATA[8]
Return
Programın kısaca özeti şu:
Giriş kısmında 2 usartı olan 18F24K22 nin usart ayarları kesme ayarları tanımlamalar vs.
- Sonrasında kesmeleri açıp ana programda for next ile uzun beklemeler ile gecikmeli olarak sensöre okuma komutu gönderip geri dönüp tekrar ana programda gelen datayı interrupt sayacını kontrol ederek sırası ile gelen byteları alıp nextion ekrana serial den göndermek.
Program devamlı bu şekilde dönüyor..
Dediim gibi gelen datalardan 2. ve 3. byte okunan co2 miktarı.Bunu da programda bir byte tanımlayıp düşük ve yüksek byteleri alıp bu word'e yerleştiriyorum sonrada yallah ekrana gönderiyorum.
Sensörün kullanımı buraya kadar kolay gibi duruyor.Fakat datasheette anlatılmayan durumlar var.
Sensör ilk açıldığında 8byte veri gönderiyor daha açıldığı gibi hemde ve hemen ardından bir süre 4 kez bana gelen ölçüm değerine baktığımda 410 bilgisini 4 defa okuyorum sensör kendini kuruyor yada kalibre ediyor sonrasında normal ölçüm degerini gönderiyor.
Benim kodumda ilk enerji verdiğimde döngüm takılıyor.Kesme kilitleniyor ekranda 5 haneli bir data görüyorum.Bunun önüne geçebilmek için açılışta gecikme koyanlarda var serialden 410 datasını 4 kez okuyanlarda var..
Ben sensörü transistör ile enerjisini kesmekten yanayım.Bilmiyorum başka bir fonksiyonuda yok gibi bu durum için.
En basit okuduğum çözüm ise sensörün beslemesini kart açıldıktan sonra vermek ve işlemcinin kendini programdaki interrupt ayarlarını kurmasına müsade etmek gibi görünüyor.
Bunun için buna benzer bir şema kullanabilirsiniz sorunsuz bir kullanım olacağına kanat getirdiğim yöntem budur..
Bu arada bu tarz şeyler ile çalışırken elinizin altında USB to Serial modül olmalı ve sağlam fonsksiyonları olan bir serial terminal programı ile çalışınız.Ben ilk sensörde değer alamadığım için serial porttan dinliyim bakım dedim pic ten sensöre dönderdiğim 8 byte dizideki 0X86 datasını program 0X3F olarak gördüğünden 2 günüm boşuna gitti.
Sonra bir abimizin tavsiyesi ve uyarı ile başka bir serail terminal programı ile denemeler yaptığımda aslında benim gönderdiğim veride sorun olmadığını alıcı kısımda sorun olduğunu farkettim..
Beni yanıltan serial terminal programı oldu yani.
Sonradan daha kallavi bir program indirip kurdum.
Kullandığım serial port programı :
Son olarak eklemek istediğim bir husus data var.Sensörün yanında gelen kablosunu ben çok ince olduğu için 0.25mm lik papuç basarak 3.8mm lik klemens ile karta bağladım.kendi soketi kutudan 1 adet çıktığı içi tercih etmedim.Piyasadan da nereden bulunur yedek olarak bilmiyorum.
Size son görselim mutlu son ile biten Co2 ölçümünden:
Sağlıcakla kalın...
EDİT: 01.01.2019 Yani yazıyı yazdıktan tam bir yıl sonra ( ertesi gün yani ) programda ufak bir güncelleme ile sensörün açılıştaki verilerini görmezden gelip açılıştaki takılma olayını giderdim.
Yaptığım işlem işlemciye enerji verdiğimizde kesmeleri kapalı tutup sensörün açılması kendini toparlaması için yaklaşık 15sn kadar bekledikten sonra kesmeleri açıp sensörle haberleşmek..Şuan gayet iyi çalışıyor.
NOT: sensörün açılışta bağlı olup olmadığını gözlemlemek için bekleme süresini biraz kısıp yukarıda bahsettiğim 410 datasını 4 defa okuduktan sonra sensörün bağlı olup olmadığını teyit edebilirsiniz...
Üstad harika bir açıklama olmus.Eline sağlık.
YanıtlaSil