Skocz do zawartości
Komentator

Kurs Arduino - #8 - Sterowanie silnikami DC, pętla for

Pomocna odpowiedź

Co prawda początek przeczytałem 3 razy i musze to jeszcze przetrawić, ale sporo mi pomogłeś. Oczywiście wiedza ta jest w większości zawarta w kursie, ale raz przeczytana nie do końca się wpaja komuś początkującemu takiemu jak ja.

Jak dobrze rozumiem w moim schemacie zabrakło podłączenia od arduino do masy całego układu. Czyli jednego kabelka o tak :

Jeśli chodzi natomiast o mostek i straty na nim, to zdążyłem je już zauważyć mierząc napięcie przy pierwszym podejściu. Jednak pierwszego robota chciałbym spróbować na nim ze względu na to, że już taki posiadam a podczas dopracowywania ewentualnie wymienić na lepszy mostek lub moduł zasilania.

Podpowiedz mi jeszcze Marek jak możesz, czy przy połączeniu jak wyżej do zasilania Arduino wystarczy bateria? Bo silniki będą już zasilane z koszyczka z bateriami ? Kiedy całość podłączę i zmierzę to zobaczymy ile dociera do silników.

Na chwilę obecną mam na stanie dwa koszyki na baterie. Jeden na 4AA i drugi na 2AA. Czy w tym przypadku mogę je ze sobą połączyć szeregowo ?

Udostępnij ten post


Link to post
Share on other sites

Bateria 6F22 to bardzo poręczne źródło zasilania, ale do bardzo oszczędnych układów których elektronika była projektowana pod zasilanie takich truchłem. W zależności od typu chemii "wbudowanej" do środka producenci podają pojemności w granicach 400-600mAh. Dodatkową wskazówką dla odpowiedniego sposobu używania i obciążania baterii 9V są warunki w jakich pojemność jest testowana, np:

- obciążenie opornikiem 620Ω przez 2h dziennie,
- obciążenie opornikiem 180Ω przez 30min dziennie itp

To pokazuje, że obciążenia są raczej słabe (max. 50mA) a bateria powinna mieć czas na "oddech". Acha, i napięcie końcowe takich pomiarów to np. 5.4V więc "drenują" je do granic możliwości.

Jeśli Arduino pobiera kilkadziesiąt mA (najlepiej zmierz to), to załatwi tę baterię w jeden dzień ciągłej pracy. Trochę szkoda pieniędzy. Oczywiście prąd zależy od tego co do procesora i jego 5V jeszcze podłączysz. Każda diodka LED, czujnik, wyświetlacz a nawet mostek (też potrzebuje 5V) dodają swoje.

Oczywiście możesz połączyć oba koszyczki szeregowo. Wstawiaj zawsze ten sam typ akumulatorków tak samo naładowanych. Najlepiej niech wszystkie zaczynają od 100% a po zjechaniu napięcia całego stosu do 6V (mierzonego "na pusto") lub powiedzmy do 5.4V (przy pracujących silnikach) wszystkie wyjmujesz i ładujesz do pełna.

Gdybyś miał zestaw 8 sztuk, mógłbyś zrezygnować w ogóle z dodatkowej baterii i wszystko zasilać z NiMH. Przy 6 sztukach napięcie końcowe jest trochę za małe by podtrzymać życie Arduino przez Vin, ale na świeżo naładowanych zadziała - możesz spróbować.

http://www.tme.eu/pl/Document/c0ab49f15a138bb8d6fbec84bf23388e/GP1604AU.pdf

http://www.tme.eu/pl/Document/700ee7730c341abae0d928073d095fc5/BAT-6F22_ES.pdf

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Wprawka - oba silniki LEWO, potem oba PRAWO (łączyłem bardziej ze schematu/datasheet niż fotka i chciałem sprawdzić, czy układ jest dobrze podłączony elektrycznie)

elektrycznie był OK, ale dziwne - jak się w programie zapomni włączyć PWM dla drugiego silnika - to ten nie chce działać 🤯 . . 😉

(już poprawione)

//mostek H - sterowanie silnikami (tylko kierunek)
//dla układu/mostka L293D:         3, 6   wyjścia do pierwszego silnika
//                                 11, 14  wyjścia do drugiego silnika


