Skocz do zawartości

Elvis

Użytkownicy
  • Zawartość

    2603
  • Rejestracja

  • Ostatnio

  • Wygrane dni

    191

Wszystko napisane przez Elvis

  1. Co do obciążenia, to też się ostatnio nad tym zastanawiałem. A może obciążyć drugim silnikiem? Drugi silnik potraktować jako prądnicę, zewrzeć rezystorem...
  2. Model w sumie podobny. Natomiast sterowanie krokowymi nie zawsze jest takie proste. Przykładowo podanie od razu 100% wypełnienia generuje dużo drgań oraz co gorsza jest za głośne. Stąd sterowanie mikrokrokowe, albo jak w przypadku mojego urządzenia - modulowanie obwiedni prądu. Wykonywanie kroku powoli narastającym prądem, a następnie odcinanie prądu między krokami dla oszczędzania energii. Natomiast faktycznie w silniku DC nie następuje "ruszanie" i zatrzymywanie za każdym razem. Zastanawiam się nad czymś innym: silnik ma pewną indukcyjność, jeśli przełączanie jest poniżej stałej czasowej silnika - czy to nie sprawia problemu? Jeśli mamy wypełnienie >50%, czas na narastanie prądu jest dłuższy, ale właśnie mniejsze wypełnienie mogłoby powodować problemy. Stała czasowa to zmora silników krokowych, więc może to coś podobnego.
  3. W silnikach DC mam mniej doświadczenia, ale w przypadku krokowych właśnie prąd w peak-u ma znaczenie. Problemem jest przesunięcie rotora do nowego położenia. Takie "szarpnięcie" daje znacznie lepszy efekt, niż mały prąd przez dłuższy czas (czyli zachowanie energii). To trochę jak z pchaniem samochodu - jak już go ruszymy to dalej idzie łatwiej. Najtrudniej pokonać siłę statyczną. Myślę, że podobnie jest z silnikiem DC. Jeśli mamy wysoki peak prądu, silnik szarpie do przodu, a później siłą bezwładności kręci się do kolejnego "kroku". Jeśli mamy stały, ale mniejszy prąd nie jest w stanie nic zrobić. Zastanawiałem się nad prostym eksperymentem - wysterowaniem silnika za pomocą niewielkiego prądu, a następnie zmodulowaną obwiednią - taką jak w symulacji. Może w przyszłym tygodniu to sprawdzę i postaram się opisać wyniki.
  4. Chciałbym odnieść się do bardzo gorącej ostatnimi czasy dyskusji o częstotliwości PWM przeznaczonym do sterowania silnikiem. Dotychczasowa dyskusja skupiała się na tym, czy można sterować silnikiem przy użyciu wyższej (powiedzmy 20kHz), częstotliwości PWM. Drugi problem, to pytanie, czy silnik jest słabszy przy wyższej częstotliwości. Prosty sterownik Zacznijmy jednak od początku. Możemy oczywiście zacząć od pomiarów, ale czasem warto wykorzystać komputer, pakiet SPICE i najpierw nieco poznać problem. Największym plusem symulacji jest łatwość wykonywania pomiarów. Cena sondy prądowej do oscyloskopu potrafi przyprawić od ból głowy. Dzięki symulacji możemy poznać podstawowe wyniki bez inwestycji w sprzęt pomiarowy. Do symulacji wykorzystam bardzo prosty model silnika – cewkę połączono szeregowo z rezystancją. Sterownik też będzie bardzo uproszczony. Mogę tylko zdradzić, że bardzo podobny układ jest stosowany w produkowanych urządzeniach. Pierwsza przymiarka to sterowanie bezpośrednio tranzystorem MOS, załóżmy że przy użyciu bramki. Aby ją zasymulować dodamy do źródła sygnału szeregowo rezystor i sprawdzimy rezultat. Schemat układu: Rezystor R1 wraz z cewką L1 model silnika. Dioda D1 jest bardzo ważna – zamyka obwód w momencie gdy tranzystor M1 jest zamknięty. Tranzystor M1 to nasz sterownik silnika – gdy jest otwarty, przez silnik płynie prąd. PWM jest sterowany ze źródła V1, jak widać na rysunku mamy okres 100us, czyli częstotliwość 10kHz, wypełnienie 50%. Rezystor R2 jest dodany, aby zasymulować małą obciążalność bramki sterującej układem. Jak wiadomo tranzystory polowe mocy mają dużą pojemność bramki. Wraz z rezystancją R2 tworzy to filtr dolnoprzepustowy. Ze wzrostem częstotliwości taki filtr będzie powodował wolniejsze przełączanie tranzystora M1. Dzięki symulacji możemy sprawdzić jak taki układ będzie się zachowywał. Na początek R2=10k, f=10kHz. Prąd płynący przez silnik wygląda następująco: Teraz zwiększamy R2, powiedzmy do 47k. Rezultat – prąd silnika zmniejszył się znacznie. Z ok. 700mA do 100mA. Ten sam efekt uzyskamy zostawiając poprzednią wartość R2, a zwiększając częstotliwość. Dla R2=10k i częstotliwości f=20kHz, średni prąd wyniesie ok. 400mA. Łatwo się domyślić, że jednoczesne zwiększenie rezystancji R2 oraz częstotliwości jeszcze bardziej pogorszy sytuację. Wniosek 1 W przypadku prostego sterownika zwiększenie częstotliwości zmniejsza średni prąd płynący przez silnik. Filtr dolnoprzepustowy Skąd taki efekt? Jak już wspominałem, R2 wraz z kondensatorem w M1 tworzy filtr dolnoprzepustowy. Więcej przeczytamy chociażby na wikipedii: http://pl.wikipedia.org/wiki/Filtr_dolnoprzepustowy Skoro już używamy pakietu SPICE, możemy sprawdzić jak to działa. To co widzimy to fragment naszego poprzedniego układu. PWM i R2 jest bez zmian, ale zamiast tranzystora sterującego mamy kondensator. Na wykresie widzimy napięcie na C1, w odpowiedzi na prostokątne sterowanie z naszego PWM. Zzamiast pionowych zboczy, nasz sygnał został „wygładzony”. Tak właśnie wygląda sygnał sterujący naszego tranzystora. Na wykresie widać, że "zaokrąglenie" wykresu ma ok 30µs. Wynika to ze stałej czasowej naszego układu. Wynosi ona R2 C1, czyli 10k 1n = 10µ. Po tym czasie napięcie osiąga 63% w docelowej wartości. Po 3 razy dłuższym czasie już 95%. Ten czas zależy tylko od wartości R2 i C1, nie zależy od częstotliwości. Ale im wyższa częstotliwość, czym częściej występuje zbocze sygnału, które jest przez 30µs wygładzane. Oznacza to tym większe straty, im wyższa jest częstotliwość. Dlatego proste mostki działają z niskimi częstotliwościami – nawet jeśli przełączanie zajmuje kilka, czy kilkadziesiąt µs, jest to mało przy okresie PWM rzędu 5000µs (200Hz). Natomiast przy częstotliwości 10kHz (100µs), napięcie lewo zdąży narosnąć. A więc nasz tranzystor ledwo się otworzy, już musi się zamykać. Driver tranzystora MOS Jest to pierwszy problem, z którym konstruktorzy muszą sobie poradzić, jeśli chcą sterować silnik z wyższą częstotliwością. Na szczęście rozwiązanie jest proste. Dodamy wzmacniacz prądu, w ten sposób bardzo zmniejszymy wartość R2 i przyspieszymy przełączanie tranzystora kluczującego. Prosty układ (jak już pisałem stosowany przemysłowo) zobaczymy poniżej: Do poprzednio analizowanego układu dodane zostały tranzystory Q1 i Q2. Pracują one jako wzmacniacz prądu (wtórniki emiterowe). Napięcie nie jest wzmacniane, za to prąd, którym może być wysterowana bramka M1 jest znacznie większy. Sterowanie tranzystora MOS mocy Od razu małe wyjaśnienie. Pewnie niektórzy mogą być zaskoczeni - po co prąd do sterowania tranzystorem MOS. Oczywiście tranzystory MOS są sterowane napięciowo. W stanie statycznym prąd przez bramkę prawie nie płynie (poza minimalnym prądem upływu). Niestety zupełnie inaczej jest w stanie dynamicznym (podczas przełączania). Tranzystory mocy w technologii mos mają znaczną pojemność bramki. Oznacza to, że przełączenie wymaga dostarczenia ładunku, a podczas przełączania prąd płynie. Im większy prąd możemy dostarczyć tym szybciej (w pewnych granicach oczywiście) tranzystor się przełączy. Dzięki szybszemu przełączaniu możemy zwiększyć częstotliwość PWM. Częstotliwość akustyczna Teraz jak widać częstotliwości PWM rzędu 20kHz już nam nie straszne. Dlaczego 20kHz jest tak ważne? Jest to zakres poza akustyczną, co bywa bardzo ważne, chyba że lubimy piszczące układy. Nie chodzi tutaj tylko o płynność sterowania. Nikt chyba nie lubi urządzeń, które „piszczą” w zależności od prędkości obrotowej, czy jasności podświetlenia. Dodam tylko że nie sam silnik lubi wydawać paskudne dźwięki. Nawet niepozorny kondensator umie popsuć przyjemność korzystania z zaprojektowanego urządzenia. Natomiast wracając do silników – mając poprawiony układ sterowania, możemy sprawdzić, dla wyższych częstotliwości jego zachowanie: f=100kHz Jak widać nawet 100kHz jest możliwe do uzyskania. Z drugiej strony widać też pewny spadek sprawności, zamiast blisko 1A mamy 800mA. Mamy pierwszy problem rozwiązany. Odpowiedni sterownik potrafi sterować silnikiem nawet przy wysokiej częstotliwości PWM. Tani i prosty, tylko z niską częstotliwością. Współczynnik wypełnienia Teraz drugi problem – jak układ zachowa się przy małym wypełnieniu? Znowu z pomocą przychodzi nam symulacja. Zacznijmy od końca. Przyjmijmy wypełnienie 10%, i f=100kHz. Jak widać średni prąd to ok. 60mA. Zmniejszmy częstotliwość do 10kHz. Teraz prąd średni jest nieco większy – ok. 60 mA. Widać natomiast znacznie większą amplitudę. Zobaczmy co będzie przy f=1kHz. Teraz amplituda jest wręcz ogromna – prąd osiąga 720mA. Wartość średnia jest znacznie mniejsza. Dla niskich częstotliwości, prąd chwilowo osiąga znacznie większą wartość. W przypadku wyższych częstotliwości silnik pracuje równo i nie jest w stanie pokonać większego oporu. Jaki z tego wniosek? W przypadku większej częstotliwości moment mamy taki sam jak dla mniejszej. Ale musimy zastosować większe wypełnienie PWM, aby uzyskać ten sam moment. Podsumowanie * dla małych częstotliwości PWM wystarczy nam prosty sterownik silnika * wyższe częstotliwości dają bardziej rownomierną pracę silnika * częstotliwość poniżej 20kHz może powodować efekty akustyczne * im wyższa częstotliwość tym sterownie silnikiem jest trudniejsze Podsumowanie 2 Urządzenia które dość dobrze znam od ponad 10 lat pracują z silnikiem DC sterowanym z PWM o częstotliwości ok. 35kHz. Zapewniam, że jest to możliwe. Natomiast jest ogólną zasadą w elektronice, że im wyższa częstotliwość, tym trudniejszy jest układ. Dyskusja na forum Moim zdaniem w burzliwej dyskusji wszyscy mają (trochę) racji. Silnik tak samo sterowany (prosty sterownik, stałe wypełnienie PWM), zmniejsza moment ze wzrostem częstotliwości. Z drugiej strony można, a nawet powinno się konstruować układy na wyższą częstotliwość PWM. Wszystko zależy od projektu (i trochę od umiejętności). W chińskiej wkrętarce w zupełności wystarczy 200Hz. W innym układzie 40kHz może być za mało. Załączniki W załącznikach przesyłam pliki wykorzystane do symulacji. Pakiet LTSpice jest dostępny za darmo pod adresem: http://www.linear.com/designtools/software/
  5. Moim zdaniem prawda jest jak zwykle po środku. Co ciekawe obaj macie rację, a jednocześnie popełniacie błąd w procedurze pomiarowej. Zna ktoś indukcyjność silników pololu? Wolałbym tłumaczyć moje zdanie na konkretnych danych.
  6. Jeśli miałoby uszkodzić, to jest jeszcze jedna opcja - można dać oddzielny stabilizator dla serwa. Zawsze mniej problemów niż dodatkowy akumulator.
  7. Przed stabilizatorem i kondensatorami wejściowymi daj jeszcze diodę. Jak silniki będą powodowały spadki napięcia, stabilizator jeszcze chwilę "pociągnie" na energii zgromadzonej w kondensatorach. [ Dodano: 22-01-2012, 12:35 ] Poza tym radziłbym serwo zasilać bezpośrednio z akumulatora. Po pierwsze mniej obciążysz stabilizator, po drugie w serwo też jest silnik, więc i zakłócenia. [ Dodano: 22-01-2012, 12:38 ] I jeszcze jedno - prowadzenie masy. Najlepiej dla silnika poprowadzić oddzielną masę. Tzn. przy wejściu z akumulatora rozdzielić masę dla układów mocy i procesora.
  8. Jak chodzi o dostępność układów to polecam spróbować u dystrybutora: http://www.gamma.pl/ Na darmowe próbki też jest szansa.
  9. Jeśli interesują Cię większe ilości, to nie ma problemu. Zamawiasz partię 3V i po sprawie. Mogę polecić wyświetlacze Ampire: http://ampire.com.tw/en/p1-product.asp Dystrybutorem jest Gamma: http://www.gamma.pl/katalog-produktow/wyswietlacze/znakowe.html Tylko najpierw sprawdź, czy 3V wersja Ci odpowiada. Moim zdaniem kontrast jest trochę gorszy niż 5V.
  10. Nie wszystkie wyświetlacze wymagają napięcia 5V. Niektóre mają wbudowaną przetwornicę. Zobacz np. na stronie farnella. Ceny są znaczne, ale jest trochę wyświetlaczy na 3V. [ Dodano: 14-12-2011, 21:50 ] Przykładowy wyświetlacz na 3V: http://pl.farnell.com/fordata/fdcc1602l-flyybw-91le/disp-lcd-16x2-3v-g-bl/dp/1847940
  11. Ja bym radził odczytać cały scratchpad z DS1820 i sprawdził CRC. Z tymi czujnikami wcale nie tak łatwo się dogadać. Możliwe że błąd jest w samej transmisji po 1-wire. Możesz też spróbować zmienić temp0, temp1 z char na coś większego. Możliwe, że kompilator źle rozumie: temp=(float)(temp1+(temp2*256))/16;
  12. Na AVR można zmienić bez problemu. Po stronie PC odbieraj normalnie, jako 8 bitowe dane. Można też spróbować innego terminala po stronie PC. Polecam putty: http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html A swoją drogą - jeśli komunikacja PC<->moduł i AVR<->moduł działa poprawnie to trzeba tylko wysłać ramkę konfigurującą prędkość 40000 z obu urządzeń.
  13. Moim zdaniem problem jest w niedokładności zegarów. Bit stop-u jest przez odbiornik interpretowany jako najwyższy bit i stąd problem. Proponuję taki eksperyment: zmień format danych na 9 bitów danych, 1 bit stopu i prześlij wartość 0x43.
  14. Ja też widziałem na własne oczy jak takie błędy wyglądają. Na labkach tego nie przerabiałem, za to w pracy wielokrotnie. Oczywiście, że enkodery są wykorzystywane, ale nie są takie proste w użyciu jak mogą się wydawać. Zapewniam, że błędy będą dużo większe niż +- jedna podziałka. Ale to trzeba "na własnej skórze" doświadczyć, żeby uwierzyć. Jako jedno ze źródeł problemów polecam sprawdzić co dzieje się podczas drgania - jeśli tarcza enkodera zatrzyma się na granicy między poziomami odczytu. Jeśli do tego dodamy problem zmiany kierunku ruchu, to robi się bardzo wesoło. Główna wada jest taka, że jak już raz "zgubimy" krok enkodera, to nie tylko o tym nie wiem, ale kolejne gubienia mogą się dodawać do naszego błędu. Stąd po pewnym czasie działania błędy mogą być znaczne.
  15. W przypadku enkodera inkrementalnego błędy będą się kumulować. Konieczne więc byłoby dodanie układu zerowania położenie i powrót to takiego miejsca co pewien czas. Potencjometr nie ma takiej wady, działa jak enkoder absolutny. A co do dokładności to głównie zależy od jakości potencjometru oraz jakości przetwarzania sygnału. Jeśli po każdym pomiarze układ wraca do poziomu "zerowego" i jesteś w stanie łatwo dodać układ zerowania, to enkoder sprawdzi się bardzo dobrze. Natomiast jeśli układ ma się np. wychylić, a później przez pewien czas wykonywać ruchy bez powrotu do zera, to polecam potencjometr. Największą wadą potencjometru jest jego zużywanie się. Z czasem jego parametry będą ulegały pogorszeniu.
  16. Poprzednia część kursu. [Kurs] Programowanie ARM LPC1114 cz.7 - Czujniki odbiciowe W poprzednich częściach kursu poznaliśmy już możliwości procesora niezbędne do zbudowania prostego robota. Potrafimy sterować silnikami, odczytywać poziom napięcia za pomocą przetwornika analogowo-cyfrowego. Tym razem wykorzystamy poznaną wiedzę do wykrywania linii, które jest podstawą do budowy naszego linefollowera. W pierwszej części kursu pojawił się schemat płytki z czujnikami odbiciowymi. Zastosowałem czujniki TCRT5000. Warto w kilku słowach omówić ich działanie. Każdy czujnik składa się z 2 elementów: 1) diody oświetlającej podłoże 2) fototranzystora wykrywającego światło odbite od podłoża Fotodioda i fototranzystor pracuje w podczerwieni, jeśli chcemy sprawdzić, czy dioda działa prawidłowo można wykorzystać aparat bez filtru. Większość telefonów wyposażonych jest właśnie w takie aparaty. Niestety czujniki użyte w moim robocie zostały wymontowane z poprzednich konstrukcji. Jak widać działają nie najlepiej. Zdjęcie od razu ujawnia, które czujniki na pewno nie będą działały zadowalająco. Dioda zasilana jest przez rezystor i układ nie wymaga chyba omówienia. Warto za to chwilę popatrzeć na schemat podłączenia fototranzystora. Przez fototranzystor płynie prąd zależny jego oświetlenia. Nas interesuje napięcie w punkcie OPTO1 (jest ono podawane na wejście przetwornika A/C). Napięcie OPTO1 wynosi VCC minus spadek na rezystorze R2. Czyli Uopto1 = Vcc - U2. Z prawa Ohma spadek napięcia na rezystorze R2 wynosi: U2 = R2 * i, gdzie i to prąd płynący przez rezystor. Jednocześnie prąd i jest to prąd płynący przez fototranzystor naszego czujnika. Gdy fototranzystor nie jest oświetlany, płynie przez niego bardzo mały prąd, więc i spadek napięcia na rezystorze R2 jest mały. Oznacza to, że poziom napięcia w punkcie OPTO1 jest prawie taki jak VCC. Gdy oświetlimy fototranzystor, zacznie przez niego płynąć większy prąd. Spowoduje to zwiększenie spadku napięcia na R2, a w rezultacie zmniejszenie napięcia na OPTO1. Czyli zależność jest taka: • fototranzystor oświetlony - niskie napięcie na OPTO1 • fototranzystor nieoświetlony - wysokie napięcie na OPTO1 Jak będzie oświetlany nasz fototranzystor? Przez światło diody odbite od podłoża. Więc zależność będzie następująca: • jasne podłoże - niskie napięcie na OPTO1 • ciemne podłoże (linia) - wysokie napięcie na OPTO1 Jak pamiętamy z poprzedniej części, napięcie na przetworniku A/C zamieniane jest na liczbę z zakresu 0-1023. Im wyższe napięcie tym wyższa wartość odczytana przez czujnik. Na podstawie tego co ustaliliśmy oznacza to, że niskie wartości - odpowiadają jasnemu podłożu. Wysokie wartości z przetwornika - ciemne podłoże / linię. Czas sprawdzić, czy wszystko działa prawidłowo. Podłączamy fototranzystory do wejść procesora. Ja wybrałem 4 działające czujniki i 4 przetworniki. Niestety podczas wcześniejszych prac uszkodziłem procesor, więc nie wszystkie przetworniki działają prawidłowo. Na szczęście dostępne jest 8 wejść, udało się wśród nich znaleźć 4 sprawne. Wgrywamy program18.zip do procesora (jest to właściwie poprzedni przykład, który odczytuje tylko wybrane kanały ADC). Poniżej widzimy rezultat dla robota nad białą kartką: Porównajmy wyniki z czarną kartką: I jeszcze biała kartka z czarną linią pod czujnikiem AD4: (warto zwrócić uwagę, że ta kartka jest nieco „bielsza” niż użyta poprzenio). Wyniki są zgodne z naszymi oczekiwaniami - im ciemniejsze tło, tym wyższe odczyty. Właściwie w tej chwili moglibyśmy już napisać program sterowania robotem. Jednak postaramy się wykonać jeszcze jedną czynność. Jak widać moje czujniki są bardzo kiepskiej jakości - szczególnie AD1 daje inne odczyty niż pozostałe. Co więcej odczyty będą zależały od koloru podłoża / warunków oświetlenia. Aby pozbyć się wszystkich tych niedoskonałości, przygotujemy program do kalibracji czujników. Kalibracja czujników Kalibracja będzie przebiegać następująco: Dla każdego czujnika będziemy zapisywać najmniejszą i największą wartość odczytaną przez czujnik. W tym czasie czujniki powinny zostać przesunięte nad podłożem i linią. Najmniejsza wartość będzie odpowiadała barwie podłoża, najwyższa - linii. Programowo będziemy skalować odczyty do wspólnego przedziału 0-100. Czyli odczyt po przeskalowaniu 0 będzie oznaczał czyste tło, 100 czarną linię. Pośrednie odczyty pozwolą na wykrywanie częściowego przesłonięcia linii. Omawiany przykład znajdziemy w pliku program19.zip. Wykorzystywane będą 4 czujniki, będą im odpowiadały indeksy od 1 do 4. Dodatkowo dodane zostaną 2 skrajne, udawane czujniki tzw. atrapy. Będą one zawsze zawierały odczyt 0 - czyli podłoże. Dodanie ich ułatwi napisanie algorytmu sterowania robotem. Na początek deklarujemy 4 tablice: int32_t opto_min[6]; int32_t opto_max[6]; int32_t opto_value[6]; int32_t opto_scaled[6]; W tablicach opto_min[] oraz opto_max[] będziemy zapisywać najniższe i najwyższe odczyty danego czujnika. Tablica opto_value[] będzie przechowywać ostatni odczyt z przetwornika A/C. Natomiast tablica opto_scaled[] będzie zawierała odczyty z czujników po przeliczeniu na wartości 0-100. Zdefiniujemy też kilka funkcji pomocniczych. Funkcja opto_read() odczytuje wartości z przetworników (i zapisuje w opto_value[]). Następnie wywołujemy opto_scale(), która przelicza odczytane ostatnio wartości i zapisuje w tablicy opto_scaled[]. Zanim będziemy mogli używać funkcji opto_scale() musimy wykonać kalibrację. Do kalibracji przygotujemy funkcję calib_update() - zaktualizuje ona wpisy w tablicach opto_min[] oraz opto_max[]. Pozostaje jeszcze pytanie, jak przesuwać czujniki podczas kalibracji. Można to oczywiście wykonać ręcznie, ale nie o to chodzi podczas budowy robota. Wykonamy więc obrót w lewą i prawą stronę, tak aby pod czujnikami znalazła się linia trasy. Niestety brak mostka H nie daje możliwości obrotu w miejscu. Mimo wszystko kalibrację można wykonać. Funkcja opto_calib() wykona za nas kalibrację. Najpierw obróci robota w prawo, następnie w lewo i znowu w prawo, aby wrócić do pierwotnej pozycji. Po kalibracji przeskalowane odczyty wyglądają następująco: Jak widać linia znajduje się pod czujnikiem 3 i częściowo 2. Dzięki wykorzystaniu przetworników A/C dostajemy nie tylko robota, który dopasowuje się do warunków (autokalibracja), ale jeszcze możemy wykrywać częściowe najechanie czujnika na linię. program18.zip program19.zip
  17. Zobacz układ L297. Zawiera sterownik do L298 i umożliwia sterowanie prądowe, czyli właśnie zadanie jaki prąd maksymalnie może przez silniki płynąć.
  18. Poprzednia część kursu. [Kurs] Programowanie ARM LPC1114 cz.6 - ADC W tym odcinku zajmiemy się działaniem przetwornika analogowo-cyfrowego (ang. Analog-to-Digital Converter). Mikrokontroler LPC1114 jest wyposażony w jeden, 10-bitowy przetwornik. Wejście przetwornika podłączone jest przez multiplekser do 8 wejść procesora. Możemy wybrać, sygnał z którego wejścia chcemy odczytać. • AD0 - P0.11 • AD1 - P1.0 • AD2 - P1.1 • AD3 - P1.2 • AD4 - P1.3 • AD5 - P1.4 • AD6 - P1.10 • AD7 - P1.11 Na płytce ZL32ARM znajdziemy potencjometr P1 podłączony do pinu P0.11, czyli kanału AD0 przetwornika A/C. Obracając potencjometrem możemy zmieniać napięcie podawane na wejście przetwornika. Przetwornik zmienia napięcie na liczby. Jak wiemy przetwornik jest 10-bitowy. Oznacza to, że pozwala na odczyt 2^10, czyli 1024 poziomów napięcia. Są one reprezentowane jako liczby od 0, do 1023. Jeśli na wejście przetwornika podamy napięcie 0V, odczytamy wartość 0, gdy napięcie 3.3V, odczytamy 1023. Ogólnie przeliczenie z napięcia, na wartość wyraża wzór: ADC = 1023 * Vad / 3.3 Podobnie, mając odczytaną wartość z przetwornika, możemy obliczyć napięcie na przetworniku: Vad = 3.3 * ADC / 1023 Gdy znamy podstawy działania przetwornika, czas napisać program odczytujący wartość z przetwornika. W pliku program16.zip znajdziemy omawiany program. Opis zaczniemy niejako od końca. Mamy dwie funkcje: adc_init() adc_get(int channel) Pierwszą należy wywołać raz na początku programu. Druga funkcja odczytuje wartość z przetwornika o podanym numerze. Wykorzystamy wcześniej podane układy peryferyjne, aby w zależności od wartości z przetwornika: • regulować częstotliwość migania diody LED • wysyłać odczytaną wartość z przetwornika przez RS-232 • sterować prędkością silnika zależnie od położenia potencjometru Pętla główna programu wygląda następująco: while(1) { val = adc_get(0); uart_send_int(val); uart_send("\n"); if (val>=0) { pwm_set(val/10, 100-val/10); GPIOClear(LED_1); delay(val/50); GPIOSet(LED_1); delay(20-val/50); } } Funkcja uart_send_int wysyła wartość liczbową (odczytaną z przetwornika) przez RS-232. Funkcja pwm_set służy do sterowania prędkością silników robota. Opóźnienia (funkcja delay) regulują częstotliwość migania diody. Program jak widać jest bardzo krótki, Poniżej rezultat działania: Teraz zajmijmy się funkcjami obsługującymi konwerter. • adc_init() Ta funkcja ma dwa zadania. Po pierwsze musi uruchomić przetwornik (domyślnie wyłączony, aby oszczędzać prąd). Realizują to następujące instrukcje: LPC_SYSCON->PDRUNCFG &= ~0x0010; LPC_SYSCON->SYSAHBCLKCTRL |= 0x2000; Kolejnym krokiem jest ustawienie funkcji pinów przetwornika. Na razie wykorzystamy tylko kanał AD0: LPC_IOCON->R_PIO0_11 = 0x02; • adc_get Przed konwersją ustawiamy parametry pracy przetwornika. Realizuje to linia: LPC_ADC->CR = ADCR_CLKDIV|(1<<channel); channel to numer kanału, z którego będziemy odczytywać dane (u nas 0). Natomiast stała ADCR_CLKDIV określa dzielnik zegara dla przetwornika A/C. Procesor jak pamiętamy działa z częstotliwością 48MHz. Natomiast przetwornik wymaga zegara o częstotliwości co najwyżej 4.5MHz. Musimy więc podzielić częstotliwość zegara systemowego przez 11 (48MHz/11 = 4.36MHz). Możemy podać większą wartość dzielnika, natomiast należy unikać przekraczania częstotliwości 4.5MHz - może to spowodować błędne działanie przetwornika. Stała ADCR_CLKDIV zawiera wartość dzielnika pomniejszoną o 1. Chcemy używać dzielnik 11, więc definiujemy: #define ADCR_CLKDIV (10<<8) Dalej następuje uruchomienie konwertera: LPC_ADC->CR |= 0x01000000; Oczekiwanie na zakończenie konwersji: while (((val=LPC_ADC->GDR) & 0x80000000)==0); Na koniec wyłączenie konwertera i zapisanie wyniku: LPC_ADC->CR &= ~0x01000000; if ((val & 0x40000000)==0) { result = (val>>6) & 0x3ff; } Jeśli jest to nieco zawiłe, nie należy się poddawać, w przykładowych programach znajdziemy gotową funkcję obsługi konwertera. Więcej kanałów przetwornika Umiemy już odczytywać dane z kanału 0 (AD0), czas odczytać wszystkie 8 kanałów. Kolejny przykład znajdziemy w pliku program17.zip. Funkcje dotyczące przetwornika A/C zostały przeniesione do nowego modułu (pliki adc.h oraz adc.c). Tym razem wszystkie piny podłączone do konwertera są ustawiane jako wejścia przetwornika analogowo-cyfrowego: LPC_IOCON->R_PIO0_11 = 0x02; // P0.11 <- AD0 LPC_IOCON->R_PIO1_0 = 0x02; // P1.0 <- AD1 LPC_IOCON->R_PIO1_1 = 0x02; // P1.1 <- AD2 LPC_IOCON->R_PIO1_2 = 0x02; // P1.2 <- AD3 LPC_IOCON->SWDIO_PIO1_3 = 0x02; // P1.3 <- AD4 LPC_IOCON->PIO1_4 = 0x01; // P1.4 <- AD5 LPC_IOCON->PIO1_10 = 0x01; // P1.10 <- AD6 LPC_IOCON->PIO1_11 = 0x01; // P1.11 <- AD7 Ponieważ przesyłamy znacznie więcej danych przez RS-232, zwiększona została prędkość transmisji. Zamiast jak dotychczas 9600, dane wysyłane są z prędkością 115200. Poniżej widzimy rezultat działania programu: Odczyt z kanału AD0 możemy regulować potencjometrem, pozostałe wymagają podłączenia źródła sygnału. Ponieważ docelowym przykładem będzie robot, pozostałe wejścia zostaną podłączone do optoelementów. Napięcie na przetworniku będzie się zmieniało w zależności od koloru podłoża. program16.zip program17.zip
  19. zmień pętlę while na: while (1) { PORTB |= (1<<PB2); _delay_ms(2000); PORTB &= ~(1<<PB2); _delay_ms(2000); }
  20. Poprzednia część kursu. [Kurs] Programowanie ARM LPC1114 cz.5 - RS-232 W poprzedniej wersji kursu komunikacja przez RS-232 została opisana dla procesora LPC-2114. Nowy procesor działa bardzo podobnie i w artykule opiszę jedynie różnice między układami. Zachęcam, więc najpierw do przeczytania poprzedniego kursu: • tutaj znajdziemy opis komunikacji • biblioteka standardowa (printf) • bootloader Nowy procesor posiada jeden moduł UART, zamiast jak LPC2114 dwa. Pozwala to na obsługę jednego połączenia RS-232. Część o komunikacji poprzez RS232 prawie bez zmian odnosi się do nowego procesora. Biblioteka standardowa powoduje ogromne wydłużenie kodu, więc nie polecam jej stosowania. Niestety darmowy kompilator, jakim jest gcc nie najlepiej sobie z tym radzi. Odcinek o bootloaderze jest w pełni aktualny na nowym procesorze. Tutaj też znajdziemy bootloader, jego działanie jest identyczne jak poprzednio. Na początek inicjalizujemy moduł UART odpowiedzialny za komunikację przez RS-232. #define BAUDRATE 9600 #define BAUDRATEDIVISOR (48000000/(BAUDRATE*16)) void uart_init(void) { LPC_SYSCON->SYSAHBCLKCTRL |= 0x1000; LPC_IOCON->PIO1_6 = 0x01; LPC_IOCON->PIO1_7 = 0x01; LPC_UART->FCR = 0x07; LPC_UART->LCR = 0x80; // DLAB = 1; LPC_UART->DLL = BAUDRATEDIVISOR & 0x00ff; LPC_UART->DLM = (BAUDRATEDIVISOR >> 8) & 0x00ff; LPC_UART->LCR &= ~0x80; // DLAB = 0; //Set mode LPC_UART->LCR = 0x03; //8 bit word length, 1 stop bit, No parity } Jak widać kod jest właściwie identyczny jak poprzednio. W definicji stałej BAUDRATEDIVISOR zmieniona została częstotliwość zegara, tym razem wynosi ona 48MHz, zamiast 15MHz jak poprzednio. Poza tym dostęp do rejestrów odbywa się przez znane już nam wskaźniki. Inaczej ustawiamy też funkcję wyjść I/O. Zamiast rejestru PINSEL pojawia się kod: LPC_IOCON->PIO1_6 = 0x01; LPC_IOCON->PIO1_7 = 0x01; Nie powinno być zaskoczeniem, że funkcja wysyłająca dane jest również podobna do poprzedniej wersji: void uart_send_byte(const uint8_t byte) { while(!(LPC_UART->LSR & 0x20)); LPC_UART->THR = byte; } W pliku program13.zip znajdziemy przykładowy program. Program kompilujemy i wgrywamy do procesora jak zwykle. Niestety gdy go uruchomimy, pojawiają się problemy. Przyczyną jest znany nam z poprzedniej części bootloader. Linie RTS i DTR interfejsu RS-232 sterują resetem procesora oraz pinem uruchamiającym bootloader. W efekcie nasz program nie działa, gdy uruchamiamy terminal komunikacyjny. Musimy zmienić program do komunikacji na taki, który pozwoli nam na sterowanie liniami RTS oraz DTR. Polecam program Hercules, dostępny na stronie: http://www.hw-group.com/products/hercules/index_en.html Uruchamiamy program, wybieramy zakładkę „Serial”, a następnie w ramce po prawej stronie ustawiamy parametry komunikacji: • Name - nazwa portu do którego podłączony jest moduł • Baud - prędkość transmisji 9600 • Data size - 8 • Parity - none • Handshake - OFF • Mode - Free Następnie naciskamy przycisk „Open” i jeśli zostaną zaznaczone opcje „DTR” lub „RTS” to je wyłączamy: Teraz jak widać mamy działającą komunikację przez RS-232, a jednocześnie możemy programować układ. Wystarczy nacisnąć „Close” i za pomocą FlashMagic-a można wgrywać program. Postępowanie jest więc następujące: 1) zaprogramuje procesor programem FlashMagic 2) przełącz się na Hercules, naciśnij Open 3) gdy wykonasz testy, naciśnij Close 4) zmień kod programu, skompiluj nową wersję 5) przełącz się na FlashMagic i wróć do pkt.1 Mając więc 3 uruchomione programy (LPCExpresso, FlashMagic, Hercules) możemy zmieniać, wgrywać i testować komunikację przez RS-232. Kolejnym krokiem jest wydzielenie funkcji związanych z komunikacją do nowego modułu. W pliku program14.zip znajdziemy gotowy program. Czas wykorzystać zdobytą wiedzę do sterowania naszym robotem. Kod programu znajdziemy w pliku program15.zip. Sterowanie silnikiem zostało opisane w odcinku o PWM. Odbieranie danych realizuje funkcja: uint8_t uart_recv_byte(void) { while(!(LPC_UART->LSR & 0x01)); return LPC_UART->RBR; } Pętla główna programu wygląda następująco: while(1) { c = uart_recv_byte(); switch (c|32) { case 'w': pwm_set(100, 100); break; case 's': pwm_set(25, 25); break; case 'a': pwm_set(50, 0); break; case 'd': pwm_set(0, 50); break; default: pwm_set(0, 0); } uart_send_byte(c); } Jak widać jest to sterowanie robotem za pomocą znanej kombinacji znaków WSAD. Sztuczka w instrukcji switch (c|32) pozwala na ignorowanie wielkości znaków. Można wysyłać małe lub duże litery, aby sterować robotem. Mamy więc zdalnie sterowanego robota. Oczywiście jest to sterowanie przez RS-232, czyli kablowe. Możemy łatwo to zmienić stosując gotowy moduł radiowy, np. bluetooth. program13.zip program14.zip program15.zip
  21. Zobacz jeszcze raz, czy wszystko podłączyłeś jak w dokumentacji układu. Tak powinno wyglądać podłączenie: Datasheet jest tutaj: http://focus.ti.com/lit/ds/symlink/max232.pdf
  22. Jak chodzi o bibliotekę ST to ja za nią nie przepadam. Jest nieoptymalna, ale to jak każda biblioteka, nie można narzekać. Moim zdaniem jest brzydka - wypełnianie niekończących się struktur jest paskudne, ale to rzecz gustu. Natomiast tym co mnie do biblioteki zniechęciło to jej zmiany. Sam już to zobaczyłeś - masz przykład, a nie działa bo nowa wersja bibliteki... Ja interesowałem się STM32 już jakiś czas temu. Byłem niesamowicie zaskoczony, jak po może roku przerwy stare programy nie chciały się skompilować... ST przygotowało nową bibliotekę i musiałem się wszystkiego uczyć od nowa... Teraz mam uraz.
  23. No właśnie... Dlatego myślę, że warto poświęcić trochę czasu na poznanie TS - podobnie jak LPCExpresso bazuje na eclipse + gcc. Oczywiście komercyjne środowiska mają swoje zalety, ale cena jest nieco zaporowa...
  24. Przez 30 dni można używać "evaluation edition" - czyli pełna funkcjonalność. Po tym czasie zostaje tylko "Kickstart edition", z ograniczeniem do 32KB kodu. Poza tym jest jeszcze problem ew. "komercyjnego" wykorzystywania kompilatora. TS można pisać programy komercyjne, pod IAR najpierw musimy kupić licencję. Swoją drogą - ktoś wie ile taka licencja kosztuje?
  25. 30 dni, a później 32KB kodu... albo spooooory wydatek. Jak chodzi o TS to całkiem dobre środowisko, a nie bardzo rozumiem problem z SysTick. Wystarczy użyć SysTick_Config(), działa bez problemu.
×
×
  • Utwórz nowe...