Skocz do zawartości

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


Pomocna odpowiedź

Zauważyłem coś dziwnego . Program wgrałem gdy płytka nie była "okablowana" tzn.  nie  był podłączony wyświetlacz i podłączone kabelki , jeśli "uzbroiłem " płytkę miałem ten sam błąd z próbą wgrania , ale najważniejsze że działa🙂 .

dzięki za podpowiedzi 

Link to post
Share on other sites

Moje rozwiązania do zadań domowych:

7.2:

Gdy staramy się zbyt szybko pokazać nowe dane, napis na wyświetlaczu zaczyna pulsować.

7.3:

Tekst staje się trudny do odczytania, gdy jest odświeżany co ok. 100 milisekund.

7.4:

#include <LiquidCrystal.h>
#define start 12
#define Stop 13
#define reset 11
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
boolean zaczeto = false;
boolean napisanoKoniec = false;
int t = 0;
void setup() {
  // put your setup code here, to run once:
  lcd.begin(16, 2);
  lcd.setCursor(0, 1);
  pinMode(start, INPUT_PULLUP);
  pinMode(Stop, INPUT_PULLUP);
  pinMode(reset, INPUT_PULLUP);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (zaczeto == false) {
    if (digitalRead(reset) == LOW) {
      lcd.clear();
      t = 0;
    }
    if (digitalRead(start) == LOW) {
      zaczeto = true;
    }
  }
  else {
    napisanoKoniec = false;
    lcd.setCursor(0, 1);
    lcd.print(t);
    lcd.print("sek.");
    delay(1000);
    t = t + 1;
    if (digitalRead(Stop) == LOW) {
      zaczeto = false;
      if (napisanoKoniec == false) {
        lcd.setCursor(0, 0);
        lcd.print("Koniec");
      }
    }
  }
}

Zrobiłem też bardziej zaawansowaną wersję stopera, pokazującą minuty, sekundy i setne sekundy:

#include <LiquidCrystal.h>
#define start 12
#define Stop 13
#define reset 11
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
boolean zaczeto = false;
boolean napisanoKoniec = false;
int setne = 0;
int sekundy = 0;
int minuty = 0;
void setup() {
  // put your setup code here, to run once:
  lcd.begin(16, 2);
  lcd.setCursor(0, 1);
  pinMode(start, INPUT_PULLUP);
  pinMode(Stop, INPUT_PULLUP);
  pinMode(reset, INPUT_PULLUP);
}

void loop() {
  // put your main code here, to run repeatedly:
  if (zaczeto == false) {
    if (digitalRead(reset) == LOW) {
      lcd.clear();
      sekundy = 0;
      setne = 0;
      minuty = 0;
    }
    if (digitalRead(start) == LOW) {
      zaczeto = true;
    }
  }
  else {
    napisanoKoniec = false;
    lcd.setCursor(0, 1);
    if (minuty < 10) {
      lcd.print(0);
    }
    lcd.print(minuty);
    lcd.print(":");
    if (sekundy < 10) {
      lcd.print(0);
    }
    lcd.print(sekundy);
    lcd.print(":");
    if (setne < 10) {
      lcd.print(0);
    }
    lcd.print(setne);
    delay(10);
    setne = setne + 1;
    if (setne == 100) {
      setne = 0;
      sekundy = sekundy + 1;
    }
    if (sekundy == 60) {
      sekundy = 0;
      setne = 0;
      minuty = minuty + 1;
    }
  }
  if (digitalRead(Stop) == LOW) {
    zaczeto = false;
    if (napisanoKoniec == false) {
      lcd.setCursor(0, 0);
      lcd.print("Koniec");
    }
  }
}

Jednak ten stoper zauważalnie się spóźnia. Być może wynika to z tego, że wykonanie programu przy każdym obiegu pętli zajmuje trochę czasu.

  • Lubię! 1
Link to post
Share on other sites

@StefanekP super że robisz zadania domowe, kody wyglądają bardzo ładnie 🙂 

13 godzin temu, StefanekP napisał:

