Serwis Edukacyjny
w I-LO w Tarnowie
obrazek

Materiały dla uczniów liceum

  Wyjście       Spis treści       Wstecz       Dalej  

obrazek

Autor artykułu: mgr Jerzy Wałaszek
Konsultacje: Wojciech Grodowski, mgr inż. Janusz Wałaszek

©2024 mgr Jerzy Wałaszek
I LO w Tarnowie

obrazek

Warsztat

Kurs Digispark

Pierwsze programy

SPIS TREŚCI
Podrozdziały

Schemat Digisparka

obrazek
Schemat elektryczny Digisparka

Digispark jest bardzo prostą konstrukcją. Na płytce znajdziesz dwa układy scalone:

Stabilizator 78L05 pozwala zasilać Digisparka zewnętrznym napięciem od 6V do 16V. Napięcie przykłada się do końcówek GND (masa) i VIN (+ zasilania). Stabilizator wytrzymuje maksymalne napięcie 35 V (wg danych producenta), jednak wtedy bardzo się grzeje i należy go wyposażyć w radiator. Dlatego odradzam stosowanie napięć wyższych niż 12...16V.

obrazek

Gdy zasilamy płytkę napięciem z końcówki VIN, to na końcówce 5V pojawia się napięcie ze stabilizatora o wartości 5V. Jest to to samo napięcie, które zasila mikrokontroler (patrz: schemat).

Płytka Digisparka może być zasilana bezpośrednio z portu USB, wtedy na wyjściu 5V pojawi się napięcie około 4,4V (napięcie z USB pomniejszone o spadek napięcia na diodzie D3, patrz: schemat).

Zasilanie może również być podane na końcówki GND i 5V, jednakże wtedy nie wolno przekraczać napięcia 6V, ponieważ wyższe napięcie może uszkodzić mikrokontroler. Dioda D3 zapobiega przedostawaniu się napięcia zasilania do portu USB.

Na końcówki P0...P5 wyprowadzone są linie portu B mikrokontrolera. Końcówka P5 pełni w chińskich klonach funkcję RESET i nie można z niej korzystać w aplikacjach. W poprzednim rozdziale opisałem procedurę przeprogramowania tej końcówki na końcówkę we/wy, zatem jeśli jej koniecznie potrzebujesz, zaglądnij tam. Nie polecam jednak tej operacji zupełnie początkującym, bo w razie niepowodzenia możesz stracić możliwość programowania Digisparka i potrzebny będzie specjalny programator wysokonapięciowy (w sumie powinieneś sobie taki programator zorganizować, bo jest czasem bardzo przydatny). Jako końcówka we/wy P5 jest tzw. słabym portem we/wy (ang. weak I/O port). Oznacza to, iż ma ona niższą wydajność prądową – kila mA, zamiast 40mA jak w pozostałych końcówkach.

Końcówki Digisparka mogą pełnić różne funkcje.

obrazek
Sygnały wejściowe/wyjściowe Digisparka

Pamiętaj jednak, że końcówki P3 i P4 są wykorzystywane do transmisji poprzez port USB. Nawet, jeśli nie korzystasz z portu USB, to do tych końcówek podpięte są oporniki i diody Zenera, które wpływają na sygnały wejściowe na tych portach. Może się to objawiać różnymi zakłóceniami w pracy tych portów, szczególnie gdy Digispark jest podpięty do USB. Również niektóre płytki ćwiczeniowe zakłócają transmisję USB i Digisparka nie daje się zaprogramować bez odłączenia płytki aplikacyjnej. To cena za prostotę konstrukcji. Jeśli ci to nie odpowiada, przesiądź się na inny produkt Arduino.


Na początek:  podrozdziału   strony 

Budowa programu

Masz moduł Digispark, zainstalowałeś środowisko Arduino i skonfigurowałeś je do pracy z modułem Digispark (jeśli nie, to wróć tutaj i wykonaj wszystko, jak należy).

Nadszedł zatem czas na napisanie pierwszych programów. Środowisko Arduino IDE posługuje się odmianą języka C podobną do C++. Jeśli nie umiesz programować w tym języku, to trzeba ten brak naprawić. Skorzystaj ze skróconego kursu, który umieściłem w tym artykule. Na potrzeby programowania mikrokontrolerów jest on więcej niż wystarczający.

Uruchom Arduino IDE.

