Philip Napisano Lipiec 24, 2018 Udostępnij Napisano Lipiec 24, 2018 Witam,Aktualnie pracuję nad programem, dzięki któremu zautomatyzuje swój pokój. Do Arduino podłączone są: wyświetlacz LCD, klawiatura, 2x Dalllas, DHT, PIR, Kontaktron, Buzzer. Jak wszystkie te elementy uda mi się dobrze zaprogramować, aby działały tak jak chce to doda się jeszcze coś innego 😃 (RTC, Bluetooth). Poniżej opisuję jak cały program ma działać. 1. Wyświetlacz(piny8-13): wyświetla się na nim temperatura w pokoju, na dworze, wartość wilgotności i temperatury, data, godzina (RTC) po wcześniejszym wciśnięciu odpowiedniego przycisku na klawiaturze; dodatkowo wyświetla się odpowiedni komunikat podczas wyjścia z pokoju ("Miłego dnia" lub coś podobnego) 2. Czujniki temperatury Dallas(pin A0): mierzą temperaturę pokoju i na dworze 3. Czujnik wilgotności DHT(pin 15): mierzy wilgotność w pokoju, oraz temperaturę dla porównania z czujnikiem Dallas 4. Kontaktron(pin 16): wykrywa wejście do pokoju i jego zadziałanie aktywuje odpowiedni sygnał buzzera 5. Buzzer(pin 17): wydaje dźwięk podczas otworzenia drzwi; może dodatkowo odtwarzać inne dźwięki 6. Czujnik ruchu PIR(pin 18): wykrywa ruch, kiedy ktoś wychodzi z pokoju, przez co na wyświetlaczu pokazuje się odpowiedni komunikat 7. Klawiatura (0-7): przełączanie temperatury, wilgotności, daty, godziny oraz różnych dźwięków. Na razie napisałem kod, aby poprzez wciśnięcie odpowiedniego przycisku na klawiaturze na wyświetlaczu wyświetlały się temperatury oraz wilgotność i wszystko chodzi i działa. Problem jest teraz z kontaktronem i buzzerem. Podczas wejścia do pokoju ma się odtworzyć jeden raz sygnał. [...] unsigned long aktualnyCzas = 0; unsigned long zapamietanyCzas = 0; int glosnosc = 500; void setup() { Serial.begin(9600); lcd.begin(16,2); lcd.clear(); sensors.begin(); dht.setup(CzDHT); pinMode(KONTAKTRON,INPUT_PULLUP); //Kontaktron pin 16 pinMode(BUZZER,OUTPUT); //Buzzer pin 17 pinMode(PIR,INPUT); } void loop(){ aktualnyCzas = millis(); [...] if(digitalRead(KONTAKTRON)==HIGH){ //Jeśli drzwi otwarte for(int i=0;i<2;i++){ if(aktualnyCzas - zapamietanyCzas >= 500UL){ zapamietanyCzas = aktualnyCzas; if(glosnosc==500){ glosnosc = 750; } else { glosnosc = 500; } tone(BUZZER,glosnosc); //Buzzer wydaje sygnał } } } else { //Jeśli nie, to jest wyłączony noTone(BUZZER); } [...] } Natomiast nie wiem dlaczego sygnał chodzi cały czas zamiast odtworzyć się tylko raz, przecież jest for. Czy mógłby ktoś pomóc mi rozwiązać ten problem? Pozdrawiam Philip Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Lipiec 24, 2018 Udostępnij Lipiec 24, 2018 Działa tak jak napisałeś. a) Sprawdzasz, czy drzwi są otwarte. b) jeśli tak, odtwarzasz dźwięk wykonując pętlę for HGW po co; jeśli nie, przestajesz odtwarzać c) Wracasz do a). Czyli kiedy zgodie z Twoim kodem dźwięk przestanie grać? Cytuj Link do komentarza Share on other sites More sharing options...
Philip Lipiec 24, 2018 Autor tematu Udostępnij Lipiec 24, 2018 Kiedy drzwi są zamknięte, to buzzer jest wyłączony. Jak otwieram drzwi, to buzzer powinien odtworzyć ten sygnał ("pip - pip") tylko raz, a robi to w kółko bez końca. Wydaje się być dobrze, przecież jest pętla for. Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Lipiec 24, 2018 Udostępnij Lipiec 24, 2018 ...która to pętla jest całkowicie bez sensu, bo wykonuje się w kółko. Bez tej pętli program działałby tak samo (a nawet lepiej). Pokaż w kodzie, w którym miejscu mianowicie buzzer ma przestać wydawać dźwięki po odtworzeniu dwóch sygnałów. Bo na razie masz że ma przestać burczeć jak drzwi są zamknięte i tyle. Niestety - instrukcji których nie ma procesory nie zwykły wykonywać 😉 Tak w ogóle masz już w programie jedną pętlę (w której wykonuje się loop) i do Twoich zastosowań ta jedna powinna wystarczyć. Cytuj Link do komentarza Share on other sites More sharing options...
Polecacz 101 Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Zarejestruj się lub zaloguj, aby ukryć tę reklamę. Produkcja i montaż PCB - wybierz sprawdzone PCBWay! • Darmowe płytki dla studentów i projektów non-profit • Tylko 5$ za 10 prototypów PCB w 24 godziny • Usługa projektowania PCB na zlecenie • Montaż PCB od 30$ + bezpłatna dostawa i szablony • Darmowe narzędzie do podglądu plików Gerber Zobacz również » Film z fabryki PCBWay
BananWszyscy Lipiec 24, 2018 Udostępnij Lipiec 24, 2018 Jeżeli chcesz, żeby ta pętla została to mogę podpowiedzieć, że możesz dodać jakiś bit, który poinformuje, że pętla już się wykonała (przy ostatnim obiegu setujesz go np. na true) a potem w głównej pętli przy zamknięciu drzwi staje się on znowu false. Ewentualnie możesz zaimplementować reakcję tylko na zbocze narastające w inny sposób. Pomysłów może być mnóstwo. EDIT: i wtedy dzwonienie wykonuje się jeśli drzwi są otwarte i ten bit jest na false Cytuj Link do komentarza Share on other sites More sharing options...
Philip Lipiec 27, 2018 Autor tematu Udostępnij Lipiec 27, 2018 Myślałem na tym kodem bardzo długo. ethanak, Rzeczywiście pętla for jest bez sensu. BananWszyscy wziąłem twoją podpowiedź pod uwagę. Dlatego mam taki kod, ale znowu nie do końca działa tak jak powinien. Po tym jak otworzę drzwi odtwarza się ten sygnał "din - don" (raz), ale jak zamykam drzwi, to jeszcze buzzer wydaje z siebie tak jakby jeden z tych dwóch dźwięków. Czyli jak otwieram jest din - don, a jak zamykam din. Druga sprawa co do tego kodu, to nie wiem jak tu zamiast delay'a użyć millis, aby te dźwięki odtwarzały się w tym odpowiednim czasie po 500ms. Robiłem to tak samo jak poprzednio, ale wtedy buzzer wydawał ciągły dźwięk bez przerwy. #define KONTAKTRON 16 #define BUZZER 17 unsigned long aktualnyCzas = 0; //Zmienne do liczenia czasu unsigned long zapamietanyCzas = 0; int glosnosc = 500; //Zmienna do zmiany glośności buzzera boolean odegranoDzwiek = false; boolean otwartoDrzwi = false; void setup() { Serial.begin(9600); pinMode(BUZZER,OUTPUT); pinMode(KONTAKTRON,INPUT_PULLUP); } void loop() { aktualnyCzas = millis(); if(digitalRead(KONTAKTRON)==HIGH){ //Jeśli drzwi otwarte otwartoDrzwi = true; //to otwarto drzwi } else { //Jeśli nie odegranoDzwiek = false; //nie odegarano dźwięku otwartoDrzwi = false; //nie otwarto drzwi noTone(BUZZER); } if(otwartoDrzwi == true && odegranoDzwiek == false){ //Jeśli drzwi otwarte i nie odegrano dźwięku tone(BUZZER,500,500); //Odegraj dźwięk delay(100); tone(BUZZER,1000,500); odegranoDzwiek = true; //Odegrano } } Proszę o pomoc jak użyć tu zamiast delay - millis oraz jak zrobić, aby nie było tego jednego dźwięku przy zamykaniu. Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Lipiec 27, 2018 Udostępnij Lipiec 27, 2018 Przede wszystkim - dodatkowy dźwięk przy zamykaniu pochodzi najprawdopodobniej od drgań styków kontaktronu. Podłącz równolegle kondensator 100nF, a przy okazji zainteresuj się biblioteką Bounce2 za pomocą której możesz wyeliminować ten efekt na drodze programowej. Co do "przerobienia" programu z delay na millis (jak ja nie lubię takich określeń, to nie jest żadne przerobienie tylko napisanie wszystkiego od początku w zupełnie inny sposób) wiesz może co to jest maszyna stanów? Pewnie nie... Otóż Twój program (załóżmy na razie, że nie wykonuje nic innego) może byc w jednym ze stanów: a) nic nie gramy, czekamy na otwarcie drzwi b) gramy pierwszy dźwięk c) gramy drugi dźwięk d) nic nie gramy, czekamy na zamknięcie drzwi I żadne jakieś tam dodatkowe bity nie są potrzebne... Program będzie działać w ten sposób: Jeśli maszyna jest w stanie a, sprawdzamy czy drzwi są otwarte. Jeśli nie, nie robimy nic. Jeśli tak, zapamiętujemy bieżący czas, uruchamiamy odgrywanie pierwszego dźwięku (tone z dwoma, a nie trzema parametrami) i ustawiamy maszynę w stan b. Jeśli maszyna jest w stanie b, sprawdzamy czy minęło już ileś tam milisekund od zapamiętanego czasu. Jeśli nie, nie robimy nic. Jeśli tak, zapamiętujemy bieżący czas, uruchamiamy odgrywanie drugiego dźwięku (również tone z dwoma parametrami a nie trzema) i ustawiamy maszynę w stan c. Jeśli maszyna jest w stanie c, sprawdzamy czy minęło już ileś tam (niekoniecznie tyle samo co w stanie b) milisekund od zapamiętanego czasu. Jeśli nie, nie robimy nic. Jeśli tak, zatrzymujemy granie (noTone) i ustawiamy maszynę w stan d. Jeśli maszyna jest w stanie d, sprawdzamy, czy drzwi są otwarte. Jeśli tak, nie robimy nic. Jeśli nie, ustawiamy maszynę w stan a. A teraz napisz to ładnie w C++ 🙂 1 Cytuj Link do komentarza Share on other sites More sharing options...
Philip Lipiec 28, 2018 Autor tematu Udostępnij Lipiec 28, 2018 Kondensator nie pomógł, dalej jest ten dźwięk przy tym moim starym kodzie. A z tą maszyną stanów chodzi o switch ... case ? Bo nie do końca wiem, czy mam coś próbować pisać ze switch'em czy jakoś inaczej. 😕 Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Lipiec 29, 2018 Udostępnij Lipiec 29, 2018 Najbardziej naturalny jest tu switch/case - ale równie dobrze (chociaż mniej elegancko) można to zrobić na if/else. Zostaw na razie ten dźwięk przy zamykaniu w spokoju, napisz nowy kod - jeśli dalej będzie występować to będziemy kombinować jak się go pozbyć. Na razie nie ma to sensu. I poszukaj sobie w międzyczasie jakichś informacji o maszynie stanów i automatach skończonych - forum nie może być jedynym źródłem informacji! W Wikipedii masz to bardzo ślicznie wyoślone... No bo fajnie jest przecież jeśli się rozumie własny kod, prawda? Cytuj Link do komentarza Share on other sites More sharing options...
grg0 Lipiec 29, 2018 Udostępnij Lipiec 29, 2018 Jeśli chodzi o programowanie to cały czas jestem początkujący. Jeśli to jest drganie styków, to dlaczego jest tylko jeden dźwięk po zamknięciu drzwi? Rozumiem, że program wchodzi do funkcji tone() i po czasie duration z niej wychodzi. Co robi fizycznie z portem funkcja noTone()? W tym konkretnym przykładzie noTone() chyba jest niepotrzebne? Cytuj Link do komentarza Share on other sites More sharing options...
BananWszyscy Lipiec 31, 2018 Udostępnij Lipiec 31, 2018 No tak, dodawanie dodatkowego bitu dla wykonania sekwencji a dodanie zmiennej informującej o obecnym stanie to taka różnica... ja tylko dalem przykładowe rozwiązanie problemu, które i tak będzie działać :> A pozbycie się delaya można zrobić np tak. 1. odczytaj timer - zapisz go gdzies 2. odczytuj timer i odejmuj otrzymaną wartość od zapisanej 3. powtórz 2 aż otrzymana wartość z odejmowania będzie taka jaką chcesz. Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Lipiec 31, 2018 Udostępnij Lipiec 31, 2018 ... a potem zrób z tego funkcję i nazwij ją "toWcaleNieJestDelay". @BananWszyscy: właśnie bardzo ładnie przedstawiłeś kod funkcji delay(). O to Ci chodziło? Żeby zamienić systemową funkcję na własną, która robi dokładnie to samo? Po kiego grzyba??? Cytuj Link do komentarza Share on other sites More sharing options...
BananWszyscy Lipiec 31, 2018 Udostępnij Lipiec 31, 2018 Ano po to, że w takim szkielecie nie zajmujemy się mrożeniem procesora, bo nadal możemy wykonywać pierdyliard innych rzeczy 😋 Cytuj Link do komentarza Share on other sites More sharing options...
ethanak Lipiec 31, 2018 Udostępnij Lipiec 31, 2018 Bardzo dobrze - tak działa np. delay w ESP8266 (tam wywołanie delay* jest wręcz wymagane, inaczej watchdog zrobi boo-boo i zobaczysz na serialu traceback). Tyle, że tu nie chodzi o "wsadzenie czegoś w delay" - a o napisanie programu na zupełnie innej zasadzie zamiast dorabiania na siłę protez do ułomnej w samych założeniach konstrukcji. To nie funkcja "delay" jest zła - gdyby tak było, pewnie by nie istniała. Złe jest jej wykorzystanie (w większości bez najmniejszych prób zrozumienia jak to wszystko tak naprawdę działa). Dlatego właśnie ględzę o automatach skończonych i maszynie stanów, bo zrozumienie tego (nawet na podstawie informacji zawartych we wspomnianej Wikipedii) wcale nie wymaga jakiejś tajemnej wiedzy ani piętnastu lat studiowania czarnej magii. A znając te zasady możesz programować swobodnie, a delaja wciskać tam gdzie jest rzeczywiście potrzebny. * yield() to to samo co delay(0) jakby ktoś twierdził że "można yield zamiast delay". 1 Cytuj Link do komentarza Share on other sites More sharing options...
BananWszyscy Lipiec 31, 2018 Udostępnij Lipiec 31, 2018 Zgadzam się ze wszystkim tak jak wcześniej, ja tylko chciałem pokazać, jak to wszystko działa i co się da z tym zrobić. Nie daję gotowego kodu/rozwiązania tylko pokazuje. Mnie jak uczyli to dawali zwykle błędne wskazówki, żebym się nacinał i sam coś lepszego wymyślał (bo działało, ale nie do końca tak jak się chciało). Dlatego twierdzę, że lepeiej napisać coś samemu od bardzo słabego kodu i przez łatanie dojść do czegoś porządnego, przynajmniej od razu wiadomo co pomijać 😃 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!