Skocz do zawartości

Pomocna odpowiedź

(edytowany)
39 minut temu, prezesedi napisał:

pomyślałem, że można "wyciszyć wyświetlacz".

Bardzo dobrze pomyślałeś.

Wyłączenie wyświetlacza:

display.ssd1306_command(SSD1306_DISPLAYOFF);

Włączenie w teorii powinno wyglądać tak:

display.ssd1306_command(SSD1306_DISPLAYON);

ale nie zawsze się to udaje. Możesz spróbować. Jeśli nie wyjdzie - wywołaj po command po prostu display.begin() z takimi samymi parametrami jak w setup.

39 minut temu, prezesedi napisał:

czy to jest to samo co zapis --1)

Nie - taki zapis nie ma sensu.

Operatory pre/postdekrementacji działaja tylko na zmiennych i oznaczają podstawienie do zmiennej nowej wartości, równej poprzedniej wartości minus jeden. A raczej do jedynki dość trudno podstawić cokolwiek.

Prawidłowy jest zapis x-- lub --x. O różnicy między nimi może innym razem 🙂

 

Edytowano przez ethanak
  • Lubię! 1

...DISPLAYON i ...DISPLAYOFF "już w kodzie".

Jeszcze nie sprawdzałem, ale zapewne różnica jest następująca: te komendy wyłączają i włączają zasilanie w ekranie co zmniejsza pobór prądu? Czy może chodzi też o zwolnienie części zasobu pamięci?

1 godzinę temu, ethanak napisał:

A tak przy okazji - do czego jest zmienna "kopia", bo Twój sposób nazywania zmiennych jest... jakby tu powiedzieć... niezbyt standardowy 😉

Nazwa tej zmiennej to mój wynalazek...😜 Jakoś się przyzwyczaiłem do "kopia" "stan" i wszelkiej maści "xyz" (oczywiscie tylko wtedy kiedy jest killka zmiennych, a nie 50 czy 100) ta zmienna ma zapamiętać który guzik został wciśnięty żeby można było zapętlić maszynę stanów i wrócić do konkretnego case...

56 minut temu, prezesedi napisał:

 


 

 

 

W sumie to... nie jest mój kod. To Wasze dzieło @ethanak i @farmaceuta. Nawet wątek nie jest mój i mało wspólnego z tematem.

Jak czytam mój pierwszy wpis, to jestem w szoku czego chciałem dokonać. Jak bardzo skomplikować życie sobie i innym.

@ethanak zajrzałem do pliku z czcionką jaki mi przesłałeś i wykorzystałem w kodzie polskie znaki. Efekt wygląda jak poniżej:

 

20220629_160329[1].jpg

38 minut temu, prezesedi napisał:

Nawet wątek nie jest mój i mało wspólnego z tematem.

W sumie może ktoś ( @Gieneq? @Treker ) zlituje się i wydzieli te posty do oddzielnego wątku? Proponuję tytuł "Wyświetlacz OLED w makiecie kolejowej" albo coś podobnego...

Tak przy okazji:

1 godzinę temu, prezesedi napisał:

te komendy wyłączają i włączają zasilanie w ekranie co zmniejsza pobór prądu?

Mniej więcej tak. Zasilanie ekranu zostaje wyłączone (m.in. przetwornica) a sam kontroler przechodzi w tryb niskiego poboru prądu. W Twoim rozwiązaniu rozwiązanie jest niespecjalnie trafione - stosuje się to w rozwiązaniach z zasilaniem bateryjnym, gdzie nie ma wyłącznika. Robiłem tak w takiej zabawce (gra na ATtiny85) zasilanej z bateryjki 2032. Przy zasilaniu sieciowym lepiej zastosować zwykłe czyszczenie ekranu tak jak proponowałeś.

Ale odrobina wiedzy nikomu nie zaszkodziła.

44 minuty temu, prezesedi napisał:

wykorzystałem w kodzie polskie znaki

I o to chodziło.

To co, kombinujemy dalej?

11 minut temu, ethanak napisał:

To co, kombinujemy dalej?

Oczywiście

