[046] Bargraf o dużej rozdzielczości

[046] Bargraf o dużej rozdzielczości

Kontynuując historię bargrafu z ostatniego artykułu, spróbujmy przerwać zaklęty krąg szesnastu cegiełek. Co prawda w ostatnim przypadku widać ich było 32, ale nastąpiło tam pewne oszustwo, gdyż były związane parami. Stosowano to czasem w wieżach audio, dzieląc świecące segmenty na połowę, co dawało iluzję większej rozdzielczości wskaźników wysterowania. Tutaj jednak możemy za darmo – sposobem, stworzyć sobie prawdziwe 32 niezależne pola. Wróćmy do wersji bezramkowej.


#include <Wire.h>                                                      // Biblioteka obsługująca magistralę I2C
#include <hd44780.h>                                                   // Biblioteka obsługująca wyświetlacze 44780
#include <hd44780ioClass/hd44780_I2Cexp.h>                             // Dodatek obsługujący wyświetlacze podłączone do ekspandera I2C
hd44780_I2Cexp lcd(0x20, I2Cexp_MCP23008, 7, 6, 5, 4, 3, 2, 1, HIGH);  // Konfiguracja połączeń wyświetlacza LCD

const byte woltomierz = A1;  // Port, który będzie mierzyć napięcie.
int napiecie;                // Wartość tego napięcia bez jednostek.
float napiecieV;             // Wartość tego napięcia w woltach.
byte bargraf;                // Wartość tego napięcia dla bargrafu.
int napiecieStare = 255;     // Wartość poprzednio zmierzonego napięcia.

byte znak0[8] = { 0b11000, 0b11000, 0b11000, 0b11000, 0b11000, 0b11000, 0b11000, 0b11000 };  // Grafiki użytkownika.
byte znak1[8] = { 0b11011, 0b11011, 0b11011, 0b11011, 0b11011, 0b11011, 0b11011, 0b11011 };

void setup() {
  lcd.begin(16, 2);          // Inicjalizacja wyświetlacza LCD
  lcd.createChar(0, znak0);  // Zaprogramuj grafikę użytkownika.
  lcd.createChar(1, znak1);
}

void loop() {
  while (abs(napiecie - napiecieStare) < 4) {  // Porównaj ze sobą kolejne mierzone wartości napięć i wyjdź, jeśli różnią się o więcej niż 3
    napiecie = analogRead(woltomierz);         // Pobierz wartość napięcia z portu woltomierza.
  }
  napiecieStare = napiecie;  // Przepisz wartość zmierzonego napięcia do zmiennej napiecieStare.

  lcd.setCursor(0, 0);   // Ustaw kursor na początku wyświetlacza.
  lcd.print(napiecie);   // Wyświetl ją.
  lcd.print(F("    "));  // Wyświetl cztery spacje.

  lcd.setCursor(6, 0);       // Ustaw kursor na pzycji szóstej.
  lcd.print(napiecie, HEX);  // Wyświetl zmierzoną wartość w formacie HEX
  lcd.print(F("   "));       // Wyświetl trzy spacje.

  lcd.setCursor(11, 0);                   // Ustaw kursor na pzycji jedenastej.
  napiecieV = napiecie * (5.0 / 1024.0);  // Przelicz dziesięciobitową wartość na wolty.
  lcd.print(napiecieV, 3);                // Wyświetl napięcie z dokładnością do trzech cyfr po przecinku.

  lcd.setCursor(0, 1);                  // Ustaw kursor na początku dolnego wiersza.
  bargraf = (32 + napiecie) / 64;       // Oblicz długość bargrafu, przesuwając całość o połowę działki.
  for (byte x = 0; x < bargraf; x++) {  // Powtarzaj zgodnie z długością bargrafu minus jeden.
    lcd.write(1);                       // Wyświetl grafikę z dwoma słupkami.
  }
  if ((32 + napiecie) % 64 > 32) {  //  Jeśli reszta z dzielenia długości bargrafu przesuniętą o połowę działki jest większa o połowę działki, to...
    lcd.write(0);                   // Wyświetl grafikę z jednym słupkiem.
  }
  lcd.print(F("               "));  // Wyświetl 15 spacji.
}

Zadeklarujemy sobie dwa znaki: jeden będzie kopią „cegiełki” jakiej już używaliśmy, czyli podwójnej byte znak1[8] Drugi będzie zawierał tylko jeden słupek byte znak0[8] Zmienimy teraz procedurę rysowania bargrafu. Jego długość będziemy liczyć nieco inaczej, wstępnie przesuwając zakres o połowę pierwotnej działki, czyli 32 bargraf = (32 + napiecie) / 64 Następnie narysujemy n-1 cegiełek podwójnych i na końcu dodatkowo cegiełkę pojedynczą albo spację. Ta pierwsza pojawi się tylko wtedy, gdy reszta z dzielenia napięcia powiększonego o pół działki, czyli 32, przez wartość działki, czyli 64, będzie większa o pół działki. Innymi słowy, jeśli wartość będzie większa od n działek plus połowę działki, na końcu wyświetli się jeszcze jeden słupek. W rezultacie rozdzielczość bargrafu zwiększy się dwukrotnie. Współczynniki dobrałem tak, by dla zera tym razem nie świecił się żaden segment.

Bardziej „linijkową” postać bargrafu otrzymamy, gdy zmienimy wygląd drugiego słupka w znaku zerowym.

A może by tak jeszcze bardziej zwiększyć rozdzielczość? Ależ proszę. Pole 5x8 pikseli można podzielić na trzy części, zatem dostaniemy rozdzielczość równą 48 działkom – już bardzo ładną. Trochę jednak skomplikuje się nam rysowanie, ale od czego mamy tu komputerek?

