Skocz do zawartości
Komentator

Kurs Arduino - #7 - Wyświetlacz tekstowy, LCD 2x16

Pomocna odpowiedź

(edytowany)

@leh1992Wszystko fajnie. Pytanie: czy za pół roku jak spojrzysz w ten kod, będziesz pamiętał co znaczy stan numer dwa?

A tak przy okazji: jeśli zmienna czas jest typu int, co ma niby oznaczać

czas+0.01;

Jak myślisz - jeśli zmienna czas ma wartość x to jaką będzie miała po dodaniu 0.01?

 

Edytowano przez ethanak

Udostępnij ten post


Link to post
Share on other sites

@ethanak

3 godziny temu, ethanak napisał:

Pytanie: czy za pół roku jak spojrzysz w ten kod, będziesz pamiętał co znaczy stan numer dwa?

Myślę że wywnioskuję to z ogólnej budowy kodu. A jest możliwość nazywania przypadków w funkcji switch słownie?

 

3 godziny temu, ethanak napisał:

A tak przy okazji: jeśli zmienna czas jest typu int, co ma niby oznaczać


czas+0.01;

Zmienna czas jest typu float

float czas = 0.0;

 

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
6 godzin temu, leh1992 napisał:

A jest możliwość nazywania przypadków w funkcji switch słownie?

Oczywiście. Możesz użyć np. dyrektywy #define, coś w rodzaju:
 

#define STAN_CZEKAM 1
#define STAN_COS_ROBIE 2
#define STAN_COS_INNEGO 3

i dalej w kodzie coś w stylu:
 

stan = STAN_CZEKAM;
...
switch(stan) {
   case STAN_CZEKAM:

W ten sposób zarówno Ty za pięć lat, jak i ktoś kto widzi kod po raz pierwszy będzie od razu wiedział o co chodzi w kodzie i że dana gałąż switch będzie wykonana w stanie oczekiwania.

Wygodniejszym sposobem jest użycie enum, czyli:
 

enum {
  STAN_CZEKAM = 1,
  STAN_COS_ROBIE,
  STAN_COS_INNEGO
};

W ten sposób w ogóle nie zajmujesz się drobiazgami typu "który stan odpowiada jakiej liczbie" bo w rzeczywistości nikogo to nie interesuje, a enum automatycznie przydzieli kolejne wartości kolejnym stanom. Oczywiście to najprostszy sposób zastosowania enum, można stworzyć np. nowy typ i zmienne tego typu, np.:

typedef enum {
  STAN_CZEKAM = 1,
  STAN_COS_ROBIE,
  STAN_COS_INNEGO
} stany; // tworzymy nowy typ "stany" do przechowywania stanów maszyny

stany stan; // i zmienną "stan" przed chwilą utworzonego typu

Temat dość obszerny - wpisz w google "typ wyliczeniowy" i poczytaj na ten temat trochę więcej jeśli chcesz.
 

6 godzin temu, leh1992 napisał:

Zmienna czas jest typu float

A, to zwracam honor, cóż - starość nie radość i oczy już nie te... chyba mi się dwie linijki ze sobą połączyły 😞

Edytowano przez ethanak
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@leh1992 fajnie, że wrzuciłeś swoje rozwiązanie i przyznam, że to wygląda ładnie. To o czym pisze @ethanak to dobry zwyczaj w programowaniu, który poprawia czytelność kodu. Ja ze swojej strony polecam autoformat z Arduino bo trochę się nawiasy rozjechały pod koniec (Ctrl-T), a tak to dobra robota 🙂 

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

@ethanak Dzięki za podpowiedź! Na pewno pogrzebie w tym temacie!

@Gieneq O autoformacie też pierwsze słyszę, rzeczywiście ułatwia życie 😉

 

Tutaj już kod z zastosowanymi waszymi poradami

#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

float czas = 0.0;
int stanLicznika = 0;

enum stanLicznika {oczekiwanie, pomiar, wynik};

unsigned long aktualnyCzas = 0;
unsigned long zmianaCzasu = 0;
unsigned long zmiana = 0;

void setup() {
  // put your setup code here, to run once:
  pinMode(8, INPUT_PULLUP);
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);

  lcd.begin(16, 2);
}

