Skocz do zawartości

Sterowanie precyzyjne silnikami DC


osoba1234

Pomocna odpowiedź

Będąc na etapie stworzenia modelu manipulatora jako pracy inżynierskiej. Wstępnie wybrałem silnik DC z enkoderami, zastanawiałem się nad wyborem silników krokowym jednak że ze względu na wymiary wybrałem silnik DC. Czy da się precyzyjnie sterować ruchem tych silników na układzie Arduino, sterowania nie oczekuje jakiegoś skomplikowanego, bardziej prostego, zależało by mi na uzyskaniu możliwości manualnego uzyskania pozycji, a potem z poziomu programu wczytania tej pozycji.  Czy może jednak należało by zmienić jednak te silniki na silniki krokowe?

Link do komentarza
Share on other sites

Zrobić się da, pytanie jak łatwiej. Na pewno łatwiej będzie zakupić silniki krokowe ale łatwiej znaczy drożej, dlatego w drukarkach np. często są stosowane silniki DC z fotoenkoderami. Arduino powinno sobie spokojnie poradzić z tego typu silnikiem, są nawet dedykowane do tego celu układy scalone, które świetnie z arduino współpracują.

 

Link do komentarza
Share on other sites

(edytowany)

Zależało by mi na jednak silnikach DC z enkoderami ponieważ posiadam już zrobiony model gdzie jego przebudowa by zajęła sporo czasu. Pytanie moje czy jak posiadam silnik DC z przekładnią dało by się zrobić programowo wraz z mostkiem układem mostka H, tak żeby silnik wykonywał ruch o zadany programowo kąt? Jeżeli tak to w jaki sposób się do tego zabrać? Silnik to: Silnik z przekładnią 25Dx58L 499.1:1 6V 11RPM. Tworząc układ sterowania i obliczający programowo że po zbliżeniu się o określoną wartość do punkt docelowego ma zwolnić a później zatrzymać, pytanie moje czy nie będzie jakiegoś przeskoku impulsów, oraz jak sprawdzać na bierząco impulsy z enkodera?

Edytowano przez osoba1234
Link do komentarza
Share on other sites

23 minuty temu, osoba1234 napisał:

Tworząc układ sterowania i obliczający programowo że po zbliżeniu się o określoną wartość do punkt docelowego ma zwolnić a później zatrzymać, pytanie moje czy nie będzie jakiegoś przeskoku impulsów

Aby zrobić to precyzyjnie musisz zastosować "rampę" dla startu i zatrzymania (chyba, że wszystko może działać wolno) wtedy sterujesz silnikiem ze stałym niedużym wypełnieniem PWM. Warto pamiętać, że mostkiem H, można silnik hamować.

 

24 minuty temu, osoba1234 napisał:

oraz jak sprawdzać na bierząco impulsy z enkodera

Na przerwaniach.

 

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Nie masz chyba zbyt dużego doświadczenia z mikrokontrolerami i programowaniem, prawda? Cóż, nie liczył bym na to, że ktoś mi napisze pracę inżynierską na forum internetowym. Podchodząc poważnie do tematu jakieś minimum wiedzy z jego zakresu wypadałoby jednak mieć. Mógłbym próbować pomóc w jakichś szczegółowych kwestiach w granicach wiedzy jaką posiadam ale kiedy nie wiesz nawet jak się za to zabrać..

32 minuty temu, osoba1234 napisał:

Pytanie moje czy jak posiadam silnik DC z przekładnią dało by się zrobić programowo wraz z mostkiem układem mostka H, tak żeby silnik wykonywał ruch o zadany programowo kąt?

Tak da się to zrobić i nie jest to wybitnie trudne ale nie liczysz chyba na to, że będę Ci tu wykładał wszystko od podstaw. Zachęcam do zapoznania się na początek z treścią kursu arduino w dziale "Kursy".

Żeby w ogóle było się nad czym zastanawiać trzeba znać typ tego enkodera i jego rozdzielczość.

