Skocz do zawartości

Bejro

Użytkownicy
  • Zawartość

    5
  • Rejestracja

  • Ostatnio

Reputacja

13 Dobra

O Bejro

  • Ranga
    2/10

Ostatnio na profilu byli

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

  1. Witam, Chciałbym przedstawić mój projekt, którym jest skaner 3D. Niestety jego dokładność nie pozwala na skanowanie obiektów w celu tworzenia modeli, ale można przy jego pomocy stworzyć poglądową mapę głębokości otoczenia. Skaner ten powstał głównie w celu sprawdzenia możliwości aktywnej komunikacji z Arduino z Komputerem przy użyciu Pythona. Zasada działania Skaner ten jest obsługiwany przez urządzenie zewnętrzne które łączy się z Arduino Uno za pośrednictwem USB. Składa się on z sensora ultradźwiękowego, który porusza się w dwóch osiach za pomocą serwomechanizmów - dokładnie tych. Całość jest zamocowana na czworonożnej ramie która została wydrukowana w 3D. Działanie Arduino podlega sterowaniu zewnętrznemu, a samo ma zdefiniowane jedynie podstawowe funkcje które są wywoływane za pośrednictwem komunikacji przez UART. Funkcje zawarte w Arduino dotyczą obrotu czujnika w dwóch osiach oraz wykonania pomiaru odległości i zwrócenia wyniku na połączenie szeregowe. Jak już wspomniano wcześniej, od strony komputera komunikacja realizowana jest za pomocą języka Python. Komputer wysyła polecenia dotyczące wykonania ruchu w danej osi oraz zwrotu informacji o mierzonej odległości. Niestety z powodu długiego czasu trwania pomiaru, wrażliwości sensora na wibracje, oraz wykonywaniu za każdym razem kilku pomiarów w celu minimalizacji błędów, mapowanie dużego obszaru z dużą rozdzielczością potrafi zajmować nawet kilkanaście minut - maksymalna rozdzielczość wynosi 180x180 co daje 32400 pomiarów. Arduino Kod Ardunio jest dość prosty i krótki, funkcje ograniczają się, zgodnie z tym co napisano powyżej, do obsługi serw oraz wykonywaniu pomiarów. W tym przypadku wykonywane są 3 pomiary a na linię portu szeregowego wysyłana jest wartość uśredniona. #include <Servo.h> #include <Wire.h> const int trigPin = 9; const int echoPin = 10; long duration; int distance1; int distance2; int distance3; String in = "1"; #define LED 13 int pos=105; int pos1=50; int th=1.5; int inn; Servo x; Servo y; void setup() { Serial.setTimeout(100); pinMode(LED, OUTPUT); digitalWrite (LED, LOW); x.attach(3); y.attach(6); x.write(pos); y.write(pos1); pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); Serial.begin(9600); } void loop() { x.write(pos); y.write(pos1); if (Serial.available()){ delay(10); if (Serial.available()>0) { in = Serial.read(); // Serial.write(in); inn = in.toInt(); } if (inn==1){ measure(); Serial.println((distance1+distance2+distance3)/3); } if (inn==2){ pos++; } if (inn==3){ pos--; } if (inn==4){ pos1++; } if (inn==5){ pos1--; } if (inn>10 and inn<105){ pos = inn; } if (inn>105){ pos1 = inn-105; } } } void measure(){ digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distance3= duration*0.034/2; if (distance3 > 79) distance3 = 80; delayMicroseconds(1000); digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distance2= duration*0.034/2; if (distance2 > 79) distance2 = 80; delayMicroseconds(1000); digitalWrite(trigPin, LOW); delayMicroseconds(2); digitalWrite(trigPin, HIGH); delayMicroseconds(10); digitalWrite(trigPin, LOW); duration = pulseIn(echoPin, HIGH); distance1= duration*0.034/2; if (distance1 > 79) distance1 = 80; //Serial.print("bare average=");Serial.println((distance1+distance2+distance3)/3); if ((distance1 > (distance2+distance3)/2 + th) or (distance1 < (distance2+distance3)/2 - th)){ distance1=(distance2+distance3)/2; }else if((distance2 > (distance1+distance3)/2 + th) or (distance2 < (distance1+distance3)/2 - th)){ distance2=(distance1+distance3)/2; }else if((distance3 > (distance1+distance2)/2 + th) or (distance3 < (distance1+distance2)/2 - th)){ distance3=(distance1+distance2)/2; } return distance1, distance2, distance3; Gdy Arduino odbierze wiadomość '1' wykona pomiar i zwróci jego wartość, gdy otrzyma wartość wyższą, wykona odpowiedni ruch wybranym serwem. Wartości większe niż 10 służą do ustawienia pozycji początkowej, i mogą umieścić czujnik jedynie w jednej ćwiartce pola roboczego. Python Działanie funkcji sterujących jest bardziej rozbudowane. Główny skrypt ma następującą postać. import sys import os import sonarLib as sn import matplotlib.pyplot as plt import numpy as np import smooth import index sn.resolution(index.y,index.x) sn.step(index.s) sn.smth(index.sm) sn.get() for i in range(sn.smoothness): smooth.exe(sn.r,3) sn.r = np.flip(sn.r,1) plt.imsave('img.png',sn.r,cmap='gray') os.system('show.py') Na początku wyświetlane jest prymitywne GUI - index.py stworzone przy pomocy matplotlib.pyplot. Wybrane parametry pracy są określane i przy pomocy sn.get() inicjowane są wszystkie skrypty służące do wykonania pomiarów i przetworzenia danych w macierz. Gdy długotrwały proces dobiegnie końca, obraz jest delikatnie wygładzany w celu usunięcia pikseli których wartości nie pasują do otoczenia. Częste było również występowanie artefaktów w postaci poziomych linii o dość jednolitych wartościach. Jak poniżej. (To jakiś wysoki wąski przedmiot na biurku.) Jest to "surowe" zdjęcie przed filtracją. Po filtracji zdjęcie jest wyświetlane w GUI które umożliwia na interaktywny dobór progu w celu wybrania pikseli znajdujących się bliżej niż zadana wartość. Jeśli ktoś jest ciekawy działania całego programu, to zamieszczam go tutaj: Skaner3D.rar Ostrzegam jednak, że może on być prymitywny i miejscami chaotyczny . Działanie Poniżej jedno z najlepszych "ujęć" razem z widokiem z aparatu z tej samej perspektywy. (Nie miałem oryginalnego pliku i jest to ss wykonany telefonem.) To chyba już wszystko co można w skrócie powiedzieć o tym projekcie. Mam nadzieje, że może się podobać. Gdybym miał coś w nim poprawić, na pewno zmieniłbym rodzaj czujnika na IR oraz spróbował upłynnić ruchy napędów. Poniżej jeszcze zdjęcie całego skanera od góry. Pozdrawiam, i czekam na pytania i porady.
  2. Cieszę się bardzo, że projekt się podoba . Był to mój pierwszy projekt czegoś co się przemieszcza. Co do zasilania serw, to jeśli jestem pewien, że wyjście arduino sobie nie poradzi, to zwykle wykorzystuję ESC z BEC i nie ma żadnych problemów. Tutaj jednak chciałem użyć płytki rozszerzającej, w której niestety nie ma możliwości użycia osobnego zasilania dla serw. Gdybym kiedyś powracał do projektu, na pewno bym o to zadbał. Czujniki krańcowe na końcu nóg były bardzo spontanicznym pomysłem, miałem je akurat pod ręką i pomyślałem, że zobaczę jaki efekt mogę osiągnąć. 3 stopień planowałem umieścić, ale gdy policzyłem niespalone serwa, to wyszło mi, że nie mam ich wystarczająco, więc ograniczyłem się jedynie do dwóch stopni.
  3. Witam serdecznie, Chciałbym zaprezentować mój projekt którym jest czworonożny robot kroczący sterowany za pomocą kolna arduino - nano V3. Głównym celem powstania tej konstrukcji było zabicie wolnego czasu oraz wykorzystanie nowo zamówionych części. Cały proces tworzenia od koncepcji do gotowego czworonoga trwał poniżej tygodnia. Funkcjonalność robota skupiała się na chodzeniu do przodu oraz pokonywaniu małych przeszkód. Elektronika Do stworzenia projektu potrzebny był kontroler - wspomniane już wcześniej arduino nano lub jego klon. W mojej opinii jest to najbardziej użyteczne arduino do projektów DIY, ze względu na jego małą wielkość i masę oraz identyczne możliwości obliczeniowe jak jego więksi bracia. Arduino zostało zamontowane na płytce rozszerzającej z wieloma wyprowadzeniami dla serw i nie tylko. Ten element jest bardzo uniwersalny i ułatwia podłączenie wielu komponentów bez potrzeby tworzenia odpowiedniej płytki PCB lub używania płytki stykowej. Motoryka została oparta o małe serwomechanizmy - po dwa na nogę, łącznie 8 sztuk. Dodatkowo na końcach nóg zostały zamontowane czujniki krańcowe w celu wykrywania kolizji z podłożem i optymalizacji ruchu. Siła serwomechanizmów okazała się być wystarczająca, jednakże, problemem okazało się być zasilanie. Duża ilość serwomechanizmów działających jednocześnie mocno obciąża arduino, dlatego też, serwomechanizmy powinny mieć własne źródło zasilania. W tym przypadku ograniczenie prędkości ruchów ograniczyło ten problem, ale wskazuje to na popełniony przy projektowaniu błąd. Konstrukcja Konstrukcja składa się z korpusu głównego do którego przymocowano arduino oraz 4 nóg. Jedna noga składa się z dwóch segmentów, a jeden segment z dwóch elementów łączonych śrubą. Lepiej wyjaśni to poniższe zdjęcie. Robot jest tu przedstawiony leżący na swoich plecach. Poniżej znajdują się jeszcze dwa zdjęcia pokazujące jego posturę. W pozycji leżącej, ze wszystkimi nogami skierowanymi względem siebie pod kątem prostym, robot ma przekątną około 30 cm. Powyższe elementy zostały wydrukowane przy pomocy drukarki 3D. Trwało to około 10 godzin. Kod Ze względu na krótki czas rozwoju projektu, jego funkcjonalność nie jest duża. Postało kilka wersji programu, dopasowanych do konkretnego podłoża. Nie różnią się one znacząco, więc przedstawię główny program służący do pokonywania płaskiego terenu w najszybszy i najstabilniejszy sposób. Na początek trochę definicji. Zmienne nazwane są od numeru nogi oraz jej stopnia. Przykładowo tl1 - top-left-1, oraz br2 - bottom-right-2. #include <Servo.h> Servo tr1; Servo tr2; Servo tl1; Servo tl2; Servo br1; Servo br2; Servo bl1; Servo bl2; #define br A1 #define tr A2 #define tl A3 #define bl A4 int i=0; int o=50; int p=20; int h=70; int t=10; int k=0; int l=0; int n=0; int m=0; int timer=0; int d=0; int x=50; int y=50; void setup() { Serial.begin(9600); pinMode(A1, INPUT_PULLUP); pinMode(A2, INPUT_PULLUP); pinMode(A3, INPUT_PULLUP); pinMode(A4, INPUT_PULLUP); tl1.attach(8); tl2.attach(4); bl1.attach(9); bl2.attach(5); tr1.attach(10); tr2.attach(6); br1.attach(11); br2.attach(7); tr1.write(90); tr2.write(75); tl1.write(90); tl2.write(90); br1.write(90); br2.write(90); bl1.write(90); bl2.write(90); } Kolejnym elementem kodu są definicje funkcji. void ltl(int a, int b){ tl1.write(map(a+3, 0, 100, 10, 150)); tl2.write(map(b, 100, 0, 5, 180)); } void ltr(int a, int b){ tr1.write(map(a, 100, 0, 30, 170)); tr2.write(map(b-9, 0, 100, 0, 177)); } void lbl(int a, int b){ bl1.write(map(a, 0, 100, 30, 150)); bl2.write(map(b+1, 0, 100, 0, 178)); } void lbr(int a, int b){ br1.write(map(a, 100, 0, 30, 150)); br2.write(map(b+4, 100, 0, 8, 180)); } void move(){ lbr(100-i,100-k-d); i++; if(i==100){ i=0; k=y; } if(k>0){ if(digitalRead(br)==HIGH){ k--; } } lbl(100-o,100-l-d); o++; if(o==100){ o=0; l=y; } if(l>0){ if(digitalRead(bl)==HIGH){ l--; } } ltr(100-p,100-n-d); p++; if(p==100){ p=0; n=x; l=l+10; k=k+10; } if(n>0){ if(digitalRead(tr)==HIGH){ n--; } } ltl(100-h,100-m-d);; h++; if(h==100){ h=0; m=x; k=k+10; l=l+10; } if(m>0){ if(digitalRead(tl)==HIGH){ m--; } } delay(t); } Przykładowo, nazwa funkcji ltl oznacza leg-top-left i służy do ujednolicenia określania położenia nogi, gdyż niektóre serwa położone są przeciwnie i wysoka wartość sygnału PWM oznacza dla nich przeciwne położenia. Funkcja move to gówna funkcja służąca do poruszania się. Działa ona tak, że wszystkie nogi poruszają się cały czas do tyłu, jednakże, początkowe położenia wszystkich nóg są różne. Gdy noga poruszając się do tyłu dojdzie do płożenia końcowego, podnosi się ona i przemieszcza do maksymalnego płożenia do przodu, wtedy zbliża się ona do podłoża aż do napotkania oporu odebranego przez czujnik krańcowy lub osiągnięcia pozycji maksymalnej, wtedy porusza się znów do tyłu. W ten sposób wszystkie nogi cały czas znajdują się w ruchu, który jest bardzo płynny. Brak 3 stopnia swobody w nodze wpływa jednak na to, że ślizganie jest nieuniknione. Ostatnia część kodu służy jedynie do egzekwowania funkcji move pod pewnymi warunkami. void loop() { if(analogRead(br)==LOW or analogRead(tr)==LOW or analogRead(bl)==LOW or analogRead(tl)==LOW && timer<50){ timer=200; } timer--; if(timer>0){ move(); }else{ lbl(50,50); lbr(50,50); ltl(50,50); ltr(50,50); } } Kod w funkcji loop powoduje również, że w razie podniesienia robota na pewien czas, przestaje on dalej iść. Gdy robot zostanie podniesiony, żaden czujnik krańcowy nie sygnalizuje, że stoi na ziemi, powoduje to spadek licznika timer do 0 i przejście robota w stan spoczynkowy, aż do aktywacji przez ponowne wciśnięcie któregoś czujnika. Gotowy robot Poniżej przedstawiam kilka zdjęć z postępu składania konstrukcji. Niestety nie posiadam dużo zdjęć tego projektu, gdyż serwa i mikrokontrolery szybko zmieniają u mnie właściciela. Podczas testów robot pokonał najwyższy próg o wysokości nieco ponad 4 cm. Może nie jest to imponująca wartość, ale biorąc pod uwagę, że nie może on biegać ani skakać, a maksymalna wysokość własna na jakiej znajduje się jego korpus wynosi około 4,5 cm jest to taki sam wyczyn jak pokonanie przez człowieka, z marszu, przeszkody sięgającej mu do pasa. A tu jeszcze jedno zdjęcie gotowego projektu (słaba jakość, klatka z filmu). Pozdrawiam, i czekam na pytania i porady.
×
×
  • Utwórz nowe...