Modem radiowy nRF24L01 – programowanie

Teraz przyszła pora na zaprogramowanie urządzeń. Pierwszym programem niech będzie tradycyjne już “Hello World” [Witaj Świecie].

Sprawię, że jedno urządzenie z modemem będzie wysyłało napis do drugiego urządzenia. Drugie urządzenie zaś wyśle odebrany napis do komputera, żeby wyświetlić go w Monitorze Portu Szeregowego Arduino.

Do do programowania modemu nRF24L01 potrzebujesz biblioteki RF24. Znajdziesz ja na stronie projektu RF24 na Github.

Wystarczy kliknąć przycisk “Download ZIP” i pobrać plik biblioteki.

Bibliotekę możesz zainstalować w Arduino IDE poprzez menu Szkic->Importuj bibliotekę->Dodaj bibliotekę. Inny sposób to rozpakować plik zip do katalogu domowego Arduino/librares na Linuksie lub do DokumentyArduinolibrares w Windows.

Program Nadajnika wygląda tak:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8);

const byte rxAddr[6] = "00001";

void setup()
{
  radio.begin();
  radio.setRetries(15, 15);
  radio.openWritingPipe(rxAddr);
  
  radio.stopListening();
}

void loop()
{
  const char text[] = "Hello World";
  radio.write(&text, sizeof(text));
  
  delay(1000);
}

Na początku informuje program jakich będę używał bibliotek.

  • SPI.h – do obsługi interfejsu komunikacji z modemem
  • nRF24L01.h – do obsługi tego konkretnego sterownika modemu
  • RF24.h – biblioteka która ułatwia nam sterowanie modemem radiowym

W dalszej części tworzę obiekt o nazwie “radio”.

RF24 radio(7, 8);

Obiekt ten reprezentuje podłączony do Arduino modem. Argumenty 7 i 8 to numery pinów cyfrowych, do których podłączone są sygnały CE i CSN. Jeśli podłączyłeś je do innych pinów to możesz zmienić argumenty na inne :-).

Potem tworzę globalną tablicę o nazwie “rxAddr”.

const byte rxAddr[6] = "00001";

Zapisałem w niej adres modemu do którego Arduino będzie nadawać dane. Adres ma wartość “00001”, jednak jeśli chcesz możesz mu nadać inną jako dowolny 5 literowy napis.

Adres jest po to, że jeśli w sieci masz kilka modemów, to dzięki adresowi możesz wybrać jeden konkretny modem do którego wysyłasz dane.

W funkcji “setup” wywołuję metodę “radio.begin();” [radio.rozpocznij]. Aktywuje ona modem do działania.

Następnie ustawiam metodę “radio.setRetires(15, 15);” [radio.ustaw kiedy mam sobie darować]. Ustala ona co jaki czas i ile razy modem ma ponawiać wysłanie danych jeśli odbiorca ich nie dostał.

Pierwszy argument ustala co jaki czas ponawiać próbę. Jest on wielokrotnością 250 mikrosekund. 15 * 250 = 3750. Czyli jeśli odbiorca nie odbierze danych modem będzie starał się je wysyłać co 3,75 milisekund. 

Drugi argument to liczba prób. Czyli, że ma próbować wysyłać 15 razy zanim da sobie spokój i uzna, że odbiornik jest po za zasięgiem, albo jest wyłączony.

Metoda “radio.openWritingPipe(rxAddr);” [radio.otwórz rurę/kanał do zapisu] ustawia adres odbiornika do którego program ma wysyłać dane. Jej argumentem jest utworzona wcześniej tablica z adresem odbiornika.

Ostatnia metoda funkcji “setup” to “radio.stopListening();” [radio.skończ nasłuchiwać]. Przestawia ona modem w tryb nadawania danych.

W funkcji “loop” zaczynam od stworzenia napisu który chcę wysłać przez modem.

const char text[] = "Hello World";

Jest to tablica znaków/liter typu “char” [znak] o nazwie “text” do której przypisałem napis “Hello World” [Witaj Świecie]. 

