Skocz do zawartości

BananWszyscy

Użytkownicy
  • Zawartość

    22
  • Rejestracja

  • Ostatnio

Reputacja

1 Neutralna

O BananWszyscy

  • Ranga
    2/10

Informacje

  • Płeć
    Mężczyzna
  • Lokalizacja
    Warka
  • Zawód
    Automatyk
  1. Dobra, wieczorem usiądę i spróbuję to przepisać potem tu wrócę i znowu będę truł tyłki
  2. do daniel89: Tak, chodzi tu o to, że w pętli while(1) wywoływana jest funkcja loop() którą sobie tam piszemy w IDE i przez to mamy pętlę nieskończoną. A za pomocą switcha maszynę można zaimplementować Do ethanak Tak, tylko nadal to pytanie jedno. O co chodzi z tym, że procedura/funkcja obsługa_prasy ma zależeć od decyzji operatora i w ogóle nie zależeć od funkcji obsługa_przycisków. Bo obsługa przycisków rozumiem ma zwracać właśnie ten ich stan (wciśnięcie czy co tam inne się działo). Biorąc pod uwagę, że zwracałaby ona np. tablicę z 0 i 1 na temat przycisków, to przekazując ją do obsługi_prasy na jej podstawie można decydować o wyjściu ze stanu czekania. Bo niezbyt wiem o co chodzi z tym, że nie przyciski a decyzja
  3. A ta decyzja rozumiem ma być odczytana w obsłudze klawiszy tak? Bo tego akurat nie rozumiem. Znaczy no trochę mnie bolała ta nakładka, nie wiem po co te całe setupy, nie setupy jak wiedziałem, że w mainie implementuje się pętlę nieskończoną, a to co w setupie jest przed pętlą wprost wklejane. I tak wiem, jak działa program w C, już nie musicie aż tak tłumaczyć Wracając do pytania: no tak, czyli to powinno wyglądać chyba tak: while(1) { obsługa_przycisków(); obsługa_prasy(); } a w funkcji/procedurze obsługa prasy powinno być wtedy coś takiego void obsługa_prasy() { maszyna stanów - switch(stan) i np. case (stempel_w_gore) ruch_stempla_w_gore(); break; .... } EDIT. Czy to coś takiego ma być? Czy w ogóle podział na stany jakie mam nie ma sensu do takiego układu, no bo skoro byłby cały czas w stanie np. czekaj, to ta funkcja po prostu przylatywała do czekaj, w czekaju ify nie byłyby spełnione więc skok na koniec i od nowa obieg pętli
  4. No dobra, to jeszcze jedno takie pytanie - używając funkcji do podziału tego kodu i samo ich wywoływanie w głównej pętli (tutaj loop()) narzuci, że chcąc pozbywać się zmiennych globalnych trzeba będzie przekazywać wszystkie te zmienne jako argumenty - czy wtedy pakuje się to w struktury? Możecie to szerzej opowiedzieć jak zrobić tę praskę, skoro mój sposób z poprzedniego postu czyli: nie byłby najlepszy do późniejszych zmian (tak napisał ethanak :P)? EDIT. już wiem, że komunikację robię tak jak w plckach, czyli kiedy mi się podoba... właściwie uart w atmedze jest sprzętowy
  5. Ale to było jakieś zadanko do nauki znalezione w internecie I dlaczego ma być trudno wprowadzić poprawkę - jakoś dane o przyciskach muszą być przekazane do funkcji obsługi prasy - czyli jest oddzielność między obsługą przycisków, a resztą. Chyba, że są na to jakieś sposoby. To w końcu kiedy ten przesył danych między sterownikami powinien następować - od razu w "obsłudze" stanu w switchu czy później? EDIT. I czy istnieje jakiś inny sposób na debugowanie niż ten, co ja stosuje wysyłać wszystko szeregowo na terminal
  6. Masz ZAŁOŻENIE o 2 przyciskach, a z tego co wiem - założeń nie wolno zmieniać Sterowanie silnikami i innymi tematami to jest kwestia inna, bo tym już steruje zwykle inne urządzenie/moduł. Tu jest tylko główne sterowanie i ewentualny przesył danych po jakimś porcie szeregowym czy czymś podobnie - stąd te booleany, a chciałem też mieć lampki, żeby wyglądałooo Spoko, teraz wiem, że zamiast 4 linijek można uprościć to do 1, ok. Ale do teraz nie wiem czemu mam KONIECZNIE badać reakcję na zmianę stanu, a nie na aktualny stan. Według mnie badanie zmiany stanu także ogranicza się do badania stanu w każdej pętli/przerwaniu/czymkolwiek a efekt w TYM przykładzie będzie identyczny. A o omijaniu chodzi mi o: PROGRAM: (linijki) x x x y switch y1 - załóżmy mamy y1 i w bloku y1 siedzimy CAŁY CZAS nie wychodząc do x poniżej dopóki nie zmieni się stan albo pojawi się siłowy break (typu w pętli while); y2 x2 x2 x2 i pytanie było, czy powinno być tak jak na powyższym schemacie, czy po prostu zapisuje stan, robię co tam było, lecę dalej do x2, kolejny obieg, znowu ten stan, robię tu i lecę dalej do x2. i teraz wiem, że dobrze robię stosując tę opcję EDIT. jak to czytam, to rzeczywiście niejasno to napisałem EDIT2. Czy tobie chodzi o modułowość programu w tym momencie typu (dla prasy): PROGRAM: (linijki) jakieś tam deklaracje/inicjalizacje blabla PĘTLA GŁÓWNA: odczyt_przycisków(); - zwraca jakieś dane o tym, czy są wciśnięte jakieś przyciski, czy nie itp. itd. obsługa_prasy(); - na podstawie przycisków i poprzednich danych stanu maszyny decyduje co ma się dziać wyślij_dane(); wysyłka danych otrzymanych z funkcji obsługi prasy do sterowników podrzędnych napędów/zaworów itp. i ta wysyłka chyba musi być oddzielnie ze względu na łatwiejsza synchronizację urządzeń
  7. Bardziej rozmawiajmy o "prasie" - ta winda to były moje początki daawno temu, a wtedy nie byłęm na tyle mądry, żeby zwierać x kabelków jako wejścia do 1 kabelka masowego łapkami. Wiem, że delayów się nie stosuje Dlatego jest to przerwanie cykliczne, żeby tego nie przerabiać. A i tak, na początku obiegu wciśnięcie jest ignorowane, jeżeli w poprzedniej już było wykrycie wciśnięcia. Wiem też, że są przerwania od zmiany pinów na rejestr mikrokontrera (wtedy nie wiedziałem) i w czasie obsługi tego można sprawdzać, który przycisk został ruszony i wtedy setować jakieś tam flagi gdzieś tam To chyba się PCINT oznacza w dokumentacji Mnie najbardziej chodziło o to, czy ta pętla ma przebiegać non stop w koło pomijając niektóre elementy, czy siedzieć w tych niepomijanych non stop. O ile mnie zrozumiałeś
  8. No to u mnie ten stan jest zapamiętywany, a pętla idzie dalej. Znam maszynę stanów, bo na plckach jest baardzo często implementowana. Czyli moje myślenie jest jednak ok. EDIT. no bo przecież w tym momencie mogę bezproblemowo dorzucić jeszcze jednego switcha i oddzielnie sterować drugim urządzeniem, ponieważ pętla przebiega po całości, a nie siedzi w określonym momencie X czasu (poza czasem niezbędnym do wykonania instrukcji)
  9. Zwracam się z taką małą prośbą do was wszystkich, użytkownicy tego forum Otóż zaczniemy od przykładu - prosty arduinowy kodzik pisany na kolanie, który ma za zadanie sterować prasą, w której należy trzymać 2 przyciski przez określony czas, aby wyzwolić ruch roboczy oraz czas miedzy wciśnięciem jednego i drugiego przycisku nie może przekroczyć jakiejś wartości. W programie nie uwzględniłem inicjalizacji i jakiejś konkretnej obsługi błędów czy awarii: //wejscia #define przycisk_lewy 2 #define przycisk_prawy 3 #define przycisk_kasuj 4 #define stempel_w_gorze 5 #define stempel_w_dole 6 //wyjscia #define ruch_w_dol 12 #define ruch_w_gore 13 #define blokada_narzedzia 10 #define sygnalizacja_dzp 7 #define sygnalizacja_gzp 8 enum st { czekaj, //0 stempel_gora, //1 stempel_dol, //2 czekaj_odpuszczenie_przyciskow, //3 awaria, //4 czekaj_przycisk_drugi, //5 opoznienie_zalaczenia //6 }; st stan = czekaj; short int licznik_cykli = 0; boolean stempel_dzp = false; boolean stempel_gzp = true; boolean stempel_ruch_gora = false; boolean stempel_ruch_dol = false; boolean blokada_stempla = false; boolean przycisk_lewy_ON = false; boolean przycisk_prawy_ON = false; boolean przycisk_kasuj_ON = false; void setup() { //wejscia pinMode(przycisk_lewy, INPUT_PULLUP); pinMode(przycisk_prawy, INPUT_PULLUP); pinMode(przycisk_kasuj, INPUT_PULLUP); pinMode(stempel_w_gorze, INPUT_PULLUP); pinMode(stempel_w_dole, INPUT_PULLUP); //wyjscia pinMode(ruch_w_dol, OUTPUT); pinMode(ruch_w_gore, OUTPUT); pinMode(blokada_narzedzia, OUTPUT); pinMode(sygnalizacja_dzp, OUTPUT); pinMode(sygnalizacja_gzp, OUTPUT); Serial.begin(9600); } void loop() { static unsigned long poczatek_czasu; //odczyt wejsc na poczatku petli: if (digitalRead(stempel_w_gorze) == LOW) { stempel_dzp = false; stempel_gzp = true; } if (digitalRead(stempel_w_dole) == LOW) { stempel_gzp = false; stempel_dzp = true; } if (digitalRead(przycisk_lewy) == LOW) przycisk_lewy_ON = true; else przycisk_lewy_ON = false; if (digitalRead(przycisk_prawy) == LOW) przycisk_prawy_ON = true; else przycisk_prawy_ON = false; if (digitalRead(przycisk_kasuj) == LOW) przycisk_kasuj_ON = true; else przycisk_kasuj_ON = false; // ewentualna czesc diagnostyczna if (stan==czekaj && stempel_gzp == false) stan=awaria; //maszyna stanów switch (stan) { case czekaj: if (blokada_stempla == false && stempel_gzp == true) { if (przycisk_lewy_ON == true || przycisk_prawy_ON == true) { stan = czekaj_przycisk_drugi; poczatek_czasu = millis(); } } break; case czekaj_przycisk_drugi: if (millis() - poczatek_czasu <= 1000UL) { if (przycisk_lewy_ON == true && przycisk_prawy_ON == true) { stan = opoznienie_zalaczenia; poczatek_czasu = millis(); } } else { stan = czekaj; } break; case opoznienie_zalaczenia: if (!(przycisk_lewy_ON == true && przycisk_prawy_ON == true)) stan = czekaj_odpuszczenie_przyciskow; else { if (millis() - poczatek_czasu >= 5000UL) { stan = stempel_dol; stempel_gzp = false; } } break; case stempel_gora: if (stempel_gzp == true) stan = czekaj; break; case stempel_dol: if (!(przycisk_lewy_ON == true && przycisk_prawy_ON == true)) { stan = stempel_gora; break; } if (stempel_dzp == true) { stan = stempel_gora; licznik_cykli++; if (licznik_cykli >= 10) blokada_stempla = true; } break; case czekaj_odpuszczenie_przyciskow: if (!(przycisk_lewy_ON || przycisk_prawy_ON)) stan = czekaj; break; case awaria: while(1) { digitalWrite(ruch_w_gore,LOW); digitalWrite(ruch_w_dol,LOW); digitalWrite(sygnalizacja_dzp,LOW); digitalWrite(sygnalizacja_gzp,LOW); delay(1000); digitalWrite(ruch_w_gore,HIGH); digitalWrite(ruch_w_dol,HIGH); digitalWrite(sygnalizacja_dzp,HIGH); digitalWrite(sygnalizacja_gzp,HIGH); delay(1000); } break; } //debugowanie Serial.print("Stan przyciskow: PP: "); Serial.print(przycisk_prawy_ON); Serial.print(" PL: "); Serial.print(przycisk_lewy_ON); Serial.print(" PK: "); Serial.print(przycisk_kasuj_ON); Serial.print(" RUCH G: "); Serial.print(stempel_ruch_gora); Serial.print(" D: "); Serial.print(stempel_ruch_dol); Serial.print(" Polozenie: GZP: "); Serial.print(stempel_gzp); Serial.print(" DZP: "); Serial.print(stempel_dzp); Serial.print(" Blokada: "); Serial.print(blokada_stempla); Serial.print(" Stan: "); switch (stan) { case awaria: Serial.println("awaria"); break; case czekaj: Serial.println("czekaj"); break; case stempel_gora: Serial.println("stempel gora"); break; case stempel_dol: Serial.println("stempel dol"); break; case czekaj_odpuszczenie_przyciskow: Serial.println("odpusc_przyciski"); break; case czekaj_przycisk_drugi: Serial.println("czekaj_drugi_przycisk"); break; case opoznienie_zalaczenia: Serial.println("opoznienie_zalaczenia"); break; } //ustawienie wyjsc if (stan == stempel_gora) { digitalWrite(ruch_w_gore, HIGH); digitalWrite(ruch_w_dol, LOW); } if (stan == stempel_dol) { digitalWrite(ruch_w_gore, LOW); digitalWrite(ruch_w_dol, HIGH); } if (stan == czekaj) { digitalWrite(ruch_w_gore, LOW); digitalWrite(ruch_w_dol, LOW); } if (stempel_gzp) digitalWrite(sygnalizacja_gzp, HIGH); else digitalWrite(sygnalizacja_gzp, LOW); if (stempel_dzp) digitalWrite(sygnalizacja_dzp, HIGH); else digitalWrite(sygnalizacja_dzp, LOW); } Ogólnie zajmuję się raczej programowaniem PLCków, więc taka forma jest dla mnie jak najbardziej naturalna, ponieważ nie ma sytuacji (oprócz tej awarii na sztukę), że cała pętla programu nie przejdzie najszybciej jak to możliwe. Wiem, że można te booleany itp. ładować w tablicę/strukturę, ale jak człowiek szybko coś robi to tak nie myśli. Ostatnio zostałem zrugany przez dwie osoby, że tak programów na mikrokontrolery to się nie pisze - podobnież wykonywanie kodu ma pozostać w "stanie" w jakim obecnie się znajduje, a nie wychodzić poza. Co dla mnie jest dosyć dziwne, bo dzięki mojej konstrukcji nie muszę korzystać z przerwań, aby zrobić obsługę ewentualnych przycisków (np. w windzie można by się uprzeć, aby skanowanie przycisków w środku windy i tych wzywających, przy tak prostych instrukcjach jak w tym programie nie musiałoby odbywać się w przerwaniu cyklicznym, tylko za każdym razem na początku pętli głównej). Stąd rodzi się moje pytanie - czy taki "styl" programowania jest dobry, aby pętla obiegana była w całości non stop, czy jednak powinienem próbować utrzymywać wykonywanie tylko w obrębie danego stanu, a ustawianie wyjść stosować jako funkcję i jej wywołania wszędzie umieszczać. Czy po prostu próbowano mnie wpuścić w maliny EDIT. Dorzucam jeszcze kodzik tej windy, którą robiłem... jak zaczynałem się uczyć takich rzeczy. Już wtedy próbowałem robić to po swojemu. Ogólnie wszystko działa za każdym razem, ale ostatnie wydarzenia wzbudziły pewne wątpliwości. // winda v2 //z 4 piętrami:> //z wyszukiwaniem po tablicach #include "TimerOne.h" //czujki #define guzik_pietro0 2 #define guzik_pietro1 3 #define guzik_pietro2 4 #define guzik_pietro3 5 //lampki sygn #define pietro0 10 #define pietro1 9 #define pietro2 8 #define pietro3 7 #define gora 13 #define dol 12 #define d_zamkniete 6 enum st { j_gora, j_dol, otw_drzwi, zam_drzwi, czekaj, awaria }; st stan = czekaj; boolean wolaj_pietro[4] = {}; byte aktualne_pietro = 0; boolean drzwi_zamkniete = false; boolean jazda_w_gore = false; boolean jazda_w_dol = false; byte poprzedni_ruch = 0; //0 w dół, 1 w górę void setup() { //czujki pinMode(guzik_pietro0, INPUT_PULLUP); //pietro 0 pinMode(guzik_pietro1, INPUT_PULLUP); // pietro 1 pinMode(guzik_pietro2, INPUT_PULLUP); // pietro 2 pinMode(guzik_pietro3, INPUT_PULLUP); //pietro 3 //lampki sygnalizujace pinMode(gora, OUTPUT); // jazda w gore pinMode(dol, OUTPUT); // jazda w dol pinMode(pietro0, OUTPUT); //pietro 0 pinMode(pietro1, OUTPUT); //pietro 1 pinMode(pietro2, OUTPUT); //pietro 2 pinMode(pietro3, OUTPUT); //pietro 3 pinMode(d_zamkniete, OUTPUT); //drzwi sa zamkniete // inicjalizacja przerwania cyklicznego Timer1.initialize(100000); Timer1.attachInterrupt(przerwanie_cykliczne); Serial.begin(9600); } void loop() { wolaj_pietro[aktualne_pietro] = false; //zerowanie wołania windy przy aktualnym piętrze if (aktualne_pietro >= 4) stan = awaria; switch (stan) { case czekaj: //4 //sprawdzenie czy zawolano winde za pomoca przyciskow for (int i = 0; i < 4; i++) { if (wolaj_pietro[i] == true) { stan = zam_drzwi; break; } } if (aktualne_pietro == 0) //pietro skrajne dolne { jazda_w_dol = false; jazda_w_gore = true; } if (aktualne_pietro == 3) //pietro skrajne gorne { jazda_w_dol = true; jazda_w_gore = false; } if ((aktualne_pietro != 0 && aktualne_pietro != 3) && stan == zam_drzwi) //obsługa pietr srodkowych // dla wiekszej liczby pieter po prostu negacja krańcowych { boolean zmiana_kierunku = true; if (poprzedni_ruch == 0) //wczesniej jechala w dol { for (int i = 0; i < aktualne_pietro; i++) //skanuj pietra ponizej, jezeli ktorekolwiek tak, to jedziemy dalej w dol { if (wolaj_pietro[i] == true) { jazda_w_gore = false; jazda_w_dol = true; zmiana_kierunku = false; break; } } } else if (poprzedni_ruch == 1) //jechala w gore { for (int i = aktualne_pietro; i < 4; i++) { if (wolaj_pietro[i] == true) { jazda_w_gore = true; jazda_w_dol = false; zmiana_kierunku = false; break; } } } if (zmiana_kierunku == true) { jazda_w_gore = !jazda_w_gore; jazda_w_dol = !jazda_w_dol; } } break; case zam_drzwi: //3 if (drzwi_zamkniete == false) { delay (1000); drzwi_zamkniete = true; } if (jazda_w_gore == true && jazda_w_dol == false) { stan = j_gora; delay(1000); } if (jazda_w_gore == false && jazda_w_dol == true) { stan = j_dol; delay(1000); } break; case j_gora: //0 delay(3000); aktualne_pietro += 1; if (wolaj_pietro[aktualne_pietro] == true) { stan = otw_drzwi; } poprzedni_ruch = 1; break; case j_dol://1 aktualne_pietro -= 1; delay(3000); if (wolaj_pietro[aktualne_pietro] == true) { stan = otw_drzwi; } poprzedni_ruch = 0; break; case otw_drzwi: //2 delay(1000); drzwi_zamkniete = false; stan = czekaj; break; case awaria: jazda_w_gore = false; jazda_w_dol = false; digitalWrite(dol, HIGH); digitalWrite(gora, HIGH); delay(2000); digitalWrite(dol, LOW); digitalWrite(gora, LOW); delay(2000); break; } // ustawienie wyjść sygnalizacyjnych if (stan == czekaj || stan == otw_drzwi || stan == zam_drzwi) { switch (aktualne_pietro) { case 0: digitalWrite(pietro0, HIGH); break; case 1: digitalWrite(pietro1, HIGH); break; case 2: digitalWrite(pietro2, HIGH); break; case 3: digitalWrite(pietro3, HIGH); break; } } else { digitalWrite(pietro0, LOW); digitalWrite(pietro1, LOW); digitalWrite(pietro2, LOW); digitalWrite(pietro3, LOW); } if (drzwi_zamkniete == true) digitalWrite(d_zamkniete, HIGH); else digitalWrite(d_zamkniete, LOW); if (jazda_w_gore == true && jazda_w_dol == false) { digitalWrite(dol, LOW); digitalWrite(gora, HIGH); } if (jazda_w_gore == false && jazda_w_dol == true) { digitalWrite(gora, LOW); digitalWrite(dol, HIGH); } //debugowanie Serial.print("Aktualne_pietro "); Serial.print(aktualne_pietro); Serial.print(" Stan przyciskow "); Serial.print(wolaj_pietro[0]); Serial.print(" "); Serial.print(wolaj_pietro[1]); Serial.print(" "); Serial.print(wolaj_pietro[2]); Serial.print(" "); Serial.print(wolaj_pietro[3]); Serial.print(" G: "); Serial.print(jazda_w_gore); Serial.print(" D: "); Serial.print(jazda_w_dol); Serial.print(" Stan: "); switch (stan) { case 5: Serial.println("awaria"); break; case 4: Serial.println("czekaj"); break; case 3: Serial.println("zamknij_drzwi"); break; case 2: Serial.println("otworz_drzwi"); break; case 1: Serial.println("jazda_w_dol"); break; case 0: Serial.println("jazda_w_gore"); break; } delay(1000); } void przerwanie_cykliczne() { //Pobranie stanow przyciskow, czujnika polozenia, zamkniecia drzwi if (digitalRead(guzik_pietro0) == LOW) wolaj_pietro[0] = true; if (digitalRead(guzik_pietro1) == LOW) wolaj_pietro[1] = true; if (digitalRead(guzik_pietro2) == LOW) wolaj_pietro[2] = true; if (digitalRead(guzik_pietro3) == LOW) wolaj_pietro[3] = true; }
  10. Ja np. używając Raspberry korzystam też z C++, w internecie króluje Python, ale pomocy przy C++ też jest dużo jakby co
  11. Tam gdzie "napięcie nagle się skończy" Skoro będzie przepalone, to najprawdopodobniej będzie "dziura" w obwodzie
  12. A normalnie po tej "zawieszce" malinka odpowiada na pingowanie itp? Kiedyś miałem w pracy przypadek, że na wyjściu sieci na zewnątrz wszystko działało, a komunikacji wewnątrz sieci nie było... Do teraz nikt nie wie co się tam stało
  13. Dlatego mówię, że warto ją czytać, tam jest sporo rzeczy napisane
  14. Arduinowe biblioteki nie są takie złe, szczególnie jak się przejrzy kod i kawałek dokumentacji, jeśli istnieje taka Fajnie eliminuje się z nimi niektóre problemy, ale też wypada wiedzieć jak one działają (jak np. biblioteka servo które wyłącza pwm na chyba jednym pinie, o ile dobrze pamiętam... a chyba pół dnia mi kiedyś zajęło z dojściem, czemu to cholerstwo nie działa)
  15. Trochę chyba chodzi o to, że za 1. obiegiem stanów ten zapamiętanyczas jest jakaś, potem już nigdzie nie jest zapisana (na końcu). Ale niezbyt wiem na co miałaby mieć wpływ, że przez nią wchodzimy w część kodu od ding dong. Raczej chodzi tu o to, że on jest kilka razy załączany. Dla wyobrażenia sobie tych styków możesz kiedyś dla treningu napisać kodzik dla samego kontraktronu z licznikiem, ile razy zmienia swój stan z jednego na drugi tylko przy zamknięciu drzwi, a może coś zaobserwujesz. EDIT. poprawiłęm gapę
×
×
  • Utwórz nowe...