Haberler

Wio Terminal Güncellemesi: Uygun Fiyatlı IR Termal Görüntüleme Kamerası Yapın

Artık Wio Terminal ve Grove – Infrared Temperature Sensor Array (AMG8833) ile uygun fiyatlı bir termal kamera yapabilirsiniz. Tüm bileşenlerin toplam maliyeti 80 dolardan azdır ve kolayca düşük maliyetli bir FLIR™ gibi bir termal görüntüleme kamerası edinebilirsiniz.

Kızılötesi nedir ve nasıl “görülür” ve kullanılır

Öncelikle, kızılötesine hızlıca bir göz atalım. Kızılötesi (IR), veya kızılötesi ışık, dalga boyları görünür ışıkla karşılaştırıldığında daha uzun olan elektromanyetik radyasyondur (EMR), bu da onu genel koşullarda insan gözüne görünmez kılar. Oda sıcaklığına yakın nesneler tarafından yayılan çoğu termal radyasyon kızılötesidir. (Kaynak: Wikipedia)

İnsan gözleri, görünür ışıktan daha uzun dalga boylarına sahip olduğu için kızılötesi ışığı “göremez”, ancak bir termal kızılötesi kamera basit bir çözüm sunabilir. Kızılötesi enerjiyi algılayabilir ve bunu farklı renklerle bir resme dönüştürerek algılanan nesnelerin sıcaklığını gösterebilir.

Aşağıda IR termal görüntüleme kamerasının bazı tipik uygulamaları bulunmaktadır:

  • Tıbbi bakımda temassız sıcaklık ölçümleri
  • Yangın önleme sistemleri
  • İzinsiz giriş/Hareket algılama
  • Varlık algılama / Kişi konumlandırma
  • Akıllı evler için algılama elemanları

Kendi IR Termal Görüntüleme Kameranızı Yapın

Biraz geriye gidecek olursak, Grove – Infrared Temperature Sensor Array (AMG8833) çözünürlüğü yalnızca 8 x 8 (64 Piksel) olup, bazı durumlarda yeterli olabilir. Bu nedenle, kodda daha iyi bir gösterim için 70 x 70 (4900 Piksel) genişletmek için Doğrusal Enterpolasyon kullanılır.

Bu demo, Kris Kasprzak’ın videosundan ilham alınarak hazırlanmıştır. Wio Terminal ve Grove – Infrared Temperature Sensor Array (AMG8833) ile uyumlu hale getirmek için birkaç değişiklik yapılmıştır. Çoğu grafik, genel performansı ve daha hızlı kare hızını artırmak için önce TFT LCD Sprite’larına çizilmektedir. Ayrıca ekranın ortasında bir nişangah ekledik ve nişangah üzerindeki sıcaklığı gösteriyoruz. Bu arada, Wio Terminal üzerindeki sağ düğmeye tıklayarak ekrandaki referans çizgisini açıp kapatabilirsiniz.

Referans çizgisi ile
Referans çizgisi olmadan

Donanım Gereksinimleri

Not: Bu yazıda kullanılan Wio Terminal ve pil şasisi, test için demo amaçlıdır, bu nedenle görünümü sağdaki resimlerden biraz farklıdır. Örneğin, Wio Terminal’in düğmesi mavi olmalı ve pil şasisinin dış kabuğu beyaz olmalıdır.

Yazılım Gereksinimleri

  • LCD ekran Kütüphanesini Seeed_Arduino_LCD yükleyin, daha fazla bilgi için Wio Terminal LCD sayfasını ziyaret edin.
  •  Seeed_AMG8833 depolama alanını ziyaret edin ve tüm repo’yu yerel sürücünüze indirin.
    • Artık Seeed_AMG8833 kütüphanesini Arduino IDE’ye yükleyebilirsiniz. Arduino IDE’yi açın ve sketch -> Include Library -> Add .ZIP Library seçeneğine tıklayın ve indirdiğiniz Seeed_AMG8833 dosyasını seçin.

Kurulum Talimatları

  • Grove – Infrared Temperature Sensor Array (AMG8833) cihazını Wio Terminal’in Grove I2C Arayüzüne takın.
  • Tam kodu buradan indirin veya bu sayfanın sonundaki kodu kopyalayın.
  • Kodu yükleyin.

Artık Wio Terminal’i açabilir ve yeni IR termal görüntüleme kameranızı deneyebilirsiniz!

