Skocz do zawartości

Problem z działaniem robota po dołączeniu serwa.


MarJanPol

Pomocna odpowiedź

Witam, napisałem program do kontroli pojazdu-robota za pomocą akcelerometru w smartphonie. Wszystko dzialalo jak należy. Jednak gdy dodalem serwo z funkcją sterowania suwakiem na telefonie nagle prawe koła przestały się kręcić. Po odłączeniu serwa i wgraniu poprzedniego kodu wszystko działa. Czy może ktoś domyśla się co jest przyczyną? Serwo mam zasilone z L298N

//Napisany pod UNO i RoboRemo. 
//Przed wgraniem wyjąć moduł BT z Arduino i włożyć dopiero po zakońćzeniu wgrywania żeby nie było konfliktu z UART
//W aplikacji RoboRemo ustawić akcelerometr i tylko dane x i y. ID: X, lub Y, czyli X lub Y pisane dużą literą i zaraz potem przecinek. gain=1,0. output int od 0 do 255
//zaznaczyć limit to [min, max].NIE WYSYŁAĆ SPACJI

#include <Servo.h> //Biblioteka odpowiedzialna za serwa
Servo serwomechanizm;  //Tworzymy obiekt, dzięki któremu możemy odwołać się do serwa 

int ENA=10;    //adjusting speed - prawe koła
int ENB=5;     //adjusting speed - lewe koła
int IN1=2;     // defining pin2 left rear
int IN2=4;     // defining pin4 left front
int IN3=7;     // defining pin7 right rear
int IN4=8;     // defining pin8 right front
int PWM_A=0;   //prędkość prawych
int PWM_B=0;   //prędkość lewych
int factor;    //współczynnik pomocniczy służący do procentowej zmiany prędkości w przód kół prawych lub lewych w zależoności od wyhylenia komórki na boki

int Iwart; //potrzebne do konwersji z tablicy znaków na wartość integer
char* znak; //potrzebne do zapisania pierwszego znaku - X lub Y po parsowaniu
char* Twart; //potrzebne do zapisania znaków liczbowych w tablicy po parsowaniu
int iX; //służy do przypisania wartości Iwart pochodząych z akcelerometra dla ruchów prawo-lewo
int iY; //służy do przypisania wartości Iwart pochodząych z akcelerometra dla ruchów przód-tył
int iS;
const byte numChars = 6; //określa ilość bajtów (znaków) w tablicy receivedChars. Potrzebnych jest: jeden znak na X lub Y, drugi znak na przecinek, trzy znaki na cyfry 
                        //i ostatni znak na znak zakończenia linii którego nie widać ale który jest wysyłany przez acclerometr
char receivedChars[numChars];   // an array to store the received data
boolean newData = false; //flaga - operator 

void setup() {
 serwomechanizm.attach(3);  //Serwomechanizm podłączony do pinu 3

 pinMode(ENA,OUTPUT); // pin10 (PWM)
 pinMode(ENB,OUTPUT); // pin11 (PWM) 
 pinMode(IN1,OUTPUT); // pin2
 pinMode(IN2,OUTPUT); // pin4
 pinMode(IN3,OUTPUT); // pin7 
 pinMode(IN4,OUTPUT); // pin8

 Serial.begin(9600);
 //Serial1.begin(9600);
// while (!Serial); //gdyby miało pracować z Leonardo
}

void loop() {
       recvWithEndMarker(); //idź do funkcji odpowiedzialnej za przyjęcie danych przychodzących po UART z akcelerometra
       if (newData == true) //działaj poniżej tylko jeśli flaga ustawiona na true
         {parseData(); //idź do funkcji parsowania - czyli wydzielenia z przychodzących danych tego co nas interesuje i przypisania wartości odpowiednim zmiennym
  //       showParsedData(); //funkcja testowa wyświetlania wartości sparsowanych na monitorze portu szeregowego 
         sprawdzenie(); //sprawdzenie jakie wartości przyszły z akcelerometra i w zależności od tych wartości przejście do odpowiedniej funkcji ruchu 
         newData = false;} //po przerobieniu nowych danych można już "podnieść" flagę "false"
}

