Obsługa czujnika temperatury MCP-9700

Jak podłączyć i odczytać temperaturę na wyświetlaczu LCD zgodnym z HD44780 i Arduino

Wstęp

W ofercie sklepu znajdują się różne tekstowe wyświetlacze LCD. Różnią się pomiędzy sobą rozmiarem oraz kolorem. Przykładowo zestaw LCD do Arduino – jest modułem LCD alfanumerycznym, 2×16 z przylutowaną złączką pasującą do płytki prototypowej, oraz potencjometrem 10 kΩ, liniowym do regulacji kontrastu.

Kilka wpisów wcześniej pojawił się artykuł o podłączaniu wyświetlacza LCD do Arduino. W tym wpisie pokażemy jak zrobić prosty termometr wyświetlający temperaturę na LCDku.

Podłączenie

Moduł LCD posiada kontroler zgodny z HD44780, co oznacza, że biblioteka LiquidCrystal będzie go obsługiwała. Jak go podłączyć?

Zacznijmy od kodu:

#include <LiquidCrystal.h>

float temp;
LiquidCrystal lcd (12,11,10,9,8,7);

void setup() {
  analogReference(EXTERNAL);
};

void loop () {
  temp = analogRead(0)*3.3/1024.0;

  temp = temp - 0.5;
  temp = temp / 0.01;
  delay(500);
  lcd.print("Temp: ");
  lcd.print(temp);
  lcd.print("        ");
  lcd.setCursor(0,0);
};

Obsługa LCD w podstawowym zakresie sprowadza się do podłączenia go (o tym za chwilę), zainicjowaniu go:

LiquidCrystal lcd (12,11,10,9,8,7);

Powyższe definiuje zmienną lcd, przez którą będziemy się komunikować z modułem. Tutaj przyjmujemy najprostszą postać czyli podajemy do których pinów Arduino podłączamy kolejno:


Następnie w pętli loop odczytujemy temperaturę z czujnika MCP-9700 (opisanego w tym poście). Mając temperaturę wyświetlamy napis Temp: potem wartość odczytu i wracamy na początek linii.

Jak poprawić odczyt?

Odczyt temperatury (w postaci napięcia mierzonego przez wejście analogowe 0) podawany przez MCP9700 jest podawany z dokładnością zależną od przetwornika napięcia w Arduino. Jest on 10-cio bitowy i domyślnie mierzy napięcia od 0 do 5V. 10 bitów oznacza to że mamy 1024 kroki w odczycie napięcia. Dlatego napięcie jest mierzone z krokiem 4.88 mV (5/1024).
Czujnik MCP9700 ma czułość 10 mV na stopień, czyli w praktyce znaczy to że mamy dokładność odczytu do pół stopnia (nie mówimy tutaj o jakości czujnika tylko o tym jak Arduino jest w stanie dokładnie odczytać napięcie).

Jak działa przetwornik napięcia

Przetwornik analogowo-cyfrowy ADC jest dokładnie opisany w nocie katalogowej ATmega328 strona 250. W dużym skrócie: napięcie AREF jest napięciem zasilającym przetwornik DAC (podzielnik napięcia sterowany cyfrowo) którego wyjście jest podłączone do komparatora porównywającego je z napięciem wejściowym na danym wejściu analogowym. Napięcie z przetwornika DAC ‚startuje’ od zera i jest zwiększany aż osiągnie maksimum lub komparator wykaże przekroczenie poziomu sygnału badanego. Dzięki temu wiadomo jaką wartość ma badany sygnał.

Od razu rzuca się w oczy co wpływa na dokładność takiego pomiaru. Pierwsza rzecz to rozdzielczość (w bitach) przetwornika DAC – inaczej z jakim krokiem zwiększane jest napięcie do porównywania. ATmega328 ma 10-cio bitowy.

Druga wartość to napięcie AREF. Jeżeli liczba kroków jest określona (1023 bo 10 bitów) to wiadomo jakie napięcie przypada na krok. Jest to AREF/rozdzielczość. ATmega może korzystać z 3 różnych źródeł napięcia AREF. Może to być wewnętrzne źródło 1.1V (nie wiem jakiej dokładności), napięcie zasilania (około 5V) lub wartość podana na pin AREF.
Znajomość tej wartości jest konieczna tak aby móc przeliczyć odczyt cyfrowy z przetwornika na rzeczywistą wartość napięcia. Pomińmy na razie opcje korzystania z wewnętrznego źródła 1.1V oraz z podawania AREF własnoręcznie. Skupmy się na domyślnej wartość AREF – 5V.
Teraz kłania się nam podstawowa informacja o czujniki MCP9700 – czyli czułość. Wynosi ona 10mV/st C – dlatego jeżeli chcemy odczytywać dokładnie to co podaje czujnik to musimy znać dokładną wartość AREF.