#include <Wire.h>                                                      // Biblioteka obsługująca magistralę I2C
#include <hd44780.h>                                                   // Biblioteka obsługująca wyświetlacze 44780
#include <hd44780ioClass/hd44780_I2Cexp.h>                             // Dodatek obsługujący wyświetlacze podłączone do ekspandera I2C
hd44780_I2Cexp lcd(0x20, I2Cexp_MCP23008, 7, 6, 5, 4, 3, 2, 1, HIGH);  // Konfiguracja połączeń wyświetlacza LCD

const byte woltomierz = A1;  // Port, który będzie mierzyć napięcie.
int napiecie;                // Wartość tego napięcia bez jednostek.
float napiecieV;             // Wartość tego napięcia w woltach.
byte bargraf;                // Wartość tego napięcia dla bargrafu.
int napiecieStare = 255;     // Wartość poprzednio zmierzonego napięcia.

byte znak0[8] = { 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000, 0b10000 };  // Grafiki użytkownika.
byte znak1[8] = { 0b10100, 0b10100, 0b10100, 0b10100, 0b10100, 0b10100, 0b10100, 0b10100 };
byte znak2[8] = { 0b10101, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101, 0b10101 };

void setup() {
  lcd.begin(16, 2);          // Inicjalizacja wyświetlacza LCD
  lcd.createChar(0, znak0);  // Zaprogramuj grafikę użytkownika.
  lcd.createChar(1, znak1);
  lcd.createChar(2, znak2);
}

void loop() {
  while (abs(napiecie - napiecieStare) < 4) {  // Porównaj ze sobą kolejne mierzone wartości napięć i wyjdź, jeśli różnią się o więcej niż 3
    napiecie = analogRead(woltomierz);         // Pobierz wartość napięcia z portu woltomierza.
  }
  napiecieStare = napiecie;  // Przepisz wartość zmierzonego napięcia do zmiennej napiecieStare.

  lcd.setCursor(0, 0);   // Ustaw kursor na początku wyświetlacza.
  lcd.print(napiecie);   // Wyświetl ją.
  lcd.print(F("    "));  // Wyświetl cztery spacje.

  lcd.setCursor(6, 0);       // Ustaw kursor na pzycji szóstej.
  lcd.print(napiecie, HEX);  // Wyświetl zmierzoną wartość w formacie HEX
  lcd.print(F("   "));       // Wyświetl trzy spacje.

  lcd.setCursor(11, 0);                   // Ustaw kursor na pzycji jedenastej.
  napiecieV = napiecie * (5.0 / 1024.0);  // Przelicz dziesięciobitową wartość na wolty.
  lcd.print(napiecieV, 3);                // Wyświetl napięcie z dokładnością do trzech cyfr po przecinku.

  lcd.setCursor(0, 1);                  // Ustaw kursor na początku dolnego wiersza.
  bargraf = (21 + napiecie) / 64;       // Oblicz długość bargrafu, przesuwając całość o 1/3 działki.
  for (byte x = 0; x < bargraf; x++) {  // Powtarzaj zgodnie z długością bargrafu minus jeden.
    lcd.write(2);                       // Wyświetl grafikę z trzema słupkami.
  }
  if ((21 + napiecie) % 64 > 21 && (21 + napiecie) % 64 <= 42) {  // Jeśli reszta z dzielenia długości bargrafu przesuniętą o 1/3 działki jest większa o 1/3 działki i mniejsza o 2/3, to...
    lcd.write(0);                                                 // Wyświetl grafikę z jednym słupkiem.
  }
  if ((21 + napiecie) % 64 > 42) {  // Jeśli reszta z dzielenia długości bargrafu przesuniętą o 1/3 działki jest większa o 2/3 działki, to...
    lcd.write(1);                   // Wyświetl grafikę z dwoma słupkami.
  }
  lcd.print(F("               "));  // Wyświetl 15 spacji.
}

Po pierwsze, zdefiniujemy sobie trzy wzorce cegiełek: z jednym, dwoma i trzema słupkami. W procedurze rysującej trzy słupki zmienimy współczynnik przesunięcia, już nie o połowę, a 1/3 zakresu, czyli o 21 bargraf = (21 + napiecie) / 64 Ostatnie pole będziemy wypełniać alternatywnie: jednym słupkiem – jeśli reszta z dzielenia będzie się trzymała środkowych „jednych trzecich” działki if ((21 + napiecie) % 64 > 21 && (21 + napiecie) % 64 <= 42) i dwoma – jeśli będzie należeć do górnych „jednych trzecich” if ((21 + napiecie) % 64 > 42) Trzeba pamiętać, że dzielenie przez trzy nie da nam tu liczb naturalnych, ale w przypadku bargrafu takie zaokrąglenia nie mają znaczenia.

Można jeszcze spróbować rozbudować bargraf do wszystkich kolumn, otrzymując rozdzielczość 80 działek, ale nie będzie to już wyglądać tak ładnie, bo pola alfanumeryczne są przedzielone od siebie jednopikselową przerwą, do której nie mamy dostępu. Zatem ten etap będzie chyba ostatnim sensownym i na nim zakończę rozważania.

Powiązane tematy

Płytka edukacyjna TME-EDU-ARD-2Płytka edukacyjna TME-EDU-ARD-2Sprawdź tutaj

Przeczytaj również

Nasi partnerzy

TMETech Master EventTME EducationPoweredby
Copyright © 2024 arduino.pl