Skocz do zawartości
Komentator

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

Pomocna odpowiedź

//dołączenie biblioteki wyświetlacza
#include <LiquidCrystal.h>
LiquidCrystal lcd(2,3,4,5,6,7); //info o podłączeniu wyświetlacza
int czas;//deklaracja typu
int licznik;
void setup()
{
pinMode(13, INPUT_PULLUP);
pinMode(12, INPUT_PULLUP);
czas=0; //zerowanie zmiennych
licznik=0;
lcd.clear(); //czyszczenie ekranu
lcd.setCursor(0,0); //ustawienia kursora
lcd.print("Wlacz - START"); //wyświetlenie tekstu początkowego
lcd.setCursor(0,1);
lcd.print("Czas: 0 s");

}

void loop()
{
// put your main code here, to run repeatedly:

if (digitalRead(13)==LOW || licznik>0) { //obsługa klawisza START
	lcd.setCursor(0,0); //ustawienia kursora
	lcd.print("zatrzymaj - STOP"); //wyświetlenie tekstu
	lcd.setCursor(6,1); //ustawienia kursora
	lcd.print(czas); //wyświetlenie czasu, jenostki
	lcd.print(" s");
	licznik++; //zliczanie kolejnych przebiegów
	czas=licznik/10; //przeliczenielicznika na czas
	delay(50);
	//krótkie opóźnienia( w dwóch miejscach) niwelują problem z przytrzymywaniem przycisków
}


if (digitalRead(12)==LOW) { //obsługa klawisza STOP
	lcd.clear(); //czyszczenie ekranu
	lcd.setCursor(0,0);
	//ustawienia kursora wyświetlenie tekstu
	lcd.print("Czas zliczony: "); 
	lcd.print(czas); 
	lcd.print(" s");
	licznik=0; //zerowanie licznika
}
delay(50); //druga część opóźnienia, niweluje problem z przytrzymywaniem przycisków

}

Chyba wszystko działa dobrze. Jakieś uwagi?

Udostępnij ten post


Link to post
Share on other sites

PrimeSoul, najłatwiej byłoby przeliczać sobie czas na ilość milisekund i trzymać w zmiennej/zmiennych lub tablicy. Jednak o tych ostatnich dopiero będziemy mówić 🙂

GregPL, wygląda całkiem dobrze, więc jeśli działa, to wszystko super 🙂

Udostępnij ten post


Link to post
Share on other sites
PrimeSoul, najłatwiej byłoby przeliczać sobie czas na ilość milisekund i trzymać w zmiennej/zmiennych lub tablicy. Jednak o tych ostatnich dopiero będziemy mówić 🙂

Z tablicami coś tam miałem już do czynienia wcześniej w C++, w Arduino może mniej, ale w sumie to może się pobawię z nimi w tym projekcie stopera, bo podejrzewam, że zasada działania ta sama. C++ ma bardzo dużo wspólnego z Arduino, tak na moje oko, więc spróbować nie zaszkodzi 😋.

Udostępnij ten post


Link to post
Share on other sites

PrimeSoul, pewnie, próbuj 🙂 Gdybyś miał jakiś problem, to załóż osobny temat w dziale o Arduino 🙂

Udostępnij ten post


Link to post
Share on other sites

No, nareszcie miałem więcej czasu i mogłem do tego mojego stopera solidnie przysiąść. Oto efekt (za drugim podejściem, w pierwszym pamięć nie działała) :

#include <LiquidCrystal.h> // dołączam bibliotekę LCD
#define A 11 // start/stop button
#define B 12 // save/show button
LiquidCrystal lcd (2,3,4,5,6,7); // dołączam obiekt wyświetlacza
int tablica [20]; // deklaracja tablicy pamięci; zapis do 5 wyników
int ms = 0, s = 0, m = 0, h = 0, i = 0, j = 0, k = 0; // deklaracja zmiennych

