Skocz do zawartości

Wyświetlacz, multipleksowanie i pomiar temperatury


BHBmacieg

Pomocna odpowiedź

Cześć, 

Wrzucam swoje rozwiązanie, tj termometr pokojowy z wyświetlaczem LCD oraz wskaźnikiem LED bazujący na cyfrowym czujniku temperatury. Wskazuje aktualną temperaturę, opcję pokazania najniższej i najwyżej odnotowanej temperatury oraz opcję włączenia/wyłączenia wskaźnika RGB LED - tak aby móc zostawić cały układ włączony na noc. Oczywiście w układzie są też dwa potencjometry - jeden do sterowania jasnością LCD (lub całkowitym wyłączeniem podświetlenia na noc) oraz drugi do manipulacji kontrastem. Docelowo chciałbym czegoś takiego użyć wraz z jakimś protokołem komunikacji bezprzewodowej i zrobić małą centralkę do sterowania włączaniem/wyłączeniem pieca gazowego w zależności od aktualnej temperatury w pokoju. W zasadzie to był główny powód mojego zainteresowanie arduino, po tym jak zobaczyłem ile kosztują takie centralki "gotowce" w sklepach. Wskaźnik LED dopasowany do temperatur jakie panują u mnie w pokoju, bo i tak jest wpięte na stałe na zasilacz i raczej nie będzie służył do pomiarów bardzo niskich czy wysokich temperatur. 

 

KOD:

#include <Adafruit_NeoPixel.h> //zaimplementowanie bibliotek
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>
#define czujnikTemp A5 //definicje elementów
#define przyciskMAX 2
#define przyciskMIN 3
#define przyciskRESET A4
#define przyciskOnOffWskaznik A2
#define LedRGB A3
LiquidCrystal lcd(4, 5, 6, 7, 8, 9); //informacja o pinach wyświetlacza
OneWire oneWire(czujnikTemp); //wskazanie pinu dla czujnika temperatury
DallasTemperature sensors(&oneWire); //przekazanie informacji do biblioteki
Adafruit_NeoPixel wskaznik = Adafruit_NeoPixel(8, A3, NEO_GRB + NEO_KHZ800); //zdefiniowanie nowego elementu RGB

float tempMAX = 0; //aktualna temperatura maksymalna
float tempMIN = 0; //aktualna temperatura minimalna
bool wskaznikOnOff = false; //zmienna dla włączenia lub wyłączenia linijki


void setup() {
  pinMode(przyciskMAX, INPUT_PULLUP); //zdefiniowanie pinów
  pinMode(przyciskMIN, INPUT_PULLUP);
  pinMode(przyciskRESET, INPUT_PULLUP);
  pinMode(przyciskOnOffWskaznik, INPUT_PULLUP);
  lcd.begin(16, 2); //inicjalizacja wyświetlacza LCD
  lcd.setCursor(0, 0); //ustawienie kursora
  sensors.begin(); //inicjalizacja czujników
  wskaznik.begin(); //inicjalizacja paska LED
  wskaznik.show();

  tempMAX = sensors.getTempCByIndex(0); //wczytanie temperatury maksymalnej
  tempMIN = sensors.getTempCByIndex(0); //wczytanie temperatury minialnej
 

}

void loop() {
  sensors.requestTemperatures(); //pobranie temperatury z czujnika
  float temperatura = sensors.getTempCByIndex(0); //odczytanie temperatury dla LCD
  int tempINT = sensors.getTempCByIndex(0); //odczytanie temperatury dla paska LED

  if (temperatura > tempMAX) {
      //sprawdzenie czy aktualna temperatura jest większa od poprzedniej max i ustawieenie nwowego max
      tempMAX = temperatura;
      
  }
  
 if (temperatura < tempMIN) {
      //sprawdzebnie czy aktualna temperatura jest mniejsza od poprdzeniej i ustawienie noweg min
      tempMIN = temperatura;
  }

  if (digitalRead(przyciskMAX) == LOW) { //jeśli przycisk MAX wciśnięty
      //jeśli przycisk max wciśnięty
      MAXtemp(); //wywołanie funkcji pokazującej wartość max na LCD

  } else if (digitalRead(przyciskMIN) == LOW) { //jeżeli przycisk min wciśnięty
      //jeśli przycisk wciśniety
      MINtemp(); //wywołanie funkcji pokazującej wartości min na LCD

} else if (digitalRead(przyciskRESET) == LOW) { //jeżeli przycisk RESET wciśnięty
    resetMaxMin(); //wywołanie funkcji wczytującej na nowo wartości MAX i MIN
}

if (digitalRead(przyciskOnOffWskaznik) == LOW) { //jeżeli przycisk OnOff wciśnięty
    wskaznikOnOff = !wskaznikOnOff; //zmiana wartości logicznej zmiennej

    if (wskaznikOnOff == true) { 
        wskaznikON(); //wywołanie funkcji włączającej pasek LED
    } else {
        wskaznikOFF(); //wywołanie funkkcji wyłączającej pasek LED
    }
}

wskaznikRGB(tempINT); //wywołanie funkcji zapalającej odopwiednią ilość diod
aktualnaTemp(); //wywołanie funkcji wyświetlającej wartość temperatury na LCD

}