czytam o podpinaniu dwóch wyświetlaczy, jednak dopiero zaczynam i trochę mi zejdzie. Wiem już że trzeba nazwać obydwa inaczej i zrobić komendy dla obu. Mój pomysł - ten 128x64 na budynku dworca - wszystkie kody jak do tej pory. Mały 128x32 na peronie. Mam też rozpiskę pinów ESP32 by zdefiniować drugą linię I2C.

Czy zdefiniowanie wyświetlaczy będzie następujące?

Adafruit_SSD1306 display1(128,64,&Wire);
Adafruit_SSD1306 display2(128,32,&Wire);

 

14 minut temu, prezesedi napisał:

Czy zdefiniowanie wyświetlaczy będzie następujące?

Nie - musisz użyć dwóch szyn I2C bo wyświetlacze mają ten sam adres.

Powinno być:

Adafruit_SSD1306 display1(128,64,&Wire);
Adafruit_SSD1306 display2(128,32,&Wire1);

i potem w setup inicjalizacja obu szyn:
 

Wire.begin(OLED_SDA, OLED_SCL);
Wire1.begin(OLED2_SDA, OLED2_SCL);

Wire i Wire1 są zdefiniowane przez bibliotekę. OLED2_SDA i OLED2_SCL to piny drugiej szyny.

Tylko troszkę wyhamuj rozpęd: najpierw zróbmy te nieszczęsne wyświetlanie, bo jak będziesz każdą linijkę po sto razy powielać to te nędzne 4 megabajty flasha mogą nie starczyć. Czyli najpierw zrobienie porządnych funkcji wyświetlania (można zacząć od tego co pokazałem wcześniej), a potem dopiero podłączenie drugiego wyświetlacza.

Dlaczego tak?

Bo teraz podłączenie drugiego wyświetlacza wymaga dopisania jakichś dwustu linii kodu. A ja planuję zmieścić się w kilkunastu...

Adres obu to wg I2c Scanner

I2C device found at address 0x3C  !

Ten skrócony kod można jeszcze bardziej skrócić?

2 minuty temu, prezesedi napisał:

Adres obu to wg I2c Scanner

I2C device found at address 0x3C  !

Czyli tu nic się nie poradzi, musimy zastosować dwie szyny.

2 minuty temu, prezesedi napisał:

Ten skrócony kod można jeszcze bardziej skrócić?

Oczywiście że można - tyle że chcę to zrobić etapami żebyś cokolwiek z tego zrozumiał i w razie czego był w stanie coś tam zmienić/poprawić.

47 minut temu, prezesedi napisał:

"AJM REDI"

OK, to jedziemy.

Jak rozumiem, zmieniłeś już sposób wyświetlania z makaronu w switch/case na wywołanie funkcji "wyświetl"? Jeśli nie, zrób to i pokaż pełny kod. Będziemy się zastanawiać, jak to można jeszcze uprościć - na razie poprzez usunięcie powtarzających się fragmentów kodu.

A,i przygotuj się na to, że pozmieniamy sobie nazwy zmiennych. O ile 'x' jeszcze jakoś ujdzie, o tyle 'y' sugeruje że mamy do czynienia z jakimś przesunięciem w pionie, a 'kopia' to już w ogóle pomyłka (bo czego to kopia i do czego ma niby służyć?). Ale to przy okazji następnej iteracji 🙂

pełny kod, który pracuje na 0,94" wygląda następująco (przypominam, że miałem problem z klawiaturą - dlatego tam jest bajzel - ale wyświetla dzięki temu prawidłowo)

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Keypad.h>

      //ustawienie i2c
#define OLED_SDA 21
#define OLED_SCL 22
#define SCROLL_STEP 10UL

static uint32_t displayctl= millis();

Adafruit_SSD1306 display(128,64,&Wire);



      // ustawienie klawiatury
const byte ROWS = 4; //cztery rzędy
const byte COLS = 3; //trzy kolumny
char hexaKeys[ROWS][COLS] = {
  {'2','1','3'},
  {'5','4','6'},
  {'8','7','9'},
  {'0','*','#'}};