Link do komentarza
Share on other sites

(edytowany)

Po głębszym zastanowieniu się zdecydowałem się na zastosowanie do sterownia kilku układów arduino. Silniki z enkoderami link z różnymi konfiguracjami przekładni.

 

W projekcie posiadam zastosowanych kilka rodzaju konfiguracji tego typu silników z enkoderami. Sterowanie w zamiarze ma być sterowaniem prostym.

 

Założyłem że robot będzie poruszał się w przestrzeni trzech pozycji. Do każdego z silników wraz z enkoderami jest zastosowane oddzielny układ arduino uno. Sprzężony wraz z układem sterującym jakim jest układ arduino mega. Sterowanie odbywa się po przez odpowiednie ustawianie stanów na wyjściach arduino uno oraz odpowiednio wysyłanych wartościach po przez arduino mega na pinu analogowe do układów arduino uno.

Poniżej przedstawiam kod do sterowania dwoma silnikami. Chciałbym prosić o wyrażenie swojej opini na ten temat. Kod nie jest w pełni skończony. Układ dla układu z kolejnymi silnikami będzie oparty na takiej samej zasadzie. Chciałbym się zorientować co do poprawności logiki jego wykonania. Ze względu na posiadane układy arduino, jakość ich wykonania powoduje problemy w komunikacji między nimi. Podczas praktycznego sprawdzenia działania układu. Kod ma być poprawny w teorii, ponieważ nie posiadam obowiązku tworzenie modelu rzeczywistego.

Ustawianie pozycji będzie się odbywało z poziomu pilota IR dołączonego do arduino mega wraz z wyświetlaczami. Manipulator posiada z góry określoną liczbę 3 pozycji gdzie 1 i 3 są to pozycje dojazdowe oraz 2 jest pozycją odjazdową

Docelowo jeżeli czas na to pozwoli chciałbym oprzeć przesyłanie stanów nie poprzez wyjście, tylko wykorzystać do tego magistralę I2C.  Ponieważ aktualnie posiadam problem z komunikacją obustronną kilku układów. Jedynie posiadam pewną komunikację jednostronną od głównego do podrzędnych.

Poniżej przedstawiony kod nie obejmuje części z przesyłem na I2C celem jego jest uzyskanie sekwencji oraz współgrania dwóch silników ze sobą w zadanej sekwencji ruchu.

Kod do układów arduino uno

#include "PinChangeInterrupt.h"
const byte encoder0pinA = 2;
const byte encoder0pinB = 3;

byte encoder0PinALast;
long duration;// liczba impulsow

long ilosc = 0; // ilosc zliczonych impulsow odczytana z enkodera

long pozycja1 = 1000; // pozycje dojazdowe
long pozycja2 = 2000;
long pozycja3 = 5000;

int dojazddo1; 
int dojazddo2;
int dojazddo3 ;

int a=0; // zmienne sluzace do ustawienia odpowiednich wartosci na stanach po osiagnieciu zadanej pozycji oraz po resencje pozycji
int b=0;
int c=0;

int do1=0; // zmienne sluzace do okreslenia jaki punkt okreslony w liczbie impulsow ma osiagnac silnik
int do2=0;
int do3=0;

int wyjscie1 = 0;// zmienne sluzace do wyslania iformacji po okresleniu pozycji
int wyjscie2 = 0;
int wyjscie3 = 0;

void setup() {

Serial.begin(9600);
EncoderInit();// inicjalizacja enkodera
attachPinChangeInterrupt(digitalPinToPinChangeInterrupt(9),zerowanie,HIGH); // inicjalizacja dla czujnika krancowego do zerowania pozycji
pinMode(12,INPUT_PULLUP); // przycisk dla ruchu silnika w prawo/lewo
pinMode(13,INPUT_PULLUP); // przycisk dla ruchu silnika w prawo/lewo

pinMode(4,OUTPUT); // wyjscia do sterowania kierunkiem ruchu silnika
pinMode(5,OUTPUT);

pinMode(10,OUTPUT); // wyjscie dla pwm silnika

pinMode(6,OUTPUT); // dojazd do pozycji1
pinMode(7,OUTPUT); // dojazd do pozycji2
pinMode(11,OUTPUT); // dojazd do pozycji3
pinMode(8,INPUT); // wejscie dla akutwyacji trybu automatycznego z ukadlu arduino mega

}

