W kolejnym wpisie chciałem się podzielić moją drogą do umożliwienia programowania Arduino Pro Mini (choć sposób będzie działał z każdą płytką) bez podłączania kabla USB do PC. Zamiast kabla postanowiłem użyć moduł Bluetooth XM-15B SPP. Pomysł powstał w czasie, gdy poznawałem możliwości tego modułu, które zresztą opisałem we wpisie tutaj: Arduino Uno oraz Bluetooth XM-15B.
Dla łatwiejszego zrozumienia problemu przypomnę jedynie, że wykorzystany moduł Bluetooth działa zgodnie z profilem SPP (Serial Port Profile), który jest niczym innym jak portem szeregowym UART poprzez połączenie Bluetooth. Czyli jest dokładnie tym samym co tradycyjny programator/konwerter USB->UART, jaki jest wbudowany w płytkę Arduino UNO. Natomiast płytka Arduino Pro Mini, jest w ogóle pozbawiona tego konwertera. Zatem jedyną możliwością programowania jej jest podłączenie poprzez dodatkowy konwerter USB/UART, np. FT232RL.
Wybrałem płytkę Arduino Pro Mini, gdyż to właśnie do niej docelowo zakupiłem moduł Bluetooth, aby zdalnie sterować mikrokontrolerem poprzez telefon. Ale sposób powinien działać z dowolną płytką, która wystawia połączenie szeregowe.
Zacznijmy od poprawnego podłączenia układu. Mój schemat wygląda następująco:

Podłączenie jest dość trywialne. Pin nadawania TXD z modułu Bluetooth musi zostać połączony z pinem odbiorczym RX Arduino. Tak samo pin odbiorczy RXD trafia do TX w Arduino. Zasilanie to sprawa oczywista, moduł czerpie je z Arduino, a Arduino zostało zasilone zewnętrznym źródłem 5V
podanym na wejście RAW, aby było przepuszczone przez układ stabilizujący. Nadmienię jedynie, że Arduino Pro Mini wykorzystane w tym schemacie to wersja z 5V
logiką. Choć pewnie wersja 3,3V
będzie działać identycznie, bo moduł XM-15B pracuje w obu logikach bez problemu.
Z punktu widzenia hardware’u to wszystko, jesteśmy gotowi do programowania. Musimy jedynie sparować urządzenie z komputerem. W każdym systemie operacyjnym wykonuje się to troszkę inaczej, więc nie będę wdawał się tu w szczegóły. Należy sparować się z urządzeniem o nazwie:

A następnie w systemie Windows przejść do Device Managera, celem odnalezienia numeru portu COM jaki został nadany dla naszego Bluetooth.

Przypominam, że w systemie zostaną zarejestrowane dwa porty, z czego tylko jeden będzie ten właściwy. Który wybrać? To niestety musimy określić eksperymentalnie. W moim przypadku był to port: Standard Serial over Bluetooth link (COM11).
Wydaje się, że jesteśmy już gotowi do skompilowania i wgrania programu zdalnie na płytkę. W związku z tym otworzyłem Arduino IDE oraz załadowałem najprostszy Sketch z Blink diodą LED. Nie jest ważne co wgramy, a raczej czy wgramy. Przed skompilowaniem upewniam się, że w menu: Tools->Board wybrana jest płytka Arduino Pro Mini, oraz Tools->Processor ustawiony na Atmega328P (5V, 16 MHz). Wybieram port COM11 w Tools->Port i…
Zaraz, zaraz. Zanim wgramy nasz kod, musimy się jeszcze zastanowić nad sygnałem DTR, który resetuje naszą płytkę przed wgraniem programu. Jak to działa?
Aby było możliwe wgrywanie naszych projektów na płytkę Arduino, jest ona zapisana malutkim programem zwanym Bootloaderem. Program ten ma za zadanie zaraz po uruchomieniu mikrokontrolera sprawdzić czy przypadkiem nie jest podjęta próba wgrania nowego programu. W takim przypadku Bootloader odbiera od Arduino IDE skompilowany kod i wgrywa go do pamięci procesora. Po wgraniu przechodzi do wykonania nowo wgranego źródła i dalej już dzieje się to, co sam napisałeś w swoim programie. A zatem ważne jest, aby uświadomić sobie, że Booltloader po zresetowaniu/uruchomieniu przez krótką chwilę czeka na nowe źródła a następnie przechodzi do wykonania programu głównego. Normalnie programator RS232 UART wykorzystuje sygnał DTR do podania go na wejście RESET układu Atmega. Powoduje to zresetowanie i dalej wgranie programu. Dlatego, jak używamy wbudowanych konwerterów USB/UART (lub np. FT232RL) to nie musimy nic robić. Program po prostu się ładuje, bo resetem steruje oprogramowanie po stronie uploadera (komputera). Niestety w naszym przypadku moduł Bluetooth XM-15B nie wystawia tego sygnału. Albo inaczej – mnie nie udało się go uruchomić. Więc musimy poradzić dobie inaczej. W tej sytuacji musimy wykonać reset manualnie w trakcie wgrywania kodu do procesora. Wykorzystam do tego przycisk reset wbudowany w Pro Mini. Kiedy go musimy nacisnąć? Najlepiej zrobić to w taki sposób, że
- Wciskamy i trzymamy przycisk RESET na Arduino Pro Mini
- Uruchamiamy kompilację z wgrywaniem w Arduino IDE
- Puszczamy przycisk RESET w momencie, gdy Arduino IDE wyświetla komunikat: Uploading…
Tyle teorii. Sprawdźmy co się stanie w rzeczywistości. Wykonałem powyższą procedurę i – niestety wgranie zakończone niepowodzeniem. Program skompilował się poprawnie, ale w trakcie Uploading… wysypał się z poniższym komunikatem:
Sketch uses 15296 bytes (49%) of program storage space. Maximum is 30720 bytes.
Global variables use 1129 bytes (55%) of dynamic memory, leaving 919 bytes for local variables. Maximum is 2048 bytes.
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x55
Problem uploading to board. See http://www.arduino.cc/en/Guide/Troubleshooting#upload for suggestions.
Co ważne to w trakcie ładowania programu, dioda na module Bluetooth przestała migać. A zatem Arduino otworzyło odpowiedni port COM. Ale i tak nie udało się wgrać programu. Komunikat nie mówi nam za wiele. Zatem postarajmy się zebrać więcej informacji. Aby to zrobić należy włączyć bardziej szczegółowe komunikaty w trakcie kompilowania. Można tego dokonać wchodząc do File->Preferences i zaznaczyć opcję Show verbose output during: według poniższego:

