Skocz do zawartości

Sokolsok

Users
  • Zawartość

    23
  • Rejestracja

  • Ostatnio

  • Wygrane dni

    1

Sokolsok zajął 1. miejsce w rankingu.
Data osiągnięcia: 31 marca 2012.

Treści użytkownika Sokolsok zdobyły tego dnia najwięcej polubień!

Informacje

  • Płeć
    Mężczyzna
  • Lokalizacja
    Gdańsk

Ostatnio na profilu byli

Blok z ostatnio odwiedzającymi jest wyłączony i nie jest wyświetlany innym użytkownikom.

Osiągnięcia użytkownika Sokolsok

Wynalazca

Wynalazca (6/19)

  • Za 5 postów
  • Młodszy Juror
  • Młodszy roboty
  • To już rok!
  • To już 5 lat!

Odznaki

7

Reputacja

  1. A czy nie prościej byłoby postawienie między obydwoma robotami jakiegoś sześcianu o odpowiedniej wielkości? Roboty wykrywając przed "nosem" przeszkodę by stały, po podniesieniu sześcianu przez sędziego roboty od razu (bez czekania 5 sekund) ruszają do ataku. Taka metoda byłaby chyba najprostsza, a zarazem najuczciwsza.
  2. Niestety mając dane wyłącznie z tych 4 czujników nie określi jednoznacznie położenia robota. Dla każdego przypadku będą 2 takie miejsca na dnie basenu. Potrzebna byłaby jeszcze wiedza o aktualnej orientacji. A do orientacji chyba można by użyć cyfrowego kompasu np. KMZ51 lub CMPS03. Nigdy ich nie używałem, ale nie wydaje mi się, że jest to problem.
  3. Tak naprawdę to nie jest Ci potrzebna dokładna orientacja robota. Potrzebna jest tylko wiedza czy znajduję się równolegle (nie licząc chwil, w których zawraca) do np. dłuższej ściany. Możesz uzyskać już za pomocą 2 czujników odległości (choć ja dla bezpieczeństwa użyłbym 4).
  4. Kluczowe pytanie. To ma być robot mobilny czy stacjonarny manipulator? Pomysł z kamerami jest dobry, można dzięki nim precyzyjnie wyznaczyć położenie zarówno robota jak i przedmiotów. Z mojego (niewielkiego, ale jednak) doświadczenia z obsługą w ten sposób kamerki, nawet monochromatycznej jest dużo bardziej skomplikowane, od obsługi całego szeregu czujników odległości. Jest to również zdecydowanie droższa sprawa. Do przetworzenia danych z 4 kamer w czasie rzeczywistym potrzebujesz średniej klasy PC. Chyba, że do dyspozycji masz takie kamerki w wbudowanym procesorem na pokładzie;) Do tego potrzebne jest również zewnętrzne oprogramowanie, które (raczej, ale pewien nie jestem) darmowe nie jest. Polecałbym zastosowanie czujników odległości umieszczonych przy samym chwytaku.
  5. Deklarujesz zmienne lokalnie, zadeklaruj je globalnie. A tak btw. na przyszłość wklejaj tu jaki błąd wyrzucił kompilator.
  6. Opisz trochę więcej środowisko pracy tego robota. Jeżeli ma to być jakaś otwarta, płaska przestrzeń a docelowe przedmioty ewidentnie będą się wyróżniać na podłożu (np. piłki tenisowe na korcie) to wystarczy zwykły czujnik odległości, czy to optyczny czy ultradźwiękowy nie ma większego znaczenia. Przeszukiwanie mogłoby polegać na obrocie całego robota (bądź samego czujnika) wokół własnej osi, do momentu wykrycie przeszkody. Ale jeżeli przedmiotami mają być jakieś konkretne elementy spośród innych elementów to myślę, że bez jakiegoś systemu wizyjnego się nie obejdzie.
  7. Nie tak działa czujnik. Na wejście TRIG podajesz impuls o szerokości co najmniej 10us, co inicjuje wykonanie pomiaru. Następnie nadajnik hc-sr04 wysyła 8 impulsów, które są odbierane przez (oczywiście) odbiornik czujnika. Na wyjściu ECHO otrzymujesz impuls który jest proporcjonalny do wykrytej odległości. I to właśnie czas trwania tego impulsu musisz zmierzyć. (to tak w skrócie) TCCR2 = (1<<WGM01)|(1<<CS21); //Ustawia timer2 w tryb CTC bez preskalera //Czestotliwość 16Mhz/1=16MHz //////Tu mam pierwszy problem, ponieważ program będzie chodził z wewnętrznym oscylatorem 8Mhz wiec ustawiłem bit w rejestrze TCCR2 na (1<<CS21) wg noty"clkT2S / 8 (preskaler)" --czy zrobiłem prawidłowo?////// ......... OCR2 = 0x10; //Górna wartość licznika wynosi 16 //Przerwania będą następować co 1us // /////Tutaj w OCR2 też chyba powinienem zmienić wartość skoro wprowadziłem zmiany w rejestrze TCCR2 z którym to jak się domyślam OCR2 ma być porównywany, jednak nie wiem jak to wyliczyć, czy powinienem zmienić wartość "0x10"??///// Pierwszy rejestr jak sam zauważyłeś służy do ustawienie preskalera (jak i również trybu działania) licznika czyli jeśli używasz 8 MHz i użyjesz preskalera 8 to licznik będzie miał "pojemność" 1MHz. (8MHz/8=1MHz). Rejestrze OCRn jest rejestrem porównania. Gdy aktualna wartość licznika (rejestr TCNTn) zrówna się z wartością w OCRn nastąpi przerwanie od przepełnienia. Czyli w przypadku Twojego kwarcu możesz ustawić preskaler na 1 i górną wartość na 8, lub preskaler na 8 i górną wartość na 1 - w obu przypadkach przerwanie będzie wywoływało się co 1us. Wszystkie kombinacje preskalerów i kwarców możesz sobie zobaczyć w moim pliku exelowym, który zrobiłem jak ja się tym bawiłem (załącznik). SREG = 0x80; ////po chłopsku jednym zdaniem proszę o wytłumaczenie mi do czego służy SREG i dlaczego przypisana jest mu akurat taka wartość 0x80? w nocie nie mogę się połapać//// 8 bit (I) tego rejestru gdy jest ustawiony globalnie zezwala na wszystkie przerwania. Możesz zamiennie używać sei(); A czemu 80? 80 szesnastkowo to 10000000 binarnie, a mi zależało żeby ustawić wyłącznie ten jeden bit. ISR(TIMER2_COMP_vect) { licznik++; ////domyślam się że muszę na początku zadeklarować zmienna licznik? /// } Tak, dobrze się domyślasz. (tą "flage" poniżej też) Są to makra ustawiające bądź zerujące dany bit: #define SetBit(reg, bit) ((reg) |= (0x01 << (bit))) // Ustawienie danego bitu w rejestrze #define ClrBit(reg, bit) ((reg) &= ~(0x01 << (bit))) // Wyzerowanie danego bitu w rejestrze //////EICRA ---- korzystam z atmegi 16 i tutaj też wyskakuje mi błąd ale domyślam się że poprostu u mnie ten rejestr się jakoś inaczej nazywa, czy wiecie jak?//// U Ciebie ten rejestr nazywa się MCUCR. Ps. To wszystko co to napisałem jest w dokumentacji, jesli chodzi o ATmege 16 masz nawet dokumentacje po polsku. tu Wystarczy trochę poszukać🙂 preskaler.xls
  8. mój kod obsługujący 3 takie czujniki (są komentarze więc chyba wszystko jasne powinno być): //F-cja inicjująca przerwania zawnętrzne i timer2 void InitInterrupt(void) { //PRZERWANIA ZEWNĘTRZNE DDRD = 0xf8; //PD0-PD2 - wejscie (Echo); PD3-PD5 - wyjścia(Trig) EICRA = 0x3f; //Przerwanie zostanie wywołane zboczem narastająym //na wejściach INT0, INT1, INT2 //TIMER2 TCNT2 = 0x00; //Zerowanie rejestru TCNT2 (Rejestr jednostki zegara) TCCR2 = (1<<WGM01)|(1<<CS00); //Ustawia timer2 w tryb CTC bez preskalera //Czestotliwość 16Mhz/1=16MHz OCR2 = 0x10; //Górna wartość licznika wynosi 16 //Przerwania będą następować co 1us SREG = 0x80; } //F-cja przerwania od Timera2 ISR(TIMER2_COMP_vect) { licznik++; } //F-cja przerwania zewnętrznego INT0 ISR(INT0_vect) { if(flaga==0) { TIMSK = (1<<OCIE2); //włącza Timer2 w trybie dopasowania (START) ClrBit(EIMSK, INT0); EICRA = 0x00; //Przerwanie zostanie wywołane zboczem opadającym EICRA = (1<<ISC01); //na wejściu INT0 SetBit(EIMSK, INT0); flaga=1; } else if(flaga==1) { TIMSK &=~(1<<OCIE2); //zatrzymuje Timer2 (STOP) ClrBit(EIMSK, INT0); EICRA = 0x00; //Przerwanie zostanie wywołane zboczem rosnącym EICRA = (1<<ISC01)|(1<<ISC00); //na wejściu INT0 SetBit(EIMSK, INT0); odl0=licznik; //Zapisuje wartość licznika do zmiennej "odl" odl0/=20; //oraz skaluje go licznik=0; //Zerowanie licznika flaga=0; } } //F-cja przerwania zewnętrznego INT1 ISR(INT1_vect) { if(flaga==0) { TIMSK = (1<<OCIE2); //włącza Timer2 w trybie dopasowania (START) ClrBit(EIMSK, INT1); EICRA = 0x00; //Przerwanie zostanie wywołane zboczem opadającym EICRA = (1<<ISC11); //na wejściu INT1 SetBit(EIMSK, INT1); flaga=1; } else if(flaga==1) { TIMSK &=~(1<<OCIE2); //zatrzymuje Timer2 (STOP) ClrBit(EIMSK, INT1); EICRA = 0x00; //Przerwanie zostanie wywołane zboczem rosnącym EICRA = (1<<ISC11)|(1<<ISC10); //na wejściu INT1 SetBit(EIMSK, INT1); odl1=licznik; //Zapisuje wartość licznika do zmiennej "odl" odl1/=20; //oraz skaluje go licznik=0; //Zerowanie licznika flaga=0; } } //F-cja przerwania zewnętrznego INT2 ISR(INT2_vect) { if(flaga==0) { TIMSK = (1<<OCIE2); //włącza Timer2 w trybie dopasowania (START) ClrBit(EIMSK, INT2); EICRA = 0x00; //Przerwanie zostanie wywołane zboczem opadającym EICRA = (1<<ISC21); //na wejściu INT2 SetBit(EIMSK, INT2); flaga=1; } else if(flaga==1) { TIMSK &=~(1<<OCIE2); //zatrzymuje Timer2 (STOP) ClrBit(EIMSK, INT2); EICRA = 0x00; //Przerwanie zostanie wywołane zboczem rosnącym EICRA = (1<<ISC21)|(1<<ISC20); //na wejściu INT2 SetBit(EIMSK, INT2); odl2=licznik; //Zapisuje wartość licznika do zmiennej "odl" odl2/=20; //oraz skaluje go licznik=0; //Zerowanie licznika flaga=0; } } double l_pomiar(void) { SetBit(EIMSK, INT0); SetBit(PORTD, 3); _delay_us(15); ClrBit(PORTD, 3); _delay_ms(8); ClrBit(EIMSK, INT0); return odl0; } double p_pomiar(void) { SetBit(EIMSK, INT2); SetBit(PORTD, 5); _delay_us(15); ClrBit(PORTD, 5); _delay_ms(8); ClrBit(EIMSK, INT2); return odl2; } double s_pomiar(void) { SetBit(EIMSK, INT1); SetBit(PORTD, 4); _delay_us(15); ClrBit(PORTD, 4); _delay_ms(8); ClrBit(EIMSK, INT1); return odl1; }
  9. Oprócz tego co napisał Zuk, przerwania mogą być wywoływane przez różne czynniki. Wewnętrznie (np. przez timery) bądź zewnętrznie (przez stan lub jakieś zbocze na odpowiednim wyjściu). W przypadku Twojego kodu są to przerwania zewnętrzne za pomocą pinów INT0 i INT2. Rejestr GIMSK służy do ustawienia, które wejścia (mogą być również wyjścia, wtedy przerwania te można inicjować programowo) będą obsługiwane przez przerwania. W przypadku AtMegi8 masz to w DataSheet na stronie 49. Rejestr MCUCR ustawiasz czy przerwanie to ma być wywołane zboczem narastającym, opadającym, stanem niskim czy wysokim na pinie INT0-1. (str.66 dokumentacji) Funkcja sei(); ustawia 7 bit w rejestrze SREG (str. 11 dokumentacji), zezwala globalnie na wszystkie przerwania, bez tego przerwania są wyłączone. W przypadku wystąpienia przerwania od np. INT0 zostanie wykonane to co znajduje się wewnątrz funkcji ISR(INT0_vect). A po wykonaniu wszystkich instrukcji powróci do wykonywania programu tam gdzie go przerwał - tak jak Zuk już napisał🙂
  10. Sokolsok

    Zipp

    Błędy nie przekraczały 5mm w całym zakresie ich działania. Ale te 5m zakresu podawanego przez producenta to chyba jest naprawdę w idealnych warunkach, bez jakichkolwiek zakłucaczy.
  11. Sokolsok

    Zipp

    Dodam, dodam.. Zdjęcia mam bo to był załącznik do mojej pracy, a filmiku nie nagrywałem, ale nagram coś i wrzucę oczywiście:) Tego gąszczu chyba nie dało się uniknąć (no może delikatnie zmniejszyć🙂. Czujniki, LCD i przyciski są na górnej obudowie robota więc jakoś to musiałem połączyć. Ta blacha ma 3 zastosowania: 1. jako ukrywacz tego "gąszczu kabli";P 2. jako zabezpieczenie przed wypadnięciem baterii 3. tak, dokładnie jako przeciwwaga (na jednym ze zdjęć widać jeszcze dodatkowe ciężarki do niej przyklejone) Transoptory to TCST 1103. Jeśli chodzi o tarcze kodowe to wykonałem je w jakimś darmowym programie ściągniętym z sieci stworzonym właśnie do rysowania tarcz kodowych. Wydrukowałem je na folii do drukarek laserowych. Miałem obawy, że folia ta jest za miękka, i że zaczernienie czarnych pól będzie za słabe i miałem w razie co przygotowany plan B - czyli tarcze wydrukowane na sztywnej tekturze i prążki powycinane:) Okazałe się jednak, że ta folia działa wyśmienicie. Rozdzielczość jest dość mała - 17 prążków.Oczywiście korzystam najpierw z narastającego zbocza a potem z malejącego czyli rozdzielczość wynosi 34. Co w połączeniu z kołami o średnicy 6 cm daje minimalny "krok" 5,55 mm. Nie jest to dużo, teraz już wiem, że mogłem to spokojnie zwiększyć, ale już przed obroną mi się nie chciało;P Głównym ich zadaniem (oprócz jazdy prosto) było wyliczanie aktualnych współrzędnych. I sprawdzały się całkiem nieźle (choć bez rewelacji). Przy dość skomplikowanej trasie, w której musiał wykonać dużo skrętów dokładność w punkcie docelowym wynosiła ok 5cm. Obudowa ma kształt okręgu o średnicy 175 mm. Dolna część podwozie ma specjalne wcięcia na mocowania silniki. W najszerszym miejscu szerokość konstrukcji (wraz z kołami) wynosi 250 mm, natomiast wysokość 65 mm. Czyli chyba do "dużych" robotów się nie zalicza:) Jest sporo fajnych algorytmów jak VFH, Dynamiczne okna, czy CVM. Mnie jednak gonił termin, dlatego akurat w tej kwestii poszedłem na łatwiznę.. Zastosowałem zmodyfikowany prze ze mnie algorytm BUG0. Zasada działania modyfikacji: (cytat ze mnie:P mojej pracy) Generalnie sprowadza się to do wybrania krótszej strony, z której robot ominie przeszkodę. A nie zawsze w jedną stronę jak w BUG0. Reszta jest taka sama. To jest świetne pytanie:) A odpowiedź jest prozaicznie prosta. Nie miałem pomysłu jak je tam przyczepić. Przy kole miałem huba (czy jak to się nazywa), do którego przekręciłem koła i ładnie mogłem przykleić tarczę. Z tyłu miałem sam wał. A poza tym z tą dokładnością to i tak trochę lipa była, bo silniki mają dość sporawe luzy na przekładniach..
  12. Moim zdaniem enkodery są w tym przypadku całkowicie zbędnym elementem. Wymiary basenu są niezmienne i znane. Ja to bym zrobił tak. 2 czujniki ultradźwiękowe po obu bokach, a z przodu jakiś zderzak. Metodą pokrycia terenu byłby "ruch wołu" czyli jazda wzdłuż dłuższej ściany obrót o 180 stopni i powrót. Wiedzę o orientacji i jeździe prosto robot by wyznaczał na podstawie tych 2 czujników. Ponieważ Wymiar basenu oraz wymiar robota jest znany, to znana jest jego pełna trasa (tj. ilość prostych i ilość nawrotów). Czyli w każdym momencie robot ma wiedzę w jakiej odległości od ścian powinien się znajdować. I na podstawie odchyłów od założonej odległości by korygował prędkością kół (orientacją). Teoretycznie powinien wystarczyć jeden czujnik, ale z doświadczenia wiem, że wyniki otrzymywane z takich czujników nie są w 100% stabilne i jednoznaczne, dlatego robot ma 2, większe odchylenia któregoś czujnika byłyby korygowane tym drugim. Z przodu byłby jakiś prosty zderzak oznajmiający, że robot dojechał do ściany i musi wykonać nawrót. Przy założonych prędkościach na pewno nie zrobiłby sobie "krzywdy":)
  13. Witam, pochwalę się moim pierwszym poważnym robotem autonomicznym, dzięki któremu udało mi się tytuł magistra uzyskać. Wcześniej robiłem jakieś proste konstrukcję (wyświetlacz widmowy czy prosty robot mobilny z lega technic), ale ta jest pierwsza z tych "poważniejszych";) Tematem pracy było zbudowanie w pełni autonomicznego robota mobilnego, oraz zaimplementowanie mu algorytmu umożliwiającego mu dotarcie do celu unikając przeszkód statycznych i dynamicznych. Środowisko pracy z założenia jest środowiskiem lokalnym (nie ma wbudowanej mapy otoczenia). Konstrukcja: Podwozie robota wykonane jest ze spienionego PCV – jest lżejsza i łatwiejsza w obróbce niż pleksi. Górny element obudowy przymocowany jest za pomocą czterech śrub. Elementy mocujące czujników przymocowane są klejem na gorąco, mocowania silników zostały przykręcone. Obudowa ma kształt okręgu o średnicy 175 mm. Dolna część podwozie ma specjalne wcięcia na mocowania silniki. W najszerszym miejscu szerokość konstrukcji (wraz z kołami) wynosi 250 mm, natomiast wysokość 94 mm. Wybrałem silniki - HL 149.6.21 ASM firmy Micro Motors. Mają zintegrowaną przekładnię 21:1 pozwalające na osiągnięcie 160 rpm i momentu 0,075 Nm – przy napięciu znamionowym 6 VDC. Kupiłem ja na Allegro za jakieś 15 zł za sztukę🙂 Elektronika Mózgiem robota jest ATmega 128. Ma dużą ilość wbudowanych urządzeń peryferyjnych, sporo wyprowadzeń I/O i dużo pamięci flash. Występuje niestety (albo stety) wyłącznie w obudowie SMD, jednak w sprzedaży istnieją gotowe moduły umożliwiające montaż THT, co zdecydowanie upraszcza projektowanie płytki PCB w warunkach domowych. Głównym zmysłem robota są 3 czujniki ultradźwiękowe HC-SR04. Według producenta zakres wykrywanych odległości to 2 – 500 cm z rozdzielczością 3 mm. Są to jednak parametry w wyidealizowanych warunkach, w rzeczywistości realnie i w miarę stabilnie można mierzyć w zakresie do 300 cm. Do sterowania kierunkiem oraz prędkością obrotową silników został użyty układ - L298. Scala on w jednej małej obudowie, Multiwatt 15, dwa mostki H. Zasilanie: zdecydowałem się użyć akumulatora litowo – polimerowego o pojemności – 2200 mAh i napięciu 7,4 V. Pozwala on na sprawną pracę robota przez ok. 60 min. Można go dostać w sklepie modelarskim już za ok 80 zł. Soft Tu nie ma co się rozpisywać. Całość kodu napisałem w "c". Myślę, że nie ma co go pokazywać bo jest "brzydki";P Napisany po prostu żeby działał, ale jest tam niezły bałagan, za parę miesięcy prawdopodobnie sam się w nim nie połapię😋 Fotki
  14. W swoim robocie użyłem dokładnie tych samych czujników. Działają przewyśmienicie. Zarówno Trig jak i Echo bezpośrednio podłączyłem na uC. Poniżej masz kawałek mojego schematu. Echo musisz podłączyć do wejść odsługujących przerwania zewnętrzne, natomiast Trig gdziekolwiek. W dokumentacji masz napisane, że sygnał musi wynosić co najmniej 10 us, ja dla pewności dałem 15 us. Na rysunku masz moją rzeczywistą charakterystykę U(t), niebieski to Trig a czerwony Echo. Pozdrawiam schemat: U(t):
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.