Skocz do zawartości

Problem z dokończeniem programu robota


adrianie

Pomocna odpowiedź

Jest to mój pierwszy post więc pragnę się z wszystkimi przywitać i zaprezentować mojego pierwszego robota. Jest to pierwsza konstrukcja jaką robię więc dużo rzeczy musiałem się dowiedzieć i nauczyć. Lecz udało mi się zbudować jeżdżącego robota na podwoziu Rover 5 z dwoma silnikami bez enkoderów. Użyte do tego również został mikrokontroler DFRduino Uno + motorshield 2x2A. Z czujników posiada odbiornik podczerwieni 38Khz który działa znakomicie. (udało mi się napisać program którym steruję robotem poprzez pilot. czujnik Sharp GP2Y0A21 który również spełnia swoje zadanie. (robot widzi przeszkody i je omija). Oraz 6 czujników odbiciowych TCRT5000 (do funkcji linefollower). Lecz napotkałem się z przeszkodami jako że nauczyłem się trochę podstaw programowania parę dni temu co pozwoliło mi wykonać tylko program do pilota oraz czujnika odległości. Samodzielny program wykrywania przeszkód działa bez zarzutu. Również program sterowania pilota. Lecz chciałem zrobić żeby robot był sterowany ręcznie przez pilota oraz przy naciśnięciu przycisku "play" na pilocie robot jeździł by samoczynnie i omijał przeszkody. I nie udało mi się to. Przy moich kombinacjach z kodem robot albo nie reagował na przycisk play z pilota albo włączył żeby jeździł sam lecz nie umiał potem wyjść spowrotem. Mógłbym poprosić o pomoc w modyfikacji kodu ? Chciałem również dodać funkcję na kolejnym przycisku żeby robot działał jako linefollower przy użyciu tych 6 czujników. Ale dla mnie to już magia.

Podaję kod który udało mi się napisać do tej pory.

#include "IRremote.h"

//Kontrola obrotów silników PWM:
//określamy, które piny sterują silnikami 
//piny sterujące prędkością silników 
const int E1 = 5; 
const int E2 = 6;
//piny sterujące kierunkiem jazdy 
const int M1 = 4;
const int M2 = 7;                        

boolean R = 0; //jazda do przodu 
boolean F = 1; //jazda do tyłu 

int const sharp = A0; //czujnik SHARP 2Y0A21 podpiety do analog pin 0
int wartoscSHARP = 0; //odczytana wartość z czujnikaSHARP 2Y0A21
int wyjsciowawartoscSHARP = 0; //wartosc z czujnika SHARP 2Y0A21 po konwersji

int receiver = 0; //czujnik IR podpięty do pinu cyfrowego 0
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results;

//funkcje sterujące silnikiem 1; pwm określa prędkość, reverse kierunek 
void Motor1(int pwm, boolean reverse) 
{ 
 analogWrite(E1,pwm); //ustawia wypełnienie PWM: 0 - silnik zatrzymany, 255 - pełna prędkość 
 if(reverse) 
 { 
   digitalWrite(M1,HIGH);    
 } 
 else 
 { 
   digitalWrite(M1,LOW);    
 } 
}   

//funkcje sterujące silnikiem 2; pwm określa prędkość, reverse kierunek 
void Motor2(int pwm, boolean reverse) 
{ 
 analogWrite(E2,pwm); //ustawia wypełnienie PWM: 0 - silnik zatrzymany, 255 - pełna prędkość 
 if(reverse) 
 { 
   digitalWrite(M2,HIGH);    
 } 
 else 
 { 
   digitalWrite(M2,LOW);    
 } 
}   

void setup() 
{ 
 int i; 
 for(i=4;i<=7;i++) //W Arduino Motor Shield piny wyjściowe to 4,5,6,7
 { 
   pinMode(i, OUTPUT);  //ustaw piny 4,5,6,7 jako wyjścia 
} 

pinMode(sharp, INPUT); //pin pod który podłączono czujnik jako wejście
Serial.begin(9600);  // zainicjalizuj komunikację przez SerialPort na 9600 bitów na sekundę
irrecv.enableIRIn(); // Start the receiver
}

int opcja = 5;
//o - do przodu
//1 - do tylu
//2 - lewa
//3 - prawa
//4 - stop
//5 - samodążny 


int stan = 1;

void loop(){ 



 if (irrecv.decode(&results)){
   Serial.println(results.value, HEX);
   if(results.value == 0x4BB641BE){ opcja=0; }
   if(results.value == 0x4BB6C13E){ opcja=1; }
   if(results.value == 0x4BB621DE){ opcja=2; }
   if(results.value == 0x4BB6A15E){ opcja=3; }
   if(results.value == 0x4BB6E916){ opcja=4; }
   if(results.value == 0x4BB6A857){ opcja=5; }

   irrecv.resume(); // odczytaj kolejną wartość

   switch(opcja){
     case 0:
       Motor1(255,F);
       Motor2(255,F);
     break;
     case 1:
       Motor1(255,R);
       Motor2(255,R);
     break;
     case 2:
       Motor1(255,F);
       Motor2(255,R);
     break;
     case 3:
       Motor1(255,R);
       Motor2(255,F);
     break;
     case 4:
       Motor1(0,F);
       Motor2(0,F);
     break;

     case 5:

while(results.value!=0x4BB6E916){
  { 
 wartoscSHARP = analogRead(sharp);  //odczyt z czujnika SHARP i zapis do zmiennej wartoscSHARP
 wyjsciowawartoscSHARP = map(wartoscSHARP, 0, 1023, 0, 255); //konwersja zakresu danych z 0-1023 do 0-255

 //wydrukuj na Monitorze portu szeregowego
  Serial.print("SHARP = " );  
  Serial.println(wyjsciowawartoscSHARP); 
  }
if(wyjsciowawartoscSHARP > 100) //jeśli wykryto przeszkodę 
 {
   Motor1(255,R);//jedź do tyłu 
   Motor2(255,R); 
   long los = random(800, 3000);
   delay(los); //przez losową długość czasu od 1s do 3s
   stan=0;

   Motor1(255,R); //skręcaj 
   Motor2(255,F);
   long los2 = random(800, 2000); 
   delay(los2);//przez losową długość czasu od 1s do 2s
   stan = 1; 
 } 
 else //jeśli nie widać przeszkody 
 {
   Motor1(255,F); //jedź prosto 
   Motor2(255,F); 
 } 
}
break;
 } 
 }

}
Link do komentarza
Share on other sites

 if (irrecv.decode(&results)){ 

Nie wgłębiałem się zbytnio w kod, ale na pierwszy rzut oka coś mi nie pasuje z tym IFem... jego zamknięcie jest gdzieś na samym końcu kodu, a ja bym dał zaraz po tych kilku linijkach z wyborem opcji. Zauważ, że w przypadku kodu który wkleiłeś, wnętrze IFa wykona się wyłącznie w momencie naciśnięcia przycisku, a zapewne chciałbyś by wykonywał daną czynność (opcję) cały czas, dopoki nie naciśniesz innego przycisku.

Link do komentarza
Share on other sites

Gdy poprawię kod według sugestii to robot wykonuje tylko czynność zawartą w case5: czyli jeździ i mija przeszkody. Nie działa żaden przycisk na pilocie. Od razu po włączeniu rusza.

Link do komentarza
Share on other sites

Gdy poprawię kod według sugestii to robot wykonuje tylko czynność zawartą w case5: czyli jeździ i mija przeszkody. Nie działa żaden przycisk na pilocie. Od razu po włączeniu rusza.

A, no tak - wywal jeszcze to

while(results.value!=0x4BB6E916){ 

Bo Ci cały czas to działa w pętli.

Zauważ, że jak wejdziesz do wnętrza tej pętli, to nie możesz już z niej wyjść bo wartość "results.value" może zostać zmieniona tylko podczas kolejnej próby odczytu stanu pilota, a ten odczyt wykonujesz wyżej w kodzie, poza tą pętlą. Ten warunek sprawdzający jest zbędny.

W skrócie: na początku pętli loop() sprawdzasz czy jest nacisniety przycisk i w zależności od konkretnej wartości pilota zmieniasz opcję. Potem robisz case dla danej opcji która jest ustawiona. Czyli jak nacisniesz na stop to robot staje. Gdy nacisniesz inny przycisk, to wykona się kod zmiany opcji i w tedy wykona się inny case niż wczesniej.

[ Dodano: 06-02-2013, 22:25 ]

Sorki ze post za postem. Ja bym to zrobił tak:

#include "IRremote.h"

const int E1 = 5;
const int E2 = 6;
//piny sterujące kierunkiem jazdy
const int M1 = 4;
const int M2 = 7;                       

boolean R = 0; //jazda do przodu
boolean F = 1; //jazda do tyłu


int const sharp = A0; //czujnik SHARP 2Y0A21 podpiety do analog pin 0
int wartoscSHARP = 0; //odczytana wartość z czujnikaSHARP 2Y0A21
int wyjsciowawartoscSHARP = 0; //wartosc z czujnika SHARP 2Y0A21 po konwersji

int receiver = 0; //czujnik IR podpięty do pinu cyfrowego 0
IRrecv irrecv(receiver); // create instance of 'irrecv'
decode_results results;

//funkcje sterujące silnikiem 1; pwm określa prędkość, reverse kierunek
void Motor1(int pwm, boolean reverse)
{
 analogWrite(E1,pwm); //ustawia wypełnienie PWM: 0 - silnik zatrzymany, 255 - pełna prędkość
 if(reverse){
   digitalWrite(M1,HIGH);
   }  else {
     digitalWrite(M1,LOW);
   } 
}   

//funkcje sterujące silnikiem 2; pwm określa prędkość, reverse kierunek
void Motor2(int pwm, boolean reverse)
{
 analogWrite(E2,pwm); //ustawia wypełnienie PWM: 0 - silnik zatrzymany, 255 - pełna prędkość
 if(reverse) {
 digitalWrite(M2,HIGH);
 } else {
   digitalWrite(M2,LOW); 
 }
}   

inline void przod() 
{
Motor1(255,F);
Motor2(255,F);
}

inline void tyl() 
{
Motor1(255,R);
Motor2(255,R);
}

inline void lewa() 
{
Motor1(255,F);
Motor2(255,R);
}

inline void prawa() 
{
Motor1(255,R);
Motor2(255,F);
}

inline void stp() 
{
Motor1(0,F);
Motor2(0,F);
}

inline void auto() 
{
wartoscSHARP = analogRead(sharp);  //odczyt z czujnika SHARP i zapis do zmiennej wartoscSHARP
 wyjsciowawartoscSHARP = map(wartoscSHARP, 0, 1023, 0, 255); //konwersja zakresu danych z 0-1023 do 0-255

 //wydrukuj na Monitorze portu szeregowego
  Serial.print("SHARP = " ); 
  Serial.println(wyjsciowawartoscSHARP);

if(wyjsciowawartoscSHARP > 100) //jeśli wykryto przeszkodę
 {
   tyl();
   long los = random(800, 3000);
   delay(los); //przez losową długość czasu od 1s do 3s


   prawa();
   long los2 = random(800, 2000);
   delay(los2);//przez losową długość czasu od 1s do 2s
   stp();

 }
 else //jeśli nie widać przeszkody
 {
   przod();
 }
}


void setup()
{
 int i;
 for(i=4;i<=7;i++) //W Arduino Motor Shield piny wyjściowe to 4,5,6,7
 {
   pinMode(i, OUTPUT);  //ustaw piny 4,5,6,7 jako wyjścia
}

pinMode(sharp, INPUT); //pin pod który podłączono czujnik jako wejście
Serial.begin(9600);  // zainicjalizuj komunikację przez SerialPort na 9600 bitów na sekundę
irrecv.enableIRIn(); // Start the receiver
}

void loop(){

 if (irrecv.decode(&results)){
   Serial.println(results.value, HEX);
  irrecv.resume(); // odczytaj kolejną wartość
 }
   switch(results.value){
     case 0x4BB641BE:
       przod();
     break;
     case 0x4BB6C13E:
       tyl();
     break;
     case 0x4BB621DE:
       lewa();
     break;
     case 0x4BB6A15E:
       prawa();
     break;
     case 0x4BB6E916:
       stp();
     break;
     case 0x4BB6A857:
     auto();
     break;


 }

} 

pisane na szybko, bez sprawdzania, ale ogólny zarys idei masz.

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

Wygląda to o wiele lepiej i przejrzyściej. I jest to teraz napisane łatwiej. Dziękuję za to. Lecz nie wiem czemu nie rozwiązało mojego problemu. Robot jeździ prawidłowo we wszystkich kierunkach. Bez problemu przechodzi do trybu auto i z niego wychodzi. Lecz nie potrafi rozpoznać przeszkody. Jeśli włączyłem konsolę i nacisnąłem przycisk na pilocie od trybu automatycznego to tak to wyglądało.

Program przestaje zczytywać sygnał z czujnika po kilku odczytach. W rezultacie robot jedzie prosto i wartość która ma być powyżej 100 jeśli widzi przeszkodę nigdy się nie pojawia.

Link do komentarza
Share on other sites

Wygląda to o wiele lepiej i przejrzyściej. I jest to teraz napisane łatwiej. Dziękuję za to. Lecz nie wiem czemu nie rozwiązało mojego problemu. Robot jeździ prawidłowo we wszystkich kierunkach. Bez problemu przechodzi do trybu auto i z niego wychodzi. Lecz nie potrafi rozpoznać przeszkody. Jeśli włączyłem konsolę i nacisnąłem przycisk na pilocie od trybu automatycznego to tak to wyglądało.

Obrazek

Program przestaje zczytywać sygnał z czujnika po kilku odczytach. W rezultacie robot jedzie prosto i wartość która ma być powyżej 100 jeśli widzi przeszkodę nigdy się nie pojawia.

W sumie jak tak teraz się zastanowię, to mój kod jest zły, dlatego, że zakłada, że pilot zczytuje zawsze poprawne kody i to z tego pilota którego używasz, a w praktyce mogą tam wpadać jakieś smieci i wtedy case się nie wykona. Lepiej jednak wrócić do tej zmiennej "opcja" i zapisywać w niej odpowiednią opcję wyłącznie gdy results.value jest z zakresu wartości które chcesz. Czyli trochę bardziej tak, jak miałeś wcześniej.

Myślę, że dasz radę, ale jak nie to daj znać. To powinno rozwiązać problem.

P.S: Jesteś nowy na forum, to pozwolę sobie delikatnie zasugerować - pod moim postem masz taki przycisk jak "pomógł" - jeśli pomogłem, możesz nacisnąc jeśli masz ochotę😉

  • Lubię! 1
Link do komentarza
Share on other sites

Zmieniłem te opcje w programie i wszystko śmiga jak powinno. sterowanie ręczne działa jak i również tryb auto na przycisku "play" na pilocie. Wielkie dzięki za pomoc 🙂 Mógłby mnie ktoś jeszcze naprowadzić jak wykonać program line followera z moimi 6 czujnikami odbiciowymi TCRT5000 ? Wiadomo że nie chcę zrobić na początek jakiegoś zaawansowanego programu. Poprostu chcę żeby to działało 😳 Podaję aktualny program który poprawiłem dzięki pomocy kolegi MatManiak.

#include "IRremote.h" 

const int E1 = 5; 
const int E2 = 6; 
//piny sterujące kierunkiem jazdy 
const int M1 = 4; 
const int M2 = 7;                        

boolean R = 0; //jazda do przodu 
boolean F = 1; //jazda do tyłu 

int const sharp = A0; //czujnik SHARP 2Y0A21 podpiety do analog pin 0 
int wartoscSHARP = 0; //odczytana wartość z czujnikaSHARP 2Y0A21 
int wyjsciowawartoscSHARP = 0; //wartosc z czujnika SHARP 2Y0A21 po konwersji 

int receiver = 0; //czujnik IR podpięty do pinu cyfrowego 0 
IRrecv irrecv(receiver); // create instance of 'irrecv' 
decode_results results; 

//funkcje sterujące silnikiem 1; pwm określa prędkość, reverse kierunek 
void Motor1(int pwm, boolean reverse) 
{ 
 analogWrite(E1,pwm); //ustawia wypełnienie PWM: 0 - silnik zatrzymany, 255 - pełna prędkość 
 if(reverse){ 
   digitalWrite(M1,HIGH); 
   }  else { 
     digitalWrite(M1,LOW); 
   } 
}    

//funkcje sterujące silnikiem 2; pwm określa prędkość, reverse kierunek 
void Motor2(int pwm, boolean reverse) 
{ 
 analogWrite(E2,pwm); //ustawia wypełnienie PWM: 0 - silnik zatrzymany, 255 - pełna prędkość 
 if(reverse) { 
 digitalWrite(M2,HIGH); 
 } else { 
   digitalWrite(M2,LOW); 
 } 
}    

inline void przod() 
{ 
Motor1(255,F); 
Motor2(255,F); 
} 

inline void tyl() 
{ 
Motor1(255,R); 
Motor2(255,R); 
} 

inline void lewa() 
{ 
Motor1(255,F); 
Motor2(255,R); 
} 

inline void prawa() 
{ 
Motor1(255,R); 
Motor2(255,F); 
} 

inline void stp() 
{ 
Motor1(0,F); 
Motor2(0,F); 
} 

inline void automat() 
{ 
wartoscSHARP = analogRead(sharp);  //odczyt z czujnika SHARP i zapis do zmiennej wartoscSHARP 
 wyjsciowawartoscSHARP = map(wartoscSHARP, 0, 1023, 0, 255); //konwersja zakresu danych z 0-1023 do 0-255 

 //wydrukuj na Monitorze portu szeregowego 
  Serial.print("SHARP = " ); 
  Serial.println(wyjsciowawartoscSHARP); 

if(wyjsciowawartoscSHARP > 100) //jeśli wykryto przeszkodę 
 { 
   tyl(); 
   long los = random(800, 2000); 
   delay(los); //przez losową długość czasu od 1s do 3s 

   prawa(); 
   long los2 = random(800, 2000); 
   delay(los2);//przez losową długość czasu od 1s do 2s 
   stp(); 
  } 
 else //jeśli nie widać przeszkody 
 { 
   przod(); 
 } 
} 


void setup() 
{ 
 int i; 
 for(i=4;i<=7;i++) //W Arduino Motor Shield piny wyjściowe to 4,5,6,7 
 { 
   pinMode(i, OUTPUT);  //ustaw piny 4,5,6,7 jako wyjścia 
} 

pinMode(sharp, INPUT); //pin pod który podłączono czujnik jako wejście 
Serial.begin(9600);  // zainicjalizuj komunikację przez SerialPort na 9600 bitów na sekundę 
irrecv.enableIRIn(); // Start the receiver 
} 

int opcja = 5;
//o - do przodu
//1 - do tylu
//2 - lewa
//3 - prawa
//4 - stop
//5 - samodążny 


void loop(){ 

   if (irrecv.decode(&results)){
   Serial.println(results.value, HEX);
   if(results.value == 0x4BB641BE){ opcja=0; }
   if(results.value == 0x4BB6C13E){ opcja=1; }
   if(results.value == 0x4BB621DE){ opcja=2; }
   if(results.value == 0x4BB6A15E){ opcja=3; }
   if(results.value == 0x4BB6E916){ opcja=4; }
   if(results.value == 0x4BB6A857){ opcja=5; }

   irrecv.resume(); // odczytaj kolejną wartość
   }

   switch(opcja){
     case 0: 
       przod(); 
     break; 
     case 1: 
       tyl(); 
     break; 
     case 2: 
       lewa(); 
     break; 
     case 3: 
       prawa(); 
     break; 
     case 4: 
       stp(); 
     break; 
     case 5: 
      automat(); 
     break; 


 } 

} 
Link do komentarza
Share on other sites

Zacznij od stworzenia osobnego programu dla lf'a, tak żeby Ci się nie mieszało z tym co już masz. Na początek spróbuj napisać program na ifach, nawet niekoniecznie wykorzystując wszystkie czujniki, a na przykład dwa środkowe. Później możesz spróbować zrobić regulator PD - na forum jest opis jak to działa.

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.