Jednak ten stoper zauważalnie się spóźnia. Być może wynika to z tego, że wykonanie programu przy każdym obiegu pętli zajmuje trochę czasu.

Tu się nie ma co dziwić, nie regulujesz w żaden sposób czasu obiegu pętli. W pierwszym kodzie 1sekunda opóźnienia znacznie przekracza obliczenia więc nie widać tego, ale tu 1ms jest obarczona błędem obliczeń a w dodatku nie wiesz ile czasu zajmuje wykonanie kodu w pętli. Jak dotrzesz do końca 2 części kursu to poznasz funkcje millis() która nieco pomoże 🙂 

Link to post
Share on other sites

Zadanie 7.4 

O dziwo nawet sprawnie mi poszło wymyślenie jak to w miarę ogarnąć, jednak ze względu na użycie funkcji delay, opcja zatrzymania stopera działa z opóźnieniem. Wystartowanie stopera ok, odmierza ładnie, ale zeby zatrzymać muszę przytrzymać ok 1s. Otrzymałem podpowiedź od znajomego, że muszę ogarnąć timery i przerwania... 

Ale i tak jestem zadowolony z efektu 😛

#include <LiquidCrystal.h>
LiquidCrystal lcd(2,3,4,5,6,7);
#define start 12
#define koniec 13

int licznik = 0;
void setup() {
  lcd.begin(16,2);
  lcd.setCursor(0,0);
  lcd.write("Seconds: ");
  pinMode(start,INPUT_PULLUP);
  pinMode(koniec,INPUT_PULLUP);
  
 }
void loop () {
 if (digitalRead(start) == LOW) {
   while (digitalRead(koniec) == HIGH){
    licznik = licznik +1;
    delay(1000);
    lcd.clear();
    lcd.begin(16,2);
  lcd.setCursor(0,0);
  lcd.write("Seconds: ");
    lcd.setCursor(8,0);
    lcd.print(licznik);
      }
   }
  if (digitalRead(koniec) == LOW)  {
    delay(25);
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.write("Results: ");
    lcd.print(licznik);
    delay(500);
    licznik = 0;
    lcd.setCursor(0,1);
    lcd.write("Click to restart");
  }
 }

 

Link to post
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

14 godzin temu, Krawi92 napisał:

Otrzymałem podpowiedź od znajomego, że muszę ogarnąć timery i przerwania... 

Tak to może pomóc, albo rozdrobnij zliczanie czasu na mniejsze odstępy 😉 

Link to post
Share on other sites

Sprobuje zglebic temat przerwan, bo operacje na czasie w wykorzystaniem delaya sa "malo etyczne" jesli chodzi o programowanie 😄 A problem by sie rozwiazalo w miare bezbolesnie, gdybym zamiast licznik+1 delay(1000) zrobil np wartosc licznik 0.0 + 0.1 i delay(100). Wtedy pewnie przycisk stop dzialalby szybciej, nie byloby tak zauwazalne to.

Link to post
Share on other sites
#include <LiquidCrystal.h> //Dołączenie bilbioteki
#define start1 8
#define stop1 9 
LiquidCrystal lcd(2, 3, 4, 5, 6, 7); //Informacja o podłączeniu nowego wyświetlacza
 double odczyt;
 double czas=0;
 boolean start = false;
 boolean stop11 = false;
 
void setup() {
  lcd.begin(16, 2); //Deklaracja typu
  lcd.setCursor(0, 0); //Ustawienie kursora
  lcd.print("START GRY"); //Wyświetlenie tekstu
  lcd.setCursor(0, 1); //Ustawienie kursora
  lcd.print("Naczysnij start"); //Wyświetlenie tekstu
  lcd.blink();
pinMode(start1, INPUT_PULLUP); 
pinMode(stop1, INPUT_PULLUP); 
}
 