Github & Forum’umuzda Daha Fazlasını Keşfedin

Wio Terminal hakkında daha fazla bilgi mi edinmek istiyorsunuz? Yepyeni Forum’umuz yayınlandı ve tartışmamıza katılmanızı bekliyor! Sorularınızı veya Wio Terminal ile ilgili herhangi bir teknik sorunu forumumuzda paylaşmaktan çekinmeyin. Seslerinizi duymak için sabırsızlanıyoruz ve tüm önerilere açığız!

Eğer Wio Terminal’in ne olduğunu bilmeyenler varsa, birlikte bir göz atalım!

Wio Terminal’in Kısa Tanıtımı

Wio Terminal fiziksel dünya ile I/O oluşturmak için basit ve küçük bir cihazdır. Realtek RTL8720DN tarafından desteklenen kablosuz bağlantıya sahip ATSAMD51 tabanlı bir geliştirme kartıdır.


Tam Kod

Not: Bu IR Termal Görüntüleme Kamerası’nın performansını ve kare hızını artırmak için Wio Terminal CPU Hızını 200MHz’e yükseltebilirsiniz. Seçin Tools -> CPU Speed -> 200MHz(Overclock)

/*

  Bu program, bir 8 x 8 termal kamera okuma dizisini büyütmek içindir
  10 kat büyütecek ve 240 x 320 boyutunda gösterecektir
  enterpolasyon lineerdir ve "yeterince iyi"dir, çünkü ekran 5-6-5 renk paletine sahiptir
  Nihai toplam dizi, yalnızca iç noktaların 70 x 70'lik bir dizisidir

  Revizyonlar
  1.0     Kasprzak      İlk kod
  1.1     Anson(Seeed Studio)  Grove - Kızılötesi Sensör(AMG8833) ile Wio Terminal'e uyarlanmıştır

*/

#include <Seeed_AMG8833_driver.h>
#include <TFT_eSPI.h>                // Grafik kütüphanesini dahil et (bu, sprite fonksiyonlarını içerir)  

TFT_eSPI    tft = TFT_eSPI(); 
TFT_eSprite Display = TFT_eSprite(&tft);  // "tft" nesnesine işaretçi ile "img" Sprite nesnesi oluştur
// işaretçi, pushSprite() tarafından TFT'ye itmek için kullanılır

unsigned long CurTime;

uint16_t TheColor;
// bazı başlangıç renkleriyle başla
uint16_t MinTemp = 25;
uint16_t MaxTemp = 35;

// enterpolasyonlu renkler için değişkenler
byte red, green, blue;

// satır/sütun enterpolasyonu için değişkenler
byte i, j, k, row, col, incr;
float intPoint, val, a, b, c, d, ii;
byte aLow, aHigh;

// bir ekran "pikselinin" boyutu
byte BoxWidth = 3;
byte BoxHeight = 3;

int x, y;
char buf[20];

// ekran ızgarasını açıp kapatmak için değişken
int ShowGrid = -1;

// 8 x 8 ölçülen pikseller için dizi
float pixels[64];

// enterpolasyonlu dizi için dizi
float HDTemp[80][80];

// kamera nesnesini oluştur
AMG8833 ThermalSensor;

// Izgarayı açıp kapat
void toggleGrid() {
  ShowGrid = ShowGrid *-1;
  Display.fillRect(15, 15, 210, 210, TFT_BLACK);
  yield();
}