void setup() {
   pinMode(6, OUTPUT);     //Sygnal PWM silnika 1
   digitalWrite(6, HIGH);    //Ustawiamy (na stałe) stan wysoki: Ardu pin 6 -> L293 pin 1

   pinMode(7, OUTPUT);     //Sygnały sterujące kierunkiem obrotów silnika 1
   pinMode(8, OUTPUT);

   pinMode(9, OUTPUT);     //Synal PWM silnika 2
   digitalWrite(9, HIGH);    //Ustawiamy (na stałe) stan wysoki: Ardu pin 9 -> L293 pin 9

   pinMode(10, OUTPUT);    //Sygnały sterujące kierunkiem obrotów silnika 2
   pinMode(11, OUTPUT);
}

void loop() {
 digitalWrite(7, LOW);     //Silnik 1 - obroty w lewo
 digitalWrite(8, HIGH);
 digitalWrite(10, LOW);    //Silnik 2 - obroty w lewo
 digitalWrite(11, HIGH);
 delay(1000);

 digitalWrite(7, HIGH);     //Silnik 1 - obroty w lewo
 digitalWrite(8, LOW);
 digitalWrite(10, HIGH);     //Silnik 1 - obroty w prawo
 digitalWrite(11, LOW);
 delay(1000);
}

Rozwiązanie właściwej części zadania

1. oba LEWO, jeden PRAWO drugi LEWO, oba PRAWO;

2. wyłączanie tylko PRZEŁĄCZANEGO silnika, drugi jeśli nie ma zmieniać obrotów - pracuje

3. Sygnalizacja końca cyklu - podwójny błysk "silnikami".

//mostek H - sterowanie silnikami (tylko kierunek)
//dla układu/mostka L293D:         3, 6    wyjścia do pierwszego silnika
//                                 11, 14  wyjścia do drugiego silnika
int  NrSilnika;     //numer silnika
int  akcjaS;        //Lewo, Prawo, Stop


void setup() {
   pinMode(6, OUTPUT);     //Sygnal PWM silnika 1
   digitalWrite(6, HIGH);  //Ustawiamy (na stałe) stan wysoki: Ardu pin 6 -> L293 pin 1

   pinMode(7, OUTPUT);     //Sygnały sterujące kierunkiem obrotów silnika 1
   pinMode(8, OUTPUT);

   pinMode(9, OUTPUT);     //Sygnal PWM silnika 2
   digitalWrite(9, HIGH);  //Ustawiamy (na stałe) stan wysoki: Ardu pin 9 -> L293 pin 9

   pinMode(10, OUTPUT);    //Sygnały sterujące kierunkiem obrotów silnika 2
   pinMode(11, OUTPUT);
}

void loop() {
 silnik(1, 1);               //silnik 1: lewo
 silnik(2, 1);               //silnik 2: lewo
 delay(2000);

 silnik(1, 0);               //silnik 1: stop
 delay(1000);

 silnik(1, 2);               //silnik 1: prawo   (silnik2 nadal włączony w lewo)
 delay(2000);

 silnik(2, 0);               //silnik 2: stop
 delay(1000);

 silnik(2, 2);               //silnik 2: prawo   (silnik1 już wcześniej przełączony też w prawo)
 delay(2000);

 silnik(1, 0);               //silnik 1: stop
 silnik(2, 0);               //silnik 2: stop
 delay(1000);

 //Sygnalizacja końca cyklu (podwójny błysk na obu "silnikach"
 silnik(1, 1);               //silnik 1: lewo     - błysk
 silnik(2, 1);               //silnik 2: lewo     - błysk
 delay(300);

 silnik(1, 0);               //silnik 1: stop
 silnik(2, 0);               //silnik 2: stop
 delay(300);

 silnik(1, 1);               //silnik 1: lewo     - błysk
 silnik(2, 1);               //silnik 2: lewo     - błysk
 delay(300);

 silnik(1, 0);               //silnik 1: stop
 silnik(2, 0);               //silnik 2: stop
 delay(2000);
}

void silnik(int NrSilnika, long akcjaS) {       //Lewo, Prawo, Stop
 int pinWe, pinWy;

 if (NrSilnika==1) {      //w zależności od NrSilnika- do sterowania silnikiem
   pinWe=7;            //     zostają przydzielone odpowiednie piny Arduino
   pinWy=8;  }
 if (NrSilnika==2) {
   pinWe=10;
   pinWy=11;  }

 if (akcjaS==1) {                     //obroty w Lewo
   digitalWrite(pinWe, LOW);
   digitalWrite(pinWy, HIGH); }
 if (akcjaS==2) {                     //obroty w Prawo
   digitalWrite(pinWe, HIGH);
   digitalWrite(pinWy, LOW); }
 if (akcjaS==0) {                     //Stop
   digitalWrite(pinWe, LOW);
   digitalWrite(pinWy, LOW); }
}