void loop() 
{
int pwm = analogRead(A0); // sterowanie wartosci pwm silnika za pomoca potencjomteru
pwm = map(pwm,0,1023,0,255);
analogWrite(10,pwm);

a = analogRead(A1); // odczytywanie wartosci do jakich pozcyji ma dojechac silnik z ukladu arduino mega
b = analogRead(A2);
c = analogRead(A3);

if(a<=100) // przypisanie na podstawie odczytanych wartosci stanow 0/1
{
do1 = 0;  
}
if(a>=200)
{
do1=100;  
}

if(b<=100)
{
do2=0;  
}
if(b>=200)
{
do2=100;  
}

if(c<=100)
{
do3 = 0;  
}
if(c>=200)
{
do3=100;  
} 

if(wyjscie1==0) // przypisanie wartosci stanow na wyjsciach w zaleznosci od osiagnietej pozycji przez silnik
{
 digitalWrite(6,LOW); 
}
if(wyjscie1==1)
{
 digitalWrite(6,HIGH); 
}

if(wyjscie2==0)
{
 digitalWrite(7,LOW); 
}
if(wyjscie2==1)
{
 digitalWrite(7,HIGH); 
}

if(wyjscie3==0)
{
 digitalWrite(11,LOW); 
}
if(wyjscie3==1)
{
 digitalWrite(11,HIGH); 
}

//Serial.println(do1);
//Serial.println(do1);
//Serial.println(do1);

//Serial.print("Przycisk lewy: ");
//Serial.print(digitalRead(7));
//Serial.print("Przycisk prawy: ");
//Serial.print(digitalRead(13));
//Serial.print("Przycisk dojazd do pozycji: ");
//Serial.println(digitalRead(11));

if(digitalRead(12)==LOW and digitalRead(13)==HIGH) // ruch silnika po nacisnieciu przycisku w prawo/lewo
{
digitalWrite(4,HIGH);
digitalWrite(5,LOW);

}
if(digitalRead(13)==LOW and digitalRead(12)==HIGH) // ruch silnika po nacisnieciu przycisku w prawo/lewo
{
digitalWrite(5,HIGH);
digitalWrite(4,LOW);  
}

if(digitalRead(13)==HIGH and digitalRead(12)==HIGH) // zatrzymanie silnika gdy zaden z pprzyciskow nie jest nacisniety
{
digitalWrite(5,LOW);
digitalWrite(4,LOW);  
}

if(digitalRead(13)==HIGH and digitalRead(12)==HIGH and digitalRead(8)==HIGH) // gdy zadnej przycisk nie jest nacisniety automatyczny ruch silnika
{
  
// do 2 na poczatku

if(digitalRead(12)==HIGH and digitalRead(13)==HIGH and do1==0 and do2==0 and do3==0)
{
  ilosc = pozycja2;
    if(duration>=ilosc-50 and duration<=ilosc+50)
{
wyjscie1=0;
wyjscie2=1;
wyjscie3=0;
}
silnik11();
silnik1();
}

//z pozycji 2 do pozcji 1

if(digitalRead(12)==HIGH and digitalRead(13)==HIGH and do1!=0 and do2!=0 and do3==0)
{
  ilosc = pozycja1;
    if(duration>=ilosc-50 and duration<=ilosc+50)
{
wyjscie1=1;
wyjscie2=0;
wyjscie3=0;
digitalWrite(6,HIGH);
digitalWrite(7,LOW);
digitalWrite(11,LOW);
} 
silnik11();
silnik1();

}

// z pozycji 1 do pozycji 2
if(digitalRead(12)==HIGH and digitalRead(13)==HIGH and do1!=0 and do2==0 and do3!=0)
{
ilosc = pozycja2;
  if(duration>=ilosc-50 and duration<=ilosc+50)
{
wyjscie1=0;
wyjscie2=1;
wyjscie3=1;
}
silnik11();
silnik1();
}

// z pozycji 2 do pozycji 3
if(digitalRead(13)==HIGH and digitalRead(12)==HIGH and do1==0 and do2==0 and do3!=0)
{
ilosc = pozycja3;
  if(duration>=ilosc-50 and duration<=ilosc+50)
{
wyjscie1=1;
wyjscie2=1;
wyjscie3=1;
}
silnik11();
silnik1();
}

}
if(digitalRead(8)==LOW) // zerowanie pozycji ukladu gdy tryb automatyczny jest wylaczony
{
wyjscie1=1;
wyjscie2=1;
wyjscie3=1;  
}
}

