Intel Galileo Gen2
Wrzucenie Intel Galileo do działu "Arduino i klony" może wydawać się niektórym absurdalne, jednak koniec końców, Galileo jest platformą, która jest kompatybilna Arduino, a więc możemy w pewny sposób sklasyfikować ten sprzęt jako "Arduino na sterydach". Określenie jest o tyle trafne, ponieważ wykorzystano w nim procesor Intel Quark X1000 o mikroarchitekturze Intel x86, taktowany zegarem 400Mhz.
Ogromnym atutem tej platformy jest zgodność mechaniczna i elektryczna z szeroką gamą shieldów dla Arduino. W praktyce oznacza to, że bez kłopotu wykorzystamy moduły, które już posiadamy lub postanowimy zakupić w przyszłości. Płytka pozwala również na wybór poziomu stanów logicznych, gdzie za pomocą zworki wybieramy napięcie 5V lub 3.3V. Gdyby tego było mało, na kartę microSD możemy wgrać specjalną dystrybucję Linuksa, np.: Yocto 1.4 Poky Linux.
Podobnie jak w Arduino UNO mamy do dyspozycji 14 pinów cyfrowych (z których 6 może pracować jako wyście PWM z rozdzielczością 8 lub 12-bitów) oraz 6 pinów analogowych. Do dyspozycji dostajemy również 512kB pamięci Flash na nasze szkice, 512kB pamięci SRAM i 8kB pamięci EEPROM. To nie wszystko - Intel Galileo Gen2 został również wyposażony w 256MB pamięci RAM DDR3 oraz 8MB pamięci Flash przeznaczonej na firmware.
Na sam początek zróbmy drobne zestawienie:
Arduino Uno | Arduino Zero / M0 | Intel Galileo Gen2 | |
Mikrokontroler / Procesor | ATmega328 | ATSAMD21G18 | Intel Quark X1000 |
Zegar | 16MHz | 48MHz | 400MHz |
Poziomy logiczne | 5V | 3.3V | 5V / 3.3V |
Napięcie zasilania DC | 7V - 12V | 4.3V - 5.5V | 7V - 15V |
Obciążalność pinu cyfrowego | 40mA | 7mA | 16mA / 5V 8mA / 3.3V |
Liczba pinów cyfrowych | 14 | 14 | 14 |
Liczba pinów PWM | 6 | 12 | 6 |
Wejścia analogowe | 6 | 6 (12-bit) | 6 (8/12-bit) |
Wyjścia analogowe | - | 1 (10-bit) | - |
Pamięć FLASH | 32kB | 256kB | 512kB |
Pamięć SRAM | 2kB | 32kB | 512kB |
Pamięć EEPROM | 1kB | 16kB | 8kB |
Pamięć RAM | - | - | 256MB |
Pamięć FLASH (Storage) | - | - | 8MB |
Oprócz tego, dostępny jest również port Ethernet 10/100 obsługujący standard PoE (Power-over-Ethernet), dzięki czemu możliwe jest zasilenie płytki z tego właśnie gniazda, a także slot mini-PCIE Express 1x, do którego podłączymy praktycznie co chcemy - np. kartę graficzną, Wi-Fi, itp.
Wielką wygodą dla pasjonatów Arduino UNO okażą się dwa porty UART. Jeden dostępny jest pod standardowymi pnami 0 i 1, natomiast drugi został wyprowadzony do 6-pinowego gniazda USB TTL FTDI w logice 3.3V. Co ciekawe, opcjonalnie można doprowadzić drugi UART do pinów 2 i 3.
Oprócz tego mamy możliwość skorzystania ze złącza JTAG oraz dodania zasilania bateryjnego dla podtrzymania wbudowanego zegara RTC.
Sterowniki i firmware
W przypadku Linuksa nie będzie problemu z wykryciem Galielo po podłączeniu do USB (po podłączeniu zasialania, należy odrobinę odczekać, zanim załaduje się firmware lub Linuks).
- usb 3-1.3: new high-speed USB device number 5 using ehci-pci
- usb 3-1.3: New USB device found, idVendor=8086, idProduct=babe
- usb 3-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
- usb 3-1.3: Product: Gadget Serial v2.4
- usb 3-1.3: Manufacturer: Linux 3.8.7-yocto-standard with pch_udc
- cdc_acm 3-1.3:1.0: This device cannot do calls on its own. It is not a modem.
- cdc_acm 3-1.3:1.0: ttyACM0: USB ACM device
Problem mogą mieć natomiast użytkownicy systemu Windows, gdzie będzie wymagana instalacja dodatkowych sterowników. Na szczęście nie musimy nigdzie biegać, ponieważ zostały umieszczone w rozpakowanym Arduino IDE od Intela. Możemy również skorzystać ze sterowników dostarczonych z paczką aktualizacji firmware, a właściwie będziemy musieli z nich skorzystać, jeśli będziemy chcieli przeprowadzić ten proces.
Domyślnie Intel Galileo Gen2 dostarczany jest z firmware w wersji 1.0.2, który zalecam zaktualizować do najnowszej wersji 1.0.4. Konieczne będzie skorzystanie ze specjalnego programu Intel Galileo Firmware Updater, który jest dostępny dla wszystkich popularnych platform. Sterowniki dostępne są zarówno w paczce z firmware, jak i do pobrania osobno z powyższego adresu.
W mendżerze urządzeń, do wykrytego Gadget Serial v2.4, aktualizaujemy sterowniki, wskazując ich lokalizację na dysku.
Instalacja powinna skutkować pojawieniem się nowego portu komunikacyjnego COM o nazwie Galileo.
Kiedy mamy już zinstalowany sterownik, możemy przystąpić do aktualizacji firmware:
Pamiętajmy - podczas aktualizacji firmware NIE ODŁACZAJMY ZASILANIA ANI KABLA USB.
Firmware Updater dla systemu Windows:
Firmware Updater dla systemu Linuks:
Aktualizacjia firmware trwa około 5 minut.
Jak programować?
Programowanie Intel Galileo Gen2 odbywa się za pomocą Arduino IDE, dostępnej dla systemów operacyjnych Windows, Linux i MacOS. Możemy wybrać wydanie Intela, które można pobrać z tego miejsca. W chwili pisania artykułu dostępna jest wersja 1.0.4 (oparta na Arduino IDE 1.6.0). Po zainstalowaniu i uruchomieniu, otrzymamy to, co już doskonale znamy:
Możemy również skorzystać z oficjalnego IDE od Arduino. Jednak po uruchomieniu, musimy wejść w menu Board i z menadżera płytek (Boards Manager) doinstalować pakiet Intel i586 Boards by Intel.
Po tym zabiegu w menu Boards, będziemy mieli możlwiość wyboru Galileo Gen2 jako typu programowanej płytki.
Zanim zaczniemy
Zanim zaczniemy długi romans z Intel Galileo Gen2, warto przygotować kartę microSD z systemem operacyjnym. Po pierwsze - otrzymamy możliwość korzystania z dodatkowych peryferiów takich jak karty Wi-Fi itp. Po drugie - jest to element wymagany, jeśli chcemy, aby nasz wgrany szkic z Arduino IDE był obecny po ponownym włączeniu urządzenia. W przeciwnym wypadku, zostanie on wymazany z pamięci po utracie zasilania.
Obecnie mamy do wyboru trzy dystrybucje, z których możemy skorzystać:
Obraz "SD-Card" (niezalecane)
Pierwsza z nich, to tzw. obraz SD-Card (~50MB), który należy jedynie rozpakować na wcześniej sformatowaną kartę microSD w systemie plików FAT32. Obraz systemu możemy pobrać tutaj lub tutaj. Otrzymujemy w niej sterowniki Wi-Fi, OpenCV, ALSA oraz Node.js.
Iot Devkit Image (zalecane)
Drugą możliwością jest obraz Iot Devkit Image (~210MB), który pobierzemy z następującej lokalizacji. Dla wielu osób, wybór ten może okazać się ciekawszy, ponieważ uproszczono w nim tworzenie połączeń sieciowych, zawiera więcej narzędzi dla deweloperów oraz wspiera OpenCV dla Pythona. Po rozpakowaniu pliku otrzymamy obraz o rozmiarze 1GB, który musimy wgrać na kartę microSD za pomocą WinDiskImager'a lub linuksowego polecenia dd.
- dd if=iotdk-galileo-image of=/dev/sdTwojaKartaSD
Kiedy włożymy kartę do slotu pamięci i uruchomimy ponownie Galileo, nasz port komunikacyjny w przypadku Windowsa przestanie być dostępny. Tym razem urządzenie zostanie wykryte jako CDC Serial:
Dodatkowo, Galileo zostanie wykryty jako dysk wymienny USB, na którym znajdziemy stosowne sterowniki iotdk-serial-external.zip.
które należy wypakować i zainstalować, wskazując ich lokalizację podczas aktualizacji sterowników. Kiedy wszystko przebiegnie poprawnie, tym razem ujrzymy port komunikacyjny nazwany Intel IoT Dev Kit Serial:
Debian / RoS (indywidualnie)
Trzecią możliwością jest Debian, gdzie proces instalacji znajdziecie na stronie RoS: http://wiki.ros.org/IntelGalileo/Debian
Jak "dobrać" się do Linuksa?
Aby dostać się do zainstalowanego Linuksa na karcie microSD, możemy wybrać jedną z metod.
Możemy skorzystać ze złącza UART oraz adaptera FTDI i dostać się do systemu za pomocą portu komunikacyjnego programem minicom lub PuTTy. Jest to najbardziej elastyczna forma, ponieważ pozwala nie tylko na dostęp do Linuksa, ale również do GRUB-a, a także podglądu procesu bootowania.
Zobaczmy zatem co spotkamy "w środku":
- root@galileo:~# uname -a
- Linux galileo 3.8.7-yocto-standard #1 Fri Feb 6 08:29:08 GMT 2015 i586 GNU/Linux
- root@galileo:~# lsmod
- Module Size Used by
- bnep 17740 2
- usbhid 23097 0
- usb_storage 46592 0
- stmmac 48425 0
- pppoe 17538 0
- pppox 12980 1 pppoe
- ppp_generic 23295 2 pppoe,pppox
- slhc 12965 1 ppp_generic
- g_acm_ms 34418 5
- libcomposite 24066 1 g_acm_ms
- pch_udc 31527 0
- udc_core 14227 2 libcomposite,pch_udc
- ohci_hcd 26434 0
- iwlwifi 73388 0
- cfg80211 171966 1 iwlwifi
- gpio_sch 17990 6
- evdev 17378 2
- adc1x8s102 12766 0
- industrialio_triggered_buffer 12686 1 adc1x8s102
- kfifo_buf 13032 1 industrialio_triggered_buffer
- industrialio 43200 3 industrialio_triggered_buffer,adc1x8s102,kfifo_buf
- ehci_pci 12656 0
- spi_pxa2xx 21780 0
- ehci_hcd 40351 1 ehci_pci
- spi_pxa2xx_pci 13049 1 spi_pxa2xx
- spidev 13053 0
- efivars 22987 0
- i2c_dev 13144 0
- btusb 17915 0
- pca9685 13582 16
- regmap_i2c 12714 1 pca9685
- gpio_pca953x 17384 49
- bluetooth 188237 8 bnep,btusb
- rfkill 20760 4 cfg80211,bluetooth
- usbcore 140197 6 btusb,usb_storage,ohci_hcd,ehci_hcd,ehci_pci,usbhid
- usb_common 12481 3 udc_core,libcomposite,usbcore
- intel_qrk_gip 20101 10
- uio 14412 4 intel_qrk_gip,gpio_sch
- at24 12949 0
- ipv6 240602 14
- root@galileo:~# cat /proc/cpuinfo
- processor : 0
- vendor_id : GenuineIntel
- cpu family : 5
- model : 9
- model name : 05/09
- stepping : 0
- cpu MHz : 399.088
- cache size : 0 KB
- fdiv_bug : no
- hlt_bug : no
- f00f_bug : yes
- coma_bug : no
- fpu : yes
- fpu_exception : yes
- cpuid level : 7
- wp : yes
- flags : fpu vme pse tsc msr pae cx8 apic pbe nx smep
- bogomips : 798.17
- clflush size : 32
- cache_alignment : 32
- address sizes : 32 bits physical, 32 bits virtual
- power management:
- root@galileo:~# ifconfig
- enp0s20f6 Link encap:Ethernet HWaddr --:--:--:--:--:--
- inet addr:10.42.0.47 Bcast:10.42.0.255 Mask:255.255.255.0
- inet6 addr: fe80::9a4f:eeff:fe05:413d/64 Scope:Link
- UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
- RX packets:7 errors:0 dropped:0 overruns:0 frame:0
- TX packets:74 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:1000
- RX bytes:935 (935.0 B) TX bytes:15522 (15.1 KiB)
- Interrupt:50
- lo Link encap:Local Loopback
- inet addr:127.0.0.1 Mask:255.0.0.0
- inet6 addr: ::1/128 Scope:Host
- UP LOOPBACK RUNNING MTU:65536 Metric:1
- RX packets:0 errors:0 dropped:0 overruns:0 frame:0
- TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
- collisions:0 txqueuelen:0
- RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)
- root@galileo:~# lspci
- 00:00.0 Host bridge: Intel Corporation Device 0958
- 00:14.0 SD Host controller: Intel Corporation Device 08a7 (rev 10)
- 00:14.1 Serial controller: Intel Corporation Device 0936 (rev 10)
- 00:14.2 USB controller: Intel Corporation Device 0939 (rev 10)
- 00:14.3 USB controller: Intel Corporation Device 0939 (rev 10)
- 00:14.4 USB controller: Intel Corporation Device 093a (rev 10)
- 00:14.5 Serial controller: Intel Corporation Device 0936 (rev 10)
- 00:14.6 Ethernet controller: Intel Corporation Device 0937 (rev 10)
- 00:14.7 Ethernet controller: Intel Corporation Device 0937 (rev 10)
- 00:15.0 Serial bus controller [0c80]: Intel Corporation Device 0935 (rev 10)
- 00:15.1 Serial bus controller [0c80]: Intel Corporation Device 0935 (rev 10)
- 00:15.2 Serial bus controller [0c80]: Intel Corporation Device 0934 (rev 10)
- 00:17.0 PCI bridge: Intel Corporation Device 11c3
- 00:17.1 PCI bridge: Intel Corporation Device 11c4
- 00:1f.0 ISA bridge: Intel Corporation Device 095e
- root@galileo:~# lsusb
- Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
- Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Drugim sposobem jest oczywiście gniazdo Ethernet. Jeśli wiemy jaki adres przydzieli nam DHCPD, to nie ma problemu, bowiem wystarczy jedynie ssh lub PuTTy. Problem może pojawić się, gdy nie wiemy, jaki adres IP dostało nasze Galileo. W tym celu możemy posłużyć się wgraniem poniższego szkicu i skorzystać z jednej z najmocniejszych cech Galileo - polecenia system(), które wykona program na Linuksie i zwróci nam na konsolę wyjście programu.
- void setup()
- {
- Serial.begin(9600);
- while(Serial.read()!='a')
- {
- Serial.println("Klepinij 'a' i enter!");
- delay(1000);
- }
- system("ifconfig > /dev/ttyGS0");
- }
- void loop() { }
Kiedy wgramy nasz szkic i uruchomimy monitor szeregowy, po wciśnięciu z klawiatury litery "a" oraz entera, otrzymamy wynik działania polecenia ifconfig > /dev/ttyGS0 (/dev/ttyGS0 odpowiada za UART)
Benchmark, benchmark, benchmark
Skorzystamy z naszego standardowego programu do obliczenia miliona iteracji liczby Pi:
- #define ITERATIONS 1000000L // number of iterations
- #define FLASH 10000 // blink LED every 1000 iterations
- void setup() {
- pinMode(13, OUTPUT); // set the LED up to blink every 1000 iterations
- Serial.begin(57600);
- }
- void loop() {
- unsigned long start, time;
- unsigned long niter=ITERATIONS;
- int LEDcounter = 0;
- boolean alternate = false;
- unsigned long i, count=0;
- float x = 1.0;
- float temp, pi=1.0;
- Serial.print("Beginning ");
- Serial.print(niter);
- Serial.println(" iterations...");
- Serial.println();
- start = millis();
- for ( i = 2; i < niter; i++) {
- x *= -1.0;
- pi += x / (2.0f*(float)i-1.0f);
- if (LEDcounter++ > FLASH) {
- LEDcounter = 0;
- if (alternate) {
- digitalWrite(13, HIGH);
- alternate = false;
- } else {
- digitalWrite(13, LOW);
- alternate = true;
- }
- temp = 40000000.0 * pi;
- }
- }
- time = millis() - start;
- pi = pi * 4.0;
- Serial.print("# of trials = ");
- Serial.println(niter);
- Serial.print("Estimate of pi = ");
- Serial.println(pi, 10);
- Serial.print("Time: ");
- Serial.print(time);
- Serial.println(" ms");
- delay(10000);
- }
Otrzymany wynik to 396ms, co daje nam 40x lepszy wynik niż w przypadku Arduino Zero i ponad 140x lepszy wynik niż w Arduino Uno.
Beginning 1000000 iterations...
# of trials = 1000000
Estimate of pi = 3.1415970325
Time: 396 ms
Beginning 1000000 iterations...
Dla porównania wynik Arduino Zero:
Beginning 1000000 iterations...
# of trials = 1000000
Estimate of pi = 3.1415972710
Time: 19661 ms
oraz wynik Arduino UNO:
Beginning 1000000 iterations...
# of trials = 1000000
Estimate of pi = 3.1415972709
Time: 57389 ms
Beginning 1000000 iterations..
Jeśli chodzi o prędkość portów I/O to uzyskujemy tutaj wynik 382kHz (dla porównania 350kHz Arduino Zero i 114kHz Arduino UNO).
Niezbyt imponująco? Spróbujmy skorzystać zatem ze specjalnej funkcji fastGpioDigitalWrite(), zamiast standardowego digitalWrite().
- void setup()
- {
- pinMode(13, OUTPUT);
- }
- void loop()
- {
- bool value = HIGH;
- while (1)
- {
- fastGpioDigitalWrite(GPIO_FAST_IO13, value);
- value = !value;
- }
- }
GPIO_FAST_IO13 odpowiada pinowi 13 (dioda), natomiast drugi parametr to stan logiczny pinu. Tym razem uzyskujemy wynik: 643 kHz!
Jeśli jeszcze Wam mało, możemy użyć kolejnej funkcji: fastGpioDigitalRegWriteUnsafe();
- void setup()
- {
- pinMode(13, OUTPUT);
- }
- void loop()
- {
- unsigned long value = fastGpioDigitalRegSnapshot(GPIO_FAST_IO13);
- while (1)
- {
- value ^= GPIO_FAST_IO3;
- fastGpioDigitalRegWriteUnsafe(GPIO_FAST_IO13, value);
- }
- }
Tym razem, otrzymany wynik to 1.2MHz. To jeszcze nie wszystko, bowiem niektóre piny mogą "wyciągać w ten sposób" nawet 2.9MHz - są to piny: 0, 1, 2, 3, 10, 12. Piny 4, 5, 6, 9, 11, 13 osiągną tutaj poprzedni wynik 1.2MHz. Należy jednak pamiętać, że piny 7 i 8 nie są obługiwane w trybie Fast-Mode Frequency.
Analogiczną funkcją do odczytywania stanu pinu, będzie oczywiście fastGpioDigitalRead()
Internet of Things
Skoro mowa o Internet of Things, to pamiętajmy, że korzystająć z Linuksa, mamy dostęp do praktycznie nieograniczonych możliwości. Za pomocą node.js uzyskujemy serwer WWW, w którym możemy udostępnić aplikacje do interakcji z naszym projektem z poziomu przeglądarki WWW.
... ale to już inna historia, na kolejny wpis
Sprzęt do testu dostarczył sklep internetowy elty.pl