Następnie za pomocą metody “radio.write(&text, sizeof(text));” [radio.zapisz] wysyłam tekst przez radio do modemu, którego adres ustaliłem wcześniej przez “openWritingPipe”.

Pierwszy argument metody to wskaźnik na zmienną, która przechowuje dane do wysłania. Dlatego używam przed nazwą zmiennej “&”, żeby zrobić z niej wskaźnik.

Drugi argument to ilość bajtów jakie radio ma pobrać ze zmiennej do wysłania. Użyłem tu funkcji “sizeof()[rozmiar/wielkość], która automatycznie oblicza ile bajtów ma napis w zmiennej “text”.

Przez tą metodę można wysłać maksymalnie 32 bajty na raz. Bo taki jest maksymalny rozmiar danych pojedynczego pakietu modemu.

Jeśli potrzebne ci jest potwierdzenie, że odbiornik odebrał dane, to metoda “radio.write” zwraca wartośc typu “bool”. Jak zwróci “true” [prawda], to dane dotarły do odbiornika. Jeśli zwróci “false” [fałsz/kłamstwo/bzdura] to dane nie zostały odebrane.

Metoda “radio.write” blokuje działanie programu do czasu potwierdzenia odebrania danych lub do czasu aż skończą się wszystkie próby nadawania ustalone w metodzie “radio.setRetires”.

Ostatnią częścią funkcji “loop” jest wywołanie funkcji “delay(1000);”. Blokuje ona program na 1000 milisekund, czyli jedną sekundę. Sprawia, że program będzie co sekundę wysyłał napis “Hello World” do odbiornika.

Program odbiornika w drugim urządzeniu z modemem będzie wyglądał tak:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8);

const byte rxAddr[6] = "00001";

void setup()
{
  while (!Serial);
  Serial.begin(9600);
  
  radio.begin();
  radio.openReadingPipe(0, rxAddr);
  
  radio.startListening();
}

void loop()
{
  if (radio.available())
  {
    char text[32] = {0};
    radio.read(&text, sizeof(text));
    
    Serial.println(text);
  }
}

Program wygląda z grubsza dość podobnie do programu nadajnika. Najpierw wybierane są biblioteki, których będziemy używać, potem tworzony jest obiekt “radio” z wybranymi pinami sterującymi, w kolejnej linii widać tablicę z adresem odbiornika – takim samym jak w programie nadajnika.

W funkcji “setup” na początku ustawiam obiekt “Serial” do komunikacji Arduino z komputerem.

while (!Serial);

Ten fragment czeka, aż port USB w Arduino przełączy się w tryb portu szeregowego COM:

Metoda “Serial.begin(9600);” [Port Szeregowy.rozpocznij] ustawia prędkość komunikacji z komputerem przez USB/COM.

Następna częśc funkcji to ustawianie modemu. Rozpoczyna je znana z poprzedniego programu metoda “radio.begin();” ustawiająca modem do działania z programem.

Kolejna linia programu to “radio.openReadinPipe(0, rxAddr);” [radio.otwórz rurę/kanał do odczytu], która ustala jaki nasz modem ma adres pod którym odbiera dane.

Pierwszy argument to numer rury/strumienia. Można stworzyć do 6 strumieni odczytu reagujących na różne adresy. Ja utworzyłam adres tylko dla strumienia numer 0.

Drugi argument to adres na jaki ma reagować strumień, żeby odebrać dane. Ustawiłem tu adres przypisany do tablicy “rxAddr”.

Kolejną czynnością jest włączenie odbierania danych przez modem za pomocą metody “radio.startListening();”. Od tej chwili modem czeka na dane wysłane pod ustalony adres.

W funkcji “loop” program wykonuje następujące operacje.
Najpierw sprawdza czy dotarły jakieś dane na adres modemu za pomocą metody “radio.available();”. Metoda ta zwraca wartość “true” [prawda]jeśli czekają na nas jakieś dane, lub “false” [fałsz] jeśli nikt nic nie wysłał.

char text[32] = {0};

Jeśli dane czekają, to tworzę 32-elementową tablicę typu “char” o nazwie “text” wypełnioną zerami, do której zapiszę odebrane dane.

By odczytać dane używam metody “radio.read(&text, sizeof(text));”.

Pierwszym argumentem metody jest wskaźnik do zmiennej do której mają być zapisane dane odebrane przez modem. By przedstawić zmienną jako wskaźnik zastosowałem znak “&” przed jej nazwą.

Drugim argumentem jest ilość danych do zapisania w zmiennej. Zastosowałem tu znowu funkcję “sizeof()” [rozmiar/wielkość], która automatycznie obliczy rozmiar tablicy “text”. 

Po odebraniu danych, przekazuje je do metody “Serial.println(text);”, która wysyła odebrany tekst do komputera, gdzie można go podglądać w “Monitorze portu szeregowego” za pomocą Arduino IDE.

Przy poprawnych połączeniach i działaniu programu, monitor powinien zwracać takie wartości.

Modem nRF24L01 możesz kupić w sklepie Nettigo:

sprae

Modem radiowy nRF24L01 – podłączenie do Arduino

Moduł radiowy bardzo łatwo podłączysz do Arduino. Wystarczy połączyć sygnały o takich samych nazwach na obydwu płytkach.

image

Schemat jest uniwersalny i pasuje do wszystkich płytek Arduino UNO, DUE, MEGA, Leonardo, Yun itp. standardu Arduino 1.0 (R3), ale również i starszych.

Sygnały interfejsu SPI znajdują się we wtyku ICSP. Do podłączenia przydadzą się przewody typu Gniazdo-Gniazdo (F-F), które zaproponowałem w spisie części na dole.

Resztę sygnałów możesz podłączyć za pomocą przewodu Wtyk-Gniazdo (F-M).

Wejście zasilania modułu VCC podłączasz w Arduino do pinu z napięciem 3.3 V
Wyprowadzenie GND podłączasz w Arduino do pinu GND.

Sygnały wybierające CE i CSN możesz podłączyć do dowolnych pinów cyfrowych. Potem w bibliotece RF24 możesz określić, których pinów użyłeś. Ja wybrałem piny 7 i 8 bo takich się będę trzymał w przykładach.

W płytce Arduino UNO sygnały SPI są połączone z niektórymi pinami cyfrowymi. Są one przez to wyłączone z użycia podczas korzystania z modemu.

  • MOSI jest połączony z cyfrowym pinem 11
  • MISO jest połączony z cyfrowym pinem 12
  • SCK jest połączony z cyfrowym pinem 13
  • SS (nie używany, ale też blokuje) jest połączony z cyfrowym pinem 10

W Arduino MEGA 1280 i 2560 jest podobna sytuacja.

  • MOSI jest połączony z cyfrowym pinem 51
  • MISO jest połączony z cyfrowym pinem 50
  • SCK jest połączony z cyfrowym pinem 52
  • SS jest połączony z cyfrowym pinem 53

W Arduino DUE, Yun i Leonardo nie ma tego problemu. Sygnały SPI na złączu ICSP są niezależne od pinów cyfrowych.

imageJa zamiast przewodów Gniazdo-Gniazdo użyłem płytki stykowej :-P.

Zestaw do podłączenia modemu nRF24L01 z wygodnymi przewodami i Arduino Leonardo.

sprae

Snap4Arduino – następca S4A

Opisując wczoraj Scratch dla Arduino – S4A czułem, że projekt mimo, że funkcjonalny to jest nieco opuszczony. Dziwiło mnie, że nikt nie zrobił poprawek do starego firmware dla Arduino do komunikacji z programem. To nie jest trudne.

Przeglądałem blog projektu i okazało się, że autorzy pracują nad czymś nowszym. Nowy projekt nosi nazwę Snap4Arduino. Środowisko jest bardzo podobne do Scratch, tak więc nikt nie będzie czuł się zagubiony.

Snap4Aruino na razie jest w wersji Alpha i u mnie był dość niestabilny. U ciebie może będzie lepiej, bo ja mam również system operacyjny w wersji testowej co pewnie pogłębiło niestabilność #życieNaKrawędzi ;-).