void setup() {
  Serial.begin(115200);

  // ekranı başlat ve arka planı siyah yap
  tft.begin();
  tft.fillScreen(TFT_BLACK);

  // Izgarayı açıp kapatmak için kesme
  pinMode(WIO_KEY_A, INPUT);
  attachInterrupt(digitalPinToInterrupt(WIO_KEY_A), toggleGrid, FALLING);

  // ekran döndürmesini ayarla (gerekirse 0'a değiştirmeniz gerekebilir)
  tft.setRotation(3);

  // bir açılış ekranı göster

  tft.setCursor(20, 20);
  tft.setTextColor(TFT_BLUE, TFT_BLACK);
  tft.print("Termal ");

  tft.setTextColor(TFT_RED, TFT_BLACK);
  tft.print("Kamera");

  // sensörün açılmasına izin ver
  bool status = ThermalSensor.init();
  delay(100);

  if (!status) {
      Serial.print("AMG8833 başlatılamadı");
  }

  // başlangıç testi için kamerayı oku
  ThermalSensor.read_pixel_temperature(pixels);

  // durumu kontrol et ve sonuçları göster
  if (pixels[0] < 0) {
    while (1) {
      tft.setCursor(20, 40);
      tft.setTextColor(TFT_RED, TFT_BLACK);
      tft.print("Okuma: BAŞARISIZ");
      delay(500);
    }
  }
  else {
    tft.setCursor(20, 40);
    tft.setTextColor(TFT_GREEN, TFT_BLACK);
    tft.print("Okuma: TAMAM");
    delay(2000);
  }

  tft.fillScreen(TFT_BLACK);

  Display.createSprite(TFT_HEIGHT, TFT_WIDTH);
  Display.fillSprite(TFT_BLACK); 

  // renk enterpolasyon rutinleri için kesme noktalarını al
  // bu fonksiyon, sıcaklık ölçeği değiştiğinde çağrılır
  Getabcd();

  // sensörlerin maksimum ve minimum değerleriyle eşleşen bir efsane çiz
  DrawLegend();

}

