Termometr bezdotykowy (pirometr) z modułem GY-906 w Arduino
Moduł modMLX906 (GY-906) to bezdotykowy czujnik temperatury, którego konstrukcja oparta jest na sensorze promieniowania podczerwonego MLX90614. Dzięki użyciu w module stabilizatora 3.3 V oraz rezystorów podciągających do zasilania (linie SDA, SCL), moduł modMLX906 (GY-906) jest idealnym rozwiązaniem do zbudowania taniego i skutecznego termometru bezdotykowego. Aplikacja tego modułu może okazać się szczególnie przydatna wszędzie tam, gdzie pożądany jest pomiar temperatury bez fizycznej ingerencji w obiekt mierzony.
Układ MLX90614 może mierzyć temperatury obiektu w zakresie -70 do +380°C oraz temperatury otoczenia (obudowy) w zakresie -40 … + 125°C. Komunikacja z układem odbywa się po magistrali I2C lub za pośrednictwem sygnału PWM. Wartości odczytywane z układu są wynikowymi procesów cyfrowej obróbki sygnału z detektora (w układzie MLX90614 zintegrowano sensor, nisko-szumny wzmacniacz, przetwornik ADC 17-bit oraz procesor DSP ). Układ MLX90614 jest fabrycznie skalibrowany.
Od strony sprzętowej projekt wykorzystuje płytkę Arduino UNO wraz z modułem LCD Keypad Shield. Przy pomocy czterech przewodów żeńsko – żeńskich dołączono moduł pirometru modMLX906 (GY-906) do złącz szpilkowych, przylutowanych do płytki LCD Keypad Shield. Czujnik MLX90614 -(… )-BAA, zawarty w module modMLX906 (GY-906), mierzy temperaturę obiektu przy pomocy jednego kanału, zaś do polepszenia parametrów odległościowych pirometru należałoby zastosować optykę o odpowiedniej ogniskowej oraz materiale (przepuszczającym promieniowanie podczerwone).
Program sterujący pracą pirometru napisano w Arduino. Do obsługi magistrali I2C, łączącej sensor z mikrokontrolerem, wykorzystano bibliotekę I2C Master, wyświetlacz alfanumeryczny natomiast obsługiwany jest przez bibliotekę LiquidCrystal (zintegrowaną ze środowiskiem Arduino).
Na początku programu zadeklarowane zostają zmienne – między innymi daneL oraz daneH – obie przechowujące odczytane z czujnika wartości temperatur. Zmienna adres odpowiada za przechowywanie adresu magistralowego sensora, z kolei zmienna erc ma za zadanie przechowywać wartość z rejestru, który nie jest wykorzystywany, a jego odczyt jest konieczny do poprawnego zakończenia transmisji. W funkcji setup następuje inicjalizacja wyświetlacza oraz magistrali I2C. Początek programu zawierający deklaracje i funkcje setup() ukazano na listingu 1.
Listing 1. Deklaracje zmiennych, funkcja setup()
#include #include LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int adres = 0xb4; // Adres czujnika MLX90614 int erc = 0; // Zmienna przechowująca wartość PEC int daneH = 0; // Drugi bajt danych int daneL = 0; // Pierwszy bajt danych double tempnalsb = 0.02; // Zmienna, przez którą wymnażana będzie wartość cyfrowa double temperatura = 0; // Zmienna przechowująca temperaturę void setup(){ i2c_init(); // Inicjalizacja magistrali I2C lcd.begin(16, 2); // Inicjalizacja wyświetlacza }
W pętli głównej następuje odczyt, konwersja, i wyświetlenie wartości z czujnika.
Rozpoczęta zostaje transmisja po magistrali I2C – jako pierwszy odczytywany będzie rejestr temperatury obiektu (Tobj1, adres 0x07). Odczytywane są trzy bajty z jednego rejestru – jest to warunek konieczny poprawnej transmisji. Sensor przechowuje informacje o temperaturach w postaci dwóch bajtów; trzeci bajt zawiera informacje o kodzie błędu w transmisji – zostaje odczytany, lecz nie jest wykorzystywany w programie. Następną operacją jest przygotowanie zmiennej „temperatura” (typu double); do niej zostaje zapisana wartość z drugiego bajtu (zamaskowana przez mnożenie binarne wartością 01111111) oraz przesunięta o osiem pozycji w lewo. Poprzez dodanie do tej zmiennej wartości pierwszego bajtu (odczytanego z czujnika) otrzymano jedną zmienną, która przechowuje wartość temperatury w postaci cyfrowej (zmienna 16-bit, najbardziej znaczący bit wyzerowany).
Konieczne jest późniejsze przeliczenie tej wartości; wpierw na jednostkę układu SI (Kelvin), wykonując mnożenie wartości cyfrowej przez 0.02 (wartość przypadająca na najmniej znaczący bit), następnie zaś, by uzyskać wartość w stopniach Celsiusza, należy od wyniku odjąć liczbę 273.15. Wynik zostaje ukazany na wyświetlaczu, przy czym za pomocą instrukcji lcd.write(0xDF) wyświetlony zostaje znak stopnia.
Pirometr wyświetla temperaturę mierzonego obiektu oraz, w drugiej linii wyświetlacza, temperaturę czujnika / otoczenia. Procedura odczytu temperatury otoczenia jest analogiczna do odczytu temperatury obiektu – dokonuje się jej jednak pod innym adresem rejestru (0x06 HEX). Na końcu programu wprowadzane jest opóźnienie 200 mS. Kod pętli głównej programu przedstawiono na listingu 2.
Listing 2. Pętla główna programu
void loop(){ i2c_start_wait(adres+I2C_WRITE); // Rozpoczęcie komunikacji I2C w trybie zapisu i2c_write(0x07); // Zapis wartości 0x07 (wybranie rejestru Tobj1) i2c_rep_start(adres+I2C_READ); // Ponowny start komunikacji I2C pod adresem do odczytu daneL = i2c_readAck(); // Odczyt pierwszego bajtu danych daneH = i2c_readAck(); // Odczyt drugiego bajtu danych erc = i2c_readNak(); // Odczyt trzeciego (nieistotnego) bajtu danych i2c_stop(); // Koniec transmisji I2C temperatura = (double)(((daneH & 0x007F) << 8) + daneL); // Utworzenie 16-sto bitowej zmiennej składającej się z dwóch zmiennych jedno-bajtowych temperatura = temperatura*tempnalsb; // Na jeden bit przypada 0,02 K, wynikiem tej operacji jest temperatura w Kelvinach temperatura = temperatura - 273.15; // Konwersja na stopnie Celsiusza lcd.setCursor(0,0); // Wyświetlenie (pierwsza linia LCD) lcd.print("Tobj = "); lcd.print(temperatura); lcd.print(" "); lcd.write(0xDF); // Znak stopnia lcd.print("C "); i2c_start_wait(adres+I2C_WRITE); i2c_write(0x06); // Wybór rejestru temperatury otoczenia i2c_rep_start(adres+I2C_READ); daneL = i2c_readAck(); daneH = i2c_readAck(); erc = i2c_readNak(); i2c_stop(); temperatura = (double)(((daneH & 0x007F) << 8) + daneL); temperatura = temperatura*tempnalsb; temperatura = temperatura - 273.15; lcd.setCursor(0,1); // Wyświetlenie (druga linia LCD) lcd.print("Tsns = "); lcd.print(temperatura); lcd.print(" "); lcd.write(0xDF); lcd.print("C "); delay(200); // Opóźnienie 200 mS }
Pomiar dwóch parametrów (temperatury obiektu oraz otoczenia czujnika) może posłużyć do realizacji dodatkowej kompensacji temperaturowej czujnika, wykonania obliczeń różnicy temperatury otoczenia i obiektu lub też sprawdzenia, czy mierzony obiekt nie nagrzewa nadmiernie struktury sensora.
Czujnik MLX90614 powinien współpracować z odpowiednią optyką, by uzyskać najlepsze rezultaty pomiarów przy większych odległościach od mierzonego obiektu. Bez użycia optyki (jak w tym przykładzie), najbardziej realne wyniki pomiaru uzyskuje się w odległości poniżej 2 cm (odległość od czujnika do obiektu mierzonego).
Pełny kod programu:
/* * Termometr bezdotykowy z modułem GY - 906 * Obsługa czujnika MLX90614 po magistrali I2C * Linia SDA = A4 * Linia SCL = A5 * Zasilanie czujnika z 5V */ #include #include LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int adres = 0xb4; // Adres czujnika MLX90614 int erc = 0; // Zmienna przechowująca wartość PEC int daneH = 0; // Drugi bajt danych int daneL = 0; // Pierwszy bajt danych double tempnalsb = 0.02; // Zmienna, przez którą wymnażana będzie wartość cyfrowa double temperatura = 0; // Zmienna przechowująca temperaturę void setup(){ i2c_init(); // Inicjalizacja magistrali I2C lcd.begin(16, 2); // Inicjalizacja wyświetlacza } void loop(){ i2c_start_wait(adres+I2C_WRITE); // Rozpoczęcie komunikacji I2C w trybie zapisu i2c_write(0x07); // Zapis wartości 0x07 (wybranie rejestru Tobj1) i2c_rep_start(adres+I2C_READ); // Ponowny start komunikacji I2C pod adresem do odczytu daneL = i2c_readAck(); // Odczyt pierwszego bajtu danych daneH = i2c_readAck(); // Odczyt drugiego bajtu danych erc = i2c_readNak(); // Odczyt trzeciego (nieistotnego) bajtu danych i2c_stop(); // Koniec transmisji I2C temperatura = (double)(((daneH & 0x007F) << 8) + daneL); // Utworzenie 16-sto bitowej zmiennej składającej się z dwóch zmiennych jedno-bajtowych temperatura = temperatura*tempnalsb; // Na jeden bit przypada 0.02 K, wynikiem tej operacji jest temperatura w Kelvinach temperatura = temperatura - 273.15; // Konwersja na stopnie Celsiusza lcd.setCursor(0,0); // Wyświetlenie (pierwsza linia LCD) lcd.print("Tobj = "); lcd.print(temperatura); lcd.print(" "); lcd.write(0xDF); // Znak stopnia lcd.print("C "); i2c_start_wait(adres+I2C_WRITE); i2c_write(0x06); // Wybór rejestru temperatury otoczenia i2c_rep_start(adres+I2C_READ); daneL = i2c_readAck(); daneH = i2c_readAck(); erc = i2c_readNak(); i2c_stop(); temperatura = (double)(((daneH & 0x007F) << 8) + daneL); temperatura = temperatura*tempnalsb; temperatura = temperatura - 273.15; lcd.setCursor(0,1); // Wyświetlenie (druga linia LCD) lcd.print("Tsns = "); lcd.print(temperatura); lcd.print(" "); lcd.write(0xDF); lcd.print("C "); delay(200); // Opóźnienie 200 mS }