Nie jestem zbyt dobry przy funkcjach (w programowaniu), więc przy okazji chciałem potrenować tworzenie funkcji z parametrami i sterowanie silnikami zrobiłem za pomocą silnik(NrSilnika, Akcja), nie do końca mi się udało - chciałem rodzaj Akcji zadawać za pomocą liter/znaków Lewo, Prawo, Stop, próbowałem przez char akcjaS;,

zadawanie parametru np silnik(1, "L");

a potem sprawdzenie warunku if (akcjaS=="L") ...

Ale nie wyszło... i musiałem parametr podawać jako "liczbę"/ int, a nie "znak"~literę.

Szkoda, obsługa programu byłaby bardziej intuicyjna...

pozdrówka - Maciek

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Zadanie 8.1

void setup() {
 pinMode(6, OUTPUT); //Sygnał PWM silnika nr 1
 digitalWrite(6, HIGH); //Stan wysoki na pinie 6
 pinMode(5, OUTPUT); // Sygnał PWM silnika nr 2
 digitalWrite(5, HIGH); // Stan wysoki na pinie 5

 pinMode(7, OUTPUT); //Sygnaly sterujace kierunkiem obrotow silnika nr 1
 pinMode(8, OUTPUT);

 pinMode(4, OUTPUT); //Sygnaly sterujace kierunkiem obrotow silnika nr 2
 pinMode(3, OUTPUT); 

}

void loop() {
 digitalWrite(7, HIGH); //do przodu
 digitalWrite(4, HIGH);
 delay(1000);

 digitalWrite(7, LOW); 
 digitalWrite(4, LOW);
 delay(1000);

 digitalWrite(8, HIGH); //przeciwnie
 digitalWrite(4, HIGH);
 delay(1000);

 digitalWrite(8, LOW); 
 digitalWrite(4, LOW);
 delay(1000);

 digitalWrite(8, HIGH); // do tylu
 digitalWrite(3, HIGH);
 delay(1000);

 digitalWrite(8, LOW); 
 digitalWrite(3, LOW);
 delay(1000);
}

zadanie 8.4

void setup() { 
 pinMode(6, OUTPUT); //Sygnał PWM silnika nr 1

 pinMode(7, OUTPUT); //Sygnały sterujące kierunkiem obrotów silnika nr 1
 pinMode(8, OUTPUT);

 digitalWrite(7, LOW); //Silnik nr 1 - obroty w lewo
 digitalWrite(8, HIGH);
 Serial.begin(9600);
} 

void loop()  { 
 for (int i = 0; i <= 255; i++) { // rozpedzania silnika
   analogWrite(6, i); 
   delay(30);   
 }
 for (int a = 255; a >= 0; a--) { // hamowanie silnika
   analogWrite(6, a);
   delay(30);
 }
}
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Cześć, mam problem ze zmianą kierunku obrotów silnika, wszytko podłączylem tak jak na schemacie z diodami i diody działają poprawnie (zmienia się kierunek prądu) lecz po podłaczeniu silnika kręci się on tylko w jedna stronę, sprawdzałem pare silników i na każdym to samo. Układ zasilam z zasilacza 12V, a napięcie wychodzące nie spada tylko jest w granicach 18,5V, podpowie ktoś co moze byc nie tak?

Udostępnij ten post


Link to post
Share on other sites

norbi312, witam na forum! Ciężko powiedzieć, co może być źle, bo nie znamy dokładnego połączenia i kodu. Jednak jeśli układ zasilasz z 12V, a na wyjściu mostka mierzysz 18V, to już jest zły sygnał, bo to raczej nie jest możliwe... Czy na pewno zasilacz daje 12V i cały układ zasilany z niego działa poprawnie?

Udostępnij ten post


Link to post
Share on other sites

Nie da się jednym arduino sterować serwem i silnikiem DC? Chodzi mi, że silnikiem steruje obrotami, a serwo pokazuje swoim ramieniem % prędkości. Np w pętli zrobić od 50% do 100%, jak zadeklaruje wyjście do sterowania serwem to mi analogWrite nie działa do silnika, czyli PWM.

Jeszcze można by na wyświetlaczu wyświetlać % 😃, ale narazie utknąłem na serwie z DC.

Udostępnij ten post


Link to post
Share on other sites

