[076] Układamy wiedzę - cz. 2

[076] Układamy wiedzę - cz. 2

W poprzednim artykule zakończyliśmy rozważania na etapie użycia na początku szkicu definicji adresu zamiast tychże adresów w treści programu, by w razie potrzeby zmiany pinu wprowadzić tylko jedną korektę, a nie całą serię odwołań powtykanych w programie. Zamiast trzynastki użyłem nazwy diodaSwiecaca, która jest zmienną o wartości równej 13, co zostało powołane do życia i nakarmione tą wartością tutaj:


byte diodaSwiecaca = 13;  // Numer pinu, do której podłączona jest dioda świecąca.

void setup() {
  pinMode(diodaSwiecaca, OUTPUT);  // Zadeklaruj port diody jako wyjście.
}

void loop() {
  digitalWrite(diodaSwiecaca, HIGH);  // Włącz diodę.
  delay(250);                         // Zaczekaj 250 milisekund.
  digitalWrite(diodaSwiecaca, LOW);   // Wyłącz diodę.
  delay(250);                         // Zaczekaj 250 milisekund.
}

Ale na początku mamy jeszcze słówko byte. Gdybyśmy je skasowali, wyskoczyłby błąd. Otóż w Arduinolandzie, jak również w większości języków programowania, nie można sobie tak po prostu wymyślić zmiennej i obdarować ją wartością. Należy jeszcze określić co to za zmienna, a określeń może być kilka i każde z nich niesie jakieś konsekwencje.

Do dalszych zabaw użyjemy wyświetlacza z płytki edukacyjnej TME. Spójrzmy jak bardzo arduinowa matematyka jest zależna od typów zmiennych. Zaczniemy od byte On oznacza, że zmienna będzie mogła przyjmować wartości od 0 do 255. Matematyka w świecie byte jest malutka.

#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

byte x;  // Zmienne do ćwiczeń z arduinowej matematyki.
byte y;
byte z;

void setup() {
  lcd.begin(16, 2);  // Inicjuj wyświetlacz LCD
  x = 200;
  y = 100;
  z = x + y;
  lcd.print(z);  // Wyślij wartość zmiennej z na wyświetlacz.
}
void loop() {
}

Zadeklarujmy sobie trzy takie zmienne: x, y oraz z. Pierwszej przyznamy wartość 200, drugiej 100, a trzeciej – sumę. Po wyświetleniu zamiast 300 zobaczymy… 44. Dlaczego?

Bo licznik doszedł do 255, a następnie przewinął się. Innymi słowy, liczby większe od 255 są ignorowane, bierze się tylko resztę z dzielenia przez tą wartość, a ta wyniosła właśnie 44. Ma to dwie zalety: raz – program nie wywali się na skutek przekroczenia zakresu, dwa – w pewnych sytuacjach, gdy interesuje nas tylko reszta z dzielenia jakichś dużych liczb, możemy pomijać fakt, że nadal są duże albo że wyszły z ułamkiem. Dlatego też w poprzednim przykładzie, zamiast deklarować adres portu diody jako 13, możemy równie dobrze użyć 269, tylko raczej w tym przypadku nie widzę zastosowań dla tej metody. Ale możemy.

No dobra, a gdybyśmy jednak potrzebowali większych wartości? Sięgamy do kolejnego typu: int

int x;  // Zmienne do ćwiczeń z arduinowej matematyki.
int y;
int z;

void setup() {
  x = 200;
  y = 100;
  z = x + y;
  lcd.print(z);  // Wyślij wartość zmiennej z na wyświetlacz.
}

Teraz już możemy szaleć w przedziale od -32 768 do 32 767 na tej samej zasadzie. Wynik nie wynosi już 44, a 300, czyli tyle, ile podpowiada nam rozsądek.

Ale gdy przekroczymy wspomniany zakres, znowu zaczną dziać się cuda, jak poprzednio, czyli wylądujemy na drugim końcu przedziału, jednak teraz z uwzględnieniem liczb ujemnych. Zróbmy inne działanie: minus tysiąc podzielmy przez trzy. Dostaliśmy wynik: -333

Nadal więc mamy liczby bez ułamków, ale teraz także ujemne. Odmianą tego typu zmiennej jest int bez znaku, czyli unsigned int Różni się tym, że zaczyna się od zera, ale za to kończy na 65 535. W określonych przypadkach możemy potrzebować szerszego zakresu bez liczb ujemnych i tu właśnie mamy coś takiego.

Nadal mało? Ależ proszę: format long daje nam już zakres całkowity do 2 miliardów z hakiem i do w dwie strony – także w liczbach ujemnych (konkretnie od -2 147 483 648 do 2 147 483 647). Alternatywnie mamy wersję unsigned long przekraczającą 4 miliardy bez liczb ujemnych (konkretnie 4 294 967 295).

