Skocz do zawartości

Elvis

Użytkownicy
  • Zawartość

    2613
  • Rejestracja

  • Ostatnio

  • Wygrane dni

    195

Wszystko napisane przez Elvis

  1. Aby sprawdzić, gdzie są przechowywane zmienne funkcje itd. najlepiej otworzyć plik z rozszerzeniem .map (znajduje się w katalogu z plikiem wynikowym). Przykładowo w program14.map znajdziemy fragment: Memory Configuration Name Origin Length Attributes ROM 0x00000000 0x0001e000 xr RAM 0x40000000 0x00004000 rw *default* 0x00000000 0xffffffff Tutaj zdefiniowana jest mapa pamięci naszego mikrokontrolera. Od adresu 0 mamy Flash, od 0x40000000 pamięć RAM. Dalej odnajdujemy adresy zmiennych, czy funkcji. Przykładowo stała: const unsigned int SIN_TABLE[] = { 0, 15, 31, 46, 61, 76, 90, 104, 117, 129, 141, 152, 161, 170, 178, 184, 190, 194, 197, 199, 200 }; Daje wynikowo: *(.rodata) .rodata 0x00000418 0x74 program14.o 0x00000438 SIN_TABLE 0x00000418 LED_PIN Więc jak widać const działa zgodnie z oczekiwaniami, stała umieszczana jest w pamięci Flash.
  2. Ja bym radził oprócz oceny "na oko" podłączyć miliamperomierz i sprawdzić ile mA pobiera podświetlenie. Na diodę powinno być 10-20mA. Więc wystarczy sprawdzić ile diod ma wyświetlacz, i można chociaż z grubsza prąd oszacować. Poza tym jak pisze Nawyk zacząć o rezystora, sprawdzić jak świeci i ile prądu bierze.
  3. Strasznie drogo w AVT... Poczekaj chwile, może Treker coś z Kamami załatwi. Jeśli nie, to może lepiej inną płytkę wybrać. Bo prawie 180 zł to nieporozumienie...
  4. Ja również bardzo dziękuję za oddane głosy. Gratuluję wszystkim laureatom.
  5. Poprzednia lekcja RS-232, c.d. - biblioteka standardowa W przypadku Bascom-a używanie RS-232 jest bajecznie proste. Polecenie „print” wysyła tekst, właściwie nic nie trzeba robić. W tej części spróbujemy uzyskać podobny efekt w języku C. Funkcja sprintf Najpierw przyjrzymy się funkcji „sprintf”. Należy ona do biblioteki standardowej C, więc jest dostępna na właściwie każdej platformie i kompilatorze. Aby ją wykorzystać wystarczy zaimportować plik stdio.h: #include <stdio.h> Funkcja sprintf jest bardzo podobna do znanej funkcji printf. Każdy kurs C zaczyna się wyświetleniem „Hello World” za pomocą printf. Sprintf jako pierwszy parametr przyjmuje bufor (tablicę znaków) i zamiast na ekran, wypisuje wynik do bufora. Obejrzyjmy kod: char buf[32]; sprintf(buf, "Hello world!\n"); Program nie wypisze nic na ekran. W jego wyniku zmieni się zawartość tablicy buf, ale nic nie będzie widać. Po co więc nam funkcja sprintf? Za jej pomocą możemy właściwie dowolnie formatować napisy, wykorzystywać formatowania w rodzaju %d, %f, \n itd. Następnie bufor możemy za pomocą naszej funkcji uart_send_string() wysłać przez RS-232. Zmieńmy nieco poprzedni program. Tym razem, gdy otrzymamy nieznane polecenie (znak), wypiszemy kod tego znaku. Fragment: default: uart1_send("Nieznane polecenie\r\n"); break; Zastąpimy następującym: default: sprintf(buf, "#%d - Nieznane polecenie\r\n", c); uart1_send(buf); break; Kompilujemy program i... czeka nas przykra niespodzianka. Dostajemy całe mnóstwo błędów: c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(freer.o): In function `_malloc_trim_r': mallocr.c:(.text+0x48): undefined reference to `_sbrk_r' mallocr.c:(.text+0x64): undefined reference to `_sbrk_r' mallocr.c:(.text+0x84): undefined reference to `_sbrk_r' c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(makebuf.o): In function `__smakebuf': makebuf.c:(.text+0x3c): undefined reference to `_fstat_r' makebuf.c:(.text+0x110): undefined reference to `isatty' c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(mallocr.o): In function `_malloc_r': mallocr.c:(.text+0x424): undefined reference to `_sbrk_r' mallocr.c:(.text+0x4cc): undefined reference to `_sbrk_r' c:/winarm/bin/../lib/gcc/arm-elf/4.1.1/../../../../arm-elf/lib\libc.a(stdio.o): In function Okazuje się, że musimy sami zdefiniować brakujące funkcje. Najprościej będzie skopiować gotowy plik z funkcjami z przykładu w katalogu: C:\WinARM\examples\lpc2129_adc_stdio\syscalls.c Kopiujemy plik do naszego projektu, dodajemy go w oknie edytora. Niestety błędy podczas kompilacji pozostają bez zmian. Musimy dodać nowy plik do kompilacji, czyli poleceń w pliku Makefile. Odnajdujemy fragment: # List C source files here. (C dependencies are automatically generated.) # use file-extension c for "c-only"-files SRC = $(TARGET).c I do zmiennej SRC dodajmy nowy plik: SRC = $(TARGET).c syscalls.c Jest to bardzo ważny moment. Od tej chwili nasz program będzie się składał z dwóch plików źródłowych. Część kodu jest w program19.c, część w syscalls.c. Jest to bardzo częsty i użyteczny mechanizm. Nie musimy trzymać wszystkich funkcji w jednym, z czasem bardzo dużym pliku. Zamiast tego dzielimy projekt na mniejsze części, funkcje umieszczamy w różnych plikach. Bardzo ułatwia to orientowanie się w projekcie oraz pozwala na wykorzystywanie plików z innych projektów w nowych programach. Niestety problemy nadal występują. syscalls.c:15:18: error: uart.h: No such file or directory syscalls.c: In function '_read_r': syscalls.c:31: warning: implicit declaration of function 'uart0GetchW' syscalls.c:31: warning: nested extern declaration of 'uart0GetchW' syscalls.c:37: warning: implicit declaration of function 'uart0Putch' syscalls.c:37: warning: nested extern declaration of 'uart0Putch' Na początek po prostu pozbędziemy się problemów - zakomentujemy wszystkie linie, które sprawiają problemy. W języku C wystarczy na początku linii napisać // aby kompilator resztę traktował jako komentarz. Dzięki temu linie te zostaną pominięte podczas kompilacji, ale gdy będziemy chcieli do nich wrócić, wystarczy usunąć napis //. Kompilujemy program i wgrywamy do procesora. Poniżej wynik działania: W archiwum program19.zip znajdziemy kompletny kod przykładu. Wgrywanie zajmuje teraz dużo więcej czasu niż w poprzedniej wersji. Niestety dołączenie funkcji sprintf znacznie zwiększyło objętość programu. Zajmuje teraz aż 45KB! Czyli o ponad 40KB więcej niż poprzednio... Moduł obsługi UART-a Zanim przejdziemy dalej warto nieco uporządkować program. W pliku głównym poza samym programem napisaliśmy kod odpowiedzialny za komunikację przez UART1. Kod ten na pewno przyda się w kolejnych programach, jest dość długi i utrudnia analizę programu głównego. Przygotujemy własny moduł, czyli utworzymy dwa pliki: uart.h, uart.c Do pliku uart.c przeniesiemy funkcje związane z komunikacją, czyli: uart1_init, uart1_recv, uart1_send_byte, uart1_send. Plik nagłówkowy jest potrzebny kompilatorowi, aby w programie głównym rozpoznawane były nazwy naszych funkcji. Wpisujemy do niego nagłówki funkcji poprzedzone słowem kluczowym extern, które informuje kompilator, że treść funkcji zdefiniowana jest gdzie indziej (w pliku uart.c). Następnie w programie głównym dodajemy instrukcję włączającą nasz nowy moduł: #include "uart.h" Musimy jeszcze w pliku Makefile dodać informację o nowym pliku z programem: uart.c. Wykonujemy to podobnie jak poprzednio dla pliku syscalls.c. Kompilujemy nowy projekt i sprawdzamy działanie. Wielkość kodu, ani działanie programu nie ulega zmianie. Natomiast program jest nieco "czytelniejszy", a nasz nowy moduł uart będziemy mogli wykorzystywać w kolejnych programach. Archiwum Program20.zip zawiera omawiany przykład. Funkcja printf i scanf Teraz możemy przystąpić do prawdziwego ułatwienia pracy. W standardowych programach pisanych na PC do komunikacji z użytkownikiem można wykorzystać standardowe funkcje printf oraz scanf. Ich użycie jest bardzo proste i każdy kurs C szczegółowo je omawia. Nauczymy się wykorzystywać je na mikrokontrolerze. Otwieramy plik syscalls.c i sprawdzamy, które linie musieliśmy zakomentować, aby program się kompilował. Na początek: #include "uart.h" Tutaj jest łatwo - wystarczy usunąć komentarz, mamy moduł uart.h, więc wszystko powinno być dobrze. Następnie zobaczmy zakomentowane odwołania do funkcji uart0Putch. Jak można się domyślić, ta funkcja ma wysyłać znaki. Nasza wersja nazywa się uart1_send_byte. Wystarczy więc zmienić nazwę wywoływanej funkcji i oczywiście usunąć komentarze. Zobaczmy jeszcze funkcję uart0GetchW. Odpowiada ona za odczyt znaku. Nasza wersja nazywa się uart1_recv i niestety działa nieco inaczej - zamiast czekać na znak, zwraca 0 jeśli nic nie zostało odebrane. Musimy więc dodać pętlę, w której będziemy czekać, aż coś odbierzemy. do { c = uart1_recv(); } while (c==0); Czas teraz wrócić do programu głównego i wykorzystać nowo przygotowane funkcje. Nowy program ma na celu jedynie prezentację, jak łatwo teraz programować komunikację przez RS-232: while (1) { printf("Podaj prędkość robota: "); scanf("%d", &speed); printf("\n"); if (speed>150) speed = 0; if (speed<0) printf("Za mala wartosc\n"); else if (speed>100) printf("Za duza wartosc\n"); else printf("Predkosc wynosi %d%%\n", speed); } Okazało się, że kod w pliku syscalls.c wymagał nieco poprawek - wersja z przykładu nie działała w 100% poprawnie. W załączniku znajdziemy plik program21.zip z poprawioną i przetestowaną wersją. Wnioski Wykorzystanie funkcji printf do komunikacji jest bardzo wygodnym rozwiązaniem. Niestety w przypadku kompilatora gcc oraz biblioteki standardowej, cena jaką trzeba zapłacić za wygodę jest wysoka. Dla dużych programów 40kB nie stanowi problemu, natomiast jeśli nasz program jest mały, lepiej poszukać innego rozwiązania. Program21.zip Program20.zip Program19.zip
  6. Może warto zobaczyć ten dokument: http://www.atmel.com/dyn/resources/prod_documents/doc2553.pdf Atmel opisuje w nim różnice między atmega88 i atmega8. Na mój gust różnice są spore - inne adresy rejestrów, część ma pozmieniane nazwy. Poza tym inne jest napięcie referencyjne dla ADC. Trzeba więc pewnie program trochę pozmieniać.
  7. Timer + rs232 powinien wystarczyć. Przed wywołaniem funkcji uruchamiasz timer, po zakończeniu zatrzymujesz i wartość wysyłasz przez rs232.
  8. Ja czasy mierze w ten sposób, że na wolnym pinie zmieniam stan przed wywołaniem określonej procedury i po powrocie. Następnie na oscyloskopie oglądam przebieg.
  9. Miejsce 1: Nawyk Miejsce 2: Zuk Miejsce 3: Lassar Uzasadnienie: Pierwsze miejsce dla Nawyk-a, głównie za artykuł o serw-ach. Ładnie zebrane informacje, porządny artykuł. Na pewno plus za opis modułu MEMS. Chociaż jak chodzi o MEMS, to trochę za mało jak na mój gust... Drugie miejsce dla Zuk-a za artykuł o pomiarze stanu akumulatorów. Temat dla mnie interesujący w dziedzinie niekoniecznie związanej z robotyką. Ale na pewno ładnie i profesjonalnie opisany. Z trzecim miejscem miałem problem. Głosuję na Lassar-a za opis zawieszeń.
  10. Poprzednia lekcja Lekcja 9 - RS-232 Nastepna lekcja Na początek krótki wstęp Wszyscy pewnie znają interfejs RS-232. Charakterystyczne gniazdo DB-9 dawniej montowane było w każdym komputerze PC. Obecnie coraz częściej gniazdo zastępowane jest przez USB, na szczęście dostępne są przejściówki USB<->RS232. Wtyczka wyposażona jest w 9 linii, opis możemy znaleźć na wikipedii, poniżej dla przypomnienia najważniejsze linie: Numer pinu Oznaczenie Funkcja 2 - RxD - Odbiór danych 3 - TxD - Transmisja danych 5 - GND - Masa Te trzy linie wystarczą do naszych celów - wymiany informacji między mikrokontrolerem, a PC. Łącząc dwa urządzenia, musimy podłączyć je „na krzyż”, czyli linię RxD łączymy z TxD drugiego układu: Zasada jest prosta, chociaż łatwo się pomylić: to co jeden układ wysyła przez linię TxD, drugi musi odebrać, linią RxD. Takie połączenie dawno temu było popularne do łączenia dwóch komputerów PC. Komunikacja z mikrokontrolerem Najpierw ostrzeżenie: Nie wolno łączyć bezpośrednio mikrokontrolera z gniazdem RS-232 w PC. Dlaczego? Otóż RS-232 przesyła dane za pomocą napięć ±11V. Procesory nie tolerują takich napięć. Więc należy zapamiętać, że nie wolno podłączać bezpośrednio RS-232 do naszego układu. Procesory ARM tolerują napięcia od 0V do 3.3V, więc podłączenie 11V mogłoby nasz układ uszkodzić. Aby temu zapobiec potrzebujemy tzw. konwertera napięć. Jest to specjalny układ, który napięcie -11V zamieni na 3.3V, a +11V na 0V. Na rynku dostępnych jest wiele tego typu układów, chociażby popularny max232. Podłączamy więc układ następująco: W naszym przypadku płytka ZL1ARM jest już wyposażona w odpowiedni konwerter napięć. Warto jednak pamiętać o odpowiednim podłączeniu, gdy będziemy chcieli budować własne układy. Płytka ewaluacyjna wyposażona jest w dwa gniazda RS-232, oznaczone COM0 oraz COM1. Jeden układ MAX232 wystarcza do konwersji napięć dla obu gniazd, a nasz układ LPC2114 wyposażony jest w dwa sprzętowe interfejsy zgodne ze standardem RS-232. Interfejsy te nazywane są odpowiednio UART0 oraz UART1. Interfejs UART0 połączony jest z gniazdem COM0, natomiast UART1 z COM1. Dotychczas już wykorzystywaliśmy łącze COM0 (UART0) do programowania procesora. Dodatkowe układy umieszczone na płytce ewaluacyjnej pozwalają na łatwe programowanie (zapewniają reset oraz uruchomienie bootladera). Wrócimy do nich później. Ponieważ COM0 jest zajęty przez programator, na początek wykorzystamy COM1 do komunikacji z komputerem PC. Łączymy wyjście COM1 naszej płytki z wolnym portem COM komputera. Ja wykorzystam przejściówkę USB<->RS232 ponieważ mój laptop nie posiada gniazda RS-232. Prędkość transmisji i format danych Łącze RS-232 pozwala na przesyłanie danych z różnymi prędkościami oraz w różnej postaci danych. Zastosujemy popularny format, czyli: 8 bitów danych, 1 bit stopu, brak kontroli parzystości oraz transmisji. Prędkość możemy ustawić dość dowolnie, zaczniemy od 9600 kbps, możemy zmienić na 115200 kbps jeśli chcemy szybciej przesyłać dane. Wysyłanie danych Na początek zdefiniujemy stałą, ustalającą prędkość transmisji: #define BAUDRATE 9600 Aby zmienić prędkość transmisji wystarczy przypisać jej inną wartość. Do rejestrów będziemy musieli wpisać wartość równą prędkości zegara peryferiów (pclk) podzielonej przez prędkość transmisji pomnożoną przez 16. Jeśli to zawiłe, wystarczy napisać: #define BAUDRATEDIVISOR (15000000/(BAUDRATE*16)) Wartość pclk wynosząca 15000000 (15MHz) pojawiła się w części poświęconej zegarom. Teraz musimy wpisać wartości konfiguracyjne do odpowiednich rejestrów. Więcej informacji jak zwykle znajdziemy w dokumentacji procesora: void uart1_init(void) { PCB_PINSEL0 |= 0x00010000; PCB_PINSEL0 |= 0x00040000; UART1_FCR = 1; //Set baudrate UART1_LCR |= 0x80; // DLAB = 1; UART1_DLL = BAUDRATEDIVISOR & 0x00ff; UART1_DLM = (BAUDRATEDIVISOR >> 8) & 0x00ff; UART1_LCR &= ~0x80; // DLAB = 0; //Set mode UART1_LCR = 0x03; //8 bit word length, 1 stop bit, No parity } Rejestry PINSEL odpowiadają za funkcję pełnioną przez dane wyprowadzenie. Domyślnie (czyli po resecie procesora) linie pracują jako wejścia-wyjścia, za pomocą podanego przypisania linia P0.8 będzie działać jako nadawanie (TxD), a P0.9 jako odbieranie (RxD) danych przez UART1. Następne instrukcje ustawiają prędkość oraz tryb transmisji. Gdy UART jest już skonfigurowany możemy zacząć wysyłać przez niego dane. void uart1_send_byte(unsigned char byte) { while(!(UART1_LSR & 0x20)); UART1_THR = byte; } Funkcja czeka najpierw na koniec poprzedniej transmisji (o ile trwała), po czym zapisuje do bufora kolejny bajt. Za cało transmisję odpowiada sprzęt. Będziemy wysyłać napisy, więc przygotujemy jeszcze jedną funkcję: void uart1_send(const char *s) { while (*s) { uart1_send_byte(*s); s++; } } Pozwoli ona na wysłanie całego napisu. Teraz możemy uruchomić program program17.zip i zobaczyć rezultat. Na PC powinniśmy uzyskać komunikat „Hello world!”. Kod programu jest bardzo krótki: int main(void) { pll_init(); timer0_init(); uart1_init(); while (1) { uart1_send("Hello world!!!\r\n"); } } Warto przy okazji zwrócić uwagę na program obsługujący port RS-232. Nie wszystkie działają równie dobrze. Polecam putty, dostępny za darmo pod adresem: http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html Rezultat działania programu widać poniżej: Komunikacja dwukierunkowa Skoro umiemy już wysyłać dane, czas spróbować dane odbierać. Poniższa funkcja będzie odpowiedzialna za odczyt danych z UART1 (COM1): unsigned char uart1_recv(void) { if ((UART1_LSR & 0x01)==0) return 0; return UART1_RBR; } W pierwszej linii sprawdzamy, czy są jakieś odebrane dane. Procesor LPC2114 ma wbudowany bufor dla odbieranych i wysyłanych danych o pojemności 16 bajtów. Dzięki temu nawet bez obsługi przerwań nasz program może działać całkiem sprawnie. Jeśli bufor odbiorczy jest pusty zwracamy 0. Jest to informacja dla programu głównego, że chwilowo brak danych. W przeciwnym przypadku odczytujemy daną z bufora i zwracamy jako wynik funkcji. Przykładowy program będzie odczytywał komendy 'a', 'w', 'd' oraz wyświetlał komunikat o wybranym kierunku jazdy robota. Oczywiście poza wysyłaniem komunikatu, należałoby odpowiednio wysterować silniki. while (1) { c = uart1_recv(); switch (c) { case 'a': uart1_send("a - Jazda w lewo\r\n"); break; case 'w': uart1_send("w - Jazda w prawo\r\n"); break; case 'd': uart1_send("d -Jazda prosto\r\n"); break; case 0: break; default: uart1_send("Nieznane polecenie\r\n"); break; } } W pliku Program18.zip znajdziemy kompletny kod przykładu. Poniżej rezultat działania: Program18.zip Program17.zip
  11. Dla częstotliwości 868MHz antena, tzw. ćwierćfalówka powinna mieć długość ok. 8,5cm. Czyli trzeba przylutować przewód o właśnie takiej długości. Ciężko mi jest powiedzieć o jakim konkretnie przewodzie mówisz, ale postaraj się użyć w miarę solidny.
  12. Szkoda, że pisząc o liczbach losowych autor nic nie wspomniał o matematyce - rachunku prawdopodobieństwa i statystyce. Warto wspomnieć jakie cechy powinien mieć dobry generator liczb. Nie każde źródło liczb pozornie losowych spełnia wymogi generatora. Np. wciskanie jednego przycisku wcale nie jest tak bardzo losowe - ludzie mają dość przewidywalny refleks i rozkład prawdopodobieństwa wcale nie jest jednostajny. Nawet dodawanie liczb "modulo" należałoby podeprzeć pewną dawką matematyki. Wybór podstawy dla działań modulo ma znaczenie. Przykładowo wybranie naturalnej dla timera i informatyki liczby 256 jest bardzo złym pomysłem. Podstawa działań modulo powinna być liczbą pierwszą - tego autor nie wspomniał, ani tym bardziej nie napisał dlaczego.
  13. Płytka była projektowana pod CC1000, ale później znalazłem inne moduły. Stąd pozostałe były podpinane "na pająka". Dokładniej na kynar-ek. Podłączenia są zdefiniowane w kodzie źródłowym: #define PORT_SEL PORTB #define PORT_SDI PORTD #define PORT_SCK PORTD #define PORT_SDO PORTB #define RFXX_SCK 6 #define RFXX_SDO 0 #define RFXX_SDI 7 #define RFXX_SEL 1 Nie wykorzystywałem sprzętowego SPI, więc nie było większej różnicy pod które piny I/O podłączyć. Wszystko i tak jest robione programowo.
  14. Gdy hamujesz silniki wzrasta płynący przez nie prąd. Często powoduje to obniżenie napięcia na procesorze i w efekcie jego reset albo zawieszenie. Musiałbyś wysłać schemat robota, ciężko coś doradzać bez tego.
  15. Prawdopodobnie problemem jest zasilanie. Dodaj kondensatory, powinno pomóc.
  16. Polecenia do BTM muszą się kończyć znakiem końca linii (CR), w C wystarczy wysłać \r. Bascoma nie znam, ale może jest coś jak Println, czy printline? [ Dodano: 27 Sie 10 01:57 ] może zadziała: Print "ATN?" ; Chr(13) ;
  17. Wniosek taki, że masz źle ustawioną częstotliwość pracy procesora. Działa 8x wolniej niż zakładasz. Czyli nie jak masz w kodzie 8Mhz, ale 1Mhz $crystal = 8000000 Spróbuj na początek zmienić kod na: $crystal = 1000000 A najlepiej ustaw odpowiednio fuse-bity.
  18. Moim zdaniem FT232 nie trzeba przeprogramowywać - najczęściej domyślne ustawienia pracują w pełni poprawnie. Spróbuj użyć innego programu do obsługi COM-a. U mnie pod Termit-em też nic nie działa, a putty chodzi bez problemu. http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
  19. Przejściówka powinna działać. Nie używałem tego konkretnie modelu, ale mam ten sam chip, więc na 99% wszystko będzie ok.
  20. Szczerze mówiąc to sam nie wiem co się stało. Robot stał spokojnie w pokoju, włączniki od płyty AVR oraz ARM9 były wyłączone. Nagle pojawił się dym. Możliwe że było spięcie przed włącznikami płytek. Ja bardziej podejrzewam, że luty płytki AVR przebiły obudowę akumulatora. W sumie nic się nie stało, ale przestrzegam przed używaniem li-pol - trzeba być baaaardzo ostrożnym.
  21. Jak chodzi o składową Y w modelu YUV to zdjęcia czarno-białe na dole artykułu powstały przez przypisanie do wszystkich składowych RGB wartości Y. Dla linefollowera myślę że wystarczyłoby to w zupełności. Jak chodzi o światłoluba to pewnie też, chociaż można byłoby dodać filtr na U-V, żeby wyodrębnić tylko interesujący nas kolor. Przedstawiłem algorytm przeliczania z YUV do RGB z kilku powodów. Po pierwsze chciałem sprawdzić, czy dobrze odczytuję dane z kamerki. Po drugie poprzednia wersja miała algorytm JPEG->RGB->analiza, chciałem porównać prędkość działania z przetwarzaniem YUV->RGB->analiza oraz samym przetwarzaniem obrazu na podstawie składowej Y. Jak widać ta kamerka pozwala na dużo szybsze działanie, chociaż szkoda że na razie nie mam na czym przetestować w pełni autonomicznej wersji robota. [ Dodano: 22 Sie 10 03:34 ] Temperatura była na tyle duża, że miedziane przewody popaliło. Serwa uległy stopieniu, w obudowach porobiły się dziury. Nawet sharp uległ stopieniu - tego mi najbardziej szkoda. Ogólnie cały robocik trafił do śmieci... Teraz zastanawiam się czym go zastąpić.
  22. Logitech-a nie polecam. Mam chyba właśnie C200 - na obudowie nie ma symbolu, ale kupowałem najtańszą. Główna wada to przesyłanie tylko i wyłącznie w formacie JPEG. Dekodowanie tego zajmuje wieki. Zaraz dopiszę do artykułu rezultat testu innej kamerki - jest dużo lepiej.
  23. Na razie największym problemem jest dekodowanie jpeg-ów. Powoduje bardzo duże opóźnienia. Dzisiaj kupiłem inną kamerkę. Na pudełku ma napisane, że obsługuje RGB24. Co ciekawe wcale nie obsługuje... Zamiast tego przesyła YUYV. Rozpoznawanie jasności powinno być więc łatwiejsze niż w RGB. A co najważniejsze obraz nie jest skompresowany. Tylko te ilości danych do przetworzenia... Bufor obrazu dla 640x480 to 600kB. Obraz pobieram w 320x240, ale to nadal 150kB na ramkę.
  24. Próbowałem zmusić kamerkę do generowania strumienia we wszystkich możliwych formatach - RGB, YUV, GRAY itd. Niestety zawsze wysyłany jest JPEG. Wydaje mi się, że to efekt wykorzystania pierwszej lepszej (najtańszej) kamerki jaką mieli w sklepie. Na przyszłość trzeba wybrać kamerkę, która: 1) obsługuje nieskompresowane dane 2) są do niej moduły v4l Co do wykrywania to liczę jasność 3 obszarów - po lewej, środek i po prawej. Następnie robot stara się skierować w tę stronę, gdzie jest najjaśniej. W teorii i na testowych obrazach wszystko działało pięknie, natomiast sam robot zachowywał się bardzo kiepsko. Zamiast jechać do światła wolał np. telewizor w sąsiednim pokoju. Lepiej byłoby wykrywać coś bardziej charakterystycznego - np. plamkę lasera. Niestety nie mam takiego, ale pewnie dałoby dużo lepsze efekty. Najpierw filtr na kolor czerwony, później wyszukiwanie. Ogólnie temat jest dość trudny, najlepiej byłoby przekompilować OpenCV na ARM i zacząć zabawę z algorytmem.
  25. Może po prostu użyj 74ac240 zamiast szukać odpowiednika? Układ można kupić za 61gr tutaj: http://sklep.slawmir.com.pl/product_info.php?products_id=17078
×
×
  • Utwórz nowe...