char message1[]="1 00:05 EC 'SOBIESKI' Wien";
char message2[]="2 01:15 EC 'POLONIA' Berlin";
char message3[]="3 02:00 EC 'CHOPIN' Graz";
char message4[]="4 03:30 EC 'SILESIA' Praha";
char message5[]="1 04:05 EIP 'GIBKI CUG' Warszawa Wsch.";
char message6[]="2 05:00 TLK 'JASNA G\013RA' Cz\005stochowa";
char message7[]="3 05:55 EIC 'KORMORAN' Olsztyn G\025.";
char message8[]="4 06:20 IC 'TATRY' Zakopane";
char message9[]="1 07:15 IC 'G\013RAL' Bielsko Bia\025a";
char message10[]="2 07:30 EIC 'LATARNIK' Ko\025obrzeg";
char message11[]="3 08:00 K\006 'SZTYGAR' Tarnowskie G\014ry";
char message12[]="4 08:05 IC 'CZANTORIA' Wis\025a G\025\005bce";
char message13[]="1 11:55 TLK 'GRANICA' Cha\025upki";
char message14[]="2 12:00 IC 'SUDETY' K\025odzko";
char message15[]="3 12:10 IC 'LAJKONIK' Krak\014w";
char message16[]="4 12:25 K\006 'BESKIDY' \016ywiec";
char message17[]="1 14:15 K\006 'G\013RNIK' Gliwice";
char message18[]="2 14:40 K\006 'FIAT' Tychy Lodowisko";
char message19[]="3 15:00 PR 'WARTA' Wielu\023 D\003browa";
char message20[]="4 15:25 TLK 'BOLEK I LOLEK' Wodzis\025aw \006l.";
char message21[]="1 17:30 IC 'ODRA' Opole";
char message22[]="2 17:40 EIP 'PRZEMY\006LANIN' Przemy\007l G\025.";
char message23[]="3 17:55 K\006 'SPODEK' Katowice";
char message24[]="4 18:15 EIC 'KARKONOSZE' Jelenia G\014ra";
char message25[]="1 19:00 EIP 'NEPTUN' Hel";
char message26[]="2 19:20 K\006 'PIRAT' Lubliniec";
char message27[]="3 19:45 PR 'SPRINTER' \016ywiec";
char message28[]="4 20:00 K\006 'GWAREK' Racib\014rz";
char message29[]="1 21:00 EIC 'BA\024TYK' Gdynia G\025.";
char message30[]="2 21:30 EIP 'PIAST' Pozna\023 G\025.";
char message31[]="3 21:45 PR 'GIBKI CUG' Tarnowskie G\014ry";
char message32[]="4 22:00 IC 'CHEMIK' P\025ock";
char message33[]="1 22:05 EIC 'WYDMY' Ustka";
char message34[]="2 22:40 TLK 'SZYCHTA' Sosnowiec P\025d.";
char message35[]="3 23:20 EIC 'WOLIN' \006winouj\007cie";
char message36[]="4 23:50 EC 'LW\013W EXPRESS' Kiev";
   int x, minX;

      // podłączenie klawiatury do Arduino   
byte rowPins[ROWS] = {18, 5, 17, 16};  //Piny, do których podłączamy wyprowadzenia od rzędów
byte colPins[COLS] = {2, 4, 15}; //Piny, do których podłączamy wyprowadzenia od kolumn

