Juszczu Napisano Maj 8, 2021 Udostępnij Napisano Maj 8, 2021 (edytowany) Witam, postaram się w skrócie opisać założenie i problem. Założenie jest, iż Arduino ma sterować zawieszeniem pneumatycznym w samochodzie [tzw. Airride]. Chodzi dokładnie o ustawienie wysokości zawieszenia poprzez odczyt ciśnienia na osiach przód i tył oraz wybranie odpowiedniego programu. W teorii bardzo proste, lecz pojawił się problem, gdyż o ile poza funkcją switch sterowanie przekźnikiem działa jak powinno. Czyli jeżeli ciśnienie jest niższe od zadanego przekaźnik zostaje włączony do czasu aż ciśnienie wzrośnie do żądanej wartości. Lecz gdy ten sam kod wrzucę już do funkcji switch pod odpowiedni przypadek, wtedy gdy ciśnienie jest niższe od zadanego przekaźnik zalącza się, lecz po osiągnięciu zadanego ciśnienia nie wyłącza się. Kod w fazie testowej wygląda tak: #include <Bounce2.h> Bounce b = Bounce(); // Przycisk opuszczania Bounce a = Bounce(); // Przycisk podnoszenia int cisnienieP = 0; // zmienna ciśniena z przodu int cisnienieT = 0; // zmienna ciśnienia z tyłu int gora = 12; // podnoszenie int dol = 11; // opuszczanie int PG = 7; // przekaźnik przód podnoszenie int PD = 6; // przekaźnik przód opuszczanie int TG = 5; // przekaźnik tył podnoszenie int TD = 4; // przekaźnik tył opuszczanie int podnies; // funkcja podnoiszenia int licznik; // licznik podnoszenia int opusc; // funkcja opuszczania int count; // licznik opiuszczania long czas; void setup() { Serial.begin(9600); pinMode(gora, INPUT_PULLUP); pinMode(dol, INPUT_PULLUP); pinMode(PG, OUTPUT); pinMode(PD, OUTPUT); pinMode(TG, OUTPUT); pinMode(TD, OUTPUT); digitalWrite(PG, HIGH); digitalWrite(PD, HIGH); digitalWrite(TG, HIGH); digitalWrite(TD, HIGH); b.attach(gora); b.interval(5); a.attach(dol); a.interval(5); } void loop() { cisnienieP = analogRead(A0); cisnienieT = analogRead(A1); b.update(); if ( b.fell() ) { delay(50); licznik++; if(licznik == 4) licznik = 0; czas = millis()/1000; } if(millis()/1000-czas > 2 && podnies < 4) { podnies = licznik; licznik = 0; } switch(podnies) { case 1: { digitalWrite(PG, HIGH); digitalWrite(PD, HIGH); digitalWrite(TG, HIGH); digitalWrite(TD, HIGH); break; } case 2: { if (cisnienieP < 488) { digitalWrite(PG, LOW); } else { digitalWrite(PG, HIGH); } delay(50); break; } case 3: { digitalWrite(PG, HIGH); digitalWrite(PD, LOW); digitalWrite(TG, HIGH); digitalWrite(TD, LOW); delay(1000); digitalWrite(PG, HIGH); digitalWrite(PD, HIGH); digitalWrite(TG, HIGH); digitalWrite(TD, HIGH); break; } } a.update(); if ( a.fell() ) { delay(50); count++; if(count == 4) count = 0; czas = millis()/1000; } if(millis()/1000-czas > 2 && opusc < 4) { opusc = count; count = 0; } switch(opusc) { case 1: { digitalWrite(PG, HIGH); digitalWrite(PD, HIGH); digitalWrite(TG, HIGH); digitalWrite(TD, HIGH); break; } case 2: { digitalWrite(PG, HIGH); digitalWrite(PD, HIGH); digitalWrite(TG, HIGH); digitalWrite(TD, HIGH); break; } case 3: { digitalWrite(PG, HIGH); digitalWrite(PD, LOW); digitalWrite(TG, HIGH); digitalWrite(TD, LOW); delay(1000); digitalWrite(PG, HIGH); digitalWrite(PD, HIGH); digitalWrite(TG, HIGH); digitalWrite(TD, HIGH); break; } } } Docelowo miał wyglądać tak (tylko poglądowo): #include <Bounce2.h> Bounce b = Bounce(); // Przycisk opuszczania Bounce a = Bounce(); // Przycisk podnoszenia int cisnienieP = 0; // zmienna ciśniena z przodu int cisnienieT = 0; // zmienna ciśnienia z tyłu int gora = 12; // podnoszenie int dol = 11; // opuszczanie int PG = 7; // przekaźnik przód podnoszenie int PD = 6; // przekaźnik przód opuszczanie int TG = 5; // przekaźnik tył podnoszenie int TD = 4; // przekaźnik tył opuszczanie int podnies; // funkcja podnoiszenia int licznik; // licznik podnoszenia int opusc; // funkcja opuszczania int count; // licznik opiuszczania long czas; void setup() { Serial.begin(9600); pinMode(gora, INPUT_PULLUP); pinMode(dol, INPUT_PULLUP); pinMode(PG, OUTPUT); pinMode(PD, OUTPUT); pinMode(TG, OUTPUT); pinMode(TD, OUTPUT); digitalWrite(PG, HIGH); digitalWrite(PD, HIGH); digitalWrite(TG, HIGH); digitalWrite(TD, HIGH); b.attach(gora); b.interval(5); a.attach(dol); a.interval(5); } void loop() { cisnienieP = analogRead(A0); cisnienieT = analogRead(A1); b.update(); if ( b.fell() ) { delay(50); licznik++; if(licznik == 4) licznik = 0; czas = millis()/1000; } if(millis()/1000-czas > 2 && podnies < 4) { podnies = licznik; licznik = 0; } switch(podnies) { case 1: { digitalWrite(PG, HIGH); digitalWrite(PD, HIGH); digitalWrite(TG, HIGH); digitalWrite(TD, HIGH); break; } case 2: { if (cisnienieP < 488) { digitalWrite(PG, LOW); } else { digitalWrite(PG, HIGH); } delay(50); { if (cisnienieT < 325) { digitalWrite(TG, LOW); } else { digitalWrite(TG, HIGH); } delay(50); break; } case 3: { if (cisnienieP < 535) { digitalWrite(PG, LOW); } else { digitalWrite(PG, HIGH); } delay(50); { if (cisnienieT < 368) { digitalWrite(TG, LOW); } else { digitalWrite(TG, HIGH); } delay(50); break; } } a.update(); if ( a.fell() ) { delay(50); count++; if(count == 4) count = 0; czas = millis()/1000; } if(millis()/1000-czas > 2 && opusc < 4) { opusc = count; count = 0; } switch(opusc) { case 1: { digitalWrite(PG, HIGH); digitalWrite(PD, HIGH); digitalWrite(TG, HIGH); digitalWrite(TD, HIGH); break; } case 2: { if (cisnienieP > 488) { digitalWrite(PD, LOW); } else { digitalWrite(PD, HIGH); } delay(50); { if (cisnienieT > 325) { digitalWrite(TD, LOW); } else { digitalWrite(TD, HIGH); } delay(50); break; case 3: if (cisnienieP > 535) { digitalWrite(PD, LOW); } else { digitalWrite(PD, HIGH); } delay(50); { if (cisnienieT > 368) { digitalWrite(TD, LOW); } else { digitalWrite(TD, HIGH); } delay(50); break; } } } Oczywiście dana czynność czyli podniesienie czy opuszczenie musi wykonać się raz po wybraniu programu, następnie wrócić do stanu spoczynku. Czy dobrze rozumuje że problemem jest funkcja switch i tak na prawdę potrzebuję zrobić osobne pętle a sterować wyborem pętli?? Edytowano Maj 8, 2021 przez Juszczu Cytuj Link do komentarza Share on other sites More sharing options...
Peposh Maj 9, 2021 Udostępnij Maj 9, 2021 (edytowany) Przyjrzyj się na spokojnie temu kodu: b.update(); if ( b.fell() ) { //jeżeli wciśnięto przycisk delay(50); licznik++; //zmien licznik if(licznik == 4) licznik = 0; czas = millis()/1000; //zacznij liczyc czas } if(millis()/1000-czas > 2 && podnies < 4) //jezeli czas>2[s] { podnies = licznik; //ustaw zmienną podnies licznik = 0; //wyzeruj licznik } Zaczynasz liczyć czas po wciśnięciu przycisku. Po dwóch sekundach spełniony jest drugi warunek, zmienna podnieś=licznik(tak ma być), licznik=0. Program idzie dalej do switcha, gdzie wybiera się odpowiedni zestaw instrukcji (włącz przekaźnik). Wszystko działa jak trzeba, ale co się dzieje w następnej pętli? Warunek if (millis()/1000-czas>2 && podnies<4) nadal jest jest spełniony! Tym razem podnies=0 (bo licznik=0 z poprzedniej pętli), w switchu nie ma nic dla zera, więc nic się nie dzieje, przekaźnik nadal włączony. To samo dzieje się dla zmiennej opusc. Jeżeli program ma zrobić coś tylko raz(w Twoim przypadku zmienić zmienną podnies/opusc po 2s od klikania przyciskiem), to musi zapamiętać czy to już zrobił. W tym celu stosuje się tzw. flagi, czyli zmienne w których zapisujemy konieczność wykonania zadania(lub jego wykonanie): static bool podnies_zmiana=false; //nasza flaga w której zapiszemy, czy chcemy zmienić zmienną 'podnies'. Można ją też zadeklarować globalnie- wtedy bez 'static' b.update(); if ( b.fell() ) { //jeżeli wciśnięto przycisk delay(50); licznik++; //zmien licznik if(licznik == 4) licznik = 0; czas = millis()/1000; //zacznij liczyc czas podnies_zmiana=true; //chcemy zmienic stan 'podnies' } if(millis()/1000-czas > 2 && podnies < 4 && podnies_zmiana==true) //jezeli czas>2[s] i chcemy zmienic 'podnies'. to podnies<4 jest niepotrzebne, bo zawsze będzie true { podnies = licznik; //ustaw zmienną 'podnies' licznik = 0; //wyzeruj licznik podnies_zmiana=false; //już nie chcemy zmieniać 'podnies' do kolejnego wciśnięcia przycisku } Powrót programu do stanu "spoczynku" można zrealizować w switchu po napompowaniu zawieszenia, wystarczy zmienić podnies na 0(Twój switch nic nie robi dla 0). Przy okazji znalazłem mały błąd związany z break: switch(podnies){ //(...) case 2: { if (cisnienieP < 488) { //za małe ciśnienie- pompujemy digitalWrite(PG, LOW); } else { //cisnienie ok, przestajemy pompować, podnies=0 bo już nic nie chcemy robić digitalWrite(PG, HIGH); podnies=0; } delay(50); } break; //break; dajemy za klamrą! //itd. } Analogiczne musisz pozmieniać kod dla zmiennej opusc. Edytowano Maj 9, 2021 przez Peposh 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!