Skocz do zawartości

Przeszukaj forum

Pokazywanie wyników dla tagów 'bluetooth'.

  • Szukaj wg tagów

    Wpisz tagi, oddzielając przecinkami.
  • Szukaj wg autora

Typ zawartości


Kategorie forum

  • Elektronika i programowanie
    • Elektronika
    • Arduino i ESP
    • Mikrokontrolery
    • Raspberry Pi
    • Inne komputery jednopłytkowe
    • Układy programowalne
    • Programowanie
    • Zasilanie
  • Artykuły, projekty, DIY
    • Artykuły redakcji (blog)
    • Artykuły użytkowników
    • Projekty - DIY
    • Projekty - DIY roboty
    • Projekty - DIY (mini)
    • Projekty - DIY (początkujący)
    • Projekty - DIY w budowie (worklogi)
    • Wiadomości
  • Pozostałe
    • Oprogramowanie CAD
    • Druk 3D
    • Napędy
    • Mechanika
    • Zawody/Konkursy/Wydarzenia
    • Sprzedam/Kupię/Zamienię/Praca
    • Inne
  • Ogólne
    • Ogłoszenia organizacyjne
    • Dyskusje o FORBOT.pl
    • Na luzie

Kategorie

  • Quizy o elektronice
  • Quizy do kursu elektroniki I
  • Quizy do kursu elektroniki II
  • Quizy do kursów Arduino
  • Quizy do kursu STM32L4
  • Quizy do pozostałych kursów

Szukaj wyników w...

Znajdź wyniki, które zawierają...


Data utworzenia

  • Rozpocznij

    Koniec


Ostatnia aktualizacja

  • Rozpocznij

    Koniec


Filtruj po ilości...

Data dołączenia

  • Rozpocznij

    Koniec


Grupa


Imię


Strona


