SOYER Grudzień 7, 2017 Autor tematu Udostępnij Grudzień 7, 2017 OK, trochę się namęczyłem z implementacją migania i drugiej FSM do mojego programu. Szukałem winnych, okazało się, że: 1. poszczególne stany różnych FSM musiałem ponumerować kolejno "FSM1" (1-5) i "FSM2" (6-7), dlaczego jeśli wywaliłem cyfry za nazwami stanów (i zostawiałem same nazwy) to wywalało mi błąd(expected primary expresion before ";")? 2. podobnie z case w dwóch różnych FSM musiałem numerować jak wyżej 3. oczywiście( ) nazwy zmiennych różne w różnych FSM Proszę mnie poprawić jeśli coś pokręciłem lub zrobiłem niezgodnie ze sztuką, program działa: #include <LiquidCrystal.h> //Dołączenie bilbioteki #include <SimpleDHT.h> LiquidCrystal lcd(8, 3, 4, 5, 6, 7); //Informacja o podłączeniu SimpleDHT11 dht11; #define led1 10 #define led2 12 #define led3 9 #define led4 11 #define led5 8 #define przycisk 2 #define STATE_DZIECI 1 #define STATE_ZOSIA 2 #define STATE_FRANEK 3 #define STATE_DOMINIK 4 #define STATE_WYNIKI 5 #define STATE_ON 6 #define STATE_OFF 7 unsigned long pMillis = 0; unsigned long pMillis1 = 0; int state = STATE_WYNIKI; int state1 = STATE_ON; int licznik = 1; int swiatlo = 0; int odczytSw = 0; byte temperature = 0; byte humidity = 0; int pinDHT11 = 13; //pin czujnika const long interval = 5000; const long interval1 = 1000; boolean wyswietlono = false; unsigned long cMillis; void setup() { pinMode(10, OUTPUT); pinMode(2, INPUT_PULLUP); lcd.begin(16, 2); Serial.begin(9600); } void loop() { cMillis = millis(); Serial.println(state); jasnosc(); switch(state){ case 1: dzieci(); wait_and_checkButton(); break; case 2: zosia(); wait_and_checkButton(); break; case 3: franek(); wait_and_checkButton(); break; case 4: dominik(); wait_and_checkButton(); break; case 5: if (wyswietlono == false){ wyniki(); wyswietlono = true; } if(cMillis - pMillis > interval){ pMillis = cMillis; wyswietlono = false; lcd.clear(); switch(licznik){ case 1: state = STATE_ZOSIA; licznik++; break; case 2: state = STATE_FRANEK; licznik++; break; case 3: state = STATE_DOMINIK; licznik++; break; case 4: state = STATE_DZIECI; licznik=1; break; } } break; } } void zosia(){ switch(state1){ case 6: if(cMillis - pMillis1 <= interval1){ lcd.setCursor(0,0); lcd.print(" Czesc Zosia :-)"); } else{ pMillis1=cMillis; state1 = STATE_OFF; } break; case 7: if(cMillis - pMillis1 <= interval1){ lcd.clear(); } else{ pMillis1 = cMillis; state1 = STATE_ON; } break; } } void wait_and_checkButton(){ if((cMillis - pMillis > interval) || ((cMillis - pMillis < interval) && (digitalRead(2) ==LOW))){ pMillis = cMillis; lcd.clear(); wyswietlono = false; state = STATE_WYNIKI; } } void franek(){ if (wyswietlono == false){ lcd.setCursor(0,0); lcd.print("Czesc Franek :-)"); wyswietlono = true; } } void wyniki(){ dht11.read(pinDHT11, &temperature, &humidity, NULL); //odczyt z czujnika lcd.setCursor(2, 0); lcd.print("Wilg.: "); lcd.print((int)humidity); lcd.print("%RH"); lcd.setCursor(2, 1); lcd.print("Temp.: "); lcd.print((int)temperature); lcd.print("*C"); // wyswietlamy temp. i wilgotnosc wraz z jednostkami } void dominik(){ if (wyswietlono == false){ lcd.setCursor(0,0); lcd.print("Czesc Dominik:-)"); wyswietlono = true; } } void dzieci(){ if (wyswietlono == false){ lcd.setCursor(4,0); lcd.print("Dominik"); //tekst 2 linii lcd.setCursor(2,1); lcd.print("Zosia Franek"); wyswietlono = true; } } void jasnosc(){ odczytSw = analogRead(A3); swiatlo = map(odczytSw, 100, 900, 50, 255); analogWrite(10,swiatlo); }
Elvis Grudzień 8, 2017 Udostępnij Grudzień 8, 2017 Nadal używasz magiczne liczby zamiast stałych... w case możesz zastąpić liczby nazwami stałych i będzie dużo czytelniej. To samo dotyczy pinów.
SOYER Grudzień 8, 2017 Autor tematu Udostępnij Grudzień 8, 2017 Niestety nie rozumiem chyba działania #define. jeśli napiszę #define STATE_ON on i następnie wstawię to "on" w odpowiednie case i "state = " to mi wywala " 'on' was not declared in this scope " Podobnie zapis np #define led1 4 powoduje, że w czasie kompilacji led1 jest zamieniane na 4 i program wie, że chodzi o pin 4. digitalWrite(led1, HIGH); Więc jak mogę tą czwórkę zastąpić nazwą? Wybacz ale nie kapuję...
Elvis Grudzień 8, 2017 Udostępnij Grudzień 8, 2017 #define led1 4 To informacja dla preprocesora, ze wystapienia "led1" ma zastapic przez 4. Podobnie: #define STATE_ON on oznacza ze STATE_ON zstanie zastapione przez "on". Ale zarowno 4, jak i "on" musi miec w tym miejscu sens dla kompilatora. Wiec jesli "on" jest nieoporawne, dostaniesz blad. Nie chodzi mi o pozbycie sie "4" z linii #define, ale uzywanie: digitalWrite(led1, HIGH); oraz case STATE_ON: Taki kod jest znacznie latwiej czytac. A w nastepnym kroku mozesz poczytac co robi enum w jezyku C 1
SOYER Grudzień 8, 2017 Autor tematu Udostępnij Grudzień 8, 2017 DZIĘKI WIELKIE ELVIS . Jesteś niezawodny. Dopytam jeszcze o state i case, czy dobrze rozumuję, w linijce #define STATE_SUPER 7 STATE_SUPER jest dla nas i naszej wygody, a kompilator potrzebuje '7' tak? a w linijce: case STATE_SUPER: też STATE_SUPER jest dla nas i naszej wygody, a kompilator potrzebuje(i sobie zamienia zgodnie z #define) na '7' tak? Mój poprawiony kod (enum w użyciu, ułatwia sprawę ) #include <LiquidCrystal.h> //Dołączenie bilbioteki #include <SimpleDHT.h> LiquidCrystal lcd(8, 3, 4, 5, 6, 7); //Informacja o podłączeniu SimpleDHT11 dht11; #define fotorezystor A3 #define ledLCD 10 #define przycisk 2 enum STALE {DZIECI=1, ZOSIA, FRANEK, DOMINIK, WYNIKI, ON, OFF}; int stan = WYNIKI; int miganie = ON; int licznik = 1; int swiatlo = 0; int odczytSw = 0; byte temperature = 0; byte humidity = 0; int pinDHT11 = 13; //pin czujnika unsigned long cMillis; unsigned long pMillis = 0; unsigned long pMillis1 = 0; const long interval = 5000; const long interval1 = 500; boolean wyswietlono = false; void setup() { pinMode(ledLCD, OUTPUT); pinMode(przycisk, INPUT_PULLUP); lcd.begin(16, 2); Serial.begin(9600); } void loop() { cMillis = millis(); Serial.println(przycisk); jasnosc(); switch(stan){ case DZIECI: dzieci(); wait_and_checkButton(); break; case ZOSIA: zosia(); wait_and_checkButton(); break; case FRANEK: franek(); wait_and_checkButton(); break; case DOMINIK: dominik(); wait_and_checkButton(); break; case WYNIKI: if (wyswietlono == false){ wyniki(); wyswietlono = true; } if(cMillis - pMillis > interval){ pMillis = cMillis; wyswietlono = false; lcd.clear(); switch(licznik){ case 1: stan = ZOSIA; licznik++; break; case 2: stan = FRANEK; licznik++; break; case 3: stan = DOMINIK; licznik++; break; case 4: stan = DZIECI; licznik=1; break; } } break; } } void zosia(){ switch(miganie){ case ON: if(cMillis - pMillis1 <= interval1){ lcd.setCursor(0,0); lcd.print(" Czesc Zosia :-)"); } else{ pMillis1=cMillis; miganie = OFF; } break; case OFF: if(cMillis - pMillis1 <= interval1){ lcd.clear(); } else{ pMillis1 = cMillis; miganie = ON; } break; } } void wait_and_checkButton(){ if((cMillis - pMillis > interval) || ((cMillis - pMillis < interval) && (digitalRead(przycisk) ==LOW))){ pMillis = cMillis; lcd.clear(); wyswietlono = false; stan = WYNIKI; } } void franek(){ if (wyswietlono == false){ lcd.setCursor(0,0); lcd.print("Czesc Franek :-)"); wyswietlono = true; } } void wyniki(){ dht11.read(pinDHT11, &temperature, &humidity, NULL); //odczyt z czujnika lcd.setCursor(2, 0); lcd.print("Wilg.: "); lcd.print((int)humidity); lcd.print("%RH"); lcd.setCursor(2, 1); lcd.print("Temp.: "); lcd.print((int)temperature); lcd.print("*C"); // wyswietlamy temp. i wilgotnosc wraz z jednostkami } void dominik(){ if (wyswietlono == false){ lcd.setCursor(0,0); lcd.print("Czesc Dominik:-)"); wyswietlono = true; } } void dzieci(){ if (wyswietlono == false){ lcd.setCursor(4,0); lcd.print("Dominik"); //tekst 2 linii lcd.setCursor(2,1); lcd.print("Zosia Franek"); wyswietlono = true; } } void jasnosc(){ odczytSw = analogRead(fotorezystor); swiatlo = map(odczytSw, 100, 900, 50, 255); analogWrite(ledLCD, swiatlo); } Jeszcze raz dziękuję, program rzeczywiście teraz nawet dla mnie wygląda jaśniej Co do zmiennych millis rzeczywiście trafiłeś w sedno bo myślałem(??), że one są jakieś "magiczne" szczególnie ta aktualna, u mnie jako cMillis, a oczywiście to zwykłe zmienne które trzeba odpowiednim czasie i miejscu aktualizować. Teraz czeka mnie I2C i kolejne czujniki temperatury. Pozdrawiam. P.S. zastanawia mnie jeszcze wnętrze case: WYNIKI co tam można uprościć?
SOYER Grudzień 13, 2017 Autor tematu Udostępnij Grudzień 13, 2017 Witam, trochę bawiłem się z millisami znowu, udało mi się zrobić przewijanie tekstu na LCD, w funkcji franek() dołożyłem kolejną FSM, wszystko bez ani jednego delay(). Dodałem cyfrowy czujnik temperatury. Działa bezbłędnie na 25m skrętce(najtańszej) po której mam też puszczone zasilanie i sygnał z kamery, łączonej jeszcze po drodze w trzech miejscach Wszelkie sugestie mile widziane:-) Pozdrawiam #include <LiquidCrystal.h> //Dołączenie bilbioteki #include <SimpleDHT.h> #include <OneWire.h> #include <DallasTemperature.h> LiquidCrystal lcd(8, 3, 4, 5, 6, 7); OneWire oneWire(9); DallasTemperature sensors(&oneWire); DeviceAddress terZew = {0x28, 0x2E, 0xA6, 0xEC, 0x8, 0x0, 0x0, 0x6A}; SimpleDHT11 dht11; #define fotorezystor A3 #define ledLCD 10 #define przycisk 2 #define termZew 9 enum STALE {DZIECI=1, ZOSIA, FRANEK, DOMINIK, TERM_ZEW, WYNIKI, ON, OFF, UP, DOWN}; int stan = WYNIKI; int miganie = ON; int licznik = 1; int up_down = UP; int swiatlo = 0; int odczytSw = 0; byte temperature = 0; byte humidity = 0; int pinDHT11 = 13; //pin czujnika unsigned long cMillis; unsigned long pMillis = 0; unsigned long pMillis1 = 0; const long interval = 6000; const long interval1 = 500; const long scroll_speed = 400; boolean wyswietlono = false; byte tempMAX = 0; byte tempMIN = 0; byte tempZEW; void setup() { pinMode(ledLCD, OUTPUT); pinMode(przycisk, INPUT_PULLUP); pinMode(termZew, INPUT); lcd.begin(16, 2); Serial.begin(9600); tempMAX = sensors.getTempCByIndex(0); tempMIN = sensors.getTempCByIndex(0); } void loop() { cMillis = millis(); Serial.println(przycisk); jasnosc(); switch(stan){ case DZIECI: dzieci(); wait_and_checkButton(); break; case ZOSIA: zosia(); wait_and_checkButton(); break; case FRANEK: franek(); wait_and_checkButton(); break; case DOMINIK: dominik(); wait_and_checkButton(); break; case TERM_ZEW: if(wyswietlono==false){ term_zew(); wyswietlono=true; } wait_and_checkButton(); break; case WYNIKI: if (wyswietlono == false){ wyniki(); wyswietlono = true; } if(cMillis - pMillis > interval){ pMillis = cMillis; wyswietlono = false; lcd.clear(); switch(licznik){ case 1: stan = TERM_ZEW; licznik++; break; case 2: stan = ZOSIA; licznik++; break; case 3: stan = FRANEK; licznik++; break; case 4: stan = DOMINIK; licznik++; break; case 5: stan = DZIECI; licznik=1; break; } } break; } } void zosia(){ switch(miganie){ //napis miga z częstotliwością (interval1) case ON: if(cMillis - pMillis1 <= interval1){ lcd.setCursor(0,0); lcd.print(" Czesc Zosia :-)"); } else{ pMillis1=cMillis; miganie = OFF; } break; case OFF: if(cMillis - pMillis1 <= interval1){ lcd.clear(); } else{ pMillis1 = cMillis; miganie = ON; } break; } } void wait_and_checkButton(){ //czekamy czas(interval) i ciągle sprawdzamy przycisk if((cMillis - pMillis > interval) || ((cMillis - pMillis < interval) && (digitalRead(przycisk) ==LOW))){ pMillis = cMillis; lcd.clear(); wyswietlono = false; stan = WYNIKI; } } void franek(){ //napis pojawia się raz u góry raz u dołu z częstotliwością(interval1)[FSM;-)] switch(up_down){ case UP: if(cMillis - pMillis1 <= interval1){ lcd.setCursor(2,0); lcd.print("Czesc Franek"); } else{ lcd.clear(); pMillis1=cMillis; up_down = DOWN; } break; case DOWN: if(cMillis - pMillis1 <= interval1){ lcd.setCursor(0,1); lcd.print("Czesc Franek :-)"); } else{ lcd.clear(); pMillis1 = cMillis; up_down = UP; } break; } } void wyniki(){ dht11.read(pinDHT11, &temperature, &humidity, NULL); //odczyt z czujnika lcd.setCursor(2, 0); lcd.print("Wilg.: "); lcd.print((int)humidity); lcd.print("%RH"); lcd.setCursor(2, 1); lcd.print("Temp.: "); lcd.print((int)temperature); lcd.print("*C"); // wyswietlamy temp. i wilgotnosc wraz z jednostkami } void dominik(){ //napis przesuwa się z poza ekranu od lewej do prawej z prędkością 1 znak na(scroll_speed) lcd.setCursor(0,0); lcd.print(" Czesc Dominik:-)"); for (int positionCounter = 0; positionCounter < 13; positionCounter++) { lcd.scrollDisplayLeft(); while(cMillis-pMillis1<=scroll_speed){ cMillis=millis(); } if(cMillis-pMillis1>scroll_speed){ pMillis1=cMillis; } } } void dzieci(){ //tu planuję rozjazd pierwszej lini na prawo, a drugiej w lewo, ale na razie wymiękam... lcd.setCursor(4,0); lcd.print("Dominik"); lcd.setCursor(2,1); lcd.print("Zosia Franek"); } void jasnosc(){ //dostosowanie jasności LCD do oświetlenia pomieszczenia odczytSw = analogRead(fotorezystor); swiatlo = map(odczytSw, 100, 900, 50, 255); analogWrite(ledLCD, swiatlo); } void term_zew(){ //termometr zew. z pamięcią temperatury max. i min. sensors.requestTemperatures(); tempZEW = sensors.getTempCByIndex(terZew); if (tempZEW > tempMAX) { tempMAX = tempZEW; } if (tempZEW < tempMIN) { tempMIN = tempZEW; } lcd.setCursor(2,0); lcd.print("Temp.zew. "); lcd.print(tempZEW); lcd.print("*C"); lcd.setCursor(2,1); lcd.print("Temp.min. "); lcd.print(tempMIN); lcd.print("*C"); wyswietlono=true; }
SOYER Grudzień 16, 2017 Autor tematu Udostępnij Grudzień 16, 2017 Cześć chłopaki, postawiłem takie zadanie przed sobą: wyświetlacz lcd 2x16, w pierwszej linii tekst i w drugiej tekst, i teraz chcę by jednocześnie górny tekst "pojechał" w lewo, a dolny w prawo. Chciałem to zrobić jako maszyna stanów przełączająca się na tyle szybko pomiędzy górną i dolną linią żeby ludzkie oko tego nie wyłapało. Przewijanie oparte na funkcjach lcd.scrollDisplayRight() ew. Left oczywiście. Tylko mam problem jak zapamiętać w jakim konkretnym miejscu jest dana linia(STAN), tzn ile już przewinęła. #include LiquidCrystal lcd(8, 3, 4, 5, 6, 7); unsigned long cMillis=0; unsigned long pMillis=0; unsigned long pMillis1=0; const long interval = 500; const long interval1 = 50; enum STALE {LINE1 = 1, LINE2} stan1 = LINE1; #define fotorezystor A3 #define ledLCD 10 int swiatlo = 0; int odczytSw = 0; int scroll_state_line1=0; int scroll_state_line2=0; int pozycja1 = 0; int pozycja2 = 0; void setup() { pinMode(ledLCD, OUTPUT); lcd.begin(16, 2); } void loop() { jasnosc(); cMillis = millis(); pMillis1 = cMillis; switch(stan1){ case LINE1: linia1(); if(cMillis -pMillis1>interval1){ stan1 = LINE2; pMillis1=cMillis; } break; case LINE2: linia2(); if(cMillis-pMillis1>interval1){ stan1=LINE1; pMillis1 = cMillis; } break; } } void jasnosc(){ odczytSw = analogRead(fotorezystor); swiatlo = map(odczytSw, 100, 900, 50, 255); analogWrite(ledLCD, swiatlo); } void linia1(){ lcd.setCursor(0,0); lcd.print(" Dominik"); for (pozycja1; pozycja1<(pozycja1 + 1); pozycja1++) { lcd.scrollDisplayRight(); while(cMillis-pMillis<=interval){ cMillis=millis(); } if(cMillis-pMillis>interval){ pMillis=cMillis; lcd.clear(); scroll_state_line1=pozycja1; } } } void linia2(){ lcd.setCursor(0,1); lcd.print(" Zosia Franek"); for (pozycja2; pozycja2 <(pozycja2 + 1); pozycja2++) { lcd.scrollDisplayLeft(); while(cMillis-pMillis<=interval){ cMillis=millis(); } if(cMillis-pMillis>interval){ pMillis=cMillis; lcd.clear(); scroll_state_line2=pozycja2; } } } Nie działa, ale pokazuje jak to robię, że nie działa Da się to zrobić? Jak tak to jak?
deshipu Grudzień 16, 2017 Udostępnij Grudzień 16, 2017 Przecież zapamiętujesz w globalnych zmiennych pozycja1 i pozycja2? Tylko nie rozumiem po co ci tam te pętle for.
Elvis Grudzień 16, 2017 Udostępnij Grudzień 16, 2017 SOYER, nie działa bo wyhodowałeś sobie delay-a: while(cMillis-pMillis<=interval){ cMillis=millis(); } To jest dokładnie treść funkcji delay - więc ma prawo nie działać.
SOYER Grudzień 16, 2017 Autor tematu Udostępnij Grudzień 16, 2017 // include the library code: #include <LiquidCrystal.h> // initialize the library by associating any needed LCD interface pin // with the arduino pin number it is connected to const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2; LiquidCrystal lcd(rs, en, d4, d5, d6, d7); void setup() { // set up the LCD's number of columns and rows: lcd.begin(16, 2); // Print a message to the LCD. lcd.print("hello, world!"); delay(1000); } void loop() { // scroll 13 positions (string length) to the left // to move it offscreen left: for (int positionCounter = 0; positionCounter < 13; positionCounter++) { // scroll one position left: lcd.scrollDisplayLeft(); // wait a bit: delay(150); } // scroll 29 positions (string length + display length) to the right // to move it offscreen right: for (int positionCounter = 0; positionCounter < 29; positionCounter++) { // scroll one position right: lcd.scrollDisplayRight(); // wait a bit: delay(150); } // scroll 16 positions (display length + string length) to the left // to move it back to center: for (int positionCounter = 0; positionCounter < 16; positionCounter++) { // scroll one position left: lcd.scrollDisplayLeft(); // wait a bit: delay(150); } // delay at the end of the full loop: delay(1000); } To oryginalny kod z "Przykłady" i dalej "LiquidCrystal" i "Scroll". Wymieniłem delay na fragment zacytowany przez Ciebie Elvis (bo delay jest be) i wstawiłem pętle for o które pytasz deshipu... tak jak w tym przykładzie. Nie potrafię inaczej zrobić przewijania, tylko na tym przykładzie... P.S. wymyślenie jak zapisać delay przy pomocy millis zajęło mi dobre pół godziny i trochę nerwów ale wymyśliłem
SOYER Styczeń 16, 2021 Autor tematu Udostępnij Styczeń 16, 2021 (edytowany) Tak teraz czytam te moje posty w tym temacie To naprawdę byłem ja? Z perspektywy czasu widzę dopiero jak wiele się tutaj nauczyłem. DZIĘKI WSZYSCY FORBOTOWICZE KTÓRZY POŚWIĘCALIŚCIE MI CZAS I NERWY Choć teraz zdaję sobie sprawę jak wiele nie potrafię, to jednak dzięki waszej pomocy własnej pracy i teraz już pewnemu doświadczeniu, umiem wyłapywać szkolne błędy, brak nawiasu kiedy kompilator wywala bląd w dziwnym miejscu, wiem co to biblioteki, potrafię je używać. Podstawy, ale jakże trudno było na początku, jednak da się. Nauczyłem się korzystać z przeogromnej bazy wiedzy w internetach na temat arduino i pokrewnych, jednak FORBOT zawsze pozostaje ostateczną wyrocznią, ew. szybką pomocą. Co do millis, to od dawna używam biblioteki timers, jeszcze mnie nie zawiodła ani na arduino ani na esp. Kluczowe było jednak zrozumienie tych zależności między delay, millis(), działaniem programu. Kuczowe było zrozumienie tego, że o ile mu nie przeszkadzamy, to główna pętla leci w kółko kupę razy na sekundę, to główny warunek zrozumienia prawidłowego działania tego co piszemy. Ja jako początkujący nie do końca rozumiałem tego konsekwencje, też to przyszło z czasem. Także apel do początkujących, z programowaniem jak ze wszystkim, trzeba ćwiczyć, ćwiczyć i jeszcze raz ćwiczyć. Stawiać sobie coraz ambitniejsze cele, ale zaczynać od prostych. Pozdrawiam Edytowano Styczeń 16, 2021 przez SOYER 1 1
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »