Skocz do zawartości
Komentator

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

Pomocna odpowiedź

@Lorenzini witam na forum! Cieszę się, że kurs jest pomocny i udało Ci się uruchomić ten układ. Powodzenia podczas dalszych eksperymentów. Jeśli będziesz miał jakieś pytania to śmiało pytaj na forum 😉

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@Vova fajnie, że działa 🙂 Powodzenia w dalszych eksperymentach!

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Mam też i drugi swój projekt z wyświetlaczem. Symulator prostej gry w kości 🙂

Link do filmu na YT (bo nie wiem jak tu umieścić film).

Ze względu na ilość kabelków odpuściłam podłączanie wyświetlacza przez kable i zrobiłam to przez konwerter.

 

 

Edytowano przez ceiem
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Moja wersja kodu 7.4, oczywiście przy mocnym wsparciu forum (podgląd rozwiązań kolegów)

#include <LiquidCrystal.h> //Dołączenie bilbioteki
#define przyciskA 8
#define przyciskB 9

LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Informacja o podłączeniu nowego wyświetlacza
int licznik = 0;// Zmienna do mierzenia czasu
boolean stan_przyciskuA = 0;//Zmienne do zapamietania stanu przycisków A i B
boolean stan_przyciskuB = 0;
void setup() {
  pinMode(8, INPUT_PULLUP);//Piny 8 i 9 jako przyciki
  pinMode(9, INPUT_PULLUP);
  lcd.begin(16, 2); //Deklaracja typu
  lcd.clear();// Wyczysc wyswietlacz
  lcd.setCursor(0, 0);//Ustawienie kursora
}
void loop() {
  if (digitalRead(przyciskA) == LOW) {//Gdy wcisnieto przycisk "A"
    stan_przyciskuA = 1;//Zpamietaj stan przycisku "A"
    licznik = 0;//Wyzerój licznik
    lcd.clear();//Wyczysc wyswietlacz
  }
  if (stan_przyciskuA == 1) {//Gdy wcisnieto przycisk "A"
    licznik = licznik + 1;//Zacznij odliczanie
    lcd.setCursor(0, 0);//Ustawienie kursora w pierwszej linijce
    lcd.clear();//Wyczysc wyswietlacz
    lcd.setCursor(0, 1);//Ustawienie kursora w drugiej linijce
    lcd.print(licznik);//Drukuj tekst
    delay(1000);//Zmiana wartosci licznka co 1 sek
  }
  if (digitalRead(przyciskB) == LOW) { //Gdy wcisnieto przycisk"B"
    stan_przyciskuB = 1;//Zapamietaj stan przycisku "B"
    stan_przyciskuA = 0;//Zresetu stan przycisku "A"
  }
  if (stan_przyciskuB == 1) { // Gdy wcisnieto przycisk "B"
    licznik = licznik + 0;// "Zatrzymaj" licznik
    lcd.setCursor(0, 0);//Ustawienie kursora w pierwszej linijce
    lcd.print("Koniec");//Drukuj tekst
    lcd.setCursor(0, 1);//Ustawienie kursora d drugiej linijce
    lcd.print(licznik);// Drukuj tekst
  }
}

 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@Vova fajnie że dalej działasz z pracami domowymi. Mam tylko uwagę do kodu bo szukałem gdzie konkretnie zliczasz czas w tym stoperze i jednak bazowanie na liczbie opóźnień wprowadza duży błąd pomiarowy. Spróbuj to zniwelować bazując na czasie pomierzonym funkcją millis().

Spróbuj napisać program tak, by czas był aktualizowany, np co 100ms, wyświetlany z interwałem 1000ms. Wtedy nieważne czy wyświetlacz go w 1050ms czy w 950ms, od narastajacego czasu zostanie odjęta stała wartość.

 

@ceiem Widzę że projekt jest już bardzo ambitny i dalece wykracza poza temat tego kursu 🙂 Fajnie że rozwijasz się dalej i wystawiasz sobie większe wyzwania! Powodzenia w dalszych zadaniach! 🙂 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Mam jednak problem z losowaniem. Gdy odłączam zasilanie i podłączam ponownie mam zawsze takie same losowe wyniki. Nie wiem jak to zmienić. W c++ robię to zawsze na podstawie upływającego czasu (biblioteki ctime, cstdlib, inicjacja czasu) i nie mam takiego problemu, tutaj niestety nie wiem jak z tym sobie poradzić. Może ktoś podpowie?