zioloiso, korzystanie z biblioteki do sterowania serwami wyłącza PWM tylko na pinach 9 i 10. Na pozostałych wszystko powinno działać poprawnie 🙂

Udostępnij ten post


Link to post
Share on other sites

Heh akurat tam podłączyłem teraz działa, na dniach pobije się z tym co wymyśliłem.

Udostępnij ten post


Link to post
Share on other sites

zioloiso, super, działaj dalej 🙂

Udostępnij ten post


Link to post
Share on other sites

Ok, poszło jak chciałem. Założenie mojego zadania było takie:

- steruje silnikiem DC L/R, mięki star z rozpędzaniem;

- powolne zatrzymywanie;

- możliwości przerwania rozpędzania spowalniania;

- zmiana kierunku odbywa się na zasadzie, że spowalnia, zatrzymuje się i rusza w przeciwnym kierunku;

- serwo pokazuje % obrotów;

- LCD pokazuje kierunek i prędkość;

Użyłem w programie, 3 przyciski, lcd, serwo, i silnik dc z mostkiem;

#include <Servo.h> // biblioteka serwa
#include <LiquidCrystal.h> //Dołączenie bilbioteki

Servo serwomechanizm; // obiet dzieki ktoremu mozemy sie odwolac do serwa
LiquidCrystal lcd(8, 9, 10, 11, 12, 13); //Informacja o podłączeniu nowego wyświetlacza

#define prstop 6 // stop
#define lewo 7 // przycisk startu w lewo
#define prawo 0 // przycisk startu w prawo

boolean st1 = false; // zmienna wyjscia 4
boolean st2 = false; // zmienna wyjscia 5
boolean ststop = false; // spr czy przerwano stop
int pr = 100; // pr zadana analogowego wyjscia
int zmiana = 1;  // zmiana  o ile

void setup() { 
 Serial.begin(9600);// ustawienie uart
 serwomechanizm.attach(2); // serwomechanizm podlaczony do pinu 9
 serwomechanizm.write(180); // pozycja zero serwa
 pinMode(10, OUTPUT); //Sygnał PWM silnika nr 1
 pinMode(4, OUTPUT); //Sygnały sterujące kierunkiem obrotów silnika nr 1
 pinMode(5, OUTPUT);

 pinMode(lewo, INPUT_PULLUP); // przycisk w lewo
 pinMode(prstop, INPUT_PULLUP); // przycisk stop
 pinMode(prawo, INPUT_PULLUP); // przycisk w prawo  
 digitalWrite(4,LOW); // kierunek obr silnika off
 digitalWrite(5,LOW);

 //lcd startowe
 lcd.begin(16, 2); //Deklaracja typu
 lcd.setCursor(0, 0); //Ustawienie kursora
 lcd.print("KIERUNEK:"); // napisa na wyś 
 lcd.setCursor(9, 0); 
 lcd.print("STOP ");
 lcd.setCursor(0, 1); //ustawienie kursora w 2 wierszu
 lcd.print("PREDKOSC:");
 lcd.setCursor(9, 1);
 lcd.print("0  ");
 lcd.setCursor(13, 1);
 lcd.print("[%]");
} 

void strwys(int  pr, boolean st1, boolean st2) // wyswietlanie na lcd predkosci w % i stanu
{   
   int wys = map(pr, 100, 255, 1, 100); // przeskalowanie predkosci na procenty i wys
   lcd.setCursor(9, 1);
   lcd.print(wys);
   lcd.setCursor(13, 1);
   lcd.print("[%]");

   if(st1 == true && st2 == false) // sprawdzenie czy kierunek to lewo
   {
     lcd.setCursor(9, 0);
     lcd.print("LEWO  ");
   }
   if(st1 == false && st2 == true) // sprawdzanie czy kierunek to prawo
   {
     lcd.setCursor(9, 0);
     lcd.print("PRAWO");
   }
   if(wys<100) // kasuje zero po 100%
   {
     lcd.setCursor(11, 1);
     lcd.print(" ");
   }
   if(wys<10) // kasuje zero po 10%
   {
     lcd.setCursor(10, 1);
     lcd.print(" ");
   }

   if(pr<101) // silnik stoi
   {
     lcd.setCursor(9, 1);
     lcd.print("0  ");
     lcd.setCursor(9, 0); 
     lcd.print("STOP ");
   }
}

void strservo(int pr) // wskazywanie serwem ile % obr
{
   int serwo = map(pr, 100 , 255 , 180, 0); // przemapowanie pozycji serwa
   serwomechanizm.write(serwo); // wykonaj ruch
}