Program można pobrać ze strony projektu:

Działa z systemami operacyjnymi Windows, Linux i OS X.

By móc połączyć się z płytką kontrolera wymagane jest wczytanie do niej protokołu Firmata. To standardowy protokół obsługujący chyba wszystkie płytki Arduino i zgodne z nimi czyli np. Teensy.

Żeby go wczytać, wybierz w Arduino IDE menu: Plik > Przykłady > Firmata > StandardFirmata i wgraj do swojej płytki.

Snap4Arduino dzięki Firmata pozwala na dowolne wykorzystanie pinów kontrolera i  ich obsługa jest 7x szybsza niż w poprzednim projekcie.
Dodatkową zaletą jest to, że projekt został napisany w NodeJS, co pozwala na łatwe dodawanie klocków i rozwijanie programu.

sprae

Arduino rozszerza analogowy syntezator

Syntezator to instrument dla muzyków majsterkowiczów. To taki zestaw różnych modułów – kilku generatorów, filtrów, efektów i klawiatury muzycznej. Moduły można ze sobą łączyć przewodami by wpływały na siebie. Uzyskując oczekiwane, ciekawe brzmienie.

Dziś syntezatory są emulowane za pomocą programów komputerowych. Jednak tak jak i w innych dziedzinach, istnieją ludzie, którzy wolą prawdziwe analogowe wersje. To dla nich stworzono syntezator Werkstatt-Ø1.

image
Zdjęcie pochodzi ze strony Moogmusic

Syntezator składa się samemu, żeby podkreślić jego analogowy środek.

Producent syntezatora pozwala rozszerzać go na wiele możliwości. Jedną z nich jest podłączenie Arduino jako dodatkowego generatora.

image

Potrzebny jest do tego rezystor 10 kOhm i kondensator elektrolityczny 2,2 uF. W takim połączeniu tworzą filtr dolnoprzepustowy, zamieniający sygnał PWM z pinu 6 Arduino na sygnał analogowy.

Programowanie generatora jest bardo proste. Wystarczy ściągnąć specjalnie przygotowaną bibliotekę i bawić się w modyfikowanie jej przykładów.

/*Werkstatt Arpeggiator 
  Moog Music Inc. 2014
  Written by Chris David Howe

  Circuit consists of one 10kΩ resistor and a 2.2µf capacitor low pass filter.
*/

#include <werkstatt.h>

arpeggiator arpeggiator(6); //initiate and name the arpeggiator class (Output pin)

/* 
notes are assigned in intervals: tonic, minor2nd, major2nd, minor3rd,
major3rd, fourth, tritone, fifth, minor6th, major6th, minor7th,
major7th, octave. 
*/
  int notes[] = {tonic, octave}; // VCO EXP config


// note values: w, h, q, qt, e, et, sx, sxt, th, sxf 
  int note_values[] = {e, e}; //VCO EXP config

  
void setup() {
}      


void loop() {
for (int i = 0; i < ( sizeof(notes)/sizeof(int) ); i++)
  {
   //define a BPM and run the arpeggiator.play function  
   arpeggiator.play(140, notes[i], note_values[i]); 
   }
}


W tablicy “notes” zapisujesz wysokości dźwięków, zaś w tablicy “note_value” zapisujesz czasy trwania dźwięków. Stałe do wypełniania tablic to zapis nutowy angielskich skrótów nazw nut i wysokości dźwięków.

Za tempo grania odpowiada metoda “arpeggiator.play”. Jej pierwszy argument to tempo wyrażone w taktach na minutę.

Program możesz modyfikować w dowolny sposób, tak by reagował na różne czujniki, przełączniki lub nawet zewnętrzny sygnał MIDI.

Bibliotekę możesz pobrać ze strony Werkstatt Workshop, na której są projekty modów do tego syntezatora.

W bibliotece i na stronie Workshop opisane są jeszcze inne modyfikacje związane z Arduino. Np. generator szumu lub LFO – oscylator małych częstotliwości do modulowania dźwięków.

