Popularny post BeeKeyPro Napisano Styczeń 20, 2025 Popularny post Udostępnij Napisano Styczeń 20, 2025 Witam. Budowę auta na pilota planowałem już od dawna, ale nie wiedziałem jak się do tego zabrać. Dopiero niedawno gdy miałem okazje wykonać projekt z tego filmu, dowiedziałem się jak to zrobić. I tak oto powstało takie auto na pilota: Auto na pilota Użyte komponenty i moduły: Arduino UNO Moduł sterownika silników DC L293D Akumulatorki Li-Ion 18650 + koszyk Silnik DC z przekładnią + koła (x4) Odbiornik IR Rezystor 68Ω Kondensator 100µF Przełącznik I/O Pilot IR (ja użyłem ten pilot) Na samym początku musiałem zbadać kody które odbiornik odbiera po wciśnięciu danego przycisku na pilocie, więc napisałem i wgrałem taki kod: #include <IRremote.h> const int RECV_PIN = A0; void setup() { Serial.begin(9600); IrReceiver.begin(RECV_PIN, ENABLE_LED_FEEDBACK); Serial.println("Odbiornik IR gotowy."); } void loop() { if (IrReceiver.decode()) { Serial.print("Kod: "); Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); IrReceiver.resume(); } Okazało się, że odbiornik odbiera losowe sygnały gdy klikam ten sam przycisk. Problem rozwiązał ,,filtr na zasilaniu odbiornika". (problem szczegółowo opisywany i rozwiązywany jest w tym wątku): Ustaliłem sposób w jaki będą działać przyciski i zająłem się budową auta: Instrukcja obsługi pilota Auto budowałem w podobny sposób jak na filmie do którego linkowałem na początku tego opisu. Dlatego nie będę też opisywał tutaj tego jakie kroki wykonałem, żeby je zbudować. Lepiej zajrzyjmy do kodu. #include <IRremote.hpp> #include <AFMotor.h> AF_DCMotor motorM1(4); AF_DCMotor motorM2(3); AF_DCMotor motorM3(2); AF_DCMotor motorM4(1); const int RECV_PIN = A0; int speed=200; void setup() { IrReceiver.begin(RECV_PIN); motorM1.setSpeed(speed); motorM2.setSpeed(speed); motorM3.setSpeed(speed); motorM4.setSpeed(speed); } void loop() { if (IrReceiver.decode()) { if(IrReceiver.decodedIRData.decodedRawData == 0xBF40FF00){ // JAZDA W PRZÓD motorM1.run(FORWARD); motorM2.run(FORWARD); motorM3.run(FORWARD); motorM4.run(FORWARD); } if(IrReceiver.decodedIRData.decodedRawData == 0xE619FF00){ // JAZDA W TYŁ motorM1.run(BACKWARD); motorM2.run(BACKWARD); motorM3.run(BACKWARD); motorM4.run(BACKWARD); } if(IrReceiver.decodedIRData.decodedRawData == 0xF807FF00){ // SKRĘT W LEWO motorM1.run(FORWARD); motorM2.run(FORWARD); motorM3.run(BACKWARD); motorM4.run(BACKWARD); } if(IrReceiver.decodedIRData.decodedRawData == 0xF609FF00){ // SKRĘT W PRAWO motorM3.run(FORWARD); motorM4.run(FORWARD); motorM2.run(BACKWARD); motorM1.run(BACKWARD); } if(IrReceiver.decodedIRData.decodedRawData == 0xEA15FF00){ // STOP motorM3.run(RELEASE); motorM4.run(RELEASE); motorM2.run(RELEASE); motorM1.run(RELEASE); } IrReceiver.resume(); } } I tak jak widać po kodzie, sterowanie tym autem jest uciążliwe. W klasycznych autach na pilota, jak klika się przycisk (jazda w przód) to auto jedzie póki nie puścisz przycisku. Tutaj jak klikam przycisk, to auto jedzie do momentu w którym nie nacisnę innego przycisku, lub przycisku stop. Jak wie ktoś jak wykonać taki kod, który pozwoli sterować autem tak jak w klasycznych autach, to był bym wdzięczny jakby podpowiedział pod tym opisem. Podczas pisania kodu, napotkałem jeszcze jeden problem. Biblioteka AFMotor gryzła się z IRremote, przez co nie mogłem sterować silnikami M1 i M2, więc w kodzie mogłem używać tylko jednej z tych bibliotek. Rozwiązanie problemu też znajduje się w tym wątku: Na koniec najlepsza część, czyli filmik: Choć kod i schemat połączenia wszystkiego były wykonane przeze mnie to dużo inspirowałem się tym filmem. Dziękuje za przeczytanie całego DIY i z góry przepraszam, jeśli się je dziwnie czytało, ale zupełnie nie wiedziałem jak się do niego zabrać. Czekam z niecierpliwością na wasze uwagi. Pozdrawiam. 12
ethanak Styczeń 20, 2025 Udostępnij Styczeń 20, 2025 Strasznie brzydki ten kod... Po pierwsze, masz jakieś tajemnicze zeroiksy w kodzie, które absolutnie nie wyglądają ładnie. Po drugie pomieszane odbieranie danych z wykonaniem polecenia. Na początek spróbuj kodu, który robi to samo co Twój, ale łatwiej będzie później coś zmienić: #include <IRremote.hpp> #include <AFMotor.h> AF_DCMotor motorM1(4); AF_DCMotor motorM2(3); AF_DCMotor motorM3(2); AF_DCMotor motorM4(1); const int RECV_PIN = A0; int speed=200; /* a teraz żeby nie mieć porypanych stałych w kodzie */ #define J_PRZOD 0xBF40FF00 #define J_WSTECZ 0xE619FF00 #define J_LEWO 0xF807FF00 #define J_PRAWO 0xF609FF00 #define J_STOP 0xEA15FF00 // to sprawdź #define J_REPEAT 0xFFFFFFFF void setup() { IrReceiver.begin(RECV_PIN); motorM1.setSpeed(speed); motorM2.setSpeed(speed); motorM3.setSpeed(speed); motorM4.setSpeed(speed); } /* trochę porządku na poiczątek */ void loop() { uint32_t kod = 0; /* najpierw odbieramy dane */ if (IrReceiver.decode()) { kod = IrReceiver.decodedIRData.decodedRawData; IrReceiver.resume(); } /* a teraz interpretujemy odebrany kod */ switch(kod) { case J_PRZOD: motorM1.run(FORWARD); motorM2.run(FORWARD); motorM3.run(FORWARD); motorM4.run(FORWARD); break; case J_WSTECZ: motorM1.run(BACKWARD); motorM2.run(BACKWARD); motorM3.run(BACKWARD); motorM4.run(BACKWARD); break; case J_LEWO: motorM1.run(FORWARD); motorM2.run(FORWARD); motorM3.run(BACKWARD); motorM4.run(BACKWARD); break; case J_PRAWO: motorM3.run(FORWARD); motorM4.run(FORWARD); motorM2.run(BACKWARD); motorM1.run(BACKWARD); break; case J_STOP: motorM3.run(RELEASE); motorM4.run(RELEASE); motorM2.run(RELEASE); motorM1.run(RELEASE); break; } } Sprawdź czy działa, a przede wszystkim czy kod powtórzenia jest rzeczywiście 0xffffffff (nie mam takiego pilota więc nie sprawdzę). Reszta jutro. 2
BeeKeyPro Styczeń 20, 2025 Autor tematu Udostępnij Styczeń 20, 2025 @ethanak Dzięki ogromne, zaraz sprawdzę.
BeeKeyPro Styczeń 20, 2025 Autor tematu Udostępnij Styczeń 20, 2025 @ethanak Wszystko działa. Twój kod wygląda 100 jak nie 1000 razy lepiej. Ogromne dzięki! Kiedyś znak powtórzenia to było u mnie 0xFFFFFFFF, ale teraz to jest po prostu 0x0.
ethanak Styczeń 20, 2025 Udostępnij Styczeń 20, 2025 Top tak pięć minut przed wyjściem - sprawdź jeszcze ten kod. Na razie w działaniu nie powinno być różnicy, ale to już można sobie ładnie przerabiać #include <IRremote.hpp> #include <AFMotor.h> AF_DCMotor motorM1(4); AF_DCMotor motorM2(3); AF_DCMotor motorM3(2); AF_DCMotor motorM4(1); const int RECV_PIN = A0; int speed=200; /* a teraz żeby nie mieć porypanych stałych w kodzie */ #define C_PRZOD 0xBF40FF00 #define C_WSTECZ 0xE619FF00 #define C_LEWO 0xF807FF00 #define C_PRAWO 0xF609FF00 #define C_STOP 0xEA15FF00 // to sprawdź - na wszelki wypadek będą dwa #define C_REPEAT 0xFFFFFFFF #define C_REPEAT2 0x0 /* i reczywiste proste kody do programu */ enum { J_ZERO = 0, J_PRZOD, J_WSTECZ, J_LEWO, J_PRAWO, J_STOP }; void setup() { IrReceiver.begin(RECV_PIN); motorM1.setSpeed(speed); motorM2.setSpeed(speed); motorM3.setSpeed(speed); motorM4.setSpeed(speed); } /* dalej trochę porządku - wywalamy odbieranie danych do funkcji * i pozbywamy się jakichś kodów w programie. * Trzeba pamiętać o zasadzie maksymalnej izolacji - funkcja * odbierająca kody z pilota nie musi wiedzieć noc o silnikach, * również części programu odpowiadającej za silniki nie jest * potrzebna wiedza o jakichkolwiek kodach */ int getIR() { uint32_t kod; if (!IrReceiver.decode()) return 0; // tu nie ma co dalej myśleć kod = IrReceiver.decodedIRData.decodedRawData; IrReceiver.resume(); /* teraz zamieniam odeprane kody IR na właściwe * Oczywiście można (i trzeba) zrobić to prościej, * ale na razie to musi wystarczyć */ int rc; switch(kod) { case C_PRZOD: rc=J_PRZOD; break; case C_WSTECZ: rc=J_WSTECZ; break; case C_LEWO: rc=J_LEWO; break; case C_PRAWO: rc=J_PRAWO; break; /* kody powtarzania na razie nas nie interesują, * traktujemy ja na razie jako pomijane */ case C_REPEAT: case C_REPEAT2: rc = 0; break; /* i teraz dowolny klawisz będzie służyć jako STOP */ default: rc = J_STOP; break; } /* później będziemy jeszcze bawić się zmienną rc * ale na razie po prostu przekażemy to do programu */ return rc; } void loop() { /* najpierw odbieramy dane */ int kod = getIR(); /* a teraz interpretujemy odebrany kod */ switch(kod) { case J_PRZOD: motorM1.run(FORWARD); motorM2.run(FORWARD); motorM3.run(FORWARD); motorM4.run(FORWARD); break; case J_WSTECZ: motorM1.run(BACKWARD); motorM2.run(BACKWARD); motorM3.run(BACKWARD); motorM4.run(BACKWARD); break; case J_LEWO: motorM1.run(FORWARD); motorM2.run(FORWARD); motorM3.run(BACKWARD); motorM4.run(BACKWARD); break; case J_PRAWO: motorM3.run(FORWARD); motorM4.run(FORWARD); motorM2.run(BACKWARD); motorM1.run(BACKWARD); break; case J_STOP: motorM3.run(RELEASE); motorM4.run(RELEASE); motorM2.run(RELEASE); motorM1.run(RELEASE); break; } } Reszta jutro (daj w międzyczasie znać czy ruszyło) 1
BeeKeyPro Styczeń 20, 2025 Autor tematu Udostępnij Styczeń 20, 2025 @ethanak Działa, ale po co takie coś robić? Kod robi to samo, a jest dłuższy.
_LM_ Styczeń 20, 2025 Udostępnij Styczeń 20, 2025 8 minut temu, BeeKeyPro napisał: po co takie coś robić? Czytelność, oraz łatwiej zaprowadzić zmiany, poprawki. 1
AntekBezak Styczeń 20, 2025 Udostępnij Styczeń 20, 2025 No to teraz przed tobą najfajniejszy etap nauki arduino: autopiloty, światłoluby, linefollowery, dodawanie różnych innych funkcji na pokład... mnóstwo potencjału. Gratuluję udanego projektu! 2
ethanak Styczeń 20, 2025 Udostępnij Styczeń 20, 2025 @BeeKeyPro już kolega wyjaśnił. W komentarzu masz coś o izolacji, prawda? I od tej pory można zajmować się tylko funkcją getIR. Jeśli np. zmieni się pilot, albo w ogóle zasda przekazywania poleceń (np. radio) reszta programu nie musi nic wiedzieć o zmianach. Ty masz akurat prosty program, ale w bardziej skomplikowanych przypadkach (np. półautomatyczny robot) taka izolacja jest niezbędna. No a jutro postaram się wrzucić do tej funkcji zależności czasowe. @AntekBezak i najważniejsze - automat skończony aka maszyna stanów. 1
Popularny post BeeKeyPro Styczeń 20, 2025 Autor tematu Popularny post Udostępnij Styczeń 20, 2025 Wiem że to nie worklog, ale mały update zrobiłem (światła samochodowe): Oczywiście da się je przełączać przyciskiem (tym czerwonym na pilocie): 4
BeeKeyPro Styczeń 20, 2025 Autor tematu Udostępnij Styczeń 20, 2025 @ethanak #include <IRremote.hpp> #include <AFMotor.h> AF_DCMotor motorM1(4); AF_DCMotor motorM2(3); AF_DCMotor motorM3(2); AF_DCMotor motorM4(1); const int RECV_PIN = A0; boolean standiod = 1; int speed=200; #define J_PRZOD 0xBF40FF00 #define J_WSTECZ 0xE619FF00 #define J_LEWO 0xF807FF00 #define J_PRAWO 0xF609FF00 #define J_STOP 0xEA15FF00 #define L_ONOFF 0xBA45FF00 #define J_REPEAT 0x0 #define BIEG_1 0xF30CFF00 #define BIEG_2 0xE718FF00 #define BIEG_3 0xA15EFF00 void setup() { Serial.begin(9600); pinMode(A1, OUTPUT); pinMode(A2, OUTPUT); IrReceiver.begin(RECV_PIN); } void loop() { digitalWrite(A1, standiod); digitalWrite(A2, standiod); motorM1.setSpeed(speed); motorM2.setSpeed(speed); motorM3.setSpeed(speed); motorM4.setSpeed(speed); uint32_t kod = 0; if (IrReceiver.decode()) { kod = IrReceiver.decodedIRData.decodedRawData; Serial.println(IrReceiver.decodedIRData.decodedRawData, HEX); IrReceiver.resume(); } switch(kod) { case J_PRZOD: motorM1.run(FORWARD); motorM2.run(FORWARD); motorM3.run(FORWARD); motorM4.run(FORWARD); break; case J_WSTECZ: motorM1.run(BACKWARD); motorM2.run(BACKWARD); motorM3.run(BACKWARD); motorM4.run(BACKWARD); break; case J_LEWO: motorM1.run(FORWARD); motorM2.run(FORWARD); motorM3.run(BACKWARD); motorM4.run(BACKWARD); break; case J_PRAWO: motorM3.run(FORWARD); motorM4.run(FORWARD); motorM2.run(BACKWARD); motorM1.run(BACKWARD); break; case J_STOP: motorM3.run(RELEASE); motorM4.run(RELEASE); motorM2.run(RELEASE); motorM1.run(RELEASE); break; case L_ONOFF: standiod = !standiod; break; case BIEG_1: speed=100; break; case BIEG_2: speed=150; break; case BIEG_3: speed=250; break; } }
orb777 Styczeń 24, 2025 Udostępnij Styczeń 24, 2025 @BeeKeyPro , jak w swoim autku zamocowałeś silniki do podwozia, też klejem na gorąco?
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ę »