Keypad keypad = Keypad( makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS );

  void setup(){

  Wire.begin(OLED_SDA, OLED_SCL);
  Serial.begin(9600);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setTextWrap(false);
  x = display.width();
  minX = -16 * strlen(message1);
  }

  void wyswietl(const char *msg1, const char *msg2, const char *msg3, const char *msg4)
{
    display.ssd1306_command(SSD1306_DISPLAYON);
    display.clearDisplay();
    display.setTextSize(2); // wystarczy raz
    display.setCursor(x,0);
    display.print(msg1);
    display.setCursor(x,16);
    display.print(msg2);
    display.setCursor(x,32);
    display.print(msg3);
    display.setCursor(x,48);
    display.print(msg4);
    display.display();
    x -= 1;
}

  void loop(){
 static byte y = 0;
 static long last = 0;
 static byte kopia = 0;

  char key = keypad.getKey();
      Serial.println(key);
 
  if (key == '1') { 
    delay(500);       
   x= display.width();
   y = 1;
   kopia = 1;
} else if (key == '2') { 
   delay(500);       
   x= display.width();
   y = 2;
   kopia = 2;
} else if (key == '3') { 
   delay(500);
   x= display.width();
   y = 3;
   kopia = 3;
} else if (key == '4') { 
   delay(500);
   x= display.width();
   y = 4;
   kopia = 4;
} else if (key == '5') { 
   delay(500);
   x= display.width();
   y = 5;
   kopia = 5;
} else if (key == '6') { 
   delay(500);
   x= display.width();
   y = 6;
   kopia = 6;
} else if (key == '7') { 
   delay(500);
   x= display.width();
   y = 7;
   kopia = 7;
} else if (key == '8') { 
   delay(500);
   x= display.width();
   y = 8;
   kopia = 8;
} else if (key == '9') { 
   delay(500);
   x= display.width();
   y = 9;
   kopia = 9;
} else if (key == '0') { 
   delay(500);
   x= display.width();
   y = 0;
   kopia = 0;
}

if (millis() - displayctl < SCROLL_STEP) return;
displayctl = millis();

switch(y) {
        case 0:
        display.ssd1306_command(SSD1306_DISPLAYOFF);
        break;
        
        case 1:
        wyswietl(message1, message2, message3, message4);
        break;

        case 2:
        wyswietl(message5, message6, message7, message8);
        break;

        case 3:
        wyswietl(message9, message10, message11, message12);
        break;

        case 4:
        wyswietl(message13, message14, message15, message16);
        break;

        case 5:
        wyswietl(message17, message18, message19, message20);
        break;

        case 6:
        wyswietl(message21, message22, message23, message24);
        break;

        case 7:
        wyswietl(message25, message26, message27, message28);
        break;

        case 8:
        wyswietl(message29, message30, message31, message32);
        break;

        case 9:
        wyswietl(message33, message34, message35, message36);
        break;

   case 10: 
   display.clearDisplay();
   display.setCursor(18,0);
   display.setTextSize(1);
   display.print("KATOWICE BRYNOW");
   display.setTextSize(3);
   display.setCursor(20,15);
   display.print("15:20");
   display.display();
   y = 11;
   last = millis();
   break;

   case 11:
   if (millis() - last > 3000UL) { // 3000 = 3 sekundy
    y = kopia;
    x = display.width();
    }
  break;
  }
  
    
  if(x < minX) {
    x = display.width();
    y = 10;
   }
}

 

  • Lubię! 1

OK, jeśli to działa to spróbujmy teraz trochę posprzątać.

Przede wszystkim to co mówiłem o zmiennych. Po pierwsze - zdecydujmy się na język. Polski jest fajny, ale bez polskich literek czasem można się pogubić. Mieszanka językowa polsko-angielska też nie jest za ciekawa. Pozostańmy więc przy angielskim.

  • Zmienna o nazwie 'y' niknie z programu. W jej miejsce pojawia się zmienna globalna currentMsg (to co jest rzeczywiście wyświetlane)
  • Zmienna o nazwie 'kopia' niknie z programu. W jej miejsce pojawia się zmienna globalna scheduleMsg (czyli komunikat rozkładu)
  • Zmienna o nazwie 'last' niknie z programu. W jej miejsce pojawia się zmienna globalna lastLocalMsg (kiedy zaczęto wyświetlać nazwę stacji)
  • Zmienną 'x' pozostawimy na razie bez zmian...

Tak więc mamy przed setup() (tam gdzie zwykło się umieszczać deklaracje zmiennych):
 

byte currentMsg=0; // nic nie wyświetlamy
byte scheduleMsg=0; // nie wyświetlamy rozkładu
uint32_t lastLocalMsg; // to jest właściwy typ do trzymania czasu a nie żaden long.

W związku z tym początek głównej pętli będzie wyglądać tak:
 

