Skocz do zawartości

Tablica liderów


Popularna zawartość

Pokazuje zawartość z najwyższą reputacją 28.03.2019 we wszystkich miejscach

  1. 2 punkty
    Co to jest timelapse? W razie, gdyby ktoś nie wiedział, co mało prawdopodobne, ale jednak - jest to przeciwieństwo slow-motion, czyli film, który jest kilka albo kilkanaście razy przyspieszony. Filmy takie pozwalają obejrzeć zjawiska, które ze swojej natury są bardzo wolne, na przykład wyrastanie ciasta, płynięcie chmur na niebie, rośnięcie roślin i tak dalej. Nagranie timelapse nie jest jakimś wielkim wyczynem, bo większość aparatów i kamerek sportowych ma taki tryb wbudowany, a na telefony komórkowe istnieją tysiące aplikacji realizujących takie właśnie nagranie. Do czego więc może służyć maszyna do timelapse? Najbardziej podstawową wersją timelapse jest oczywiście nieruchomy kadr - ustawiamy kamerę na statywie, uruchamiamy proces nagrywania i zostawiamy wszystko na odpowiedni czas. Filmy takie same w sobie robią już wrażenie, ale znacznie ciekawiej jest, gdy kadr jest zmienny, na przykład gdy zastosujemy panoramowanie (czyli powolny obrót) albo liniowe przesunięcie. Kłopot polega na tym, że obrót taki musi być realizowany bardzo wolno - w tempie dopasowanym do tempa robienia zdjęć. 45 stopni to być może dużo, ale jeżeli kamera ma zarejestrować, powiedzmy, 40 minut materiału przy 30 klatkach na sekundę, to mamy prędkość obrotu rzędu 45/(40*60) = 0,01875 stopnia na sekundę. Żeby było trudniej, kamera musi obracać się płynnie, bo timelapse będzie wyraźnie poszarpany. Do czegoś takiego trzeba już dedykowanego urządzenia: kupionego albo - co znacznie ciekawsze - zrobionego samodzielnie. Komponenty Tym razem kontrolerem stało się Arduino Uno, między innymi dlatego, że razem z shieldem z wyświetlaczem i klawiaturą zapewniło dosyć niskim kosztem interfejs użytkownika. Płynny i w pełni kontrolowany obrót zapewni silnik krokowy, a ten konkretny, czyli SY35ST26-0284A wybrałem w dużej mierze dlatego, że można go zasilić bezpośrednio dwucelowym akumulatorem LiPo. Do silnika należało oczywiście również kupić odpowiedni sterownik. Oprócz tego wyposażyłem się też w obudowę - być może efekt końcowy nie powala estetyką, ale bardzo nie lubię kończyć projektów z gmatwaniną sterczących przewodów i po ukończeniu jeżdżącego robota stwierdziłem, że będę dbał również o wygląd moich projektów. To nie był koniec zakupów - silnik krokowy oferuje 200 kroków na obrót, co daje 1,8 stopnia na krok. Tymczasem ja potrzebowałem stukrotnie większej dokładności, dlatego konieczne było zbudowanie przekładni zębatej. Zębatki Z przekonaniem, że w Internecie można znaleźć wszystko zacząłem szukać zębatek i okazało się, że wcale nie tak łatwo jest znaleźć zębatki do takiego projektu. Byłem ograniczony ich rozmiarem oraz sposobem montażu - nie posiadając wtedy drukarki 3D (na której pewnie sam wydrukowałbym potrzebne koła), miałem też ograniczone możliwości związane z montażem komponentów. W akcie desperacji napisałem email z zapytaniem ofertowym do krakowskiej firmy, która specjalizuje się w produkcji kół zębatych, ale koszty rzędu (o ile dobrze pamiętam) 800 PLN za cztery koła zębate przekraczały wielokrotnie mój budżet na ten projekt. Wróciłem więc do poszukiwań i w końcu znalazłem odpowiednie koła zębate w sklepie conrad.pl. Kupiłem dwa czterdziestozębowe i dwa trzydziestozębowe - w przypadku, gdyby te pierwsze nie zmieściły się wewnątrz obudowy. Oprócz tego kupiłem jedną piętnastkę oraz dwunastkę - ta ostatnia miała otwór na oś pasujący do kupionego przeze mnie silnika krokowego. Przekładnia Teraz musiałem zaprojektować przekładnię - skorzystałem w tym celu z darmowego Solid Edge Drafting - świetnego dwuwymiarowego cada. Pomierzyłem wszystkie przestrzenie suwmiarką i wyszło na to, że przekładnia zmieści się w całości w przedniej, podwyższonej części obudowy. Nie dysponuję żadną maszyną CNC, ale otwory w aluminiowych płytkach musiałem zrobić bardzo dokładnie, bo inaczej zębatki nie zazębiłyby się (w jedną albo drugą stronę) albo obracały ze zbyt dużym oporem. Wpadłem więc na pomysł - wydrukowałem układ otworków w obu płytkach przygotowany wcześniej w cadzie na papierze samoprzylepnym i przykleiłem go na obrabianym aluminium. Potem dociąłem płytki zgodnie z ramkami i wywierciłem otwory w oznaczonych miejscach - okazało się, że taka dokładność była wystarczająca i wszystko ładnie wskoczyło na swoje miejsca. Montaż Po zbudowaniu przekładni nie zostało już zbyt dużo do roboty - zamontowałem wewnątrz obudowy Uno z shieldem LCD, podłączyłem do przygotowanej wcześniej płytki prototypowej ze sterownikiem silnika, a do niej sam silnik. Potem skręciłem wszystko i dostałem (w miarę) zgrabne urządzenie. Programowanie Na potrzeby tego projektu napisałem specjalnie własny zestaw bibliotek, które ułatwiają budowanie wielopoziomowych menu na shieldzie LCD. Programik jest stosunkowo prosty - należy obrócić silnik w położenie źródłowe i docelowe, ustalić czas obrotu - i uruchomić. Program oblicza o jaki kąt obrócić silnik w jakim czasie i powolutku obraca oś z jednego położenia do drugiego. Ponieważ program z bibliotekami jest dosyć duży, nie będę go tu zamieszczał, ale można go ściągnąć z mojego repozytorium na gitlabie. Efekty Czy cel został osiągnięty? Definitywnie tak - nagrane filmy poddaję niewielkiej obróbce w VirtualDub (korzystam z plugina o nazwie deshaker), żeby odrobinę poprawić ich jakość, ale nawet i bez tej obróbki filmiki wyglądają całkiem przyzwoicie. Przykładowy poniżej: Wnioski Po pierwsze, maszyna jest niestety przeraźliwie głośna. Obracanie (przynajmniej na początku, podczas ustawiania zakresów) osi generuje dźwięk przypominający skrzyżowanie kosiarki do trawy i piły łańcuchowej. Winne są najprawdopodobniej pancerne zębatki oraz luzy na osiach - teraz, mając już drukarkę 3D, wydrukowałbym sobie wszystko z PLA spasowane do dziesiątych milimetra, podczas budowy tego urządzenia skazany byłem jednak tylko na własne ręce i montaż przekładni na pewno nie jest tak dokładny jaki mógłby być. Poza tym warto byłoby rozważyć również zastosowanie mniejszych, plastikowych zębatek, tylko obawiałem się trochę, czy będę w stanie zamontować je pewnie do osi - tak, by nie wyrobiły się i nie zaczęły obracać w miejscu. Plusem tej przekładni jest natomiast fakt, że jest po prostu pancerna - myślę, że spokojnie mógłbym zamontować na niej lustrzankę z solidnym obiektywem i ani przekładnia ani silnik nawet by nie sapnęły. Zdecydowanie warto było zainwestować w obudowę - kosztowała mnie raptem 15 złotych, a znacząco podniosła estetykę projektu (i przynajmniej w pewnym stopniu chroni elektronikę przed warunkami atmosferycznymi i kurzem. Wbrew pozorom dosyć wygodne okazało się zasilenie urządzenia z zewnątrz - wyprowadziłem sobie ze środka kabelek zakończony wtyczką T-Dean i gdy chcę uruchomić narzędzie, po prostu łapię jeden z dwucelowych akumulatorów LiPo walających się gdzieś po domu i maszyna może na nim działać naprawdę długo. Choć urządzenie powstało już jakiś czas temu, nie użyłem go jeszcze zbyt wiele razy; tak naprawdę zbudowałem je pod kątem filmowego projektu, który mam zamiar nakręcić, ale wymaga on dosyć dużo czasu w plenerze, a tego zasobu od jakiegoś czasu niestety trochę mi brakuje. Ale też nie tracę nadziei - być może za kilka lat zrealizujemy go razem z córką? Czas pokaże...
  2. 2 punkty
    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...
  3. 2 punkty
    To co robiłem jak najbardziej było testami jednostkowymi. A logika biznesowa to miejsce, gdzie takie testy dają najwięcej wartości i są najłatwiejsze do napisania.
  4. 2 punkty
  5. 2 punkty
  6. 1 punkt
    Dostępne na rynku oczyszczacze powietrza nie kosztują mało. Sam filtr, który wydaje się najważniejszym elementem kosztuje najczęściej nie więcej niż 1/3 oczyszczacza. Postanowiłem więc zbudować własny oczyszczacz. Oczywiście czas poświęcony na budowę też ma wartość, ale nie traktuje tego jako roboczogodziny a po prostu zabawę . W moim przypadku, koszt całości wyniósł około 300zł. Dla porównania, gotowy oczyszczacz Xiaomi to wydatek około 500zł, jesienią było to minimum ~650zł . Kupiłem filtr Xiaomi z wkładem węglowym, który jest nieco droższy niż zwykły, który montowany w fabrycznych oczyszczaczach. Użyty przeze mnie wentylator posiada według producenta wydajność 150m³/h co jest wartością 2x mniejszą niż fabryczny oczyszczacz. Jest to jednak w zupełności wystarczające. Mechanika Oczyszczacz składa się z filtra powietrza, wentylatora 200mm, łącznika filtra z wentylatorem i sterownika. Łącznik został wydrukowany na drukarce 3D. Wentylator to najtańszy wentylator 200mm jaki znalazłem w sklepie komputerowym. Elektronika Całość bazuje na płytce z ESP32. Na niej znajduje się shield prototypowy Arduino, a do niego są zamontowane kolejne elementy. Używałem głównie gotowych modułów. Starałem się w miarę możliwości nie lutować ich bezpośrednio do PCB tylko umieszczać na listwach kołkowych. Schematu niestety nie mam. Wszystko było lutowane na bieżąco w przypływach weny Planuje jeszcze wyprowadzić drugą szynę I2C i podłączyć do niej drugi barometr który będzie umieszczony w wewnętrznej części filtra. Będę mógł w ten sposób zbadać zależność różnicy ciśnień od obrotów wentylatora. Czujniki Jako czujnik pyłu zastosowałem GP2Y1010AU0F. Kluczem była niska cena. Niestety wymaga on dość dokładnego synchronizowania w czasie załączania diody LED i pomiaru napięcia wyjściowego. Z czym miałem duże problemy o czym napiszę niżej. Dodatkowo, jako że jest to czujnik analogowy, jego wyjście skaluje się względem napięcia zasilania. A tak się składa że o ile ESP32 jest zasilane ze stabilnych 3.3V, to czujnik jest zasilany z szyny 5V. Tutaj występuje wyraźny rozstrzał między zasilaniem z zasilacza (wtedy szyna 5V jest zasilana przez diodę która powoduje spadek napięcia) a zasilaniem przez USB. Staram się to kompensować dodatkowym pomiarem napięcia szyny 5V. Nie jest to idealnie, choć daje dużo. Prawdopodobnie czujnik nie skaluje swojego wyjścia idealnie liniowo z napięciem zasilania, stąd ten problem. Oprócz tego na płytce znajduje się czujnik wilgotności HDC1080 oraz ciśnienia BMP280. Oba mają wbudowane termometry, więc nie potrzeba dodatkowego. Teraz prawdopodobnie użyłbym BME280. Interfejs W sterowniku użyłem wyświetlacza OLED. Wyświetlane są na nim aktualne parametry, takie jak: temperatura, wilgotność, poziom zanieczyszczeń, moc wentylatora i inne. Wyświetlacz jest sterowany za pomocą interfejsu I2C. Obok wyświetlacz znajduje się enkoder. Użyłem gotowego modułu bo akurat nie miałem pod ręką tego typu enkodera z przyciskiem. Można nim regulować moc oczyszczacza oraz przełączać między trybami: "auto" i "manual". Oczywiście jak na 2019 rok przystało, oczyszczaczem można sterować też po WiFi :) Na ESP32 jest uruchomiony webserver. Panel webowy wygląda tak: W kodzie znajdują się funkcje które utrzymują stałą łączność WiFi z routerem. Dane dostępowe do znanych nam WiFi należy umieścić w pliku "wifi_credentials.json" i wgrać wraz z innymi plikami. Niestety hasła należy umieścić w formie tekstowej. Biblioteka micropythona do obsługi WiFi nie obsługuje haseł w wersji zahashowanej (PSK). W przyszłości może dopiszę bardziej ludzką formie wprowadzania haseł Sterowanie wentylatorem Z racji tego że użyłem najtańszego wentylatora o tej średnicy, posiada on tylko 3 pinową wtyczkę. Taki wentylator można sterować jedynie napięciowo. Wymyśliłem więc sposób na regulację PWMem napięcia wyjściowego przetwornicy impulsowej. Polega to na podkradaniu lub wprowadzaniu dodatkowego prądu do wyjściowego dzielnika napięcia. Schemat tego wygląda następująco: Zauważyłem że im mniejsza częstotliwość sygnału PWM, tym bardziej nieliniowa jest zależność Vout=f(PWM). Dlatego częstotliwość PWM została ustawiona na 312kHz. Aproksymacje tej funkcji stworzyłem robiąc pomiary Vout w zależności od danego wypełnienia PWM, a następnie w arkuszu kalkulacyjnym wyznaczyłem współczynniki funkcji liniowej. Współczynniki te są na sztywno zapisane w kodzie. Micropython Zdecydowałem się użyć micropythona ze względu na chęć nauki czegoś nowego. Niestety, jak okazało się w trakcie, posiada on wiele ograniczeń. Największą wadą jest używanie blokującego dostępu do interfejsów komunikacyjnych. Przez co np.: w trakcie odświeżania wyświetlacza nie można dokonywać pomiarów czujnika pyłu czy obsługiwać żądań serwera. Ne można też używać drugiego rdzenia ESP32. Przez co interfejs użytkownika chodzi wyraźnie wolno, i nie wygląda na uruchomiony na czymś tak mocnym Cały kod jest dostępny na GitHubie: https://github.com/Harnas/ESP32_Airpurifier
  7. 1 punkt
    Bardzo fajne wykonanie. Jakieś 2 lata temu zrobiłem podobny feeder. Ale Twój wygląda o wiele lepiej. Kotki widzę że również zadowolone. Świetna robota !
  8. 1 punkt
    Dziękuję za głosy na Cukiereczka oraz za przesłany zestaw gadżetów!
  9. 1 punkt
    To wszystko zależy od protezy. Jeśli masz protezę poniżej kolana to po prostu się musisz przyzwyczaić do stopy. Jeśli masz nad kolanem (i jakiś napęd tego kolana) to ważniejszy jest kąt zgięcia (zresztą mózg nie dostaje danych o bezwzględnym położeniu kończyny, ale właśnie o kątach). To że ludzie z protezami chodzą o kulach to raczej normalne - żadna proteza nie zapewni dokładnego wyczucia położenia, a kula pomaga w wielu przypadkach w utrzymaniu równowagi (ewentualnie po porostu w tym, żeby nie polecieć na ryj jak się potkniesz). A jeśli masz sztywną protezę powyżej kolana, to i tak kula jest potrzebna choćby po to, aby zejść ze schodów bo sztywna proteza tego nie umożliwia. Sam mam taką trzecią nogę (cukrzyca, dna i tak dalej) i potrzebuję jej wtedy kiedy tracę równowagę... a przecież obie nogi mam swoje...
  10. 1 punkt
    @adusn86 Wszystko co ma efekt "wow" kosztuje. Żyroskop do mojego robota kosztował z 5 zł, ale podejrzewam że w Segwayach są dokładniejsze. Cały mój robot nie jest zbyt dokładny co widać po tym jak się trzęsie, choć to pewnie głównie zasługa silników. Są to drogie pojazdy, ale jak się doda wszystko razem to koszt części niski nie jest, a że ich główne zastosowanie jest w specjalistycznej branży to i marżę można dodać sobie większą. @ethanak Zgaduję że dzięki temu taka noga będzie się sama naturalnie zginać w kolanie, tak jak to robi ludzka noga. Nogi mam swoje i nigdy nie miałem do czynienia z protezami, ale tak zgaduję. Drugą opcją która przychodzi mi do głowy to balansowanie tej nogi. Zauważ że jak stoisz, pomimo że się nie ruszasz to mięśnie w nodze cały czas pracują aby utrzymać cię w pionie, a szczególnie palce u stopy. Z tego co słyszałem, osobom które straciły palce u nóg ciężej jest utrzymać stabilność. Bardzo dobrze to widać na robocie, który pomimo że ma za zadanie stać prosto, cały czas musi korygować swoją pozycję i silniki cały czas pracują, w przeciwnym wypadku od razu się wywala. Osoby z protezą nogi często chodzą o kulach, chociaż teoretycznie ilość kończyn jest taka sama. Sztuczna noga nie zapewnia jednak tego balansu który zapewnia prawdziwa. To wszystko moje domysł, poczekajmy aż Adusn się wypowie
  11. 1 punkt
    z ciekawości: po co w protezie nogi żyroskop? poważnie pytam...
  12. 1 punkt
    Nie testowałem, ale powinno dać się programować ATmegę8, tutaj masz przykładowy poradnik na ten temat: https://www.hackster.io/hami/programming-atmega8-using-arduino-ide-90c2ad
  13. 1 punkt
    W sumie Arduino to taka zabawka... edukacyjna co prawda ale jednak zabawka. Co w tym dziwnego, że większość projektów powstałych na bazie zabawki to po prostu zabawki następnej generacji? Pokaż przykłady projektów które były: bajerami duperelami aby potwierdzić swoją opinię. Twierdzenie że "coś tam to większość" to nie to forum - tu siedzą ludzie przyzwyczajeni (abo tacy, którzy powinni się przyzwyczaić) do ścisłych sformułowań
  14. 1 punkt
    Cześć wszystkim, jestem Filip i mam 24 lata i studiuję na ASP. Zajmuję się sztuką interaktywną i robotyczną. Obecnie robię pracę dyplomową magisterską właśnie w ramach sztuki robotycznej. Zawodowo zajmuję się programowaniem front-endowym i czasami sztuką.
  15. 1 punkt
    @roger_z >"Założę się, że to były po prostu testy dlatego, że miały jakieś być." Nie, było to TDD. I w dodatku prowadzący z którymi to było są na co dzień seniorami w pewnej dużej firmie IT, jeśli ma to tu jakieś większe znaczenie. >"warto mieć testy, żeby przy refactoringach czegoś nie popsuć." Jeśli zmienia się również interfejsy to trzeba wtedy pisać od nowa testy. Przy takim dynamicznym kodzie chyba lepiej pisać testy po napisaniu kodu.
  16. 1 punkt
    #2 Klawiatura na Arduino to dość przydatna sprawa. Tylko że jak ma się podobne komercyjne rozwiązania to własne DIY odchodzą na drugi plan. Ale jest w tym trochę prawdy, że ciężko wymyślić coś naprawdę praktycznego. Ostatnio zainteresowało mnie modelarstwo (modele HO lokomotyw, semafory itp...) jest to temat, w którym za prosty sterownik diody świecącej płaci się po kilkadziesiąt $. Myślę, że to jest obszar, w którym znajomość Arduino i podstaw elektroniki pozwala zaoszczędzić sporo pieniędzy.
  17. 1 punkt
    Trochę wyrywam z kontekstu, ale wykorzystam to, by podkreślić jedną ważną rzecz TDD to NIE są testy jednostkowe. @dambodomyslam się, że pytasz o narzędzia do C/C++. Mimo że wiele lat spędziłem z tymi językami, to było to w czasach, gdy o TDD nie miałem jeszcze pojęcia. Jako że od długiego czasu siedzę już w Javie, to w C/C++ też dopiero robię research, jakich narzędzi do TDD warto używać. @Harnas >Nigdy nie pracowałem w TDD poza laborkami na studiach. Założę się, że to TDD nie było odpowiednio omówione. Założę się, że to były po prostu testy dlatego, że miały jakieś być. >Wydaje mi się że aby TDD dobrze działało wymagana jest dokładna wiedza o tym co, jak i w jakiej strukturze ma powstać. Tak. Zauważ, że w danej chwili dokładnie wiesz, nad czym pracujesz. Testami pokrywasz bieżącą, właśnie implementowaną funkcjonalność. Nawet w innowacyjnych startupach ma to sens. Kod będzie ewoluował? Tym bardziej warto mieć testy, żeby przy refactoringach czegoś nie popsuć.
  18. 1 punkt
    To jakiego typu projekty chciałbyś widzieć w wykonaniu hobbystów? Ludzie budują głównie to na co mają ochotę i to, co sprawia im frajdę. Takie kolorowe gadżety buduje się najprzyjemniej
  19. 1 punkt
    Wszystkie osoby, których projekty zostały zgłoszone w tym temacie powinny właśnie otrzymać prywatną wiadomość z kodami rabatowymi Wyjątkiem są jedynie te osoby, które poprosiły o wygenerowanie zsumowanych kodów na koniec akcji. Jeśli ktoś nie otrzymał kodu to jest to jedynie moje przeoczenie, proszę wtedy o wysłanie prywatnej wiadomości. Kody będę otrzymywał w tej chwili już znacznie szybciej, więc autorzy wszystkich nowych DIY otrzymają swoje rabaty na początku następnego tygodnia. PS Ukryłem wcześniejsze wiadomości dotyczące ręcznego przydzielania rabatów, aby nie wprowadzać nikogo w błąd.
  20. 1 punkt
    Jakiś wysiłek i pracę trzeba było włożyć w projekty, szkoda tylko, że większość z nich to duperele, bajery i zabawki.
  21. 1 punkt
    TDD sprawdza się tam, gdzie masz do napisania jakąś logikę aplikacji. Z przykładów mogę podać np. protokoły komunikacyjne. Pisałem ich już trochę i TDD jest świetne do sprawdzania przekłamania pól w ramkach, retransmisji, timeoutów, handshakeów i innych tego typu procedur, które ciężko jest dobrze napisać, a debugowanie jest problematyczne, bo czasem ciężko wywołać te błędy. Poza tym później jak się na przykład zmieni się długość i kolejność pól to bez unit testów nawet mała zmiana może oznaczać całe dni debugowania. Pisałem też w ten sposób różne sterowniki z logiką typu wyłącz awaryjnie, jeżeli przez określony czas sygnał jest powyżej progu. Poza tym obliczenia zawierające logikę, obsługa błędów, triggerowanie eventów. W tych wszystkich zastosowaniach TDD po prostu pomaga. Owszem, pracowałem też ze źle napisanymi testami i faktycznie jest to udręka. Jednak często wystarczą proste refactoringi typu podzielenie ogromnego testu, w którym nie wiadomo o co chodzi na wiele małych skupionych na jednym zadaniu. Wtedy jak taki test nie przechodzi, od razu nazwa daje wskazówkę co jest nie tak. Inna sprawa, że zwykle trudność w testowaniu pokazuje problemy z implementacją np. wielka funkcja robiąca wiele rzeczy na raz. Sformułowania takie jak: w stosunku do TDD są bardzo niesprawiedliwe. Zwykle jest właśnie w drugą stronę - duże projekty bez testów jednostkowych też czasem przez przypadek mogą działać poprawnie, ale jest to raczej wyjątek od reguły.
  22. 1 punkt
    Przeczytałem i tylko utwierdziłem się w tym co pisałem. Twoje przypadki idealnie pasują do tych wymienionych w linku np z pokryciem kodu w >80%- i co tam jest o czymś takim? Takie cytaty: "Or the problem may be at the other end: developers don’t have adequately refined design skills, or the process doesn't encourage architectural thinking and conscientious design. Maybe the requirements are so bad that developers wouldn’t know what to test if they had to, so they make their best guess." "If you have comprehensive unit tests but still have a high failure rate in system tests or low quality in the field, don’t automatically blame the tests (either unit tests orsystem tests). Carefully investigate your requirements and design regimen and its tie to integration tests and system tests." Ten mi się podoba: "Testing does not increase quality; programming and design do." - jeśli mamy "średni" kod i nagle wyjdzie pomysł "piszmy testy" to można założyć, że będą gorszej jakości niż ten kod sam w sobie, bo team dopiero się tego uczy itp - więc jak sobie to wymieszamy - to otrzymamy w wyniku coś gorszego i będzie narzekanie jak z cytatu wyżej "że to przez testy". Też podobne zdanie jest w podsumowaniu: "Testing can’t replace good development: a high test failure rate suggests you should shorten development intervals, perhaps radically, and make sure your architecture and design regimens have teeth"
  23. 1 punkt
  24. 1 punkt
    Mało wiadomo o całym napędzie w tym rowerze. Jeżeli to nie jest silnik typu hub (a wnioskuję, że nie jest) to musisz dodać przekładnię zmniejszającą obroty. Pomyśl jaką prędkość chcesz osiągnąć (np 20km/h), oblicz obwód Twojego koła i policz jakie przełożenie potrzebujesz między silnikiem a kołem do osiągnięcia takiej prędkości. Pomijasz tutaj sprawności, opory toczenia, moce itd.
  25. 1 punkt
  26. 1 punkt
    Wszystko opisane przystępnie tylko mam jedną uwagę - w akapicie 'Jak dobrać rezystor do diody' w artykule, przydała by się wskazówka przy obliczaniu prądu płynącego przez diodę. Początkujący mogą pomyśleć, że skoro obliczamy Id to korzystając z prawa Ohma dzielimy Ud przez opór, który znamy "Sprawdźmy obliczając prąd płynący przez diodę przy założeniu, że znamy napięcie zasilania, napięcie odkładające się na diodzie oraz dokładną wartość rezystora (korzystamy z przekształconego prawa Ohma):" Warto by w formie jakiejś wskazówki podać, że prąd diody to prąd płynący w całym obwodzie, a ten jest ograniczany w tym przypadku tylko rezystorem, więc do wzoru trzeba podstawić Ur - czyli spadek napięcia na rezystorze a nie na diodzie.
  27. 1 punkt
    Nazwa RoChN - Robot o Chwytliwej Nazwie obejmuje trzy wersje robota (V1 - V3), które zbudowaliśmy z kolegą paor na początku w ramach eksperymentu, a następnie już jako pełnoprawna szkolna drużyna robotyczna KRÓL. Jest to jedna z ostatnich tego typu (procesor, brak enkoderów) konstrukcji na dużych zawodach w Polsce. Pomimo tego osiąga całkiem przyzwoite wyniki, zdarzyło mu się też powalczyć o podium, którego jednak nigdy nie zdobył. Opiszę po kolei wszystkie wersje, ponieważ nie różnią się na tyle, aby można było je uznać za osobne konstrukcje. Elektronika: Zastosowaliśmy mikrokontroler ATmega324 taktowany 16MHz kwarcem, 12 czujników linii KTIR0711s podłączone do trzech poczwórnych komparatorów LM339 i mostek H - TB6612FNG. Do komunikacji wykorzystaliśmy HC-05. Sekcja zasilania od wersji trzeciej składa się z dwóch stabilizatorów na 5V - osobnych dla czujników i logiki. Silniki są zasilane bezpośrednio z akumulatora 2s. Z akumulatorem 150mAh waży około 70g. Mechanika: Zastosowane silniki to Pololu HP 10:1. Sprawdziły się dobrze, chociaż za względu na dość znaczny przebieg szczotki są mocno zużyte. Robot składa się z dwóch dwustronnych płytek drukowanych połączonych aluminiowymi listewkami i taśmą ffc. Z tyłu znajduje się dodatkowa podpórka wykonana z kawałka drutu, która zapobiega odwracaniu się robota przy starcie z dużą prędkością. Przednia płytka posiada ślizgacze wykonane z rezystorów THT - sprawują się lepiej, niż stosowane do tego przedtem LEDy. Oprogramowanie: Program do robota został napisany w języku C. Realizuje on regulator PD, z którym było sporo problemów ze względu na brak wiedzy teoretycznej oraz doświadczenia w strojeniu. Powstał też program na komputer ułatwiający komunikację z robotem poprzez bluetooth i umożliwiający zmiany w konfiguracji, ręczne sterowanie i trochę innych "bajerów". Krótki opis zmian w kolejnych wersjach: -V1 Pierwsze podejście do zbudowania linefollowera na zawody. Wykonana domowymi metodami płytka okazała się być bardzo wadliwa i ostatecznie robot ten nigdy nie ruszył z miejsca - przód nie został nawet wyczyszczony z tonera. Większość elementów z płytki głównej została później wylutowana. Wyciągnęliśmy z tej porażki wiele wniosków, w końcu człowiek najlepiej uczy się na błędach. -V2 W przeciwieństwie do poprzednika robot posiada płytkę drukowaną wykonaną na zamówienie. Problemy spowodowały części projektu, które nie zostały przetestowanie przy okazji wersji pierwszej - stabilizator napięcia przegrzewał się i trzeba było dodać mu radiator w postaci kawałka drutu. Już na zawodach okazało się, że robot jest za szeroki, w wyniku czego miewał problemy z ciasnymi zakrętami. Pojawiły się też kłopoty z modułem bluetooth - legendarnym HC-05, który po jakimś czasie odmówił współpracy i trzeba było go wymienić. W międzyczasie zmieniliśmy też kształt przedniej płytki, jak się później okazało z kiepskiego na jeszcze gorszy. Wyciągnęliśmy z tej konstrukcji dużo wniosków, które wpłynęły na wersję trzecią. Na zdjęciach widać, że część elementów została wylutowana do ponownego użycia. -V3 Prawdopodobnie ostatnia wersja z tej serii, praktycznie pozbawiona błędów projektowych. Węższa i lżejsza. Oddzieliliśmy zasilanie czujników linii od reszty, a do połączenie przedniej płytki z tylną zastosowaliśmy taśmę o rasterze 0.5 mm. Również ta konstrukcja miała kilka przodów w ramach eksperymentów z ułożeniem czujników. Przez jakiś czas używaliśmy opon odlewanych z silikonu, jednak okazały się mniej przyczepne niż mini-z - może to kwestia braku doświadczenia w doborze proporcji. Podczas początkowych testów udało nam się dwa razy spalić mikrokontroler i zepsuć rezonator kwarcowy, który niezbyt umiejętnie wymieniłem - wydać to na zdjęciach. Osiągnięcia: 6. miejsce Robotic Arena 2019 4. miejsce Robomaicon 2019 Zdjęcia i filmy z zawodów: Wersja 2 na starcie lf drag na BBR 2018
  28. 1 punkt
  29. 1 punkt
  30. 1 punkt
  31. 1 punkt
  32. 1 punkt
  33. 1 punkt
    Ankieta w artykule była ważna do niedzieli. Swoje głosy oddały łącznie 62 osoby, wszystkim głosującym dziękuję za wskazanie swoich faworytów. Za najlepszą konstrukcję tego zestawienia uznaliście Cukiereczka, czyli robota typu linefollower. Gratulacje dla autora, który zgodnie z wcześniejszym ogłoszeniem wygrywa zestaw gadżetów Forbota. @mice.co, czekam na kontakt w wiadomości prywatnej - podaj adres do wysyłki
  34. 1 punkt
  35. 1 punkt
  36. 1 punkt
  37. 1 punkt
  38. 1 punkt
  39. 1 punkt
  40. 1 punkt
  41. 1 punkt
  42. 1 punkt
  43. 1 punkt
  44. 1 punkt
  45. 1 punkt
    Witam serdecznie To mój pierwszy wpis na tym forum. Na wstępie chciałbym podziękować za kurs arduino. Mając 32 lata i będąc humanistą zainteresowałem się tą małą, ale jakże ciekawą płytką. Wasz kurs bardzo pomaga w zrozumieniu o co chodzi w tym "tajemnym programowaniu". Jestem na początku drogi i pewnie jeszcze długo będę się czuł jak dziecko we mgle, ale postanowiłem podzielić się rozwiązaniem zadania nr 2.4. Program zdaje się działać prawidłowo, ale wolałbym by ktoś mądrzejszy to ocenił. #define zielona 8 #define czerwona 9 String odebraneDane = ""; // pusty ciag odebranych danych void setup () { Serial.begin(9600); // inicjalizacja połaczenia z pc pinMode(zielona, OUTPUT); // konfiguracja wyjsc pinMode(czerwona, OUTPUT); digitalWrite(zielona, LOW); // wyłaczamy diody na starcie digitalWrite(czerwona, LOW); } void loop () { if(Serial.available() > 0) { //czy arduino odebrało dane //jesli tak, to odczytaj je do znaku konca linii i zapisz w zmiennej odebraneDane odebraneDane = Serial.readStringUntil('\n'); if (odebraneDane == "zielona"){ // jesli odebrano słowo "zielona" digitalWrite(zielona, HIGH); //to włączamy diode zielona delay(1000); digitalWrite(zielona, LOW); } if (odebraneDane == "czerwona") { digitalWrite(czerwona, HIGH); // to włącz diodę czerwoną delay(1000); digitalWrite(czerwona, LOW); } if (odebraneDane !="czerwona" and odebraneDane!="zielona") { Serial.println("Podales zly kolor!"); } }}
  46. 1 punkt
    W końcu zabrałem się za kurs i tydzień temu w sobotę odebrałem paczkę z elementami. Dzisiaj można powiedzieć, go że ukończyłem . Wykonałem wszystkie zadania i trochę eksperymentowałem. Bardzo dziękuje za stworzenie kursu, wszystko bardzo fajnie opisane i pokazane. Wkrótce zabieram się za część drugą. Dziękuje raz jeszcze za włożoną pracę w napisanie ciekawych artykułów i przygotowania tego wszystkiego. Dodam jeszcze, pewnie przez niektórym znaną, stronę na której można zobaczyć działanie układów, które robimy. Lepiej zrozumiałem dzięki niej ostatni układ i polecam jej przejrzenie, choć oczywiście nie zastąpi ona samego składania układów . W linku zrobiony przerzutnik bistabilny z ostatniego artykułu na stronie o której pisałem:Link
  47. 1 punkt
  48. 1 punkt
    Dziękuję serdecznie za ten kurs! Dla takich początkujących jak ja jest idealny! A jako sumienny uczeń również pozwolę sobie pokazać swoją "pracę domową" Najwięcej czasu zajęło mi dobieranie rezystora dla czerwonej diody, by ją całkiem wygasić. Ostatecznie wpadłem na pomysł, by na chwilę podłączyć potencjometr, ustawić odpowiednią do wygaszenia wartość, następnie zmierzyć opór potencjometru i wstawić właściwy opornik - w moim przypadku 390 Ohm. Na zdjęciach nie bardzo widać, że te diody na prawdę świecą, więc dla porządności jeszcze "filmik": Serdecznie pozdrawiam i biorę się za następne zadania!
  49. 1 punkt
    Kozacki kurs, naprawdę dawno nie widziałem w sieci tak pożytecznego materiału... Ja wiem, że trochę wazelina, ale co tam Trzymajcie tak dalej...
  50. -1 punktów
    @ganderZauważ, że to co robiłeś to już nie są testy jednostkowe, tylko testowanie logiki biznesowej - a to faktycznie należy testować. Przeczytaj ze zrozumieniem materiały, które sam podlinkowałeś na blogu, tam jest to wszystko ładnie opisane Edit: proponuję zakończyć tą dyskusję prostym podsumowaniem - niech każdy pracuje tak jak uważa że daje to dobre efekty. Nie ma sensu się spinać i kłócić o to która ideologia jest jedynie słuszna. Ja napisałem na początku, nie jestem fanem tdd, ale jak firma dobrze płaci to czasem tego używam... więc takie złe tdd nie jest
Tablica liderów jest ustawiona na Warszawa/GMT+01:00
×
×
  • Utwórz nowe...