Do programowania Arduino stosowany jest język C. W poniższym rozdziale przedstawimy podstawy tego języka. Wiadomości, które nabędziesz podczas lektury tego rozdziału, będą przydatne podczas pisania każdego szkicu Arduino. Zrozumienie tych podstawowych wiadomości pozwoli Ci na wykorzystywanie wszystkich możliwości Arduino. Programowanie Wiele osób mówi w więcej niż jednym języku. Im więcej języków się zna, tym łatwiej przychodzi nauka kolejnych języków. Dzieje się tak, ponieważ poliglota zauważa reguły występujące w gramatyce i leksyce poszczególnych języków. Taka sama prawidłowość występuje w przypadku nauki języków programowania. Nauka języka C będzie przebiegać o wiele szybciej, jeżeli znasz już jakiś inny język programowania. Pierwsza dobra wiadomość to fakt, że zakres wyrażeń stosowanych w języku programowania jest o wiele mniejszy od zakresu słownictwa stosowanego w języku mówionym. Ponieważ język programowania jest językiem pisanym, a nie mówionym, możesz zawsze posłużyć się pomocą słownika lub podręcznika. Składnia języka programowania jest ściśle uregulowana. Gdy już opanujesz po dstawowe pojęcia, nauka kolejnych zagadnień związanych z danym językiem programowania przebiega bardzo sprawnie. Program (w przypadku Arduino zwany szkicem) można interpretować jako listę poleceń wykonywanych w kolejności, w jakiej zostały zapisane. Załóżmy, że napisałeś poniższy kod programu: digita1Wri te(l3, HIGH); delay (SOO); digita1Wri te(l3, LOW) ; Każda z tych trzech linii kodu służy do wykonania jakiejś czynności. Pierwsza linia kodu ustawia wysoki (z ang. high) poziom napięcia na złączu wyjściowym o numerze 13. Jest to złącze, z którym połączona jest dioda LED znajdująca się na płytce Arduino. A więc dioda ta zostanie zapalona. Druga linia kodu informuje o tym, że Arduino zaczeka 500 milisekund (pół sekundy) i wykona polecenie zawarte w trzeciej linii kodu, czyli wyłączy diodę. Zaprezentowane trzy linijki kodu sprawią, że dioda zostanie jednokrotnie zapalona, a następnie zgaszona. Na po czątku może Cię przerażać zarówno zastosowana interpunkcja, jak również i wyrazy, które nie są rozdzielane spacjami. Wielu początkujących programistów wie, co chce zrobić, ale nie wie, jak ma to zapisać. Nie ma tu niczego strasznego. Wszystko zostanie wyjaśnione. Na początek zajmijmy się interpunkcją i sposobem tworzenia wyrażeń. Obie te rzeczy są elementami składni języka programowania. Większość języków wymaga dokładnego stosowania się do reguł składniowych. Jedna z zasad tworzenia nazw mówi, że nazwy muszą być jednowyrazowe. A więc nie mogą zawierać znaku rozdzielającego - spacji. Wyrażenie digital Write jest nazwą. Jest to nazwa wbudowanej funkcji, która dokonuje konfiguracji złączy wyjściowych na płytce Arduino. Więcej informacji na temat funkcji zostanie przedstawionych w kolejnych rozdziałach. Przy zapisie nazw należy uważać nie tylko na znaki rozdzielające. W zapisie nazw rozróżniane są wielkie i małe litery. Funkcja digital Write musi posiadać dane dotyczące tego, obsługą którego złącza ma się zająć. Funkcja powinna również posiadać informację dotyczącą napięcia, jakie ma się pojawić na złączu - wysokie (z ang. high) czy niskie (z ang. low). Te dwie informację noszą nazwę argumentów, które są przekazywane do funkcji podczas jej wywołania. Parametry funkcji muszą być umieszczone w nawiasach i oddzielone przecinkami. Istnieje konwencja zapisu mówiąca o tym, że nawias należy otwierać bezpośrednio za ostatnią literą nazwy funkcji, a pomiędzy przecinkiem i kolejnym parametrem powinna być umieszczona spacja. Jeżeli jednakże czujesz taką potrzebę, możesz zastosować więcej spacji wewnątrz nawiasów.
Jeżeli funkcja posiada tylko jeden argument, nie ma potrzeby umieszczania przecinku w naw1as1e. Zauważ, że każda linia kodu jest zakończona średnikiem. Bardziej logiczne byłoby zakonczenie każdej linii kodu kropką. Średnik sygnalizuje koniec danego polecenia, tak jak kropka sygnalizuje koniec zdania. W kolejnym podroz dziale dowiesz się, co dzieje się, gdy w zintegrowanym środowisku programistycznym Arduino klikniesz ikonę Załaduj . Pozwoli Ci to na pracę z przy kładowymi szkicami. Czym jest język programowania? To dziwne, że w książce dotyczącej programowania dopiero w trzecim rozdziale piszemy o tym, czym jest język programowania. Potrafisz rozpoznać szkic Arduino, a także masz już niewielkie pojęcie o tym, jakie operacje są w nim zdefiniowane. Musisz jednak mieć większą świadomość tego, jak kod zapisany w języku programowania jest tłumaczony z zapisanych wyrażeń na realnie wykonywaną czynność, taką jak włączenie i wyłączenie diody LED.
Blink po raz kolejny
W Arduino stosujemy funkcje setup oraz loop w celu oddzielenia od siebie rzeczy, które muszą być wykonane raz w wyniku uruchomienia programu, od rzeczy, które będą wykonywane w sposób ciągły. Funkcja setup jest uruchamiana jednokrotnie po uruchomieniu szkicu. Dodajmy do naszej funkcji kod, który sprawi, że dioda wbudowana w Arduino zostanie zapalona. Zmodyfikuj napisany wcześniej kod w sposób pokazany poniżej, a następnie załaduj gotowy szkic na płytkę.
Kod: Zaznacz cały
void setup() {
pinMode(13, OUTPUT) ;
digitalWrite(13, HIGH);
}
void loop() {
}
( 5 V).
Po uruchomieniu tego szkicu zobaczysz, że dioda zostaje zapalona i nie gaśnie. Efekt ten nie jest zachwycający, a więc spróbujmy sprawić, naprzemiennie włączając i wyłączając diodę, że będzie ona migać. Instrukcje włączającą i wyłączającą diodę umieścimy raczej w funkcji l oop niż w funkcji setup. Pozostawmy wywołanie funkcji pi nMode wewnątrz funkcji setup, ponieważ funkcja pi nMode musi zostać wywołana tylko jednokrotnie. Szkic nadal działałby, gdybyś przeniósł wywołanie funkcji pi nMode do funkcji loop, ale nie ma takiej potrzeby. Dobrą praktyką programistyczną jest robienie tylko raz rzeczy, które muszą być wykonane jednokrotnie. Zmodyfikuj swój szkic, aby wyglądał w następujący sposób:
Kod: Zaznacz cały
void setup() {
pinMode(13, OUTPUT);
}
void loop() {
digitalWrite(13, HIGH);
delay (500);
digitalWrite(l3, LOW) ;
}
1. Uruchom funkcję setup i zainicjuj złącze o numerze 13 tak, aby działało jako wyjście.
2. Uruchom funkcję loop i włącz wysoki sygnał na złączu o numerze 13 (włącz diodę LED).
3. Odczekaj pół sekundy.
4. Podaj niski sygnał na złącze o numerze 13 (wyłącz diodę LED).
5. Uruchom ponownie funkcję l oop -przejdź z powrotem do punktu drugiego i
ponownie włącz wysoki sygnał na złączu o numerze 13 (włącz diodę LED).
Problem znajduje się pomiędzy punktem czwartym i piątym. Dioda jest wyłączana, ale jest natychmiast włączana ponownie. Dzieje się to tak szybko, że wydaje się, że dioda LED jest cały czas włączona. Mikrokontroler znajdujący się na płytce Arduino jest w stanie przetwarzać 16 milionów instrukcji na sekundę. Nie jest to wykonywanie 16 milionów poleceń napisanych w języku C, lecz pomimo tego jest to bardzo duża wartość. Dioda będzie wyłączona tylko przez niewielki ułamek sekundy. Aby rozwiązać ten problem, należy dodać kolejną funkcję opóźniającą del ay po wyłączeniu diody LED. Twój kod powinien wyglądać w następujący sposób:
Kod: Zaznacz cały
void setup ( ) {
pinMode ( 13 , OUTPUT ) ;
}
void loop ( ) {
digitalWrite ( 13 , HIGH ) ;
delay (500) ;
digitalWrite ( 13 , LOW) ;
delay (500) ;
}
W przytoczonym wcześniej szkicu korzystaliśmy ze złącza o numerze 13. Odwoływaliśmy
się do niego trzykrotnie. Jeżeli zdecydowałbyś się na korzystanie z innego złącza, musiałbyś
zmodyfikować kod programu w trzech miejscach. Podobnie jeżeli chciałbyś zmienić czę
stotliwość błysków, musiałbyś zmienić wartość argumentu funkcji del ay w więcej niż jed
nym miejscu.
Zmienne mogą być traktowane jako wartości, którym nadano nazwy. Mają one o wiele
szersze zastosowanie, jednakże na razie skupimy się jedynie na tym.
Definiuj ąc zmienną w języku C, musisz określić jej typ. Chcemy, aby nasze zmienne
były liczbami całkowitymi - w języku C zmienne takie noszą nazwę i nt (od angielskiego
słowa integer). Poniżej przedstawiono deklarację zmiennej o nazwie ledPin. Przypisano jej
wartość 13:
int ledPin 13 ;
Wyrażenie ledPin jest nazwą zmiennej. D o nazw zmiennych stosuje się te same reguły
co do nazw funkcji. A więc nazwy nie mogą zawierać żadnych spacji. Istnieje konwencja
dotycząca nazewnictwa zmiennych mówiąca o tym, że nazwy zmiennych zaczyna się z małej
litery, a każde kolejne słowo rozpoczyna się wielką literą. Programiści określają ten sposób
notacji terminem „camelCase".
Zmodyfikujmy nasz szkic w następujący sposób:
Kod: Zaznacz cały
int ledPin = 13;
intdelayPeriod = 500 ;
void setup ( )
{
pinMode ( ledPin , OUTPUT ) ;
}
void loop ( )
{
}
Wszędzie tam, gdzie w poprzednim szkicu stosowaliśmy wartość 13, teraz stosujemy
zmienną ledPin, a wszędzie tam, gdzie stosowaliśmy wartość 500, teraz stosujemy zmienną
delayPeriod.
Jeżeli chcesz, aby dioda błyskała z większą częstotliwością, wystarczy zmienić w jednym
miejscu wartość zmiennej delayPeriod. Spróbuj zmienić wartość tej zmiennej na 100 i uru
chomić szkic na płytce Arduino.
Są inne rzeczy, do których możemy sprytnie zastosować funkcje. Zmodyfikujmy szkic
tak, aby na początku miganie przebiegało z bardzo dużą częstotliwością, a następnie częstotli
wość błysków malała - tak jakby Arduino „męczyło się". Aby wykonać szkic dający taki
efekt, musimy po każdym błysku dodawać jakąś wartość do zmiennej del ayPeri od.
Zmodyfikuj szkic, dodając linię kodu na końcu funkcji l oop tak, jak to zrobiono w po
niższym kodzie. Uruchom szkic na płytce Arduino. W ciśnij przycisk Reset i obserwuj efekt
działania szkicu.
Kod: Zaznacz cały
int ledPin = 1 3 ;
int delayPeriod 100 ;
void setup ( )
{
pinMode ( ledPin , OUTPUT ) ;
}
void loop ( )
{
digital Write ( led Pin , H I G H ) ;
delay (delayPeriod ) ;
digital Write ( led Pin , LOW) ;
delay (delayPeriod ) ;
delayPeriod = delayPeriod + 100;
}
dym wywołaniu funkcji l oop Arduino mignie diodą LED oraz równocześnie doda 100 do
zmiennej del ayPeri od. Niedługo wrócimy do zagadnień związanych z operacjami aryt
metycznymi, ale najpierw poznajmy inne funkcje Arduino.
Eksperymentowanie w języku C
Musisz w jakiś sposób testować pisany przez siebie kod. Jednym ze sposobów na to jest umieszczenie kodu, który chcesz sprawdzić, w funkcji setup, sprawdzenie kodu przy użyciu Arduino, a następnie wyświetlenie wyniku przez Arduino za pomocą tak zwanego monitora portu szeregowego, co pokazano na rysunku Pisanie kodu języka C w fu nkcji setup Monitor portu szeregowego
Monitor portu szeregowego jest częścią środowiska programistycznego Arduino. Dostęp do niego możesz uzyskać, klikając ikonę znajdującą się po prawej stronie paska narzędzi. Monitor działa jako kanał komunikacyjny pomiędzy Twoim komputerem i Arduino.
Możesz wpisać komunikat w górnej części okna monitora portu szeregowego, a kiedy klikniesz ikonę Send lub wciśniesz klawisz Enter, wpisany kod zostanie wysłany do Arduino. Jeżeli Arduino ma coś do zakomunikowania, to zostanie to wyświetlone w oknie monitora portu szeregowego. Dane są przesyłane w obu kierunkach za pośrednictwem interfejsu USB. Jak zapewne się spodziewałeś, istnieje wbudowana funkcja pozwalająca na wysyłanie wiadomości do monitora portu szeregowego. Funkcja ta nosi nazwę Seri al . print l n. Jest to funkcja jednoargumentowa. Argumentem tym jest treść, którą chcemy przesłać. Treść ta jest zwykle pewną zmienną. Będziesz korzystać z tego mechanizmu do sprawdzania rzeczy związanych ze zmiennymi oraz arytmetyką w języku C. Tak naprawdę jest to jedyny sposób na wizualizowanie rezultatów Twoich eksperymentów w języku C.
PODST A WY JĘZYKA C 45 Możesz wpisać komunikat w górnej części okna monitora portu szeregowego, a kiedy klikniesz ikonę Send lub wciśniesz klawisz Enter, wpisany kod zostanie wysłany do Arduino. Jeżeli Arduino ma coś do zakomunikowania, to zostanie to wyświetlone w oknie monitora portu szeregowego. Dane są przesyłane w obu kierunkach za pośrednictwem interfejsu USB. Jak zapewne się spodziewałeś, istnieje wbudowana funkcja pozwalająca na wysyłanie wiadomości do monitora portu szeregowego. Funkcja ta nosi nazwę Seri al . print l n. Jest to funkcja jednoargumentowa. Argumentem tym jest treść, którą chcemy przesłać. Treść ta jest zwykle pewną zmienną. Będziesz korzystać z tego mechanizmu do sprawdzania rzeczy związanych ze zmiennymi oraz arytmetyką w języku C. Tak naprawdę jest to jedyny sposób na wizualizowanie rezultatów Twoich eksperymentów w języku C. Zmienne numeryczne i arytmetyka Ostatnią rzeczą, jaką zrobiłeś, modyfikując szkic sterujący mi gającą diodą, było stopniowe zwiększanie czasu trwania błysku przy użyciu następującego kodu:
delayPeriod = delayPeriod + 100;
Przyjrzyjmy się temu kodowi. Składa się on z nazwy zmiennej, znaku równości, a następnie wyrażenia delayPeri od + 100. Znak równości wykonuje działanie zwane przypisaniem, czyli przypisuje nową wartość do zmiennej. Nowa wartość zmiennej jest określana przez to, co znajduje się pomiędzy znakiem równości a średnikiem. W omawianym przypadku nowa wartość zmiennej delayPeriod jest poprzednią wartością zmiennej delayPeriod zwiększoną o 100. Sprawdźmy działanie omówionego wcześniej mechanizmu poprzez uruchomienie poniższego szkicu i otwarcie monitora portu szeregowego.
Kod: Zaznacz cały
void setup() {
Serial.begin(9600);
int a = 2;
int b = 2;
int c = a + b;
Serial.println (c);
}
voidloop() {
}
Kod: Zaznacz cały
void setup ( )
{
Serial.beg i n (9600) ;
intdegC = 20 ;
intdeg F ;
degF = degC * 9 / 5 + 32 ;
Serial.println(degF) ;
}
int degC = 20 ;
Pisząc tę linię kodu, przeprowadziliśmy tak naprawdę dwie operacje. Deklarujemy zmienną typu int o nazwie degC, a jednocześnie określamy wartość początkową tej zmiennej -20. Możesz również wykonać te dwie operacje, korzystając z dwóch oddzielnych linii kodu:
int degC; degC = 20;
Zmienną musisz deklarować tylko raz. Deklarując zmienną, informujesz kompilator o jej typie -w tym przypadku zmienna była typu int. Zadeklarowanej zmiennej możesz wielokrotnie przypisywać nowe wartości:
int degC;
degC = 20;
degC = 30;
W przykładzie dotyczącym zamiany jednostki temperatur definiujesz zmienną degC i nadajesz jej początkową wartość -20. Natomiast definiuj ąc zmienną degF, nie nadajesz jej żadnej wartości początkowej. W kolejnej linii kodu zmiennej tej przypisywana jest wartość zgodnie z przeprowadzonymi obliczeniami. Dopiero po ich wykonaniu wynik jest przesyłany do monitora portu szeregowego.
Gdy przyjrzysz się obliczeniom, zauważysz, że znak gwiazdki(*) jest stosowany do operacji mnożenia, a znak kreski ukośnej (/) jest stosowany do operacji dzielenia. Operacje matematyczne określane przez operatory (+, -, *i/) są wykonywane w ustalonej kolejności. N aj pierw wykonywane są operacje mnożenia, następnie dzielenia, a dopiero później dodawania i odejmowania. Jest to kolejność, w jakiej z reguły przeprowadza się operacje arytmetyczne. Czasem, w przypadku wyrażeń arytmetycznych, warto zastosować nawiasy. W tym celu możesz zastosować następujący zapis:
degF = ((degC * 9) / 5) + 32;
Wyrażenia tego typu mogą być dowolnie długie i dowolnie złożone. Ponadto poza podstawowymi operacjami matematycznymi możliwe jest stosowanie olbrzymiej liczby dostępnych funkcji matematycznych. Funkcje te omówimy jednak później.