Z menu wybierz opcję PlikNowy (klawisze Ctrl+N).

Arduino stworzy nowy projekt, który tutaj nazywa się szkicem (ang. sketch).

obrazek

Sprawdź, czy w opcji NarzędziaPłytka jest wybrany moduł Digispark (Default - 16,5mhz):

obrazek

Jeśli nie, to wybierz taki moduł z listy.

Program w typowym języku C składa się z funkcji, z których jedną jest funkcja startowa main(). W Arduino funkcja ta jest ukryta przed programistą. Zamiast niej są dwie funkcje:

void setup() {
 // put your setup code here, to run once:

}

void loop() {
 // put your main code here, to run repeatedly:

}

Obie posiadają typ void, co oznacza, że nie zwracają żadnych wartości, zatem nie musisz kończyć ich poleceniem return.

Kod funkcji setup() jest uruchamiany jednokrotnie, gdy mikrokontroler rozpoczyna pracę. Tutaj umieszcza się zwykle polecenia, które konfigurują elementy mikrokontrolera, tak aby program mógł z nich korzystać.

Kod funkcji loop() jest uruchamiany cyklicznie w kółko. Tutaj umieszcza się fragment programu, który steruje pracą mikrokontrolera w trakcie jego działania.

Graficznie wygląda to tak:

obrazek

Płytka Digispark posiada dwie diody LED.

obrazek   obrazek

Jedna z nich sygnalizuje podłączenie zasilania do płytki (znajduje się przy złączu 5V/GND/VIN), a druga podłączona jest do portu P1 (w starszych modelach do P0).

Napiszemy pierwszy program, który szybko mruga tą drugą diodą. Najpierw musisz zidentyfikować port, do którego ta dioda jest podłączona. Napiszemy program, który zapala diodę LED podłączoną do portu P0:

Przygotuj płytkę Digisparka, podłącz do niej kabel USB, ale kabla nie wpinaj do portu USB w swoim komputerze.

W edytorze Arduino wprowadź program:

void setup() {
 // put your setup code here, to run once:
   pinMode(0,OUTPUT);
}

void loop() {
 // put your main code here, to run repeatedly:
  digitalWrite(0,HIGH);
}

Gdy wpiszesz program, kliknij u góry okna edytora ikonę weryfikacji.

obrazek

Ponieważ jest to nowy program, wyświetlone zostanie okno zapisu katalogu szkicu na twój dysk twardy. Nazwy szkiców składają się ze słowa sketch (szkic) oraz daty. W tym momencie możesz tę nazwę zmienić lub zachować. Kliknij na koniec w przycisk Zapisz.

Po zapisie rozpocznie się kompilacja twojego programu, której postęp możesz obserwować pod oknem edytora:

obrazek

Jeśli kompilacja się powiedzie, to dostaniesz komunikat:

obrazek

Jeśli w programie będzie jakiś błąd, to Arduino IDE poinformuje cię o miejscu jego położenia:

obrazek

Tutaj specjalnie usunąłem przecinek za wywołaniem funkcji PinMode(). Błąd musisz usunąć, inaczej program nie zostanie skompilowany.

W środowisku Arduino programujesz wykorzystując gotowe i wygodne funkcje. W funkcji setup() należy odpowiednio przygotować mikrokontroler do pracy. W naszym przypadku chcemy sterować diodą LED poprzez port P0. Musimy zatem ustawić ten port w tryb wyjścia, tzn. dać mikrokontrolerowi możliwość ustawienia na linii P0 stanu 0 lub 1. W tym celu wywołujemy funkcję biblioteczną pinMode(). Pierwszym parametrem jest numer portu od 0 do 5 (P5 nie będziemy używać). Drugi parametr określa tryb (ang. mode) pracy tego portu. OUTPUT oznacza wyjście,  czyli mikrokontroler będzie mógł sterować stanem logicznym na linii P0. Na tym funkcja setup() się kończy: mikrokontroler został skonfigurowany.

W funkcji loop() umieszczono wywołanie funkcji bibliotecznej digitalWrite(). Funkcja posiada dwa parametry: numer portu od 0 do 5 (5 nie będziemy używać) oraz stan logiczny (0 = LOW, 1 = HIGH), który na tym porcie zostanie ustawiony. Dany port musi zostać ustawiony w tryb wyjścia, inaczej funkcja nie zadziała.