void loop() {
  //czas=czas+1;
  if( digitalRead (start1)== LOW and start==false){
    start=true;
    lcd.clear();
     lcd.setCursor(0, 1); //Ustawienie kursora
  lcd.print("GRA rozpoczęta"); //Wyświetlenie tekstu
  while (digitalRead (stop1)== HIGH){czas=czas+1; delay(1000);}
 
 
    }
if ( digitalRead (stop1)== LOW and start==true and stop11==false){
  lcd.clear();
  stop11=true;
    lcd.setCursor(0, 1); //Ustawienie kursora
  lcd.print("GRA koniec"); //Wyświetlenie tekstu
  
   lcd.setCursor(0, 0); //Ustawienie kursora
  lcd.print(czas); //Wyświetlenie tekstu
}
}

Mam pytanie.

Gdy nie damy delay tylko samo czas=Czas+1 to ile trwa obieg programu ? Niby wyskakują mi wartość ponad 4tys

Link to post
Share on other sites
1 godzinę temu, Antagonista99 napisał:

Gdy nie damy delay tylko samo czas=Czas+1 to ile trwa obieg programu ? Niby wyskakują mi wartość ponad 4tys

 

loop():
        push    rbp # 2 cycles
        mov     rbp, rsp # 1 cycle
        mov     eax, DWORD PTR czas[rip] # 1 cycle
        add     eax, 1 # 1 cycle
        mov     DWORD PTR czas[rip], eax # 1 cycle
        nop #1 cycle
        pop     rbp #2 cycles
        ret # 4 cycles
        
        
# Sum: 13 cycles

13 cykli zegara, zakładając, że używasz kwarcu 16MHz to jest to ok.  812.5ns na każdą pętlę. (UWAGA: nie wliczyłem czasu wykonania pętli while wewnątrz API Arduino, więc będzie to coś bliżej 1us/pętlę). 

Mogłem się walnąć w obliczeniach, ale raczej jest dobrze 😉 

P.S. nie wliczałem też reszty kodu, bo pytanie było ciut nieprecyzyjne, tutaj jest tylko

void loop()
{
  czas = czas + 1;
}

Jeżeli chcesz policzyć całość tutaj masz link. Musisz przekształcić kod z C++ na ASM, przypisać czasy wykonania do instrukcji i je zsumować. Wtedy masz wynik w ilości cykli. Potem liczysz to z równania wynik/zegar i wychodzi Ci czas jednej pętli.

Edytowano przez H1M4W4R1
  • Lubię! 2
Link to post
Share on other sites
20 godzin temu, H1M4W4R1 napisał:

 


loop():
        push    rbp # 2 cycles
        mov     rbp, rsp # 1 cycle
        mov     eax, DWORD PTR czas[rip] # 1 cycle
        add     eax, 1 # 1 cycle
        mov     DWORD PTR czas[rip], eax # 1 cycle
        nop #1 cycle
        pop     rbp #2 cycles
        ret # 4 cycles
        
        
# Sum: 13 cycles

13 cykli zegara, zakładając, że używasz kwarcu 16MHz to jest to ok.  812.5ns na każdą pętlę. (UWAGA: nie wliczyłem czasu wykonania pętli while wewnątrz API Arduino, więc będzie to coś bliżej 1us/pętlę). 

Mogłem się walnąć w obliczeniach, ale raczej jest dobrze 😉 

P.S. nie wliczałem też reszty kodu, bo pytanie było ciut nieprecyzyjne, tutaj jest tylko


void loop()
{
  czas = czas + 1;
}

Jeżeli chcesz policzyć całość tutaj masz link. Musisz przekształcić kod z C++ na ASM, przypisać czasy wykonania do instrukcji i je zsumować. Wtedy masz wynik w ilości cykli. Potem liczysz to z równania wynik/zegar i wychodzi Ci czas jednej pętli.

Chodzi mi o to że po uruchomieniu programu to wartości sięgają ponad 3-4 tys. Czy to czas obiegu pętli ? Czy jest mozliwość że tyle razy na sekunde trwa iteracja ? 

Link to post
Share on other sites
43 minuty temu, Antagonista99 napisał:

Chodzi mi o to że po uruchomieniu programu to wartości sięgają ponad 3-4 tys. Czy to czas obiegu pętli ? Czy jest mozliwość że tyle razy na sekunde trwa iteracja ? 

