Popularny post Mike84 Napisano Lipiec 31, 2019 Popularny post Udostępnij Napisano Lipiec 31, 2019 Witam! Na samym wstępie się może przedstawię, jako że jestem nowy na tym forum. 🙂 Mam na imię Mikołaj, 17 lat, uczę się jako technik mechatronik i elektroniką samą w sobie zajmuję się dopiero niespełna rok. ============================================================================================ Chciałbym przedstawić swoje pierwszą własną konstrukcje - Miarę ultradźwiękową "Gacek". Podobne urządzenie było przedstawiane w kursach arduino i na bazie jego działania oparłem swoje. Całość chciałem wykonać na podstawie tego co do tej pory się nauczyłem oraz nie mam jeszcze za dużo doświadczenia w robieniu tego typu projektów, dlatego niektóre rozwiązania mogą się wydawać amatorskie. 😛 Gabarytowo wyszło mi trochę za wielkie przez to, że kupiłem za dużą obudowę. 😅 Wymiary(cm): 11 x 15 x 7 Lista komponentów: Arduino UNO Wyświetlacz lcd 16x2 Czujnik ultradźwiękowy US-015 2x Potencjometry 3x Przyciski Przełącznik Żółty 3mm led Rezystor 1000Ω Obudowa uniwersalna Płytka uniwersalna Wtyk DC do arduino Koszyk na baterię 9V Trochę kabli Większość potrzebnych rzeczy już miałem, musiałem tylko dokupić parę drobiazgów oraz obudowę, w sumie wydałem +/- 70 zł. Całość mieści się w granicach 150-200 zł. Schemat połączeniowy: Kod programu: /////////////////////////////////////////// // Miara ultradźwękowa - "Gacek" // /////////////////////////////////////////// #include <LiquidCrystal.h> // Dodanie biblioteki LiquidCrystal lcd(2, 3, 4, 5, 6, 7); // Piny wyświetlacza #define przycisk1 13 #define przycisk2 12 #define przycisk3 11 #define trig 8 #define echo 9 #define led 10 //////////////////////////////////////////////////////// byte prostokat[8] = { B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111 }; // Wypełniony prostokąt byte strzalkaP[8] = { B01000, B01100, B01110, B01111, B01110, B01100, B01000, B00000 }; // Strzałka w prawo byte strzalkaL[8] = { B00010, B00110, B01110, B11110, B01110, B00110, B00010, B00000 }; // Strzałka w lewo //////////////////////////////////////////////////////// Dodanie tablic specjalnych znaków boolean kolejnosc1 = false; boolean kolejnosc2 = false; boolean start = false; int tryb = 1; int opcja = 0; int jednostka = 0; int odcinek = 0; //////////////////////////////////////////////////////// Zmienne globalne void setup() { //////////////////////////////////////////////////////// lcd.begin(16, 2); // rozmiar ekranu lcd lcd.createChar(0, prostokat); lcd.createChar(1, strzalkaP); lcd.createChar(2, strzalkaL); // Stworzenie specjalnych znaków na bazie powyższych tablic lcd.clear(); ///////////////////////////////// pinMode(przycisk1, INPUT_PULLUP); pinMode(przycisk2, INPUT_PULLUP); pinMode(przycisk3, INPUT_PULLUP); pinMode(trig, OUTPUT); pinMode(echo, INPUT); pinMode(led, OUTPUT); digitalWrite(led, LOW); //////////////////////////////////////////////////////// Ustawienie pinów lcd.setCursor(0, 0); lcd.write(byte(0)); // wyświetlenie specjalnego znaku (prostokąta) lcd.setCursor(3, 0); lcd.print("GACEK v1.0"); lcd.setCursor(15, 0); lcd.write(byte(0)); ///////////////////////////////////// Ekran powitalny } void loop() { //////////////////////////////////////////////////////// float wynik; int pomiar1, pomiar2, pole, odczyt; pole = 0; odczyt = 0; pomiar1 = 0; pomiar2 = 0; //////////////////////////////////////////////////////// Zmienne lokalne if (start == false) { // Warunek odpowiadający za jednorazowe wyświetlenie delay(3000); // ekranu startowego przy włączeniu urządzenia start = true; } if (tryb < 1) { // Warunki zmniejszące przedział zmiennej do 1-3 tryb = 1; } if (tryb > 3) { tryb = 3; } lcd.clear(); // Czyszczenie ekranu przy powrocie do menu //////////////////////////////////////////////////////// switch (tryb) { case 1: lcd.setCursor(2, 0); lcd.print("Tryb"); lcd.setCursor(2, 1); lcd.print("Miary"); lcd.setCursor(15, 0); lcd.write(byte(1)); lcd.setCursor(15, 1); lcd.print("B"); break; case 2: lcd.setCursor(0, 0); lcd.write(byte(2)); lcd.setCursor(0, 1); lcd.print("A"); lcd.setCursor(2, 0); lcd.print("Tryb"); lcd.setCursor(2, 1); lcd.print("Pomiaru Pola"); lcd.setCursor(15, 0); lcd.write(byte(1)); lcd.setCursor(15, 1); lcd.print("B"); break; case 3: lcd.setCursor(0, 0); lcd.write(byte(2)); lcd.setCursor(0, 1); lcd.print("A"); lcd.setCursor(2, 0); lcd.print("Tryb"); lcd.setCursor(2, 1); lcd.print("Nastawny"); break; } //////////////////////////////////////////////////////// Wybór trybu while (digitalRead(przycisk1) == HIGH && digitalRead(przycisk2) == HIGH && digitalRead(przycisk3) == HIGH) {} // Czekania na wybór operatora //////////////////////////////////////////////////////// if (digitalRead(przycisk1) == LOW) { // Przesuń w lewo tryb = tryb - 1; while (digitalRead(przycisk1) == LOW) {} } if (digitalRead(przycisk2) == LOW) { // Przesuń w prawo tryb = tryb + 1; while (digitalRead(przycisk2) == LOW) {} } if (digitalRead(przycisk3) == LOW) { // Wybierz ten tryb opcja = tryb; while (digitalRead(przycisk3) == LOW) {} } ////////////////////////////////////////////////////////// Sterowanie w menu if (opcja > 0) { // Jeśli wybrano tryb... lcd.clear(); //////////////////////////////////////////////////////// while (opcja == 1) { // Tryb miary //////////////////////////////////////////////////////// pomiar(); if (wynik == pomiar()) { }else{ if (wynik == pomiar() * 0.39) { }else{ if (wynik == pomiar() / 100.0) { }else{ lcd.clear(); } } } //////////////////////////////////////////////////////// Filtr przełączania liczb na ekranie lcd.setCursor(0, 0); lcd.write(byte(0)); lcd.setCursor(1, 0); lcd.print("Pomiar"); lcd.setCursor(7, 0); lcd.write(byte(0)); lcd.setCursor(9, 0); lcd.print("="); //////////////////////////////////////////////////////// switch (jednostka) { case 0: lcd.setCursor(0, 1); lcd.write(byte(0)); lcd.setCursor(1, 1); lcd.print("cm"); lcd.setCursor(3, 1); lcd.write(byte(0)); wynik = pomiar(); lcd.setCursor(11, 0); lcd.print(wynik, 0); break; case 2: lcd.setCursor(0, 1); lcd.write(byte(0)); lcd.setCursor(1, 1); lcd.print("cal"); lcd.setCursor(4, 1); lcd.write(byte(0)); wynik = pomiar(); wynik = wynik * 0.39; lcd.setCursor(12, 0); lcd.print(wynik, 2); break; case 1: lcd.setCursor(0, 1); lcd.write(byte(0)); lcd.setCursor(1, 1); lcd.print("m"); lcd.setCursor(2, 1); lcd.write(byte(0)); wynik = pomiar(); wynik = wynik / 100.0; lcd.setCursor(11, 0); lcd.print(wynik, 2); break; } //////////////////////////////////////////////////////// Wybór jednostki delay(50); if (digitalRead(przycisk3) == LOW) { jednostka = jednostka + 1; lcd.clear(); if (jednostka > 2) { jednostka = 0; } while (digitalRead(przycisk3) == LOW) {} } if (digitalRead(przycisk1) == LOW) { // wyjście do menu opcja = 0; while (digitalRead(przycisk1) == LOW) {} } } //////////////////////////////////////////////////////// Sterowanie wyborem jednostki oraz przycisk wyjścia do menu //////////////////////////////////////////////////////// while (opcja == 2) { // Tryb pomiaru pola //////////////////////////////////////////////////////// lcd.setCursor(0, 0); lcd.write(byte(0)); lcd.setCursor(1, 0); lcd.print("Pomiar1"); lcd.setCursor(8, 0); lcd.write(byte(0)); lcd.setCursor(10, 0); lcd.print("="); lcd.setCursor(0, 1); lcd.write(byte(0)); lcd.setCursor(1, 1); lcd.print("Pomiar2"); lcd.setCursor(8, 1); lcd.write(byte(0)); lcd.setCursor(10, 1); lcd.print("="); //////////////////////////////////////////////////////// if (digitalRead(przycisk1) == LOW) { opcja = 0; pomiar1 = 0; pomiar2 = 0; kolejnosc1 = false; kolejnosc2 = false; pole = 0; while (digitalRead(przycisk1) == LOW) {} } //////////////////////////////////////////////////////// Wyjście do menu if (digitalRead(przycisk2) == LOW) { lcd.clear(); pomiar1 = 0; pomiar2 = 0; kolejnosc1 = false; kolejnosc2 = false; while (digitalRead(przycisk2) == LOW) {} } //////////////////////////////////////////////////////// Reset if (digitalRead(przycisk3) == LOW) { pomiar(); if(pomiar() == 0){ pomiar(); } if(pole > 0){ pole = 0; } while (kolejnosc1 == true && kolejnosc2 == true) { lcd.clear(); pole = pomiar1 * pomiar2; lcd.setCursor(0, 0); lcd.write(byte(0)); lcd.setCursor(1, 0); lcd.print("Pole"); lcd.setCursor(5, 0); lcd.write(byte(0)); lcd.setCursor(7, 0); lcd.print("="); lcd.setCursor(9, 0); lcd.print(pole); lcd.setCursor(0, 1); lcd.print("B"); lcd.setCursor(2, 1); lcd.print("-"); lcd.setCursor(4, 1); lcd.print("RESET"); while (digitalRead(przycisk2) == HIGH && digitalRead(przycisk1) == HIGH) {} if (digitalRead(przycisk1) == LOW) { opcja = 0; pomiar1 = 0; pomiar2 = 0; kolejnosc1 = false; kolejnosc2 = false; pole = 0; lcd.clear(); break; } if (digitalRead(przycisk2) == LOW) { kolejnosc1 = false; kolejnosc2 = false; pomiar1 = 0; pomiar2 = 0; lcd.clear(); break; } } if (kolejnosc1 == true && kolejnosc2 == false && pole == 0) { pomiar2 = pomiar(); lcd.setCursor(12, 1); lcd.print(pomiar2); kolejnosc2 = true; } if (kolejnosc1 == false && pole == 0) { pomiar1 = pomiar(); lcd.setCursor(12, 0); lcd.print(pomiar1); kolejnosc1 = true; } while(digitalRead(przycisk3) == LOW){} while (digitalRead(przycisk1) == HIGH && digitalRead(przycisk2) == HIGH && digitalRead(przycisk3) == HIGH && pole == 0) {} } } ////////////////////////////////////////////////////////// // Opcja nr.2 - Pomiar pola ////////////////////////////////////////////////////////////////// while (opcja == 3) { lcd.setCursor(0, 0); lcd.write(byte(0)); lcd.setCursor(1, 0); lcd.print("Odcinek"); lcd.setCursor(8, 0); lcd.write(byte(0)); lcd.setCursor(10, 0); lcd.print("="); lcd.setCursor(12, 0); lcd.print(odcinek); ///////////////////////////////////////////////// while (digitalRead(przycisk2) == LOW) { odcinek = odcinek + 1; delay(100); lcd.setCursor(12, 0); lcd.print(odcinek); } if (digitalRead(przycisk1) == LOW) { opcja = 0; odcinek = 0; while (digitalRead(przycisk1) == LOW) {} } while (digitalRead(przycisk3) == LOW) { odcinek = odcinek - 1; if(odcinek < 0){ odcinek = 0; } delay(100); lcd.setCursor(12, 0); lcd.print(odcinek); if(odcinek - 1 == 8 || odcinek - 1 == 98 || odcinek - 1 == 998){ // Łatka naprawaiająca mieszanie się liczb na wyświetlaczu lcd.clear(); lcd.setCursor(0, 0); lcd.write(byte(0)); lcd.setCursor(1, 0); lcd.print("Odcinek"); lcd.setCursor(8, 0); lcd.write(byte(0)); lcd.setCursor(10, 0); lcd.print("="); } } if (odcinek > 0) { pomiar(); if (odczyt >= 10 && pomiar() < odczyt || odczyt >= 100 && pomiar() < odczyt){ lcd.clear(); } lcd.setCursor(0, 1); lcd.write(byte(0)); lcd.setCursor(1, 1); lcd.print("Obecnie"); lcd.setCursor(8, 1); lcd.write(byte(0)); lcd.setCursor(10, 1); lcd.print("="); if(pomiar() < 1000){ odczyt = pomiar(); lcd.setCursor(12, 1); lcd.print(odczyt); } if(odcinek == odczyt) { digitalWrite(led, HIGH); }else{ digitalWrite(led, LOW); } if (digitalRead(przycisk1) == LOW) { digitalWrite(led, LOW); lcd.clear(); odcinek = 0; opcja = 0; odczyt = 0; while (digitalRead(przycisk1) == LOW) {} } delay(25); } } ////////////////////////////////////////////////////////////////// // Tryb nr. 3 - Pomiar wymiarowy } } //////////////////////////////////////////////////////// int pomiar() { long czas, dystans; digitalWrite(trig, LOW); delayMicroseconds(2); digitalWrite(trig, HIGH); delayMicroseconds(10); digitalWrite(trig, LOW); czas = pulseIn(echo, HIGH); dystans = czas / 58; dystans = dystans + 11; delay(100); Serial.println(dystans); return dystans; //////////////////////////////////////////////////////// // Program wykonujący pomiary czujnikiem } Po uruchomieniu urządzenia wyświetla się menu wyboru trybu, którym steruje się przyciskami A oraz B, natomiast guzik C zatwierdza wybór. Potencjometry regulują jasność oraz kontrast wyświetlacza lcd. Miara ma trzy tryby pomiarów: Pierwszy z nich to mierzenie ciągłe z dodatkową opcją przeskalowania jednostki na metry oraz cale (w planie miałem także zamiar dodać milimetry, ale pomiary wychodziły bardzo niedokładnie, dlatego zrezygnowałem z tego pomysłu). Jak widać na nagraniu pomiar czasami może się różnić o 1 cm niż w rzeczywistości, może to być wina arduino, które przeskalowuje wynik z czujnika na centymetry przy czym przybliża go do pełnych liczb. Punkt zero znajduje się z tyłu obudowy, a co za tym idzie pomiar nie może być mniejszy niż 14 cm. Aby wrócić do menu wyboru wystarczy przytrzymać przycisk A. Następna opcja to pomiar pola, polega ona na zebraniu dwóch pomiarów, aby następnie na ich podstawie wyliczyć pole. Przy tworzeniu tego trybu napotkałem kilka błędów typu jakieś wyskakujące znikąd zera czy też liczby, ale ostatecznie doszedłem to tego, że problem leży w odświeżaniu wyświetlacza i załatałem ten problem. Ostatnim, trzecim trybem jest miara nastawna, działa ona w ten sposób, że najpierw ustala się na jakiej odległości ma znajdować się mierzony obiekt, po czym manewrujemy tym przedmiotem aż do momentu gdy pomiar czujnika będzie się zgadzał z wcześniej ustaloną wartością o czym poinformuje dioda. W planach mam jeszcze wprowadzenie nowych trybów oraz oczywiście zminiaturyzowania całego urządzenia. 😄 Pozdrawiam! 4 Cytuj Link do komentarza Share on other sites More sharing options...
Treker (Damian Szymański) Sierpień 4, 2019 Udostępnij Sierpień 4, 2019 @Mike84, właśnie zaakceptowałem opis. Dziękuję za przedstawienie ciekawego projektu, zachęcam do prezentowania kolejnych DIY oraz aktywności na naszym forum 😉 Cytuj Link do komentarza Share on other sites More sharing options...
Pomocna odpowiedź
Dołącz do dyskusji, napisz odpowiedź!
Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!