void recvWithEndMarker() //funkcja odpowiedzialna za przejęcie danych przychodzących po UART (czyli w tym wypadku przez Bluetooth z accelerometru) do tabicy receivedChars
{
   static byte ndx = 0;
   char endMarker = '\n'; //określa jaki znak kończy daną porcję znaków przychodzących po UART. 
                          //W tym wypadku jest to znak nowej linii bo w monitorze portu szeregowego można było zobaczyć, 
                          //że każda porcja informacji przychodząca z akcelerometru - czyli koljeno wartości przypsane do X lub Y - zaczynają się od nowej linii
   char rc;

/*gdy pojawiły się jakieś dane z UART w buforze pamięci mikroprocesora i flaga jest ustawiona na false 
to działaj. Przypisuj kolejno pojedyncze znaki z bufora pamięci do zmiennej rc a następnie do kolejnych komórek tablicy receivedChars 
dotąd aż nie pojawi się znak kończący '\n'. Gdyby znaków było więcej niż komórek w tablicy to cały czas nadpisuj ostatnią komórkę tej tablicy nowym znakiem
Jeśli w końcu pojawi się znak kończący '\n' to przypisz ostatniej komórce znak '\0' oznaczający dla komputera koniec łańcucha znaków.
Zmień flagę na true i na chwilę przestań zajmować się znakami w buforze pamięci nawet gdyby tam były. W razie czego poczekają one tam chwilę 
ale raczej ich jeszcze nie będzie bo dane z UART przychodzą wolniej niż wykonywane są kolejne operacje przez mikroprocesor. Wróć do funkcji loop 
*/    
   while (Serial.available() > 0 && newData == false) //Serial1 - gdyby miało pracować z Leonardo
   {
       rc = Serial.read();//Serial1 - gdyby miało pracować z Leonardo

       if (rc != endMarker) {
           receivedChars[ndx] = rc;
           ndx++;
           if (ndx >= numChars) {
               ndx = numChars - 1;
           }
       }
       else {
           receivedChars[ndx] = '\0'; // terminate the string
           ndx = 0;
           newData = true;
       }
   }
}

void parseData() //parsowanie czyli podział danych zapisanych w tablicy na części. Elementem rozdzielającym jest przecinek
{    
   znak = strtok(receivedChars,",");      // get the first part - the string
   Twart = strtok(NULL, ","); // this continues where the previous call left off
   Iwart = atoi(Twart);     // convert this part to an integer
   if (znak[0]=='X')
   iX = Iwart;
   if (znak[0]=='Y')
   iY = Iwart;
   if (znak[0]=='S')
   iS = Iwart;
}
void sprawdzenie()
{
 if (znak[0]=='S')
 {
  serwomechanizm.write(iS); //Wykonaj ruch
 }
 if (iY<118 && iX>117 && iX<139) //PRZÓD PROSTO
{
 PWM_A = map(iY,117,0,50,255); 
 PWM_B = map(iY,117,0,50,255);
 przod();
}

if (iY>138 && iX>117 && iX<139) //TYŁ PROSTO
{
 PWM_A = map(iY,139,255,50,255); 
 PWM_B = map(iY,139,255,50,255);
 tyl();
}

 if (iY>117 && iY<139 && iX>117 && iX<139) //ZATRZYMANIE
{
 PWM_A = 0; 
 PWM_B = 0;
 zatrz();
}

if (iY<118 && iX<118) //PRZÓD PRAWO
{
 factor = map(iX,117,0,100,0);
 PWM_A = (map(iY,117,0,50,255))*factor/100; 
 PWM_B = map(iY,117,0,50,255);
 przod();
}

if (iY<118 && iX>138) //PRZÓD LEWO
{
 factor = map(iX,139,255,100,0);
 PWM_A = map(iY,117,0,50,255); 
 PWM_B = (map(iY,117,0,50,255))*factor/100;
 przod();
}

if (iY>138 && iX<118) //TYL PRAWO
{
 factor = map(iX,117,0,100,0);
 PWM_A = (map(iY,139,255,50,255))*factor/100; 
 PWM_B = map(iY,139,255,50,255);
 tyl();
}

if (iY>138 && iX>138) //TYL LEWO
{
 factor = map(iX,139,255,100,0);
 PWM_A = map(iY,139,255,50,255); 
 PWM_B = (map(iY,139,255,50,255))*factor/100;
 tyl();
}
/*
if (iY>117 && iY<139 && iX<118) //DOOKOŁA PRAWO
{
 PWM_A = map(iX,117,0,50,255); 
 PWM_B = map(iX,117,0,50,255);
 prawo();
}

if (iY>117 && iY<139 && iX>138) //DOOKOŁA LEWO
{
 PWM_A = map(iX,117,0,50,255); 
 PWM_B = map(iX,117,0,50,255);
 lewo();
}
*/
}

