Skocz do zawartości

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


Pomocna odpowiedź

Napisano

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

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 🙁

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.

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

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...