Arduino i niezbędne części kupisz u nas w Nettigo.

sprae

Arduino IDE 1.5.8

Pojawiło się nowe Arduino IDE w gałęzi 1.5 (tej głównie dla Arduino DUE i YUN).

Przetłumaczyłem wprowadzone zmiany ze strony Arduino:

ARDUINO 1.5.8 BETA – 2014.10.01

[środowisko programistyczne]
* Znajdź/Zastąp działa na wielu zakładkach na raz (Erwin Ried, Fulvio Ieva)
* Naprawione złe działanie “Zastąp”, kiedy w polu “Znajdź” jest pusto (Fulvio Ieva)
* Dużo zmian w trybie poleceń tekstowych konsoli (Matthijs Kooijman)
* Kursor się nie przemieszcza gdy włączysz opcję autoformatowania kodu

[biblioteki]
* SPI: dodano transakcyjne API (Paul Stoffregen)
https://github.com/arduino/Arduino/pull/2223
https://groups.google.com/a/arduino.cc/forum/#!msg/developers/TuZLfjeZjDI/6deNjw3Y9m4J
* FileIO bridge: naprawiono złą wartość zwracaną przez File::size() kiedy rozmiar pliku przekraczał 32768
* Zaktualizowano Temboo to najnowszej wersji
* Zaktualizowano/naprawiono przykładowe programy

[rdzeń]
* sam: Operatory “new” i “delete” nie zabierają już 50Kb biblioteki stdclib
* Poprawiono implementacje wewnętrzych funkcji kompilatora gcc (__cxa_guard_*) (Alexey Guseynov)
* Naprawiono problem wgrywania programów do Leonardo (i na innych płytkach zależnych od kontrolera mega32u4)
* Małe udoskonalenia klasy String (Matthijs Kooijman)
* Poprawiono wskazywanie ilości dostępnej pamięci Flash na płytce mega2560 (Leonardo Milani, Arnav Gupta)
* sam: usunięto nieużywane puste makro digitalPinToTimer(..) (Bill Perry)

Poniższe funkcje dodano także w Arduino IDE 1.0.6:

[rdzeń]
* avr: Dodano pustą funkcję atexit() biblioteki cstdlib (Christopher Andrews)

sprae

WiFi Shield 101 – Nowe WiFi do Arduino

Na targach World Maker Faire firma Atmel zaprezentowała nowy Shield do komunikacji z siecią WiFi dla Arduino UNO i Zero. Będzie obsługiwał standardy IEEE 802.11 b/g/n.

Shield ma sprzętowo obsługiwać protokół TCP/IP oraz zaawansowane funkcje kryptograficzne. Dzięki temu ma być lepiej zabezpieczony przed hackerami. W stanie uśpienia ma pobierać 2 uA. Arduino będzie komunikowało się z nim za pomocą magistrali SPI we wtyczce ICSP.

Urządzenie ma pojawić się w styczniu 2015 w sklepie Arduino.

sprae

Arduino Rozpoznaje głos

Zawsze myślałem, że do rozpoznawania głosu potrzebne jest dużo mocy obliczeniowej. W latach ‘90 marketingowcy mówili, że jak tylko procesory osiągną 1 GHz to będziemy mówić do komputerów. Teraz mamy rozpoznawanie głosu w telefonach, tabletach i przeglądarkach, ale za sprawą chmury obliczeniowej.

Tym czasem Arjo Chakravarty w grudniu 2013 napisał bibliotekę do Arduino. Rozpoznaje ona słowa z dokładnością 80%. Wycisnął to wszystko z ATmega328 o zegarze 16 MHz i 300 bajtów pamięci RAM.

Biblioteka wymaga do działania podłączenia mikrofonu pojemnościowego z przedwzmacniaczem do jednego ze wejść analogowych Arduino.

Jest jeszcze jeden projekt rozpoznawania mowy w serwisie Instructables. Opiera się on na bazie biblioteki BitVoicer. Układ elektryczny jest taki sam.

sprae

Diody RGB z interfejsem szeregowym