void silniklewo(int & pr, int zmiana,boolean & st1, boolean & st2) // funkcja sterujaca w lewo
{  
   if(st1 == false && st2 == true) // sprawdzam czy nie kreci sie w przeciwnym kierunku
   {
     silnikstop(pr,zmiana,st1,st2);      
   }    
   if(ststop == true)
   {
     return;
   }
   st1=true;
   st2=false;
   digitalWrite(4,HIGH);
   digitalWrite(5,LOW);      
   do{
   if(digitalRead(prstop) == LOW) // przerwanie procedury rozpedzania
   {
     break;
   }
   analogWrite(3, pr);         
   pr=pr+zmiana;
   strservo(pr);
   strwys(pr,st1,st2);
   delay(100);
   }while(pr<255);       
}

void silnikprawo(int & pr, int zmiana,boolean & st1, boolean & st2) // fukcja sterujaca silnikiem w prawo
{
   if(st1 == true && st2 == false) // sprawdzam czy nie kreci sie w przeciwnym kierunku
   {
     silnikstop(pr,zmiana,st1,st2);      
   }
   if(ststop == true)
   {
     return;   
   }
   st1=false;
   st2=true;  
   digitalWrite(4,LOW);
   digitalWrite(5,HIGH);  
   do{
   if(digitalRead(prstop) == LOW) // przerwanie procedury rozpedzania
   {
     break;
   }
   analogWrite(3, pr);      
   pr=pr+zmiana;
   strservo(pr);
   strwys(pr,st1,st2);
   delay(150);
   }while(pr<255);      
}

void silnikstop(int & pr, int zmiana,boolean & st1, boolean & st2) // zatrzymywanie silnika
{
   delay(200); // żeby prog nie głupiał
   do{
     if(digitalRead(prstop) == LOW) // przerwanie procedury stopu
     {
      ststop = true; // przerywamy procedure stop
      return;        
     }
     analogWrite(3, pr); 
     pr=pr-zmiana;
     strservo(pr);
     strwys(pr,st1,st2);
     delay(75);
   }while(pr>100);
   st1=false; // informuje prog ze silnik stop
   st2=false; 
   digitalWrite(4,LOW); // kierunek obr silnika off
   digitalWrite(5,LOW); 
   ststop = false; // info ze nie przerwalismy
   delay(500); // zaczekanie na calkowite zatrzymanie silnika   
 } 

void loop()  {   
   delay(150); // żeby prog nie głupiał  
   if(digitalRead(prstop) == LOW) // czy przycisk stop wcisniety
   {  
     silnikstop(pr,zmiana,st1,st2);    
   }

   if(digitalRead(lewo) == LOW) // czy przycisk w lewo wcisniety
   {      
     silniklewo(pr,zmiana,st1,st2);
   }  

   if(digitalRead(prawo) == LOW) // czy przycisk w prawo wcisniety
   {      
     silnikprawo(pr,zmiana,st1,st2);
   }     
   ststop = false; 
   delay(150); // żeby prog nie głupiał                            
}

Zastanawiam się jak by można kod zoptymalizować, żeby uczył się ładniejsze prog pisać. Można by jeszcze dodać sterowanie UART na switchu np, spr if czy sa dane, jeśli tak to switch i gra. Filmu nie wrzuce jednak bo moja kamera w telefonie jest po przejściach.

Udostępnij ten post


Link to post
Share on other sites

zioloiso, nie sprawdzałem, czy układ działa w praktyce (wierzę, że działa) - kod wygląda ładnie. Jak na ten etap kursu, to bardzo ładnie 😉 Polecam skupić się na dalszym poznawaniu Arduino i dodawaniu nowych peryferiów. Na pewno nauczysz się wtedy więcej, niż podczas takiej optymalizacji programów "na siłę", aby były jeszcze ładniejsze. Zawsze da się "coś" poprawić, trzeba jednak kiedyś uznać, że dany program jest skończony 😉

Udostępnij ten post


Link to post
Share on other sites

Dzięki za opinie, zamieszczę krótki film:

Planuje, dokończyć kurs i przerobić podstawy elektroniki i lutowania. Może wtedy ruszę dopiero na 2 poziom arduino lub elektroniki.

Dzięki za świetną prace jaką jest to miejsce.

Udostępnij ten post


Link to post
Share on other sites

zioloiso, super wygląda bardzo fajnie! Kurs elektroniki + lutowanie, to dobra kontynuacja 🙂

Udostępnij ten post


Link to post
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!

Gość
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...