void EncoderInit()
{
  Direction = true;//default -> Forward
  pinMode(encoder0pinB,INPUT);
  attachInterrupt(0, wheelSpeed1, RISING);
}

void wheelSpeed1() // zliczanie impulsow
{
    if (digitalRead(3))
    {duration++;
    }
  else
      duration--;
}

void silnik1() // ruch silnika do zadanej pozycji oraz jej utrzymywanie
{
  while(duration<=ilosc)
  {
   digitalWrite(5,HIGH);
   digitalWrite(4,LOW);
   Serial.println("silnik 1      ");
   Serial.print(duration);
  }  
}

void silnik11()
{
    while(duration>=ilosc)
  {
   digitalWrite(4,HIGH);
   digitalWrite(5,LOW);
   Serial.println("silnik 1   ");
   Serial.print(duration);
  }  
}

void zerowanie() // zerowanie pozycji silnika
{
 duration=0; 
}

 

Kod dla układu arduino mega

void setup() 

{
Serial.begin(9600);
// silnik 1 wejscie odbierajace informacje o osiagnieciu pozycji przez silnik 1
pinMode(30,INPUT); // wyjscie 6 ukladu arduino uno
pinMode(31,INPUT); // wyjscie 7 ukladu arduino uno
pinMode(32,INPUT); // wyjscie 11 ukladu arduino uno
// wyjscie do okreslania jaka pozycję ma osiągnąć silnik 1
pinMode(33,OUTPUT); // wejscie A1 ukladu arduino uno
pinMode(34,OUTPUT); // wejscie A2 ukladu arduino uno
pinMode(35,OUTPUT); // wejscie A3 ukladu arduino uno

pinMode(7,OUTPUT); // wyjscie do zalaczania trybu automatycznego silnika 1

// silnik 2 wejscie odbierajace informacje o osiagnieciu pozycji przez silnik 2
pinMode(36,INPUT); // wyjscie 6 ukladu arduino uno
pinMode(37,INPUT); // wyjscie 7 ukladu arduino uno
pinMode(38,INPUT); // wyjscie 11 ukladu arduino uno
// wyjscie do okreslania jaka pozycję ma osiągnąć silnik 2
pinMode(39,OUTPUT); // wejscie A1 ukladu arduino uno
pinMode(40,OUTPUT); // wejscie A2 ukladu arduino uno
pinMode(71,OUTPUT); // wejscie A3 ukladu arduino uno

pinMode(8,OUTPUT); // wyjscie do zalaczania trybu automatycznego silnika 1

pinMode(11,INPUT_PULLUP); // wlaczanie trybu automatycznego po przez wcisniecie przycisku bistabilnego

}