I ponownie przechodzimy do kompilacji, aby zobaczyć bardziej szczegółowe informacje. Z poniższego listingu wykasowałem tę cześć, która odpowiadała za informację o kompilacji – gdyż nie było w niej błędów, a pozostawiłem jedynie tę z momentu wgrywania binariów na płytkę:
Sketch uses 15296 bytes (49%) of program storage space. Maximum is 30720 bytes.
Global variables use 1129 bytes (55%) of dynamic memory, leaving 919 bytes for local variables. Maximum is 2048 bytes.
avrdude: Version 6.3, compiled on Jan 17 2017 at 12:00:53
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"
Using Port : COM11
Using Programmer : arduino
Overriding Baud Rate : 57600
avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0x55
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0x55
avrdude done. Thank you.
Problem uploading to board. See http://www.arduino.cc/en/Guide/Troubleshooting#upload for suggestions.
Z powyższych informacji od razu rzuciła mi się w oczy linia:
Overriding Baud Rate : 57600
Wynika z tego, że avrdude
(program, który wgrywa binarki do procesora) otwiera port COM oczekując prędkości transmisji 57600
. Okazuje się, że każda płytka posiada swoją własną konfigurację z jaką port UART nawiązuje komunikację z komputerem. Wszystko jest zapisane w Bootloaderze. A zatem skąd avrdude
wie jaką prędkość wybrać? Jest to zapisane w pliku konfiguracyjnym Arduino IDE, który mieści się w ścieżce: C:\Program Files (x86)\Arduino\hardware\arduino\avr\boards.txt
. W moim przypadku sekcja opisująca Arduino Pro Mini wygląda następująco:
##############################################################
pro.name=Arduino Pro or Pro Mini
pro.upload.tool=avrdude
pro.upload.protocol=arduino
pro.bootloader.tool=avrdude
pro.bootloader.unlock_bits=0x3F
pro.bootloader.lock_bits=0x0F
pro.build.board=AVR_PRO
pro.build.core=arduino
pro.build.variant=eightanaloginputs
## Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega328P
## --------------------------------------------------
pro.menu.cpu.16MHzatmega328=ATmega328P (5V, 16 MHz)
pro.menu.cpu.16MHzatmega328.upload.maximum_size=30720
pro.menu.cpu.16MHzatmega328.upload.maximum_data_size=2048
pro.menu.cpu.16MHzatmega328.upload.speed=57600
pro.menu.cpu.16MHzatmega328.bootloader.low_fuses=0xFF
pro.menu.cpu.16MHzatmega328.bootloader.high_fuses=0xDA
pro.menu.cpu.16MHzatmega328.bootloader.extended_fuses=0xFD
pro.menu.cpu.16MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex
pro.menu.cpu.16MHzatmega328.build.mcu=atmega328p
pro.menu.cpu.16MHzatmega328.build.f_cpu=16000000L
Widać tutaj zapisaną prędkość transmisji bootloadera w opcji pro.menu.cpu.16MHzatmega328.upload.speed
.
A co z tego wynika? Pierwsze co przychodzi na myśl, to to, że moduł XM-15B domyślnie działa z prędkością 9600
. Więc musimy zmienić jego konfigurację, na 57600
. Jak tego dokonać możesz przeczytać w opisie związanym z konfiguracją modułu Bluetooth XM-15B poprzez komendy AT – Arduino Uno oraz Bluetooth . Aby sprawdzić prędkość wykonaj polecenie:
AT
OK
AT+UART?
+UART:9600,0,0
OK
Moduł zwrócił prędkość 9600
. Zatem zmieńmy ją na taką, którą oczekuje Bootloader. Wykonaj poniższe polecenia:
AT
AT+UART=57600,0,0
AT+INIT
AT+RESET
Dla pewności sprawdź jeszcze raz, czy moduł raportuje nową prędkość i jeśli tak – to możemy wrócić do naszego zdalnego programowania poprzez Bluetooth.
Ponownie podłączam moduł Bluetooth i rozpoczynam wgrywanie kodu na mikrokontroler według opisanej powyżej procedury. Tym razem rezultat wygląda następująco:
avrdude: Version 6.3, compiled on Jan 17 2017 at 12:00:53
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
Copyright (c) 2007-2014 Joerg Wunsch
System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"
Using Port : COM11
Using Programmer : arduino
Overriding Baud Rate : 57600
AVR Part : ATmega328P
Chip Erase delay : 9000 us
PAGEL : PD7
BS2 : PC2
RESET disposition : dedicated
RETRY pulse : SCK
serial program mode : yes
parallel program mode : yes
Timeout : 200
StabDelay : 100
CmdexeDelay : 25
SyncLoops : 32
ByteDelay : 0
PollIndex : 3
PollValue : 0x53
Memory Detail :
Block Poll Page Polled
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
eeprom 65 20 4 0 no 1024 4 0 3600 3600 0xff 0xff
flash 65 6 128 0 yes 32768 128 256 4500 4500 0xff 0xff
lfuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
hfuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
efuse 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
lock 0 0 0 0 no 1 0 0 4500 4500 0x00 0x00
calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
Programmer Type : Arduino
Description : Arduino
Hardware Version: 2
Firmware Version: 1.16
Vtarget : 0.0 V
Varef : 0.0 V
Oscillator : Off
SCK period : 0.1 us
avrdude: AVR device initialized and ready to accept instructions
Reading | ################################################## | 100% 0.03s
avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: reading input file "C:\Users\piotr.jozwiak\AppData\Local\Temp\arduino_build_704769/efektownaChmurka.ino.hex"
avrdude: writing flash (15296 bytes):
Writing | ################################################## | 100% 13.34s
avrdude: 15296 bytes of flash written
avrdude: verifying flash memory against C:\Users\piotr.jozwiak\AppData\Local\Temp\arduino_build_704769/efektownaChmurka.ino.hex:
avrdude: load data flash data from input file C:\Users\piotr.jozwiak\AppData\Local\Temp\arduino_build_704769/efektownaChmurka.ino.hex:
avrdude: input file C:\Users\piotr.jozwiak\AppData\Local\Temp\arduino_build_704769/efektownaChmurka.ino.hex contains 15296 bytes
avrdude: reading on-chip flash data:
Reading | ################################################## | 100% 9.58s
avrdude: verifying ...
avrdude: 15296 bytes of flash verified
avrdude done. Thank you.
A po chwili miga dioda wbudowana w płytkę Arduino – co oznacza powodzenie. Udało się wgrać kod bez kabla USB.
Jak widać z powyższego przypadku czasem trzeba głębiej pogrzebać, aby dojść do rozwiązania. Opisany sposób nie jest idealny ze względu na potrzebę wciskania przycisku RESET. Idealnie by było, gdyby robił to za nas moduł Bluetooth. Taka możliwość jest przy zastosowaniu modułu HC-05, chociaż nie jest ona łatwo osiągalna, bo wymaga dolutowania dodatkowego kabelka do układu – jak można to zobaczyć tutaj: https://www.instructables.com/id/Program-an-Arduino-Wireless-Over-Bluetooth/ .
Próbowałem się wzorować na powyższym przypadku z HC-05, jednak w układzie XM-15B nie znalazłem żadnego wyjścia, które mogło by służyć za sygnał DTR. Zatem na tę chwilę pozostaję z przymusem ręcznego wciskania Reset – co i tak jest dla mnie wygodniejsze niż podłączenie kabla USB.