void setup() {
 pinMode(A, INPUT_PULLUP); // pin 11 jako wejście do przycisku
 pinMode(B, INPUT_PULLUP); // pin 12 jako wejście do przycisku
 lcd.begin (16,2); // deklaracja typu wyświetlacza
 lcdstart(); // wywołujemy pozycję startową wyświetlacza
 while (digitalRead(A)!=LOW) {}; // czeka na przycisk A do startu
 delay(200); // opóźnienie dla rzeczywistego czasu wciśnięcia
 ms+=20; // doliczenie do liczby milisekund 200
}

void lcdstart() { // program zerujący wyświetlacz do pozycji startowej
 lcd.clear(); // czyszczenie wyświetlacza
 lcd.setCursor(0,0); // kursor na pozycję startową
 lcd.print("Time:[h:m:s:ms]"); //15 znaków
 lcd.setCursor(0,1); // kursor w drugiej lini
 lcd.print("00:00:00:00"); //11 znaków, podstawa do nadpisywania
}

void czyszczenie() { // podprogram zerujący stoper i pamiec
 for (i=0; i<=19; i++) { // pętla for zerująca po kolei każdy
   tablica[i] = 0; // element tablicy
 }
 h = 0;
 s = 0;
 m = 0;
 ms = 0;
 i = 0;
 j = 0;
 k = 0;
}

void odliczanie() { // podprogram odliczający i wyświetlający czas
 if (ms>=100) { //warunek naliczenia sekundy
   ms = 0;
   s++;
 }
 lcd.setCursor(9,1); // ustawiam kursor na pozycji ms
 if (ms<10) {        // ms jednocyfrowe
   lcd.print("0");
   lcd.print(ms);
 }
 else                // ms dwucyfrowe
 lcd.print(ms);

 if (s>=60) { // warunek naliczenia minuty
   s = 0;
   m++;
 }
 lcd.setCursor(6,1); // ustawiam kursor na pozycji sekund
 if (s<10) {         // s jednocyfrowe
   lcd.print("0");
   lcd.print(s);
 }
 else                // s dwucyfrowe
 lcd.print(s);

 if (m==60) { // warunek naliczenia godziny
   m = 0;
   h++;
 }
 lcd.setCursor(3,1); // ustawiam kursor na pozycji minut
 if (m<10) { // m jednocyfrowe
   lcd.print("0");
   lcd.print(m);
 }
 else      // m dwucyfrowe
 lcd.print(m);

 if (h==24)  //warunek kończący dzień; zerowanie licznika
 h = 0;
 lcd.setCursor(0,1); // ustawiam kursor na pozycji godzin
 if (h<10) { // h jednocyfrowe
   lcd.print("0");
   lcd.print(h);
 }
 else  // h dwucyfrowe
 lcd.print(h);

 delay(10); // opóźniam o 10 ms, co jest największą czułością stopera
 ms++;
}

void pamiec(int x) { // funkcja pamieci
 tablica[x] = ms - 1;
 tablica[x+1] = s;
 tablica[x+2] = m;
 tablica[x+3] = h;
}