void loop() {  
  CurTime = millis();

  // sıcaklık alanı için büyük beyaz bir kenar çiz
  Display.fillRect(10, 10, 220, 220, TFT_WHITE);

  // sensörü oku
  ThermalSensor.read_pixel_temperature(pixels);

  // şimdi 8 x 8 sensör dizisine sahibiz
  // daha büyük bir ekran elde etmek için enterpolasyon yap
  // önce 8 sensör pikseli arasında 70 sütun noktasını enterpole et
  for (row = 0; row < 8; row ++) {
    for (col = 0; col < 70; col ++) {
      // ilk dizi noktasını al, sonra bir sonraki
      // ayrıca sonraki satırlar için 8 artırmanız gerekiyor
      aLow =  col / 10 + (row * 8);
      aHigh = (col / 10) + 1 + (row * 8);
      // her 10 sütun için enterpolasyon miktarını al
      // burada, performansı yüksek tutmak için basit lineer enterpolasyon yapıyoruz ve
      // ekran 5-6-5 renk paleti olduğu için şatafatlı enterpolasyon düşük renk derinliğinde kaybolur
      intPoint =   (( pixels[aHigh] - pixels[aLow] ) / 10.0 );
      // her sütunu artırmak için ne kadar artırılacağını belirle (temelde 0-9)
      incr = col % 10;
      // enterpolasyonlu değeri bul
      val = (intPoint * incr ) +  pixels[aLow];
      // 70 x 70 dizisine kaydet
      // çünkü ekran dışarıya işaret ediyor, satır verilerini transpoze etmek için satırı ters çevir
      HDTemp[ (7 - row) * 10]
= val; } } // şimdi 70 sütun ile ham veriye sahibiz // her 70 sütunu enterpole et // Arduino'yu unutun..hız olarak yeterince hızlı değil..Teensy > 72 mhz ile başlangıç noktasıdır for (col = 0; col < 70; col ++) { for (row = 0; row < 70; row ++) { // ilk dizi noktasını al, sonra bir sonraki // ayrıca sonraki sütunlar için 8 artırmanız gerekiyor aLow = (row / 10 ) * 10; aHigh = aLow + 10; // her 10 sütun için enterpolasyon miktarını al // burada, performansı yüksek tutmak için basit lineer enterpolasyon yapıyoruz ve // ekran 5-6-5 renk paleti olduğu için şatafatlı enterpolasyon düşük renk derinliğinde kaybolur intPoint = (( HDTemp[aHigh]
- HDTemp[aLow]
) / 10.0 ); // her sütunu artırmak için ne kadar artırılacağını belirle (temelde 0-9) incr = row % 10; // enterpolasyonlu değeri bul val = (intPoint * incr ) + HDTemp[aLow]
; // 70 x 70 dizisine kaydet HDTemp[ row ]
= val; } } // 70 x 70 dizisini göster DisplayGradient(); // Ekranın ortasında bir nişangah Display.drawCircle(115, 115, 5, TFT_WHITE); Display.drawFastVLine(115, 105, 20, TFT_WHITE); Display.drawFastHLine(105, 115, 20, TFT_WHITE); // Sprite'ı ekrana it Display.pushSprite(0, 0); // Ekranın ortasında sıcaklığı göster tft.setRotation(3); tft.setTextColor(TFT_WHITE); tft.drawFloat(HDTemp[35][35], 2, 90, 20); // Kare hızını yazdırmak için bu satırı açın Serial.print("Kare hızı: "); Serial.println(1/(0.001*(millis() - CurTime))); } // sonuçları görüntülemek için fonksiyon void DisplayGradient() { tft.setRotation(4); // 70 satır boyunca geç for (row = 0; row < 70; row ++) { // titreme olmayan bir ızgara çizmenin hızlı yolu--her 10 pikseli 2x2 yapmak, 3x3 yerine // ızgaradan sonra çizim yapmak çok fazla titreme yapar if (ShowGrid < 0) { BoxWidth = 3; } else { if ((row % 10 == 9) ) { BoxWidth = 2; } else { BoxWidth = 3; } } // sonra her 70 sütun boyunca geç for (col = 0; col < 70; col++) { // titreme olmayan bir ızgara çizmenin hızlı yolu--her 10 pikseli 2x2 yapmak, 3x3 yerine if (ShowGrid < 0) { BoxHeight = 3; } else { if ( (col % 10 == 9)) { BoxHeight = 2; } else { BoxHeight = 3; } } // nihayet her 70 x 70 noktayı çizebiliriz, enterpolasyonlu rengi almak için çağrıya dikkat edin Display.fillRect((row * 3) + 15, (col * 3) + 15, BoxWidth, BoxHeight, GetColor(HDTemp[row]
)); } } } // hızlı ama etkili renk enterpolasyon rutinim uint16_t GetColor(float val) { /* değeri geçin ve R G B'yi hesaplayın bunu yapmanın birkaç yayımlanmış yolu var, ben temelde R G B'yi grafikleştirdim ve basit lineer denklemler geliştirdim tekrar 5-6-5 renkli bir ekran, R G B renk hesaplaması için doğru sıcaklık gerektirmeyecektir denklemler http://web-tech.ga-usa.com/2012/05/creating-a-custom-hot-to-cold-temperature-color-gradient-for-use-with-rrdtool/index.html adresine dayanmaktadır */ red = constrain(255.0 / (c - b) * val - ((b * 255.0) / (c - b)), 0, 255); if ((val > MinTemp) & (val < a)) { green = constrain(255.0 / (a - MinTemp) * val - (255.0 * MinTemp) / (a - MinTemp), 0, 255); } else if ((val >= a) & (val <= c)) { green = 255; } else if (val > c) { green = constrain(255.0 / (c - d) * val - (d * 255.0) / (c - d), 0, 255); } else if ((val > d) | (val < a)) { green = 0; } if (val <= b) { blue = constrain(255.0 / (a - b) * val - (255.0 * b) / (a - b), 0, 255); } else if ((val > b) & (val <= d)) { blue = 0; } else if (val > d) { blue = constrain(240.0 / (MaxTemp - d) * val - (d * 240.0) / (MaxTemp - d), 0, 240); } // ekranın renk eşleme fonksiyonunu kullanarak 5-6-5 renk paletini elde et (R=5 bit, G=6 bit, B=5 bit) return Display.color565(red, green, blue); } // sıcaklık ile RGB grafiğindeki kesme noktalarını almak için fonksiyon void Getabcd() { a = MinTemp + (MaxTemp - MinTemp) * 0.2121; b = MinTemp + (MaxTemp - MinTemp) * 0.3182; c = MinTemp + (MaxTemp - MinTemp) * 0.4242; d = MinTemp + (MaxTemp - MinTemp) * 0.8182; } // bir efsane çizmek için fonksiyon void DrawLegend() { // maksimum ve minimum metin ile renk efsanesi j = 0; float inc = (MaxTemp - MinTemp ) / 160.0; for (ii = MinTemp; ii < MaxTemp; ii += inc) { tft.drawFastHLine(260, 200 - j++, 30, GetColor(ii)); } tft.setTextSize(2); tft.setCursor(245, 20); tft.setTextColor(TFT_WHITE, TFT_BLACK); sprintf(buf, "%2d/%2d", MaxTemp, (int) (MaxTemp * 1.8) + 32); tft.print(buf); tft.setTextSize(2); tft.setCursor(245, 210); tft.setTextColor(TFT_WHITE, TFT_BLACK); sprintf(buf, "%2d/%2d", MinTemp, (int) (MinTemp * 1.8) + 32); tft.print(buf); } // KODUN SONU

Leave a Reply

Your email address will not be published. Required fields are marked *