A gdybyśmy potrzebowali wartości ułamkowych, albo jakichś kosmicznych zakresów? Dla takich rzeczy istnieje kolejna forma: float Różni się ona zasadniczo: po pierwsze przenosi ułamki, po drugie – jest… niedokładna! Precyzja sięga jakichś 6-7 cyfr, więc chcąc zbudować kalkulator w oparciu o float, musimy się liczyć z tym, że czasem dostaniemy dziwne wyniki.

float x;  // Zmienne do ćwiczeń z arduinowej matematyki.
float y;
float z;

void setup() {
  x = 1;
  y = 3;
  z = x / y;
  lcd.print(z, 10);  // Wyślij wartość zmiennej z na wyświetlacz.
}

Spójrzmy na przykład: podzielimy 1 przez 3. W linii wyświetlającej aktywowałem obrazowanie aż 10 cyfr po przecinku.

Pierwszych siedem pokazuje prawdę, natomiast później pojawiają się już bzdury. Każdy kalkulator tak działa, tylko dba się o to, by ukryć cyfry nieprawdziwe, ograniczają liczbę wyświetlanych cyfr. W naszym przypadku nie można ich pokazywać więcej niż 7, a czasem nawet 6.

No dobrze, ale po co to wszystko? Nie lepiej zadeklarować od razu float i mieć z tym spokój? Owszem, można tak, ale praca na tym typie zmiennych jest wolna i zasobożerna. Zasadą generalną jest pomyśleć i ustalić jakich wartości będziemy potrzebować i ograniczyć typ zmiennych do tychże. Wyjątkiem, które lansuje organizacja zajmująca się standardem Arduino, jest przyjmowanie domyślnego typu zmiennych int. Ja jednak wolę byte, acz kompilator jest mądry i gdy wartości nie przekraczają 255, zużycie zasobów jest takie samo.

Dla porządku wspomnę o kolejnych typach zmiennych. Char w zasadzie jest tożsamy z byte, ale dotyczy kodów znaków według standardu ASCII i tam się tylko przydaje. Word to to samo co int bez znaku, a short – ze znakiem. Dublujących się bytów jest więcej: mamy int z cyferką oznaczającą liczbę bitów, a także z literą u – w przypadku liczb ujemnych. To wszystko można wiedzieć, ale nie trzeba.

Ważny za to jest ostatni typ: bool Jest on najuboższy, bo przyjąć może tylko dwie wartości: zero albo jeden. Z tym, że dla odmiany można użyć także określeń LOW i HIGH – dużymi literami albo false i true – małymi. Którego gdzie używać? Z punktu działania programu wszystko jedno, owe określenia stworzono dla nas tylko, by używać takiego, które najbardziej pasuje kontekstem. LOW i HIGH będzie kojarzone z poziomami elektrycznymi, false i true – z logiką, a zera i jedynki z arytmetyką.

Skoro więc znamy już problematykę liczb, obejrzyjmy sobie na szybko matematykę. Dodawanie + odejmowanie - mnożenie * i dzielenie / jest oczywiste, z zastrzeżeniem na dokładność arduinowego kalkulatora no i oczywiście prawidła związane z typem zmiennych.

Wyciąganie wartości bezwzględnej abs(x) nie wymaga komentarza.

W zanadrzu mamy jeszcze: obliczanie kwadratu liczby sq(x) w zasadzie zbędne, bo łatwe do zastąpienia mnożeniem liczby przez siebie.

Rozwinięciem jest potęgowanie z dowolnym wykładnikiem, także ułamkowym pow(x,y) co jak wiemy ze szkoły, jest inną postacią pierwiastkowania.

Pierwiastkowanie sqrt(x) jest o wiele bardziej przydatne i dokładniejsze niż pozostałe działania zmiennoprzecinkowe, acz jak wszystkie kolejne – będzie już potrzebować czasu. Wszak wykorzystuje ośmiobitowy mózg. Niestety by dostać się do innego stopnia niż drugi, musimy użyć potęgowania z wykładnikiem ułamkowym.

Trygonometrię reprezentuje święta trójca: sinus sin(x) cosinus cos(x) i tangens tan(x) Należy pamiętać, że poruszamy się w radianach, bez możliwości pracy w stopniach, więc jeśli będzie potrzeba, trzeba będzie jeszcze dokonać stosownych przeliczeń. Na koniec przedstawię jeszcze nieco mniej typowe funkcje.

Constrain(x,min,max) zwraca wartość argumentu, jeśli należy do przedziału albo któryś z jego krańców, zależnie od tego, który przekroczył.

Min(x,y) oraz max(x,y) zwracają większą bądź mniejszą liczbę z pary.

Map(x,min1,max1,min2,max2) – często przeze mnie używana – przelicza proporcjonalnie wartość z jednego zakresu na drugi, oszczędzając sporej ilości rachunków. To nie wszystko, ale na dzisiaj wystarczy.

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

Przeczytaj również

Nasi partnerzy

TMETech Master EventTME EducationPoweredby
Copyright © 2025 arduino.pl