void interwal(int x) { // funkcja wyniku interwalowego
 lcd.setCursor(9,1);
 if (tablica[x]<10) { // pierwszy zapisany wynik (ms) jednocyfrowy
   lcd.print("0");
   lcd.print(tablica[x]);
 }
 else  // dwucyfrowy
 lcd.print(tablica[x]);

 lcd.setCursor(6,1);
 if (tablica[x+1]<10) { //zapisane s jednocyfrowe
   lcd.print("0");
   lcd.print(tablica[x+1]);
 }
 else // zapisane s dwucyfrowe
 lcd.print(tablica[x+1]);

 lcd.setCursor(3,1);
 if (tablica[x+2]<10) { // zapisane m jednocyfrowe
   lcd.print("0");
   lcd.print(tablica[x+2]);
 }
 else // zapisane m dwucyfrowe
 lcd.print(tablica[x+2]);

 lcd.setCursor(0,1);
 if (tablica[x+3]<10) { // zapisane h jednocyfrowe
   lcd.print("0");
   lcd.print(tablica[x+3]);
 }
 else // zapisane h dwucyfrowe
 lcd.print(tablica[x+3]);
}
void loop() {
 while (digitalRead(A)!=LOW && digitalRead(B)!=LOW) { //odlicza do czasu wciśnięcia przycisku
   odliczanie();
 }
 if (digitalRead(A)==LOW) { // jeśli wciśnięto przycisk A
   delay (400); // opóźnienie dla rzeczywistego czasu wciśnięcia
   while (digitalRead(A)!=LOW && digitalRead(B)!=LOW) {}; // stop
   if (digitalRead(A) == LOW) {  // po wciśnięciu A
     delay(200); // opóźnienie dla rzeczywistego czasu wcisnięcia
     ms+=20; // uwzględnienie tego opóźnienia
   }
   else if (digitalRead(B)==LOW) { // po wcisnięciu B
     for (k = 0; k<=4; k++) { // funkcja for dla wyników interwałowych
       delay(400); // opóźnienie dla rzeczywistego czasu wcisnięcia
       interwal(4*k);
       while (digitalRead(B)!=LOW) {};
     }
     czyszczenie(); // czyszczenie pamieci i zmiennych stopera
     lcdstart(); // czyszczenie wyswietlacza
     while (digitalRead(A)!=LOW) {}; // czeka na przycisk A do startu
     delay(200); // opóźnienie dla rzeczywistego czasu wciśnięcia
     ms+=20; // doliczenie do liczby milisekund 200
   }
 }
 else if (digitalRead(B)==LOW) { //jesli wcisnieto przycisk B
   pamiec(4*(j%5)); // zapisywanie wyniku do tablicy z nadpisem
   j++; // przeskakujemy na następne pola pamięci
   delay(400); // dla rzeczywistego czasu wcisniecia przycisku
   ms+=40; // uwzględnienie tego opóźnienia
 }
}

Ogólnie mimo wszystko byłbym wdzięczny bardziej zaawansowanym o dokładniejsze przejrzenie kodu, bo pewnie gdzieś wciąż znajdują się jakieś niedociągnięcia, których testy mi nie wskazały. Z góry dzięki 😋

Udostępnij ten post


Link to post
Share on other sites

PrimeSoul, hm, a nie prościej było przeliczać czas na milisekundy i zapisywać je jako jedną liczbę 🙂?

Udostępnij ten post


Link to post
Share on other sites

Treker, pewnie byłoby prościej i nawet ekonomiczniej w pamięci 😋, ale taką wizję miałem, żeby to tak zrobić no i tak zrobiłem 😋. A jak już miałem większość kodu, to dopiero się połapałem, że to nienajlepsza opcja. Tylko wtedy to już nie miało sensu zmieniać 😋

Udostępnij ten post


Link to post
Share on other sites

PrimeSoul, a pisałem o tym kilka postów wcześniej 🙂

Masz przynajmniej dobrą wprawkę - jak zbierzesz siły na nowo, to warto byłoby spróbować napisać to jeszcze raz, porządnie 🙂

Udostępnij ten post


Link to post
Share on other sites

Witam

Mam spory problem z wyświetlaczem.

Zrobiłem wszystko zgodnie z kursem. Kilkukrotnie podpinałem przewody oraz wgrywałem program.

Niestety na wyświetlaczu cały czas widać podświetloną pierwsza linie podobnie jak na jednym ze zdjęć.

Arduino_LCD3.jpg

Jak kręce potencjometrem widok zmienia się z tego co widać po lewej na to co widać po prawej lub na odwrót.

Będąc mocno wzburzonym poszedłem się dotlenić. Moje zdziwienie było ogromne gdy po powrocie włączyłem Arduino leonardo A na wyświetlaczu pokazał się napis który chciałem.

Niestety moja radość nie trwała długo. Gdy chciałem zmienić napis nic się nie działo. Cały czasna na wyświetlaczu był ten sam napis. Pomyślałem że wymaga dłuższego odpięcia od zasilania. Niestety znów zaczęła wyświetlać się podświetlona pierwsza linia.

Próbowałem zrobić jeszcze tak jak na oficjalnej stronie Arduino ale nic to nie zmieniło.

Pomocy

Udostępnij ten post


Link to post
Share on other sites

