
Projekt przedstawia możliwości budowy prostego manipulatora. Sterowanie dużą wersją manipulatora odbywa się poprzez poruszanie mniejszą kopią, zwaną "drzewkiem", której przeguby stanowią potencjometry. Całość jest sterowana programem opartym na architekturze Arduino.
1. Płytka Arduino UNO
2. Dwa profile aluminiowe o długości około 20cm
3. Filament do drukarki 3D
4. Cztery potencjometry (100k)
5. Kable (męsko męskie i żeńsko żeńskie)
6. Dwa serwa (minimum 1.5 Nm)
5. Silnik krokowy (28byj-48) ze sterownikiem (ULN2003A)
8. Tektura, blacha, srebrna taśma, drut, klej do pistoletu na klej
9. Srubki i nakrętki
10. Łożysko (6810-ZZ)
1. Drukarka 3D (w naszym przypadku bambu lab p1p)
2. Pistolet na gorący klej
Projekt "Manipulator robotyczny" stanowi podstawę do budowy bardziej złożonych manipulatorów hobbystycznych i przemysłowych. Konstrukcja składa się z trzech par obrotowych i czterech członów, tworząc zwięzły łańcuch kinematyczny. Projekt łączy aspekty mechaniczne, elektroniczne i programistyczne na poziomie embedded.
Mechanika
Pod względem mechanicznym projekt wymagał wydrukowania modeli podstawy na silnik, łożysko oraz stół metodą druku 3D, które razem tworzą dolną część konstrukcji. Wykonano także uchwyty na pozostałe człony manipulatora, współpracujące bezpośrednio z serwomechanizmami.
Mała wersja manipulatora wymagała połączenia stołu wykonanego z kartonu, potencjometrów i blaszki aluminiowej w jedną całość.
Elektronika
Elektronicznie projekt polegał na podłączeniu serwomechanizmów i silnika krokowego do zasilania oraz sterowania za pomocą Arduino. Zewnętrzne zasilanie tych elementów zrealizowano poprzez akumulatory Ni-MH w standardowym koszyczku.
Mniejsza wersja wymagała podłączenia zasilania bezpośrednio z Arduino oraz odpowiednich wyjść do pinów analogowych, aby odczytywać wartości z każdego potencjometru osobno.
Kodowanie
Pod względem programistycznym projekt obejmował stworzenie funkcji ruchu, odpowiedzialnej za poruszanie serwomechanizmami i silnikiem krokowym w pętli loop. W kodzie zastosowano filtr cyfrowy (wykładniczy I rzędu) oraz histerezy w celu wyeliminowania błędnie oscylujących wartości odczytów z potencjometrów.
Aby poprawnie odwzorować ruchy małego "drzewka" na manipulator, istotne było odpowiednie zmapowanie przefiltrowanych wartości, co wymagało wcześniejszego przetestowania odczytów z funkcji analogRead.









#include <Arduino.h>
#include <Servo.h>
#include <Stepper.h>
//Piny podłączeniowe serwomechanizmów
const int pserwo1=6;
const int pserwo2=5;
//definicja klas serwomechanizmów
Servo serwo1,serwo2;
//definicja ilości kroków silnika krokowego
const int rozdzielczosc = 2052;
//klasa silnika krokowego, podlaczasz in1-4 jako 8-11
Stepper sm=Stepper(rozdzielczosc, 8, 10, 9, 11);
//definicja parametrów filtra/u, obie formy poprawne
float alpha=0.05;
int threshold=4;
//definicja parametrów ruchowych
float s1k,s2k,smk;//serwo 1 kat, serwo 2 kat, stepper motor kat
float s1kp=0,s2kp=0,smkp=0;//poprzednie -||-
float smkd=0; //no teoretycznie docelowy kont
int delta; //liczba krokow dla silniczka
//inicjalizacja funkcji
int ruchf(int ktory);
void setup() {
//prędkość silniczka
sm.setSpeed(15);
//inicjalizacja serwomechanizmów
serwo1.attach(pserwo1);
serwo2.attach(pserwo2);
ruchf(1);
ruchf(2);
}
void loop() {
ruchf(1);
ruchf(2);
ruchf(3);
delay(15);
}
//dalej wykorzystywany jest filtr dolnoprzepustowy, ponieważ w małym stopniu przepuszcza nową wartość, zależy to od alphy, gdize tutaj jest 0.05, czyli 0.05 nowego odczytu
//stanowi o wartości kąta w kolejnym kroku, co bezposrednio spowalnia reakcje na zmiane, a tym samym ruch serwomechanizmu
int ruchf(int ktory){
if(ktory==1){
int surowypomiar1 = analogRead(A0);
s1k=alpha*(float)surowypomiar1+(1-alpha)*s1kp;
s1kp=s1k;
if(abs((int)s1k-(int)s1kp)>threshold)
s1kp=s1k;
else
s1k=s1kp;
s1k=map((int)s1k,100,800,0,180);
if(s1k < 0) s1k = 0;
if(s1k > 180) s1k = 180;
serwo1.write(s1k);
}
else if(ktory==2){
int surowypomiar2 = analogRead(A1);
s2k=alpha*(float)surowypomiar2+(1-alpha)*s2kp;
s2kp=s2k;
if(abs((int)s2k-(int)s2kp)>threshold)
s2kp=s2k;
else
s2k=s2kp;
s2k=map((int)s2k,135,850,180,0);
if(s2k < 0) s2k = 0;
if(s2k > 180) s2k = 180;
serwo2.write(s2k);
}
else if(ktory==3){
int surowypomiar3 = analogRead(A2);
smk=alpha*(float)surowypomiar3+(1-alpha)*smkp;
smkp=smk;
if(abs((int)smk-(int)smkp)>threshold)
smkp=smk;
else{
smk=smkp;
}
smk=map((int)smk,150,850,0,rozdzielczosc);
delta=(int)smk-(int)smkd;
if(delta!=0){
sm.step(delta);
smkd=smk;
}
}
}
https://www.youtube.com/watch?v=nRsaf16EdNM
https://www.youtube.com/watch?v=u5k2ewa1_is