Skocz do zawartości

mati 6

Użytkownicy
  • Zawartość

    192
  • Rejestracja

  • Ostatnio

  • Wygrane dni

    6

mati 6 wygrał w ostatnim dniu 14 lutego 2015

mati 6 ma najbardziej lubianą zawartość!

Reputacja

29 Bardzo dobra

O mati 6

  • Ranga
    5/10

Informacje

  • Płeć
    Mężczyzna
  1. Jak już reklamować, to warto podać też jakiś kontakt, albo adres strony internetowej
  2. Proszę bardzo, już informuję ( Zamiast "(uint8_t ms) " użyłem "(uint16_t ms)" ponieważ niektóre delaye są dłuższe. Stara wersja (info przy kompilacji): Program: 2362 bytes (28.8% Full) (.text + .data + .bootloader) Data: 24 bytes (2.3% Full) (.data + .bss + .noinit) Nowa wersja: Program: 1170 bytes (14.3% Full) (.text + .data + .bootloader) Data: 2 bytes (0.2% Full) (.data + .bss + .noinit) A zmian przecież tak dużo nie ma Wstrzymałem się jeszcze z przebudową funkcji do zapalania diod ( ale faktycznie pomysł Marka1707 jest sprytny ) Nie jesteśmy w piaskownicy Jestem szalenie wdzięczny za wasze uwagi.
  3. Dzięki wszystkim. Nie spodziewałem się aż takiego odzewu. Niezaprzeczalne, że kod jest do poprawy. Jutro na pewno do tego przysiądę. Niemniej jednak pierwszorzędną sprawą było dla mnie dostarczenie w pierwszej kolejności działającego kodu, który ( w chwili jego pisania ) rozumiałem i mogłem łatwo modyfikować. Przypominam, to moje pierwsze połączenie Uc i C. Za niektóre " błędy " jest mi wstyd już teraz , z niektórych będę się śmiał jutro, a część pewnie będę jeszcze przez długi czas popełniał. Na tym etapie mikrokontroler jeszcze wiele wybacza, ale macie rację, że to nie powód by robić to byle jak. Tak czy inaczej nie żałuję, że wstawiłem ten kod. Byłem gotowy na konstruktywną krytykę i jeszcze raz wielkie dzięki za nią. Jeśli jacyś inni początkujący chcieliby coś zaczerpnąć z takiej konstrukcji to dobrze, by zastali jak najładniejszy kod. Pozdrawiam edit: Do czasu poprawy kodu dodałem w pierwszym poście ostrzeżenie o nie-perfekcyjności kodu
  4. Zgadza się. Z tego powodu ograniczona jest prędkość całego robota. Machanie dobierałem doświadczalnie ( ciekawa zabawa, by dodatkowo połączyć to z odpowiednim zapalaniem i gaszeniem diod by wprowadzić efekt synchronizacji). W chwili obecnej wygląda to tak: ->komenda, by serwo przesunęło się o jedną jednostkę ( ok. 10-11 stopni) -> odczekaj 20ms -> zgaś diodę, pod którą wcześniej był czujnik -> odczekaj kolejne 15ms -> zapal kolejną diodę -> sprawdź stan czujnika na nowej pozycji Nie omieszkam pobawić się jeszcze tymi parametrami, by uzyskać jeszcze lepszą synchronizację.
  5. Wstęp Witam serdecznie. Prezentuję dziś mobilnego robota, którego zadaniem jest wykrywanie przeszkód i unikanie kolizji. Jest to pierwszy projekt po długiej przerwie, starałem się możliwie rzetelnie podejść do sprawy. Opis działania Robot posiada tylko jeden sensor ( cyfrowy czujnik Sharp o zasięgu do 10cm) umieszczony na orczyku serwa, które stale obraca go w zakresie mniej więcej od 0 do 100 stopni. Dodatkowo nad czujnikiem znajduje się łuk diod LED, które sygnalizują bieżące wychylenie czujnika i przeszkody (widać na filmie). Po wykryciu przeszkody robot zmienia kierunek jazdy ( kierunek zależny od miejsca wykrycia przeszkody). Powstawanie w 3 krokach Mechanika Sam przyznaję, że to wygląda dziwnie :/ Napęd stanowią dwa przerobione ( pozbawione elektroniki i mechanicznych blokad) serwomechanizmy typu standard. Obracaniem czujnika zajmuje się micro serwo. Konstrukcja oparta jest na laminacie. Montaż głównie za pomocą śrubek i dystansowników. Trzeci punkt podporu stanowi małe kółko obrotowe ( dostępne w każdym sklepie budowlanym). Koła są kupne, z mocowaniem pasującym do wału standardowego serwomechanizmu. W trakcie budowy problemem okazał się za mocno do przodu wysunięty środek ciężkości. Zniwelowałem to dokładając z tyłu dużą śrubę z nakrętkami służącą za obciążnik. Akumulator przymocowany jest za pomocą rzepu samoprzylepnego. Elektronika Serce robota to atmega88p. Zasilanie: pakiet lipo s2 7.4V 400mAh. Dwa stabilizatory ( jeden dla elektroniki, drugi dla serwa*). Mostek l293D i trochę drobnicy ( wszystko na schemacie i zdjęciach). *Nie jest to rozwiązanie idealne, jednakże chyba najprostsze, by w łatwy sposób dostarczyć 5V dla jednego serwa. Program Nic specjalnego, jednakże jest to mój pierwszy projekt napisany w C ( przed przerwą zaczynałem w Bascomie). Timer0 generuje sygnał dla serwa, Timer1 zajmuje się PWMem dla silników. Serwo przemieszcza się wyłącznie między 11 na sztywno zaprogramowanymi położeniami ( pokrywającymi się z położeniem diod LED ). Brak przerwań, stan czujnika odczytywany jest tylko w postojach pomiędzy jednym, a drugim LEDem ( ok. 11 stopni), jednak kąty widzenia czujnika chyba niwelują martwe pole. Zmiana kierunku jazdy jest wprost proporcjonalna od odległości przeszkody od środka robota ( mówiąc inaczej, gdy przeszkoda jest z boku robot skręca lżej, im bliżej środka tym mocniej robot „odbija”) Najprawdopodobniej powstanie jakiś fajniejszy algorytm Wady Na zdjęciu widoczne dociążenie robota Przede wszystkim kompletnie zapomniałem o środku ciężkości, wydawało mi się, że sam ciężar serw wystarczy. Stąd też potrzebne było dodatkowe obciążenie. Cały system wykrywania przeszkody jest swego rodzaju kompromisem. Z jednej strony zasięg czujnika jest mały, z drugiej strony zbyt szybki obrót serwa również wpływa negatywnie na przeszukiwanie terenu. Robot jest celowo spowolniony, by miał czas na przebadanie otoczenia. Problemy są z wykrywaniem za wysokich, zbyt niskich przeszkód, oraz przeszkód w kolorze czarnym. (Czego się oczywiście spodziewałem). Galeria Schematy Płytki Program v1.01 #define F_CPU 1000000L #include <avr/io.h> #include <util/delay.h> #define LED1 0xFE #define LED2 0xFD #define LED3 0xFB #define LED4 0xF7 #define LED5 0xEF #define LED6 0xDF #define LED7 0xFE #define LED8 0xEF #define LED9 0xF7 #define LED10 0xFB #define LED11 0xFD #define silnik_lewyA 0b10000000 #define silnik_lewyB 0b00100000 #define silnik_prawyA 0b01000000 #define silnik_prawyB 0b10000000 #define sensor 0b0000001 int i; void czekaj_ms(uint16_t ms) { for(uint16_t g=0; g<ms; g++) _delay_ms(1); } void przod_przod(int x, int y, int z) { PORTB|=silnik_lewyA | silnik_prawyA; PORTD&= (~silnik_lewyB) & (~silnik_prawyB); OCR1A=x; OCR1B=y; czekaj_ms(z); } void tyl_tyl(int x, int y, int z) { PORTB&=(~silnik_lewyA) & (~silnik_prawyA); PORTD|= silnik_lewyB | silnik_prawyB; OCR1A=x; OCR1B=y; czekaj_ms(z); } void przod_tyl(int x, int y, int z) // Lewy silnik do przodu, prawy do tylu { // silnik lewy do przodu OCR1B=x; PORTB|=silnik_lewyA; PORTD&= (~silnik_lewyB); //silnik prawy do tylu OCR1A=y; PORTB&=(~silnik_prawyA); PORTD|=silnik_prawyB; czekaj_ms(z); } void tyl_przod(int x, int y, int z) // Lewy silnik do tylu, prawy do przodu { // silnik lewy do tylu OCR1B=x; PORTB&= (~silnik_lewyA); PORTD|= silnik_lewyB; //silnik prawy do przodu OCR1A=y; PORTB|=silnik_prawyA; PORTD&=(~silnik_prawyB); czekaj_ms(z); } void inicjalizacja() { //PWM DLA SERWA ( timer0) STEROWANIE PRZEZ PODANIE NA OCR0A wartosci od 10 do 35 TCCR0A = ( 1 << COM0A1 ) | (1<<WGM01) | (1<<WGM00); TCCR0B = (1<<CS00) | (1<<CS01); DDRD|=0x40; PORTD=0x40; //PWM DLA SILNIKOW (timer1) TCCR1A= (1<< COM1A1)|(1<<COM1B1)|(1<<WGM11); //MODE 14 FAST PWM TCCR1B= (1<<WGM13)|(1<<WGM12)|(1<<CS10); // PRESCALER=1, frec.PWM = 1kHz ICR1=999; } void dioda(int x) { //Zapalanie kolejnych diod switch(x) { case 11: PORTC&=LED1; break; case 10: PORTC&=LED2; break; case 9: PORTC&=LED3; break; case 8: PORTC&=LED4; break; case 7: PORTC&=LED5; break; case 6: PORTC&=LED6; break; case 5: PORTD&=LED7; break; case 4: PORTD&=LED8; break; case 3: PORTD&=LED9; break; case 2: PORTD&=LED10; break; case 1: PORTD&=LED11; break; } } void dioda_off() { PORTC|=0b00111111; PORTD|=0b00011111; } void przeszkoda() { //Hamowanie tyl_tyl(800,800,100); OCR1A=0; OCR1B=0; for (uint8_t g=0;g<4;g++) // ZAMRUGANIE DIODAMI { dioda(i/2 -4); dioda(i/2 -5); dioda(i/2 -6); czekaj_ms(300); dioda_off(); czekaj_ms(200); } tyl_tyl(500,500,i*30); if (i>=22) przod_tyl(800,800,((-30)*i+1060)); else tyl_przod(800,800,(30*i-260)); przod_przod(500,500,1); } void szukanie() { int czas=20; while(1) { for (i=12; i<33;i+=2) { OCR0A=i; czekaj_ms(czas); dioda_off(); czekaj_ms(czas); dioda(i/2 -5); if (!(PINB & sensor)) przeszkoda(); } for (i=32; i>11; i-=2) { OCR0A=i; czekaj_ms(czas); dioda_off(); czekaj_ms(czas); dioda(i/2 -5); if (!(PINB & sensor)) przeszkoda(); } } } void main(void) { inicjalizacja(); DDRD=0b11111111; PORTD=0b00000000; DDRC=0b00111111; DDRB=0b11111110; PORTB=0b11100000; przod_przod(500,500,1); szukanie(); } Film Najprawdopodobniej powstanie jakiś fajniejszy algorytm
  6. Dzięki wielkie za odpowiedź Wielka ulga, że to co napisałem miało choć połowicznie sens EDIT: działa #define F_CPU 1000000L #include <avr/io.h> #include <util/delay.h> int main(void) { TCCR0A = ( 1 << COM0A1 ) | (1<<COM0B1) | (1<<WGM01) | (1<<WGM00); TCCR0B = (1<<CS00) | (1<<CS01); DDRD=0xFF; PORTD=0xFF; OCR0A=23; while(1) { int i; for (i=16; i<32;i++) { OCR0A=i; _delay_ms(1000); } } } Serwo podłączone do PD6 ( OC0A) ani drgnie przy takim programie ( prócz momentu, w którym podłączam zasilanie ). Sprawdziłem miernikiem, na zasilaniu dostaje piękne 5V, a ścieżka z sygnałem od PD6 z atmegi88 do goldpina dla serwa pięknie przewodzi. Poniżej umieszczam również kroki, jakie wykonywałem podczas dłubania w nocie katalogowej: =========================================================== Bazowałem na artykule: [Dla początkujących] PWM w praktyce - język Użytkownika Grabki https://www.forbot.pl/forum/topics20/dla-poczatkujacych-pwm-w-praktyce-jezyk-c-vt7455.htm Odnalazłem te tabele ( w punkcie dot. timera0 ) Wybrałem MODE 3, czyli muszę ustawić WGM02 0 WGM01 1 WGM00 1 Bazując na 2 powyższych tabelach doszedłem do wniosku, że muszę zająć się jeszcze : COM0A1, COM0A0, COM0B1, COMOB2, CS02, CS01, CS00, F0C0A, FOC0B Tutaj wybrałem opcję 3 ( nie wiem czy dobrze) COM0A1 = 1 COM0A0 = 0 Tutaj również opcja 3 ( nie wiem czy dobrze ) COM0B1 =1 COM0B0 =0 “The FOC0A bit is only active when the WGM bits specify a non-PWM mode. However, for ensuring compatibility with future devices, this bit must be set to zero when TCCR0B is written when operating in PWM mode.” Zatem FOC0A = 0 ( tak jest ustawiony domyślnie ) Sprawa FOC0B wygląda identycznie jak wyżej, więc FOC0B=0 ( domyślnie ) tutaj prescaler 64, więc CS02 = 0 CS01=1 CS00=1 Składając to do kupy wyszło mi , że w TCCR0A: COM0A1 = 1 COM0A0 = 0 COM0B1 =1 COM0B0 =0 WGM01=1 WGM00=1 W TCCR0B: FOC0A = 0 FOC0B=0 WGM02=0 CS02 = 0 CS01=1 CS00=1 Przy czym wszystkie bity są domyślnie ustawione na '0', więc zająłem się tylko jedynkami TCCR0A = ( 1 << COM0A1 ) | (1<<COM0B1) | (1<<WGM01) | (1<<WGM00); TCCR0B = (1<<CS00) | (1<<CS01);
  7. Witam. Długi czas szukałem w internecie gotowych rozwiązań na sterowanie serwem za pomocą PD6 ( OC0A) na atmega88, jednak nie znalazłem nic pomocnego. Postanowiłem przełamać się i samodzielnie zanurzyć w głębiny not katalogowych. Po dłuuugim czasie udało mi się rozgryźć jak ustawić PWM ( odpowiednie bity TCCR0A i TCCR0B), jednak gdy doszło do przekształcenia samego PWM na sygnał dla serwomechanizmu okazało się, że ludzie zazwyczaj korzystają z Timera1, który ma tryb ( 14) który jako wartość TOP przyjmuje ICR1. Timer0 niestety takiej opcji nie ma. Rozwiązniem mogloby być ustawienie trybu, w którym OCRA stanowi TOP, jednakże wówczas nóżka 0C0A ( tj. PD6) nie może służyć jako wyjście sygnału PWM. Płytka jest już wytrawiona i polutowana, dlatego szukam rozwiązania nie ingerującego w hardware. Jeśli dobrze rozumiem, to ustalenie ICR1 służy precyzyjnemu wyliczeniu częstotliwości sygnału ( tj. 50 Hz dla serwa). Mając częstotliwość Uc 1MHz, wykorzystując prescaler 64 podstawiając do wzoru: 1MHz/(64*256) otrzymuję 61Hz, co nie jest aż tak oddalonym wynikiem, jednak wciąż nie mogę wysterować w ten sposób serwem podając różne wartości na 0CR0A. TCCR0A = ( 1 << COM0A0 ) | (1< TCCR0B = (1< Jak wyżej, ustawiłem tryb fast pwm, top= 0xFF; Prescaler=64 Oraz " Clear OC0A on compare match, set OC0A at Bottom ( non-inverting mode)" i tak samo OC0B
  8. A zamieniałeś silniki stronami ? Może wina mostka, bo prąd jaki mogą pobierać pololki jest znacznie większy, niż górna granica twojego l293d
  9. Proxxon również posiada swój odpowiednik tego multichucka. Na opakowaniu pisze 0,4-3,2mm, ale nie sprawdzałem czy może chwycić więcej/mniej. Kupione w Obi ( sam uchwyt - używam go przy innej tańszej multiwiertarce).
  10. Jak zmiejszyć ilość przelotek ? Te przy złączu do programowania są niepotrzebne. Wykorzystaj piny w złączu jako przelotki. Przy sharpach sprawa jest podobna. Sygnał od resetu do ISP mógłby iść na około i łączyć się ze złączem na stronie top. Kolejne 2 przelotki omijasz obracając dławik o 90* i puszczając ścieżki między jego padami. Przelotka na prawo od X1 również niepotrzebna, gdyż na stronie bottom mógłbyś dalej pociągnąć ścieżkę do drugiej przelotki. Przy R2 wystarczyłaby jedna przelotka zamiast 2. To oczywiście nie wszystkie możliwości Powyżej tylko pierwsze wnioski po powierzchownym spojrzeniu na pcb.
  11. Tak. Wraz z dokręcaniem tej nasadki 3 trzony zaciskają się... Jeszcze raz przestrzegam, byś kupił odpowiedni model... Najlepiej weź ze sobą tą starą nakrętkę i spróbuj ją przykręcić w markecie do multiwiertarki dremela lub proxxona. Jeśli nie będzie pasować do jednej, to duże prawdopodobieństwo, że odpowiedni będzie model drugiej firmy. Ja prawie odruchowo wziąłem ten zacisk dremela, ale coś mnie tknęło, by sprawdzić ten gwint i jak by się okazało źle bym postąpił. Ewentualnie jeśli masz w domu nakrętki M8 to przymierz je do gwintu swojej wiertarki. Standardem Proxxona przy tym gwincie jest właśnie M8.
  12. http://allegro.pl/uchwyt-wiertarski-0-5-3-2mm-proxxon-28941-i2714600649.html UCHWYT WIERTARSKI 0,5-3,2mm PROXXON 28941 Sprzedający jarek701114 O takie coś chodzi ? Musisz uważać, bo istnieją co najmniej 2 standardy takich nakrętek ( dremel z mniejszą średnicą otworu gwintowanego i proxxon z większą [m8]). U mnie również ta nasadka zaciskająca była badziewna i pękła od zbyt mocnego dokręcenia i kupiłem właśnie taką jak w powyższym linku. Prócz solidnego wykonania znacznie przyśpiesza proces wymiany wierteł i innych nasadek. Również mam jakąś chińszczyznę i by zamontować taką nasadkę na wąż musiałem odciąć troche plastiku by odslonić cały gwint. Nie próbowałem przykręcać tego uchwytu bezpośrednio do wiertarki, bo giętki wał jest dosyć solidnie przymocowany i nie chce tego już ruszać..
  13. chyba wkradło się zwarcie powyżej złącza do programowania. No i przy samym złączu ścieżka biegnie niebezpiecznie blisko kwadratowego pada.Również na dole między mostkami przelotka nachodzi na ścieżkę. Sprawdź jeszcze, czy pola lutownicze ( chyba kondensatora smd) między mostkami nie stykają się rogiem z ścieżką.
  14. Można by to zrobić nie zmieniając obecnych wymiarów... Ścieżke najbardziej wysuniętą na lewo przesuwasz do środka, Całość przesuwasz w lewo i ścieżkę puszczasz po prawej. Pad od zworki od prawej jest dosyć blisko ścieżki. Dławik możesz minimalnie w lewo przesunąć ( przesuwając przy tym ścieżkę idącą od Uc do złącza)... Dzięki temu zwiększą się odstępy padów od sąsiednich ścieżek.
  15. Do tego jedna zworka przechodzi przez obudowe złącza do programowania... chyba, że wstawisz tam po prostu goldpiny. Ale mimo to da się wyprowadzić ścieżkę po lewej tak, by zworka szła poziomo. edit: możesz też uniknąć zworki od zasilania przy złączu do programowania puszczając ścieżkę dookoła całej płytki.
×
×
  • Utwórz nowe...