void MAXtemp() { //funkcja odpowiedzalna za wyświetelenie wartości MAX na LCD
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Max: " + String(tempMAX) + "*C");
    delay(5000);
}

void MINtemp() { //to samo co wyżej tylko MIN
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("Min: " + String(tempMIN) + "*C");
      delay(5000);
}

void resetMaxMin() { //funkcja odpowiedzialna za reset wartosci MAX i MIN
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Min i max reset!");
    tempMAX = sensors.getTempCByIndex(0);
    tempMIN = sensors.getTempCByIndex(0);
    delay(3000);

}

void aktualnaTemp() { //funkcja odpowiedzialna na wyświetelenie aktualnej temperatury na LCD
    sensors.requestTemperatures(); 
    float temperatura = sensors.getTempCByIndex(0);
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Temp: " + String(temperatura) + "*C");
    delay(2000);
}

void wskaznikRGB (int temperatura) { //funkcja odpowiedzialna na podświetlenie odpowiedniej ilosci diod na pasku LED

    if (wskaznikOnOff == true) {
         wskaznik.clear();

        if (temperatura >= 0) {
            temperatura = map(temperatura, 17, 30, 1, 8);

            int i = 0; 
            for (i = 0; i < temperatura; i++) {
                wskaznik.setPixelColor(i, wskaznik.Color(10, 0, 0));
            } 
        } 
        wskaznik.show();   

    } else {
        wskaznik.clear();
        wskaznik.show();
    }
}

void wskaznikON() { //funkcja odpowiedzialna za wyświetelenie info o włączeniu paska LED
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Wskaznik RGB-ON");
    delay(2000);
}

void wskaznikOFF() { //to samo co wyżej tylko o wyłączeniu
    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("Wskaznik RGB-OFF");
    delay(2000);
}

Oraz film z podstawowych funkcji:

 

  • Lubię! 1
Link do komentarza
Share on other sites

Widzę, że projekt jest już całkiem rozbudowany. Fajnie że umieszczasz w kodzie komentarze - łatwiej się czyta i wiadomo o co chodzi.

13 godzin temu, BHBmacieg napisał:

 Docelowo chciałbym czegoś takiego użyć wraz z jakimś protokołem komunikacji bezprzewodowej i zrobić małą centralkę do sterowania włączaniem/wyłączeniem pieca gazowego

To czekam na gotowy projekt, myślę że już wiele nie brakuje 🙂 tylko oby było to bezpieczne rozwiązanie 😄 

Link do komentarza
Share on other sites

(edytowany)

@Gieneq już sprawdziłem instrukcję obsługi mojego pieca. Jest tam przygotowana specjalna zworka, w którą należy się wpiąć i po prostu w momencie gdy temperatura spadnie później zadanej zamknąć obwód. To samo dzieje się gdy włączam go ręcznie za pomocą pokrętła umieszczonego na obudowie pieca.

W ciągu kolejnych dni na pewno do układu dołożę jeszcze czujnik poziomu wilgotności, bo w zimie zdarza mi się mieć z nią problemy przez zbyt szczelne okna i chciałbym to też mieć pod kontrolą.

A komentarzy tyle wstawiam również dla siebie. Wciąż jestem na etapie intensywnej nauki i symulatanicznie zajmuję się projektami "klasycznymi" jak i projektami pierwszych robotów/pojazdów sterowanych na różne sposoby. A tak jak mam wszystko zakomentowane to nie mam problemu żeby sobie przypomnieć co chciałem w danym miejscu uzyskać, nawet jeśli na obecną chwilę nie dziala to w 100% jakbym chciał.

Na początku próbowałem zrealizować wyświetlanie temperatury na wyświetlaczu 7 segmentowym, jednak napotkałem problem z multipleksowaniem ekranów. Zaraz po uruchomieniu programu jest nawet ok, a potem częstotliwość odświeżania spada dramatycznie. Próbowałem tutaj wykorzystać bibliotekę SegSev. Wygląda tak jakby pomiar z cyfrowego czujnika temperatury trwał zbyt długo i ekran nie jest w stanie się tak szybko odświeżać. Mam rację czy coś innego jest tutaj problemem?

Tutaj kod z tej próby: 


#include <SevSeg.h> //wczytanie niezbędnych bibliotek
#include <OneWire.h>
#include <DallasTemperature.h>
#define czujnikTemp A5 //definicje pinów elementów
#define przyciskMAX 2
#define przyciskMIN A0
SevSeg sevseg; //inicjacja wyświetalcza 7 seg
OneWire oneWire(czujnikTemp); //wskazanie pinu czujnika temperatury
DallasTemperature sensors(&oneWire); //przekazanie informacji do biblioteki



void setup() {

    pinMode(przyciskMAX, INPUT_PULLUP); 
    pinMode(przyciskMIN, INPUT_PULLUP);
    Serial.begin(9600);
    sensors.begin(); //inicjalizacja czujników
    byte numDigits = 2; //zdefiniowanie parametrów wyświetlacza 7 segmentowego
    byte digitPins[] = {9, 10};
    byte segmentPins[] = {7, 5, 11, 4, 12, 8, 6};
    bool resistorsOnSegments = true; // info, ze do segmentów podłączone są oporniki
    byte hardwareConfig = N_TRANSISTORS; //typ tranzystora
    sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);


}

void loop() {
  

  sensors.requestTemperatures(); //pobranie temperatury z czujnika

  int temperaturaINT = sensors.getTempCByIndex(0);
  sevseg.setNumber(temperaturaINT, 2); //wyświetl temperaturę korzystająć z dwóch wyświetlaczy
  sevseg.refreshDisplay(); 


}

i film z zachowania układu:

 

Edytowano przez BHBmacieg
  • Lubię! 1
Link do komentarza
Share on other sites

Wydzieliłem temat z kursu, ponieważ jest on zdecydowanie bardziej rozbudowany i może być mylący dla przyszłych czytelników.

2 godziny temu, BHBmacieg napisał:

est tam przygotowana specjalna zworka, w którą należy się wpiąć i po prostu w momencie gdy temperatura spadnie później zadanej zamknąć obwód.

O, to ciekawe. Myślałem o czymś podobnym może nie w piecu ale w elektrycznym bojlerze, który mam w mieszkaniu. Jest tam nastawnik z różnymi planami ale to się średnio sprawdza, przydałoby się coś bardziej inteligentnego 🙂 

2 godziny temu, BHBmacieg napisał:

Wygląda tak jakby pomiar z cyfrowego czujnika temperatury trwał zbyt długo i ekran nie jest w stanie się tak szybko odświeżać. Mam rację czy coś innego jest tutaj problemem?

Musiałbyś zmierzyć czas dokonania pomiaru. Jeżeli faktycznie będzie coś na rzeczy to możesz zrobić kilka usprawnień: zapisać adres Dallasa i komunikować się tylko z nim. Sprawdzać czy pomiar jest gotowy (jest tam taka funkcja is...Ready()). Jest też w przykładach do biblioteki Dallas Temperature przykład gdzie pomiar jest nieblokujący. Wtedy nie będziesz czekać aż czujnik coś pomierzy, bo już będzie gotowe do odbioru 🙂 

Co do wyświetlacza najlepiej spróbuj samemu napisać swój kod do multipleksowania wtedy będziesz mieć pewność jak działa. Ewentualnie sprawdź kod źródłowy biblioteki której używasz i napisz coś podobnego dostosowanego do potrzeb.

Edytowano przez Gieneq
Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

(edytowany)
1 godzinę temu, Gieneq napisał:

Co do wyświetlacza najlepiej spróbuj samemu napisać swój kod do multipleksowania wtedy będziesz mieć pewność jak działa. Ewentualnie sprawdź kod źródłowy biblioteki której używasz i napisz coś podobnego dostosowanego do potrzeb.

Napisałem swój własny kod do multipleksowania wyświetlacza. Zanim zacząłem korzystać z gotowej biblioteki. W tym przypadku zdecydowałem się na użycie gotowej biblioteki, żeby po prostu sprawdzić jak ona funkcjonuje. Jak będzie chwila czasu to wrócę do tego pomysłu, spróbuję użyć własnego kodu odpowiedzialnego na multipleksowanie ekranu. 

W jaki sposób mogę zmierzyć czas dokonania pomiaru?