digitalWrite(0,HIGH) (lub digitalWrite(0,1)) ustawia stan logiczny 1 na linii P0. Jeśli jest tam podłączona dioda LED, to się zaświeci.

Jeśli weryfikacja zakończyła się sukcesem, to kliknij ikonę przesłania programu do mikrokontrolera na płytce Digispark:

obrazek

Program zostanie ponownie skompilowany, po czym pojawi się komunikat:

obrazek

Komunikacja z płytką Digispark jest dosyć specyficzna. Program ładujący (loader) w mikrokontrolerze na płytce przez 5 sekund tuż po włączeniu zasilania sprawdza, czy poprzez USB nie nadchodzi nowy program. Jeśli tak,, to program zostanie odczytany i zapisany w pamięci Flash mikrokontrolera, po czym loader go uruchomi. Jeśli w ciągu tych 5 sekund po włączeniu nie zostanie nawiązana komunikacja i nie zostanie odczytany nowy program, to loader uruchomi program, który znajduje się już w pamięci Flash. Wynika z tego, że nowy program możesz wgrać do Digisparka tylko tuż po podłączeniu go do portu USB. Operację tę wykonujesz za każdym razem, gdy chcesz zapisać w mikrokontrolerze nowy program. Po kompilacji programu ARDUINO IDE daje 60 sekund na podłączenie płytki Digispark do USB. Jeśli ten czas minie, to procedurę przesłania programu musisz powtórzyć od początku.

Włóż zatem kabel USB podłączony do Digisparka do portu USB w twoim komputerze. ARDUINO IDE wykryje podłączenie Digisparka i prześle mu nowy program. Jeśli operacja się powiedzie, to pojawi się komunikat:

 obrazek

Podsumujmy. Programowanie Digisparka wygląda następująco:

Raz przesłany program będzie się uruchamiał po 5 sekundach za każdym razem, gdy podłączysz zasilanie do płytki Digispark (np. podłączając tę płytkę do portu USB komputera PC).

Jeśli po przesłaniu programu dioda LED (ta obok mikrokontrolera) nie zaświeci się, to masz nowszy model, w którym LED jest podłączona do P1. Zmień program:
void setup() {
 // put your setup code here, to run once:
   pinMode(1,OUTPUT);
}

void loop() {
 // put your main code here, to run repeatedly:
  digitalWrite(1,HIGH);
}

Prześlij go ponownie do Digisparka. Dioda LED powinna się teraz zaświecić.

obrazek

Jeśli dioda LED na płytce Digispark wciąż jest zgaszona, to masz coś uszkodzone.

Na potrzeby dalszej części rozdziału zapamiętaj sobie, na którym porcie masz diodę LED.

Kolejny program szybko mruga diodą LED.
#define LED 1

void setup() {
 // put your setup code here, to run once:
   pinMode(LED,OUTPUT);
}

void loop() {
 // put your main code here, to run repeatedly:
  digitalWrite(LED,HIGH);
  delay(100);
  digitalWrite(LED,LOW);
  delay(100);
}

Omówmy elementy tego programu:
#define LED 1   definiuje symbol LED jako 1. Jeśli na twojej płytce Digispark dioda LED jest podłączona do P0, to zmień 1 na 0. Reszta programu bez zmian.
pinMode(LED,OUTPUT);   ustawiamy port o numerze LED jako wyjście.
digitalWrite(LED,HIGH);   do portu o numerze LED zapisujemy stan logiczny 1.
delay(100);   wstrzymujemy wykonanie na 100 milisekund (1/10 sekundy).
digitalWrite(LED,LOW);   do portu o numerze LED zapisujemy stan logiczny 0.

Ponieważ funkcja loop() wykonuje się cyklicznie, to zawarty w niej kod będzie powodował zmiany stanu logicznego portu o numerze LED pomiędzy 0 a 1 co 100 milisekund. W efekcie podłączona do tego portu dioda LED zacznie cyklicznie mrugać.

Poeksperymentuj sobie z opóźnieniami w tym programie.

Podsumowanie

Program Arduino zbudowany jest z dwóch funkcji:


Na początek:  podrozdziału   strony 

Migacze

Z jedną diodą LED na pokładzie Digisparka wiele nie poszalejemy, jednak możemy poćwiczyć programowanie, aby przygotować się do bardziej ambitnych projektów.