/*
void showParsedData() 
{
   Serial.print("znak: ");
   Serial.println(znak);
   Serial.print("wartosc: ");
   Serial.println(Iwart);
}
*/

void przod()
{
 analogWrite(ENA,PWM_A);
 analogWrite(ENB,PWM_B);
 digitalWrite(IN1,0);
 digitalWrite(IN2,1);
 digitalWrite(IN3,0);  
 digitalWrite(IN4,1);
}

void tyl()
{
 analogWrite(ENA,PWM_A);
 analogWrite(ENB,PWM_B);
 digitalWrite(IN1,1);
 digitalWrite(IN2,0);
 digitalWrite(IN3,1);  
 digitalWrite(IN4,0);
}

void prawo()
{
 analogWrite(ENA,PWM_A);
 analogWrite(ENB,PWM_B);
 digitalWrite(IN1,1);
 digitalWrite(IN2,0);
 digitalWrite(IN3,0);  
 digitalWrite(IN4,1);
}

void lewo()
{
 analogWrite(ENA,PWM_A);
 analogWrite(ENB,PWM_B);
 digitalWrite(IN1,0);
 digitalWrite(IN2,1);
 digitalWrite(IN3,1);  
 digitalWrite(IN4,0);
}

void zatrz()
{
 analogWrite(ENA,PWM_A);
 analogWrite(ENB,PWM_B);
 digitalWrite(IN1,1);
 digitalWrite(IN2,1);
 digitalWrite(IN3,1);  
 digitalWrite(IN4,1);
}

the

Link do komentarza
Share on other sites

Wcześniej serwo podłączyłem bezpośrednio do UNO ale ponieważ prawe kola zaczely wariować to znaczy przestały się obracać więc pomysłami że może serwo wprowadza jakieś zakłócenia. Dlatego zasilanie serwa przeniosłem na L298N (na stabilizowane wyjście 5v) zeby wykorzystać zewnętrzne zasilanie. Nic to jednak nie pomogło - działa tak samo wadliwie 🙁

Link do komentarza
Share on other sites

Nie mamy schematu tego Twojego cuda więc tylko możemy się domyślać z tłumaczeń trochę naokoło, że masz jakiś stabilizator i to on zasila L298 (tylko 5V dla tego mostka? to bez sensu) i teraz serwo.

Oczywiście napisałeś prosty kod testowy włączający oba silniki na różne PWM i jednocześnie kręcący serwem bez żadnych zdalnych sterowań i akcelerometrów żeby sprawdzić poprawność działania sprzętu - i on też zawiódł.

A z czego zasila się ten robot? Co jest przed stabilizatorem 5V, jakie silniki tam masz i jaki stabilizator? I po co on w ogóle gdy masz mostek do silników? Czy próbowałeś serwo podpiąć na inny pin Arduino? Może są jakieś interakcje między generacją sygnału dla serwa a PWM-ami silników lub innymi wyjściami np. sterującymi kierunkiem? Mierzyłeś jakieś napięcia? To główne, zasilające wszystko i te 5V podczas problemów.

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

marek17017, dziękuję Ci za pochylenie się nad moim problemem.

Owe "cudo" jak to ładnie nazwałeś wygląda tak: CUDO

Jest i schemat cuda: SCHEMAT

Załączyłem schemat z zaznaczeniem skąd ciągnę 5V.

Program stworzyłem samemu wykorzystując czyjś fragment dot. buforowania danych i parsowania. Program zbiera dane z akcelerometru telefonu i kręci kołami w zależności od ruchu komórki. TA CZĘŚĆ DZIAŁA WYŚMIENICIE.

Następnie dodałem parę linijek kodu obsługujących serwo. Dane z suwaka na telefonie (0-180st) są na identycznej zasadzie przekazywane z telefonu do Arduino. TA CZĘŚĆ TEŻ DZIAŁA tak jak powinna. Niestety po dodaniu serwa z jakiegoś powodu prawe koła zaczęły fiksować -

obracają się tylko przy maksymalnym nachyleniu komórki. Program w wersji bez serwa działa jak należy.

658834348_Wyjcie5VzL298N.thumb.jpg.8e4f519215cbaaf9a54af1020c6fcc4f.jpg

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.