freakone | strona domowa

freakone.pl

14 Sierpnia

Atmega, Bluetooth i Android

Badając temat taniej komunikacji bezprzewodowej nieodzownym rozwiązaniem do sprawdzenia jest Bluetooth.
Swój moduł bluetooth w zestawie z kluczem USB kupiłem w serwisie dealextreme. Jest tam mnóstwo tanich, chińskich rzeczy i co najlepsze wysyłka do Polski jest za darmo. Wireless Bluetooth RS232 TTL Transceiver kosztował mnie 6.6$, a Super Mini Bluetooth 2.0 Adapter Dongle 1.8$ co razem dało śmieszne 25zł. Niestety nie miałem szczęścia i dostałem wersję z uboższym firmware - płytka mogła służyć tylko jako host (sama nie mogła się podłączać do innych urządzeń).

Samo podłączenie i uruchomienie urządzenia jest banalne. 2 piny zasilające (3.3V), 2 piny komunikacji szeregowej i opcjonalny pin na diodę sygnalizacyjną. Schemat i specyfikację można odnaleźć w tym datasheecie.



Konfiguracja urządzenia odbywa się poprzez wysyłanie komend AT+ przez UARTA. Domyślnie połączenie szeregowe ma parametry: baud 9600, brak parzystości, 8 bitów danych, 1 bit stopu. Po podłączeniu na początku wysyłamy samą komendę "AT", jeśli wszystko jest w porządku urządzenie odpowie nam "OK". Lista wszystkich komend jest dostępna w tym pliku. Możemy zmieniać: szybkość połączenia, nazwę urządzenia i pin. Należy pamiętać, że komendy działają jedynie, gdy moduł nie jest połączony z innym urządzeniem.

Komunikacja z komputerem

Tutaj nie będę się rozpisywał, rozwiązanie najbardziej oczywiste, banalne i najszybsze do skonfigurowania. Podłączamy zakupionego dongla (na windowsie 7 wszystkie sterowniki instalują się same), przez windowsowego managera odnajdujemy nasze urządzenie.
Po podaniu PINu zostaniemy zapytani o stworzenie portu COM, oczywiście się zgadzamy. To wszystko, mamy teraz dostęp do naszego urządzenia przez port komunikacyjny, możemy podłączyć się terminalem, czy łatwo zaimplementować funkcję w programie.
Oczywiście jeśli komuś nie pasuje windowsowa obsługa bluetootha może użyć np. BlueSoleila.

Komunikacja z telefonem

Idąc dalej stwierdziłem, że moduł można sprzęgnąć z telefonem. Smartfon jest dużo bardziej mobilny od laptopa co może się przydać w testach np. LineFollowera (którego aktualnie konstruuje kolega Łukasz). Bieganie za robotem z laptopem nie jest tak wygodne jak z telefonem :) Jako, że posiadam telefon z Androidem oczywistym wyborem było napisanie samemu aplikacji. W markecie są dostępne terminale bluetooth, jednak nie posiadają funkcjonalności, którą chciałem osiągnąć.

Moja aplikacja umożliwia nam pełną, dwukierunkową komunikację z danym układem - możemy zarówno wysyłać polecenia jak i odbierać informacje (czy to debugujące, czy interfejsowe). Idąc za ciosem można rozbudować program tak, że dostaniemy pełne, wielostopniowe menu dla danego układu. Jest to jednocześnie mój "Hello World" na androida - apka ma kilka niedociągnięć (zwiechy przy przywracaniu ze stanu uśpienia lub gdy starci połączenie) ale da się jej używać. Wszelkie nowe wersje będę publikował na blogu.

Zaimplementowane są: przesyłanie informacji z czujnika położenia (możemy np. użyć telefonu jako kierownicy i sterować torem jazdy robota), przycisków typu włącz-wyłącz i zwykłych. To jedynie ułamek tego co możemy zrobić - wszystko zależy od naszych potrzeb i pomysłu. Dostępne jest mnóstwo czujników: akcelerometr, czujnik pola magnetycznego, oświetlenia itp, itp.


Kod źródłowy
Skompilowana aplikacja

Układ testowy

Mikroprocesor AVR ATiny2313(8MHz RC) połączony z modułem BT i parę diodek.

Działanie aplikacji na androida i układu testowego:


Kod źródłowy dla AVR:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>

#define F_OSC 8000000
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_OSC / (USART_BAUDRATE * 16UL))) - 1) 

void USART_Init()
{		
	UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);	
	UCSRC = (3<<UCSZ0);
	
	UBRRL = BAUD_PRESCALE; 	// Load lower 8-bits of the baud rate value into the low byte of the UBRR register
	UBRRH = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR registe
}

void uart_put(unsigned char data )
{
	while ( !(UCSRA & (1<<UDRE)) )
		; 			                

	UDR = data; 			        
}

volatile char accelero[3];
volatile unsigned char i = 0;
ISR(USART_RX_vect)
{
	if(i > 0)
	{
		accelero[i - 1] = UDR;
		
		if(i == 3) 
			i = 0;
		else
			i++;
	}
	else
	{	
		switch(UDR)
		{					
			case 0x01: // button1
			PORTB ^= (1 << PB0);
			break;
			
			case 0x02: // button2
			PORTB ^= (1 << PB2);
			break;

			case 0x04: //pozycja
			i++;
			break;
		}
	}
}

int main()
{
	DDRB = 0xff;
	PORTB = 0;	
	
	sei();	//rejestr przerwań 
	USART_Init(); //inicjalizacja uarta
	
	uart_put('T'); // mozemy sobie cos wyslac do telefonu
	
	while(1)
	{
		// w zaleznosci od polozenia gasimy lub zapalamy diody
		if(accelero[2] > 30)
			PORTB |= (1 << PB3);
		else if(accelero[2] < -30)
			PORTB &= ~(1 << PB3);
		
		if(accelero[1] > 30)
			PORTB |= (1 << PB2);
		else if(accelero[1] < -30)
			PORTB &= ~(1 << PB2);
	}

}