Tak, bez delay'a wartość zmiennej czas będzie pędzić do przodu kilkaset do kilku tysięcy jednostek na sekundę. I nie, to nie jest czas obiegu pętli. To jest ilość wystąpień pętli w określonym czasie (inaczej częstotliwość lub częstość kołowa).

f = 1/t 

Czyli częstotliwość to odwrotność czasu wykonania pętli. Jeżeli masz 1000 wykonań na sekundę to czas jednego wykonania to 1s/1000 = 1ms.

Edytowano przez H1M4W4R1
  • Lubię! 1
Link to post
Share on other sites
#include <LiquidCrystal.h> //Dołączenie bilbioteki
LiquidCrystal lcd(2, 3, 4, 5, 6, 7);
int sekundy = 0;
int minuty = 0;
int i = 0;
boolean timerON = false;
#define startClock 9
#define stopClock 10
#define resetClock 11

void setup() {
  lcd.begin(16, 2);
  lcd.clear();
  lcd.setCursor(0, 0);
  printTimeBasic();
  lcd.setCursor(0, 1);
  lcd.print("START STOP RESET");
  Serial.begin(9600);
  pinMode(startClock, INPUT_PULLUP);
  pinMode(stopClock, INPUT_PULLUP);
  pinMode(resetClock, INPUT_PULLUP);
}

void loop() {
  if(digitalRead(resetClock) == LOW){
    timerON = false;
    sekundy = 0;
    minuty = 0;
    lcd.setCursor(0, 0);
    printTimeBasic();
    }
  if(digitalRead(startClock) == LOW) {
    timerON = true;
    Serial.println("start");
    delay(50);
    }
 if(timerON == true){
   ChecktoStop();
   sekundy++;
   lcd.setCursor(0, 0);
   printTimeBasic();
   if(sekundy > 9){
    lcd.setCursor(0, 0);
    printTimeSecOver9();
    } 
    else if(minuty > 9 && sekundy < 10 ) {
      lcd.setCursor(0, 0);
      printTimeMinOver9();
      }
    else if(minuty >=10 && sekundy >= 10 ) {
       lcd.setCursor(0, 0);
       printBothOver9();
        }
    if(sekundy == 59) {
      minuty++;
      sekundy = 0;
      }
  }
}

void printTimeBasic () {
  lcd.print("Czas: ");
  lcd.print("0");
  lcd.print(minuty);
  lcd.print(":");
  lcd.print("0");
  lcd.print(sekundy);
  }

  void printTimeSecOver9 () {
  lcd.print("Czas: ");
  lcd.print("0");
  lcd.print(minuty);
  lcd.print(":");
  lcd.print(sekundy);
  lcd.print(" ");
  }
  void printTimeMinOver9 () {
  lcd.print("Czas: ");
  lcd.print(minuty);
  Serial.println(minuty);
  lcd.print(":");
  lcd.print("0");
  lcd.print(sekundy);
  Serial.println(sekundy);
  lcd.print(" ");
  }

  void printBothOver9 () {
  lcd.print("Czas: ");
  lcd.print(minuty);
  lcd.print(":");
  lcd.print(sekundy);
  lcd.print(" ");
  }
  void ChecktoStop() {
    for(i=0; i<100; i++){
      if(digitalRead(stopClock) == LOW) {
         timerON = false;
         Serial.println("stop");
      }
       delay(10);
      }
    }

Zadanie domowe 7.4, dodałem również przycisk RESET, który zatrzymuje stoper i ustawia go spowrotem na 00:00.

  • Lubię! 2
Link to post
Share on other sites

@n1ckenn super, dobrze że robisz coś ponad 🙂 

Taka tylko drobna uwaga, #define dawaj najlepiej na samej górze kodu. Jak poznasz millis() to dowiesz się, że czas najlepiej zliczać używając unsigned long. Na szczęście kod jest domyślnie optymalizowany więc różne takie niedociągnięcia są wybaczane 🙂 

  • Pomogłeś! 1
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...

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.