W Nettigo pojawił się nowy wynalazek. Diody RGB z interfejsem szeregowym.

image

Mają one 5 mm średnicy, a ich największą zaletą jest to, że do uzyskania każdej barwy wystarczy jeden pin. To nie wszystko. Tym samym jednym pinem można sterować większą ilością diod.

Diody podłącza się w taki sposób:

image

Od strony płaskiego ścięcia obudowy piny mają następujące znaczenie:

  • Data Out – Wyjście danych. Podłączasz do Data In kolejnych diod, którymi chcesz sterować.
  • Ground – Masa. Podłączasz do GND w Arduino.
  • +5V – Zasilanie. Podłączasz do 5V w Arduino.
  • Data In – Wejście danych. Tu podłączasz dowolny pin cyfrowy Arduino.

Dla każdej barwy RGB (Czerwony, Zielony, Niebieski) dioda ma 256 poziomów jasności. Co daje możliwość uzyskania 16,8 mln barw.

Bibliotekę do sterowania diodami napisali pracownicy Adafruit. Jest ona łątwa w użyciu. Do działania wymaga kontrolera opartego na AVR (Arduino UNO, Leonardo, YUN, Mini Pro, Teensy 2.0, ATtiny) i Arduio IDE.

#include <Adafruit_NeoPixel.h>

#define PIN 2

Adafruit_NeoPixel lamp = Adafruit_NeoPixel(1, PIN, NEO_RGB + NEO_KHZ800);

void setup() {
  lamp.begin();
  lamp.show();
}

void loop() {
  lamp.setPixelColor(0, 0, 0, 0);
  lamp.show();
  delay(1000);
  lamp.setPixelColor(0, 255, 0, 0);
  lamp.show();
  delay(1000);
  lamp.setPixelColor(0, 0, 255, 0);
  lamp.show();
  delay(1000);
  lamp.setPixelColor(0, 0, 0, 255);
  lamp.show();
  delay(1000);
}

Wejście danych “Data In” diody podłączyłem do pinu 2 Arduino.
Program co sekundę świeci innym kolorem diody (Czerwonym, Zielonym i Niebieskim).

Adafruit_NeoPixel lamp = Adafruit_NeoPixel(1, PIN, NEO_RGB + NEO_KHZ800);

Tworzy obiekt “lamp” do sterowania diodami.
Pierwszym argumentem jest ilość diod podłączonych w szereg do sterowania. U mnie jest jedna dioda, więc jest tam wartość 1.

Drugim argumentem jest pin, którym sterujesz diodami. W moim przypadku jest to pin nr 2.

Trzecim argumentem jest konfiguracja podłączonych diod.

lamp.begin();

Ta metoda aktywuje działanie obiektu lamp.

lamp.setPixelColor(0, 0, 0, 0);

Ustawia kolor wybranej diody.
Pierwszym argumentem jest numer diody, której chcesz ustawić kolor. 0 to pierwsza dioda.

Argumenty 2, 3, 4 to jasność składowych kolorów R, G, B. Przjmują one wartości od 0 do 255.

lamp.show();

Ta metoda wysyła dane o ustawionych kolorach do diod.

W Nettigo diody sprzedajemy w zestawach po 5 sztuk. Są one w 2 wersjach. Z przeźroczystą obudową (świecą promieniem do przodu) i dyfuzyjne z obudową w kolorze mlecznym, która się rozświetla.

sprae

Miernik aktywności fizycznej

Ten projekt bardzo mi się spodobał ze względu na konstrukcję.


Zdjęcie pochodzi ze strony instructables.com

To urządzenie noszone na ręku. Ale zachwycające jest to, że nie upchnięto wszystkiego w małej przestrzeni pod wyświetlaczem, tylko rozłożono w modułach na “pasku”. Właśnie ta modułowa konstrukcja bardzo mi się spodobała. Elementy elektroniczne projektu wpasowane są w małe ramki wykonane na drukarce 3D. Ramki mają na bokach zawiasy, dzięki którym łączą się ze sobą w pasek na rękę.

