Autor: Dondu
Artykuł jest częścią cyklu: Bluetooth + mikrokontroler
Nadszedł czas na pokazanie w jaki sposób można wykorzystać moduł Bluetooth HC-05. Zrobimy to na przykładzie koprocesora omawianego przy okazji tematu dot. UART RS-232 i terminala RealTerm.
W niniejszym artykule wykonamy dokładnie to samo ale z wykorzystaniem modułu HC-05 do komunikacji bezprzewodowej (radiowej) zamiast wykorzystania kabli połączeniowych.
Schemat
Schemat nie będzie skomplikowany, ale zależny od posiadanej wersji mikrokontrolera ATmega8.
Zasilanie
Ponieważ posiadany przeze mnie moduł HC-05 działa na napięciu 3,3V (posiada własny regulator napięcia) musimy dostosować posiom sygnałów linii danych TxD i RxD do 3,3V. Mamy więc dwie możliwości:
- zastosować ATmega8 w wersji ATmega8A lub ATmega8L, ponieważ mogą pracować z napięciem 3,3V przy częstotliwości 1MHz, którą będziemy taktować mikrokontroler,
- lub zastosować ATmega8 zasilaną 5V oraz konwerter poziomów.
Szczegóły w tym zakresie omówiłem w artykule: Moduł HC-05 - Informacje podstawowe
Ponieważ dysponuję ATmega8A wykorzystam go do niniejszego artykułu. W związku z tym że moduł HC-05 zasilać będę z 5V, a ATmega8A z 3,3V, zastosujemy dodatkowy regulator napięcia 3,3V wykorzystując LF33CV.
Połączenie sygnałów danych TxD oraz RxD
Aby dane mogły być wymieniane prawidłowo należy dokonać krzyżowania linii danych w następujący sposób:
Nie zapomnij o tym :-)
Schemat
Na bazie powyższych założeń przygotowałem schemat układu testowego:
Program
Program koprocesora matematycznego oprzemy o przykład z artykułu UART RS-232 i terminala RealTerm. W stosunku do oryginału zmianie ulegnie jedynie częstotliwość taktowania, którą ustawimy na 1MHz za pomocą wewnętrznego generatora RC (standardowe ustawienie fabryczne wszystkich wersji ATmega8).
Tutaj należy zaznaczyć, że robię to tylko dla testów i mogę zaryzykować ewentualne problemy w komunikacji ponieważ wewnętrzny generator RC nie zapewnia wystarczająco niskiego poziomu błędu (w szerokim zakresie temperatur pracy) co może uniemożliwić prawidłową transmisję danych.
Jeżeli posiadasz rezonator kwarcowy możesz go dodać wraz z kondensatorami do pinów XTAL1 i XTAL2, co pozwoli na pozbycie się ewentualnych problemów. W takim przypadku nie zapomnij zmienić fusebitów oraz częstotliwości taktowania w opcjach projektu, który możesz pobrać w dalszej części artykułu.
Program pokazuje przy okazji w jaki sposób zrealizować transmisję danych za pomocą interfejsu UART (USART) i z wykorzystaniem przerwań.
Main.c:
/* Program realizujący obliczanie i wysłanie przez moduł HC-05 (Bluetooth z interfejsem SPP, czyli RS-232) wyniku funkcji kwadratowej y = 0.3187x^2 + 2x - 7 na podstawie x odebranego wcześniej także za pomocą HC-05. Szczegóły: http://mikrokontrolery.blogspot.com/2011/03/Bluetooth-HC-05-ATmega8-Test-komunikacji-koprocesor.html Mikrokontroler: Atmega8 Autor: Dondu Data: 2014.10.02 */ //#include <stddef.h> #include <avr\io.h> #include <stdio.h> #include <avr/interrupt.h> #include <util/delay.h> //zmienne dot. odbioru danych volatile unsigned char odb_x; //odebrana liczba X volatile unsigned char odb_flaga =0;//flaga informująca main o odebraniu liczby //bufor znaków ze wzorem funkcji, który wysyłamy po starcie programu volatile unsigned int usart_bufor_ind; //indeks bufora nadawania char usart_bufor[30] = "y = 0.3187x^2 + 2x - 7"; //bufor nadawania void usart_inicjuj(void) { //definiowanie parametrów transmisji za pomocą makr zawartych w pliku //nagłówkowym setbaud.h. Jeżeli wybierzesz prędkość, która nie będzie //możliwa do realizacji otrzymasz ostrzeżenie: //#warning "Baud rate achieved is higher than allowed" #define BAUD 9600 //9600bps standardowa prędkosc transmisji modułu HC-05 #include <util/setbaud.h> //linkowanie tego pliku musi być //po zdefiniowaniu BAUD //ustaw obliczone przez makro wartości UBRRH = UBRRH_VALUE; UBRRL = UBRRL_VALUE; #if USE_2X UCSRA |= (1<<U2X); #else UCSRA &= ~(1<<U2X); #endif //Ustawiamy pozostałe parametry moduł USART //U W A G A !!! //W ATmega8, aby zapisać do rejestru UCSRC należy ustawiać bit URSEL //zobacz także: http://mikrokontrolery.blogspot.com/2011/04/avr-czyhajace-pulapki.html#avr_pulapka_2 //standardowe parametry transmisji modułu HC-05 UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); //bitów danych: 8 //bity stopu: 1 //parzystość: brak //włącz nadajnik i odbiornik oraz ich przerwania odbiornika //przerwania nadajnika włączamy w funkcji wyslij_wynik() UCSRB = (1<<TXEN) | (1<<RXEN) | (1<<RXCIE); } //-------------------------------------------------------------- ISR(USART_RXC_vect) { //przerwanie generowane po odebraniu bajtu odb_x = UDR; //zapamiętaj odebraną liczbę odb_flaga = 1; //ustaw flagę odbioru liczby dla main() } //-------------------------------------------------------------- ISR(USART_UDRE_vect){ //przerwanie generowane, gdy bufor nadawania jest już pusty, //odpowiedzialne za wysłanie wszystkich znaków z tablicy usart_bufor[] //sprawdzamy, czy bajt do wysłania jest znakiem końca tekstu, czyli zerem if(usart_bufor[usart_bufor_ind]!= 0){ //załaduj znak do rejestru wysyłki i ustaw indeks na następny znak UDR = usart_bufor[usart_bufor_ind++]; }else{ //osiągnięto koniec napisu w tablicy usart_bufor[] UCSRB &= ~(1<<UDRIE); //wyłącz przerwania pustego bufora nadawania } } //-------------------------------------------------------------- void wyslij_wynik(void){ //funkcja rozpoczyna wysyłanie, wysyłając pierwszy znak znajdujący się //w tablicy usart_bufor[]. Pozostałe wyśle funkcja przerwania, //która zostanie wywołana automatycznie po wysłaniu każdego znaku. //dodaj do tekstu wyniku znaki końca linii (CR+LF), by na //ekranie terminala wyniki pojawiały się w nowych liniach unsigned char z; for(z=0; z<30; z++){ if(usart_bufor[z]==0){ //czy to koniec takstu w tablicy //tak znaleziono koniec tekstu, dodajemy znak CR usart_bufor[z] = 13; //znak powrotu karetki CR (Carrige Return) usart_bufor[z+1] = 10; //znak nowej linii LF (Line Feed) usart_bufor[z+2] = 0; //znak końca ciągu tekstu w tablicy break; } } //Zaczekaj, aż bufor nadawania będzie pusty while (!(UCSRA & (1<<UDRE))); //bufor jest pusty można wysłać //następny znak do wysyłki to znak nr 1 usart_bufor_ind = 0; //włącz przerwania pustego bufora UDR, co rozpocznie transmisję //aktualnej zawartości bufora UCSRB |= (1<<UDRIE); } //-------------------------------------------------------------- int main(void) { usart_inicjuj(); //inicjuj moduł USART (RS-232) sei(); //włącz przerwania globalne wyslij_wynik(); //na początku wysyłamy text wzoru, który po //resecie jest w tablicy usart_bufor[] while(1){ //tutaj Twój program .... //czekamy na informację o odebraniu danej nie blokując mikrokontrolera if(odb_flaga){ odb_flaga = 0; //zgaś flagę //wykonaj obliczenia i wynik przekształć na znaki ładując do //bufora usart_bufor[] sprintf(usart_bufor, "%f", 0.3187 * odb_x * odb_x + 2 * odb_x - 7); wyslij_wynik(); //rozpocznij wysyłanie wyniku przez RS-232 } //w tym czasie można wykonywać dowolny program //umieść go tutaj lub przed if() powyżej } }Do pobrania kompletny projekt AVR Studio 4.18 wraz z plikiem Hex dla 1MHz:
HC-05-Bluetooth-ATmega8-koprocesor.zip
Uruchomienie i testowanie
Czas na wykonanie testu komunikacji HC-05 z komputerem.
Ustanowienie połączenia
Po włączeniu zasilania należy dokonać:
- parowania komputera i HC-05,
- uruchomienia i ustawienia parametrów terminala RealTerm oraz zainicjowania połączenia z modułem HC-05.
Po wykonaniu powyższych czynności powinieneś mieć poprawnie połączony terminal RealTerm z modułem HC-05, co pozwala nam przejść do testowania programu i komunikacji. Poprawność stwierdza się świeceniem diody zielonej. Jeżeli połączenie nie jest potwierdzone świeceniem diody zielonej, nie będzie komunikacji i nie ma sensu byś przechodził do realizacji dalszej części artykułu.
Testowanie komunikacji
Jeśli dioda zielona świeci możemy przejść do testowania łączności z mikrokontrolerem. W tym celu naciskamy przycisk RESET (patrz schemat). W oknie terminala powinieneś otrzymać komunikat wysyłany przez mikrokontroler jakim jest wzór matematyczny, którego wyniki podawać będzie mikrokontroler za każdym razem, gdy wyślesz do niego za pomocą terminala liczbę z przedziału 0 - 255:
Następnie w zakładce Send w polu po lewej stronie podajemy liczbę całkowitą z przedziału 0 - 255, np. 10 i klikamy przycisk Send numbers, co spowoduje następującą sekwencję zdarzeń:
- liczba w postaci jednego bajtu o wartości 10 zostanie wysłana do modułu HC-05,
- po jej odebraniu moduł HC-05 wyśle liczbę z pomocą pinu TxD do mikrokontrolera ATmega8A (pin RxD),
- moduł UASRT mikrokontrolera ATmega8A po odebraniu liczby wywoła przerwanie,
- w wyniku przerwania mikrokontroler odczyta odebraną liczbę 10 i dokona obliczenia wartości y zgodnie ze wzorem,
- następnie ATmega8A przygotuje wynik w postaci ciągu kodów ASCII i umieści w buforze (pamięci SRAM mikrokontrolera w tablicy usart_bufor[])
- po czym zainicjuje wysyłanie zawartości (także poprzez przerwania) bufora za pomocą interfejsu USART do modułu HC-05 (wyjście TxD ATmega8A, połączone z wejściem RxD modułu HC-05),
- moduł HC-05 odbierając poszczególne znaki ASCII przesyłać je będzie do termilana RealTerm na komputerze drogą radiową,
- terminal wyświetli odebrane znaki ASCII,
czego rezultatem będzie:
Możesz oczywiście wysyłać kolejne liczby, a wyniki będą pojawiać się w kolejnych liniach kodu. Aby nie było widać znaków sterujących 0x0D i 0x0A, należy w zakładce Display w polu Display as zaznaczyć Ansi:
W ten sposób otrzymaliśmy koprocesor matematyczny działający drogą radiową :-)
Problem liczb i znaku zapytania w terminalu
Możesz się natknąć na problem pojawiającego się w wynikach jedynie znaku zapytania. Rozwiązanie problemu znajdziesz tutaj: Problem znaku zapytania podczas konwersji float do znaków ASCII
Podsumowanie
Na bazie powyższego programu możesz zrobić dowolną wymianę danych pomiędzy mikrokontrolerem, a komputerem. Program jest napisany z użyciem przerwań w taki sposób, by nie oczekiwał (blokując mikrokontroler) na kolejne liczby do obliczenia.
Jak widzisz moduł HC-05 na tym etapie nie jest niczym innym, jak zastępstwem przewodów w interfejsach przewodowych :-)
fajny "gotowiec" .... szacun za styl w jakim opisałeś .... moim zdaniem wartościowy i praktyczny artykulik dla kogoś kogo tematyka transmisji na małe odległości interesuje a zaczyna się bawić z AVRami
OdpowiedzUsuń:-)
UsuńFunkcja Inicjalizujaca blokuje mi program i dalej nie idzie (Procesor jest podłączony dobrze i działa - sprawdziłem na dwóch ATMEGAch 8A-PU)
OdpowiedzUsuńPrzechodzi przez tę funkcję jeśli zakomentuję linię ustawiania UCSRB albo jeśli zakomentuję warunek #if USE_2X
UCSRA |= (1<<U2X);
#else
UCSRA &= ~(1<<U2X);
#endif
Wtedy jednak blokuje się na funkcji "wyslij_wynik()"
Jakiś pomysł?
Jeżeli pozbawiasz funkcji części kodu, to może ona nieprawidłowo ustawić parametry transmisji w konsekwencji komunikacja nie będzie możliwa. Funkcja jest prawidłowa więc zostaw ją w pierwotnej wersji.
UsuńNie przedstawiasz całego programu więc nie sposób stwierdzić, co jest przyczyną.
Rozumiem, że w wersji oryginalnej załączonej do artykułu komunikacja jest prawidłowa? Jeśli nie, to znaczy, że problem leży przed Tobą na biurku (połączenia, ustawienia fusebitów, itp.), a nie w oryginalnym programie.
Proponuję więc byś utworzył na forum temat i wkleił cały program, schemat i zdjęcia. Tutaj natomiast wrzuć proszę link do tego tematu na forum, a zerknę do niego.
Jak przesłać stringa do uart? albo inta z wynikiem pomiaru z czujnika temperatury?
OdpowiedzUsuńNo przecież ten temat to pokazuje :)
UsuńMożesz także wpisać UART lub USART w wyszukiwarce w spisie treści - znajdziesz wiele innych przykładów.
Cześć
OdpowiedzUsuńJaką maksymalną prędkość transmisji udało się wam uzyskać?
Szukam w internecie i są rozbieżne informacje. Czy coś na poziomie 1,5M -2M baud na tym module jest osiągalne?
Cześć!
OdpowiedzUsuńDzięki wielkie za poradnik!
Natrafiłem na pewien problem. Chciałem ustawić wyższe prędkości przesyłu danych. Jednak zwiększając baud rate w kodzie mikrokontrolera (19.2k, 38.4k i więcej) w realtermie dostaję same śmieci.
Czy powinienem zmieniać coś jeszcze?
Czy ustawienia w Realterm także zmieniłeś?
UsuńCześć fajny artykuł. Jak przesłać 3 parametry z czujników za pomocą HC-05 pomiędzy 2 atmegami32?
OdpowiedzUsuńCześć.
UsuńNie sprawdzałem, ale HC-05 może pracować jako master lub slave oraz posiada komendy AT parowania i łączenia z wybranym modułem. Nie powinno więc być problemu.
Jednak taki sposób komunikacji jest dość drogi. Lepiej użyć znacznie tańszych modułów nie opartych o Bluetooth np. nrf24l01, które kupisz za 0,5$/szt z darmową dostawą :-)
Fakt tanie nie są, ale juz je zakupiłem. Jako, że mam małe doświadczeine w programowaniu, to mój problem stanowi napisania oprogramowania do stworzenia i przesłania takiego bufora danych a następnie odczytu na atmedze ;/
OdpowiedzUsuńOne są tanie, ale do Twojego celu są inne jeszcze tańsze, ale skoro kupiłeś, to OK :)
UsuńKomunikację z komputerem już opanowałeś?
Komendy AT także?
Przerobiłeś już wszystkie artykuły z tego cyklu?: Bluetooth + mikrokontroler
niestety jest jeden problem, nie mam BT w lapku;/ własnie dla testów chyba zakupię sobie jakis adapterek do latpopa
UsuńAle może masz smartfon z Androidem - zastąpi komputer - w cyklu artykułów (link wyżej) opisałem aplikacje na Android. Natomiast Bluetooth w postaci malutkiego wtyku USB to bardzo dobra i tania alternatywa - można go kupić za mniej niż 1$ z darmową dostawą.
UsuńFaktycznie znalazłem aolikacje na telefon, ale kupię również do laptopa BT. Myśle, że fajnie byłoby zrobić artykuł transmisji danych pomiędzy 2 prockami. Dzięki artykułom można się wiele nauczyć a i nie ukrywam, że muszę takie coś zrobić :D
UsuńWpisałem temat na listę.
UsuńMam problem, w transmisji po kablu wszystko gładko działa, wykorzystuje funkcje sprintf oraz dtostrf. Przesyła mi ładnie wyniki np 23.7 ale jak wepnę moduł HC-05 to pokazuje np 27 z pominięciem "3." Sprawdzałem HC tez ma ustawiona prędkość 9600 jak w kodzie i Realtermie. Probowałem na kwarcach 7.3728. 8 oraz 11,0592 MHz. Przykłady z blogu działaja, zarówno echo jak i przyklad z funkcja. Moduł zasilany 5V atmege prbowalem i 5V i 3V3 zeby byla zgodność na RX TX ale efekt taki sam. Co z tym zrobic?
OdpowiedzUsuńWidziałem Twój temat na Elektrodzie: Przejscie z UARTa na HC-05, błędne wyświetlanie w Realtermie, ale nie zabrałem głosu, bo wszystko co można było wskazać wskazali Ci inni forumowicze.
Usuń