adrianie Napisano Luty 6, 2013 Udostępnij Napisano Luty 6, 2013 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 More sharing options...
MatManiak Luty 6, 2013 Udostępnij Luty 6, 2013 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 More sharing options...
adrianie Luty 6, 2013 Autor tematu Udostępnij Luty 6, 2013 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 More sharing options...
MatManiak Luty 6, 2013 Udostępnij Luty 6, 2013 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 More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. 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
adrianie Luty 6, 2013 Autor tematu Udostępnij Luty 6, 2013 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 More sharing options...
MatManiak Luty 6, 2013 Udostępnij Luty 6, 2013 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ę😉 1 Link do komentarza Share on other sites More sharing options...
adrianie Luty 8, 2013 Autor tematu Udostępnij Luty 8, 2013 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 More sharing options...
mactro Luty 8, 2013 Udostępnij Luty 8, 2013 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 More sharing options...
Pomocna odpowiedź
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ę »