Udostępnij ten post


Link to post
Share on other sites

O, dziękuję. Czyli jednak trzeba ruszyć dalej 🙂

 

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
Dnia 20.04.2020 o 08:23, Gieneq napisał:

Spróbuj to zniwelować bazując na czasie pomierzonym funkcją millis().

Nie mogę sobie poradzić z tym że czas z funkcją millis() jest odmierzany tuz po uruchomieniu programu. I zanim wcisnę przycisk już upłynie kilka sekund i mój stoper nie zaczyna od zera🤔 Na razie taki kawałek kodu (już nie mówiąc o wdrążeniu drugiego przycisku, przecież tego odmierzania nie można zatrzymać😟)

 #include <LiquidCrystal.h> //Dołączenie bilbioteki
#define przyciskA 8
#define przyciskB 9

LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Informacja o podłączeniu nowego wyświetlacza
unsigned long aktualny_czas = 0;// Zmienne do mierzenia czasu
unsigned long zapamietany_czas = 0;
boolean stan_przyciskuA = 0;//Zmienne do zapamietania stanu przycisków A i B
boolean stan_przyciskuB = 0;
void setup() {
  pinMode(8, INPUT_PULLUP);//Piny 8 i 9 jako przyciki
  pinMode(9, INPUT_PULLUP);
  lcd.begin(16, 2); //Deklaracja typu
  lcd.clear();// Wyczysc wyswietlacz
}
void loop() {
   aktualny_czas = millis();
  if (digitalRead(przyciskA) == LOW) {//Gdy wcisnieto przycisk "A"
    stan_przyciskuA = 1;//Zpamietaj stan przycisku "A"
  }
  if (stan_przyciskuA == 1) {//Gdy wcisnieto przycisk "A"
   if (aktualny_czas - zapamietany_czas >=1000UL){//Zacznij odliczanie
    zapamietany_czas = aktualny_czas;
    lcd.setCursor(0, 0);//Ustawienie kursora w pierwszej linijce
    lcd.clear();//Wyczysc wyswietlacz
    lcd.setCursor(0, 1);//Ustawienie kursora w drugiej linijce
    lcd.print(aktualny_czas/1000);//Drukuj tekst
   }
  }
}

 

Udostępnij ten post


Link to post
Share on other sites

A zrób 2 stany i programowy zatrzask "latch"

#define STOP 0
#define COUNTING 1
  
int mode = STOP;
int last_state = digitalRead(x);
long start_time;

void loop(){
  int current_state = digitalRead(x);
  // latch reagujacy na stan opadajacy
  if (current_state  == LOW && last_state  == HIGH){
    if (mode == STOP){
      mode = COUNTING;
      start_time = millis();
      // i co sobie wymarzysz przy starcie stopera  
    }
    if (mode == COUNTING)
      mode = STOP;
  }
  if(mode == COUNTING) {
    //logika wyswietlania....
  }


  last_state  = current_state ;
}

 

Udostępnij ten post


Link to post
Share on other sites

@Gieneq Dziękuje bardo za poświecenie czasu i starania. Jednak  nie radze sobie z tym zadaniem. 

17 godzin temu, Gieneq napisał:

int last_state = digitalRead(x);

  Nie wiem co miałbym podstawić zamiast"X" w powyższej linijce kodu. Na mój rozum powinien tam być "przyciskA" ? 

17 godzin temu, Gieneq napisał:

