Przeszukaj forum
Pokazywanie wyników dla tagów 'Leonardo'.
Znaleziono 11 wyników
-
Witam. Od niedawna zacząłem interesować się programowaniem oraz Arduino, i chciałbym zrobić takie coś (ale kompletnie nie wiem jak to zrobić): Klikam przycisk => silnik kręci się w prawo (3s) => przerwa (2s) => silnik kręci się w lewo (3s) => Stop. I kiedy kliknę przycisk znowu to samo od poczatku. *Arduino Leonardo *Silnik (zwykły, chiński z samochodu RC) Proszę o pomoc, będę bardzo wdzięczny.😉
-
Witam wszystkich, Dawno mnie tu nie było, praca, studia itp. W końcu znalazłem coś czasu, aby przedstawić projekt już chyba ostatni mojej kierownicy, który wykonałem w ramach pracy inżynierskiej na kierunku Mechatronika. Projekt od wcześniejszych pod względem elektroniki znacznie się nie różni jedyne co to został zastosowany inny enkoder oraz silnik DC co opisze w dalszej części postu. A więc tak: Główne założenia projektu: Wykorzystanie mikrokontrolera Arduino Leonardo do sterowania urządzeniem, Użycie enkodera OMRON E6B2-CWZ6C do odczytu położenia kierownicy, Wykorzystanie silnika DC ZY6812 oraz sterownika silnika IBT_2 do wytworzenia siły zwrotnej tzw. force feedback, Wykonanie mechanizmu, który ma za zadanie przekazać informację na temat zachowania się kierownicy podczas jazdy w symulatorze wyścigów samochodowych, oraz innych grach czy symulatorach samochodowych, Wykonanie większości elementów konstrukcji w technologii druku 3D przy użyciu materiału PETG, Wykonanie wałka głównego łączącego enkoder, koło kierownicy, oraz przekładnię za pomocą obróbki skrawaniem na maszynie sterowanej numerycznie CNC z pręta aluminiowego o średnicy Ø60mm oraz oznaczeniu PA6/EN AW 2017, Wykonanie estetycznej oraz w pełni funkcjonalnej obudowy urządzenia, Wykorzystanie sportowego koła kierownicy wraz z zaczepem quick release, Zasilanie urządzenia zasilaczem ADLS-360-24, Możliwość dołączenia dodatkowych elementów takich jak: pedał gazu, hamulca, sprzęgła, hamulec ręczny, skrzyni biegów poprzez gniazda RJ 45 z tyłu obudowy. Większość układu elektroniki została opisana we wcześniejszych moich postach, więc jeżeli jest ktoś zainteresowany to zapraszam do odwiedzenia ich, natomiast tutaj dodam kilka zdjęć przedstawiających wykonane urządzenie oraz film, który również prezentuje urządzenie oraz jego działanie. Link do filmu :
- 24 odpowiedzi
-
- 13
-
- Steering Wheel
- DIY
-
(i 2 więcej)
Tagi:
-
Witam, mam problem nagłej potrzeby. Prostu układ: esp8266 nodemcu v3 podłączony pod zasilacz impulsowy 12V przekaźnik 8 kanałowy z optoizolacją zasilany na 5V Z Zasilania 12V idzie też prąd na stabilizator 5V - ten zasila tylko i wyłącznie wejście Vcc płytki przekaźnika. problem jest taki, że przekaźnik normalnie działa w przypadku gdy styk IN1 załącze z arduino leonardo. Wszystko jest idealnie z arduino. Natomiast gdy spróbuję to samo zrobić z esp zamiast arduino, to na przekaźniku zapala się tylko LED że 1 styk został załączony, jednak nie słychać nawet charakterystycznego "trzasku" przełączania styku a sam kanał nie działa i nic się nie dzieje oprócz led sygnalizującego załączenie styku. Problem palący czasowo, ktos wie czemu arduino normalnie załącza styk na przekaźniku a esp już nie? I jak to rozwiązać?
-
Witam ostatnio chciałem pobawić się troszkę arduino lecz gdy podłączyłem je do komputera, komputer płytki nie wykrył świeciła się tylko dioda zasilania i migała dioda L . Nie jest to wina kabla, ponieważ pliki z telefonu przez ten kabel przechodzą normalnie. Problem dotyczy płytki arduino Leonardo R3.
-
Hej, Umieszczam tutaj sposób wypalenia bootloadera na Atmega328P (Arduino Uno) za pomocą Arduino Leonardo. Nie jest to tak proste jak z użyciem Uno i długo się z tym męczyłem, wiec wrzucam dla potomnych. Nie jestem pewien dlaczego tak się robi, ale działa 😉 Potrzebujesz: Leonardo, Atmega328P, rezonatora kwarcowego, rezystora 10k om, dwóch kondensorów 22pF. Niestety musisz przeinstalować Arduino IDE do wersji 1.0.5. Wersje tą znajdziesz na oficjalnej stronie Arduino (https://www.arduino.cc/en/main/OldSoftwareReleases). 1. odinstaluj Arduino IDE 2. zainstaluj Arduino IDE 1.0.5 3. otwórz przykład ArduinoISP (Plik->Przykłady->ArduinoISP) 4. zmień "#define RESET SS" na "#define RESET 10" (druga linijka po komentarzu) 5. zmień "#define LED_HB 9" na "#define LED_HB 13" 6. wybierz płytkę Leonardo (Narzędzia-> Płytki->Arduino Leonardo) 7. wybierz port (COM) 8. wgraj program 9. przejdź do folderu "hardware" (C:\Program Files (x86)\Arduino\hardware) (ścieżka może się trochę różnić, ale chyba wyłapałeś o co chodzi) 10. utwórz w folderze hardware folder o nazwie "leofix" 11. otwórz notatnik i przekopiuj : " arduinoispleo.name=Arduino as ISP (Leonardo) arduinoispleo.communication=serial arduinoispleo.protocol=arduino arduinoispleo.speed=19200 " 12. zapisz to jako programmers.txt 13. podłącz układ : Atmego328P: Arduino Leonardo: RX pin 2-------------------------------------digital pin 0 TX pin 3-------------------------------------digital pin 1 MISO pin 18-----------------------------------ICSP pin MISO MOSI pin 17-----------------------------------ICSP pin MOSI SCK pin 19-----------------------------------ICSP pin SCK RESET pin1-------------------------------------digital pin 10 oraz 5v i GND (pamiętaj, że GND jest w dwóch miejscach, 5V również ) 14. dodaj rezonator, rezystor i dwa kondensatory. Schemat znajdziesz na oficjalnej stronie: https://www.arduino.cc/en/Tutorial/ArduinoToBreadboard. 15. zrestartuj Arduino IDE 16. wybierz płytkę UNO (Narzędzia-> Płytki->Arduino UNO) 17. wybierz port (COM) 18. wybierz Leonardo jako programator (Narzędzia->Programator-> Arduino as ISP (Leonardo) ) 19. wypal bootloader (Narzędzia->Wypal Bootloader) Jeżeli ktoś wie jak to zrobić prościej to piszcie 😉 (np. nie przeinstalowywanie Ardiuno IDE). Sorry ale nie wiem jak się wstawia zdjęcia źródło: 1. https://www.instructables.com/id/Arduino-Leonardo-as-Isp/ 2. można też obejrzeć Elektro Marsa (62. Jak przenieść projekt z Arduino na ATmega 328 )
-
Jak jednocześnie wyświetlać coś na LCD i obracać silnik krokowy?
Atypowy opublikował temat w Programowanie
Witam Chciałbym napisać kod dzięki któremu gdy kliknę przycisk, na wyświetlaczu pokazuje licznik który liczy do 100%, a w tym samym czasie obraca się silnik krokowy. Niestety nie wiem jak to zrobić żeby w tym samy czasie wszytko to się działo. Jak próbowałem to zrobić, to najpierw wyświetlacz liczył do 100%, a potem kręcił się silnik. Pomocy! -
Czołg Bluetooth - problem z zasilaniem i sterownikiem silników
Cinek97 opublikował temat w Arduino i ESP
Dobry wieczór, Jestem "świeży" w sprawach programowania kontrolerów takich jak arduino, ale musiałem zrobić projekt na uczelnie. Wybrałem sobie sterowany przez moduł bluethooth XM-15 czołg. Podłączyłem wszystko z lekką pomocą stworzyłem połączenie z telefonem, przy użyciu terminala arduino "odpowiadało mi". Więc dodałem bibliotekę do silników dodałem kilka linijek kodu i wtedy zaczął się problem. Używam shielda z L293D i póki arduino jest połączone z komputerem czołg się porusza, ale jeśli podepnę zasilanie do złącza DC, nic nie działa. Używam Arduino Leonardo, a moduł bluethooth jest połączony do pinów 10,11. Czy to wina płytki czy coś w kodzie mam nie tak? Drugie pytanie czy da się zamiast terminala sterować za pomocą "gotowych kontrolerów" z google marketu. Poniżej kod programu: #include <SoftwareSerial.h> #include <MotorDriver.h> //Deklaracja portu szeregowego dla Bluetootha SoftwareSerial Bluetooth(10, 11); //Utworz instancje Bluetooth 10-RX 11-TX int buffer_in[200]; int i=0; int BluetoothDane; //do zmiennej int będą zapisywane odebrane dane MotorDriver m; int jade=0; void setup() { //i=0; // jade=0;//uruchomienie transmisji z terminalem while(!Serial); Serial.begin(9600); Bluetooth.begin(9600); //uruchom SerialSoftware z prędkością 9600 baud //Serial.println("Polaczyles sie z modulem Bluetooth czolgiem"); // digitalWrite(13,LOW); } void loop() { if (Bluetooth.available()) //Jeśli są jakieś dane { i=0; while (Bluetooth.available()>0) //Odczytujemy dane z bluetooth aż odczytamy wszystko { buffer_in[i]=Bluetooth.read(); //kopiuje dane z bluetooth do bufora i++; } digitalWrite (13,HIGH); Serial.println("Odebrano =\n"); Serial.print(i); //Serial.print("Zawartosc bufora\n"); for(int j=0;j<i-5;j++) Serial.println(buffer_in[j]); Serial.print("Koniec bufora\n"); if (i>0) //sprawdzamy czy cokolwiek odebraliśmy { //jesli tak to sprawdzamy co w buforze if (buffer_in[0]==1) { Serial.println("jade do przodu"); m.motor(1,FORWARD,255); m.motor(4,FORWARD,255); } if (buffer_in[0]==2) { Serial.println("jade do tylu"); m.motor(1,BACKWARD,255); m.motor(4,BACKWARD,255); } if (buffer_in[0]==3) { Serial.println("prawo"); m.motor(1,FORWARD,255);; m.motor(4,BRAKE,0); } if (buffer_in[0]==4) { Serial.println("lewo"); m.motor(4,FORWARD,255); m.motor(1,BRAKE,0); } if (buffer_in[0]==5) { Serial.println("Stop"); m.motor(1,BRAKE,0); m.motor(4,BRAKE,0); } //jak już sprawdzilismy co w buforze to trzeba go wyczyscic // i w następnym przebiegu petli znowu czekamy na coś co przyjdzie z blue memset(buffer_in, 0, sizeof(buffer_in)); } delay(1); //odczekaj 1ms } } -
Pojawił mi się mały problem, a mianowicie gdy chce, żeby po wciśnięciu przycisku zaczął obracać się silnik, to nie mogę wyświetlić na wyświetlaczu(w tym samym momencie gdy silnik się kręci) "#" w pętli while (żeby był efekt ładowania), który co 1s pojawia "#", ponieważ najpierw silnik się obraca a później wyświetla "#" na wyświetlaczu.
- 1 odpowiedź
-
- silnik krokowy
- Arduino
- (i 2 więcej)
-
Witam, Mam problem i to dosyć spory, ponieważ zepsułem swoje arduino leonardo w taki sposób, że podłączyłem zły zasilacz i zamiast DC, arduino otrzymało 12V AC. Zwracam się z pomocą gdzie szukać problemu i czy w ogóle istnieje możliwość naprawy. Chciałbym sam naprawić uszkodzony element. Dlatego też pisze na forum o pomoc od czego zacząć sprawdzanie czy dany element jest okej czy też nie. Oczywiście o ile jest możliwość wskrzeszenia tego maleństwa. Z góry dzięki za pomoc :). Ja osobiście na pierwszy rzut oka nie widzę żadnych zmian ale wrzucam zdjęcie dla osób które może coś dostrzegą.
-
Witam, Mam następujący problem. Mianowicie chce wypalić bootloader w "arduino" nano przy pomocy arduino leonardo, lecz po uruchomieniu wypalania otrzymuje taki komunikat błędu i nie wiem co z tym zrobić sprawdzałem połączenia. Połączenia do "arduino" nano robiłem przy pomocy zdjęcia poniżej. Arduino:1.8.9 (Windows Store 1.8.21.0) (Windows 10), Płytka:"Arduino Nano, ATmega328P" avrdude: ser_open(): can't open device "\\.\COM6": Nie mo�na odnale�� okre�lonego pliku. Błąd przy wgrywaniu bootloadera.
- 27 odpowiedzi
-
Trudne początki Tak naprawdę to jest chyba mój pierwszy projekt w świecie Arduino! Zamarzyłem sobie zbudowanie własnego, terenowego pojazdu zdalnie sterowanego - takiego, na którym można potem zamontować jakiś chwytak, ramię albo kamerkę z przekaźnikiem FPV. Kontroler Tu akurat nie miałem większego wyboru, bo wtedy pod ręką miałem akurat Arduino Leonardo. Zaletą tej płytki jest kompatybilność z popularnymi shieldami do Uno a także złącze microUSB typu B (zamiast mało popularnego złącza "drukarkowego" w Uno). Na potrzeby tego niezbyt skomplikowanego projektu moc obliczeniowa tej płytki jest również całkowicie wystarczająca. Podwozie Moim planem było zbudowanie definitywnego i niepokonanego łazika marsjańskiego, więc zwykłe podwozie nie wchodziło w grę - koniecznie musiało być terenowe. Przegrzebałem naprawdę połowę Internetu w poszukiwaniu tego idealnego podwozia (ale - nie ukrywajmy - mieszczącego się również w moim budżecie) i w końcu mój wybór padł na podwozie Dagu DG012-ATV z napędem na cztery koła. Nieco podwyższony prześwit w stosunku do innych podwozi (dający nadzieję na pokonywanie niewielkich przeszkód), napęd na cztery koła - wszystko to brzmiało bardzo zachęcająco. Czterema silnikami coś oczywiście musi obracać, razem z podwoziem nabyłem więc również czterokanałowy sterownik silników DFRobota (w postaci shieldu dla Arduino). Serwo i czujnik Żeby urozmaicić nieco projekt, dodałem do niego serwo modelarskie, na którym zamontowałem ultradźwiękowy czujnik odległości z założeniem, że spróbuję kiedyś napisać program do autonomicznego poruszania się. RC Od długiego czasu używam do zdalnego sterowania aparatury FrSky Taranis, więc oczywiście musiałem skorzystać z kompatybilnego odbiornika - w tym przypadku X8R. Zasilanie Projekt oczywiście musiał być mobilny, więc zdecydowałem się na zasilenie go dwucelowym akumulatorem Lipo; konieczne okazało się też zastosowanie układu BEC, który obniżył napięcie akumulatora do 5V. Teraz pozostało już tylko zmontować wszystko w całość. Montaż podwozia Tu obyło się bez niespodzianek i problemów, po prostu skręciłem wszystko zgodnie z instrukcją i wyprowadziłem na zewnątrz przewody, którymi zasilane miały być silniki. Potem sprawy nieco się skomplikowały. Wszystko rozbiło się generalnie o to, że jak bym nie ułożył elementów na podwoziu, po prostu nie było takiego ułożenia, żeby wszystko się zmieściło. Sprawy utrudniał również fakt zastosowania Leonardo, które - umówmy się - jest raczej kobylaste i znacznie lepiej sprawdziłoby się tu kompatybilne z tą płytką Arduino Micro. Do tego dochodził BEC, odbiornik, serwo (którego nota bene nie miałem jak zamocować, bo w wersji 4WD podwozia miejsce na serwo zajmowane było przez dwa dodatkowe silniki) no i oczywiście akumulator. Dlatego zdecydowałem się na umieszczenie wszystkiego ponad podwoziem, pozostawiając na dole sam akumulator. Przykleiłem więc na dolnym pokładzie rzep, na którym mocowany jest akumulator - przeciążenia podczas poruszania robota są tak znikome, że jest to naprawdę pewny i sprawdzony sposób montażu (pozwalający też szybko zamontować albo zdemontować akumulator w razie potrzeby). Oprócz tego przykręciłem w narożnikach podwozia długie dystanse (kupione kiedyś w Chinach na potrzeby projektu quadrokoptera) i zabrałem się za przygotowywanie górnej części pojazdu. Górne podwozie wykonałem z fragmentu płytki aluminiowej, którą dociąłem tak, by znalazła się dokładnie ponad górną częścią podwozia - i jednocześnie dzięki temu przykryła koła, z których pył mógł się dostawać do elektroniki. W płytce wyciąłem otwór na serwo; ponieważ nie dysponuję żadnym sprzętem CNC, który pomógłby mi wyciąć równy, parametryczny otwór, rad nierad wziąłem do ręki wiertarkę, najpierw nawierciłem otwory, potem zamontowałem w niej frez i zacząłem ręcznie wycinać aluminium, a na końcu doszlifowałem wszystko pilnikami o zmniejszającej się ziarnistości. Cały proces poniżej: Teraz można było powoli przystąpić do montażu. Na pierwszy ogień poszło serwo, które na szczęście wpasowało się w wycięty przeze mnie otwór po prostu idealnie. Następnym krokiem było zamontowanie BECa, którego umieściłem pod górnym pokładem. Przewód zasilający (zakończony złączem T-Dean) musiałem rozgałęzić, ponieważ jedna para przewodów musiała zostać połączona z BECem, który obniży napięcie do 5V dla części elektroniki, zaś druga para - do sterownika silników, który będzie potem je zasilał. Szczęśliwie silniki akceptują napięcie dwucelowego akumulatora LiPo - trzeba to koniecznie sprawdzić przed zakupem/montażem! Arduino Leonardo można zasilić bezpośrednio z akumulatora, natomiast konieczne było przylutowanie odpowiedniej wtyczki (na zdjęciu po prawej stronie). Na koniec pozostało podłączenie wszystkich komponentów i otrzymujemy następujący efekt: Programowanie Pierwszym programikiem, który napisałem, był tester silników, który uruchamiał każdy z nich na pół sekundy. Kod wygląda następująco: const int E1 = 3; // Motor1 Speed const int E2 = 11; // Motor2 Speed const int E3 = 5; // Motor3 Speed const int E4 = 6; // Motor4 Speed const int M1 = 4; // Motor1 Direction const int M2 = 12; // Motor2 Direction const int M3 = 8; // Motor3 Direction const int M4 = 7; // Motor4 Direction void M1_advance(char Speed) { digitalWrite(M1, HIGH); analogWrite(E1, Speed); } void M2_advance(char Speed) { digitalWrite(M2, LOW); analogWrite(E2, Speed); } void M3_advance(char Speed) { digitalWrite(M3, LOW); analogWrite(E3, Speed); } void M4_advance(char Speed) { digitalWrite(M4, HIGH); analogWrite(E4, Speed); } void M1_back(char Speed) { digitalWrite(M1, LOW); analogWrite(E1, Speed); } void M2_back(char Speed) { digitalWrite(M2, HIGH); analogWrite(E2, Speed); } void M3_back(char Speed) { digitalWrite(M3, HIGH); analogWrite(E3, Speed); } void M4_back(char Speed) { digitalWrite(M4, LOW); analogWrite(E4, Speed); } void setup() { for (int i = 3; i < 9; i++) pinMode(i, OUTPUT); for (int i = 11; i < 13; i++) pinMode(i, OUTPUT); pinMode(LED_BUILTIN, OUTPUT); } void loop() { digitalWrite(LED_BUILTIN, HIGH); M1_advance(100); delay(500); M1_advance(0); M2_advance(100); delay(500); M2_advance(0); M3_advance(100); delay(500); M3_advance(0); M4_advance(100); delay(500); M4_advance(0); digitalWrite(LED_BUILTIN, LOW); delay(2000); // Delay 2S } Jak widać, sterowanie silnikami odbywa się poprzez podawanie kierunku poprzez piny cyfrowe i prędkości poprzez piny analogowe - proste, jak konstrukcja cepa. Teraz przyszła kolej na odbiornik RC i tu zaczęły się schody. Odbiorniki klasycznie podają stan każdego kanału poprzez sygnał PWM. W praktyce jest to seria naprzemiennych zer i jedynek, z których każda para 1+0 trwa 1/55 sekundy. Wartość możemy odczytać mierząc czas trwania sygnału 1: jeżeli jest to 1 milisekunda, przyjmujemy wartość minimalną ("-1"), jeżeli 1.5 milisekundy, to wartość środkową ("0"), zaś jeśli 2 milisekundy, to wartość maksymalną ("1"). Niektóre odbiorniki pozwalają na nieco szerszy zakres - od 0.5ms do 2.5ms, X8R domyślnie podaje wartości z tego pierwszego zakresu. Ponieważ musiałem mierzyć wartości na dwóch różnych kanałach, zdecydowałem się skorzystać z mechanizmu przerwań. Działa on mniej więcej następująco: gdy zajdzie wybrane zdarzenie (na przykład zmiana stanu danego pinu z niskiego na wysoki), wykonanie programu jest przerywane, zostaje wykonana funkcja oznaczona jako tzw. handler przerwania, a po jej zakończeniu program wznawia wykonanie w miejscu, w którym został przerwany. Na Arduino można znaleźć bardzo wygodną bibliotekę EnableInterrupt, która uogólnia sposób dodawania i usuwania handlerów przerwań pomiędzy różnymi wersjami Arduino, a korzysta się z niej w następujący sposób: #include "EnableInterrupt.h" volatile int microsStart = 0; void pin0Rising() { microsStart = micros(); disableInterrupt(0); enableInterrupt(0, pin0Falling, FALLING); } void pin0Falling() { int microsEnd = micros(); int diff = microsEnd - microsStart; if (diff > 1500) { digitalWrite(LED_BUILTIN, HIGH); } else { digitalWrite(LED_BUILTIN, LOW); } disableInterrupt(0); enableInterrupt(0, pin0Rising, RISING); } void setup() { enableInterrupt(0, pin0Rising, RISING); pinMode(LED_BUILTIN, OUTPUT); } void loop() { } Po wpięciu przewodu sygnałowego do pinu 0 i uruchomieniu programiku na kontrolerze, wbudowana dioda powinna się zapalić w momencie, gdy ustawimy drążek w położeniu większym niż połowa. Zwrócę jeszcze uwagę na magiczne słówko "volatile" przy deklaracji zmiennej - informuje ono kompilator, że zmienna ta nie może zostać zoptymalizowana (kompilator, a dokładniej optymalizator w niektórych przypadkach może w locie usunąć zmienną, na przykład jeżeli nie jest ona używana lub przez cały czas trwania programu ma zawsze tę samą wartość). Dodam tu jeszcze jedną ważną informację: program obsługi przerwania powinien być tak krótki, jak to tylko możliwe! Ma to sporo sensu jeżeli się nad tym nieco dłużej zastanowić, ale ja na to nie wpadłem i w pierwotnej wersji programu cała obsługa silników umieszczona była właśnie w programie obsługi przerwania. I ku mojemu zdziwieniu, po uruchomieniu programu, pomimo tego, że drążki były w położeniu zerowym, dwa silniki zaczęły się obracać. Okazało się, że obsługa przerwania obliczającego czas trwania PWM na pierwszym kanale trwała tak długo, że sztucznie opóźniała wywołanie drugiego przerwania wykonującego te same obliczenia dla drugiego kanału, przez co podawało ono zawyżone wartości. Wystarczyło przebudować program w taki sposób, by obsługa silników znalazła się poza programami obsługi przerwań i wszystko wróciło do normy. Pamiętajmy - to może oczywiste, ale mimo wszystko warto to powiedzieć - że mikrokontrolery nie są wielowątkowe, a przerwania nie są wątkami: wykonują się tylko jedno na raz. Drugie przerwanie musi czekać, aż pierwsze zostanie do końca obsłużone. Przed napisaniem końcowego programu pozostało mi już tylko przetestować obsługę czujnika ruchu, programik wygląda następująco: #include <NewPing.h> #define ULTRASONIC_TRIGGER_PIN 9 #define ULTRASONIC_ECHO_PIN 10 #define MAX_DISTANCE 400 NewPing sonar(ULTRASONIC_TRIGGER_PIN, ULTRASONIC_ECHO_PIN, MAX_DISTANCE); void setup() { pinMode(LED_BUILTIN, OUTPUT); } void loop() { digitalWrite(LED_BUILTIN, HIGH); delay(50); digitalWrite(LED_BUILTIN, LOW); delay(50); int ping = sonar.ping_cm(); if (ping < 30) digitalWrite(LED_BUILTIN, HIGH); else digitalWrite(LED_BUILTIN, LOW); delay(200); } Również i tu korzystam z wbudowanej diody, która powinna zapalić się, gdy zmierzona przez czujnik odległość będzie mniejsza niż 30 cm. Wreszcie program obsługujący całego robota: #include <NewPing.h> #include "EnableInterrupt.h" #include "NewPing.h" // Motor constants // Motor1 Speed #define MOTOR_1_SPEED_PIN 3 // Motor2 Speed #define MOTOR_2_SPEED_PIN 11 // Motor3 Speed #define MOTOR_3_SPEED_PIN 5 // Motor4 Speed #define MOTOR_4_SPEED_PIN 6 // Motor1 Direction #define MOTOR_1_DIR_PIN 4 // Motor2 Direction #define MOTOR_2_DIR_PIN 12 // Motor3 Direction #define MOTOR_3_DIR_PIN 8 // Motor4 Direction #define MOTOR_4_DIR_PIN 7 // Ultrasonic constants #define ULTRASONIC_TRIGGER_PIN 9 #define ULTRASONIC_ECHO_PIN 10 #define MAX_DISTANCE 400 // Servo constants #define SERVO_PIN 13 // AI constants #define DISTANCE_THRESHOLD_2 80 #define DISTANCE_THRESHOLD_1 40 // Ultrasonic control NewPing sonar(ULTRASONIC_TRIGGER_PIN, ULTRASONIC_ECHO_PIN, MAX_DISTANCE); // Motor control functions void M1_advance(byte Speed) ///<Motor1 Advance { digitalWrite(MOTOR_1_DIR_PIN, HIGH); analogWrite(MOTOR_1_SPEED_PIN, Speed); } void M2_advance(byte Speed) ///<Motor2 Advance { digitalWrite(MOTOR_2_DIR_PIN, LOW); analogWrite(MOTOR_2_SPEED_PIN, Speed); } void M3_advance(byte Speed) ///<Motor3 Advance { digitalWrite(MOTOR_3_DIR_PIN, LOW); analogWrite(MOTOR_3_SPEED_PIN, Speed); } void M4_advance(byte Speed) ///<Motor4 Advance { digitalWrite(MOTOR_4_DIR_PIN, HIGH); analogWrite(MOTOR_4_SPEED_PIN, Speed); } void M1_back(byte Speed) ///<Motor1 Back off { digitalWrite(MOTOR_1_DIR_PIN, LOW); analogWrite(MOTOR_1_SPEED_PIN, Speed); } void M2_back(byte Speed) ///<Motor2 Back off { digitalWrite(MOTOR_2_DIR_PIN, HIGH); analogWrite(MOTOR_2_SPEED_PIN, Speed); } void M3_back(byte Speed) ///<Motor3 Back off { digitalWrite(MOTOR_3_DIR_PIN, HIGH); analogWrite(MOTOR_3_SPEED_PIN, Speed); } void M4_back(byte Speed) ///<Motor4 Back off { digitalWrite(MOTOR_4_DIR_PIN, LOW); analogWrite(MOTOR_4_SPEED_PIN, Speed); } // PWM control volatile int microsYStart = 0; volatile int microsXStart = 0; volatile int microsZStart = 0; volatile int yMicros = 0; volatile int xMicros = 0; volatile int zMicros = 0; int UScounter = 0; int USlock = 0; // Pin 0 interrupt handling void pin0Rising() { microsYStart = micros(); disableInterrupt(0); enableInterrupt(0, pin0Falling, FALLING); } void pin0Falling() { yMicros = micros() - microsYStart; disableInterrupt(0); enableInterrupt(0, pin0Rising, RISING); } // Pin 1 interrupt handling void pin1Rising() { microsXStart = micros(); disableInterrupt(1); enableInterrupt(1, pin1Falling, FALLING); } void pin1Falling() { xMicros = micros() - microsXStart; disableInterrupt(1); enableInterrupt(1, pin1Rising, RISING); } // Pin2 interrupt handling void pin2Rising() { microsZStart = micros(); disableInterrupt(2); enableInterrupt(2, pin2Falling, FALLING); } void pin2Falling() { zMicros = micros() - microsZStart; disableInterrupt(2); enableInterrupt(2, pin2Rising, RISING); } void setup() { for (int i = 3; i < 9; i++) pinMode(i, OUTPUT); for (int i = 11; i < 13; i++) pinMode(i, OUTPUT); pinMode(ULTRASONIC_TRIGGER_PIN, OUTPUT); pinMode(ULTRASONIC_ECHO_PIN, INPUT); pinMode(SERVO_PIN, OUTPUT); enableInterrupt(0, pin0Rising, RISING); enableInterrupt(1, pin1Rising, RISING); enableInterrupt(2, pin2Rising, RISING); } void loop() { // Eval motor signals int yValue = (yMicros - 1500) / 2; int xValue = (xMicros - 1500) / 2; if (yValue > 260 || yValue < -260) yValue = 0; if (xValue > 260 || xValue < -260) xValue = 0; int leftEngines = constrain(xValue + yValue, -250, 250); int rightEngines = constrain(yValue - xValue, -250, 250); // Check for obstacles every 10th iteration UScounter++; if (UScounter >= 10) { UScounter = 0; int frontDistance = sonar.convert_cm(sonar.ping_median(5)); if (frontDistance != 0 && frontDistance < DISTANCE_THRESHOLD_2) { if (frontDistance > DISTANCE_THRESHOLD_1) USlock = 1; else USlock = 2; } else USlock = 0; } if (USlock == 1) { leftEngines = constrain(leftEngines, -250, 128); rightEngines = constrain(rightEngines, -250, 128); } if (USlock == 2) { leftEngines = constrain(leftEngines, -250, 0); rightEngines = constrain(rightEngines, -250, 0); } if (abs(leftEngines) < 20) { M3_advance(0); M4_advance(0); } else if (leftEngines > 0) { M3_advance(leftEngines); M4_advance(leftEngines); } else { M3_back(-leftEngines); M4_back(-leftEngines); } if (abs(rightEngines) < 20) { M1_advance(0); M2_advance(0); } else if (rightEngines > 0) { M1_advance(rightEngines); M2_advance(rightEngines); } else { M1_back(-rightEngines); M2_back(-rightEngines); } } Pozwala on na kontrolowanie robota przy pomocy jednego drążka aparatury (dwóch kanałów). Oprócz tego program cyklicznie sprawdza odległość przed robotem i zabezpiecza przed wjechaniem w ścianę: w przypadku przeszkody znajdującej się bliżej niż 80 cm od robota, zostanie ograniczona jego maksymalna prędkość, natomiast jeżeli odległość ta będzie mniejsza niż 40cm, robot zatrzyma się całkowicie i niemożliwe będzie ruszenie nim do przodu. Wnioski To była prawdziwa frajda zobaczyć, jak robot rusza i jeździ zgodnie z instrukcjami z aparatury! Pierwszy skończony projekt. Nauczyłem się na nim dużo, bo okazało się, że w trakcie pracy podjąłem bardzo dużo nietrafnych decyzji. Robot tak naprawdę nigdy nie wyjechał z domu, ma bardzo otwartą konstrukcję, która sprzyja dostawaniu się do obudowy pyłu i piachu. W domowych warunkach wystarczyłby natomiast napęd na dwa koła - w ten sposób miałbym też trochę miejsca wewnątrz obudowy. Arduino Leonardo jest świetne, ale wielkie. Znacznie lepiej sprawdziłoby się Arduino Micro albo Teensy. To drugie nawet bardziej, bo shield do sterowania silnikami pożera dużo pinów i niewiele zostaje na odbiór sygnału z odbiornika RC. Udało mi się jeszcze podłączyć czujnik odległości, ale serwo wpiąłem już bezpośrednio w odbiornik, bo po prostu zabrakło mi pinów. Nie ma większego sensu robić żadnych projektów (innych niż wstępne prototypy) na przewodzikach połączeniowych. Lepiej kupić sobie płytkę prototypową, złącza goldpinowe, przewodziki kydexowe i polutować wszystko na płytce - układ zajmuje znacznie mniej miejsce i jest znacznie mniej podatny np. na przypadkowe wyjęcie przewodu. Chodzi mi po głowie wskrzeszenie projektu - właśnie przy pomocy Teensy oraz drukarki 3D, przy pomocy której mogę wydrukować całe nadwozie szyte na miarę. Ale podejrzewam, że zajmę się tym dopiero za jakiś czas...