Skocz do zawartości

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


Komentator

Pomocna odpowiedź

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

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
Link do komentarza
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
Link do komentarza
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?

Link do komentarza
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
   }
  }
}

 

Link do komentarza
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 ;
}

 

Link do komentarza
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 . . .

 

Link do komentarza
Share on other sites

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
Link do komentarza
Share on other sites

@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
Link do komentarza
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
Link do komentarza
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...

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.