Mruganie diodą LED podłączoną do portu mikrokontrolera jest odpowiednikiem programu Hello World, czyli pierwszego programu, który każdy początkujący programista powinien uruchomić.

Migacz 1

Pierwszy program wykorzystuje funkcję LEDflash(), która włącza diodę LED na 0,05 sekundy, po czym ją wyłącza. W pętli głównej wywołujemy tę funkcję co 0,95 sekundy. W efekcie program generuje błyski co 1 sekundę:

#define LED 1

void LEDflash()
// Zapala LED na 0,05 sekundy
//--------------------------
{
  digitalWrite(LED,1);  // zapal LED
  delay(50);            // czekaj 0,05 sekundy
  digitalWrite(LED,0);  // zgaś LED
}

void setup() {
 // put your setup code here, to run once:
   pinMode(LED,OUTPUT); // port LED jako wyjście
   digitalWrite(LED,0); // gasimy LED
}

void loop() {
 // put your main code here, to run repeatedly:
  LEDflash();           // błyśnij LED
  delay(950);           // czekaj 0,95 sekundy
}

Migacz 2

Wykorzystujemy tu znów funkcję LEDflash() z poprzedniego programu. Tym razem jednak dioda LED wykonuje 3 szybkie mrugnięcia na początku każdej sekundy.

#define LED 1

void LEDflash()
// Zapala LED na 0,05 sekundy
//--------------------------
{
  digitalWrite(LED,1);  // zapal LED
  delay(50);            // czekaj 0,05 sekundy
  digitalWrite(LED,0);  // zgaś LED
}

void setup() {
 // put your setup code here, to run once:
   pinMode(LED,OUTPUT); // port LED jako wyjście
   digitalWrite(LED,0); // gasimy LED
}

void loop() {
 // put your main code here, to run repeatedly:
  char i;
  for(i = 0; i < 3; i++)
  {
    LEDflash();         // mrugamy LED
    delay(100);         // czekamy 0,1 sekundy
  }
  delay(550);           // uzupełniamy czas do 1 sekundy
}

Migacz 3

Kolejny program generuje sygnał SOS (ang. Save Our Souls, czyli Ratujcie Nasze Dusze).

obrazek

Sygnał ten nadawany jest alfabetem Morse'a, który został opracowany specjalnie na potrzeby telegrafii. Każda litera w alfabecie Morse'a składa się z kombinacji trzech sygnałów dźwiękowych/świetlnych (krótkiego – kropka, długiego – kreska, przerwy).

Na przykład:

literka A jest kodowana jako • — (kropka, przerwa, kreska).

literka B jest kodowana jako — • • •

itd.:

obrazek

Za podstawę czasu przyjmuje się czas trwania kropki. Przerwa powinna mieć ten sam czas. Kreska powinna trwać tyle, ile 3 kropki. Przerwa pomiędzy kolejnymi literami powinna trwać tyle, ile kreska. Przerwa pomiędzy grupami liter (słowami) powinna trwać przez czas 3 kresek.

Sygnał SOS składa się z 3 liter:

S • • •
O — — —
S • • •

Zatem: SOS = • • •   — — —   • • •

Mamy wszystko, przystępujemy do pisania programu. Wykorzystamy w nim kilka funkcji.

#define LED 1
#define DOT 100
#define DASH 300

void dot()
// Zapala LED na 0,1 sekundy
//---------------------------
{
  digitalWrite(LED,1);  // zapal LED
  delay(DOT);           // czekaj 0,1 sekundy
  digitalWrite(LED,0);  // zgaś LED
}

void dash()
// Zapala LED na 0,3 sekundy
//---------------------------
{
  digitalWrite(LED,1);  // zapal LED
  delay(DASH);          // czekaj 0,3 sekundy
  digitalWrite(LED,0);  // zgaś LED
}

void s()
// Litera S
//---------
{
  for(char i = 0; i < 3; i++)
  {
    dot();
    delay(DOT);
  }
  delay(DOT+DOT);
}

void o()
// Litera O
//---------
{
  for(char i = 0; i < 3; i++)
  {
    dash();
    delay(DOT);
  }
  delay(DOT+DOT);
}

void setup() {
 // put your setup code here, to run once:
   pinMode(LED,OUTPUT); // port LED jako wyjście
   digitalWrite(LED,0); // gasimy LED
}