void loop() {
  aktualnyCzas = millis();

  switch (stanLicznika) {
    case oczekiwanie:
      lcd.setCursor(0, 0);
      lcd.print("Wcisnij");
      lcd.setCursor(0, 1);
      lcd.print("przycisk");
      if (digitalRead(8) == LOW) {
        lcd.clear();
        zmianaCzasu = aktualnyCzas;
        stanLicznika = pomiar;
      }
      break;
    case pomiar:
      lcd.setCursor(0, 0);
      lcd.print("Pomiar czasu");

      zmiana = aktualnyCzas - zmianaCzasu;
      if (zmiana >= 10) {
        zmianaCzasu = aktualnyCzas;
        czas = czas + 0.01;
      }
      lcd.setCursor(0, 1);
      lcd.print(czas);
      if (digitalRead(9) == LOW) {
        lcd.clear();
        stanLicznika = wynik;
      }
      break;

    case wynik:
      lcd.setCursor(0, 0);
      lcd.print("Koniec pomiaru");
      lcd.setCursor(0, 1);
      lcd.print(czas);
      if (digitalRead(10) == LOW) {
        lcd.clear();
        czas = 0;
        stanLicznika = oczekiwanie;
      } else if (digitalRead(8) == LOW) {
        lcd.clear();
        stanLicznika = pomiar;
      }
      break;
  }
}

 

Edytowano przez leh1992
Dodany kod
  • Lubię! 2

Udostępnij ten post


Link to post
Share on other sites

@leh1992 teraz wygląda bardzo ładnie, choć jeszcze jakbyś zastąpił wszystkie tzw. "magiczne liczby" w pinach jakimiś definami bo jednak nie jest to takie oczywiste:

else if (digitalRead(8) == LOW)

Widzę, że udało Ci się dać tylko jeden odczyt Seriala i dodać enuma jak sugerował @ethanak więc jest dużo lepiej 🙂 tak trzymaj!

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Widziałem już podobne pytanie ale nie znalazłem odpowiedzi. Mój wyświetlacz czasem zamiast wyswietlać prawidłową treść pokazuje dziwne symbole.

Wrzucam krótki filmik i dwa zdj układu.

Wszystkie elementy poza potencjometrem należą do zestawu forbota. W układzie zmniejszyłem podświetlenie wyświetlacza (podpięte przez  rezystor) żeby było coś widać na filmie. Przewody odpowiadające za przesył danych skleiłem taśmą aby łatwiej odczytać schemat.

Do tego mój kod:

#include <LiquidCrystal.h>
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

void setup() {
  lcd.begin(16, 2); //deklaracja typu
  lcd.setCursor(0, 0); //ustawienie kursora
  lcd.print("Lukasz");
  lcd.setCursor(0, 1);
  lcd.print("forbot.pl");
  pinMode(10, OUTPUT);
  analogWrite(10, 50);
}

void loop() {
  lcd.noDisplay();
  delay(500);
  lcd.display();
  delay(500);
}

20200901_021622.jpg20200901_021447.jpg

Edytowano przez Gieneq

Udostępnij ten post


Link to post
Share on other sites

@hojda może jest jakiś błąd przy przesyle do Arduino. Zrób kilka testów:

  1. daj na początku setup opóźnienie np 2 sekundy, może przy starcie coś się dzieje,
  2. zamiast display/nodisplay daj kod, który masz w setup do części w loop - najlepiej zrób z tego funkcje i używaj w pętli loop - chodzi o to, żeby do Arduino był wysyłan napis, a nie sama komenda wygaszania,
  3. wymień kabelki i przełóż coś na płytce stykowej, bo może coś nie styka.

Udostępnij ten post


Link to post
Share on other sites

Zadanie 7.1 

#include <LiquidCrystal.h> //biblioteka ekranu
LiquidCrystal lcd(2,3,4,5,6,7); //podłączenie wyświetlacza

void setup() {
  lcd.begin(16,2);
  lcd.setCursor(0,0);
  lcd.print("    MIKOLAJ!");
  lcd.setCursor(0, 1);
  lcd.print("--> forbot.pl<--");
}

void loop() {
}

117950639_347470626255637_5217487722258711628_n.thumb.jpg.69238e8f22645b4bbbe80c320c7b79a9.jpg

Zadanie 7.2

W wyniku zastosowania funkcji clear() program czyści wszystko co zostało przez nas wyświetlone. Napis "Nap. Odczytane" znika na zawsze, natomiast sama wartość napięcia odczytana z fotorezystora pojawia się ponownie ponieważ jest odczytywana i wyświetlana w pętli loop przez cały czas działania programu. 

Zadanie 7.3

Poniżej 100ms wynik jest już ciężki do odczytania, ponieważ zmiany wartości następują bardzo szybko. Około 50ms ciężko już odczytać cokolwiek ponieważ wartość nie jest ani przez moment stała. 

Zadanie 7.4

 

Niedawno z bratem robiliśmy podobne zadanie bo ma zajęcia z Arduino w technikum 😄 