void loop() 
{

analogWrite(33,200); // ustawienie stanow wysokich na wysciach dla obu silnikow
analogWrite(34,200);
analogWrite(35,200);

analogWrite(39,200);
analogWrite(40,200);
analogWrite(41,200);

//Serial.println(digitalRead(11));

if(digitalRead(11)==LOW) // wlaczenie trubu automatycznego
{
digitalWrite(7,HIGH);
digitalWrite(8,HIGH);

// z dowlonej pozycji do 2

if(digitalRead(30)==HIGH and digitalRead(31)==HIGH and digitalRead(32)==HIGH and digitalRead(36)==HIGH and digitalRead(37)==HIGH and digitalRead(38)==HIGH || digitalRead(30)==LOW and digitalRead(31)==HIGH and digitalRead(32)==LOW and digitalRead(36)==HIGH and digitalRead(37)==HIGH and digitalRead(38)==HIGH || digitalRead(36)==LOW and digitalRead(37)==HIGH and digitalRead(38)==LOW and digitalRead(30)==HIGH and digitalRead(31)==HIGH and digitalRead(32)==HIGH)
{
analogWrite(33,0);
analogWrite(34,0);
analogWrite(35,0);

analogWrite(39,0);
analogWrite(40,0);
analogWrite(41,0);
}

// z pozycji 2 do pozycji 1

if(digitalRead(30)==LOW and digitalRead(31)==HIGH and digitalRead(32)==LOW and digitalRead(36)==LOW and digitalRead(37)==HIGH and digitalRead(38)==LOW || digitalRead(30)==LOW and digitalRead(31)==HIGH and digitalRead(32)==LOW and digitalRead(36)==HIGH and digitalRead(37)==LOW and digitalRead(38)==LOW || digitalRead(36)==LOW and digitalRead(37)==HIGH and digitalRead(38)==LOW and digitalRead(30)==HIGH and digitalRead(31)==LOW and digitalRead(32)==LOW)
{
analogWrite(33,200);
analogWrite(34,200);
analogWrite(35,0);
analogWrite(39,200);
analogWrite(40,200);
analogWrite(41,0);
}

// oba sa w 1

// z pozycji 1 do pozycji 2
if(digitalRead(30)==HIGH and digitalRead(31)==LOW and digitalRead(32)==LOW and digitalRead(36)==HIGH and digitalRead(37)==LOW and digitalRead(38)==LOW || digitalRead(30)==HIGH and digitalRead(31)==LOW and digitalRead(32)==LOW and digitalRead(36)==LOW and digitalRead(37)==HIGH and digitalRead(38)==HIGH || digitalRead(36)==HIGH and digitalRead(37)==LOW and digitalRead(38)==LOW and digitalRead(30)==LOW and digitalRead(31)==HIGH and digitalRead(32)==HIGH)
{
analogWrite(33,200);
analogWrite(34,0);
analogWrite(35,200);

analogWrite(39,200);
analogWrite(40,0);
analogWrite(41,200);
}

// z pozycji 2 do pozycji 3
if(digitalRead(30)==LOW and digitalRead(31)==HIGH and digitalRead(32)==HIGH and digitalRead(36)==LOW and digitalRead(37)==HIGH and digitalRead(38)==HIGH || digitalRead(30)==HIGH and digitalRead(31)==HIGH and digitalRead(32)==HIGH and digitalRead(36)==LOW and digitalRead(37)==HIGH and digitalRead(38)==HIGH || digitalRead(36)==HIGH and digitalRead(37)==HIGH and digitalRead(38)==HIGH and digitalRead(30)==LOW and digitalRead(31)==HIGH and digitalRead(32)==HIGH)

{
analogWrite(33,0);
analogWrite(34,0);
analogWrite(35,200);

analogWrite(39,0);
analogWrite(40,0);
analogWrite(41,200);
}

}

if(digitalRead(11)==HIGH) // ustawienie wartosci gdy tryb automatyczny jest wylaczony
{
digitalWrite(7,LOW);
analogWrite(33,200);
analogWrite(34,200);
analogWrite(35,200);
digitalWrite(8,LOW);
analogWrite(39,200);
analogWrite(40,200);
analogWrite(41,200);
}
}

 

Edytowano przez osoba1234
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.