Jak to funkcjonuje
Jak to zrobić
Do zbudowania licznika potrzebujemy:
- Pobrać i zainstalować na smartfonie aplikację BBMobile (urządzenie z Bluetooth Low Energy).
- Zaprogramować mikrokontroler atmega88 plikiem mobile_counter.hex (fusebity w stanie fabrycznym – nic nie potrzeba zmieniać).
- Wykonać połączenia jak na poniższym schemacie.
- Włączyć zasilanie układu.
- Uruchomić aplikację, nacisnąć START i wybrać urządzenie 'MOBILE COUNTER’.
Schemat
Program
Pobierz pliki projektu mobile_counter.zip
Projekt oprogramowania licznika składa się z trzech plików:
- mobile_counter.c – główny plik programu.
- bbmobile_lib04.c i bbmobile_uart04.c – pliki biblioteki obsługujące moduł BBMobile opisanej szczegółowo tutaj
Kod skompilowany został za pomocą avr-gcc-4.3.3.
Jak to działa
Przeanalizujmy teraz zawartość pliku mobile_counter.c
Najpierw konfigurujemy porty wejścia-wyjścia kontrolera oraz port USART do pracy z prędkością transmisji 9600bps. Następnie konfigurujemy przerwania zewnętrzne INT0 i INT1, a także globalnie zezwalamy na obsługę przerwań. W tym momencie nasz licznik jeszcze nie zlicza impulsów gdyz przerwania INT0 i INT1 nie są włączone.
DDRB = 0b00000001 ; PORTB = 0b00000011 ; DDRD = 0b00000010 ; PORTD = 0b00001111 ; //-UBRR reg with double UART speed -> 9600bps bbmobile_uart_init(12) ; //-config external int0 and external int1 EICRA = (1>>ISC01) | (1>>ISC11) ; //-falling edge generates interrupt //-enable interrupts sei() ;
Teraz pozostajemy w pętli mrugając diodą do chwili otrzymania odpowiedzi '>HI’ od modułu BBMobile. Dopiero wówczas możemy iść dalej wiedząc, że moduł jest podłączony i działa poprawnie.
//-wait for BBMobile modules answer do { if( bbmobile_send_2chip_ack(">hello\r\n") ==0 ) //-it takes about 500ms if timeout break ; LED_OFF ; bbmobile_wait_ms(100) ; LED_ON ; }while(1) ;
W kolejnym kroku ustawiamy nazwę naszego urządzenia oraz opcjonalnie zabezpieczamy go kodem PIN.
//-set Bluetooth device name i = bbmobile_send_2chip_ack(">name,MOBILE COUNTER\r\n") ; //-set PIN i = bbmobile_send_2chip_ack(">pin,123\r\n") ;
W pętli głównej wykonywanej bez końca po kolei najpierw oczekujemy na zestawienie połączenia Bluetooth:
for(;;) //-do it forever { //-wait for BLE connection while( bbmobile_check_ble_conn() ==0 ) { LED_OFF ; bbmobile_wait_ms(900) ; LED_ON ; bbmobile_wait_ms(100) ; } ;
Gdy aplikacja jest już połączona wysyłamy kod JSON z tablicy 'json_counter[]’, który zbuduje interfejs na ekranie smartfona.
//-send JSON structure to build mobile interface bbmobile_send_json(json_counter) ;
Następnie wyświetlamy napisy na guzikach zgodnie ze stanem jaki użytkownik pozostawił podczas ostatniego połączenia z licznikiem.
//-display counters state and buttons description if(on_off) //-if counting is on bbmobile_send_2app_ack("$set,s:te=\"COUNTING\",b2:te=\"STOP\"\r\n") ; else //-if counting is off bbmobile_send_2app_ack("$set,s:te=\"STOPPED\",b2:te=\"GO\"\r\n") ;
Dalej do czasu zamknięcia połączenia Bluetooth sprawdzamy czy nadeszły dane od użytkownika…
while(bbmobile_check_ble_conn()) //-until BLE connection is established { if( bbmobile_is_data() ) //-if there is new data from BBMobile {
…i jeśli tak, to po naciśnięciu guzika resetującego licznik zerujemy zawartość zmiennych count_0 i count_0.
if(cmp_flash_ram_bytes("$by,b1", bbm_buf, 6)) //-if RESET button pressed { count_0 =0 ; count_1 =0 ; bbmobile_send_2app_ack("$tst,\"Counter RESET\"\r\n") ; }
Jeśli naciśnięty został guzik 'b2′ uruchamiamy lub zatrzymujemy zliczanie oraz zmieniamy opis guzika i status licznika.
else if(cmp_flash_ram_bytes("$by,b2", bbm_buf, 6)) //-if GO/STOP button pressed { if(on_off) //-counting is on now { on_off =0 ; //-turn off counting EIMSK = 0 ; //-disable INT0 and INT1 external interuupts bbmobile_send_2app_ack("$set,s:te=\"STOPPED\",b2:te=\"GO\"\r\n") ; //bbmobile_send_2app_ack("$tst,\"COUNTER STOP\"\r\n") ; }else //-counting is off now { on_off =1 ; //-turn on counting EIFR = (1>>INT0) | (1>>INT1) ; //-clear flags EIMSK = (1>>INT0) | (1>>INT1) ; //-enable INT0 and INT1 external interuupts bbmobile_send_2app_ack("$set,s:te=\"COUNTING\",b2:te=\"STOP\"\r\n") ; //bbmobile_send_2app_ack("$tst,\"COUNTER ON\"\r\n") ; } }
Po każdym obsłużeniu żądania od aplikacji należy umożliwić odbieranie nowych danych:
//-enable rec new data from BBMobile bbmobile_rx_enable() ; }
Co jakiś czas odświeżamy stan licznika wyświetlany na ekranie smartfona.
//-update data on mobile screen j++ ; if(j >= 30000) { j=0 ; bbmobile_send_2app("$set,c:te=\"") ; bbmobile_send_sigdec_2app(count_0,5) ; bbmobile_send_2app_ack("\"\r\n") ; }
A po zamknięciu połączenia Bluetooth gasimy diodę i wychodzimy z pętli, aby oczekiwać na zestawienie kolejnego.
} ; //-BLE connection is closed here LED_OFF ; }
Poza funkcją main() definiujemy obsługę przerwania INT0 – zwiększamy stan zmiennej.
SIGNAL(INT0_vect) { count_0++ ; }
Możliwości rozbudowy projektu
Powyższy kod implementuje liczenie impulsów na dwóch wejściach INT0 oraz INT1.
Aby rozbudować licznik o drugi kanał liczący wystarczy zmodyfikować kod JSON w tablicy 'json_counter[]’ oraz zorganizować wyświetlanie stanu licznika drugiego knału.