Skocz do zawartości

Tablica liderów


Popularna zawartość

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

  1. 8 punktów
    Od momentu poznania ESP8266 bardzo spodobał mi się ten układ. Gdy skończyłem robić pierwszy projekt oparty na tym układzie od razu zacząłem wymyślać kolejny. Dzisiaj chciałbym Wam przedstawić sterownik oświetlenia. Współpracuje on ze zwykłym włącznikiem świecznikowym i mieści się w puszce fi60, dzięki czemu (nad każdym włącznikiem światła mam puszkę fi70) w puszcze fi70 zostaje jeszcze sporo miejsca na kable. Po zaprojektowaniu płytki w programie Eagle zleciłem wyprodukowanie jej firmie jlcpcb. Wszystko trwało tydzień (zamawiałem również inne płytki dlatego tyle to trwało ). Płytki wysłali w piątek po południu czasu lokalnego a w poniedziałek płaciłem już vat u kuriera z DHL . Płytki wyglądają bardzo dobrze (sami możecie ocenić jakość produktu ) Po odebraniu płytek zacząłem wszystko składać w całość. ESP8266 12F zostało wykorzystane jako "mózg" płytki. Jako zasilacz służy Hi-Link HLK-PM01 230V na 5V. Za załączenie napięcia odpowiedzialne są dwa przekaźniki z cewką na 5V. Dodatkowo do każdego przekaźnika dołożyłem diodę prostowniczą. ESP jest zasilane napięciem 3.3v przez co musiałem zastosować LDO. Dodatkowo na wejściu fazy do układu zamontowałem bezpiecznik firmy bel fuse. Żeby esp mogło załączać przekaźnik musiałem wykorzystać tranzystor bc817 w wersji smd. Do tego potrzebowałem jedno złącze ark raster 5mm podwójne, oraz dwa złącza ark raster 5mm potrójne. Całość po zlutowaniu i umieszczeniu w puszcze fi60 wygląda następująco: Teraz przyszła kolej na oprogramowanie. Zdecydowałem się zrobić prostą stronę konfiguracyjną na której możemy: zmienić hasło do urządzenia zmienić dane serwera mqtt (sterowanie z każdego miejsca na świecie ) zmienić przyłączenie do sieci wi-fi zobaczyć jak długo pracuje nasz układ wybrać ilość podpiętych włączników (jedno albo dwa) Całość jest również sterowana z telefonu z systemem android. Teraz przymierzam się do zrobienia wersji v2 tego sterownika, chcę by był oparty na triakach i optotriakach (z tego co wyliczyłem to żarówka led o mocy 15W pobiera tylko 60mA a świeci jak zwykła żarówka 120W) oraz będzie posiadała wsparcie dla dotykowych podświetlanych włączników (moduły httm oraz panele marki weilak, wszystko mam tylko projekt został ) Jestem bardzo ciekaw Waszych opinii, dajcie znać w komentarzach co myślicie mo jej konstrukcji
  2. 7 punktów
    Cześć. Chciałbym przedstawić wam mój projekt robota samobalansującego. Jest to mój najbardziej zaawansowany jak dotąd projekt, który pochłonął najwięcej pracy. Pomysł na zbudowanie takiego robota zrodził się w mojej głowie w wakacje po obejrzeniu filmiku przedstawiającego podobną konstrukcję. Pracę nad nim rozpocząłem jeszcze w wakacje, a z przerwami zakończyłem w lutym. Działanie robota jest podobne do dostępnych na rynku Hoverboardów, czyli robot ma za zadanie poruszać się w taki sposób, aby utrzymać się w pionie, oczywiście bez podpierania. Konstrukcję robota zaprojektowałem sam i wykonałem z pręta gwintowanego i plexi. Uznałem że taka konstrukcja zapewni robotowi wymaganą sztywność i niską masę, jednocześnie nie rujnując budżetu. Najpierw wykonałem jej model w Fusion 360, a później przystąpiłem do pracy. Roboty z tym trochę było, bo obróbka plexi do łatwych nie należy. Sporo czasu zajęło przycięcie prostokątów, a jeszcze więcej wywiercenie otworów, które musiały być idealnie rozmieszczone, aby później dało się przełożyć przez nie pręt gwintowany. Po zbudowaniu ramy przyszła pora na elektronikę. Ponieważ robot nie zapewnia dużo miejsca, a jednocześnie środek ciężkości powinien być możliwie wysoko, dla ułatwienia balansu, musiałem się postarać ścisnąć wszystko jak to tylko możliwe. Baterię zasilającą robota (ogniwe Li-Po odzyskane z powerbanka o pojemności 3000 mAh) umieściłem na najwyższej półce. Tam również trafiła przetwornica step-up podnosząca napięcie do 7,4 V. Wiem że lepiej byłoby dać dwie baterie połączone szeregowo, ale w momencie budowania budżet na to nie pozwolił. Szybko okazało się że jedna przetwornica to za mało - Arduino restartowało się przy każdym uruchomieniu silnika, nawet jeśli do układu przyłączyłem bardzo duży kondensator. Dodałem więc drugą - teraz silniki były zasilanie niezależnie od elektroniki sterującej. Pozwoliło to stanąć robotowi po raz pierwszy, jednak wciąż jedna przetwornica zasilająca silniki ograniczała ich moc. Dodałem drugą, co nieco poprawiło sytuację, jednak wciąż nieco ogranicza silniki. Póki co szukam lepszego rozwiązania. Schodząc na niższą półkę. Tam trafiła płytka ze sterownikiem i druga z mostkiem H. Pierwszą płytkę lutowałem sam na płytce uniwersalnej - zajęło to kilka godzin i mnóstwo cyny, ale satysfakcja była nie do opisania, zwłaszcza że wszystkie połączenia wykonałem cyną. Po spędzeniu kolejnej godziny na pozbywaniu się zwarć układ był gotowy do testów Robot aby ustalić swoją pozycję korzysta z modułu żyroskopu i akcelerometru MPU6050 oraz wbudowanych w silniki enkoderów. Dane z tych czujników trafiają do Arduino Nano które poprzez układ L298N steruje dwoma silnikami. Dzięki akcelerometrowi i żyroskopowi robot zna swój kąt przechylenia. W pierwszych wersjach kodu szybko okazało się, że to nie wystarczająco, ponieważ o ile robot stał, to cały czas przesuwał się w jedną stronę. Wynika to z tego że konstrukcja nie jest idealnie wyważona, a robot nie zna swojej pozycji, jedynie kąt nachylenia, więc jeżeli ustawiony na sztywno kąt odbiegał od kąta balansu, robot "dryfował". Aby temu zapobiec dodałem drugie sprzężenie zwrotne, tym razem oparte o enkodery przy silnikach. Enkodery zliczają ilość impulsów które silniki wykonały w każdą ze stron, a oprogramowanie dąży, aby ich różnica była równa 0. Pierwsze próby nie były zbyt udane. Kiedy doprowadziłem kod do stanu w którym robot chociaż próbował się utrzymać, udawało mu się to przez maksymalnie kilkanaście sekund. Jednak wraz z poprawianiem kodu robot stał dłużej i dłużej. Obecnie już się nie wywala, jednak mostek H po dłuższym staniu się przegrzewa, więc czas pracy ograniczony jest do kilku minut. Mimo to robot robi duże wrażenie, chociaż z pewnością nie jest idealny. Zastosowałem tanie chińskie silniki, i jak się okazało, jeden obraca się szybciej niż drugi, więc robot obraca się w jedną stronę. Do tego jak wspomniałem przegrzewa się, a silnikom brakuje momentu, więc robot się trzęsie zamiast stać idealnie prosto. Są to jednak problemy które mam w planach poprawić. Planuję dodać również możliwość sterowania po BT (już nawet na płytce jest miejsce na moduł HC-06), ale na razie nie miałem czasu. Oto filmik prezentujący działanie robota:
  3. 7 punktów
    Witajcie. Chciałbym Wam przedstawić prosty sposób wykorzystania modułu ESP-32, który użyłem do stworzenia urządzenia, za pomocą którego możecie śledzić poziom zainteresowania wybranym repozytorium GitHub. Dzięki wbudowanym dwóm wyświetlaczom, będziecie na bieżąco informowani o: aktualnej liczbie gwiazdek dziennej liczbie gwiazdek aktualnej liczbie obserwujących aktualnej liczbie forków Początkowo chciałem skorzystać ze starszego modułu ESP8266 12-F, jednak napotkałem problem który objawiał się przy wykonywaniu requesta do api GitHub. Podczas oczekiwania na odpowiedź z serwera, na wyświetlaczach zanikały wszystkie cyfry i wyglądało to jakby coś było nie tak z urządzeniem. Z pomocą przyszedł układ ESP-32, który oparty jest na dwóch rdzeniach. Była to świetna okazja aby zapoznać się z tym modułem, ponieważ wcześniejsze projekty wykonywałem na ESP8266. Użycie nowszej odsłony ESP, pozwoliło mi wysyłać requesty asynchronicznie. Do działania ramki wymagane jest połączenie z siecią poprzez WiFi. Tutaj świetnie sprawdziła się biblioteka "WiFi Manager", która umożliwiła mi szybkie podłączenie ramki do dowolnej sieci. Jeżeli chodzi o zasilanie to jest to napięcie 5V, które podaje poprzez wtyki USB. W obudowie ramki znajdują się trzy przyciski. Pierwszy służy jako włącznik. Pozostałe dwa to włączniki chwilowe. Po wciśnięciu pierwszego na wyświetlaczu prezentowany jest adres IP, który wykorzystujemy przy konfiguracji. Natomiast drugi przycisk resetuje liczbę gwiazdek z dnia. Do układu podłączona jest 3 kolorowa dioda LED, która informuje nas o stanie połączenia: CZERWONY – brak sieci, błąd podczas pobierania danych ZIELONY – połączenie sieciowe ustanowione, dane pobrane poprawnie NIEBIESKI – tryb access pointu ( zanik sieci ) Domyślnie odświeżanie danych odbywa się co 90 sekund. Oczywiście interwał można zmienić. Ale należy uważać, aby nie wykonywać do api GitHub więcej niż 60 requestów na godzinę, ponieważ serwer ma ustawiony RateLimit. Po przekroczeniu ilości zapytań zostaniemy zablokowani na godzinę. Jak już wspomniałem wyżej, pod adresem IP jaki przydzielony został do urządzenia działa prosty web server, który serwuje nam stronę z konfiguracją, gdzie musimy wprowadzić nazwę użytkownika repozytorium oraz nazwę repozytorium które chcemy obserwować. Po zapisaniu konfiguracji w pamięci EEPROM urządzenie jest restartowane i gotowe do użycia. Dodatkowym atutem urządzenia jest automatyczna aktualizacja oprogramowania poprzez HTTPS OTA. Sprawdzanie wersji następuje podczas uruchomienia oraz po północy. Urządzenie jest w pełni bezobsługowe. Gdy wystąpi zanik sieci, ESP cały czas będzie próbowało nawiązać połączenie za pośrednictwem zapamiętanych poświadczeń. Jeśli sieć nie będzie dostępna, przełączy się w tryb access pointu ( ssid: "GITHUB-FRAME"). Jeśli nie zostanie wybrana nowa sieć w menadżerze sieci, to po czasie 3 minut, nastąpi restart i proces się powtórzy. Tak pokrótce, wygląda zasada działania całego układu. Poniżej przedstawię Wam główne etapy budowy całej ramki. A więc zaczynamy. LISTA ELEMENTÓW: ESP-32 WROOM DevKit 1.0 – 1 szt. Wyświetlacz LED 4-Cyfrowy TM1637 – 0.56" – 1 szt. Wyświetlacz LED 4-Cyfrowy TM1637 - 0.36" – 1 szt. 4-pinowy przewód, żeński – żeński – raster 2.54 – 4 szt. Gniazdo + wtyk, JST – JST – 2 szt. Gniazdo + wtyk, mikro JST – mikro JST – 2 szt. Płytka uniwersalna PCB 50x70mm PI-01 – 1 szt. Rezystor węglowy – 220 ohm – 5 szt. Rezystor węglowy – 2,2k ohm – 3 szt. Zworki do płytek stykowych - 1 zestaw Wtyk goldpin kątowy 4 pinowy, raster 2,54mm – 4 szt. Dioda LED 5mm RGB wsp. Anoda – 1 szt. Dioda LED 3mm biała – 3 szt. Przełącznik chwilowy okrągły – 10mm – 2 szt. Przełącznik kołyskowy ON-OFF – 1 szt. Kabel USB A – USB micro – 1 szt. Zasilacz 5V z gniazdem USB A – 1 szt. Rurki termokurczliwe - 1 szt. Ramka IKEA RIBBA – 21x30cm ( ważne żeby była dość głęboka, aby zmieścić elektronkę ) – 1 szt. Papier samoprzylepny do drukarki – 1 szt. Rura elektroinstalacyjna RLM 16 – 1 szt. NARZĘDZIA: Lutownica Cyna Obcążki Wiertarka lub wkrętarka Wiertła: 7, 10, 13 Pistolet do kleju na gorąco Nóż Drukarka ZAŁOŻENIA: Stabilność działania Intuicyjna obsługa Szybka adaptacja w miejscu instalacji Estetyka Plan Początkowo ramka miała powstać pod konkretnie wybrane repozytorium i wyświetlać tylko liczbę gwiazdek. Ale stwierdziłem, że i tak pobieram inne dane z endpointa api to czemu miałbym ich nie wyświetlić. Postanowiłem, że dodam dwa nowe klucze: "forks" oraz "watchers" i wyświetlać je kolejno w 5 sekundowym odstępie czasowym. Jeżeli chodzi o repozytorium, to dając możliwość wprowadzenia własnych ustawień url-a, zwiększyłem tym samym skalowalność przedsięwzięcia. Do tego doszły automatycznie aktualizacje software-u. Więc taką ramkę może stworzyć każda osoba, która chociaż trochę ma pojęcie o informatyce i niekoniecznie zna się na programowaniu. BUDOWA Prace nad ramką rozpocząłem od budowy prototypu metodą na "pająka". W tym celu skorzystałem z płytki prototypowej, przycisków typu "tact switch", paru zworek oraz kilkunastu przewodów do połączenia wszystkiego w całość. Całe oprogramowanie zostało napisane za pośrednictwem Arduino IDE czyli w języku C. Gdy miałem już działający prototyp, rozpocząłem prace nad przeniesieniem całości na uniwersalną płytkę PCB. Zadanie wydawałoby się proste ale wymagało procesu planowania. W tym celu wykorzystałem oprogramowanie Fritzing. Oprogramowanie to umożliwia stworzenie całej dokumentacji projektu. Na tę chwilę wykorzystałem tylko narzędzie do stworzenia szkicu płytki prototypowej. Mając gotowy już projekt z rozlokowaniem wszystkich elementów i połączeń. Mogłem przystąpić do lutowania. Jak widać na zdjęciach, podczas montażu elementów używałem uchwytu, który stabilnie trzyma płytkę w miejscu. Bardzo ułatwił mi pracę. Po przylutowaniu wszystkich elementów elektronicznych, wlutowałem przewody z gniazdami, dzięki którym będę mógł odłączyć układ od samej konstrukcji ramki Teraz przyszedł czas na najtrudniejszy etap jakim było dostosowanie drewnianej ramki do potrzeb projektu. W programie Photoshop stworzyłem szablon do wiercenia i wycinania potrzebnych otworów. Szablony te znajdziecie również w repozytorium projektu. Po wydrukowaniu szablonu przykleiłem kartkę do “pleców ramki” i wyciąłem wszystkie otwory. Trochę trzeba się do tego przyłożyć i mieć sporo cierpliwości. Cięcie, pasowanie, cięcie, pasowanie aż do skutku. Ufff. W końcu mogłem przystąpić do zamontowania wyświetlaczy oraz diod LED. Z pomocą przyszedł mi klej na gorąco. Trzyma mocno i pewnie, wystarczająco do tego typu prac. Trzy diody LED umieściłem w przyciętych krążkach z białej rury pcv ( tych do prowadzenia przewodów po ścianach ) a górę zaślepiłem kawałkiem plastiku w którym zamocowałem diody. A tak całość prezentuje się od frontu Za pomocą 4 żyłowych przewodów zakończonych wtykami żeńskimi, połączyłem wszystkie elementy z główną płytką. W celu szybszej identyfikacji przewodów, oznaczyłem każde połączenie za pomocą lakierów do paznokci ( pozdrawiam swoją żonę Magdalenę ). Główny układ przykleiłem do pleców ramki również za pomocą kleju na gorąco. Na koniec pomalowałem cały front na biało farbą emulsyjną, ponieważ papier który używa się w drukarkach ma małą gramaturę co sprawia, że jest półprzezroczysty. Dzięki podbiciu koloru tła biel będzie intensywniejsza. W ostatecznej wersji grafikę wydrukowałem na papierze fotograficznym, który jest na tyle gruby, że malowanie okazało się być zbędne. SOFTWARE Cały program opiera się na dwóch pętlach. Pierwsza pętla Task1, sprawdza czy użytkownik wprowadził url repozytorium z którego mają zostać pobrane dane. Jeżeli konfiguracja została wprowadzona, program wywołuje funkcję getData(), która odpowiedzialna jest za pobranie danych z API. Interwał tej pętli definiuje zmienna requestInterval, która domyślnie posiada wartość 90 ( czyli 90 sekund). Druga pętla Task2, służy do wyświetlania odpowiednich danych na wyświetlaczach oraz podświetlania ikon. Tutaj również sprawdzany jest stan na pinach 27 i 15 ( przyciski BUTTON_IP oraz BUTTON_RESET_TODAY). Interwał tej pętli to około 15 sekund. Po północy następuje sprawdzenie dostępności nowszej wersji oprogramowania oraz resetowany jest licznik gwiazdek otrzymanych w ciągu całego dnia. Poniżej znajdziecie link do repozytorium z projektem: OPROGRAMOWANIE + SZABLONY DO DRUKU PODSUMOWANIE Przyznam się szczerze, że prototyp urządzenia miałem już gotowy rok temu. Ale ze względu na gruntowny remont mieszkania musiałem odsunąć hobby na dalszy plan. Rozciągnięcie projektu w czasie sprawiło, że przy każdym powrocie zawsze coś zmieniałem, rozbudowywałem. Wszystko wtedy można przemyśleć kilka razy i na spokojnie zastanowić się nad rozwiązaniem jakiegoś problemu. Na co dzień zajmuję się programowaniem front-endu, ale dzięki takim projektom mogę połączyć moje główne zainteresowania: majsterkowanie, elektronikę, grafikę i jak już wcześniej wspomniałem, programowanie i stworzyć coś namacalnego i cieszącego oko. Zachęcam wszystkich do twórczego działania i poszerzania swojej wiedzy. Tego typu projekty dadzą Wam satysfakcję, świetną zabawę oraz sporo nauczą. Także klawiatury, lutownice, piły, śrubokręty, wiertarki w dłoń i do działania! Instrukcję już macie Do następnego projektu! Pozdrawiam.
  4. 6 punktów
    Artykuł przeznaczony do wszystkich zapaleńców druku 3D. Można nie kupować dość drogi filament do swojej drukarki 3D, a produkować w domu własny filament z zużytych butelek PET od napojów. Przy tym nieważne, jeżeli butelka jest pognieciona, ona również się nadaje do domowej produkcji filamentu. Filament z butelek ma sporo zalet w porównaniu z firmowym filamentem kupowanym – ABS albo PLA. Przede wszystkim, że produkowany filament nic nie kosztuje, jest po prostu darmowy Produkowany pręt filamentu Jest bardzo sztywny i absolutnie nie łamliwy, wytrzymuje sporo ostrych przegięć. Filament własnej produkcji jest sporo mocniejszy i twardszy, jak na rozciąganie tak i o wiele bardziej odporny na uderzenie. Absolutnie nie pochłania wody, czyli nie trzeba go ani suszyć, ani chronić w zamkniętym zabezpieczonym od nawilżania się opakowaniu. Praktycznie nie skurcze się przy ochłodzeniu w trakcie druku. Nie wymaga chłodzenia drukowanej warstwy. Nie wymaga stołu podgrzewanego. Dla przyczepności wystarczy miejsce na stole posmarować cienką warstwą kleju w sztyfcie na przykład typu „Glue Stick” Wydrukowane detal można obklejać od razu po skończeniu wydruku. Taki filament jest bardzo odporny na działanie rozpuszczalników i środków chemicznych. Jak widać filament produkcji własnej ma sporo zalet w porównaniu z filamentami kupowanymi, a najważniejsze – że jest darmowy. Niżej przedstawiono zdjęcia maszynki do produkcji filamentu: Do domowej produkcji filamentu wykorzystywane zużyte butelki od napojów. Ale butelki muszą być czyste, resztki kleju do nalepki powinni być usuwane. Technologia produkcji jest bardzo prosta i składa się z trzech następujących operacji: Poprawa zgniecionych butelek i butelek z ryflowaną powierzchnią tak, żeby ścianka boczna butelki była gładka. Nacinanie butelek na paski o określonej szerokości, od 5mm do 12mm w zależności od grubości ścianki butelki. Produkcja pręta filamentu z nacinanych pasków na specjalnej maszynce z nawijaniem na bębenek odbiorczy. Na tych wideo można obejrzeć prace maszynki i przyrządu do nacinania pasków z butelek: Zębatka drukowanie:
  5. 6 punktów
    Już słyszę głosy: O, staremu ethanakowi coś się chyba pokręciło... Post jest o jakimś Kedrigernie w dziale DIY - a na zdjęciu mamy coś przypominającego robota z dumnym napisem "Ciapek"... Spieszę z wyjaśnieniami. To nie pomyłka. Post jest na temat serwera mowy Kedrigern, a Ciapek to żaden robot. Po prostu dość trudno zrobić zdjęcie programu, poza tym wypadałoby raczej pokazać ów program w działaniu - a ten wymaga jednak czegoś co będzie gadać (czyli jakiejś bardziej fikuśnej obudowy na głośnik). A ponieważ ostatnio zapatrzyłem się w rysunki Daniela Mroza... cóż, Ciapek z ludzkimi dłońmi, stopami i uszkami wyszedł tak jak wyszedł Zacznę możę od opisu elektroniki (jako że jest to najprostsze, a użytkownik może sobie ją skomponować z zupełnie innych elementów). Sercem całego układu jest Raspberry Pi. Można zastosować dowolny model (chociaż ze starymi, krótkimi GPIO mogą być lekkie problemy), ja użyłem w swoim egzemplarzu Raspberry Pi Zero W. Oprócz tego potzebny jest jakikolwiek układ odtwarzania dźwięku. "Duże" (pełnpowymiarowe) malinki jak popularny 3B+ mają już wyprowadzone wyjście audio, potrzebny jest tylko jakiś niewielki wzmacniacz. Dla wersji Zero potrzebny jest jednak układ zewnętrzny. Prawdopodobnie doskonale spisałby się opisywany ostatnio moduł z wyjściem audio do Raspberry Pi Zero, ja zastosowałem jednak moduł i2s. Jest on dość wygodny w użyciu jako że zawiera w sobie wzmacniacz mono o całkiem sporej (do 3 W) mocy, poza tym początkujący elektronicy nie muszą się martwić o jakieś dziwne masy audio, filtrowane zasilania i tym podobne dziwactwa interesujące tylko "analogowców" - moduł podłącza się pięcioma przewodami do malinki, z drugiej strony dwoma do głośnika i już gra Ponieważ nasz "robocik" musi potrafić poruszać ustami, zastosowałem najprostsze (i najprawdopodobniej najtańsze) rozwiązanie - czyli matrycę LED 8x8 ze sterownikiem, na której rysowane będą kształty ust. Od razu uprzedzę pytanie: owszem, próbowałem zrobić bardziej skomplikowany mechanizm używający serw. Niestety - oprócz trudności mechanicznych (te są do przezwyciężenia) natrafiłem na rzecz, której nie da się przeskoczyć: prędkość serwa. Typowe serwo potrzebuje 0.1 sekundy na przekręcenie orczyka o 60° - a nawet zakładając, że owe 60° wystarczy (w co osobiście wątpię), jest to co najmniej dwa razy za wolno (przy czym owe "dwa" mogłoby się w rzeczywistych układach rozrosnąć do trzech czy czterech). Będę jeszcze próbować rozwiązania z solenoidami - jeśli mi się uda to opublikuję wyniki. Ale może w międzyczasie ktoś inny napisze moduł "solenoid"? Zresztą - chciałem, aby każdy mógł sobie w domu wypróbować Kedrigerna ponosząc jak najmniejsze koszty, a opisywany układ można (mając RPi z wyjściem audio) zmontować kosztem klikunastu złotych (matryca) bez żadnych płytek - po prostu łącząc matrycę przewodami z GPIO malinki. Jako głośnika użyłem leżącego gdzieś w szufladzie zakurzonego głośniczka od starego telefonu z sekretarką, pasować jednak będzie dowolny pod warunkiem dopasowania mocy głośnika do posiadanego wzmacniacza. I to cała wielce skomplikowana elektronika. Jak widać na zdjęciu - nie ma tam nic skomplikowanego. Przejdę więc do opisu programu. Kilka lat temu udało mi się zmusić Mbrolę do w miarę prawidłowego gadania po polsku (do tego stopnia, że można ją było wykorzystać np. do tworzenia audiobooków). System TTS Milena (tak się nazywa ten "zmuszacz" do Mbroli - czyli bardziej fachowo NLP) bardzo dobrze sprawdził się na pecetowym Linuksie, wersja na Windows była raczej ciekawostką ale również działała - postanowiłem więc przystosować ją do malinki. Po przezwyciężeniu pewnych trudności z kompilacją (np. "char" dla architerktury Intel to w GCC domyślnie signed, w ARM z jakichś przyczyn unsigned) okazało się, że co prawda Milena działa, ale "rozruch" ma straszliwie powolny. Nic dziwnego - pliki tekstowe słowników wymowy i translacji fonetycznej muszą być kompilowane przy załadowaniu programu, a malinka ze swoją wolniutką kartą pamięci i nieszczególnie silnym procesorkiem potrzebuje zbyt dużo czasu, zanim wydobędzie z siebie jakieś zdanie. Postanowiłem więc zrobić inaczej: serwer wczytuje wszystkie pliki raz przy starcie systemu, a prosty program klienta przekazuje mu tylko treść komunikatów. Takie rozwiązanie ma również inne zalety: uruchomiony na sockecie TCP serwer może być na zupełnie innej fizycznej maszynie niż klient. I w ten sposób powstał program Kedrigern (nazwany na cześć pewnego czarodzieja, który postanowił odczarować księżniczkę z zaklęcia odbierającego głos). Jak mi to wyszło - oceńcie sami. Oto filmik ukazujący Kedrigerna w działaniu: Nie będę tu rozpisywał się o wszystkich zasadach działania i możliwościach Kedrigerna i Mileny (to w końcu ma byc post na forum a nie książka z dokumentacją), zacznę więc od instalacji Kedrigerna na malince. Wszystkie konieczne komponenty (z wyjątkiem głosu pl1) są w załączonym pliku tgz. Rozpakujmy go w dowolnym katalogu (np. w głównym katalogu użytkownika malinki) i instalujemy mbrolę wraz z polskim głosem: sudo dpkg -i mbrola3.0.1h_armhf.deb sudo apt install mbrola-pl1 Teraz możemy zainstalować Milenę. I tu uwaga: jeśli ktoś miał starszą wersję Mileny niż 0.2.92 musi ją przeinstalować na tę właśnie wersję - inaczej nie będzie działać moduł ruchu ust Kedrigerna! sudo dpkg -i milena*.deb Po zainstalowaniu wszystkiego powinno działać już polecenie milena_say, czyli musimy wypróbować: milena_say dzień dobry kolego I znów uwaga: jeśli wyjściem audio jest HDMI, polecenie może nie działać prawidłowo! Należy spróbować dodać parametr -d opóżniający generację mowy do czasu "załapania" HDMI, czyli najprościej: milena_say -d 2000 dzień dobry kolego Niestety, przy użyciu wyjścia HDMI mogą pojawić się problemy z późniejszym działaniem Kedrigerna, ale po pierwsze nie jest to miejsce na omawianie problemów z audio, po drugie wcale nie czuję się mistrzem w tym zakresie i prawdopodobnie ktoś tu wie lepiej ode mnie jak tym problemom zaradzić. W każdym razie mając uruchomiona Milenę i Mbrolę możemy przystąpić do instalacji Kedrigerna. Zaczynamy od instalacji serwera, czyli sudo dpkg -i kedrigern_0.2.0-1_armhf.deb Jeśli mamy podłąćzoną matrycę LED (8x8, MAX7219) możemy użyć jej jako wyświetlacz ust: sudo dpkg -i kedrigern-matrix_0.2.0-1_armhf.deb No i oczywiście coś co pozwoli nam korzystać z serwera, czyli: sudo dpkg -i libkedrigern_0.1.2-1_armhf.deb Teraz możemy sprawdzić, co potrafi nasz serwer: kedrigern -h lub (jeśli mamy zainstalowany moduł matrix) kedrigern -M matrix -h W odpowiedzi dostaniemy wykaz opcji, z którymi możemy uruchomić serwer. Aby je przetestować, należy otworzyć drugi terminal; w pierwszym uruchamiamy serwer poleceniem "kedrigern" z różnymi opcjami, w drugim testujemy poleceniem kdr-say. Po ustaleniu opcji należy zedytować plik /etc/default/kedrigern i w nim ustawić domyślne parametry. Po przetestowaniu poleceniem kedrigern -C /etc/default/kedrigern możemy już uruchomić nasz serwer w tle: sudo systemctl start kedrigern Jeśli chcemy, aby serwer startował od razu przy starcie systemu, należy wydać polecenie: sudo systemctl enable kedrigern Do komunikacji z serwerem służą polecenia kdr-say, kdr-stop i kdr-speaking. Moduł matrix pozwala na wyświetlanie ust zsynchronizowane z głosem syntezatora. Oto przykładowe obrazy ust dla różnych fonemów: Fonem A Fonem I Fonem O Fonem U Fonemy M, P i B Wybrałem do pokazania kilka najbardziej charakterystycznych kształtów. Jeśli komuś nie odpowiadają stworzone przeze mnie kształty może w prosty sposób dorobić własne lub poprawić moje na bazie pliku /usr/share/kedrigern/demo.shape i podłączyć go do Kedrigerna, np. za pomocą opcji "-m matrix:shape" lub wprowadzając odpowiednie zmiany w pliku konfiguracyjnym. Protokół komunikacyjny jest bardzo prosty. Nie wnikając w szczegóły - załączony moduł w Pythonie (działa w wersji 2 i 3 Pythona) pozwala na sterowanie serwerem, a jednocześnie stanowi przykład sposobu komunikacji. I to wszystko... A nie, nie wszystko. Bo zaraz ktoś powie że to tylko zabawka, że komu potrzebne gadające roboty... Przede wszystkim: Kedrigern może generować komunikaty diagnostyczne w czasie testowania/programowania robota. Jakie to ma znacze nie nie muszę chyba mówić nikomu, kto choć raz ustawiał np. regulatory silników czy zakres ruchu serw w warunkach polowych. Poza robotyką może być bardzo dobrym rozwiązaniem do urządzeń typu headless - ja np. stosuję podobne (poprzednika Kedrigerna) rozwiązanie do obsługi sterownika pieca CO (podanie np. godzin nieobecności w mieszkaniu) czy jako wygodnego interfejsu do wpisywania wyników pomiaru ciśnienia krwi i poziomu cukru z małej przenośnej klawiaturki. A to już nie są zabawki A w ogóle przypominam, że Roomba też gada (tyle że Ciapek ładniej) Zdaję sobie sprawę z tego, że opis jest bardzo pobieżny. Z chęcią odpowiem na wszystkie pytania - o ile kogoś to będzie interesować... W każdym razie wypróbowanie Kedrigerna nawet bez modułu ust posiadacza RPi z wyjściem audio nic nie kosztuje, a może się przyda? Kody źródłowe Mileny i Kedrigerna są dostępne na stronie http://milena.polip.com A, i ostatnie wyjaśnienie: Ciapek to mały troll, wychowanek czarodzieja Kedrigerna w książce Johna Morressy'ego "Głos dla księżniczki". Nawet trochę podobny Przy okazji: @Treker, czemu pliki zip są cacy a tgz są be? kedrigern.zip pykedrigern.zip
  6. 5 punktów
    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. 5 punktów
    Właśnie zaakceptowałem Twój opis, możesz go teraz zgłosić do akcji rabatowej umieszczając link w temacie zbiorczym. Dziękuję za przedstawienie ciekawego projektu, zachęcam do prezentowania kolejnych DIY oraz aktywności na naszym forum Świetny projekt, bardzo lubię takie klimaty! Tutaj dla porównania moje "analogowe" statystyki Forbota (liczba osób online + odsłony z całego dnia):
  8. 4 punkty
    Witam chciałem wam przedstawić wykonaną przeze mnie kierownicę do komputera PC. Kierownica nie jest jeszcze do końca wykonana tak jak bym chciał , ale jest skończona działa można ją będzie jeszcze rozbudować Budowa od strony elektronicznej: Do budowy kierownicy użyłem jako podstawę Arduino Leonardo. Opierałem się o podobny projekt który znalazłem na yt . Lecz ja zrobiłem to trochę ładniej niż tamten chociaż nie ma rewelacji mogło być lepiej , ale w przyszłości myślę zrobić jeszcze jedną lepszą Oprócz Arduino Leonardo , zamiast jakiś potencjometrów i kombinowania z przekładniami użyłem enkoder z drukarki Canon IP2700. Ogólnie to oprócz enkodera to jeszcze parę przycisków potencjometry do pedałów i jakieś diody na podświetlenie. Poniżej schemat jak to podłączone. Oprogramowanie gotowe znalazłem pod tym filmem z którego się wzorowałem, wystarczyło wgrać XLoaderem i to wszystko podłączyć jak na schemacie. Od strony mechanicznej wygląda to tak: Odbijanie i blokada zostały zrobione na sprężynie niestety nie mam zdjęć . Dodam link do filmu na którym jest pokazane jak to działa. Ręczny przerobiony ze starej kierownicy . Elementy skrzyni biegów wydrukował mi kolega w 3D. i wygląda to tak: Pedały ze starej kierownicy , dorobiony jeden sprzęgłowy z innej kierownicy: Ostatecznie wygląda to tak: Link do filmu jak to działa i jak zrobione niektóre rzeczy: To by było na tyle w planach zrobienie Force Feed Back , na silniku DC 12v i przekładniach Pozdrawiam Krzysiek
  9. 4 punkty
    O mnie Witam, Jestem Maciej - pracuje jako software architect (nie mam wykształcenia elektronicznego dlatego proszę o wyrozumiałość jeżeli chodzi o połączenia i rozwiązania - z tego też powodu w projekcie nie daje gotowego przepisu na zasilanie ) i żeby do końca nie zgnuśnieć po godzinach tworzę platformę RemoteMe. W platformie chodzi głównie o ułatwienie sterowaniem urządzeniami IoT poprzez internet - bez konieczności posiadania VPNa, publicznego IP. Po stronie RemoteMe tworzycie strony internetowe ( RemoteMe posiada hosting na Wasze pliki ) + zestaw bilbiotek (Javascript, RasbeprryPi (python), Arduino ESP ) które w łatwy sposób pozwolą na komunikowanie się z Waszymi urządzeniami. Co do protokołu to opracowałem własny (bardziej jest to konwencja przesyłu paczek niż protokół jako taki ) (działa przez sockety, websockety, wywoływania RESTowe) - umożliwia on przesył wiadomości do określonego urządzenia, i coś w rodzaju topic- subscribera ( u mnie się to nazwa"variables" zmienne ) Wasze urządzenia rejestrują się w RemoteMe po zarejestrowaniu, możecie do nich wysyłać komendy przez stronę internetową albo z innych urządzeń. Jednym z ostatnich featerów są "Out of the box projects" - polega to na tym, że jednym kliknięciem importujecie projekt na Wasze konto - oczywiście możecie potem wszytko zmieniać wedle własnych pomysłów - właśnie ostatnim takim projektem jest Samochód RaspberryPi z kamerką o którym w tym kursie. Projekt jest częściowo openSourcowy - bilbioteki Javascript, Python, api Restowe są openSource - sam kod serwera i program na RasbeprryPi jest zamknięty. Platformę tworzę sam - po godzinach i udostępniam za darmo O kursie Ten kurs – przedstawia budowę samochodu sterowanego przez przeglądarkę z wyświetlaniem obrazu z kamerki. Jest to dość specyficzny kurs (jak pisałem wyżej ) – całość oprogramowanie jest już zrobiona, a dodanie plików do własnego konta w RemoteMe sprowadza się do paru kliknięć. Po tak dodanym projekcie można własnoręcznie i dowolnie edytować wszystkie pliki źródłowe (strona WWW skrypt pythonowy) – zwłaszcza, że same pliki projektu nie są skomplikowane, a kod jest dość czytelny i samo opisujący się (mam przynajmniej taką nadzieję ) Na dole kursu opisana jest bardziej szczegółowo zasada działania samochodu. Jeżeli nie jesteście zainteresowani samą platformą RemoteMe to i tak myślę, że w kursie znajdziecie garść pomysłów na podobny projekt Kurs właściwy Na filmie działanie + krok po kroku wszystko z tego kursu. W poprzednim kursie pokazałem jak sterować pozycją kamerki i przechwytywać obraz na przeglądarkę tutaj i sterowanie kamerką tutaj . Teraz rozbudujemy ten projekt i zbudujemy samochód z napędem na 4 koła ( sterowany podobnie jak czołg – żeby skręcić prawa para kół musi się kręcić z inną prędkością niż lewa). Taki efekt otrzymamy na wideo też całość kursu – można zaglądnąć, gdy gdzieś utkniecie Części RaspberryPi z wifi ( np zeroW) link Podwozie z silnikami link Sterownik serwomechanizmów na I2C link Kamera do Rpi + taśma jeżeli potrzebna link Dwa SerwoMechanizmy kompatybilne z uchwytem kamerki kamery link Uchwyt na kamerkę z serwami link Mostek H TB6612FNG link Zasialnie – np akumlatory podłączone do przetwornicy – żeby uzyskać odpowiednie napięcie link Połączenia RaspberryPI steruje serwami poprzez moduł PWM i napędem przez ustawianie stanu pinów na mostku oraz dostarczając sygnału PWM poprzez ten sam moduł, który wysyła sygnał do serwomechanizmów. (Dzięki modułowi do generowanie sygnału PWM nie musimy tych sygnałów generować przez samo RaspberryPi – co jest dość problematyczne, poprostu przez I2C przesyłamy odpowiednie instrukcje do sterownika serw (poprzez bibliotekę pythonową dostarczoną przez adafruit), a ten generuje odpowiedni sygnał PWM dla serwo mechanizmów i do mostka H) Schemat połączeń: Poprzez magistrale I2C RPi steruje kontrolerem serwo mechanizmów, dwa ostanie wyprowadzenia kontrolera są podłączone do mostka H, gdzie wykorzystując sygnał PWM ustawiamy prędkość silników. Do mostka H są również podłączone piny RPi które stanami wysokim i niskim będą określać kierunek obrotu silników napędowych – po szczegóły odsyłam do dokumentacji układu TB6612FNG, równie dobrze można użyć mostka L298N lub podobnego. Zaprojektowałem płytkę PCB, którą możecie użyć pliki eagle,gerber itd tutaj plik pcb.zip Schemat płytki pokrywa się ze schematem powyżej. Wyprowadzenia płytki: Wejście sygnału PWM z kanałów 15 i 14 modułu PWM Wejście zasilania silników do poruszania się Zasilanie układów (PWM, RPi) koniecznie dokładne +5V Wyjście silników napędu, pierwsze dwa wyjścia do jednej pary silników kolejne dwa do drugiej Zasilanie serw i w tym przypadku silników napędu w moim przypadku ~6V (należy sprawdzić w specyfikacji serw i silników, jakie maksymalne napięcie można podłączyć) ZWORKA gdy zepniemy dwa piny napięcie z 5 będzie podawane też do zasilania silników napędu ZWORKA gdy jest podłączona zasilane jest RaspberryPI z połączenia 3 przed podłączeniem zworki należy dokładnie sprawdzić napięcia, żeby nie uszkodzić Najdroższego komponentu czyli właśnie malinki Wlutowujemy kabelki, bo nie będziemy korzystali z konwertera stanów Wlutowujemy kabelki, bo nie będziemy korzystali z konwertera stanów Oczywiście jest jeszcze potrzebne odpowiednie zasilanie, w moim przypadku 6v jako napięcie silników napędu i serw, oraz 5v dla RasbeprryPi i kontrolerów. Poniżej kilka zdjęć poglądowych całości samochodu: Programowanie Przed utworzeniem projektu skonfigurujcie kamerkę i komunikacje I2C używając raspi-config opisane tutaj. Ten projekt jest jednym z gotowych projektów, które możecie prosto zaimplementować kilkoma kliknięciami: KLIK - po zalogowaniu otworzy się projekt. Przejdźcie do zakładki “Build It” i podążajcie krokami, na końcu klik w “Build Project” i otrzymacie: Po kliknięciu “Get QR” pokaże się kod QR, który możecie zeskanować smartfonem, lub po prostu otworzyć stronę przyciskiem “Open” w przeglądarce na komputerze. Narazie nie radzę zmieniać pozycji kamery dopóki nie ustawimy pozycji serw – w niektórych przypadkach możecie uszkodzić swoje serwomechanizmy. Samochód powinien jeździć jak na filmie – może się zdarzyć, że skręca w złą stronę albo serwa są źle skalibrowane, poniżej w omawianiu kodu napisałem jak to naprawić. Omówienie tego, co się stało Jak zauważyliście, tworzenie projektu było mocno zautomatyzowane. Dlatego omówię teraz, co się dokładnie wydarzyło i jak modyfikować Wasz projekt. Przede wszystkim utworzyły się dwie zmienne (zakładka variables): Zmienna cameraPos przesyła pozycje kamery, drive pozycje joysticka. Obie są typem “Small int x2” oznacza to, że wartoscią zmiennej są dwie liczby integer. Strona internetowa zmienia nasze zmienne, a skrypt pythonowy te zmiany rejestruje i odpowiednio reaguje (jak rozwiniemy zmienne zobaczymy, że urządzeniem nasłuchującym na zmiany jest właśnie skrypt pythonowy). Zobaczmy jak wygląda kod Pythonowy (więcej o zmiennych tutaj) Python Skrypt pythonowy został automatycznie wgrany. Oczywiście możemy go podejrzeć i modyfikować ( żeby stworzyć nowy skrypt pythonowy np dla innych projektów zobacz tutaj) . Z informacji jakie teraz są Ci potrzebne to skrypt pythonowy to kolejne urządzenie w remoteMe jest zarządzalne przez skrypt (uruchomiony przez ./runme.sh) , do tego urządzenia możemy wysłać wiadomości, urządzenie reaguje też na zmiany zmiennych, które obserwuje i może te zmienne zmieniać. Żeby otworzyć skrypt pythonowy kliknij python.py i wybierz Edit : Wygląda on następująco. Poniżej omówię ciekawsze fragmenty import logging import socket import math import struct import sys import os os.chdir(sys.argv[1]) sys.path.append('../base') import remoteme import Adafruit_PCA9685 import time import RPi.GPIO as GPIO motorAIn1 = 25 # GPIO25 motorAIn2 = 8 # GPIO8 motorBIn1 = 24 # 24 motorBIn2 = 23 # 23 motors = [[motorAIn1, motorAIn2], [motorBIn1, motorBIn2]] motorsPWM = [14, 15] pwm = None; def motorForward(motorId): GPIO.output(motors[motorId][0], GPIO.LOW) GPIO.output(motors[motorId][1], GPIO.HIGH) def motorBackward(motorId): GPIO.output(motors[motorId][0], GPIO.HIGH) GPIO.output(motors[motorId][1], GPIO.LOW) def motorSoftStop(motorId): GPIO.output(motors[motorId][0], GPIO.LOW) GPIO.output(motors[motorId][1], GPIO.LOW) def setMotor(motorId, speed): if speed == 0: motorSoftStop(motorId) elif speed > 0: motorForward(motorId) elif speed < 0: motorBackward(motorId) speed=-speed logger.info("set speed {} for motor {} ".format(speed,motorId)) pwm.set_pwm(motorsPWM[motorId], 0, int(speed)) def onCameraPosChange(i1, i2): global pwm logger.info("on camera change {} , {}".format(i1, i2)) pwm.set_pwm(1, 0, i1) pwm.set_pwm(0, 0, i2) pass def onDriveChange(x, y): logger.info("on drive change x {} , y {}".format(x, y)) global pwm left=y right=y left+=x right-=x delta=(left+right)/2 left+=delta right+=delta # when your car doesnt drive as suppose try to swich right and left variable below # or remove add minuses next to 2 # another way is to switch cables conencted to motors setMotor(0, 2*left) setMotor(1, 2*right) pass def setupPWM(): global pwm pwm = Adafruit_PCA9685.PCA9685() pwm.set_pwm_freq(80) def setupPins(): global GPIO GPIO.setmode(GPIO.BCM) # Broadcom pin-numbering scheme for motor in motors: for pinId in motor: GPIO.setup(pinId, GPIO.OUT) try: logging.basicConfig(level=logging.DEBUG, format='%(asctime)s %(name)-12s %(levelname)-8s %(message)s', datefmt='%d.%m %H:%M', filename="logs.log") logger = logging.getLogger('application') setupPWM() setupPins() remoteMe = remoteme.RemoteMe() remoteMe.startRemoteMe(sys.argv) remoteMe.getVariables().observeSmallInteger2("cameraPos" ,onCameraPosChange); remoteMe.getVariables().observeSmallInteger2("drive" ,onDriveChange); remoteMe.wait() finally: pass Sterowanie silnikami: def motorForward(motorId): GPIO.output(motors[motorId][0], GPIO.LOW) GPIO.output(motors[motorId][1], GPIO.HIGH) def motorBackward(motorId): GPIO.output(motors[motorId][0], GPIO.HIGH) GPIO.output(motors[motorId][1], GPIO.LOW) def motorSoftStop(motorId): GPIO.output(motors[motorId][0], GPIO.LOW) GPIO.output(motors[motorId][1], GPIO.LOW) def setMotor(motorId, speed): if speed == 0: motorSoftStop(motorId) elif speed > 0: motorForward(motorId) elif speed < 0: motorBackward(motorId) speed=-speed logger.info("set speed {} for motor {} ".format(speed,motorId)) pwm.set_pwm(motorsPWM[motorId], 0, int(speed)) Funkcja setMotor dla motorId 1 lub 2 ustawia prędkość speed (może być ujemna). poprostu najperw na odpowiednich pinach ustawiamy odpowiednio stany (ruch do przodu do tyłu, hamowanie), a następnie w zależności od prędkości ustawiamy odpowiednio wypełnienie PWM korzystając ze sterownika serw. def onCameraPosChange(x, y): global pwm logger.info("on camera change {} , {}".format(x, y)) pwm.set_pwm(1, 0, x) pwm.set_pwm(0, 0, y) pass Funkcja setMotor dla motorId 1 lub 2 ustawia prędkość speed (może być ujemna). poprostu najperw na odpowiednich pinach ustawiamy odpowiednio stany (ruch do przodu do tyłu, hamowanie), a następnie w zależności od prędkości ustawiamy odpowiednio wypełnienie PWM korzystając ze sterownika serw. def onDriveChange(x, y): logger.info("on drive change x {} , y {}".format(x, y)) global pwm left=y right=y left+=x right-=x delta=(left+right)/2 left+=delta right+=delta # when your car doesnt drive as suppose try to swich right and left variable below # or remove add minuses next to 2 # another way is to switch cables conencted to motors setMotor(0, 2*left) setMotor(1, 2*right) pass Powyższa funkcja zostanie wywołana jak zmieni się zmienna drive – np po zmianie joysticka na stronie. x,y to po prostu współrzędne wychylenia joysticka (1024,1024) oznacza wychylenie maksymalnie do góry i w prawo. Na podstawie tych zmiennych wyliczamy prędkość lewej i prawej strony samochodu. Jeżeli samochód skręca, zamiast jechać do przodu, jedzie do tyłu zamiast do przodu: setMotor(0, Y2*left) setMotor(1, X2*right) Dajcie minusy w różnych kombinacjach (w miejsca X i Y) do czasu, aż samochód jedzie do przodu – gdy joystick jest wychylony do góry. (będzie to odpowiadać zamianą miejscami przewodów lewej strony dla miejsca Y i prawej strony dla miejsca X). Następnie, jeżeli prawa i lewa strony są zamienione (samochód skręca w złą stronę ), w funkcji powyżej zamieńcie left i right miejscami. def setupPWM(): global pwm pwm = Adafruit_PCA9685.PCA9685() pwm.set_pwm_freq(80) def setupPins(): global GPIO GPIO.setmode(GPIO.BCM) # Broadcom pin-numbering scheme for motor in motors: for pinId in motor: GPIO.setup(pinId, GPIO.OUT) Po prostu ustawiamy odpowiednie piny (te do sterowania mostkiem H) na wyjścia. I tworzymy obiekt do kontrolowania sterowania serw. (Uwaga żeby sterownik serw działał prawidłowo musimy włączyć komunikacje I2C używając raspi-config więcej tutaj ) remoteMe.startRemoteMe(sys.argv) remoteMe.getVariables().observeSmallInteger2("cameraPos" ,onCameraPosChange); remoteMe.getVariables().observeSmallInteger2("drive" ,onDriveChange); remoteMe.wait() Ustawienie RemoteMe i ustawienie jakie funkcję mają zostać wywołane, gdy zmienne do sterowania kamery i napędu zostaną zmienione. To tyle w samym skrypcie pythonowym, jak widzicie, nie jest on zbyt skomplikowany, po więcej informacji zapraszam tutaj Strona WWW Tak naprawdę zostały stworzone dwie strony WWW — jedna do kalibracji druga — strona do sterowania samochodem i wyświetlania obrazu z kamerki. Otwórzmy stronę do kalibracji: Otworzy się strona internetowa z dwoma suwakami. Ustawmy górny i dolny na środkową pozycję – kamera się poruszy- górny suwak powinien poruszać kamerę w osi x, dolny y. Jeżeli się tak nie dzieje – zamieńcie miejscami przewody serwomechanizmu. Następnie za pomocą suwaków ustalcie maksymalne wychylenie osi x i osi y dla mnie jest to: x : 298 – 830 i centralna pozycja. Ważne, żeby centralna pozycja byłą dokładnie pomiędzy przedziałem u mnie ((298+830) /2 = 564) y: 223 – 723 i podobnie centralna pozycja kamery w osi y powinna być w środku przedziału Zapiszmy liczby gdzieś w notatniku i otwórzmy do edycji stronę do sterowania samochodem: <camera autoConnect="true" showInfo="true" class="cameraView"></camera> <connectionstatus webSocket="true" directConnection="false" camera="true"></connectionstatus> <variable component="cameraMouseTrack" type="SMALL_INTEGER_2" style="display:block" name="cameraPos" xMin="298" xMax="830" invertX="true" yMin="223" yMax="723" invertY="true" requiredMouseDown="true" reset="true" onlyDirect="true"></variable> <div class="joystickButtons"> <div class="buttons"> <variable class="gyroscope" component="gyroscope" type="SMALL_INTEGER_2" name="cameraPos" label="Gyroscope Camera" orientationSupport="true" xMin="298" xMax="830" xRange="19" invertX="true" yMin="223" yMax="723" yRange="20" invertY="false" onlyDirect="true"></variable> <variable class="gyroscope" component="gyroscope" type="SMALL_INTEGER_2" name="drive" label="Gyroscope Drive" xMin="-512" xMax="512" xRange="19" invertX="false" yMin="-512" yMax="512" yRange="20" invertY="false" onlyDirect="true"></variable> <button class="mdl-button mdl-js-button mdl-button--raised mdl-js-ripple-effect gyroscope" onClick="toggleFullScreen()">fullscreen </button> </div> <div class="joystickParent"> <variable class="joystick" component="joystick_simple" type="SMALL_INTEGER_2" name="drive" xRange="1024" yRange="1024" onlyDirect="true"></variable> </div> <div style="clear: both;"/> </div> Są to automatyczne komponenty do sterowania samochodem i wyświetlaniem obrazu wideo. Strona, którą otworzyliście zawiera już wszystkie komponenty potrzebne do sterowania waszym samochodem. Jedyne co trzeba zrobić to zmienić zakres ruchów serwo mechanizmów. xMin,xMax,yMin,yMax, zamieńcie na wartości jakie otrzymaliście na poprzedniej stronie z suwakami. Jeżeli chcecie stworzyć własną stronę ze swoimi komponentami najlepiej utworzyć ją od początku pokazane tutaj – pozwoli Wam to dodawać komponenty w przy pomocy kreatora, gdzie ustalicie potrzebne parametry, albo po prostu edytować źródła tej już utworzonej strony – wcześniej warto utworzyć kopię, gdyby coś poszło nie tak (albo skasować pliki i utworzyć projekt jeszcze raz – wtedy nie zapomnijcie wcześniej wykasować też zmienne) Po zmianie wartości x/y/Min/Max możemy otworzyć naszą stronę np w smartfonie, klikamy na index.html, ale tym razem wybieramy opcje get anymous link Następnie, klikamy ikonkę kodu QR, a kod, który się pojawi skanujemy smarfonem. Oczywiście sterowanie działa również poprzez internet – nie tylko w sieci lokalnej, jednak w niektórych przypadkach jest potrzebna dodatkowa konfiguracja więcej o niej tutaj Trochę szczegółów technicznych ( nie obowiązkowe ) RemoteMe serwuję stronę WWW do sterowania Waszym samochodem ( a dodatkowo Was loguje na Wasze konto – stąd token w linku otwieranym przez smartfon ) i uczestniczy w negocjowaniu tworzenia połączenia WebRTC. Połączenie webRTC jest to połączenie bezpośrednie (RaspberryPi – przeglądarka ( w niektórych przypadkach np za NATem jest potrzebny dodatkowo stun sewer)). Po stworzeniu połączenia webRTC stan zmiennych nie jest w ogóle wysyłany do remoteMe (bo pole “onlyDirect” w komponentach jest ustawione na true). Protokołem webRTC przesyłany jest też obraz, a że webRTC tworzy połaczenie point to point opóźnienie jest znikome. Program na RaspberryPi który odpalacie poleceniem ./runme.sh tworzy połączenie websocketowe z platformą RemoteMe oraz zarządza skryptem pythonowym (wysyła do niego wiadomości, przesyła wiadomości ze skryptu dalej do platformy etc ). Działanie skryptu pythonowego jest możliwe dzięki dodatkowym bilbiotekom RemoteMe (znajdują sie w folderze leafDevices/base/ ). Sama strona internetowa po websocketach łączy się do platformy RemoteMe (pozwalają na to skrypty javascriptowe zaimportowane w headerze pliku index.html ze ścieżek /libs/). Ułatwiają i ustanawiają komunikacje z platformą RemoteMe. Same komponenty wstawione w index.html typu : <variable component="**" W funkcjach pliku remoteMeComponents.js są zastępowane na “standardowe” i “bootstrapowe” komponenty htmlowe, dodatkowo do komponentów przypinane są eventy reagujące na akcje użytkownika i wysyłające odpowiednie komunikaty do skryptu pythonowego. Można podejrzeć jak remoteMeComponents.js zamienia i tworzy nowe komponenty – może to być interesujące gdy macie potrzebę stworzenia własnych komponentów, które RemoteMe nie pozwala dodać z kreatora. W większości przypadków akcje Waszych komponentów będą wykonywać zapis zmiennych w postaci RemoteMe.getInstance().getVariables() .setSmallInteger2("cameraPos",123,456,true); która wyśle do skryptu pythonowego informacje o zmianie zmiennej, podobnie sterujemy silnikami ustawiając odpowiednią zmienną. Podsumowanie Tworząc tej projekt chciałem pokazać Wam jak w łatwy sposób sterować Waszym samochodem z widokiem FPV. Projekt można rozbudowywać, lub zmieniać np, gdy korzystanie z innego mostka H niż ja. Zachęcam zatem do eksperymentowania ze źródłami projektu . Gdy jest to Wasz pierwszy projekt, zachęcam do zrobienia na początek projektu z mrugającą diodą i poczytanie dokumentacji na www.remoteme.org Pozdrawiam, Maciej
  10. 4 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...
  11. 4 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...
  12. 4 punkty
    RozZuBeN – Robot z Zupełnie Bezsensowną Nazwą Jest to robot klasy nanosumo, który został stworzony na wiosnę 2018 roku przez Pojemnika i mnie - wtedy uczniów pierwszej klasy VIII LO w Poznaniu. Zainteresowaliśmy się tą kategorią na Robomaticonie 2018, gdzie nie było żadnego sumo w tej skali. Pomyśleliśmy, że gdybyśmy mieli akumulator z silnikiem, to byśmy łatwo zgarnęli nagrodę za ostatnie (pierwsze!) miejsce. Tak powstał ten robot. Przestudiowaliśmy regulaminy różnych zawodów i wyodrębniliśmy minimalne założenia które musi spełniać nasz robot podczas zawodów: Poruszanie się Nieporuszanie się (przed startem) Po starcie nie może się zatrzymać na dłużej niż 30 sekund Czekanie 5 sekund po starcie Fajnie by było, gdyby sam z siebie nie wypadał z ringu Udało nam się spełnić wszystkie 5 punktów. Płytka: O ile 1, 2 i 3 punkt założeń projektowych można rozwiązać jednym przełącznikiem, to do czwartego potrzebne by było jakieś opóźnienie (układ RC lub popularny NE555 z tranzystorem). 5 punkt przekonał nas do użycia mikrokontolera. Zastosowaliśmy attiny84, które ilością pinów cyfrowych zapewniło nam dużą elastyczność w projektowaniu płytki. Taktowany jest wewnętrznym oscylatorem (miał być zewnętrzny generator kwarcowy ale nie mogliśmy go polutować). Umieściliśmy sterownik silników A3901 z którego wykorzystujemy tylko jeden z dwóch kanałów, dwa czujniki KTIR0711s jako czujniki krawędzi ringu podłączone bezpośrednio do ADC mikrokontrolera, dwa ledy sygnalizacyjne (zielony i bursztynowy, który jest w praktyce pomarańczowy ), przełącznik do startowania robota, dzielnik rezystorowy do mierzenia napięcia akumulatora (chyba nawet niewykorzystany), złącze do programowania (2x3 żeńskie goldpiny precyzyjne) i stabilizator napięcia na 3,3V w obudowie SOT23 (nie pamiętamy oznaczenia). W Eaglu zrobiliśmy kwadrat 25x25mm, rozmieściliśmy elementy „na oko”, połączyliśmy ścieżkami, i wysłaliśmy do OSH Parku. Zajęło nam to dwie godziny. Był to koniec marca, płytka przyszła w połowie maja. Wcześniej zamówiliśmy wszystkie elementy, ale oczywiście pomyliliśmy attiny84 z attiny88, więc złożenie potrwało trochę dłużej niż przewidywaliśmy. Płytkę lutowało się całkiem dobrze, choć do drobnych elementów chyba jednak lepsze są płytki cynowane zamiast złoconych (niby złoto lepiej przewodzi prąd ale cynę najlepiej się lutuje do innej cyny). Praktycznie od razu płytka dogadała się z programatorem (co nie było takie oczywiste w naszych poprzednich robotach). Konstrukcja mechaniczna: Mieliśmy kilka pomysłów na spełnienie pierwszego założenia projektu: silniczek wibracyjny z jakiegoś telefonu, żeby robot tylko drgał (przecież ruch to ruch) albo umieszczenie dwóch silników tak by stykały się wałami z podłożem, aby nie była potrzebna przekładnia, mechanizmy sprężynowe chyba też były... Porządna przekładnia z zębatek odpadała, bo nie wiedzieliśmy jak ją zrobić. Ostatecznie wykorzystaliśmy przekładnię cierną. Wał silnika z nałożoną rurką termokurczliwą (dla lepszego tarcia) jest przyciśnięty do opony jedynego w robocie kółka wyciągniętego z jakiejś zabawki. Brzmi to okropnie i tak też zostało to zmontowane. „Felga” kółka trze o korpus silnika, więc to miejsce musi być często smarowane wazeliną techniczną, żeby robot nie zaciął się podczas walki. Wszystko jest zalane gorącym klejem z drucikami z goldpinów tworzącymi swego rodzaju usztywnienie. Czasem gorący klej sprawiał problemy czujnikom przeciwników (nie wiemy dlaczego). Robot o jednym kółku nie przewraca się, ponieważ na całej podstawie ma przyklejony kawałek styropianowej tektury znaleziony w szufladzie. Przed i za kołem znalazło się też trochę miejsca na ktiry. Wszystko połączyliśmy kabelkami, przykleiliśmy akumulator (Li-Po 1S 150 mAh) (oczywiście też na gorący klej) i włączyliśmy. Okazało się, że silnik jest za mocny i wywraca robota tuż po starcie, ale i tak byliśmy dumni, że robot porusza się całkiem skutecznie. Zrezygnowaliśmy też z przełącznika, który był bardzo niewygodny i zastąpiliśmy go odbiornikiem IR. Nie chcieliśmy się bawić z dekodowaniem sygnałów, więc sygnał połączyliśmy dużym kondensatorem do masy zmieniającym dane na jedną dłuuugą jedynkę odczytywaną przez procesor. Program: Po wielu próbach doszliśmy do wniosku, że najlepiej jest poruszać się metodą krótkich „skoków” polegających na szybkim włączeniu i wyłączeniu silnika (wtedy robot nigdy się nie przewracał). Po każdym „skoku” robot sprawdza czy jest na krawędzi. Jeśli tak to zaczyna poruszać się w drugą stronę i zapala bursztynowego leda. Po 10 sekundach ruchu robot zatrzymuje się na równe 10 sekund aby to przeciwnik zużywał akumulator. Całość powtarzana jest aż do utraty zasilania. Ta technika działa zaskakująco dobrze w przypadku konfrontacji z robotem, który też jest „ślepy”. Podczas ruchu może niechcący wypchnąć przeciwnika, a kiedy stoi bardzo ciężko jest go ruszyć (chyba, że przeciwnik jest rozpędzony lub ma dobre silniki). Akumulator starcza na bardzo dużo często remisowych walk. Zwykle ładujemy go przed zawodami do 4,20V a po walkach nadal ma ponad 4,10V. Osiągnięcia: 2018: 3. miejsce Bałtyckie Bitwy Robotów 3. miejsce Robocomp 2. miejsce Sumo Challenge 2019: 4. miejsce Robotic Arena 1. miejsce Robomaticon Robot tylko na Robotic Arena zajął ostatnie miejsce. Na każdych zawodach miał 3 przeciwników, więc na Robomaticonie wygrał ze wszystkimi! (z czego z jednym walkowerem) Wnioski: Robot spisuje się niespodziewanie dobrze, co obrazuje niestety poziom konkurencji w Polsce. Aktualnie kończymy prace nad kolejną konstrukcją, która tym razem będzie miała dwa kółka i będzie widzieć przeciwnika, co pozwoli liczyć na walkę a nie tylko łut szczęścia. Mamy nadzieję, że aktywnie zawalczy o pierwsze miejsca. Kilka filmów z zawodów: Chętnie odpowiemy na wszystkie pytania dotyczące robota.
  13. 4 punkty
    Elektroniczny Multitool Jak się zaczęło? Ano zaczęło się od tego, że zanabyłem sobie hulajnogę elektryczną. Długo i sumiennie przeglądałem różne recenzje, opisy, wertowałem informacje, aż w końcu zdecydowałem się na Airwheel Z5 Strong, którą na marginesie polecam. Pomimo wielu zalet - w tym kilku rozwiązań unikalnych w tym segmencie urządzeń, jak na przykład wygodne podesty albo łatwo wymienny akumulator - ma jednak pewną niewielką wadę: brak wyświetlacza informującego na przykład o bieżącej prędkości czy o przejechanej drodze. Ponieważ od jakiegoś czasu bawię się Arduino, stwierdziłem, że stosunkowo łatwo powinno dać się skonstruować taki licznik samodzielnie - wystarczy przecież zastosować GPS, który uniezależnia mnie od rozwiązań zastosowanych w hulajnodze. Zacząłem więc powoli kolekcjonować wszystkie niezbędne komponenty. Wyświetlacz Zacząłem trochę nietypowo, bo od wyświetlacza. Zrobiłem już kilka projektów na wyświetlaczach znakowych, ale - oczywiście - nie dają one takich możliwości, jak solidny, kolorowy, a najlepiej dotykowy wyświetlacz. Mój wybór padł na dotykowy wyświetlacz 2.4", pracujący z rozdzielczością 320x240 i komunikujący się przez popularny protokół SPI. Mój wygląda nieco inaczej niż ten w sklepie, ale różnią się płytką z kontrolerem, wyświetlacz jest ten sam. Kontroler Obejrzałem sobie sporo filmików dotyczących podłączania wyświetlaczy do Arduino i uderzyło mnie to, że w większości przypadków liczba klatek na sekundę osiągała bardzo często wartości jednocyfrowe. Jest to zrozumiałe - wszelkie Uno, Leonardo, Micro i tak dalej są taktowane ze stosunkowo małymi częstotliwościami, a przynajmniej zbyt małymi, by osiągnąć zadowalające rezultaty graficzne. Dlatego tym razem porzuciłem całę rodzinę *ino na rzecz chyba nieco mniej znanego kontrolera, Teensy 3.5. Kosztuje swoje, ale dostajemy naprawdę ciężką artylerię: 120 Mhz, 512 kB Flash, 192 kB RAMu, 62 piny, zintegrowany zegar czasu rzeczywistego (trzeba go tylko zasilić bateryjką CR2032), czytnik kart microSD i oczywiście możliwość programowania przez micro USB, bez konieczności stosowania programatorów. Polecam, korzystanie z takiego kombajnu to naprawdę czysta przyjemność. GPS Ta decyzja była stosunkowo prosta, zdecydowałem się na rozwiązanie ekonomiczne i kupiłem prosty GPS komunikujący się przez UART (szeregowo). Przyznam szczerze, że po zakupie Teensy trochę szkoda było mi poświęcić taki świetny kontroler li tylko na licznik do hulajnogi. Dlatego zanabyłem jeszcze popularny czujnik pogodowy BME280 i stwierdziłem, że w czasie, gdy nie będę korzystał z urządzenia jako licznika, zrobię z niego małą stację pogodową. Na wyposażeniu urządzenia znalazł się również czujnik położenia MPU9250, bo zamierzałem napisać rejestrator pochyłości podłoża (i ewentualnie również jego jakości), ale w końcu z tego pomysłu zrezygnowałem. Być może za jakiś czas dopiszę sobie do urządzenia cyfrową poziomicę. Konstrukcja Zacząłem od płytki prototypowej, która błyskawicznie zamieniła się na totalnie zagmatwaną pajęczą sieć przewodów kydexowych. Myślałem na początku, że poprzestanę na niej, ale plątanina ta wyglądała tak dramatycznie, że z pomysłu w końcu zrezygnowałem, traktując go tylko jako prototyp. Sprawdziłem, czy wszystkie urządzenia będą pracowały prawidłowo i generalnie każdy moduł udało mi się uruchomić i pobrać z niego dane, z tym wyjątkiem, że BME280 i MPU9250 odmawiały współpracy podłączone do jednej szyny I2C. Szczęśliwie Teensy oferuje tych szyn chyba z pięć, więc przepiąłem BME na inną i wszystko wstało bez problemu. Kiedy wszystko działało, siadłem do Eagle'a i zaprojektowałem PCB, który miał zastąpić tę nieszczęsną płytkę prototypową. W Polsce jest kilka firm, które wykonują nawet pojedyncze sztuki takich płytek, a moją zamówiłem w firmie Satland Prototype. Musiałem poczekać dwa tygodnie, ale w końcu płytka doszła pocztą i mogłem zacząć lutować. Jakiś czas temu wyposażyłem się w drukarkę 3D, więc po zlutowaniu (i uruchomieniu) wszystkiego siadłem do Fusion 360 i zaprojektowałem obudowę na całe urządzenie. Zadbałem o to, żeby BME został odseparowany wewnętrzną ścianką od reszty urządzenia, bo ekran LCD potrafi się grzać i zafałszowuje odczyty. GPS zamocowałem w osobnym miejscu, wsunięty w odpowiedni slot i zabezpieczony ścianką z drugiej strony, ponieważ niestety wersja, którą kupiłem, nie posiadała żadnych otworów montażowych. Płytka z komponentami siedzi w przygotowanym na jej wymiary wgłębieniu i jest ściśnięta pomiędzy dwiema częściami obudowy, więc nie ma możliwości się przesunąć. Do tego otwór na wyświetlacz, siateczka w przedniej ściance przepuszczająca powietrze do czujnika pogodowego i tyle. Słowo komentarza, bo pewnie padnie takie pytanie: schemat dotyczy nowej wersji płytki z usuniętym radyjkiem NRF, na zdjęciu jest starsza wersja - szczegóły na końcu artykułu. Programowanie Proces programowania musiałem rozłożyć w czasie, ale projekt szedł powoli do przodu. Zacząłem od części pogodowej, ogrom miejsca w programowalnej pamięci kontrolera pozwolił mi poszaleć, więc przygotowałem sobie w C++ klasy odpowiedzialne za obsługę interfejsu użytkownika, spięcie różnych modułów w jedną całość, wyświetlanie grafiki i tak dalej. Również i tym razem dałem się ponieść - nie mogłem znaleźć w Internecie dobrego programu do generowania czcionek w formacie zrozumiałym dla biblioteki ILI9341_t3 przygotowanej przez twórcę Teensy (działa ona szybciej od regularnej biblioteki), a zależało mi na czcionce siedmiosegmentowej - takiej trochę "retro" (widać na screenach). Zapytałem więc Paula o kilka rzeczy, siadłem któregoś wieczoru i wyrzeźbiłem edytor czcionek dla ILI9341_t3. Mój prosty programik może się podobać lub nie, ale najlepszą alternatywą jaką znalazłem jest gigantyczne makro w Excelu, więc sami rozumiecie... Dużym odkryciem było dla mnie, że na platformę Arduino można już programować w Visual Studio Code - Arduino Studio jest wciąż wymagane (bo zawiera wszystkie narzędzia potrzebne do zbudowania programu dla kontrolerka), ale tak naprawdę wszystkie operacje - budowanie, wrzucanie na płytkę, monitor portu szeregowego - można już obsłużyć bezpośrednio w tym świetnym środowisku. Tylko że... niestety Teensy nie jest całkowicie zgodne z Arduino i do budowania na tę platformę potrzebny jest dodatkowy programik, Teensyduino, który nieco modyfikuje Arduino Studio i nie jest kompatybilny z VS Code. Tym niemniej, większość developmentu zrealizowałem w tym ostatnim, jedynie budując i wrzucając aplikację na urządzenie przy pomocy AS. Zastosowałem też własny mechanizm podwójnego buforowania: cały obraz buduję w RAMie i wyświetlam go hurtem w jednym kroku. Ogranicza to trochę lag związany z wyświetlaniem poszczególnych elementów, opóźnienie wciąż jest, ale jest znacznie mniej zauważalne. Kosztowało mnie to prawie połowę pamięci RAM, ale z uwagi na to, że pozostałe komponenty aplikacji prawie go nie zużywają, mogłem sobie na to pozwolić. Źródła trzymam na Gitlabie, chcecie obejrzeć - sklonujcie sobie repo. Efekt W chwili obecnej płytka w trybie stacji pogodowej wyświetla klasycznie: temperaturę, ciśnienie i wilgotność, a także wykresy: bieżący (jasna linia - jeden piksel to 15 sekund) i historia - 1h, 8h lub 24h wstecz.Tryby można przełączać po dotknięciu ekranu - pojawia się wtedy proste menu. Aplikacja wyposażona jest w wygaszacz ekranu, który zapobiega wypaleniu pikseli - szczególnie, że w trybie stacji pogodowej bardzo dużo z nich mogłoby być na to narażone. Po 30 sekundach ekran się wyłącza (wygasza), a włącza ponownie po dotknięciu. Niestety nie udało mi się wyłączyć jego podświetlenia - doczytałem, że w tym ekranie programowo nie da się tego zrobić. Szkoda. W trybie GPS wyświetlane są na razie podstawowe informacje wczytane z odbiornika: prędkość, wysokość n.p.m., kierunek jazdy, liczba satelit, z których odczytywane są dane oraz położenie geograficzne - długość i szerokość. Za jakiś czas dopiszę pewnie tryb "rowerowy", czyli przebyta droga, średnia i maksymalna prędkość i tak dalej. Aplikację mam napisaną na tyle modularnie, że teraz taki moduł mogę już sobie praktycznie niewielkim kosztem poskładać "z klocków". Problemy Człowiek uczy się na błędach, a mądry człowiek na błędach innych. Podczas rozwijania tego projektu nadziałem się na mnóstwo problemów, więc podzielę się moimi rozwiązaniami - być może komuś oszczędzi to czasu i nerwów. Po pierwsze, zasilanie - w dwóch odsłonach. Pierwsza odsłona - pierwotnie na płytce znajdowało się jeszcze radyjko NRF24, ponieważ jakiś czas temu zbudowałem sobie "satelitę" - małą płytkę z czujnikiem temperatury i wilgotności zasilaną z bateryjki CR2032: miałem nadzieję, że w trybie stacji pogodowej urządzenie będzie również ściągało informacje z tego źródła. Testy bez GPSu wypadły pozytywnie - to widać na zdjęciach - ale po podłączeniu wszystkiego i włączeniu zasilania, ekran rozbłysł na chwilę, a potem powolutku przygasł i zgasł całkowicie. Podejrzewałem od razu NRF, chciałem go rozlutować, ale w trakcie tego procesu oderwałem jeden pad na płytce, więc nie miałem już możliwości łatwego sprawdzenia, czy to on jest winien. Żeby uniknąć dalszych uszkodzeń, podrzuciłem płytkę ojcu, który w pracy ma wysokiej klasy rozlutownicę, a ja zaprojektowałem w międzyczasie drugą, tym razem już bez NRFa. Warto zawsze sprawdzić, czy uda się zasilić wszystkie komponenty - ja leniwie pociągnąłem zasilanie wszystkiego z płytki, a mogłem przecież wstawić na płytkę port microSD i pociągnąć dodatkowe ścieżki bezpośrednio z niego - wtedy obciążyłbym zasilacz (który pewnie nawet by nie sapnął), a nie samą płytkę. Druga kwestia - hulajnoga, którą kupiłem, ma w baterii wyjście USB - można (według instrukcji) doładowywać sobie na przykład komórkę (traktować akumulator jako powerbank). Również do tego portu podłączana jest latareczka, którą można sobie włączyć podczas jazdy. Niestety podczas prób terenowych okazało się, że przysiad napięcia podczas rozpędzania jest tak duży, że płytka gaśnie albo się zawiesza. Musiałem więc zasilić ją z osobnego powerbanku, w przyszłości pomyślę nad zasileniem płytki z osobnego akumulatora albo po prostu baterii. Teraz BME280 - małe ostrzeżenie. Układzik jest rewelacyjny, malutki i stosunkowo dokładny... ale się grzeje! Potrafi rozgrzać się na tyle, że zafałszowuje informacje o temperaturze o 1.5-2 stopnie. Rozwiązanie (proponowane nawet przez Boscha) polega na zmniejszeniu dokładności pomiaru (urządzenie może działać w trybie oversampling, czyli robi np. 8 pomiarów i uśrednia - należy to wyłączyć), wyłączeniu filtrowania (które również poprawia jakość pomiarów), przełączyć się w tryb "forced" - wtedy płytka robi pomiar tylko na życzenie - i ograniczyć pomiary do jednego na minutę (!). Ja nie ograniczyłem się tak bardzo, pomiary mam co 15 sekund, ale mimo wszystko układ się grzeje i na początku na wykresie widać delikatny skok temperatury, który po chwili się stabilizuje. Jest również prawdopodobne, że grzeje się nie tyle BME, co wyświetlacz - podobny problem miałem w innej stacji pogodowej z wyświetlaczem znakowym. Tam temperatura skakała do góry o kilka stopniu po uruchomieniu. Kwestia estetyki - nie zadbałem o to, żeby schować obramowanie ekranu z widocznymi ścieżkami panelu dotykowego. W innych projektach nie popełniam już tego błędu, widoczny jest sam ekran (wygląda to o niebo lepiej). Ogólnie jednak jestem zadowolony, płytka jest rozwojowa, a nowe funkcjonalności mogę dodawać programowo, więc podejrzewam, że wzbogacę ją jeszcze o kilka dodatkowych trybów pracy.
  14. 3 punkty
    Cześć, w tej cenie można już kupić prostszy dobry oscyloskop, który jest dużo bardziej uniwersalnym przyrządem pomiarowym niż multimetr. Według mnie do zastosowań amatorskich to lekka przesada. Miernik w cenie do 400 PLN w zupełności wystarczy. Rozważ zakup tańszego oscyloskopu jeśli koniecznie chcesz wydać te 1100 PLN, będziesz miał z niego dużo większy pożytek (a może też pełnić funkcje multimetru) niż z multimetru. Pozdrawiam
  15. 3 punkty
    O widzę znajomy temat to i ja coś mam Modyfikacja Biedronkowej latarki :). Wystarczy wykręcić 5 śrubek podważyć i zdjąć szare klamry i schować aku za pcb od led. Ja wstawiłem 1000 mAh bynajmniej tyle miał napisane ale , że już leciwy był bo to ze starego telefonu to na pewno mniej dlatego rezystor wymieniowy przy ładowarce (R3). Przetwornica ustawiona na 5V i ładnie świeci a co najważniejsze to nie "ściemnia" tak jak na paluszkach. Ledy na płytce pobierają 250mA jak dobrze pamiętam a led czołowy 100mA. Obudowy nie trzeba w żaden sposób modyfikować ani nawiercać i maskownica od baterii też ładnie się zamyka.
  16. 3 punkty
    Cześć! Zakładam, że skoro czytasz ten wpis to zapewne interesuje Ciebie elektronika/robotyka/majsterkowanie i zastanawiasz się jak skonstruować swojego robota. A może szukasz inspiracji? Motywacji do dalszego działania? Jeżeli odpowiedź brzmi tak, to zapraszam Ciebie do przeczytania mojego wpisu. Traktuje on o moim pierwszym elektronicznym projekcie - linefollowerze o wdzięcznym imieniu Ianush88. Wpis podzieliłem na poszczególne fragmenty tak, abyś łatwo trafił do sekcji które Ciebie interesują najbardziej. Początek każdego z nich będzie oznaczony pogrubionym tekstem. To tyle jeżeli chodzi o wstęp, zapraszam do lektury! Ważna uwaga: Ze względu na fakt, że jest to mój pierwszy projekt i ma dla mnie głównie charakter edukacyjny w wielu przypadkach zdecydowałem się na wybór prostych rozwiązań, które o wiele łatwiej zaimplementować i ewentualnie naprawić. Nad optymalizacją konstrukcji postanowiłem się skupić w ewentualnej przyszłej ewolucji tego projektu. Konstrukcja & mechanika Ianush88 to klasyczny przedstawiciel rodziny linefollower - składa się z dwóch płytek PCB połączonych ze sobą dwoma kątownikami z tworzywa sztucznego. Do głównej (większej) płytki PCB przymocowane są silniki prądu stałego Pololu HP z przekładnią 10:1 - standardowy wybór zdecydowanej większości konstruktorów linefollowerów ze względu na optymalny balans między maksymalną prędkością obrotową (3000 obr/min) a generowanym momentem (0,22 kg*cm). Do wałów silników zamocowane są koła Solarbotics RW2 - wybrałem je głównie ze względu na ich bezproblemową dostępność i łatwość w połączeniu z całą konstrukcją. Muszę przyznać, że odpowiednio wyczyszczone generują całkiem sporo przyczepności. Niestety nie mam porównania z oponami mini-z czy odlewanymi z silikonu, ale jestem z nich zadowolony. Przednia płytka PCB zawierająca czujniki linii opiera się na podłożu przy pomocy dwóch tranzystorów THT w obudowie TO-92. Ich nóżki przylutowałem do płytki a obudowy przetarłem lekko papierem ściernym tak, by swoimi krawędziami nie zahaczały o nierówności trasy. Elektronika Robot zasilany jest z akumulatora 2S 7.4V (korzystam z trzech o różnych wartościach pojemności: 150mAh, 250mAh i 800mAh). Napięcie z akumulatora jest stabilizowane i obniżane do 5V przez stabilizator napięcia LM1117. Mózgiem całej konstrukcji jest Atmega16A - wybrana przeze mnie ze względu na moją znajomość tej rodziny mikrokontrolerów. Taktowana jest przez sygnał z kwarcu o częstotliwości 16MHz. Posiada istotne ze względu na projekt peryferia: ośmiokanałowy, 10 - bitowy przetwornik ADC, UART do komunikacji z zewnętrznym urządzeniem oraz trzy timery. Każdy z ośmiu kanałów przetwornika został wykorzystany do pomiarów napięcia z kolektorów czujników odbiciowych KTIR0711S. Znajdują się one na wysuniętej z przodu płytce PCB, umiejscowione symetrycznie po obu stronach. Sygnały między płytkami przekazywane są przy pomocy taśmy i złącz FFC. Timer 1 wykorzystałem do generowania dwóch sygnałów PWM sterujących prędkością każdego z silników. Doprowadzone są one do sterownika silników TB6612FNG, który jest układem z dwoma klasycznymi mostkami H. Do wejść UARTu mikrokontrolera poprowadzone są ścieżki ze złącza goldpin, do którego podłączony jest moduł bluetooth HC-05. Wraz z UART wykorzystuje go do komunikacji między robotem a telefonem lub komputerem. Na głównej płytce znajduje się także 6 - pinowe złącze ISP służące do programowania mikrokontrolera oraz przycisk który można dowolnie zaprogramować (ja używam go do ręcznego startowania/zatrzymywania robota). Dodatkowo na głównej płytce PCB umieściłem 8 LEDów prezentujących wskazania poszczególnych czujników odbiciowych. Całość została zaprojektowana przy użyciu oprogramowania Altium Designer. Obie płytki PCB są jednostronne i rozstawienie wszystkich elementów wraz z ich połączeniem było ogromnym wyzwaniem, co jednak udało się osiągnąć (ostatecznie skorzystałem z tylko jednej "przelotki"). Na płytce z czujnikami widoczne są przeróbki w postaci dolutowanych przewodów - jest to efekt złego zaprojektowania płytki i pośpiechu w przygotowaniach do zawodów... Program Do sterowania robotem zaimplementowałem regulator PD. Wartością zadaną jest w tym przypadku położenie czarnej linii względem robota, a sterowaniem wartości wypełnienia sygnału PWM dla poszczególnych silników. Uchyb wyliczany jest na podstawie pomiarów napięcia na kolektorach poszczególnych czujników odbiciowych. Gdy napięcie przekroczy pewną wartość graniczną, przy której uznajemy, że pod czujnikiem znajduje się już czarna linia do uchybu dodawana jest konkretna wartość błędu. Każdy czujnik ma przypisaną swoją "wagę" i przy każdej iteracji regulatora wyznaczany jest średni błąd, a następnie uchyb i sterowanie. Do regulatora PD dorzuciłem pewne wyjątki, które obsługują takie przypadki jak np. zgubienie linii tak, by robot potrafił na nią z powrotem trafić. Mogę tutaj polecić artykuł "Algorytm linefollowera w C – dla początkujących i nie tylko" , który całkiem dobrze opisuje jak zaimplementować regulator pd do robota typu linefollower. Do zmiany ustawień robota, w tym nastaw regulatora przygotowałem aplikację przy pomocy narzędzia MIT App Inventor. Dobrze jego obsługę prezentuje artykuł: "Tworzenie aplikacji Android". Do komunikacji przygotowałem swój własny protokół o określonej ramce danych. Wprowadzanie danych i naciśnięcie odpowiedniego przycisku powoduje wysłanie wiadomości o konkretnej budowie i zawartości do mikrokontrolera, który ją przetwarza i zmienia wartości odpowiednich parametrów. Przemyślenia Już zaprojektowałem nową płytkę czujników, tym razem mam nadzieję że poprawnie. Teraz będą ustawione zdecydowanie bliżej siebie, ponieważ chcę żeby robot szybciej mógł reagować na zmiany trasy. W przyszłym projekcie na pewno skorzystam już z płytek dwustronnych, co pozwoli na gęstsze upakowanie elektroniki, a co za tym idzie zmniejszenie gabarytów i masy robota. A mniejsza masa = lepsze osiągi. Plus brak problemów z połączeniem wszystkich komponentów. Dostrzegłem także, że kluczową sprawą jest przyczepność mechaniczna - nawet gdy silniki mają duży moment i prędkość obrotową bez przyczepności nie przekłada się to na lepsze wyniki. Dlatego planuję w przyszłości wykorzystanie opon mini-z lub odlewanych z silikonu. Na pewno dojdzie także wykorzystanie enkoderów do pomiarów prędkości obrotowych silników i implementacja regualtorów PID dla silników. Pozwoli to na płynną regulację prędkościami i w konsekwencji mniejszą ilością uślizgów kół. Myślę także o ulepszeniu regulatora dla całego robota, sprawdzeniu kilku ciekawych rozwiązań. To już koniec! Jeżeli masz pytania lub zainteresował Ciebie jakiś temat poruszony w tym wpisie to daj mi znać w komentarzu! Powodzenia przy tworzeniu nowych konstrukcji!
  17. 3 punkty
    Jako, że zbliżały się pierwsze urodziny pewnego młodego człowieka w mojej rodzinie wpadłem na pomysł, żeby wreszcie z długiej fazy mówienia o jakimś projekcie przejść do fazy robienia go. I tak o to padł pomysł zbudowania kolorowej lampki nocnej. Koncepcja Jako, że lampka to bardziej mebel niż zabawka to całość musiała być solidna a przy tym najlepiej nie brzydka. Jako klosz (obudowa) na początku myślałem o użyciu rury z plexi ale cena okazała się niestety nie akceptowalna. Wpadłem na pomysł użycia opakowania spożywczego z plastiku. Przeszukałem kilka sklepów gospodarstwa domowego i znalazłem pasujące pudełko. No to już z górki. Potem jeszcze trochę diod led,jakieś zasilanie i sterowanie. Dno lampki przykręcone jest na dwie śruby M3 ze stożkowym łbem, wewnątrz przyklejone są dwie tulejki dystansowe robiące za gwint. Wnętrze "klosza" to "choinka" zbudowana z plastikowej rurki, jej podstawy oraz łańcucha diod. Podstawa całości oraz choinki to płytki wycięte z deski do krojenia kupionej właśnie w tym celu. Nie jest to sztywne tworzywo ale do takiego zastosowania sprawdza się super, łatwo się obrabia, wygląda dobrze i trudno zgadnąć z czego to jest Całość pomalowana sprejem na jasny niebieski (celowałem w błękitny, chyba nie wyszło źle). Elektronika Potrzebna była, przede wszystkim, pełna dowolność koloru a jako, że nie chciałem bawić się w skomplikowane (w sensie kabelkologii) sterowanie tradycyjnymi ledami RGB padło na diody WS2811. Kupiłem łańcuch 50 diod 12mm. Całość może pobrać do 15W (50 x 60mA przy 5V) więc zastosowałem zasilacz 12V 2A oraz trzy moduły przetwornic na układach LM2596. Dlaczego aż trzy? Widząc grubość tych przewodów w łańcuchu obawiałem się, że na końcu może być już zauważalnie niższa jasność. Żeby tego uniknąć podzieliłem go na 3 sekcje zasilania bez rozłączania przewodu sygnałowego ze wspólna masą (przetwornice są nieizolowane). Do sterowania diodami wziąłem arduino pro mini (w moim przypadku klona), peryferiami się trochę marnuje ale to akurat miałem w szufladzie a cena jest bardzo atrakcyjna. Jako interfejs użytkownika użyłem enkodera z przyciskiem, poza tym jest tylko włącznik zasilania na tyle obudowy. Schemat jako taki nigdy nie powstał, jest to dość prosta konstrukcja, wszystkie połączenia można wywnioskować z kodu. Arduino jest zasilane z jedn z przetwornic, miałem jakiś problem z zasilaniem go z 12V, podłączyłem do 5V i działa (a już myślałem, że odejdzie do krainy wiecznych łowów, na szczęście nie). Program Napisany w arduino z bibliotekami do obsługi enkodera, diod i przyciśnięć (tutaj podziękowania dla @ethanak, sam bym nie wpadł, żeby takiej biblioteki poszukać). Dzięki nim nie musiałem się zajmować szczegółami ich sterowania zwłaszcza, że orłem programowania to ja nie jestem. Dzięki nim poszło w miarę szybko a efekty są co najmniej zadowalające. Jeżeli chodzi o efekty świetlne to na początku bazowałem na przykładach od adafruit ale niestety są one oparte na delayach a tutaj jest to nie do przyjęcia. Później, kiedy nie udało mi się samodzielnie przerobić ich, żeby je usunąć znalazłem w internecie ten kod , który temat rozwiązał. Menu napisałem sam z użyciem biblioteki Rotary.h oraz PMButton.h. Obsługa lampki Lampka domyślnie jest wyłączona (diody się nie świecą, arduino jest zasilone) dwu sekundowe przytrzymanie przycisku włącza lampkę z domyślnym trybem pierwszym w menu oraz najmniejszą jasnością. Jednorazowe kliknięcie to zmiana trybu, kręcenie enkoderem zmienia jasność świecenia. Kolejne dwusekundowe przytrzymanie wyłącza świecenie. W czasie pracy na maksymalnej mocy dół lampki nagrzewa się do ok 30*C, uważam to za bardzo dobry wynik. Dławiki przetwornic mają ok. 30-35*C. Trudności, przemyślenia Z całego tego projektu najprostsza okazała się część elektroniczna, kawałek płytki uniwersalnej, 4 moduły i trochę czasu. Trudności zaczęły się gdy przyszło do wykończenia obudowy, bardzo obawiałem się wiercenia w tym plastiku z obawy o pęknięcie. Swoją drogą robienie małych otworów też nie jest takie proste, dremel na najmniejszych obrotach i tak kręci się za szybko, topi plastik i trzeba wiercić na kilka razy. Wycinanie otworu na gniazdo zasilające poszło gładko, diamentowa tarcza dała sobie radę bez problemu. Pozostałą szparę nad nim zakleiłem klejem montażowym. Jak już się z całą resztą uporałem to przeszedłem do pisania programu. Bardzo doceniam wszystkich twórców, którzy wstawiają swoje, działające, kody do internetu, bardzo pomogły i ten etap przeszedłem z tarczą. W sumie to z tego też powodu źródło zostawiam w załączniku, jak ktoś potrzebuje jakiś kawałek albo chce sobie zbudować (a może nawet ulepszyć) to można brać do woli. Podsumowanie Budowa tej lampki zajęła mi około miesiąca i cieszę się, że wreszcie zbudowałem coś takiego od początku do końca. Młodemu (a w szczególności jego rodzicom) się bardzo spodobało więc myślę, że cel zrealizowany. Ja też się trochę nauczyłem i za to bardzo sobie to cenię. Kilka zdjęć z budowy: Niestety zapomniałem o zdjęciu lampki w całości, w działaniu. Postaram się to nadrobić. Jeżeli macie jakieś pytania albo czegoś nie napisałem/napisałem niezrozumiale to proszę o zwrócenie uwagi, odpowiem i uzupełnię opis. lampaRGB.zip
  18. 3 punkty
    Chociaż temat bardzo popularny to świetna robota ! Musze się też wziąć za tego typu przeróbkę oświetlenia. Wszystkie potrzebne elementy mam. PS. łącznik świecznikowy
  19. 3 punkty
    Raport mniejszości Oglądaliście kiedyś ten film? Główny bohater posługiwał się tam futurystycznym (przynajmniej jak na tamte czasy) interfejsem, którym sterował przy pomocy gestów. Fragment, który mam na myśli, możecie obejrzeć na Youtube. Osiągnięcie takiego poziomu zaawansowania wymaga oczywiście lat pracy, ale możemy spróbować skonstruować urządzenie, które będzie namiastką opisanego powyżej interfejsu. Koncepcja Zbudujemy urządzenie typu pan-tilt, czyli platformę obracającą się w dwóch osiach, sterowaną serwami. Sterowanie odbywać się będzie zdalnie, poprzez przechylanie telefonu komórkowego - platforma będzie próbowała naśladować gesty wykonywane przy pomocy telefonu. Platforma Na początku sama platforma - zdecydowałem się zaprojektować własną od zera, bazując na projekcie znalezionym na Thingiverse. Obrót w osi poziomej jest zmniejszony przez zębatkę - pozwala ona mniej więcej na 1/3 oryginalnego zakresu ruchu, ale za to jest on bardziej płynny. Obrót wokół osi pionowej jest natomiast nieograniczony. Pewnym kłopotem okazały się zębatki - przygotowanie dobrego koła zębatego wbrew pozorom wcale nie jest tak prostym zadaniem, jakim mogłoby się wydawać. Co więcej, nie ma również zbyt dużo narzędzi pozwalających na wygenerowanie prawidłowych kół zębatych. Po długich poszukiwaniach udało mi się jednak odnaleźć odpowiednie narzędzie - umożliwia ono konstruowanie kół zewnętrznych, wewnętrznych oraz listew zębatych: Gear Bakery. Wygenerowane koła zębate zapisywane są jako pliki .dxf, a te można już bez problemu wciągnąć do Fusion 360. Założyłem, że platforma będzie obracana zwykłymi, małymi serwami modelarskimi. Docelowo planowałem postawić na niej co najwyżej sportową kamerkę, więc moment rzędu 1.8 kg*cm jest tu całkowicie wystarczający. Pozostało wymodelowanie i wydrukowanie części, z których złożyłem potem platformę. Kontroler Tym razem potrzebowałem trochę więcej mocy obliczeniowej niż w wypadku prostszych projektów - w końcu musiałem postawić serwer odbierający dane po UDP - zdecydowałem się więc na Raspberry Pi. Serwer napisałem w Pythonie, bo język ten jest stosunkowo wysokopoziomowy i mocno separuje programistę od warstwy systemu i sprzętu: mogłem dzięki temu skupić się na istocie zadania, a nie na detalach implementacyjnych. Raspberry ma jednak pewną wadę - nie za dobrze radzi sobie z generowaniem sygnału PWM - sprzętowo może robić to tylko na jednym pinie. Co gorsza, standardowa biblioteka RPi.GPIO pozwala jedynie na programowe generowanie PWM - nie dawało to zbyt dobrych efektów. Na szczęście problem ten można bardzo elegancko obejść. Firma Adafruit przygotowała bowiem cwany układzik, który pozwala na sterowanie przy pomocy PWM aż dwunastoma niezależnymi urządzeniami, natomiast komunikacja tego układu z Raspberry odbywa się już po moim ulubionym protokole, czyli I2C. Układ ten rozwiązał jeszcze jeden problem, którego istnienie uświadomiłem sobie tak naprawdę w momencie, gdy właśnie zniknął. Serwa trzeba przecież jakoś zasilić, a nie można podłączyć ich do pinu 5V Raspberry - mają przecież znacznie większe zapotrzebowanie prądowe. PCA9685 w tym celu wyprowadza jednak szybkozłączkę, do której można podpiąć zewnętrzne zasilanie. Za każdym razem, gdy potrzebuję gdzieś 5V, zwykle robię mały przekręt: korzystam z kontrolera silnika bezszczotkowego, do którego przylutowałem wtyczkę T-Dean. Oprócz tego - co oczywiste - że ESC służy do sterowania silnikiem, obniża on również napięcie do 5V i przekazuje przewodami, które normalnie podłącza się do odbiornika RC. W pierwotnym zamyśle mechanizm ten nosił nazwę BEC - Battery Eliminator Circuit - i pozwalał w łatwy sposób zasilić odbiornik RC bez użycia dodatkowego akumulatora. Tymczasem wystarczy ominąć pin sterowania i mamy mały, wygodny, mobilny zasilacz na 5V. Konfiguracja Raspberry Aby mój skrypt w Pythonie uruchomił się, konieczne jest doinstalowanie biblioteki Adafruit pozwalającej na sterowanie kontrolerem PCA9685. Na początku trzeba oczywiście włączyć szynę I2C; robimy to w oknie konfiguracji Raspberry. Potem upewniamy się, że zainstalowane są następujące pakiety: sudo apt-get install python-smbus sudo apt-get install i2c-tools Po zainstalowaniu i2c-tools możemy użyć programiku i2cdetect, żeby sprawdzić, czy Raspberry prawidłowo wykrył kontroler PCA9685: ~ $ sudo ic2detect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: 40 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: 70 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- Teraz możemy ściągnąć i zainstalować bibliotekę do Pythona. sudo apt-get install build-essential python-dev cd ~ git clone https://github.com/adafruit/Adafruit_Python_PCA9685.git cd Adafruit_Python_PCA9685 sudo python setup.py install Uruchamiamy Do uruchomienia całego urządzenia potrzebujemy dwóch kawałków kodu, jednego mniejszego, drugiego większego. Tym mniejszym jest serwer w Pythonie, który steruje serwami. Możecie go ściągnąć z mojego repozytorium albo po prostu przekleić, bo jego kod jest stosunkowo krótki: # -*- coding: utf-8 -*- import socket import sys import time import Adafruit_PCA9685 # Częstotliwość sterowania PWM FREQUENCY = 50 # Czas jednego cyklu CYCLE_TIME = 1 / float(FREQUENCY) # Procentowy czas cyklu dla położenia minimalnego SERVO_MIN_PERCENT = 0.00055 / CYCLE_TIME # Procentowy czas cyklu dla położenia maksymalnego SERVO_MAX_PERCENT = 0.00245 / CYCLE_TIME # Wartość minimalna dla 4096 kroków SERVO_MIN = int(4096 * SERVO_MIN_PERCENT) # Wartość maksymalna dla 4096 kroków SERVO_MAX = int(4096 * SERVO_MAX_PERCENT) # Tworzymy obiekt pwm (przyjmie domyślnie adres 0x40) pwm = Adafruit_PCA9685.PCA9685() pwm.set_pwm_freq(FREQUENCY) def setAngle(channel, angle): pwm.set_pwm(channel, 0, int(SERVO_MIN + (float(angle) / 180.0) * (SERVO_MAX - SERVO_MIN))) def processCommand(command): angles = command.split("|") angles = list(map(lambda x: max(-90, min(90, -int(x.strip()))) + 90, angles)) print("P: {0}, Y: {1}".format(angles[0], angles[2])) setAngle(14, int(angles[0] / 10) * 10) setAngle(15, int(angles[2] / 10) * 10) def main(): # Create TCP/IP socket sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # Bind the socket to the port server_address = ('', 10000) sock.bind(server_address) print("Waiting for data...") buffer = "" try: while True: data, addr = sock.recvfrom(32); buffer = buffer + data commandEnd = buffer.find(";") if (commandEnd != -1): command = buffer[0:commandEnd] buffer = buffer[commandEnd+1:] processCommand(command) except KeyboardInterrupt: print('Ctrl+C received, closing...') # Start program main() Drugi program jest już większy - to aplikacja na Androida, która pozwala na podłączenie się do serwera i przesyłanie informacji o orientacji telefonu. Ta również dostępna jest w moim repozytorium, tylko tym razem trzeba kod już ściągnąć i przebudować w Android Studio. Efekt Końcowy efekt na zdjęciu będzie wyglądał marnie, dlatego przygotowałem krótki filmik prezentujący, jak uruchomić cały projekt i jakie są efekty jego działania: Wnioski Serwa są bardzo wygodne w montażu i obsłudze, ale niestety również mało precyzyjne. Do takiego prostego projektu nadają się świetnie, ale w warunkach produkcyjnych trzeba byłoby wymienić je na ciche i dokładne silniki bezszczotkowe - takie, jakie są używane w gimbalach. Platforma reaguje na specyficzne ułożenie komórki; dzieje się tak dlatego, że komórka obrót wokół osi pionowej wysyła jako odchylenie od północy (0 stopni to północ). Tymczasem platforma "nie wie", w którą stronę jest zwrócona. Aby projekt był bardziej uniwersalny, można zastosować jedno z dwóch rozwiązań: dodać czujnik orientacji do platformy i kompensować różnice albo zapamiętać ułożenie komórki podczas łączenia do serwera i uznać je za pozycję "zerową". Mojemu projektowi daleko oczywiście do zaprezentowanego rozwiązania w "Raporcie mniejszości", ale nie ukrywam, że dał mi sporo frajdy. Można wykorzystać go jako bazę do zdalnego sterowania położeniem kamery lub na przykład ramienia robota.
  20. 3 punkty
    Czytaj dokładnie co napisałem: w połączeniach komórkowych blokowane są połączenia przychodzące (inaczej: nie odpalisz serwera na komórce), a zewnętrzny serwer to VPS albo dedyk (a nie współdzielony serwer w firmie Kogucik S. A. gdzie masz dostęp do ograniczonej konfiguracji Apacza przes htaccess i nic poza tym). Nawet nie musisz mieć tunelu (wystarczy utrzymać połączenie TCP z jakimś sensownym heartbeatem żeby natujący router nie zapomniał kto się z kim połączył) no i oczywiście jakiś inteligentny soft na serwerze.
  21. 3 punkty
    Może zamiast się spierać kto ma więcej racji, warto byłoby wyjaśnić całe zamieszanie. Żadna metoda nie jest lepsza, ani jedynie słuszna. W przypadku Raspberry i Raspbiana znajdziemy gotowe narzędzie, czyli raspi-config, które można, a ale wcale nie trzeba używać. Natomiast na pewno warto zrozumieć jako ono działa. Otóż jest to prosty skrypt, kod odpowiedzialny za zmianę hasła (https://github.com/asb/raspi-config/blob/master/raspi-config) wygląda następująco: do_hostname() { if [ "$INTERACTIVE" = True ]; then whiptail --msgbox "\ Please note: RFCs mandate that a hostname's labels \ may contain only the ASCII letters 'a' through 'z' (case-insensitive), the digits '0' through '9', and the hyphen. Hostname labels cannot begin or end with a hyphen. No other symbols, punctuation characters, or blank spaces are permitted.\ " 20 70 1 fi CURRENT_HOSTNAME=`cat /etc/hostname | tr -d " \t\n\r"` if [ "$INTERACTIVE" = True ]; then NEW_HOSTNAME=$(whiptail --inputbox "Please enter a hostname" 20 60 "$CURRENT_HOSTNAME" 3>&1 1>&2 2>&3) else NEW_HOSTNAME=$1 true fi if [ $? -eq 0 ]; then echo $NEW_HOSTNAME > /etc/hostname sed -i "s/127.0.1.1.*$CURRENT_HOSTNAME/127.0.1.1\t$NEW_HOSTNAME/g" /etc/hosts ASK_TO_REBOOT=1 fi } Czyli jak pewnie widać, zmiana nazwy hosta to dwie linijki: echo $NEW_HOSTNAME > /etc/hostname sed -i "s/127.0.1.1.*$CURRENT_HOSTNAME/127.0.1.1\t$NEW_HOSTNAME/g" /etc/hosts A czy wolimy je wykonać z linii poleceń, skryptu czy gotowca, to już chyba bez różnicy.
  22. 3 punkty
    Hej, sprostowanie - obraz (i komendy) NIE wędruje przez internet - no chyba, że masz w dwóch różnych sieciach np smartphone jest w internecie mobilnym, a samochodzik w internecie domowym Opóźnienia sieć lokalna ~140ms Smartphone 4G, samochód sieć domowa ~170ms (jestem za Natem więc musiałem skorzytać z turn servera, który jest gdzieś w europie) i jako dowód filmik zmontowałem Czy da się szybciej - pewnie tak bo po różnicy opóźnień widać, że to największe opóźnienia generuje składanie obrazu przez RPI - więc pewnie kwestia buforowania.
  23. 3 punkty
    Witam, jest to mój pierwszy projekt, na którym uczyłem się nieco programowania ... a że w piwnicy leżał mi popsuty odkurzacz to postanowiłem go ożywić po swojemu. Odkurzacz który notabene dostałem jako gratis działał dosłownie 10 minut po czym nie dawał oznak życia. 1.Podwozie jest wykorzystane w 100% z oryginału, nie zmieniałem nic oprócz zrobienia miejsca na elektronikę. 2. Z oryginału wykorzystałem również zasilanie (czyli ogniwa Li-lon) wraz z ładowarką. Zasilanie było oryginalne 7.2 V 3. Elektronika - wykorzystałem Arduino UNO wraz z shield sterownika L293D do 4x silników DC lub 2x krokowych w sumie wykorzystałem taki bo taki miałem, trochę nad wyrost bo zostają nie wykorzystane (a może jeszcze nie wykorzystane) dwa wejścia pod silniki DC. Jako że zaczynałem od podstaw programowanie, przysporzyło mi to trochę problemów. Ale od czego jest forum Na początku udało mi się zrobić aby pojazd sam się poruszał i odbijając od przeszkód (za pomocą dwóch umieszczonych wyłączników krańcowych umieszczonych z przodu odkurzacza) zmieniał kierunek jazdy, nie działało to w 100% tak jak sobie to na początku założyłem, ze względu na ogromny brak wiedzy w programowaniu, ale jednak pierwsze efekty pracy zainspirowały mnie do dalszej pracy nad robotem. #include <AFMotor.h> AF_DCMotor motorP(1); // silnik prawy AF_DCMotor motorL(2); // silnik lewy #define zdL 9 #define zdP 10 void setup() { motorP.setSpeed(255); motorL.setSpeed(255); pinMode(zdP, INPUT_PULLUP); pinMode(zdL, INPUT_PULLUP); } void loop() { bool zderzakL = digitalRead(zdL) == HIGH; bool zderzakP = digitalRead(zdP) == HIGH; // jazda do tyłu if (zderzakL == LOW && zderzakP == LOW) { motorP.run(BACKWARD); motorL.run(BACKWARD); } // // skręt w prawo else if (zderzakL == LOW) { motorP.run(BACKWARD); motorL.run(FORWARD); } // skręt w lewo else if (zderzakP == LOW) { // delay(200); motorP.run(FORWARD); motorL.run(BACKWARD); } // jazda do przodu else { motorP.run(FORWARD); motorL.run(FORWARD); } } Z shelda wykorzystałem piny 9 oraz 10 do serwa jako sterowanie do krańcówek. Kolejną rzecz jaką chciałem zrobić i pobawić się było stworzenie możliwości sterowania odkurzaczem za pomocą bluetooth oraz telefonu z androidem. A więc jak tylko paczuszka ze sklepu pojawiła się w moim domu wraz z modułem bluetooth (2.1 XM-15B 3,3V/5V) postanowiłem działać dalej. Pierwszy problem to połączenie modułu bluetooth z płytką, musiałem dolutować w odpowiednie miejsca przewody aby móc komunikować się z arduino (Rx, Tx) jak również doprowadzenie zasilania. Jednak nie stanowiło to większego wyzwania, udało się za pierwszym razem. Następnie przyszedł czas na połączenie bluetooth z telefonem. Udało mi się to zrealizować również w dość szybkim czasie (wcześniej oczywiście przeglądałem różnego rodzaju poradniki, czy posty kolegów z forum). Przyszedł czas na aplikację do telefonu, jako że gotowe rozwiązania nie podobały się (a może bardziej ambicja wzięła górę) postanowiłem stworzyć coś własnego. Z pomocą przyszła stronka http://ai2.appinventor.mit.edu. Gdzie w sposób prawie że obrazkowy udało mi się zrobił własny interfejs z własna logiką. Przyszedł czas na oprogramowanie w Arduino wszystkich funkcji które chciałem uzyskać tj: możliwość ręcznego sterowania przełączania na tryb automatyczny sterowania prędkością silniczków Udało mi się to za pomocą kodu: #include <AFMotor.h> AF_DCMotor motorP(1); // silnik prawy AF_DCMotor motorL(2); // silnik lewy #define zdL 9 #define zdP 10 String data; void setup() { Serial.begin(9600); Serial.println("Test portu"); pinMode(zdP, INPUT_PULLUP); pinMode(zdL, INPUT_PULLUP); bool zderzakL = digitalRead(zdL) == HIGH; bool zderzakP = digitalRead(zdP) == HIGH; } uint8_t oP = 255; uint8_t oL = 255; int pierwszyStart = 1; void loop() { if (Serial.available() > 0) { delay(1); char znak = Serial.read(); data += znak; pierwszyStart = 2; ///////////// Prędkość silników ///////////// if (data == "X") { oP = oP + 1; } if (data == "x") { oP = oP - 1; } if (data == "Y") { oL = oL + 1; } if (data == "y") { oL = oL - 1; } ///////////// Prędkość silników ///////////// Serial.print("Prędkość silnika prawego: "); Serial.println(oL); Serial.print("Prędkość silnika lewego: "); Serial.println(oP); if (data == "G") { motorP.setSpeed(oP); motorL.setSpeed(oL); motorP.run(FORWARD); motorL.run(FORWARD); } if (data == "B") { motorP.setSpeed(oP); motorL.setSpeed(oL); motorP.run(BACKWARD); motorL.run(BACKWARD); } if (data == "L") { motorP.setSpeed(oP); motorL.setSpeed(oL); motorP.run(BACKWARD); motorL.run(FORWARD); } if (data == "R") { motorP.setSpeed(oP); motorL.setSpeed(oL); motorP.run(FORWARD); motorL.run(BACKWARD); } if (data == "S") { motorP.setSpeed(0); motorL.setSpeed(0); } if (data == "A") { bool zderzakL = digitalRead(zdL) == HIGH; bool zderzakP = digitalRead(zdP) == HIGH; motorP.setSpeed(oP); motorL.setSpeed(oL); // jeżeli oba zderzaki if (zderzakL == LOW && zderzakP == LOW) { motorP.run(BACKWARD); motorL.run(BACKWARD); delay(250); motorP.run(FORWARD); motorL.run(BACKWARD); delay(1150); } // skręt w prawo else if (zderzakL == LOW) { motorP.run(BACKWARD); motorL.run(BACKWARD); delay(100); motorP.run(FORWARD); motorL.run(BACKWARD); delay(100); } // skręt w lewo else if (zderzakP == LOW) { motorP.run(BACKWARD); motorL.run(BACKWARD); delay(100); motorP.run(BACKWARD); motorL.run(FORWARD); delay(100); } // jazda do przodu else { motorP.run(FORWARD); motorL.run(FORWARD); } } data = ""; } else { if (pierwszyStart == 1) { bool zderzakL = digitalRead(zdL) == HIGH; bool zderzakP = digitalRead(zdP) == HIGH; motorP.setSpeed(oP); motorL.setSpeed(oL); // jeżeli oba zderzaki if (zderzakL == LOW && zderzakP == LOW) { motorP.run(BACKWARD); motorL.run(BACKWARD); delay(250); motorP.run(FORWARD); motorL.run(BACKWARD); delay(1150); } // skręt w prawo else if (zderzakL == LOW) { motorP.run(BACKWARD); motorL.run(BACKWARD); delay(100); motorP.run(FORWARD); motorL.run(BACKWARD); delay(100); } // skręt w lewo else if (zderzakP == LOW) { motorP.run(BACKWARD); motorL.run(BACKWARD); delay(100); motorP.run(BACKWARD); motorL.run(FORWARD); delay(100); } // jazda do przodu else { motorP.run(FORWARD); motorL.run(FORWARD); } } } delay(50); } Na pewno nie jest on w 100% zgodny ze sztuką, ale nic dziwnego bo programowania się nie uczyłem. Jest to zlepek funkcji odnalezionych w internecie i przystosowanych do moich potrzeb. Szczerze chciałbym zobaczyć prawidłowy wygląd kodu Na tym chyba zakończę podsumowując że obiekt spełnił moje oczekiwania, a to jest chyba najważniejsze: mogę sterować robotem/odkurzaczem z telefonu przy włączeniu uruchamia się tryb automatyczny bez potrzeby uruchamiania aplikacji w telefonie możliwość włączania/wyłączania na tryb automatyczny z telefonu sterowanie robotem w trybie automatycznym (w przypadku chęci korekty kierunku jazdy) i poza nim odbijanie od przedmiotów Filmik prezentujący funkcjonalność automatycznej jazdy.
  24. 2 punkty
    na szczęście dostałem śrubokręt (znaczy ten... no... wkrętak), co prawda oranżady nie orwierałem ale śrubki wkręca całkiem fajnie
  25. 2 punkty
Tablica liderów jest ustawiona na Warszawa/GMT+02:00
×