Koniecznie muszę się zagłębić w ten przykład z biblioteki, który powoduje, że pomiar jest nieblokujący. W zasadzie to w całą zawartość tej biblioteki bo wydaję się niezwykle ciekawa. Nie ukrywam, że w wersji ostatecznej, wolałbym użyć wyświetlacz 7 segmentowy, ponieważ jest on mniejszy i bardziej czytelny z większej odległości niż wyświetlacz LCD. Chciałbym go też zintegrować z czujnikiem wilgotności, żeby na przykład po wciśnięciu odpowiedniego przycisku wyświetlacz pokazywał wartość wilgotności powietrza a nie temperaturę. Tylko czy jest to wykonalne, skoro z pokazaniem samej temperatury pojawiają się dość nieoczywiste problemy?

Edytowano przez BHBmacieg
Link do komentarza
Share on other sites

2 godziny temu, BHBmacieg napisał:

W jaki sposób mogę zmierzyć czas dokonania pomiaru?

Najprościej to funkcją millis(). zapisujesz raz do zmiennej long czas i później drugi raz odejmujesz po wykonaniu tego co mierzysz. 

long czasStartu = millis();
//jakies tam dlugie cos
long czasKOnca = millis() - czasStartu;

Oczywiście takie podejście jest obarczone błędem - millis() też ileś tam trwa. Dlatego możesz zamiast raz odpalić pomiar temperatury, zapętlić go np 100x i wynikowy czas podzielić przez 100. W ten sposób wpływ funkcji millis() będzie mniejszy.

2 godziny temu, BHBmacieg napisał:

Nie ukrywam, że w wersji ostatecznej, wolałbym użyć wyświetlacz 7 segmentowy, ponieważ jest on mniejszy i bardziej czytelny z większej odległości niż wyświetlacz LCD.

To i racja.

2 godziny temu, BHBmacieg napisał:

Tylko czy jest to wykonalne, skoro z pokazaniem samej temperatury pojawiają się dość nieoczywiste problemy?

Jest wykonalne o ile odejdziesz od jakichkolwiek opóźnień. Możesz poczytać jak np. w grach realizuje się pętle - tam wszystko co nie jest wydzielane w osobne wątki działa na zasadzie liczników czasu. sprawdzasz czas przed i po aktualizacji. Jeżeli pojawi się lag to możesz coś z tym zrobić. Ale po kolei, najpierw sprawdź czy problem to ten dallas 🙂 sam się chętnie dowiem ile trwa pomiar.

Możesz też porobić różne testy, np. czy jak podasz konkretny adres to bęzie lepiej - z dokumentacji biblioteki wynika, że samo wyzwolenie pomiaru działa na wszystkie podłączone urządzenia, dopóki nie wiesz ile ich jest to może być różnie.

Link do komentarza
Share on other sites

Ja tylko z taką delikatną sugestią...

Multipleksowanie jest fajne, ale do nauki albo jak się nie ma nic lepszego do roboty. Nie lepiej użyć czegoś takiego? Wiem, że to dla cieniasów jest, prawdziwi twardziele multipleksują wyświetlacze... - ale przy bardziej skomplikowanym programie zawsze gdzieś coś trochę czasu zeżre, a multipleksowane ledy tego nie lubią!

  • Lubię! 1
Link do komentarza
Share on other sites

1 minutę temu, ethanak napisał:

Ja tylko z taką delikatną sugestią...

Multipleksowanie jest fajne, ale do nauki albo jak się nie ma nic lepszego do roboty. Nie lepiej użyć czegoś takiego? Wiem, że to dla cieniasów jest, prawdziwi twardziele multipleksują wyświetlacze... - ale przy bardziej skomplikowanym programie zawsze gdzieś coś trochę czasu zeżre, a multipleksowane ledy tego nie lubią!

A może i lepiej ale teraz te kwarantanny i inne straszne rzeczy. Działam na tym co mam w domu. Ale uwaga słuszna, przy najbliższej wizycie w sklepie z elektroniką poszukam. A raczej na pewno taki moduł będzie dostępny więc dorzucę do koszyka. 

Link do komentarza
Share on other sites

11 godzin temu, BHBmacieg napisał:

Na początku próbowałem zrealizować wyświetlanie temperatury na wyświetlaczu 7 segmentowym, jednak napotkałem problem z multipleksowaniem ekranów. Zaraz po uruchomieniu programu jest nawet ok, a potem częstotliwość odświeżania spada dramatycznie. Próbowałem tutaj wykorzystać bibliotekę SegSev. Wygląda tak jakby pomiar z cyfrowego czujnika temperatury trwał zbyt długo i ekran nie jest w stanie się tak szybko odświeżać.

Problemy masz dwa. Funkcje obsługi onewire w <OneWire.h> są blokując tak samo jak diód przez <Adafruit_NeoPixel.h>. Do onewire uzyj uart, na stronie maxim-dallas jest przykład. Do diód użyj SPI na przerwaniach. Onewire można też sterować na przerwaniach od timera ale to więcej roboty niż z uart.

Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.