Skocz do zawartości

Sterownik Airride, problem z sterowaniem w funkcji switch.


Juszczu

Pomocna odpowiedź

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 przez Juszczu
Link do komentarza
Share on other sites

(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 przez Peposh
Link do komentarza
Share on other sites

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!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.