Przykład

Odczyt z analogRead() dał nam 150. Myślimy że napięcie odczytane to 5/1024*150 = 0.7324 V. Jest to prawda, jeżeli AREF faktycznie wynosi 5V. A jeżeli ma naprawdę 4.9V? To wówczas prawdziwa wartość jaką oznacza odczyt 150 to: 0.7178V. Różnica – 14.6 mV. Dla czułości 10mV/C – prawie 1.5 stopnia!

A ile wynosi dokładnie ten AREF w domyślnym ustawieniu? Niby 5V, ale tak naprawdę Vcc (napięcie zasilania) podane na ATmega328.

Zaraz, powie ktoś, przecież Arduino ma na sobie regulator napięcia na 5V, więc taka duża różnica nie powinna występować. Prawda. Ale tylko jeżeli zasilamy Arduino przez gniazdo zasilania, a nie przez USB!

Jak wiadomo, standard USB mówi, że napięcie zasilania wynosi 5V, więc regulator napięcia nie działa, napięcie z kabla USB idzie prosto do ATmega. A regulator napięcia nie działa, bo żeby dostarczyć regulowane 5V to musi dostać więcej aby mieć z czego regulować, więc nie ma technicznej (prostej) możliwości regulacji zapewniającej 5V jeśli napięcie zasilania to też 5V.
Inaczej mówiąc jesteśmy zdani na to co komputer podaje na USB. I tutaj zaskoczenie, bo notebook, z którego programujemy Arduino na porcie USB najwyraźniej podaje 4.9 V zamiast równych 5V.
Finalnie – przez to odczyt w naszym przypadku był zawyżony o te 1.5 stopnia.

Ale, jeżeli skorzystać z

analogReference(INTERNAL);

to rezygnujemy z górnych zakresów odczytu (bo maksymalny odczyt to 1.1V czyli po przeliczeniu na temperature (1.1-0.5)/0.01 = 60 stopni) na rzecz zwiększenia dokładności odczytu (1.1/1024 = ok 1mV, tj 0.1 C) . Jeszcze raz uwaga – zwiększenie dokładności odczytu nie pomiaru

To tyle w dużym skrócie jeżeli chodzi o to co naprawdę mierzy analogRead. Ażeby wyjaśnić czemu na zdjęciu jeden odczyt to 18 stopni a drugi 20 – nie jest to jakaś magia związana z analogRead – jeden z czujników MCP to wersja A a drugi bez A w numerku. Ten z A (dołączony do Starter Kitu jak i sprzedawany samodzielnie) ma dokładność odczytu +/i 2 a bez A +/- 4 stopnie).

UWAGA!
Potencjalne zagrożenie. Wg dokumentacji funkcji analogReference domyślne ustawienie (czyli gdy nie wywołamy w ogóle analogReference lub gdy zrobimy to z wartością DEFAULT), jest podatne na uszkodzenia gdy podamy napięcie na wejście AREF!

Z danych katalogowych MCP9700 wynika że maksymalne napięcie wyjściowe to 500 mV+ 125*10mV = 1.75V. Najlepiej byłoby zmusić przetwornik do pomiaru napięć w przedziale 0-1.75V, ale wymagało by to dodania dzielnika napięcia abyśmy taką wartość uzyskali. Nie jest to żadna skomplikowana sprawa, ale aby nie komplikować bardziej tego przykładu wykorzystamy prosty sposób na poprawę jakości odczytu, bez dodawania nowych elementów. Wykorzystamy fakt, że Arduino dostarcza nam poza 5V również 3.3V i bez żadnych kłopotów możemy poprawić czułość odczytu napięcia.

Dlatego w setup jest wywołanie

analogReference(EXTERNAL)

(nie wystarczy podać samego napięcia na AREF) a w loop zmienia się wzór do obliczania temperatury. Po zmianie napięcia odniesienia mamy krok odczytu napięcia 3.2 mV, co oznacza że odczyt pomiaru temperatury jest z dokładnością 0.3°C a nie 0.5°C jak wcześniej.

UWAGA – to jest tylko dokładność odczytu pomiaru a nie poprawa dokładności pomiaru. Czujnik ma, tak jak miał wcześniej dokładność +-2°C :) ta sztuczka poprawi tylko nasze samopoczucie, że odczyt nie skacze tak bardzo :)

Pamiętajmy, że zmiana AREF dotyczy wszystkich wejść analogowych.