Wyobrażam sobie takie moduły jak shieldy do Arduino.

Urządzenie przedstawione w projekcie jest miernikiem aktywności fizycznej. Składa się z Arduino Pro Mini 3.3V, czujnika położenia MPU6050, modułu Bluetooth HC-06 oraz akumulatorka LiPO, Każde z tym elementów umieszczone jest w innej ramce obudowy.

Miernik odczytuje dane z akcelerometru i przesyła do telefonu z Androidem. Telefon analizuje te dane i oblicza ilość kroków i kalorii.

sprae

Licznik na przerwaniach

Wczoraj zamieściłem wpis “Najszybszy projekt na świecie”, w którym opisałem jak zbudować licznik do orbitreka. Michał poprosił w komentarzach, bym w celach edukacyjnych pokazał jak napisać taki licznik na przerwaniach.

Przerwanie – sygnał z urządzenia peryferyjnego, który powoduje zatrzymanie programu głównego i uruchomienie funkcji obsługującej przerwanie.

W Arduino wejścia przerwań są w pinach cyfrowych 2 i 3. W UNO przerwanie 0 jest w pinie 2, a przerwanie 1 w pinie 3. W Leonardo jest odwrotnie :-.

Do obsługi przerwań służy funkcja “attachInterrupt”

attachInterrupt(int, func, mode);

  • int – numer przerwania 0 lub 1 w zależności od pinu
  • func – nazwa fukcji obsługującej przerwanie
  • mode – ustala kiedy przerwanie ma być wywołane:
    LOW – kiedy na pinie jest stan niski;
    CHANGE – kiedy zmienia się stan;
    RISING – kiedy zmienia się stan z LOW na HIGH;
    FALLING – kiedy zmienia się stan z HIGH na LOW.

Program licznika z użyciem przerwania będzie wyglądał tak:

word steps;

void setup()
{
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(0, onStep, FALLING);
}

void loop()
{
}

void onStep()
{
  static unsigned long lastTime;
  unsigned long timeNow = millis();
  if (timeNow - lastTime < 50)
    return;
    
  steps++;
  Serial.println(steps);
  lastTime = timeNow;
}

Ustawiłem przerwanie nr 0 (pin 2 w UNO). Ma ono wywoływać funkcję “onStep”. Wywołanie nastąpi gdy stan na pinie zmieni się z HIGH na LOW.

Funkcja “onStep” zaczyna się od fragmentu eliminującego drgania styków.
Gdy włącznik (u nas kontaktron) zwiera styki, to przez ułamek sekundy one drgają. Te drgania mogą spowodować, że wywoła się kilka przerwań i funkcja zaliczy kilka kroków.
Dlatego początek sprawia, że pierwsze przerwanie będzie zaliczone, a każde kolejne przez 50 ms zostanie zignorowane jako drgania styków i nie zaliczy kroku.

Liczba kroków przechowywana jest jak poprzednio w zmiennej globalnej “steps”.

W funkcji “loop” możesz napisać dowolny fragment programu. Gdy pojawi się impuls na pinie 2, program w “loop” zostanie przerwany i wykonana zostanie funkcja “onStep”. Po jej zakończeniu program w “loop” zacznie pracę tam gdzie skończył.

Fragment eliminujący drgania styków działa tak:

Zmienna typu static przechowuje wartość nawet po wyjściu z funkcji. Na początku ma wartość 0. Po ponownym uruchomieniu funkcji będzie miała wartość taką, jaka była w niej ostatnio zapisana.
W tej zmiennej (“lastTime”) zapisany jest czas ostatniego wywołania przerwania.

W zmiennej “timeNow” zapisany jest aktualny czas,

Po odjęciu timeNow od lastTime uzyskujemy czas jaki upłynął w milisekundach od ostatniego przerwania.
Jeśli jest on mniejszy niż 50 ms, to wychodzimy z funkcji (return).

Jeśli czas jest większy niż 50 ms, zaliczany jest krok, wysyłany do Monitora portu szeregowego i zapisywany jest nowy czas ostatniego przerwania w zmiennej “lastTime”.

sprae