void loop() {
 // put your main code here, to run repeatedly:
  s();
  o();
  s();
  delay(DASH+DASH);
}

Migacz 4

Dotychczas jedynie włączaliśmy lub wyłączaliśmy diodę LED. Istnieje również możliwość płynnego sterowania jasnością jej świecenia. Uzyskuje się to wysyłając na port, do którego podłączona jest dioda, impulsy o różnym stopniu wypełnienia:

obrazek

Przez wypełnienie (ang. duty) rozumiemy stosunek czasu trwania impulsu ti do czasu trwania okresu T. Wypełnienie podaje się zwykle w procentach. Np. wypełnienie 0% oznacza, że na linii portu panuje cały czas stan 0 (dioda zgaszona), 50% przez połowę okresu stan wysoki, przez drugą połowę stan niski (dioda świeci z połową intensywności), 100% przez cały okres stan wysoki (dioda świeci z pełną intensywnością).

Okres powinien krótki, inaczej zobaczymy mruganie diody. Dla oka powinno to być około 50 Hz lub więcej.

Mikrokontroler ATtiny 85 posiada sprzętową opcję generowania takich przebiegów na wybranych portach. Jest to tzw. tryb PWM (ang. Pulse Width Modulation = modulacja szerokości impulsu). Tymi sprawami zajmiemy się w dalszej części kursu. Teraz zrealizujemy sterowanie diodą programowo: w pętli będziemy zapalać lub gasić diodę począwszy od przebiegu o odpowiednim numerze.

#define LED 1
#define LIMIT 22

char counter = 0;

void setup() {
 // put your setup code here, to run once:
   pinMode(LED,OUTPUT); // port LED jako wyjście
   digitalWrite(LED,0); // gasimy LED
}

void loop() {
  for(char i = 0; i < LIMIT; i++)
  {
    if(i > counter) digitalWrite(LED,HIGH);
    else            digitalWrite(LED,LOW);
    delay(1);
  }
  counter++;
  if(counter == LIMIT)
  {
     counter = 0;
     delay(500);
  }
}

Poruszaj szybko płytką Digispark tam i z powrotem, a zobaczysz impulsy sterujące diodą LED. Zmieniając wartość LIMIT, wpływasz na szybkość wygaszania diody LED. Zbyt duża wartość spowoduje jednak migotanie.

Na tej zasadzie opiera się regulacja podświetlenia wyświetlaczy LED (telefony, monitory, itp.). Diody podświetlające ekran są szybko włączane i wyłączane. Regulując wypełnienie impulsów załączających, wpływa się na jasność ekranu. Proste?

Migacz 5

Drobna modyfikacja poprzedniego programu daje nam pulsator:

#define LED 1
#define LIMIT 22

char counter = 0;
char dir = 1;

void setup() {
 // put your setup code here, to run once:
   pinMode(LED,OUTPUT); // port LED jako wyjście
   digitalWrite(LED,0); // gasimy LED
}

void loop() {
  for(char i = 0; i < LIMIT; i++)
  {
    if(i > counter) digitalWrite(LED,HIGH);
    else            digitalWrite(LED,LOW);
    delay(1);
  }
  counter += dir;
  if((counter == LIMIT) || (counter == 0))
  {
     dir = -dir;
     delay(250);
  }
}

Zasada działania tego programu opiera się na tym, iż zmienna counter najpierw zwiększa swą zawartość od 0 do LIMIT, a po osiągnięciu LIMIT zmniejsza zawartość do 0 i cały cykl się powtarza. Generowane impulsy stają się coraz krótsze, a później coraz dłuższe. W rezultacie otrzymujesz efekt pulsującej diody LED. Przeanalizuj ten program aż dokładnie zrozumiesz sposób jego pracy.


Na początek:  podrozdziału   strony 

Zespół Przedmiotowy
Chemii-Fizyki-Informatyki

w I Liceum Ogólnokształcącym
im. Kazimierza Brodzińskiego
w Tarnowie
ul. Piłsudskiego 4
©2024 mgr Jerzy Wałaszek

Materiały tylko do użytku dydaktycznego. Ich kopiowanie i powielanie jest dozwolone pod warunkiem podania źródła oraz niepobierania za to pieniędzy.
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
Serwis wykorzystuje pliki cookies. Jeśli nie chcesz ich otrzymywać, zablokuj je w swojej przeglądarce.

Informacje dodatkowe.