Kontroler wyświetlacza domyślnie startuje w konfiguracji jednoliniowej. Ewidentnie masz problem z połączeniami i nawet procedura inicjalizacji trybu nie "dobija się" do wyświetlacza, nie mówiąc o późniejszym wypisywaniu literek. Zasilanie, podświetlanie i regulacja napięcia kontrastu jest chyba OK, bo coś działa i widać, że LCD na to reaguje. Wywal jak najwięcej kabli a najlepiej całą płytkę stykową. Jeżeli możesz połącz LCD bezpośrednio do płytki procesora. Nawet jeśli każdy zestyk (przejście kabel-płytka lub płytka-kabel) to 99% szans poprawnego działania, to przy 50 przejściach masz już tylko 60% szans powodzenia. A jeśli płytka była już używana do czegoś innego, wpychałeś w nią nóżki scalaków czy oporników, szanse działania całości spadają praktycznie do zera 🙁

Udostępnij ten post


Link to post
Share on other sites
#include <LiquidCrystal.h>  
#define START 0
#define STOP 8
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);  // deklaracja wyswietlacza
boolean start = 0;
float sekundy = 0;

void setup() {
 pinMode(START,INPUT_PULLUP);  // przycisk START
 pinMode(STOP,INPUT_PULLUP); // przycisk STOP

 lcd.begin(16,2);
 lcd.setCursor(0,0);
 lcd.print("Stoper");
 lcd.setCursor(0,1);
 lcd.print("0");
}

void loop() {
 while (digitalRead(START) == LOW) { // moment wcisniecia klawisza START
   sekundy = 0;  // 
   lcd.clear(); //
   lcd.setCursor(0,0);//    zerowanie ustwaien stopera
   lcd.print("Stoper");//


   while(digitalRead(STOP) == HIGH) {  // dopoki nie wcisnieto klawisza STOP
     lcd.setCursor(0,1);
     lcd.print(round(sekundy));  // wyswietlanie wyniku w całych sekundach
     sekundy = sekundy + 0.01; //
     delay(9);  // krótki delay zeby wylapywalo nawet krotkie wcisniecie przycisku STOP
   }

   lcd.clear();  // czyszczenie calego wyswietlacza bo nie wiem czy i jak wyczyscic sama druga linie
   lcd.setCursor(0,0);
   lcd.print("Stoper");
   lcd.setCursor(0,1);

   lcd.print("KONIEC: ");  
   lcd.print(round(sekundy));  // Napis koniec i wyswietlenie czasu
   lcd.print(" sekund");
 }
}

Opóźnienie delay i zwiększanie licznika było dobierane metodą prób i błedów, do 3 minut jeszcze się pomiar zgadza. Jak się upewnić, że pomiar będzie zawsze prawdziwy ?

while (...) {
     sekundy = sekundy + 0.01; 
     delay(10); 
}
while (...){
     sekundy = sekundy + 0.1;  
     delay(100); 
}
while (...){
     sekundy = sekundy + 0.001; 
     delay(1); 
}

Wynik powinien być podobny w tych trzech u góry ?

W praktyce w ostatnim przypadku gdy minie 2 minuty, program pokazuje ze minęło 60 sekund

Udostępnij ten post


Link to post
Share on other sites
Jak się upewnić, że pomiar będzie zawsze prawdziwy ?

Użyć przerwań z timera, zapomnieć o "delay'ach"...

Udostępnij ten post


Link to post
Share on other sites

Artur, wykonywanie stopera na delay'ach, to trochę sztuka, dla sztuki - bardziej wprawka programistyczna 🙂 Nie jest to zbyt dokładna metoda odliczania czasu. Tak jak napisał Nawyk, przy dokładnych zadaniach należałoby użyć przerwań - zajmiemy się tym w dalszych odcinkach kursu Arduino.

Na ten moment ważne, że działa - dokładność nie jest priorytetem 🙂

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

czy jest szansa, że Arduino II wystartuje przed wakacjami?

LCD prostsze niż myślałem, oczywiście na poziomie "1" 🙂 pozdrawiam.

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!

Gość
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...