TempX

  1. Swego czasu pokazywałem tu już joystick do Vice. Powiem tak: sprawdził się, idealny do grania w podróży czy w barze. Niestety - ma swoje wady. Przede wszystkim analogowy joystick nie daje "wyczucia". Poza tym zmiana konfiguracji wymagałaby przekompilowania programu - postanowiłem zrobić jego następcę. Tak więc przedstawiam: BlueShot-II Założenia były proste: Pełnowymiarowy mechanizm wraz z dwoma przyciskami Fire Symulowanie wciśnięć konkretnych klawiszy na klawiaturze BLE (najprostsza i chyba najlepsza forma emuuacji joysticka dla emulatora Vice) Prosty w obsłudze autofire Możliwość szybkiej zmiany podstawowych parametrów (port, zestawy klawiszy, parametry startowe autofire itp) Możliwość zaprogramowania kilku presetów. Zasilanie z akumulatora z możliwością podłączenia kabla USB do naładowania I co najważniejsze - jak najniższa cena. O konstrukcji mechanicznej nie ma co się rozpisywać. To zwykły chiński mechanizm i dwa typowe przyciski. Zresztą - jeśli ktoś będzie bardzo chciał (w co wątpię) mogę opublikować pliki stl i scad. Ciekawsza natomiast jest elektronika. Sercem urządzenia jet płytka ESP32 - Lolin32 Lite. Ponieważ ma możliwość podłączenia akumulatorka, na pokładzie ma ładowarkę a przede wszystkim cena poniżej 20 PLN z dostawą następnego dnia jest raczej atrakcyjna - wybór był chyba naturalny. Do programowania służą trzy klawisze: PORT - krótkie wciśnięcie pokazuje który port symuluje w danej chwili joystick. Przytrzymanie powyżej pół sekundy to zmiana portu AUTOFIRE - krótkie wciśnięcie to włączenie/wyączenie autofire, przytrzymanie to zmiana okresu (od 100 to 1000 msec). PROGRAM - krótkie wciśnięcie zmienia bieżące parametry, przytrzymanie włącza edycję głównych opcji. Dwie diody służą do pokazania stanu. Dioda AUTOFIRE pali się cały czas jeśli autofire jest wyłączony, migocze jeśli autofire jest włączony zgodnie z ustawionym okresem. Dioda BLE pali się jeśli joystick jest połączony z hostem, migocze z częstotliwością 1 HZ jeśli nie. Trzecia możlliwość (krótkie błyski raz na sekundę) oznaczają pracę w trybie Serial (o tym później). Dodatkowo mały wyświetlacz OLED 128x32 służy do wyświetlania różnych ważnych informacji - np. bieżącego portu, stanu autofire - oraz jako monitor przy programowaniu. Do elektroniki dochodzi jeszcze mała pamięć EEPROM (nie chciałem ryzykować, bo zapisy mogą być dość częste i poleganie na bibliotece Preferences mogłoby - choć to mało prawdopodobne - skończyć się smętnie). Ponieważ pamięć typu 24C01 kosztowała mnie poniżej złotówki - po prostu podkleiłem ją (obudowa SOT-8 jest raczej płaska) kropelką pod spodem Lolina i przylutowałem kynarem do pinów. Jako że ESP32 pozwala na dużą dowolność jeśli chodzi o przydział pinów - postarałem się, aby te podłączone do konkretnych elementów znalazły się obok siebie (np. joystick i klawisze Fire podłączone są do sześciu kolejnych pinów ESP, podobnie reszta). Zresztą - układ połączeń (no, ciężko to nazwać schematem ale powinno być zrozumiałe) wygląda tak: Wyjaśnię od razu jedną rzecz. Ponieważ gniazdo akumulatora jest umieszczone dość niewygodnie, podlutowałem po prostu przewody akumulatora bezpośrednio do płytki, w tym miejscu: Teoretycznie powinienem w ogóle usunąć gniazdo akumulatora - ale po pierwsze w niczym mi ono nie przeszkadza, a możliwe jest jego wysłonięcie odpowiednio modyfikując obudowę. Wracając do pinów - takie rozmieszczenie pozwoliło mi po prostu wlutować gniazda bezpośrednio do płytki, bez konieczności projektowania i trawienia PCB. Szerokość obudowy jest wystarczająca, aby można było zastosować takie gniazda kątowe. Przejdę więc do programu. Przełączenie za pomocą klawiszy Port lub Autofire powoduje zapis do EEPROM -u (po starcie ostwarzany jest ostatni stan). Możliwości bieżących ustawień są następujące: Port - 1 lub 2 Autofire - włączenie / wyłączenie Autofire mode - still (działa cały czas) lub press (strzelanie seriami) Autofire period - okres powtarzania: 100, 150, 200, 250, 300, 400, 500, 650, 800 lub 1000 msec Swap fire - zamiana Fire i Fire2 (jeśli Fire2 jest w zestawie klawiszy) Keyset1 - wybrany jeden z siedmiu zaprogramowanych zestawów (Numpad i sześć programowalnych) dla portu 1 Keyset2 - to samo dla portu 2 Dirs - 8 lub 4 kierunki. W trybie 4 kierunków pozycje pośrednie nie (np Up-Right) nie są przekazywane, w ich miejsce jest przekazywana ostatnia z pozycji (w tym przypadku Up lub Right). Name - jedna z dwóch nazw pod którymi przedstawia się joystick. Copy from - skopiowanie ustawień z jednego z 5 programowapnych presetów. Wciśnięcie klawisza PROGRAM spowoduje zapisanie opcji do EEPROM-u. Wciśnięcie Fire2 oznacza anulowanie operacji. Możliwości ustawień głównych opcji to: Keyset (1 lub 2): ustawienie klawiszy przypisanych do joysticka. Można ustawić 4 (tylko podstawowe kierunki) lub 8 (również kierunki pośrednie). Jeśli pośredni kierunek nie będzie ustawiony, joystick zasymuluje wciśnięcie dwóch klawiszy (np. Up i Right). Jeśli Fire2 nie będzie zaprogramowany, będzie działać po prostu jak równoległy przycisk Fire. Name (1 lub 2) - możliwość ustawienia obu nazw. Maksymalna długość to 15 znaków (litery, cyfry, podkreślnik, myślnik, spacja) Preset (1 do 5) - predefiniowany zestaw opcji. Opcje są identyczne jak w bieżących ustaawieniach, tyle że zamiast "skopiuj z presetu" jest "skopiuj bieżące ustawienia". Dodatkowo istnieje możliwość zaprogramowania nazwy presetu (max 4 znaki). STORE - zapisanie do EEPROM-u CANCEL (lub Fire2) anulowanie operacji. Klawisze Port i Autofire mają jeszcze jedną funkcję: wciśnięcie obu na ponad pół sekundy spowoduje przejście wyświetlacza i mikrokontrolera w stan uśpienia. Przydaje się to przy ładowaniu akumulatora (wyłącznik musi być w pozycji "włączony") - mikrokontroler i wyświetlacz praktycznie w porównaniu z prądem ładowania nie pobierają prądu. Wyjście ze stanu uśpienia poprzez wciśnięcie Fire. Mógłbym na tym zakończyć: kompletny kod jest w załączniku, potrzebne są dodatkowe biblioteki dla Arduino: Bounce2 (z managera bibliotek) ESP32-BLE-Keyboard (z githuba: https://github.com/T-vK/ESP32-BLE-Keyboard) I2C-EEPROM (z managera bibliotek) Adafruit_SSDF1306 i Adafruit_GFX (z managera bibliotek) Skompilowany program zapewne będzie działać, ale można działanie poprawić. W tym celu należy: z biblioteki Bounce2 skopiować do folderu szkicu pliki Bounce2.h i Bounce2.cpp W pliku Bounce2.cpp odkomentować linię: //#define BOUNCE_WITH_PROMPT_DETECTION Najlepiej zrobić to przed pierwszą kompilacją programu, aby builder Arduino nie próbował użyć biblioteki z cache. Powinno to poprawić szybkość reakcji joysticka. Niestety - jest tu pewna niedogodność: nie można podłączyć joysticka do komputera, który nie ma BlueTooth. Oczywiście jedną z opcji jest dokupienie dongla, ale przynajmniej w przypadku Linuksa znalazłem rozwiązanie. Uruchomiony na Linuksie programik joyport.py zamieni przychodzące przez serial numery klawiszy na odpowiednie kody i "wstrzyknie" je do kolejki zdarzeń. Jako parametr można podać urządzenie (np. /dev/ttyUSB0) lub identyfikator USB (prawdopodobnie będzie to 1A86:7523). Joystick wwykryje uruchomienie drivera i odpowiednio zareaguje - zasygnalizuje błyskami diody podłąćzenie Serial, wyśle przez bluetooth informację "wszystkie klawisze puszczone" i dopóki driver będzie uruchomiony, nie będzie przekazywać nic na bluetooth. Do uruchomienia programu potrzebne są moduły python3-serial i python3-evdev (nie są instalowane domyślnie, ale można je doinstalować np. przez apt). I to by było na tyle. Źródła programu i program w załączniku: vicestk.zip W razie pytań jestem do dyspozycji - ale teraz muszę kończyć bo Giana czeka! 🙂
  2. Mam problem z podłączeniem do arduino mega modułu HC-06, w moim układzie mam 2 silniki i jeszcze będę musiał dodać 6 serwomechanizmów co zajmie mi wszystkie piny PWM a mój moduł bluetooth z jakiegoś powodu działa tylko na pinach 2-13. Jak to naprawić? #include <SoftwareSerial.h> #define BT_TX 0 #define BT_RX 1 SoftwareSerial bt(BT_TX, BT_RX); char x; void setup() { dht.begin(); pinMode(2,OUTPUT); pinMode(4,OUTPUT); pinMode(5,OUTPUT); pinMode(7,OUTPUT); bt.begin(9600); } void loop() { digitalWrite(3,255); digitalWrite(6,255); if(bt.available()){ x = bt.read(); bt.println(x); } if(x == 'B'){ digitalWrite(4,HIGH); digitalWrite(5,HIGH); } else if(x == 'F'){ digitalWrite(2,HIGH); digitalWrite(7,HIGH); } else if(x == 'L'){ digitalWrite(2,HIGH); digitalWrite(5,HIGH); } else if(x == 'R'){ digitalWrite(7,HIGH); digitalWrite(4,HIGH); } else if(x == 'S'){ digitalWrite(2,LOW); digitalWrite(4,LOW); digitalWrite(5,LOW); digitalWrite(7,LOW); } delay(100); }
  3. Cześć. 🙂 Przedstawiam wam Small Autonomous Amateur Rover "Romek" - czyli owoc mojej, z założenia kosmetycznej, metamorfozy robota, którego można poznać w jednym z forbotowych kursów. (A ponieważ robiłem tylko w wolnych chwilach, których wielu nie mam, to niczym ciąża - zacząłem z końcem listopada, mamy narodziny z końcem sierpnia). Krótki zarys historyczny: Kilka lat temu miałem fazę, zakupiłem w Botlandzie kilka zestawów do kursów oraz tu i ówdzie trochę rzeczy do szuflady "przydasiów". Życie jednak weryfikuje i przez kilka lat zbierało kurz, aż w zeszłym roku przeszedłem w końcu kurs budowy robotów i kurs Arduino poziom I. Jednak chciałem przede wszystkim sterować robotem przez BT, do tego chciałem pozbyć się w jakiś sposób wężykowania. Odnalazłem info, że komunikacja z BT to w zasadzie komunikacja przez port szeregowy - zapiąłem HC-05, zainstalowałem aplikację Bluetooth RC Car i napisałem switch case pod dane wysyłane z tej apki. Pierwsza rozbudowa "forbociaka" - moduł HC-05 i konwerter poziomów logicznych. Robot jeździł sterowany przez BT i tyle. Podjąłem decyzję, że dokonam modyfikacji zarówno w kodzie, jak i wyglądzie - z tym ostatnim poszedł też warunek, tylko rzeczy z szuflady, żadnych nowych inwestycji - własny czelendż ruszył. Posiadałem podwozie typu T100, które miało silniki z enkoderami - pomyślałem, że super, bo te silniczki z kursu to mogłyby mieć problem z ruszeniem cięższej konstrukcji, ponadto różny typ osi sprawił, że nawet nie próbowałem z nimi rzeźbić. Początkowa radość minęła wraz z przeczytaniem specyfikacji - maksymalny prąd pracy dołączonych silników to 4,5A, zdecydowanie za dużo na shield od Forbota. Przekopywałem szufladę dalej, znalazłem w niej silniczki N20, ale to maluszki, no i oś za mała. Znalazłem także silniki DFRobot o odpowiedniej osi i punktach montażowych. Przeczytałem notę - 7,5V, prąd pracy 50mA, maks. prąd 600 mA, przekładnia 99:1 - zostały wybrane. Nie chciałem mieć elektroniki na zewnątrz, więc potrzeba było też obudowy. Na wstępie wybrałem Kradex Z125 na body i Kradex Z130 na czujnik odległości. Jednak wraz z rozbudową, wybrana obudowa okazała się za ciasna - ledwo się zamykała, a nie założyłem jeszcze wszystkiego, co chciałem. Dodatkowo chciałem odzyskać pewne piny Arduino, które zajmował shield, a których nie potrzebowałem (przycisk i odbiornik IR). Podjąłem decyzję o zmianie obudowy - miałem jeszcze Kradex Z112, która była szersza i nieco wyższa. Poprzednia obudowa wchodziła pomiędzy gąsienice, przy tej musiałem zastosować dystanse, żeby zamocować budę do podwozia i nie kolidować z gąsienicami. Dodałem płaski koszyk na 6 baterii AA, krańcówki dla jazdy autonomicznej, połączone po dwie równolegle - żeby pokryć jak najwięcej czoła i jednocześnie nie odchylać blaszek pod dużym kątem i nie dodawać wąsów z trytytek - i wyłącznik kołyskowy, żeby załączać zasilanie z zewnątrz. Kanapkę Arduino+shield rozdzieliłem i połączyłem je przewodami, odzyskując wspomniane wcześniej piny cyfrowe 2 i 3 oraz uzyskując dostęp do pinu 3,3 V. Obudowę przed dalszymi pracami pomalowałem. Żeby robot nie był tylko sterowanym autkiem, dodałem oczywiście czujnik odległości HC04-SR, czujnik temperatury i wilgotności DHT22 oraz dzielnik napięcia - zbudowany z rezystora 510k i dwóch 68k - dla pomiaru napięcia baterii. Profesjonalny dzielnik amatorski. 😉 Na koniec dodałem LED-y w oprawkach. 4 białe jako światła czołowe, każdy z rezystorem 1k. 2 zielone i 2 czerwone jako światła pozycyjne/nawigacyjne - również z rezystorami 1k. 2 żółte drogowe (już nie żółte, jeszcze nie pomarańczowe) jako światła ostrzegawcze, oczywiście z rezystorami 1k. 1 niebieski jako światło sygnalizujące jazdę autonomiczną, z rezystorem 330 Ohm. Niebieski LED jest zasilany i załączany bezpośrednio z Arduino. Pozostałe LED-y zasilane są z baterii i załączane przez tranzystory NPN BC548. Ostatecznie wyszło trochę makaronu z przewodów, ale nie jest ciasno, obudowa zamyka się dobrze, a ja mam w razie W spis przewodów, a te z górnej części, które są wpięte w Arduino są także opisane na wtykach. :) Ponieważ żółte ledy miałem tylko typu clear i ich światło było widoczne tylko na wprost soczewki, dodałem dyfuzory zrobione ze... słomki. 😄 Romek po montażu waży ok. 1290 g i prezentuje się tak: Oprogramowanie: Założyłem, że chcę się pozbyć delay(), żeby nie kolidować z DHT oraz żeby robot reagował natychmiast na polecenia. Czasami musiałem się naklikać zanim robot zareagował. Czujnik odległości był jedną z prostszych rzeczy. Zastosowałem bibliotekę New Ping, dla której utworzyłem obiekt: NewPing sonar(trigPin, echoPin, MAX_DISTANCE); Sama funkcja wygląda tak: int sonarDystans() { int dystans = sonar.ping_cm(); // Wykonanie pomiaru i zapisanie wyniku w zmiennej distance w centymetrach return dystans; } A jej wykorzystanie na przykład tak: if (sonarDystans() <= doPrzeszkody) { //Jeżeli w zadanej odległości jest przeszkoda obecnyStan = ZATRZYMAJ; //Przejdź do zatrzymania czasStanu = millis(); //Ustaw czas dla timera serwo.attach(SERWO_PIN); //Podłącz serwo } Najwięcej problemów miałem z przepisaniem logiki jazdy autonomicznej. Poziom mojej wiedzy to kurs robota, kurs Arduino I i na coś tam liźnięte o DHT i millisach. Tutaj nawet zatrudniłem forumowiczów do pomocy: Ostatecznie oryginalną logikę wymieniłem na maszynę stanów, gdzie w danym stanie wywołuję funkcję, a dopiero w funkcji mam opisane zachowanie robota. switch (obecnyStan) { case PROSTO: prosto(); break; case ZATRZYMAJ: zatrzymaj(); break; void zatrzymaj() { zatrzymajSilniki(); if (millis() - czasStanu >= 500UL) { //Odczekaj zadany czas obecnyStan = PATRZ_PRAWO; //Przejdź do wykrywania przeszkody po prawej czasStanu = millis(); } } W przypadku krańcówek musiałem dodać flagę dla kolizji, gdyż bez tego po wjechaniu w przeszkodę robot się zatrzymywał. Zapewne zanim zdążył przejść dalej program ponownie docierał do miejsca, gdzie natrafiał co zrobić po załączeniu krańcówki. Dodanie flagi sprawiło, że problem zniknął. boolean kolizjaPrawo = false; if (digitalRead(prawySensor) == LOW && kolizjaPrawo==0) { //Jeżeli przeszkoda po prawej kolizjaPrawo = 1; obecnyStan = COFAJ_PRAWY; czasStanu = millis(); } void cofajPrawy() { lewySilnik(-70); prawySilnik(-70); if (millis() - czasStanu >= 800UL) { obecnyStan = ZATRZYMAJ2; //Przejdź do wykrywania przeszkody po prawej czasStanu = millis(); kolizjaPrawo = 0; } } Samo wejście w jazdę autonomiczną również realizowane jest zmianą flagi. W switch case dle odczytu z seriala/BT poczyniłem toggleswitch. case 'A': jazdaAutonomiczna = !jazdaAutonomiczna; if (!jazdaAutonomiczna) { zatrzymajSilniki(); ekspander.digitalWrite(LEDjazda, 0); serwo.detach(); } break; Nie ukrywam, że obsługę DHT podejrzałem w drugiej części kursu do Arduino, zanim tam dotrę, ale jak już wiemy, unikam delay(). Na podstawie obsługi czujnika z kursu i tego co wiem o millisach, napisałem funkcję po swojemu. Dodałem też korektę odczytów, gdyż względem czujnika referencyjnego temperatura była zawyżana o wilgotność zaniżana. Najpierw próbowałem korekty procentowej, ale ostatecznie wprowadziłem sztywną korektę. Względem czujnika referencyjnego odczyty nie odbiegają o więcej niż 0,5 stopnia i 0,5%. W tym miejscu dodałem także odczyt z ADC, gdzie doprowadziłem wyjście z dzielnika napięcia dla baterii. Dla napięcia baterii 9,66 V napięcie doprowadzone z dzielnika wynosiło ok. 0,95 V. Po wstępnym obliczeniu mnożnika, ostateczną wartość dobrałem empirycznie. Rozbieżność nie przekracza 0,1 V, średnio jest to 0,06 V. W funkcji tej następuje także wysyłanie danych na serial. void humitemp () { //Funkcja czujnika DHT22 i pomiar napięcia float wilgotnosc = dht.getHumidity(); //Pobierz info o wilgotności do zmiennej float temperatura = dht.getTemperature(); //Pobierz info o temperaturze do zmiennej float wilgKorekta = wilgotnosc + 1.11; //Korekta dla odczytu wilgotności float tempKorekta = temperatura - 2.35; //Korekta odczytu temperatury int adc_val = analogRead(bateria); //Odczytaj wartość ADC float Ubat = adc_val * 0.0485340314; //Wylicz wartość napięcia czasDHT = millis(); //Pobierz aktualny czas Arduino roznicaDHT = czasDHT - odmierzDHT; if (roznicaDHT >= 2000UL) { //Jeżeli różnica wyniesie 2000 ms lub więcej odmierzDHT = czasDHT; //Zapisz aktualny czas arduino do zmiennej if (dht.getStatusString() == "OK") { //Jeżeli czujnik zwróci wartość ok, wykonaj poniższe Serial.print(tempKorekta); Serial.print(" °C"); Serial.print("|"); Serial.print(wilgKorekta); Serial.print(" %"); Serial.print("|"); Serial.print(Ubat); Serial.println(" V"); } } } Wspomniałem wcześniej, że odzyskałem niektóre piny z Arduino. Zależało mi zwłaszcza na pinie PWM dla świateł pozycyjnych. W prototypie używałem pinu ekspandera w trybie włącz-wyłącz, a pulsowanie osiągałem przez zastosowany kondensator, jednak nie dawało to pełnej kontroli. Uwolniony pin PWM wykorzystałem właśnie do świateł pozycyjnych. Zmienna kierunek ma wartość 1 lub -1, zatem wartość PWM jest zwiększana lub zmniejszana. Kiedy wartość PWM osiąga 0 lub 255 wartość zmiennej kierunek zostaje przemnożona przez -1 powodując zmianę jej wartości na przeciwną. void swiatlaPuls() { aktualnyCzasPWM = millis(); // Obsługa narastania i opadania PWM if (aktualnyCzasPWM - poprzedniCzasPWM >= interwalZmianyPWM) { poprzedniCzasPWM = aktualnyCzasPWM; wartoscPWM += kierunek; //Zmniana wartości PWM zależna od wartości kiereunku if (wartoscPWM >= 255 || wartoscPWM <= 0) { if (aktualnyCzasPWM - poprzedniCzasAnimacji >= interwalZmianyKierunku) { poprzedniCzasAnimacji = aktualnyCzasPWM; kierunek *= -1; // Zmiana kierunku narastania/opadania } } analogWrite(pulsLED, wartoscPWM); } } Dla świateł ostrzegawczych chciałem osiągnąć efekt szybkich mignięć wplecionych we włączanie i wyłączanie (włącz, zapulsuj, wyłącz, powtórz). Pożądane zachowanie uzyskałem stosując switch case i zmienną dla licznika i zmieniając zachowanie świateł w zależności od jej wartości. void swiatlaStrobo() { czasLEDstrobo = millis(); switch(licznikStrobo) { case 0: digitalWrite(stroboLED, 1); if (czasLEDstrobo - czasStrobo >= 700UL) { digitalWrite(stroboLED, 0); czasStrobo = czasLEDstrobo; licznikStrobo ++; } break; case 13: digitalWrite(stroboLED, 0); if (czasLEDstrobo - czasStrobo >= 500UL) { digitalWrite(stroboLED, 0); licznikStrobo ++; } break; default: if (czasLEDstrobo - czasStrobo >= 50UL) { czasStrobo = czasLEDstrobo; stanStrobo = !stanStrobo; digitalWrite(stroboLED, stanStrobo); licznikStrobo ++; } break; } if (licznikStrobo > 13) { licznikStrobo = 0; } } Na koniec moja świeżynka. Poznałem operator trójargumentowy, zauważyłem, że dla mnie - tego amatora przed monitorem - działa podobnie do if else, zatem przepisałem logikę odpowiedzialną za silniki. Dotychczas używałem oryginalnej z kursu, po poznaniu tego operatora powstało coś takiego: void lewySilnik (int VL) { if (VL == 0) return; //Jeżeli wartość VL jest równa zero to nie wykonuj funkcji int kierunekLewySilnik = (VL > 0) ? 0 : 1; //Jeżeli wartość VL jest większa od 0 to ustaw wartość 0 (jazda do przodu), jeżeli mniej to ustaw 1 (do tyłu) int vlMap = map(abs(VL), 0, 100, 0, PWM_MAX); //Przemapuj zakres PWM do zakresu 0-100, dla ujemnego VL zwróć wartość absolutną digitalWrite(L_DIR, kierunekLewySilnik); //Jazda do przodu, albo do tyłu :) analogWrite(L_PWM, vlMap); //Ustaw zadaną prędkość } Komunikacja - software: Robot jest częściowo zgodny z aplikacją o której wspomniałem na początku (sterowanie, załączanie świateł co drugi kllik), ale gotowa apka nie do końca spełnia moje oczekiwania. Można też sterować przez aplikację typu BT serial monitor, ale to też nie do końca to - choć tutaj już odbieram dane. Postanowiłem wyrzeźbić - to dobre słowo - aplikację w APP Inventorze. O ile w sekcji bloczkowej jakoś to poszło, to graficznie naprawdę była to rzeźba. Predefiniowane rozdzielczości są przedpotopowe, a i responsive nie do końca daje to, czego człowiek oczekuje. Ale, potrzebowałem jednej apki, więc postanowiłem się przemęczyć, zamiast podejmować naukę tworzenia od podstaw w jakimś ludzkim środowisku. W pierwszej wersji odbierałem temperaturę i wilgotność, napis "connect" był tylko etykietą. W drugiej odbieram jeszcze wartość napięcia. Przyciski kierunkowe to przód, tyłu, obroty w miejscu w prawo, w lewo. Dodatkowo w narożnikach przyciski przywołują jazdę po łuku w daną stronę (prawy przód, lewy tył itp). Przycisk H wyzwala impuls buzzerem. Przycisk Światła uruchamia światła. Zmienna w robocie sprawia, że po kolei uruchamiane są: światła pozycyjne i ostrzegawcze, z drugim wywołaniem dochodzą światła frontowe, z trzecim wywołaniem gaszone są pozycyjne i ostrzegawcze, pozostają frontowe. Czwarte wywołanie resetuje zmienną i gasi wszystkie światła. Przycisk Auto włącza lub wyłącza tryb jazdy autonomicznej. Podsumowanie Zdaję sobie sprawę, że kod nie jest idealny, zwłaszcza, że wiele rzeczy znałem po łebkach, niektórych uczyłem się w trakcie. Ale jestem zadowolony - coś, co miało być tylko dodaniem sterowania BT zmieniło się w duży jak dla mnie projekt, który robiony po godzinach ostatecznie działa. 😄 Co dalej? Wyciągnę zasilanie jakoś zasilanie na zewnątrz. Zastosowana obudowa sprawia, że aby ją odkręcić, muszę ściągać gąsienice w celu uzyskania dostępu do śrub. To ze zwykłej wymiany baterii, czy przyszłych zmian w oprogramowaniu, zamienia rutynę w procedurę. 😉 W drugiej części kursu Arduino widziałem czujnik ruchu, więc pewnie też go jakoś zatrudnię - zamysł taki, że w trybie auto będzie sobie oczekiwał i uruchamiał jazdę po wykryciu ruchu. A ponieważ szuflada zawiera jeszcze jednego HC-05, jakiegoś klona Nano i wyświetlacz OLED, mam w planie zrobić sprzętowy kontroler dla tego robota. 😄 Co to za antenka? To tylko ozdoba - zabieram Romka ze sobą na ERC w tym roku - będzie maskotką. 😄 Jaki koszt konwersji? Dla mnie żaden, jeżeli uznajemy, że co w szufladzie to 0 zł. Jeżeli ktoś by chciał iść w moje ślady, to myślę, że kilka stówek. Podwozie jest najdroższe. Ale jak już ktoś ma wydawać pieniądze na konwersję, to lepiej na budowę od podstaw i zrezygnować z tego shielda, na rzecz sterownika, który uciągnie silniki 4,5A - wtedy nie trzeba szukać silników, które ogarnie shield i parę zł zostaje. 😉 Osobiście, gdyby nie postanowienie zrobienia tego bez dodatkowych nakładów, to pewnie też bym dokupił kilka rzeczy, rezygnując z shielda forbotowego, ale czelendż to czelendż. Dotarłeś tutaj? No to zobacz krótki filmik. 🙂 Podjazd miał nachylenie ok. 30 stopni. A tutaj cały potworek 😅 //Załączenie bibliotek #include "DHT.h" //Czujnik temperatury i wilgotności #include "Servo.h" #include "Adafruit_MCP23008.h" //Ekspander portów #include <NewPing.h> //Obsługa HC-SR04 //Ekspander Adafruit_MCP23008 ekspander; //Deklaracje i zmienne dla DHT i pomiaru napięcia #define DHT22_PIN 7 //Pin sygnału z DHT DHT dht; //Utworzenie obiektu dla czujnika #define bateria A3 unsigned long czasDHT = 0; unsigned long odmierzDHT = 0; unsigned long roznicaDHT = 0; //Deklaracje serwomechanizmu Servo serwo; #define SERWO_PIN 11 //Pin sygnału sterującego PWM int idle = 84; //Neutralna pozycja dla serwa //Deklaracje mostek H #define L_PWM 5 //Pin prędkości lewego silnika #define L_DIR 4 //Pin kierunku lewego silnika #define R_PWM 6 //Pin prędkości prawego silnika #define R_DIR 9 //Pin kierunku prawego silnika #define PWM_MAX 210 //Maksymalne wypełnienie dla silnika 7,5V przy zasilaniu 9V //Deklaracje i definicje do obsługi buzzera #define BUZZER 10 unsigned long aktualnyCzasBuzzer = 0; unsigned long czasStartuBuzzer = 0; unsigned long czasTrwaniaBuzzer = 200; // Czas trwania impulsu w milisekundach boolean buzzerON = false; //Deklaracje i zmienne czujnika odległości i wykrywania przeszkód #define LEDjazda 0 //LED informujący o jeździe autonomicznej na 0 pinie ekspandera!!! #define lewySensor A0 //Krańcówka po lewej #define prawySensor A1 //Krańcówka po prawej #define trigPin 12 //Pin nadawczy (szary) #define echoPin 13 //Pin odbiorczy (biały) #define MAX_DISTANCE 200 // Maksymalny zasięg w centymetrach NewPing sonar(trigPin, echoPin, MAX_DISTANCE); //Inicjalizacja obiektu sonar z użyciem biblioteki NewPing const int doPrzeszkody = 25; //Odległość wykrywania przeszkody w cm //Wyliczenie stanów dla jazdy autonomicznej enum States { PROSTO, PATRZ_PRAWO, OBROT_PRAWO, PATRZ_LEWO, OBROT_LEWO, ZATRZYMAJ, ZATRZYMAJ2, COFAJ, COFAJ_LEWY, COFAJ_PRAWY, }; boolean jazdaAutonomiczna = false; boolean kolizjaPrawo = false; boolean kolizjaLewo = false; static States obecnyStan = PROSTO; //Domyślny stan unsigned long czasStanu = 0; //Zmienna dla timera stanu unsigned long czasDotyku = 0; //Zmienna dla timera krańcówek static unsigned long czasObrotu = 1100; //Zmienna dla czasu trwania obrotu //Definicje i zmienne dla świateł #define frontLED 1 //LEDy frontowe na 1 pinie ekspandera!!! #define stroboLED 2 #define pulsLED 3 int trybLED = 0; unsigned long czasStrobo = 0; unsigned long czasLEDstrobo = 0; int stanStrobo = 0; int licznikStrobo = 0; int stanPuls = 0; unsigned long poprzedniCzasPWM = 0; unsigned long poprzedniCzasAnimacji = 0; int wartoscPWM = 0; int kierunek = 1; // 1 - narastanie, -1 - opadanie unsigned long interwalZmianyPWM = 10; unsigned long interwalZmianyKierunku = 750; unsigned long aktualnyCzasPWM = 0; void setup() { //Konfiguracja ekspandera ekspander.begin(); ekspander.pinMode(LEDjazda, OUTPUT); //Konfiguracja świateł ekspander.digitalWrite(LEDjazda, LOW); pinMode(stroboLED, OUTPUT); digitalWrite(stroboLED, stanStrobo); pinMode(pulsLED, OUTPUT); analogWrite(pulsLED, stanPuls); ekspander.pinMode(frontLED, OUTPUT); ekspander.digitalWrite(frontLED, LOW); //Konfiguracja pinów mostka H pinMode(L_DIR, OUTPUT); pinMode(L_PWM, OUTPUT); pinMode(R_DIR, OUTPUT); pinMode(R_PWM, OUTPUT); //Konfiguracja pozostałych elementów pinMode(bateria, INPUT); //Odczyt ADC dla pomiaru napięcia baterii pinMode(lewySensor, INPUT_PULLUP); pinMode(prawySensor, INPUT_PULLUP); Serial.begin(9600); //Uruchomienie sprzętowej komunikacji UART dht.setup(DHT22_PIN); //Podłączenie czujnika do zadeklarowanego pinu serwo.attach(SERWO_PIN); //Podłączenie serwa do zadeklarowanego pinu serwo.write(idle); //Ustawienie serwa w domyślnej pozycji delay(200); //Opóźnienie dla ustabilizowania i przeczekania stanów nieustalonych serwo.detach(); //Odłączenie serwa //Konfiguracja buzzera i info o zakończeniu setupu pinMode(BUZZER, OUTPUT); digitalWrite(BUZZER, 1); ekspander.digitalWrite(LEDjazda, 1); delay(100); digitalWrite(BUZZER, 0); ekspander.digitalWrite(LEDjazda, 0); delay(100); digitalWrite(BUZZER, 1); ekspander.digitalWrite(LEDjazda, 1); delay(100); digitalWrite(BUZZER, 0); ekspander.digitalWrite(LEDjazda, 0); delay(100); } void loop() { humitemp(); //Wykonuj funkcje DHT if(jazdaAutonomiczna) { jazdaAuto(); } switch (trybLED) { case 0: analogWrite(pulsLED, 0); digitalWrite(stroboLED, 0); ekspander.digitalWrite(frontLED, 0); break; case 1: swiatlaPuls(); swiatlaStrobo(); ekspander.digitalWrite(frontLED, 0); break; case 2: swiatlaPuls(); swiatlaStrobo(); swiatlaFront(); break; case 3: analogWrite(pulsLED, 0); digitalWrite(stroboLED, 0); swiatlaFront(); break; case 4: trybLED = 0; break; } if (buzzerON) { klakson(); } if (Serial.available() > 0) { //Jeżeli są dostępne dane BT char jazda = Serial.read(); //Odczytaj te dane i przypisz do zmiennej switch(jazda) { //Wykonaj case zgodnie z odebranymi danymi case 'F': //Do przodu lewySilnik(95); prawySilnik(95); break; case 'B': //Do tyłu lewySilnik(-95); prawySilnik(-95); break; case 'S': //Zatrzymaj zatrzymajSilniki(); break; case 'L': //Obrót w lewo lewySilnik(-80); prawySilnik(80); break; case 'R': //Obrót w prawo lewySilnik(80); prawySilnik(-80); break; case 'G': //Lewy łuk do przodu lewySilnik(60); prawySilnik(95); break; case 'I': //Prawy łuk do przodu lewySilnik(95); prawySilnik(60); break; case 'H': //Lewy łuk do tyłu lewySilnik(-60); prawySilnik(-95); break; case 'J': //Prawy łuk do tyłu lewySilnik(-95); prawySilnik(-60); break; case 'V': //Impuls buzzerem buzzerON = !buzzerON; czasStartuBuzzer = millis(); break; case 'X': trybLED++; break; case 'A': jazdaAutonomiczna = !jazdaAutonomiczna; if (!jazdaAutonomiczna) { zatrzymajSilniki(); ekspander.digitalWrite(LEDjazda, 0); serwo.detach(); } break; } } } void lewySilnik (int VL) { if (VL == 0) return; //Jeżeli wartość VL jest równa zero to nie wykonuj funkcji int kierunekLewySilnik = (VL > 0) ? 0 : 1; //Jeżeli wartość VL jest większa od 0 to ustaw wartość 0 (jazda do przodu), jeżeli mniej to ustaw 1 (do tyłu) int vlMap = map(abs(VL), 0, 100, 0, PWM_MAX); //Przemapuj zakres PWM do zakresu 0-100, dla ujemnego VL zwróć wartość absolutną digitalWrite(L_DIR, kierunekLewySilnik); //Jazda do przodu, albo do tyłu :) analogWrite(L_PWM, vlMap); //Ustaw zadaną prędkość } void prawySilnik (int VR) { if (VR == 0) return; //Jeżeli wartość VL jest równa zero to nie wykonuj funkcji int kierunekLewySilnik = (VR > 0) ? 1 : 0; //Jeżeli wartość VR jest większa od 0 to ustaw wartość 1 (jazda do przodu), jeżeli mniej to ustaw 0 (do tyłu) int vrMap = map(abs(VR), 0, 100, 0, PWM_MAX); //Przemapuj zakres PWM do zakresu 0-100 digitalWrite(R_DIR, kierunekLewySilnik); //Jazda do przodu, albo do tyłu :) analogWrite(R_PWM, vrMap); //Ustaw zadaną prędkość } void zatrzymajSilniki() { analogWrite(L_PWM, 0); //Zatrzymaj lewy silnik analogWrite(R_PWM, 0); //Zatrzymaj prawy silnik } void humitemp () { //Funkcja czujnika DHT22 i pomiar napięcia float wilgotnosc = dht.getHumidity(); //Pobierz info o wilgotności do zmiennej float temperatura = dht.getTemperature(); //Pobierz info o temperaturze do zmiennej float wilgKorekta = wilgotnosc + 1.11; //Procentowa korekta dla odczytu wilgotności float tempKorekta = temperatura - 2.35; //Korekta odczytu temperatury int adc_val = analogRead(bateria); //Odczytaj wartość ADC float Ubat = adc_val * 0.0485340314; //Wylicz wartość napięcia czasDHT = millis(); //Pobierz aktualny czas Arduino roznicaDHT = czasDHT - odmierzDHT; if (roznicaDHT >= 2000UL) { //Jeżeli różnica wyniesie 2000 ms lub więcej odmierzDHT = czasDHT; //Zapisz aktualny czas arduino do zmiennej if (dht.getStatusString() == "OK") { //Jeżeli czujnik zwróci wartość ok, wykonaj poniższe Serial.print(tempKorekta); Serial.print(" °C"); Serial.print("|"); Serial.print(wilgKorekta); Serial.print(" %"); Serial.print("|"); Serial.print(Ubat); Serial.println(" V"); } } } int sonarDystans() { int dystans = sonar.ping_cm(); // Wykonanie pomiaru i zapisanie wyniku w zmiennej distance w centymetrach return dystans; } void swiatlaPuls() { aktualnyCzasPWM = millis(); // Obsługa narastania i opadania PWM if (aktualnyCzasPWM - poprzedniCzasPWM >= interwalZmianyPWM) { poprzedniCzasPWM = aktualnyCzasPWM; wartoscPWM += kierunek; //Zmniana wartości PWM zależna od wartości kiereunku if (wartoscPWM >= 255 || wartoscPWM <= 0) { if (aktualnyCzasPWM - poprzedniCzasAnimacji >= interwalZmianyKierunku) { poprzedniCzasAnimacji = aktualnyCzasPWM; kierunek *= -1; // Zmiana kierunku narastania/opadania } } analogWrite(pulsLED, wartoscPWM); } } void swiatlaStrobo() { czasLEDstrobo = millis(); switch(licznikStrobo) { case 0: digitalWrite(stroboLED, 1); if (czasLEDstrobo - czasStrobo >= 700UL) { digitalWrite(stroboLED, 0); czasStrobo = czasLEDstrobo; licznikStrobo ++; } break; case 13: digitalWrite(stroboLED, 0); if (czasLEDstrobo - czasStrobo >= 500UL) { digitalWrite(stroboLED, 0); licznikStrobo ++; } break; default: if (czasLEDstrobo - czasStrobo >= 50UL) { czasStrobo = czasLEDstrobo; stanStrobo = !stanStrobo; digitalWrite(stroboLED, stanStrobo); licznikStrobo ++; } break; } if (licznikStrobo > 13) { licznikStrobo = 0; } } void swiatlaFront() { ekspander.digitalWrite(frontLED, 1); } void jazdaAuto() { //Funkcja jazdy autonomicznej ekspander.digitalWrite(LEDjazda, 1); //Włącz LED informujący o jeździe autonomicznej switch (obecnyStan) { case PROSTO: prosto(); break; case ZATRZYMAJ: zatrzymaj(); break; case ZATRZYMAJ2: zatrzymaj2(); break; case PATRZ_PRAWO: //Wykrywanie przeszkód po prawej patrzPrawo(); break; case OBROT_PRAWO: //Skręt w prawo obrotPrawo(); break; case PATRZ_LEWO: //Wykrywanie przeszkód po lewej patrzLewo(); break; case OBROT_LEWO: //Skręt w lewo obrotLewo(); break; case COFAJ: cofaj(); break; case COFAJ_LEWY: cofajLewy(); break; case COFAJ_PRAWY: cofajPrawy(); break; } if (digitalRead(lewySensor) == LOW && kolizjaLewo==0) { //Jeżeli przeszkoda po lewej kolizjaLewo = 1; obecnyStan = COFAJ_LEWY; czasStanu = millis(); } if (digitalRead(prawySensor) == LOW && kolizjaPrawo==0) { //Jeżeli przeszkoda po prawej kolizjaPrawo = 1; obecnyStan = COFAJ_PRAWY; czasStanu = millis(); } } void prosto() { if (sonarDystans() <= doPrzeszkody) { //Jeżeli w zadanej odległości jest przeszkoda obecnyStan = ZATRZYMAJ; //Przejdź do zatrzymania czasStanu = millis(); //Ustaw czas dla timera serwo.attach(SERWO_PIN); //Podłącz serwo } else { //Jedź prosto lewySilnik(90); prawySilnik(90); } } void zatrzymaj() { zatrzymajSilniki(); if (millis() - czasStanu >= 500UL) { //Odczekaj zadany czas obecnyStan = PATRZ_PRAWO; //Przejdź do wykrywania przeszkody po prawej czasStanu = millis(); } } void zatrzymaj2() { zatrzymajSilniki(); if (millis() - czasStanu >= 500UL) { obecnyStan = PATRZ_LEWO; //Przejdź do wykrywania przeszkody po prawej czasStanu = millis(); } } void patrzPrawo() { serwo.write(25); //Ustw serwo w prawo if (millis() - czasStanu >= 400UL) { //Patrz przez zadany czas dla ustabilizowania serwa if (sonarDystans() > doPrzeszkody) { //Jeżeli nie ma przeszkód bliżej niż zadana odległość obecnyStan = OBROT_PRAWO; //Skręć w prawo czasStanu = millis(); //Ustaw czas dla timera } else { //Jeżeli jest przeszkoda obecnyStan = PATRZ_LEWO; //Przejdź do wykrywania przeszkody po lewej czasStanu = millis(); //Ustaw czas dla timera } } } void obrotPrawo() { lewySilnik(70); prawySilnik(-70); serwo.write(idle); //Ustaw serwo na wprost if (millis() - czasStanu >= czasObrotu) { //Skręcaj przez zadany czas serwo.detach(); obecnyStan = PROSTO; //Przejdź do jazdy na prosto czasStanu = millis(); //Ustaw czas dla timera } } void patrzLewo() { serwo.write(155); //Obróć serwo w lewo if (millis() - czasStanu >= 450UL) { //Patrz przez zadany czas dla ustabilizowania serwa if (sonarDystans() > doPrzeszkody) { //Jeżeli nie ma przeszkody w zadanej odległości obecnyStan = OBROT_LEWO; //Skręć w lewo czasStanu = millis(); //Ustaw czas dla timera } else { //Jeżeli jest przeszkoda obecnyStan = COFAJ; //Włącz alarm czasStanu = millis(); //Ustaw czas dla timera } } } void obrotLewo() { lewySilnik(-70); prawySilnik(70); serwo.write(idle); //Ustaw serwo na wprost if (millis() - czasStanu >= czasObrotu) { //Skręcaj przez zadany czas serwo.detach(); obecnyStan = PROSTO; //Przejdź do jazdy prosto czasStanu = millis(); //Ustaw czas dla timera } } void cofaj() { serwo.write(idle); //Ustaw serwo na wprost lewySilnik(-80); //cofaj prawySilnik(-80); if (millis() - czasStanu >= 800UL) { //Po upływie zadanego czasu zatrzymajSilniki(); //Zatrzymaj się obecnyStan = ZATRZYMAJ; //Przejdź do jazdy prosto czasStanu = millis(); //Ustaw czas dla timera } } void cofajLewy() { lewySilnik(-70); prawySilnik(-70); if (millis() - czasStanu >= 800UL) { obecnyStan = ZATRZYMAJ; //Przejdź do wykrywania przeszkody po prawej czasStanu = millis(); kolizjaLewo = 0; } } void cofajPrawy() { lewySilnik(-70); prawySilnik(-70); if (millis() - czasStanu >= 800UL) { obecnyStan = ZATRZYMAJ2; //Przejdź do wykrywania przeszkody po prawej czasStanu = millis(); kolizjaPrawo = 0; } } void klakson() { aktualnyCzasBuzzer = millis(); if (aktualnyCzasBuzzer - czasStartuBuzzer < czasTrwaniaBuzzer) { digitalWrite(BUZZER, HIGH); } else { digitalWrite(BUZZER, LOW); buzzerON = false; } }
  4. Witam Pisze ponieważ nie mogę poradzić sobie z błędem który dostaje podczas podłączania modułu bluetooth XM-15. Przeglądałem strony w poszukiwaniu jakieś pomocy nie udało mi się tego niestety znaleźć. Jestem nowy wiec odrazu rzuciłem się na głęboka wodę nie sprawdzając tego moduły. Konfiguracja polegała na tym że podłączyłem moduł do arduino i działało to ok. Podczas pisania programów miałem problem z uruchomieniem monitora portu szeregowego. Błąd mówił ze port jest zajęty. Zacząłem szukać po internecie co to może być i znalazłem ,że może to być poprostu złe dobrana prędkość. Więc spróbowałem ja zmieniać na 9600. Na forum jest pokazane jak zrobić to z modelem HC za pomocą polecenia AT. Napisane jest tam ze po wpisaniu AT powinno wyskoczyć " AT ok ". U mnie wyskakuje " Witaj AT ! ", pisałem jakiś prosty program który miał właśnie tak dziać, że pisze coś i on ma wyświetlać Witaj + "coś "+ !. Teraz napisałem prosty program aby wgl sprawdzić czy jakoś ten moduł mogę podłączyć i dostaje błąd problemu z wgrywaniem na płytkę. Wygląda on tak : avrdude: Version 6.3-20171130 Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/ Copyright (c) 2007-2014 Joerg Wunsch System wide configuration file is "C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.19.0_x86__mdqgnx93n4wtt\hardware\tools\avr/etc/avrdude.conf" Using Port : COM4 Using Programmer : arduino Overriding Baud Rate : 115200 avrdude: stk500_recv(): programmer is not responding avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0xe2 avrdude: stk500_recv(): programmer is not responding avrdude: stk500_getsync() attempt 2 of 10: not in sync: resp=0xe2 avrdude: stk500_recv(): programmer is not responding avrdude: stk500_getsync() attempt 3 of 10: not in sync: resp=0xe2 avrdude: stk500_recv(): programmer is not responding avrdude: stk500_getsync() attempt 4 of 10: not in sync: resp=0xe2 avrdude: stk500_recv(): programmer is not responding avrdude: stk500_getsync() attempt 5 of 10: not in sync: resp=0xe2 avrdude: stk500_recv(): programmer is not responding avrdude: stk500_getsync() attempt 6 of 10: not in sync: resp=0xe2 avrdude: stk500_recv(): programmer is not responding avrdude: stk500_getsync() attempt 7 of 10: not in sync: resp=0xe2 avrdude: stk500_recv(): programmer is not responding avrdude: stk500_getsync() attempt 8 of 10: not in sync: resp=0xe2 avrdude: stk500_recv(): programmer is not responding avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xe2 avrdude: stk500_recv(): programmer is not responding avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xe2 avrdude done. Thank you. Problem z wgrywaniem na płytkę. Program który wgrywam jest następujący : int data; void setup() { // put your setup code here, to run once: Serial.begin(115200); } void loop() { // put your main code here, to run repeatedly: data=Serial.read(); Serial.println(data); delay(200); } Jeśli odepnę wejścia TX, RX program działa normalnie i nie żadnego problemu. Po podłączeniu modułu tylko do zasilania i uruchomieniu terminala na telefonie po wpisaniu polecenie AT dostaje jakieś znaczki których nie można przeczytać. Używam Arduino Uno. Z góry przepraszam jeśli coś namieszałem jestem początkującym i to mój pierwszy problem którego nie mogę przejść. Proszę o pomoc
  5. Witam Mam pytanie odnośnie doboru części do robota. Sytuacja wygląda tak mam zakupione podwodzie do robota z kołami mecanum, silnikami DC z przekładnią jeden do 1:48, Napięcie zasilania 3V-6V, Pobór prądu 170 mA. W robocie mam zamiar użyć Arduino i sterować nim z telefonu przez Bluetooth. Pytanie pierwsze: Czy jeśli chce użyć sterowników L298N do sterowania silnikami to potrzebuję jakiś przetwornic step down, żeby nie spalić silników i sterowników, jeżeli wymagane źródło napięcia okazałoby się większe niż 6V? Pytanie drugie: Jakiego źródła zasilania najlepiej użyć do tego przedsięwzięcia? Pytanie Trzecie: Jakiego modułu Bluetooth użyć do tego najlepiej (chodzi mi o to żeby sterować silnikami z telefonu)? Widziałem że większość projektów z Arduino, bo korzysta z HC-05. Czy HC-05 to dobory wybór dla laika?
  6. Cześć, z zawodu jestem alpinistą przemysłowym i pracując na konstrukcji (ścierając kurz ) z racji już średniego wieku stwierdziłem, że będzie mi łatwiej, przyjemniej i ciekawiej jeżeli pomogę sobie jakimś pojazdem zdalnie sterowanym :). W sprawach elektroniki jestem raczej zielony, ale zacząłem i w miarę upływu czasu okazuje się, że można, i jest jakiś mglista szansa, że mi się uda :). Mózgiem operacji jest płytka PWM UNO, pojazd gąsienicowy z 2-ma silnikami 12V(chińskimi-brak jakichkolwiek informacji o prądzie maksymalnym). Sterownik silników to L293d, moduł bluetooth to HC-05. Sterowanie z komórki. Pojazd ma się poruszać po wąskiej konstrukcji ~20cm szerokości, która nachylona jest pod kątem +-45 stopni do poziomu, dlatego używam też magnesu pod spodem oddalonego o jakieś 5 mm od "gruntu". Magnes powoduje, że będę potrzebował sporej mocy, żeby poruszać się łazikiem. I tak rzeczy, o których wiem, że nie są ok to : 1. Sterownik silników powinien być ( w mojej ocenie ) mocniejszy-choć ten się jeszcze nie spalił, ale nie chcę ryzykować i chciałbym kupić inny ( pytanie jaki?) 2. Moduł bluetooth powinien przechodzić przez około 3,5V, u mnie jest 5V, ale nic się nie dzieje. 3. Kod jest bardzo toporny i mi się nie podoba 🙂 ale póki mi działa też się tym nie przejmuję. Nie radzę sobie z : Sytuacją, w której z jakiegoś powodu tracę połączenie z łazikiem, nie chcę żeby stanął i się zrestartował. Chciałbym też zamontować prosty wskaźnik (czerwoną diodę) do sygnalizacji spadku napięcia poniżej pewnego progu (potencjometr dioda i rezystor wystarczą?) Zasilanie- póki co 2 akumulatory połączone szeregowo 7,4V x 2. Na jednym też działa. Chciałbym nie przesadzić, wiem że jest spadek napięcia na sterowniku ale nie wiem do jakiego napięcia mogę dojść (pewnie już przesadziłem :)) Wszelkie informację o kardynalnych i nie tylko, błędach oczywiście mile widziane- pamiętajcie także, że jestem
  7. Cześć, chciałbym prosić o pomoc w kwestii podpięcia modułu Pmod BLE do płytki Zybo Z7-10. Opis projektu Chciałbym podłączyć Pmod BLE do płytki Zybo Z7-10. Chciałbym by testowa aplikacja mogła wysyłać i odbierać dane po bluetooth (do testowania chciałbym użyć jakiejś aplikacji z AppStore). Na początku mogłoby to być wysyłanie zwykłego ciągu znaków, jak np: "Cześć Zybo" i "Cześć telefon" czy coś podobnego. Próby podłączenia Znalazłem podobny przykład w intrnecie (tutaj -> link autorstwa osoby o nicku: ralphjy). Próbowałem odtworzyć projekt, który opisał w tym artykule jednak nie udało mi się to. Poniżej zamieszczam swój block diagram, który jest podobny do tego który prezentuje ralphjy. Dołączam jeszcze constraints mojego projektu. Niestety nie wiem jak dokładnie powinny być one podpięte. Na końcu problemu zamieszczam link do constraint dla Zybo. Oczywiście próbowałem wygenerować bitstreama, ale bezskutecznie :(. Może ktoś z Was miał już do czynienia z modułem Pmod BLE i byłby w stanie pomóc :)? Btw. dzięki wielkie za jakiekolwiek wskazówki! Sprzęt Zybo Z7-10 -> link Pmod BLE -> link Software Zybo-Z7 Constraints -> link pliki źródłowe Pmod BLE-> link
  8. cześć mamy do sprzedania moduł "Bluetooth module Telit Bluemod+S42" - wystawiamy FV Product condition: New - Packed (hermetically) on rolls of 1000 pieces Minimum quantity to sell: 2000pcsV The maximum quantity (available): 11,000 pcs. Cost for 1 pcs: 2,9 eur Delivery cost depends of ordered items General info: Bluetooth 4.2 Low Energy plug-and-play module The BlueMod+S42 is a high-performance Bluetooth 4.2 qualified single mode module. It features very low energy consumption and flexibility for designers such as Terminal I/O profile for serial cable replacement use cases as well as most GATT based Bluetooth profiles through a generic GATT implementation. Part of the BlueMod+Sx family, the BlueMod+S42 is swappable with previous generations without requiring new hardware or software spins. Although a single mode low energy module it offers a high throughput of up to 470kbit/s using Telit’s unique SPP like Terminal I/O service. Development Kit Telit’s BlueDev+S42 developer kits enables rapid prototyping of customer’s own firmware: solutions are based on a simple and powerful scripting language, Lua, supported by Telit Appzone development environment or using silicon vendor SDK for C++ development. Evaluation Kit The evaluation kits BlueEva+S42 are available to support Telit customers to evaluate and implement Bluetooth modules in their application. For each of the different FW Versions a separate Evaluation Kit is available. Key Features: BlueMod+S42 Standalone IOT platform or Bluetooth hosted applications Bluetooth v4.2 qualified module RED, FCC, IC, KC, MIC, RCM, Anatel certified Powerful Cortex M4F MCU Designed for low power applications Best of its class range performance Best of its class throughput performance Generic GATT Client or Server Implementation Point to point or point to multipoint communications Terminal I/O Profile (SPP-like) for fast and easy transparent data transfer Automation I/O Profile for digital and analog status information transfer Terminal I/O and Automation I/O Sample code for iOS and Android NFC Support for secure simple pairing LE Secure Connection with 128bit AES encryption
  9. Witam, mam mały problem z sterowaniem serwomechanizmem za pomocą modułów bluetooth HC-05. Wartością wysyłaną jest sygnał z czujnika zginania, jest on zmapowany. Łącząc to na jednym arduino wszystko śmiga jak powinno, czyli odpowiednio zginając czujnik - rusza się serwomechanizm o dany kąt. Problem pojawia się gdy próbuję wysłać ten sygnał za pomocą bluetooth (być może kod jest zły, zaczerpnięty z internetu, ale komuś podobno działało, wstawię niżej). Moje moduły bluetooth zaprogramowałem wydaje mi się prawidłowo, jest między nimi połączenie (lecz musiałem je programować na arduino uno, bo na nano po wpisywaniu komend nic się nie działo). Domyślnie były one na 9600 baud rate. Układ z arduino nano jest moim masterem. Zmapowany sygnał z czujnika zginania wziąłem pod monitor i widać takie wartości: M332 L330 J331 K330 J331 K330 J330 Moim zdaniem powinny być same liczby, a nie jakieś cyferki dodatkowo. (może tu jest problem?) Układ z arduino uno jest slavem i biorąc pod monitor watości dostarczone tutaj otrzymuje: 13 10 83 51 51 51 10 51 Więc jakby liczby są prawidłowe, ale strasznie one skaczą i zginanie czujnika nie skutkuje zmianą tych wartości. Oto kod dla MASTERA: int val1; int state=0; void setup() { Serial.begin(9600); } void loop() { if(Serial.available() > 0){ // Checks whether data is comming from the serial port state = Serial.read(); // Reads the data from the serial por } val1 = analogRead(A0); // reads the value of the potentiometer (value between 0 and 1023) int val1map = map(val1, 0, 400, 0, 180); // scale it to use it with the servo (value between 0 and 180) Serial.println(val1map); Serial.write(val1map); delay(10); } Oto kod dla SLAVE'a: #include <Servo.h> Servo kciuk; // create servo object to control a servo int state=20; void setup() { kciuk.attach(5); // attaches the servo on pins to the servo object Serial.begin(9600); } void loop() { if(Serial.available() > 0){ // Checks whether data is comming from the serial port state = Serial.read(); } kciuk.write(state); Serial.println(state); delay(10); } Może arduino nano jakoś inaczej trzeba łączyć z bluetoothem? Ja oba bluetoothy połączyłem tak: RX z bluetooth'a do TX na arduino, TX z blue do RX na arduino, GND wiadomo do GND na arduino, Vcc do 5V na arduino. Potrzebuje pilnie pomocy i z góry dziękuję za każdą wiadomość!
  10. Często wykorzystuje w swoich projektach bluetooth który przynajmniej dla mnie jest najprostszą i najlepszą formą komunikacji na małe odległości. Stąd też wpadłem na pomysł wykonania małego pilota bluetooth mniej więcej takiej wielkości żeby zmieścił się w całości w ręce i można go było obsłużyć jedną ręką. A że lubię nowości to postanowiłem wykorzystać moduł digispark z mikrokontrolerem Attiny85 które wydawało mi się najlepsze pod względem wielkości jednak nie wiedziałem wtedy jeszcze że nie posiada ona uartu który był nie zbędny do komunikacji przy pomocy modułu hc-05. Po za tym do budowy pilota wykorzystałem jeszcze obudowę kradex z47u, przyciski, joystick, akumulator Li-pol, oraz przetwornicę step-up. Zdjęcia: Trudnością którą napotkałem w trakcie budowy okazał się brak pinów portu szeregowego na szczęście rozwiązanie okazało się proste a była nim biblioteka SoftwareSerial która pozwala na symulowanie portu szeregowego na dowolnych pinach. Po za tym problemem okazał się brak miejsca który zmusił mnie do wystawienia akumulatora na zewnątrz konstrukcji a nie tak jak początkowo planowałem ukryć go wewnątrz . Kod: #include <SoftwareSerial.h>//RX, TX SoftwareSerial sserial(0,1); int a1 = 0; int a2 = 0; int a3 = 0; int a4 = 0; void setup() { sserial.begin(9600); sserial.println("test"); } void loop() { a1 = analogRead(A2);//2 od góry a2 = analogRead(A3);//3 od góry a3 = digitalRead(2);//3 od dołu a4 = digitalRead(0);// 1 od dołu if((a1 > 250)&&(a1<850)){ if((a2 > 250)&&(a2<800)){ sserial.println("u"); delay(100); } } if(a1 > 850){ sserial.println("q"); delay(100); }if(a1 < 250){ sserial.println("w"); delay(100); }if(a2 > 800){ sserial.println("e"); delay(200); }if(a2 < 250){ sserial.println("r"); delay(100); }if(a3 == HIGH){ sserial.println("t"); delay(100); }if(a4 == LOW){ sserial.println("y"); delay(100); } } Film: Przepraszam za słabą jakość filmu ale niestety aparat w telefonie nie pozwala na nagrywanie w lepszej jakości. Po za tym na filmie widać to że robot nie zawsze reaguje na polecanie ale to już było wynikiem wyładowującego się akumulatora. Starałem się by pilot był jak najmniejszy, możliwy do obsługi za pomocą jednej ręki a przy tym w miarę wygodny by dłuższa obsługa nie męczyła ręki .To rozwiązanie ma też jednak swoje wady na przykład nie ma możliwości by obsługiwać nim coś bardziej skomplikowanego niż coś co wymagało by więcej niż jednego joysticka(np. robot z chwytakiem, dron)
  11. Dzień dobry Wszystkim! Tak w skrócie, mój robot ma się poruszać po wyznaczonej ścieżce i robić mapę otoczenia wraz z pokazywaniem swojej pozycji. Mam problem z komunikacją, HC-06 mam podłączony do Arduino Mega 2560 przez RX,TX. Wysyłam dane z czujników optycznych odnośnie pozycji (pozycja już wyliczana w Arduino). Przesyłam 2 zmienne po sobie x1, y1. Arduino łączy się w 1-2 sekundy z moim telefonem, na telefonie używam Serial Bluetooth Terminal i odczyty z Arduino sa odbierane bez problemu (wysyłam około 4-6 danych/sekundę). Podczas łączenia się z komputerem trwa to 30sekund, a czasem 1-2minuty. Po stronie PC mam Bluetootha 4.0 Asusa USB-BT400 (pisze że jest kompatybilny z wersjami 2.0, 2.1, 3.0 no i 4.0... jest BLE (Low Energy). Używam do tego skryptu napisanego w Matlabie. Ta część odpowiada za samo połączenie. Działa gdyż w ustawieniach windowsa w sekcji bluetooth widzę HC-06 i mam sparowane i połączone. delete(instrfind) %zamkniecie otwartych portow w Matlabie clear all instrhwinfo('Bluetooth','HC-06') bt = Bluetooth('HC-06', 1) fopen(bt); Kolejna część kodu zajmuje się odczytem przesyłanych danych i prostym rysowaniem. tic; figure(1); x=0; xn=0; y=0; yn=0; while (true) x=fscanf(bt,'%f'); %odczyt impulsow z lewego kola y=fscanf(bt,'%f'); %odczyt impulsow z prawego kola xn=xn+x; yn=yn+y; plot(xn,yn,'black*') axis auto hold on end Dodam że czasem działa, ale głownie mam błąd z przekroczeniem czasu. Co może być przyczyną że jest taki problem z połączeniem? Poniżej screen z 2 kółek... Dzisiaj udało mi się nawiązać tylko 2 razy połączenie, a z telefonem śmiga. Tylko że na telefonie nie mam takich możliwości z odbieraniem danych i rysowaniem ich. A może jest jakaś apka na androida co by mi rysowała położenie mojego robota? Na koniec kod z Arduino. Trzymanie się lini i sterowanie silnikami wykonuje na niezależnym Arduino Nano. Próbowałem wykonywać i śledzenie linii, PID'a i odczyt z enkoderów, a także obsługę 3 czujników HC-SR04 na jednej platformie Arduino MEga2560, ale nie ogarniał (a może to mój nie zoptymalizowany kod?). Robiłem to przerwaniach, wątkach itd. Stanęło na 2 Arduino jak teraz, choć zastanawiam się nad platformą ESP32, nie wiem czy by nie było łatwiej. Proszę o pomoc. //czujniki lini #define L2_LINE_SENSOR A0 #define R2_LINE_SENSOR A1 //czujniki szczelinowe #define L_SZCZ 2 #define P_SZCZ 3 //silniki #define LMOTOR 9 #define RMOTOR 8 #define IN1 4 #define IN2 5 #define IN3 6 #define IN4 7 //czujniki ultradzwiekowe #define SechoHSCR04 51 #define StrigHSCR04 49 #define PechoHSCR04 50 #define PtrigHSCR04 48 #define LechoHSCR04 42 #define LtrigHSCR04 40 #include <Stream.h> #include <SoftwareSerial.h> SoftwareSerial mySerial(17, 16); // RX, TX #include <Wire.h> #include <Timers.h>//watki Timers<1>akcja;//watki volatile float impL=0, impP=0, vx1=0, vy1=0; //"impL","impP"-impulsy z enkoderow; float x1=0, y1=0, r=3.25, teta=0, tetaKat=0, tetaV=0, d=6.5, l=0, L=13.30, dystansL=0, dystansP=0, dystansS=0; //"r"-promien kola; "L"-odleglosc pomiedzy kolami mierzona od osi kola int licznik=0; int blad=0, g=200, vstart=40, pochodna=0, poprzedni=0, calka=0, PID=0; //"g"-granica widzialnosci czarnej lini; "vstart"-predkosc stala float Kp=8, Kd=0.1, Ki=0.4; //nastawy regulatora PID float Ldystans=0, Sdystans=0, Pdystans=0; float doMetra=0, prawo90=0; unsigned long s=0, start=0, time=0, aktualnyCzas=0, zapamietanyCzas=0, roznicaCzasu=0;//timery String inString = ""; void setup() { //Zasilanie +++ pinMode (47, OUTPUT);//ultradzwiekowy srodek digitalWrite(47, HIGH); pinMode (46, OUTPUT);//ultradzwiekowy prawy digitalWrite(46, HIGH); pinMode (38, OUTPUT);//ultradzwiekowy lewy digitalWrite(38, HIGH); pinMode (22, OUTPUT);//szczelinowy prawy digitalWrite(22, HIGH); pinMode (23, OUTPUT);//szczelinowy lewy digitalWrite(23, HIGH); //Masa --- pinMode (53, OUTPUT);//ultradzwiekowy srodek digitalWrite(53, LOW); pinMode (52, OUTPUT);//ultradzwiekowy prawy digitalWrite(52, LOW); pinMode (44, OUTPUT);//ultradzwiekowy lewy digitalWrite(44, LOW); //--------------Czujniki optyczne pinMode(L_SZCZ, INPUT); pinMode(P_SZCZ, INPUT); l=d*PI; //Silniki pinMode (LMOTOR, OUTPUT);//lewy pinMode (IN1, OUTPUT);//przod pinMode (IN2, OUTPUT);//tyl pinMode (RMOTOR, OUTPUT);//prawy pinMode (IN3, OUTPUT);//przod pinMode (IN4, OUTPUT);//tyl analogWrite(LMOTOR, 0); //Ustawienie predkosci digitalWrite(IN1, HIGH); //Kierunek: do przodu digitalWrite(IN2, LOW); //Kierunek: do tylu analogWrite(RMOTOR, 0); //Ustawienie predkosci digitalWrite(IN3, HIGH); //Kierunek: do przodu digitalWrite(IN4, LOW); //Kierunek: do tylu //Czujniki odbiciowe pinMode(R2_LINE_SENSOR, INPUT); pinMode(L2_LINE_SENSOR, INPUT); //Czujniki ultradzwiekowe pinMode(SechoHSCR04, INPUT); pinMode(StrigHSCR04, OUTPUT); pinMode(LechoHSCR04, INPUT); pinMode(LtrigHSCR04, OUTPUT); pinMode(PechoHSCR04, INPUT); pinMode(PtrigHSCR04, OUTPUT); mySerial.begin(9600); Serial.begin(9600); s=millis(); start=millis(); time = millis(); //------------Watki------------ //akcja.attach(0, 50, wysylanie); akcja.attach(0, 250, pozycja); //akcja.attach(1, 980, hcsr04lewy); //akcja.attach(2, 990, hcsr04srodek); //akcja.attach(3, 1000, hcsr04prawy); //akcja.attach(4, 2000, stopMotors); //--------------Przerwania na enkoderach kol--------------------- attachInterrupt(digitalPinToInterrupt(2), enkoderL, LOW); attachInterrupt(digitalPinToInterrupt(3), enkoderP, LOW); } //******************************************** //*****************FUNKCJE******************** //******************************************** //-----------------Wysylanie pozycji z arduinoNano przez BT void wysylanie() { if (Serial.available() > 0) { int inChar = Serial.read(); if (inChar != '\n') { inString += (char)inChar; } else { Serial.println(inString.toFloat()); inString = ""; } } } //----------------Enkodery kol void enkoderL() { if ((millis() - time) > 5) impL++; time = millis(); } void enkoderP() { if ((millis() - time) > 5) impP++; time = millis(); } //----------------Pozycja pojazdu void pozycja() { //droga przejechana przez kazde z kol dystansL=(impL/20)*l; dystansP=(impP/20)*l; //kata o jaki obrocil sie robot tetaKat=tetaKat+((dystansP-dystansL)/L); //pozycja dystansS=(dystansP+dystansL)/2; x1=dystansS*(cos(tetaKat)); y1=dystansS*(sin(tetaKat)); //Serial.print("x1: "); mySerial.println(x1); //Serial.print("y1: "); mySerial.println(y1); //reset licznikow impL=0; impP=0; } //---------------Jazda prosto 1 metr void jedenMetr () { if (doMetra<100) { dystansL=(impL/20)*l; dystansP=(impP/20)*l; dystansS=(dystansP+dystansL)/2; analogWrite(RMOTOR, 70); //Ustawienie predkosci digitalWrite(IN3, HIGH); //Kierunek: do przodu analogWrite(LMOTOR, 70); //Ustawienie predkosci digitalWrite(IN1, HIGH); //Kierunek: do przodu doMetra=dystansS+doMetra; //reset licznikow impL=0; impP=0; Serial.println(doMetra); } else if (doMetra>=100) { analogWrite(RMOTOR, 0); //Ustawienie predkosci digitalWrite(IN3, LOW); //Kierunek: do przodu analogWrite(LMOTOR, 0); //Ustawienie predkosci digitalWrite(IN1, LOW); //Kierunek: do przodu } } //---------------Skręt w prawo 90 stopni void wPrawo90 () { if (prawo90<20.88) { dystansL=(impL/20)*l; analogWrite(RMOTOR, 0); //Ustawienie predkosci digitalWrite(IN3, LOW); //Kierunek: do przodu analogWrite(LMOTOR, 70); //Ustawienie predkosci digitalWrite(IN1, HIGH); //Kierunek: do przodu prawo90=dystansL+prawo90; //reset licznikow impL=0; impP=0; Serial.println(prawo90); } else if (prawo90>=20.88) { analogWrite(LMOTOR, 0); //Ustawienie predkosci analogWrite(RMOTOR, 0); //Ustawienie predkosci digitalWrite(IN1, LOW); digitalWrite(IN3, LOW); } } //---------------Pomiar odleglosci czujnika srodkowego void hcsr04srodek () { float czas; digitalWrite(StrigHSCR04, LOW); delayMicroseconds(2); digitalWrite(StrigHSCR04, HIGH); delayMicroseconds(10); digitalWrite(StrigHSCR04, LOW); czas = pulseIn(SechoHSCR04, HIGH); Sdystans = (czas / 58); //delay(1000); //Serial.print("\nOdleglosc-srodek: "); mySerial.println(Sdystans); } //---------------Pomiar odleglosci czujnika lewego void hcsr04lewy () { float czas; digitalWrite(LtrigHSCR04, LOW); delayMicroseconds(2); digitalWrite(LtrigHSCR04, HIGH); delayMicroseconds(10); digitalWrite(LtrigHSCR04, LOW); czas = pulseIn(LechoHSCR04, HIGH); Ldystans = (czas / 58); //delay(1000); //Serial.print("\nOdleglosc-lewy: "); mySerial.println(Ldystans); } //---------------Pomiar odleglosci czujnika prawego void hcsr04prawy () { float czas; digitalWrite(PtrigHSCR04, LOW); delayMicroseconds(2); digitalWrite(PtrigHSCR04, HIGH); delayMicroseconds(10); digitalWrite(PtrigHSCR04, LOW); czas = pulseIn(PechoHSCR04, HIGH); Pdystans = (czas / 58); //delay(1000); //Serial.print("\nOdleglosc-prawy: "); mySerial.println(Pdystans); } //---------------------Wyliczenie bledu int error () { if (analogRead(L2_LINE_SENSOR) < g && analogRead(R2_LINE_SENSOR) < g) { //nie widza lini blad=1; } else if (analogRead(L2_LINE_SENSOR) > g && analogRead(R2_LINE_SENSOR) < g) { //lewy widzi linie blad=2; } else if (analogRead(L2_LINE_SENSOR) < g && analogRead(R2_LINE_SENSOR) > g) { //prawy widzi linie blad=-2; } //Serial.print("blad: "); //Serial.println(blad); return blad; } //-----------------------------PID void regPID () { pochodna=blad-poprzedni; poprzedni=blad-poprzedni; calka=constrain(calka+blad, -50, 50); PID=round(abs((Kp*blad)+(Kd*pochodna)+(Ki*calka))); //Serial.print("PID: "); //Serial.println(PID); if (blad == 1) {//jazda prosto leftMotor(vstart); rightMotor(vstart); } else if (blad == 2) { //lewy widzi linie leftMotor(vstart-PID); rightMotor(vstart+PID); } else if (blad == -2) { //prawy widzi linie leftMotor(vstart+PID); rightMotor(vstart-PID); } } //-------------------Sterowanie silnikami void leftMotor(int V) { if (V>0) { //V=constrain(V, 0, 256); analogWrite(LMOTOR, V); //Ustawienie predkosci digitalWrite(IN1, HIGH); digitalWrite(IN2, LOW); } else { //stop //V=abs(V); analogWrite(LMOTOR, 0); //Ustawienie predkosci digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); } } void rightMotor(int V) { if (V>0) { //V=constrain(V, 0, 256); analogWrite(RMOTOR, V); //Ustawienie predkosci digitalWrite(IN3, HIGH); digitalWrite(IN4, LOW); } else { //stop //V=abs(V); analogWrite(RMOTOR, 0); //Ustawienie predkosci digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); } } void stopMotors() { analogWrite(LMOTOR, 0); //Ustawienie predkosci analogWrite(RMOTOR, 0); //Ustawienie predkosci digitalWrite(IN1, LOW); digitalWrite(IN2, LOW); digitalWrite(IN3, LOW); digitalWrite(IN4, LOW); delay(1000); } //--------------PETLA GLOWNA-------------- void loop() { //jedenMetr(); //wPrawo90(); //akcja.process(); //aktualnyCzas = millis(); //roznicaCzasu = aktualnyCzas - zapamietanyCzas; //error(); //regPID(); delay(200); pozycja(); //if (roznicaCzasu >= 250UL) { //zapamietanyCzas = aktualnyCzas; //pozycja(); //hcsr04lewy(); //hcsr04srodek(); //hcsr04prawy(); //} /* float czas=millis(); Serial.println(analogRead(R2_LINE_SENSOR)); delay(1000); Serial.print(" , "); Serial.println(czas/1000); */ }
  12. Cześć. Właśnie korzystam z modułu bluetooth HC-06 podłączonego do Arduino UNO i mam z nim jeden problem, bo jak działa wysyłanie danych z aplikacji na Arduino (sterowanie np. autkiem) to niestety nie działa komunikacja ze strony Arduino. To znaczy, że aplikacja nie szczytuje mi informacji podanych z Arduino. Zrobiłem projekt na podstawie filmu z yt: https://www.youtube.com/watch?v=8DOg8onUvks w celu sprawdzenia działania modułu, i jak mogę sterować serwomechanizmem to niestety jak naciskam przyciski (informacja o stanie przycisku wyświetla się na monitorze portu szeregowego) to nie wyświetla mi się ona na telefonie. Kod zamieszam poniżej: #include <Servo.h> Servo myServo; void setup() { Serial.begin(9600); pinMode(8, INPUT_PULLUP); pinMode(9, INPUT_PULLUP); pinMode(13, OUTPUT); myServo.attach(10); } char cmd[100]; byte cmdIndex; boolean prz1, prz2, prz1_old = true, prz2_old = true; void exeCmd() { if (cmd[0] == 's') { unsigned int val = atof(cmd+2); myServo.write(val); } } void loop() { if (Serial.available() > 0) { char c = (char)Serial.read(); if (c == '\n') { cmd[cmdIndex] = 0; exeCmd(); cmdIndex = 0; } else { cmd[cmdIndex] = c; if (cmdIndex < 99) cmdIndex++; } } prz1 = digitalRead(8); prz2 = digitalRead(9); if (prz1 != prz1_old) { prz1_old = prz1; if(prz1) { Serial.println("a 0\n"); // wysyłanie danych na monitor portu szeregowego kiedy przycis jest nie załączony } else { Serial.print("a 1\n"); // wysyłanie danych na monitor portu szeregowego kiedy przycis jest załączony } } if (prz2 != prz2_old) { prz2_old = prz2; if(prz2) { Serial.println("b 0\n"); // wysyłanie danych na monitor portu szeregowego kiedy przycis jest nie załączony } else { Serial.print("b 1\n"); // wysyłanie danych na monitor portu szeregowego kiedy przycis jest załączony } } } Sam moduł HC-06 podłączyłem za pomocą dzielnika napięcia i na krzyż (TX/RX). A w samej aplikacji także wszystko zostało poprawnie ustawione, ponieważ slajder działa i mogę bez problemu sterować serwomechanizmem. I zatem mam pytanie, czy robię coś źle (wiem że coś robię źle, bo jak bym robił prawidłowo to by działało 😅), czy jest coś o czym nie wiem przez co własnie nie mogę zrealizować komunikacji ze strony Arduino? Z góry dziękuje za pomoc.
  13. Zapewne każdy z was używa często słuchawek czy to przy komputerze czy też w trakcie wędrówki do szkoły. Zapewne też nie jednemu oderwał się kabel(u mnie najczęściej była to masa) od tych słuchawek. W takim wypadku najczęściej kupuje się audio jacka i się lutuje. Tak było i u mnie ale po którymś z kolei takim przypadku stwierdziłem że dość i przerobię je po prostu na bluetooth. Do przeróbki wykorzystałem słuchawki hykkera kupione w biedronce za dwadzieścia złoty nieznanego modelu. Pomimo niskiej ceny były one nad wyraz wygodne i dobre. MATERIAŁY akumulator Li-Pol 1S 250mAh, przełącznik z dźwignią, ładowarka Li-Pol, Moduł odtwarzania muzyki XY-BT-Mini - MP3 - Bluetooth NARZĘDZIA mini szlifierka, pistolet do klejenia WYKONANIE Po otworzeniu słuchawki lewej i odlutowaniu poprzednich kabli za pomocą mini szlifierki wykonałem otwór na kabel USB do ładowarki. Przełącznik z dźwignią jest umieszczony w dawnym wyjściu kabli ze słuchawki przymocowany jest za pomocą śruby i nakrętki dołączonej w zestawie z przełącznikiem. Następnie po wykonaniu otworu na kabel USB do ładowarki zacząłem od ładowarki Li-Pol, przełącznika z dźwignią, akumulatora, modułu MP3 -Bluetooth. Dopiero po połączeniu tych elementów połączyłem głośniki w słuchawkach z modułem MP3-Bluetooth. Do umiejscowienie i odizolowania połączeń użyłem kleju na gorąco i taśmy izolującej. Po wszystkim zamknąłem z powrotem słuchawkę i zorientowałem się że istnieje problem o jakim nawet nie pomyślałem. mianowicie słuchawka się nie domyka z powodu kondensatorów modułu MP3-Bluetooth zostawiając około dwu milimetrową przerwę.Drugą słuchawkę pozostawiłem nie tknięto. FILM TESTY Po tych modyfikacjach testowałem słuchawki przez tydzień zarówno na spacerach jak i w domu przed komputerem.I jestem bardzo zadowolony. Moduł bluetooth pomimo swojej ceny(13 zł) okazał się świetnym wyborem co prawda zasięg różnił się trochę od tego deklarowanego prze producenta(był mniejszy o około 3 metry, po tym dźwięk zaczął przerywać) ale i tak spisywał się nieźle nigdy mi nie rozłączyło czy to telefonu czy komputera ze słuchawkami tylko te kondensatory tak trochę kują.Ale nawet pomimo tej szpary słuchawka się nie rozpada. Bateria na pełnym naładowaniu starcza na około 1,5 godziny zależy od głośności słuchawek.
  14. Układ do sterowania 5 silnikami za pomocą USB oraz bluetooth Proszę o sprawdzenie ewentualnie uwagi schemat.zip
  15. Witam, mam problem z modułami BT HC05, chcę zrobic dwa urządzenia typu master i slave z mastera będę przesyłał znak + (kod ascii to chyba 43) ten drugi odbierze ten znak i zmieni stan diody. Proste urządzenie zeby poduczyc się w tym zakresie. Oczywiście juz na starcie mam sporo problemów jednym z nich jest tak jakby brak komuniakcji między modułami. Znaczy niby dioda za parowanie jest załączona albo jak połacze się laptopem i przez termianl wysle to mi odbeirze i zmieni stan diody. Przesyłam kod bilioteki z Bluebooka M. Kardasia Master char bufor[100]; // bufor roboczy #define LED_TOG PORTC ^= LED_PIN #define LED_PIN (1<<PC0) #define BUZ (1<<PB0) #define BUZ_PORT PORTB #define BUZ_DIR DDRB #define BUZ_OFF BUZ_PORT &= ~BUZ #define BUZ_ON BUZ_PORT |= BUZ #define BEEP BUZ_ON; _delay_ms(5); BUZ_OFF char znak; int main( void ){ DDRA |= (1<<PA7); // ustawiamy kierunek linii podświetlenia LCD jako WYJŚCIE PORTA |= (1<<PA7); // załączamy podświetlenie LCD - stan wysoki // inicjalizacja buzzera BUZ_DIR |= BUZ; BUZ_OFF; DDRC |= LED_PIN; // kierunek pinu PC7 – wyjściowy PORTC |= LED_PIN; // wyłączenie diody LED suart_init(); lcd_init(); lcd_str( "HC_05 MASTER" ); while (1){ // if (klawisz_wcisniety()) { suart_puts( "49" ); LED_TOG; // BEEP; _delay_ms(1000); } // odsyłamy z powrotem do terminala cały odebrany string suart_puts( bufor ); suart_puts( "\r\n" ); lcd_cls(); // wyświetlamy na ekranie LCD odebrany string z terminala lcd_str( bufor ); } i Slave #include "SoftUART/soft_uart.h" char bufor[100]; // bufor roboczy #define LED1_TOG PORTC ^= LED1_PIN #define LED1_PIN (1<<PC0) int main( void ) { DDRA |= (1<<PA7); // ustawiamy kierunek linii podświetlenia LCD jako WYJŚCIE PORTA |= (1<<PA7); // załączamy podświetlenie LCD - stan wysoki // inicjalizacja soft uart'a suart_init(); DDRC |= LED1_PIN; PORTC|= LED1_PIN; lcd_init(); lcd_str( "slave" ); char znak; while ( 1 ) { // odbieramy string z terminala (funkcja blokująca) suart_gets( bufor, sizeof( bufor ) ); znak = sgetchar(); if( znak == 43) LED1_TOG; // odsyłamy z powrotem do terminala cały odebrany string suart_puts( bufor ); suart_puts( "\r\n" ); lcd_cls(); // wyświetlamy na ekranie LCD odebrany string z terminala lcd_str( bufor ); } }
  16. Witam, od dłuższego czasu mam problem z modułem HM-10. Chciałem wykorzystać go do komunikacji z moim line followerem, aby ułatwić proces regulacji parametrów robota. Po wielu próbach, testując różne aplikacje na telefon w końcu udało mi się przejąć pełną kontrolę nad modułem podpiętym pod Arduino i mogłem sterować diodą RGB za pomocą aplikacji Arduino Bluetooth Controller (HM-10 Module) . Tak wyglądała aplikacja: Z takim kodem na Arduino: int red=25,green=25,blue=25; char znak; void setup() { Serial.begin(9600); pinMode(3,OUTPUT); pinMode(5,OUTPUT); pinMode(6,OUTPUT); digitalWrite(12,HIGH); } void loop() { if(Serial.available()) { char znak=char(Serial.read()); Serial.print("odebrane: "); Serial.println(znak); if(znak=='R') { red+=10; Serial.print("R: "); Serial.println(red); } else if(znak=='G') { green+=10; Serial.print("G: "); Serial.println(green); } else if(znak=='Z') { red=50; green=50; blue=50; } else if(znak=='B') { blue+=10; Serial.print("B: "); Serial.println(blue); } } analogWrite(3,red); analogWrite(5,green); analogWrite(6,blue); } Ucieszony że wszystko działa jak należy przeniosłem moduł z płytki stykowej na płytkę główną mojego robota i odpowiednio go przylutowałem. Na moją Atmegę328p wgrałem prawie bliźniaczy program który na znak 'a' otrzymany z telefonu włącza silniki natomiast na 'A' wyłącza je. Wszystko działało jak należy. Problem zaczął się, kiedy zdalny start chciałem połączyć z algorytmem jazdy. Robot który normalnie bez problemu pokonuje wyznaczoną przeze mnie trasę, po załączeniu komunikacji bezprzewodowej po torze jedzie tak: Wstawię jeszcze fragment kodu jazdy po lini z obsługą modułu, dalej jest już sam algorytm kierowania. void setup() { pinMode(7, INPUT); //czujnik 1 pinMode(13,INPUT); //czujnik 2 pinMode(2, INPUT); //czujnik 3 pinMode(3, INPUT); //czujnik 4 pinMode(4, INPUT); //czujnik 5 pinMode(A0, INPUT); //czujnik 6 pinMode(A1, INPUT); //czujnik 7 pinMode(A2, INPUT); //czujnik 8 pinMode(A3, INPUT); //czujnik 9 pinMode(A4, INPUT); //czujnik 10 pinMode(A5, INPUT); //czujnik 11 pinMode(9, OUTPUT); //PWM do komparatora pinMode(12, OUTPUT); // silniki wł/wył pinMode(5, OUTPUT); // PWM dla silnika LEWEGO pinMode(6, OUTPUT); // PWM dla silnika PRAWEGO Serial.begin(9600); } int lasterror = 0; int przestrzelony = 0; int V = 100; //predkosc bazowa int Kp = 9; int Kd = 1; void loop() { if(Serial.available()) { char znak=Serial.read(); switch(znak) { case'a': digitalWrite(12,HIGH); break; //włączam silniki case'A': digitalWrite(12,LOW); break; //wyłączam silniki } } Proszę o pomoc, już sam nie wiem co może być tutaj nie tak. Myślałem nad zmianą modułu na popularniejszy typu HC-06 nawet ze względu na łatwość tworzenia aplikacji w App Inventorze, ale chętniej pozostałbym przy tym, gdyby udało się rozwiązać problem.
  17. Witam, zwracam się o pomoc w sprawie modułu bluetooth hc 05 (link poniżej) https://botland.com.pl/pl/moduly-bluetooth/2570-modul-bluetooth-hc-05-5903351241311.html?gclid=Cj0KCQiAn8nuBRCzARIsAJcdIfPQ8LjBcnih59HeXEDxQcFq0KBOiIap5HYn692tBzV40nsWWlcnsO0aAiISEALw_wcB Wykorzystuję go do sterowania samochodzikiem razem z arduino Uno i sterownikiem silników L239D (dodaje zdjęcie). Mam z nim taki problem, że po kilkunastu sekundach samoczynnie rozłącza się z telefonem. Sprawdziłem już czy wszystkie piny są dobrze podłączone czy nie ma błędów w lutowaniu, ale na moje oko wszystko wydaje się w porządku. Do wejścia TX na module zastosowałem dzielnik napięcia a napięcie zasilania wynosi 5V. Myślę że wszystko robię poprawnie, no chyba że jest cos o czym nie wiem 😉
  18. Po stworzeniu głośnika Bluetooth opartego o wzmacniacz 3W przyszła pora na coś mocniejszego. Celem, jaki chciałem osiągnąć było zwiększenie mocy głośnika i zachowanie jego mobilności. Udało się to osiągnąć ponad 10-krotnie. Głośnik Bodzio (bo tak został nazwany :P) ma moc 35W. Nazwa nie jest przypadkowa, ma nawiązywać do jego drewnianej obudowy, więc przyjął przydomek po sklepie z meblami. Najciekawsze jest w nim to, że został zrobiony z kolumny znalezionej na ulicy 🙂 Przygotowanie Schemat budowy głośnika Bluetooth nie był mi obcy, gdyż podobny projekt już kiedyś robiłem. Pierwszą rzeczą, jaką trzeba było zrobić to dobór wzmacniacza. Kolumna ma jeden głośnik wysokotonowy i jeden niskotonowy więc wystarczy tutaj wzmacniacz mono. Znalazłem odpowiedni na allegro o mocy 35W. Niestety w wyrzuconej kolumnie nie działał głośnik niskotonowy, więc trzeba było również dokupić odpowiedni, pamiętając, aby jego moc była większa niż wzmacniacza. Wszystkie elementy są wypisane poniżej: Lista elementów: LM2940 Buck LDO (do zasilania Bluetooth) [6zł] Step Up LM2587 (do ładowania akumulatorów) [5zł] BMS 3S Li-ion Akumulatorki 18650 6 szt. [24zł] Wzmacniacz mono 35W audio TDA8932BT klasa D Złącze jack 3,5mm [5zł] Bluetooth USB audio stereo [13zł] Głośnik niskotonowy (basowy) 4Ω Głośnik wysokotonowy 4Ω Kondensatory: 22uF; 2,2uF Rezystory: 1kΩ ; 10kΩ LED czerwona i zielona Złącze uUSB Potencjometr 50kΩ logarytmiczny [5zł] Przełączniki 2 szt. Jak zwykle najpierw zabrałem się za rozrysowanie schematu oraz przemyślenie pozycji takich elementów jak potencjometr do regulacji głośności, przełączniki, wejście jack, itp. Praca Za układ zasilania odpowiada 6 sztuk akumulatorków 18650 z odzysku. Są połączone w pakiet 3S po dwie sztuki, dla zwiększenia napięcia oraz pojemności. Pojemność pojedynczego ogniwa wynosi ok. 2000mAh co daje w sumie akumulator o napięciu 12V i pojemności 4000mAh. Gdybyśmy chcieli taki kupić nowe akumulatorki do takiego pakietu to koszt wyniósłby ok. 45 zł. Proces ładowania i rozładowywania kontroluje BMS. Ważnym założeniem jest ładowanie głośnika z zasilacza 5V przez µUSB, gdyż na imprezie czy, gdziekolwiek poza domem ciężko o zasilanie 12V, a noszenie zasilacza zawsze przy sobie jest uciążliwe i zmniejsza mobilność głośnika, dlatego zdecydowałem się na ładowarkę, jaką mają wszyscy. Można było co prawda umieścić zasilacz sieciowy 12V wewnątrz obudowy, ale trzeba by było kombinować, gdzie ukryć przewód do zasilania, więc ładowanie go przez µUSB było najwygodniejszym sposobem. Napięcie z 5V jest podnoszone dość wydajnym przekształtnikiem Boost zwiększającym napięcie do 12,6V po to, aby pojedyncze ogniwo było naładowane do 4,2V oraz wydajność ładowania był na tyle duża, aby można było ładować i słuchać muzyki jednocześnie. Do linii 5V idącej z zasilacza dodana została LED koloru czerwonego, informująca o tym, że głośnik jest ładowany. Centralnym punktem schematu jest wzmacniacz, do którego schodzi się większość elementów. Sygnał dochodzi przez potencjometr do regulacji głośności oraz przełącznik SW2 do zmiany pochodzenia sygnału (BT lub jack). Wszystkie masy oczywiście są wspólne i połączone. Za zasilanie modułu Bluetooth odpowiada przetwornica Step Down LM2940, która redukuje napięcie do 5V. Nie jest ona w żaden sposób połączona z linią zasilania. Napięcie ładowania, a zasilania elementów 5V pomimo tej samej wartości odpowiada za zupełnie inne rzeczy i połączenie ich razem spowodowałoby niepotrzebne zamieszanie w układzie. Moduł Bluetooth został podłączony przez SW3 do zasilania i włącza się dopiero w momencie zmiany pochodzenia sygnału. Na wyjściu wzmacniacza znajduję się głośnik niskotonowy odpowiadający za bass oraz wysokotonowy z filtrem górnoprzepustowym opartym o kondensator 2,2 µF. Wybrałem ten rodzaj filtru, aby uniknąć stosowania rezystora mocy, przez który przechodziłby sygnał do głośnika niskotonowego w przypadku filtra dolnoprzepustowego. W prawej dolnej części schematu znajduję się jeszcze jeden układ. Łatwo można się domyślić co to jest, ale na razie nie będę zdradzał więcej szczegółów. Zostanie on omówiony, gdy całość (część, za którą odpowiedzialny jest ten układ) zostanie skończona. Lutowanie i składanie obudowy Gdy większość elementów została skompletowana, przyszedł czas w połączenie wszystkiego w całość i sprawdzenie, czy działa . Okazało się, że głośnik gra perfekcyjnie i ma naprawdę dużą moc. Kiedy całość była jeszcze prototypem można było się pobawić np. filtrem górnoprzepustowym, a dokładniej doborem kondensatora. Metodą prób doszedłem do wniosku, że wartość 2,2 µF jest najlepsza. Ze wzoru na częstotliwość graniczną filtru: f=1/2ΠRC wychodzi około 18kHz. Jednak w praktyce (nie wiem dlaczego) ta wartość jest mniejsza. Układ zasilania Układ ten został dokładnie opisany w przypadku omawiania schematu, wiec tutaj zamieszczę tylko kilka zdjęć. Co do samego łączenia elementów to zlutowane jest tak jak widać na obrazku na dole wpisu, wszystkie ogniwa złączone są taśmą izolacyjna, a całość przyklejone na klej na gorąco w rogu obudowy. Lutowanie płyty głównej Schemat PCB jeśli można go tak nazwać został zrobiony symbolicznie, gdyż montaż elementów jest robiony na oko na dużej płytce uniwersalnej. Najważniejsze w tym schemacie są linie łączenia modułów ze sobą. We wszystkich układach dolutowane uprzednio przewody zostały zastąpione goldpinami, dzięki którym można wlutować moduł w płytkę. Wszystkie złącza zostały podpisane. Został jeszcze problem, jak zamontować płytkę w środku obudowy. Po kilku próbach udało wykombinować mi się coś takiego. Śruba przyklejona do tulei dystansowej, które z kolei zostały przyklejone na klej dwuskładnikowy (klej na gorąco nie trzymał mocno) do obudowy głośnika. Taki montaż ma swój plus, gdyż bardzo łatwo jest wyjąć płytkę z głośnika w celu naprawy lub modernizacji. Montaż elementów w obudowie Za tą część powinniśmy się zabrać, zanim cokolwiek zamontujemy lub przykleimy w obudowie, gdyż będzie tutaj trochę wiercenia/cięcia co może doprowadzić do przypadkowego uszkodzenia zamontowanych elementów . Zabieramy się za wywiercenie otworów pod potencjometr, LED'y i przełączniki. Niestety ciężko mi powiedzieć jakim wiertłem wierciłem jaką dziurę, bo nigdzie tego nie zapisałem, więc trzeba dobrać odpowiednią samemu. To samo robimy z otworami na złącze jack i gniazdo ładowania. Kiedy już mamy wszystkie otwory, oczyszczamy głośnik z zabrudzeń, gdyż będziemy teraz wszystko przyklejać/przykręcać. Zamiast gniazda µUSB montowanego do obudowy użyłem takiego przewodu, ponieważ to było jedyne gniazdo, jakie miałem, które dało się wmontować. Cena gniazd montowanych na obudowę jest dość droga, więc nie kupowałem go. Zostało jeszcze przymocować głośniki do przedniego panelu. Głośnik niskotonowy został kupiony specjalnie pod otwór po poprzedniku, aby nie bawić się w powiększanie dziury. Natomiast głośnik wysokotonowy został zabrany z jakiejś starej kolumny, która kiedyś dostałem do rozbiórki. W przypadku pierwszego nie było żadnych problemów z montażem. Głośnik pasował idealnie w otwór i miał miejsce na przekręcenie go wkrętami. Z mniejszym głośniczkiem było więcej zabawy. Nie chciałem go wklejać, ponieważ w przyszłości będzie on zastąpiony innym, lepszym zamiennikiem, więc musiał być on również wkręcany. Trzeba było wywiercić w metalowej ramce otaczającej go, dziury na wkręty. Całe szczęście w otwór pod nim mieścił się na styk, więc nie trzeba było nic przerabiać w obudowie 🙂 Składanie obudowy w całość Zadanie niby proste, a okazało się najtrudniejsze w całym projekcie. Wcześniej głośnik był klejony, ja natomiast nie chciałem tego robić, gdyż, potrzebuje mieć dostęp do wnętrzności, aby móc go rozwijać i modyfikować. Gdyby obudowa była projektowana przez mnie od zera to pewnie nie byłoby problemu, ponieważ zostałoby to przemyślane jeszcze w fazie planowania. Pierwszym pomysłem było wmontowanie zawiasu (takiego jak w drzwiczkach od szafki) oraz zamknięcia na kluczyk. Chciałem, aby wszystko było ukryte wewnątrz i nie psuło wyglądu głośnika, stąd decyzja o takich rozwiązaniach. Niestety po kupieniu, okazało się, że montaż ich będzie nie lada wyzwaniem. Znalezienie miejsca na zawias wewnątrz obudowy okazało się praktycznie niemożliwe. Podobnie z zamknięciem na kluczyk, trzeba by było dużo pozmieniać, a na końcu i tak by wyszło paskudnie. Tak więc ten pomysł został odrzucony. Stwierdziłem, że nie ma co kombinować i przykręcę po prostu go na śruby. Mimo prostoty nawet to rozwiązanie przysporzyło problemów. Założenie o niewidoczności mocowań wymagało ukrycia śrub pod osłonką. Nie chce się tutaj już rozpisywać, gdyż liczba podejść była dość duża, więc omówię tylko końcowe rozwiązanie. Na dole panel z głośnikami trzyma się na dwóch śrubach M5 specjalnie uciętych na długość, aby pasowały do osłonki, która od dołu trzyma się właśnie na nich. Natomiast od góry jest jedna śruba na środku, która wkręca się do nagwintowanego uprzednio kątownika. Nie dało się rozwiązać tego tak jak u dołu, ponieważ po bokach są diody i przyciski, a najkrótszy kątownik, jaki znalazłem nachodził na nie. Dodatkowo trzeba było przyciąć górę metalowej otoczki głośnika wysokotonowego, gdyż przeszkadzała ona we wkręceniu śruby. Uchwyt - projekt 3D Specjalnie na potrzebę tego głośnika zaprojektowałem uchwyt do noszenia do druku 3D. Jest on dostępny na thingiverse. Dwa wymogi, jakie miała spełnić to: nie psuć designu głośnika, czyli po prostu być w miarę ładna, oraz być składana. Z tymi wytycznymi i zarysem w wyobraźni zabrałem się za projektowanie. O ile sama rączka poszła dość gładko, to głowiłem się trochę jak ukryć mocowania, aby nie rzucały się w oczy. Wymyśliłem chyba dość ciekawą rzecz, a mianowicie przykręcamy dwa małe elementy, w które później wkładamy bolce od rączki (na których się obraca) i na samą górę jeszcze zaślepki, które maskują to wszystko. Myślę, że całość nie wygląda najgorzej, jest elegancka i zajmuje mało miejsca. Design Na koniec zostawiłem zaprojektowane naklejki na głośnik opisujące poszczególne funkcje. Naklejkę zaprojektowałem na wymiar dzięki uprzednio zrobionemu zdjęciu centralnie z góry z linijką w tle. Pozwoliło to odwzorować dokładne wymiary w programie Inkspace. Plik przygotowany do druku znajduje się w repozytorium (najlepiej na jakimś śliskim papierze, wtedy jakość jest znacznie lepsza). Po wydrukowaniu całość trzeba jeszcze powycinać. Naklejkę widoczną u góry głośnika najpierw obrysowałem cyrklem, a potem wyciąłem według linii ołówka. Całość została przyklejona na taśmę dwustronną i trzyma się bardzo dobrze. Podsumowanie: Jestem bardzo zadowolony z części elektronicznej tego głośnika. Została zbudowana profesjonalnie i nie było z nią żadnych problemów. Całość znajduje się na płytce, która jest zdejmowalna co ułatwia modernizacje. Nic nie jest łączone w pająka, a wszystkie przewody idą do płyty głównej i są podpisane, także podłączenie wszystkiego to zaledwie chwila. Jakość dźwięku jest bardzo dobra. Z głośnikami takich marek jak JBL (mowa tu o głośnikach o podobnej mocy) nie ma co konkurować, gdyż jakość elementów plus membrany pasywne tworzą nieskazitelną barwę dźwięku, ale wygrywa z nimi na pewno pod względem ceny, która jakby nie patrzeć jest prawie 10 razy mniejsza (55 zł). Natomiast z głośnikami niższych półek jak najbardziej konkuruje 🙂 Wygląd w mojej opinii jest bardzo dobry. Naklejki i rączka są jak najbardziej użyteczne i pasują stylowo do całości. Jedyna rzecz konieczna do wymiany to głośnik wysokotonowy, gdyż ten, który aktualnie się znajduje pochodzi z odzysku i słuchać, że nie jest w najlepszej kondycji. Przy następnych projektach proces montażu przemyśleć na samym początku jeszcze w fazie planowanie, gdyż rozmieszczenie elementów ma potem wpływ na to, w jaki sposób całość będzie zmontowana i oszczędzi nam sporo czasu. Plany na przyszłość: Wymiana głośnika wysokotonowego Membrany pasywne, aby wzmocnić jakość dźwięku oraz zasłonić dziury z tyłu Włączanie na wodę Źródła i linki: Najnowsza wersja projektu do pobrania pod tym linkiem. Są tam wszystkie pliki niezbędne do wykonania głośnika samodzielnie. Repozytorium na GitHub https://www.ti.com/lit/ds/symlink/lm2940c.pdf https://pl.wikipedia.org/wiki/Zwrotnica_głośnikowa https://pl.wikipedia.org/wiki/Filtr_górnoprzepustowy http://kaczanowski.org/elektronika/kolumna/dwa.htm https://www.youtube.com/watch?v=H17oSRbnjnU Zapraszam również do wpisu na moim blogu 🙂
  19. Cześć wszystkim, Chciałbym przetestować pewien program który znalazłem na internecie, niestety pojawia się problem przy instalacji biblioteki na Raspberry Pi , czy ktoś jest w stanie pomóc?
  20. Witam, buduję swojego jeżdżącego robota sterowanego z aplikacji na telefon. Znalazłem w internecie poniższy kod: #include <math.h> /*BTS7960 Motor Driver Carrier*/ const int MotorRight_R_EN = 4; // Pin to control the clockwise direction of Right Motor const int MotorRight_L_EN = 5; // Pin to control the counterclockwise direction of Right Motor const int MotorLeft_R_EN = 8; // Pin to control the clockwise direction of Left Motor const int MotorLeft_L_EN = 9; // Pin to control the counterclockwise direction of Left Motor const int Rpwm1 = 6; // pwm output - motor A const int Lpwm1 = 7; // pwm output - motor B const int Rpwm2 = 2; // pwm output - motor A const int Lpwm2 = 3; // pwm output - motor B long pwmLvalue = 255; long pwmRvalue = 255; byte pwmChannel; const char startOfNumberDelimiter = '<'; const char endOfNumberDelimiter = '>'; int robotControlState; int last_mspeed; void setup(){ /* For Arduino Mega 2560 Serial1 RX - pin 19 Serial1 TX - pin 18 */ Serial1.begin(9600);//Default Bluetooth Baudrate for HC-05 //Setup Right Motors pinMode(MotorRight_R_EN, OUTPUT); //Initiates Motor Channel A1 pin pinMode(MotorRight_L_EN, OUTPUT); //Initiates Motor Channel A2 pin //Setup Left Motors pinMode(MotorLeft_R_EN, OUTPUT); //Initiates Motor Channel B1 pin pinMode(MotorLeft_L_EN, OUTPUT); //Initiates Motor Channel B2 pin //Setup PWM pins as Outputs pinMode(Rpwm1, OUTPUT); pinMode(Lpwm1, OUTPUT); pinMode(Rpwm2, OUTPUT); pinMode(Lpwm2, OUTPUT); stop_Robot(); }// void setup() void loop(){ //int i = 0; if (Serial1.available()) { processInput(); } }// void loop() void processInput (){ static long receivedNumber = 0; static boolean negative = false; byte c = Serial1.read (); switch (c){ case endOfNumberDelimiter: if (negative) SetPWM(- receivedNumber, pwmChannel); else SetPWM(receivedNumber, pwmChannel); // fall through to start a new number case startOfNumberDelimiter: receivedNumber = 0; negative = false; pwmChannel = 0; break; case 'f': // Go FORWARD go_Forward(255); //Serial.println("forward"); break; case 'b': // Go BACK go_Backwad(255); break; case 'r': turn_Right(255); break; case 'l': turn_Left(255); break; case 'c': // Top Right move_RightForward(255); break; case 'd': // Top Left move_LeftForward(255); break; case 'e': // Bottom Right move_RightBackward(255); break; case 'h': // Bottom Left move_LeftBackward(255); break; case 's': stop_Robot(); break; case 'x': pwmChannel = 1; // Rpwm1 break; case 'y': // Lpwm1 pwmChannel = 2; break; case '0' ... '9': receivedNumber *= 10; receivedNumber += c - '0'; break; case '-': negative = true; break; } // end of switch } // void processInput () void stop_Robot(){ // robotControlState = 0 if(robotControlState!=0){ //SetMotors(2); analogWrite(Rpwm1, 0); analogWrite(Lpwm1, 0); analogWrite(Rpwm2, 0); analogWrite(Lpwm2, 0); robotControlState = 0; } }// void stopRobot() void turn_Right(int mspeed){ // robotControlState = 1 if(robotControlState!=1 || last_mspeed!=mspeed){ SetMotors(1); analogWrite(Rpwm1, 0); analogWrite(Lpwm1, mspeed); analogWrite(Rpwm2, mspeed); analogWrite(Lpwm2, 0); robotControlState=1; last_mspeed=mspeed; } }// void turn_Right(int mspeed) void turn_Left(int mspeed){ // robotControlState = 2 if(robotControlState!=2 || last_mspeed!=mspeed){ SetMotors(1); analogWrite(Rpwm1, mspeed); analogWrite(Lpwm1, 0); analogWrite(Rpwm2, 0); analogWrite(Lpwm2, mspeed); robotControlState=2; last_mspeed=mspeed; } }// void turn_Left(int mspeed) void go_Forward(int mspeed){ // robotControlState = 3 if(robotControlState!=3 || last_mspeed!=mspeed){ SetMotors(1); analogWrite(Rpwm1, mspeed); analogWrite(Lpwm1, 0); analogWrite(Rpwm2, mspeed); analogWrite(Lpwm2, 0); robotControlState=3; last_mspeed=mspeed; } }// void goForward(int mspeed) void go_Backwad(int mspeed){ // robotControlState = 4 if(robotControlState!=4 || last_mspeed!=mspeed){ SetMotors(1); analogWrite(Rpwm1, 0); analogWrite(Lpwm1, mspeed); analogWrite(Rpwm2, 0); analogWrite(Lpwm2, mspeed); robotControlState=4; last_mspeed=mspeed; } }// void goBackwad(int mspeed) void move_RightForward(int mspeed){ // robotControlState = 5 if(robotControlState!=5 || last_mspeed!=mspeed){ SetMotors(1); analogWrite(Rpwm1, mspeed*0.4); analogWrite(Lpwm1, 0); analogWrite(Rpwm2, mspeed); analogWrite(Lpwm2, 0); robotControlState=5; last_mspeed=mspeed; } }// void move_RightForward(int mspeed) void move_LeftForward(int mspeed){ // robotControlState = 6 if(robotControlState!=6 || last_mspeed!=mspeed){ SetMotors(1); analogWrite(Rpwm1, mspeed); analogWrite(Lpwm1, 0); analogWrite(Rpwm2, mspeed*0.4); analogWrite(Lpwm2, 0); robotControlState=6; last_mspeed=mspeed; } }// move_LeftForward(int mspeed) void move_RightBackward(int mspeed){ // robotControlState = 7 if(robotControlState!=7 || last_mspeed!=mspeed){ SetMotors(1); analogWrite(Rpwm1, 0); analogWrite(Lpwm1, mspeed*0.4); analogWrite(Rpwm2, 0); analogWrite(Lpwm2, mspeed); robotControlState=7; last_mspeed=mspeed; } }// void move_RightBackward(int mspeed) void move_LeftBackward(int mspeed){ // robotControlState = 8 if(robotControlState!=8 || last_mspeed!=mspeed){ SetMotors(1); analogWrite(Rpwm1, 0); analogWrite(Lpwm1, mspeed); analogWrite(Rpwm2, 0); analogWrite(Lpwm2, mspeed*0.4); robotControlState=8; last_mspeed=mspeed; } }// void move_LeftBackward(int mspeed) void stopRobot(int delay_ms){ SetMotors(2); analogWrite(Rpwm1, 0); analogWrite(Lpwm1, 0); analogWrite(Rpwm2, 0); analogWrite(Lpwm2, 0); delay(delay_ms); }// void stopRobot(int delay_ms) void SetPWM(const long pwm_num, byte pwm_channel){ if(pwm_channel==1){ // DRIVE MOTOR analogWrite(Rpwm1, 0); analogWrite(Rpwm2, 0); analogWrite(Lpwm1, pwm_num); analogWrite(Lpwm2, pwm_num); pwmRvalue = pwm_num; } else if(pwm_channel==2){ // STEERING MOTOR analogWrite(Lpwm1, 0); analogWrite(Lpwm2, 0); analogWrite(Rpwm1, pwm_num); analogWrite(Rpwm2, pwm_num); pwmLvalue = pwm_num; } }// void SetPWM (const long pwm_num, byte pwm_channel) void SetMotors(int controlCase){ switch(controlCase){ case 1: digitalWrite(MotorRight_R_EN, HIGH); digitalWrite(MotorRight_L_EN, HIGH); digitalWrite(MotorLeft_R_EN, HIGH); digitalWrite(MotorLeft_L_EN, HIGH); break; case 2: digitalWrite(MotorRight_R_EN, LOW); digitalWrite(MotorRight_L_EN, LOW); digitalWrite(MotorLeft_R_EN, LOW); digitalWrite(MotorLeft_L_EN, LOW); break; } }// void SetMotors(int controlCase) I nie mogę zrozumieć jakie zdanie mają zmienne : startOfNumberDelimiter oraz endOfNumberDelimiter ? Co one w tym programie robią ?
  21. Witam, mam problem z modułem bluetooth, którego potrzebuje do projektu DIY. Wszystko normalnie działało na baudzie 9600 i wprowadzałem komendy w arduino IDE. Po wpisaniu komendy AT+RESET, której zadaniem jest reset modułu straciłem jakąkolwiek możliwość dalszej komunikacji z modułem. Dioda wskazująca na oczekiwanie parowania miga tak jak wczesniej ale nie jestem wstanie się sparować a po wpisywaniu jakikolwiek komend nie dostaje żadnej odpowiedzi. Wbudowany guzik też nie reaguje, nie wiem juz co robic :(
  22. Witam Buduję robota na kołach. W jaki sposób rozwiązać zmianę prędkości silników ? Myślałem żeby zrobić kilka przycisków w aplikacji, wybranie powodowałoby ustawienie danej prędkości.
  23. Multimetry logujące dane na komputerze są drogie. Nie mówiąc już o miernikach monitorujących równocześnie napięcie, natężenie i moc oraz rezystancję odbiornika. Może więc warto zrobić coś takiego samemu? Projekt służy jedynie do pomiaru w obwodach prądu stałego przy NIEWIELKICH napięciach (nominalnie do 26V) i ograniczonym natężeniu (sprawdź specyfikację zastosowanego modułu). Absolutnie nie należy go stosować przy napięciu sieciowym, czy też wysokowydajnych źródłach prądu (np akumulator samochodowy pomimo bezpiecznego napiącia 13V w razie zwarcia może dostarczyć KILKASET AMPERÓW, co również może okazać się groźne)! Składniki: Arduino Nano (wbudowane gniazdo Micro USB zapewni łatwe zasilanie z powerbanku, możemy też użyć Pro Mini, które zapewni większą energooszczędność) moduł miernika z magistralą I²C INA219 wyświetlacz LCD 2x16 z konwerterem I²C LCM1602 Bluetooth - UART np w postaci modułu HC-06 czy HC-05 bezpiecznik (zastosowałem PPTC 3A) gniazdo oraz wtyki bananowe 4 mm gniazdo DC 5.5/2.1 mm- Bluetooth HC-05 oraz 06 obsługują poziom logiczny napięć 3.3V. Gotowe moduły posiadają jednak na ogół stabilizator pozwalający zasilić je bezpośrednio z 5V. Nadal pozostaje jednak problem 5V "logicznych" z wyjścia UART (czyli pinu TX) w Arduino. Najlepiej zastosować tu dzielnik napięcia lub konwerter poziomów logicznych. Ja wstawiłem szeregowo rezystor by w razie czego ograniczyć natężenie prądu. To jeszcze nie "zabiło" HC-06, ale też nie jest rozwiązaniem "podręcznikowym" i zalecanym. Port nadawczy (TX) w Bluetooth możemy za to bez obaw podłączyć bezpośrednio z odbiorczym (RX) w Arduino. Kod źródłowy w tym wypadku był prawdę mówiąc banalny do napisania, gdyż wymagał jedynie drobnych zmian przykładu dla stosowanej biblioteki. #include <Wire.h> #include <Adafruit_INA219.h> //https://github.com/adafruit/Adafruit_INA219 #include <LiquidCrystal_I2C.h> //https://github.com/fdebrabander/Arduino-LiquidCrystal-I2C-library #include <Narcoleptic.h> //https://github.com/rcook/narcoleptic #define DiodeVoltageDrop 0.42 LiquidCrystal_I2C lcd(0x27, 16, 2); Adafruit_INA219 ina219; void setup(void) { Serial.begin(9600); while (!Serial) { // will pause Zero, Leonardo, etc until serial console opens delay(1); } Narcoleptic.disableTimer1(); Narcoleptic.disableTimer2(); Narcoleptic.disableADC(); Narcoleptic.disableSPI(); uint32_t currentFrequency; // Initialize the INA219. // By default the initialization will use the largest range (32V, 2A). However // you can call a setCalibration function to change this range (see comments). ina219.begin(); // To use a slightly lower 32V, 1A range (higher precision on amps): //ina219.setCalibration_32V_1A(); // Or to use a lower 16V, 400mA range (higher precision on volts and amps): //ina219.setCalibration_16V_400mA(); lcd.begin(); lcd.backlight(); } void loop(void) { // float shuntvoltage = 0; float busvoltage = 0; float current_mA = 0; // float loadvoltage = 0; float power_mW = 0; // shuntvoltage = ina219.getShuntVoltage_mV(); busvoltage = ina219.getBusVoltage_V() + DiodeVoltageDrop; current_mA = 1086.5 / 1104.0 * (ina219.getCurrent_mA() - 1.4); power_mW = abs(busvoltage * current_mA); float impedance = abs(busvoltage / current_mA * 1000.0); // power_mW = ina219.getPower_mW(); // loadvoltage = busvoltage + (shuntvoltage / 1000); Serial.print(busvoltage); Serial.print("V "); Serial.print(current_mA, 1); Serial.print("mA "); Serial.print(power_mW, 0); Serial.print("mW "); Serial.print(impedance, 1); Serial.println((char)244); lcd.clear(); lcd.print(busvoltage); lcd.print("V "); lcd.print(current_mA, 1); lcd.print("mA"); lcd.setCursor(0, 1); lcd.print(power_mW, 0); lcd.print("mW "); lcd.print(impedance, 1); lcd.print((char)244); Narcoleptic.delay(500); } Do pomiaru napięcia przez układ INA219 wymagane jest połączenie GND zasilania elektroniki z GND mierzonego obwodu. Z tego też względu nie zalecam zasilać urządzenia z gniazda USB w komputerze. W razie pomyłki możemy uszkodzić komputer! Dlatego do "kablowania" danych użyłem Bluetooth. INA219 niestety nie toleruje również odwrotnej polaryzacji - potencjał po stronie mierzonego prądu nie może być niższy względem GND. Może to doprowadzić do uszkodzenia układu. Nie jest to więc urządzenie odpowiednie do "ręcznego" pomiaru napięcia zwykłymi sondami z multimetru - niezmiernie łatwo tu o odwrotną polaryzację! Dla bezpieczeństwa wstawiłem diodę pomiędzy masą miernika a mierzonego układu. Nieco przekłamuje to pomiar napięcia (spadek napięcia na diodzie nie jest dokładnie stały, jak skorygowałem w szkicu). Za to sama konstrukcja powinna zapewnić wygodną obsługę. Z boku znajdziemy gniazdo DC do podłączenia zasilacza dla mierzonego układu oraz gniazda bananowe dla kabli "wyjściowych". Do zestawu oczywiście NIE dołączono uniwersalnego zestawu kabli pomiarowych. Musiałem więc zrobić je sobie sam 😉 Przewody z wtykiem bananowym 4 mm na wejściu są zakończone: wtykiem DC 5.5/2.1 mm (wtedy multimetr jest po prostu "przedłużaczem" zwykłego zasilacza) ponownie wtykiem bananowym, co umożliwia zastosowanie np "krokodylków" jako nakładki czy podłączenie "normalnego" multimetru celem kalibracji zaciskiem typu "hak" do bezpośredniego wpinania się w goldpiny Łatwo więc podłączymy nasze urządzenie pomiędzy zasilacz a odbiornik. Po podłączeniu komputera z modułem Bluetooth - UART utworzony jest wirtualny port szeregowy. Np dla Linuksa powstanie plik urządzenia /dev/rfcomm*. Uzyskane pomiary możemy zapisać w postaci logu np za pomocą putty czy też terminalowych narzędzi dla Linuksa. Napisałem też własny program w C++, który zapisze dane otrzymane z portu szeregowego do pliku. Skompilujemy go poprzez g++ serial2log.cpp serialib/serialib.cpp -o serial2log -std=c++17 Wcześniej należy jednak umieścić Serialib ::: Simple Serial Library w folderze serialib. Jako parametry wywoływanego programu podajemy adres portu szeregowego, baud rate oraz nazwę pliku tekstowego z logiem. Np: ./serial2log /dev/ttyUSB0 9600 log.txt Pracę kończymy w bardzo "brutalny" sposób: Ctrl + C. //g++ serial2log.cpp serialib/serialib.cpp -o serial2log -std=c++17 #include <iostream> #include <chrono> #include <thread> #include <fstream> #include <ctime> #include "serialib/serialib.h" //http://serialib.free.fr int main(int argc, char *argv[]) { if (argc != 4) { std::cout << "Usage: ./serial2log serial_port baud_rate log_file\n"; return 0; } serialib LS; // Object of the serialib class int Ret; // Used for return values char Buffer[128]; // Open serial port Ret=LS.Open(argv[1],atoi(argv[2])); // Open serial link if (Ret!=1) { // If an error occured... std::cout << "Error while opening port. Permission problem?\n"; // ... display a message ... return Ret; // ... quit the application } std::cout << "Serial port opened successfully!\n"; std::ofstream logfile; logfile.open(argv[3], std::ios::out | std::ios::app); /* Ret=LS.WriteString("AT\n"); // Send the command on the serial port if (Ret!=1) { // If the writting operation failed ... std::cout << "Error while writing data\n"; // ... display a message ... return Ret; // ... quit the application. } std::cout << "Write operation is successful \n"; */ while(1){ Ret=LS.ReadString(Buffer,'\n',128,5000); // Read a maximum of 128 characters with a timeout of 5 seconds // The final character of the string must be a line feed ('\n') if (Ret>0){ std::time_t currentTime = std::time(nullptr); std::cout << currentTime << " >> " << Buffer; // If a string has been read from, print the string logfile << currentTime << " >> " << Buffer << std::flush; } else std::cout << "TimeOut reached. No data received !\n"; // If not, print a message. std::this_thread::sleep_for(std::chrono::milliseconds(100)); } // Close the connection with the device LS.Close(); logfile.close(); return 0; } Zastosowanie: całkowanie numeryczne poboru prądu po czasie. Mamy urządzenie, którego "łakomstwo" zmienia się w czasie, a my chcemy oszacować czas jego pracy na akumulatorze. Musimy więc jakoś uśrednić jego pobór prądu. Np montaż paralaktyczny teleskopu pobiera inne natężenie prądu w trakcie podążania za ruchem dobowym nieba, a inne w trybie pozycjonowania na zadany obiekt (GoTo). Po testach będziemy mogli więc oszacować, jak długo będzie on pracował zasilany z akumulatora żelowego.
  24. Załozeniem projektu było stworzenie pojazdu czterokołowego sterowanego poprzez bluetooth, wykorzystujac wbudowany w telefon akcelerometr. Został on zbudowany na ramie starego samochodu zdalnie sterowanego, do którego zgubiona została aparatura. Głównym elementem robota jest rama robota terenowego wyposazona w silnik do napedzania osi tylnej pojazdu, oraz w silnik do skretu kołami przednimi. Po drobnych modyfikacjach została dostosowana do zamontowania płytki drukowanej oraz baterii. Zostały dodatkowo zaprojektowane i wydrukowane na drukarce 3d uchwyty na baterie. Wykorzystany został moduł arduino nano ( bazujacy na Atmedze 328P).moduł bluetooth HC-06 komunikujacy sie z arduino poprzez UART(RX,TX).Zasilany napieciem 3.3V. Zasieg modułu to około 10m.Wykorzystany został moduł L298N na podstawce umozliwiajacy sterowanie dwoma silnikami DC w obu kierunkach za pomoca 4 pinów, które mozna sterowac sygnałem PWM. Wykorzystana została bateria o napieciu 11,1V. Układ został zaprojektowany przy uzyciu oprogramowania EasyEda. w celu zwiekszenia jakosci oraz aby umiescic układ w wyznaczonym na ramie miejscu o wymiarach 50x50mm. Zaprojektowany został PCB,który został wykonany za pomoca metody termotranferu na laminacie z jednostronna warstwa miedzi Aby układ mógł zostac przylutowany metoda SMD, powyższy schemat musiał zostac wydrukowany na papierze kredowym w odbiciu lustrzanym. Nastepnie wytrawiono płytke. Jako wytrawiacz posłuzył nadsiarczan sodu (B327) zmieszany w odpowiedniej proporcji z woda. W kolejnym kroku nawiercono w płytce otwory posługujac sie wiertłem 1 mm.Nastepnie wszystkie elementy przylutowano do płytki w wyznaczonych miejscach, zrobiono to w taki sposób, aby wszystkie elementy znajdowały sie po tej samej stronie co ściezki. Program do obsługi został napisany a Arduino IDE, działa on według następującego schematu; do utworzenia interfejsu komunikujacego sie z samochodzikiem posłuzyłem sie aplikajca RoboRemo w wercji darmowej. Aplikacja wysyła do naszego modułu bluetooth dane dotyczace połozenia X oraz Y naszego telefonu. interfejs wyglada w nastepujacy sposób: Aby rozpoczać użytkowanie robota nalezy podłaczyć baterie odpowiednimi przewodami znajdujacymi sie z dołu urzadzenia (czerwony z czerwonym,niebieski z niebieskim),nastepnie uruchomić samochodzik przełaczajac przełacznik znajdujacy sie nad bateria. Po tej operacji pojazd jest gotowy do sparowania z telefonem. Aby to zrobic wystarczy kliknac przycisk "Połacz z samochodem" znajdujacy sie na ekranie. Jezeli otrzymamy bład połaczenia nalezy najpierw sparowac moduł bluetooth o nazwie "samochodzik" z naszym telefonem w ustawieniach telefonu(jezeli zostaniemy poproszeni o hasło nalezy wpisac 1234).Po udanym połaczeniu z samochodzikiem mozna przystapic do jazdy klikajac przycisk "JEDŹ!". Sterować moćna przechylajac telefon.Przechylenie przodu telefonu w dół spowoduje przyspieszenie, podniesienie -zatrzymanie, a nastepnie jazde do tyłu. Aby zmienic kierunek jazdy wystarczy przechylić telefon w prawo lub lewo. Przyciśniecie przycisku "STOP!" spowoduje zatrzymanie pojazdu. Jeszcze jedno zdjęcie pojazdu:
  25. Mój pierwszy projekt, którym jakiś czas temu zacząłem swoją przygodę z Arduino. Wężyk spustowy z interwałometrem sterowany radiowo poprzez Bluetooth. W astrofotografii popularne jest wykorzystanie techniki stackowania polegającej na łączeniu dziesiątek, czasem nawet setek zdjęć w jedno. Znacznie polepsza to stosunek sygnału do szumu. Niektóre zjawiska trwają kilka godzin (np zaćmienia, tranzyty, roje meteorów). Często też warunki atmosferyczne nie zachęcają do dłuższego pobytu na zewnątrz w środku nocy. Wyzwalacz pozwoli nam zautomatyzować rejestrację zjawisk astronomicznych. Hardware: - Arduino Pro Mini 3.3V (lub inne) - Bluetooth - UART np w postaci modułu HC-06 czy HC-05 - transoptor np PS2501 służący do zwierania obwodu, wymaga podłączenia przez stosowny rezystor (napięcie i natężenie prądu znajdziemy w dokumentacji technicznej transoptora) do pinu wyznaczonego w kodzie źródłowym (#define RelayPin). - koszyk na 3xAA - przełącznik kołyskowy do włączania - cienki kabel glośnikowy, zakończony microjackiem, wlutowany do transoptora. Pamiętajmy jednak, że również strona fotodetektora ma swoją polaryzację i transoptor powinien być podłączony do wtyczki w stosownej kolejności: Na początku do sterowania konieczne było ręczne wydawanie poleceń w terminalu. Do tego celu mogliśmy zainstalować aplikację Serial Bluetooth Terminal. e - pojedyncza ekspozycja w12 - poczekaj 12s i wykonaj zdjęcie s10i1w2 - wykonaj serię 10. zdjęć, z interwalem czasowym 1s, poczekaj 2s przed rozpoczęciem. Zawsze na końcu każdego z tych poleceń można dopisać t5, zadając czas naświetlania 5s. Samo t5 też działa. Może byc więc t5 w4t5 s10i1w2t5 Jeśli podamy własny czas naświetlania, aparat MUSI być ustawiony na czas B. #define RelayPin 13 String ReceivedData = "", numberstr; unsigned int i, character, NoExposures = 0; double exptime = 0.5, interval = 1, wait = 0; void setup() { Serial.begin(9600); pinMode(RelayPin, OUTPUT); digitalWrite(RelayPin, LOW); } void loop() { if (Serial.available() > 0) { ReceivedData = Serial.readStringUntil('\n'); ReceivedData.toLowerCase(); numberstr = ""; wait = 0; if (ReceivedData[0] == 'e' || ReceivedData[0] == 't' || ReceivedData[0] == 'w') { numberstr = extractvalue(ReceivedData, 'w'); wait = numberstr.toDouble(); if (wait != 0) { Serial.print("Wait "); Serial.print(wait); Serial.println(" s before start exposure."); } delay(wait * 1000); Serial.print("Exposure"); numberstr = extractvalue(ReceivedData, 't'); exptime = numberstr.toDouble(); if (exptime != 0) { Serial.print(" time "); Serial.print(exptime); Serial.print(" s"); } Serial.println("."); exposure(ReceivedData); } if (ReceivedData[0] == 's') { NoExposures = 0; numberstr = extractvalue(ReceivedData, 's'); NoExposures = numberstr.toInt(); numberstr = extractvalue(ReceivedData, 'i'); interval = numberstr.toDouble(); if (!interval) { interval = 1; } numberstr = extractvalue(ReceivedData, 'w'); wait = numberstr.toDouble(); Serial.print("Will make series of "); Serial.print(NoExposures); Serial.print(" images with interval "); Serial.print(interval); Serial.print(" s."); if (wait != 0) { Serial.print(" Wait "); Serial.print(wait); Serial.print(" s before start."); } numberstr = extractvalue(ReceivedData, 't'); exptime = numberstr.toDouble(); if (exptime) { Serial.print(" Exposure time "); Serial.print(exptime); Serial.println(" s."); } else Serial.println(); delay(wait * 1000); for (i = 0; i < NoExposures; i++) { Serial.print("Exposure no. "); Serial.print(i + 1); Serial.print(" from "); Serial.print(NoExposures); Serial.println("."); exposure(ReceivedData); delay(interval * 1000); } } } } String extractvalue(String inputstring, char parametr) { int character; String numberstr; for (character = 0; inputstring[character] != parametr && character < inputstring.length(); character++) { } if (inputstring[character] == parametr) { numberstr = ""; for (character++; character < inputstring.length() && inputstring[character] > 47 && inputstring[character] < 58 || inputstring[character] == '.'; character++) { numberstr = numberstr + inputstring[character]; } } return numberstr; } void exposure(String ReceivedData) { numberstr = extractvalue(ReceivedData, 't'); exptime = numberstr.toDouble(); if (exptime == 0) { exptime = 0.5; } digitalWrite(RelayPin, HIGH); delay(exptime * 1000); digitalWrite(RelayPin, LOW); } Niedawno jednak zmobilizowałem się do napisania własnej aplikacji mobilnej współpracującej z urządzeniem. Postanowiłem wykorzystać do tego środowisko Apache Cordova oraz plugin Cordova (PhoneGap) Plugin for Serial Communication over Bluetooth. Bluetooth.7zip Dlaczego taki pokraczny design? Czarne tło i czerwone napisy najmniej psują akomodację oka w ciemności. To bardzo istotne przy zastosowaniach astronomicznych. Dlaczego akurat przez wielu niezalecana Cordova? bardzo słabo znam JavaScript, a ten język jest mi potrzebny (w przeciwieństwie do Javy, w której powinno się pisać aplikacje na Androida) Cordova umożliwia bardzo proste tworzenie aplikacji DOKŁADNIE tak, jakbyśmy robili normalną stronę WWW aplikacja jest skrajnie prosta i mniejsza wydajność aplikacji hybrydowych względem natywnych nie powinna stanowić problemu Po instalacji środowiska Cordova (Windows, Linux) przechodzimy do rozpakowanego folderu z kodem programu. Możemy już skompilować program komendą cordova build. Plik instalacyjny .apk znajduje się w folderze Bluetooth/platforms/android/build/outputs. By go "usadowić na telefonie" musimy jednak wcześniej zezwolić na instalację aplikacji z nieznanych źródeł. Prawdopodobnie jeszcze łatwiej "wyklikamy" aplikację mobilną w MIT App Inventor. Fotografowanie zjawisk trwających kilka godzin stało się prostsze 😉
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.