#include <LiquidCrystal.h>            //dołączenie biblioteki wyświetlacza
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);  //zadeklarowanie pinów wyświetlacza

float czas = 0.0;
int licznik = 0;

enum licznik {oczekiwanie, pomiar, wynik};   //wyliczeniowy typ danych; zmienna typu licznik może przyjąć 3 różne wartości zapisane w klamrach

unsigned long aktualnyCzas = 0;              //zadeklarowanie zmiennych umożliwiających sprawne posługiwanie się czasem
unsigned long zmianaCzasu = 0;
unsigned long zmiana = 0; 

void setup() {
  Serial.begin(9600);
  
  pinMode(8, INPUT_PULLUP);                  //przypisanie przycisków do odpowiednich pinów
  pinMode(9, INPUT_PULLUP);
  pinMode(10, INPUT_PULLUP);

  lcd.begin(16, 2);                          //deklaracja typu wyświetlacza 
}

void loop() {
  aktualnyCzas = millis();   //millis zwraca czas w milisekundach, który minął od momentu uruchomienia programu
  
  switch (licznik) {                   //instrukcja warunkowa wielokrotnego wyboru
    case oczekiwanie:                  //przypadek pierwszy, gdy licznik jest w stanie oczekiwania
      lcd.setCursor(0, 0);             //ustawienie kursora w 1 linijce
      lcd.print("Wcisnij przycisk");   //piszemy w 1 linijce
      lcd.setCursor(0, 1);             //ustawienie kursora w 2 linijce
      lcd.print("...");                //piszemy w 2 linijce
      if (digitalRead(8) == LOW) {     //gdy przycisk nr 1 zostanie wcisniety
        lcd.clear();                   //czyscimy zawartosc wyswietlacza
        zmianaCzasu = aktualnyCzas;    //przypisanie do zmiennej "zmianaCzasu" ilości milisekund które upłynęły od momentu uruchomienia programu
        licznik = pomiar;              //przeniesienie stanu licznika w tryb pomiaru
      }
      break;

    case pomiar:                       //etap drugi, gdy licznik jest w stanie pomiaru
      lcd.setCursor(0, 0);             //ustawienie kursora w 1 linijce
      lcd.print("Pomiar czasu:");      //piszemy w 1 linijce
     
      //Serial.print("Aktualny czas: "); Serial.print(aktualnyCzas);
      //Serial.print("zmianaCzasu: "); Serial.print(zmianaCzasu); 
      
      zmiana = aktualnyCzas - zmianaCzasu;    //odjecie od aktualnej ilosci czasu, czasu ktory uplynal w momencie wcisniecia 1 przycisku
      if (zmiana >= 10) {                     //jesli zmiana jest wieksza niz 10ms 
        zmianaCzasu = aktualnyCzas;           //znowu przypisujemy do zmiennej "zmianaCzasu" czas który upłynął od początku uruchomienia programu;
        czas = czas + 0.01;                   //czas się zwiększa symulując stoper
      } 
      lcd.setCursor(0, 1);                    //piszemy w 2 linijce  
      lcd.print(czas);                        //wyswietlamy aktualna ilosc czasu, zmieniajaca sie o 0.01
      if (digitalRead(9) == LOW) {            //jesli wcisniemy przycisk nr 2 
        lcd.clear();                          //czyscimy aktualna zawartosc wyswietlacza
        licznik = wynik;                      //i aktualny status licznika ustawiamy na ostatni tryb czyli wynik
      }
      break;

    case wynik:                        //etap trzeci, gdy licznik jest w stanie wyniku
      lcd.setCursor(0, 0);             //kursor na 1 linijke
      lcd.print("Koniec pomiaru!");    //piszemy w 1 linijce
      lcd.setCursor(0, 1);             //kursor na 2 linijke
      lcd.print(czas);                 //wyswietlamy aktualny czas i pozostawiamy go bez zmian
      if (digitalRead(10) == LOW) {    //jesli wcisniemy 3 przycisk
        lcd.clear();                   //czyscimy zawartosc wyswietlacza
        czas = 0;                      //zerujemy czas
        licznik = oczekiwanie;         //licznik ustawiamy w tryb 1: oczekiwanie
      } else if (digitalRead(8) == LOW) {     //jesli wcisniemy ponownie przycisk nr 1
        lcd.clear();                          //czyscimy zawartosc wyswietlacza
        licznik = pomiar;                     //licznik jest w trybie 2, pomiaru i kontynuuje mierzenie czasu od momentu w ktorym zostal zatrzymany
      }
      break;
  }
}

 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@samemilerzeczy super, powodzenia w dalszych eksperymentach 🙂

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...