if (current_state  == LOW && last_state  == HIGH){

A ta linijka sprawdza stan " przyciskA"

 

17 godzin temu, Gieneq napisał:

// i co sobie wymarzysz przy starcie stopera  

  A po tej linijce myślałem że myślałem że należy już wyświetlić "start_time" na lcd ale chyba tak nie jest. . .  Z marnym skutkiem próbowałem te znaleźć w google   jakiejś podpowiedzi co "robią" reszta linijek kodu... W którym miejscu i w jaki sposób ma się tam pojawić drugi przycisk...? 

Jako zupełnie początkujący, nie mając nigdy styczności z programowaniem nie wiem do której części kursu powinienem wrócić żeby to ogarnąć🤔 Bo chyba nie ma sensu przechodzić do następnego punktu  do kąt się nie oswoi bieżącego . . .

 

Udostępnij ten post


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

Na mój rozum powinien tam być "przyciskA" ? 

Tak, zgadza się.

5 godzin temu, Vova napisał:

A ta linijka sprawdza stan " przyciskA"

Pudło 🙂 Linijka do odczytu jest wyżej - digitalRead...

Ta linijka służy sprawdzeniu czy od ostatniego odczytu coś się zmieniło. Jeżeli ostatnio przycisk miał high a teraz low to znaczy że został wciśnięty (wykryto zbocze opadające) i tylko w tym momencie coś zrób - przy kolejnym obejściu pętli ostatni stan będzie już low, nowy low i nic się nie wydarzy.

5 godzin temu, Vova napisał:

"start_time" na lcd ale chyba tak nie jest

W tym momencie masz złapany początek czasu i teraz możesz sobie wyświetlić w pierwszym wierszu "Timer start:"

Następnie wychodzimy z tego miejsca i w kolejnych obejściach pętli będziemy lądować w bloku warunkowym mode == COUNTING - to jest idea maszyny stanów.

W tym bloku możesz zliczać czas do 1 sekundy i co sekundę aktualizować czas:

// nowa zmienna globalna - narastajacy czas
long lastTime;
#define INTERVAL 1000

//....
  if (mode == STOP){
      mode = COUNTING;
      start_time = millis();
      // i co sobie wymarzysz przy starcie stopera
      lcd.print....
      lastTime = start_time;
    }

  if(mode == COUNTING) {
      //logika wyswietlania....
      long currenttime = millis();
      //teraz masz czas startu stopera i aktualny czas - z tego liczysz roznice czyli ile tam ms uplynelo od startu stopera
      long timeDiff = currentTime - start_time;

      //teraz wylicz czy trzeba aktualizowac lcd z zadanym INTERVALEM
      if (currentTime - last_time > INTERVAL){
        //roznica wyszla np 1012, bo cos dlugo trwalo, 12 ms zostanie nadrobione
        last_time += INTERVAL; //zwiekszenie spowoduje ze 12 ms nie zostanie skasowane lez kolejne obejscie petli zaczniemy z czasem z poprzedniego wyswietlenia. W ten sposób średni czas wyświetlania będzie podobny.
       lcd.print(timeDiff);
      }
  
  
}

To jest tylko sugestywny kod, zwróć uwagę na warunki i zmienne, nie bierz tego 1:1 bo np. te lcd nie zadziała. Kod postaraj się uzupełnić, na pewno trzeba zrobić sposób na zatrzymacie stopera i reset 🙂 

Edytowano przez Gieneq

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

@Gieneq Na razie jestem na takim etapie😓Działa w taki sposób, że gdy trzymam przycisk- wyświetla aktualne odliczanie. A gdy przycisk zwolniony - odliczanie odbywa się "w tle " i w momencie wciśnięcia dodaje się do wyświetlonej wartości. Żeby sprawdzić działanie resetuje przyciskiem "RESET" na Arduino (właśnie też nie wiem czy to jest bezpieczne dla samego Arduino takie resetowanie?🤔) no i nie za każdym razem po resecie mi startuje po wciśnięciu "START". . .

Wydaje mi się że ten kod jakiś za bardzo skomplikowany ( jak dla mnie) jak na zwykły stoper... I to jeszcze nie koniec...😓

#include <LiquidCrystal.h> //Dołączenie bilbioteki
#define przyciskSTART 8
#define przyciskSTOP 9
#define STOP 0
#define COUNTING 1
#define INTERVAL 1000
LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Informacja o podłączeniu nowego wyświetlacza
int mode = STOP;
int last_state = digitalRead(przyciskSTART);
long startTime = 0;
long lastTime = 0;
long timeDiff = 0;
long currentTime = 0;
void setup() {
  pinMode(8, INPUT_PULLUP);//Piny 8 i 9 jako przyciki
  pinMode(9, INPUT_PULLUP);
  lcd.begin(16, 2); //Deklaracja typu
  lcd.clear();// Wyczysc wyswietlacz
}
void loop() {
  int current_state = digitalRead(przyciskSTART);//Gdy wcisnieto przycisk "Start"
  if (current_state == LOW && last_state == HIGH) {//ZApamietuje wcisniecie przycisku
    if (mode == STOP) {//Gdy stoper zatrzymany
      mode = COUNTING;//Zaczynamy odliczanie
      startTime = millis();//Zapisz czas oczytany z Arduino do zmiennej
      lastTime = startTime;
      lcd.clear();//Wyczysc wyswietlacz
      lcd.setCursor(0, 0);//Ustawienie kursora w pierwszej linijce
      lcd.print("START");//Drukuj tekst
      lcd.setCursor(0, 1);//Ustaw kursor w drugiej linijce
      lcd.print(lastTime / 1000);//Drukuj tekst
    }
    if (mode == COUNTING) {//Gdy odliczanie trwa
      long currentTime = millis();//Zapisz aktualy czas do zmiennej
      long timeDiff = currentTime - startTime;//Oblicz: ile czasu mineło od startu
      if (currentTime - lastTime > INTERVAL) {//Gdy mineło wiecej czasu niz 1 sekunda
        lastTime += INTERVAL;//Dodaj roznice do odczytanego czasu
        lcd.setCursor(0, 1);// Ustaw kursor w drugiej linijce 
        lcd.print(timeDiff / 1000);//Drukuj tekst
      }
    }
  }
}

 

Edytowano przez Vova

Udostępnij ten post


Link to post
Share on other sites

Ostatnia wersja działa bez trzymania przycisku. Teraz myślę jak to zatrzymać i zresetować (niby miał być temat poświęcony obsłudze lcd a ja już tydzień mecze się ze stoperem😓)

#include <LiquidCrystal.h> //Dołączenie bilbioteki
#define przyciskStart 8
#define przyciskStop 9
#define STOP 0
#define START 1
#define INTERVAL 1000

LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Informacja o podłączeniu nowego wyświetlacza
int ostatniStan = digitalRead(przyciskStart);
int stoper = STOP;
long aktualny_czas = 0;// Zmienne do mierzenia czasu
long zapamietany_czas = 0;
long czas_start = 0;
long wyliczony_czas = 0;
bool stan_przyciskuStart = 0;//Zmienne do zapamietania stanu przycisków Start i Stop
bool stan_przyciskuStop = 0;

void setup() {
  pinMode(8, INPUT_PULLUP);//Piny 8 i 9 jako przyciki
  pinMode(9, INPUT_PULLUP);
  lcd.begin(16, 2); //Deklaracja typu
  lcd.clear();// Wyczysc wyswietlacz
}
void loop() {
  if (digitalRead(przyciskStart) == LOW) {//Gdy wcisnieto przycisk "Start"
    stan_przyciskuStart = 1;//Zpamietaj stan przycisku "Start"
  }
  if (stan_przyciskuStart == 1) {
    if (stoper == STOP) {
      stoper = START;
      czas_start = millis();
      zapamietany_czas = czas_start;
      lcd.clear();//Wyczysc wyswietlacz
      lcd.setCursor(0, 0);//Ustawienie kursora w pierwszej linijce
      lcd.print("START");//Drukuj tekst
      lcd.setCursor(0, 1);//Ustaw kursor w drugiej linijce
      lcd.print(zapamietany_czas / 1000);//Drukuj tekst
    }
    if (stoper == START ) {//Gdy odliczanie trwa
      aktualny_czas = millis();//Zapisz aktualy czas do zmiennej
      wyliczony_czas = aktualny_czas - czas_start;//Oblicz: ile czasu mineło od startu
      if (aktualny_czas - zapamietany_czas > INTERVAL) { //Gdy mineło wiecej czasu niz 1 sekunda
        zapamietany_czas += INTERVAL; //Dodaj roznice do odczytanego czasu
        lcd.setCursor(0, 1);//Ustawienie kursora w drugiej linijce
        lcd.print(wyliczony_czas / 1000); //Drukuj tekst
      }
    }
  }
}

  

  • Lubię! 1

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...