void loop()
{
    char key = keypad.getKey();

Na razie możesz uczynić stosowne poprawki kosmetyczne (pozmieniać te nazwy zmiennych, skompilować program, sprawdzić czy działa i jeśli działa to czytać dalej)

Operujemy teraz cały czas jakimiś dziwacznymi zmiennymi typu messageCośtam. To jest dopuszczalne jak tych wiadomości jest dwie czy trzy, ale nie więcej. Zróbmy sobie z nich po prostu tablicę:

char * messages[] = {
    "1 00:05 EC 'SOBIESKI' Wien",
    "2 01:15 EC 'POLONIA' Berlin",
    "3 02:00 EC 'CHOPIN' Graz",
    "4 03:30 EC 'SILESIA' Praha",
    "1 04:05 EIP 'GIBKI CUG' Warszawa Wsch.",
    "2 05:00 TLK 'JASNA G\013RA' Cz\005stochowa",
    "3 05:55 EIC 'KORMORAN' Olsztyn G\025.",
    "4 06:20 IC 'TATRY' Zakopane",
    "1 07:15 IC 'G\013RAL' Bielsko Bia\025a",
    "2 07:30 EIC 'LATARNIK' Ko\025obrzeg",
    "3 08:00 K\006 'SZTYGAR' Tarnowskie G\014ry",
    "4 08:05 IC 'CZANTORIA' Wis\025a G\025\005bce",
    "1 11:55 TLK 'GRANICA' Cha\025upki",
    "2 12:00 IC 'SUDETY' K\025odzko",
    "3 12:10 IC 'LAJKONIK' Krak\014w",
    "4 12:25 K\006 'BESKIDY' \016ywiec",
    "1 14:15 K\006 'G\013RNIK' Gliwice",
    "2 14:40 K\006 'FIAT' Tychy Lodowisko",
    "3 15:00 PR 'WARTA' Wielu\023 D\003browa",
    "4 15:25 TLK 'BOLEK I LOLEK' Wodzis\025aw \006l.",
    "1 17:30 IC 'ODRA' Opole",
    "2 17:40 EIP 'PRZEMY\006LANIN' Przemy\007l G\025.",
    "3 17:55 K\006 'SPODEK' Katowice",
    "4 18:15 EIC 'KARKONOSZE' Jelenia G\014ra",
    "1 19:00 EIP 'NEPTUN' Hel",
    "2 19:20 K\006 'PIRAT' Lubliniec",
    "3 19:45 PR 'SPRINTER' \016ywiec",
    "4 20:00 K\006 'GWAREK' Racib\014rz",
    "1 21:00 EIC 'BA\024TYK' Gdynia G\025.",
    "2 21:30 EIP 'PIAST' Pozna\023 G\025.",
    "3 21:45 PR 'GIBKI CUG' Tarnowskie G\014ry",
    "4 22:00 IC 'CHEMIK' P\025ock",
    "1 22:05 EIC 'WYDMY' Ustka",
    "2 22:40 TLK 'SZYCHTA' Sosnowiec P\025d.",
    "3 23:20 EIC 'WOLIN' \006winouj\007cie",
    "4 23:50 EC 'LW\013W EXPRESS' Kiev"
};

Teoretycznie nic to nie dało, ponieważ do funkcji wyswietl musielibyśmy przekazywać parametry typu:

wyswietl(messages[0], messages[1], messages[2], messages[3]);

Spróbujmy więc zrobić coś, aby funkcja 'wyswietl' była jakaś bardziej sensowna:

void wyswietl(int n)
{
    display.ssd1306_command(SSD1306_DISPLAYON);
    display.clearDisplay();
    display.setTextSize(2); // wystarczy raz
    int i;
    for (i=0;i<4; i++) {
        display.setCursor(x,i*16);
        display.print(messages[(n-1) * 4] + i);
    }
    display.display();
    x -= 1;
}

Jakby ładniejsza się zrobiła... no ale co to zmienia?

A zmienia tyle, że możemy teraz zrobić prostą konstrukcję typu:

if (currentMessage >= 1 && currentMessage <= 9) {
    wyswietl(currentMessage);
    return;
}

switch(currentMessage) {
    case 10:
    // tu kod dla 10
    break;
    
    case 11:
    // tu kod dla 11
    break;

    default: //zamiast case 0
    // tu kod dla 0
    break;
}

Jak się skrócił kod? Ile linijek będziesz musiał zmienić gdy podłączysz display 128x32?

W ramach odpoczynku przy wieczornej herbatce wymyśl jakąś fajną nazwę dla funkcji 'wyswietl'

Stay tuned!

 

No i poległem.

Nie potrafię przejść błędu związanego z BREAK "break statement not within loop or switch".

Dla funkcji 'wyswietl' proponuję 'show'

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...