Skocz do zawartości

Problem z wejściem w odpowiedni "case", instrukcja "switch case"


Olo_1994

Pomocna odpowiedź

Witam,

Natknąłem się problem z odpowiednim wykonywaniem warunków w funkcji SwitchCase. w poniższym kodzie program nie chce wejść w case 2, oraz case 3.

void sensorTypeUpDate () {

  switch (actualSensor) {
      
    case 1:
      Serial.print("wszedl w 1 petle");
      int odczyt = analogRead(lightSensor);
      light = map(odczyt, 0, 1023, 0, 100);
      sensorType = "Jasnosc:";
      sensorValue = String(light) + "%";
      break;

    case 2:
      Serial.print("wszedl w 2 petle");
      humidity = dht.getHumidity();
      if (dht.getStatusString() == "OK") {
        sensorType = "Wilgotnosc:";
        sensorValue = String(humidity) + "RH%";
      }
      break;
      
    case 3:
      Serial.print("wszedl w 3 petle");
      temperature = dht.getTemperature();
      if (dht.getStatusString() == "OK") {
        sensorType = "Temperatura:";
        sensorValue = String(temperature) + "*C";
      }
      break; 
  }
}

Linia Serial.print potrzebna mi była do sprawdzenia czy program wchodzi w dany warunek.

O dziwo gdy zmienię kolejność warunków program działa poprawnie. Nie jest to pierwszy raz, jak się z tym spotykam. Poniższy kod działa.

void sensorTypeUpDate () {

  switch (actualSensor) {

   case 3:
      Serial.print("wszedl w 3 petle");
      temperature = dht.getTemperature();
      if (dht.getStatusString() == "OK") {
        sensorType = "Temperatura:";
        sensorValue = String(temperature) + "*C";
      }
      break;
      
    case 2:
      Serial.print("wszedl w 2 petle");
      humidity = dht.getHumidity();

      if (dht.getStatusString() == "OK") {
        sensorType = "Wilgotnosc:";
        sensorValue = String(humidity) + "RH%";
      }
      break;
      
    case 1:
      Serial.print("wszedl w 1 petle");
      int odczyt = analogRead(lightSensor);
      light = map(odczyt, 0, 1023, 0, 100);
      sensorType = "Jasnosc:";
      sensorValue = String(light) + "%";
      break;

  }
}

Z góry dziękuje za pomoc.

Link do komentarza
Share on other sites

actualSensor jest zmienną typu int. Wartości jakie może przyjąć to 1 lub 2 lub 3. I te wartości przyjmuje. Sprawdzałem to poprzez podglądanie ich monitorze portu szeregowego. Poza tym gdyby zmienna actualSensor nie przyjmowała wartości 1 lub 2 lub 3. To zmiana kolejności warunków w instrukcji Switch nie powinna mieć żadnego wpływu na działanie programu. A mimo to w przypadku drugiego kodu program działa poprawnie.

Link do komentarza
Share on other sites

przede wszystkim użyj Serial.println a nie Serial.print - wtedy masz pewność że Ci się wszystko wyświetli. Jak zmienisz i dalej będzie źle to przed switchem wrzuć println z wartością.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

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

@ethanak Zrobiłem tak jak mówiłeś, gdy actualSensor ma wartość 1 program wykonuje pierwszy się warunek (case 1). Niestety gdy actualSensor przyjmuje wartość 2 (sprawdzam jego wartość przed instrukcją switch), to już nie chce wejść w drugi warunek. To samo w przypadku gdy actualSensor przyjmuje wartość 3. Zastanawia mnie tylko czemu po zmienieniu kolejności warunków, program zaczyna działać poprawnie.

Link do komentarza
Share on other sites

trochę to dziwne... dodaj klauzulę default i wypisz w niej cokolwiek ważmego (np. wartość actualSensor).

Nie znam reszty programu, ale ja bym zakomentował wszystko w case oprócz printa i breaka i zobaczył, kiedy zaczną się jaja.

Link do komentarza
Share on other sites

Faktycznie zrobiłem tak jak mówiłeś i udało mi się znaleźć linie która wysypywała mi program

      int odczyt = analogRead(lightSensor);

Co ciekawe w  przypadku gdy zmienna "actualSensor" przyjmuje wartość 2 lub 3, program nie wchodzi warunek 2, 3, a nawet w warunek domyślny. Mimo że linia, która wysypuje program teoretycznie powinna go wysypywać dla actualSensor == 1,  a wysypuje go dla pozostałych warunków. Chyba że warunki 2 i 3 umieścimy w kodzie programu przed warunkiem 1. Co jeszcze ciekawsze po rozbiciu wyżej podanej linii na dwie:

int odczyt;
odczyt = analogRead(lightSensor);

Wszystko zaczyna działać poprawnie, mimo że oba zapisy są poprawne.

Link do komentarza
Share on other sites

poczytaj sobie o zakresach zmiennych. ogólnie c++ jest fajny bo pozwala na mieszanie deklaracji i instrukcji, ale co się wtedy dzieje na stosie to materiał na sprawę dla Sherlocka Holmesa (szczególnie przy siłowej optymalizacji wymuszanej przez Arduino IDE).

ogólnie w bloku switch nie powinno się tworzyć nowych zmiennych - przepraszam, ale czytam to na komórce i po prostu nie zauważyłem 😞

  • Pomogłeś! 1
Link do komentarza
Share on other sites

#include "DHT.h"
#include <LiquidCrystal.h>

#define DHT11_PIN 2
#define lightSensor A5
#define button 7
#define redLight 6
#define greeLight 5

DHT dht;
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);

int actualSensor = 1; //aktualnie wyświetlany sensor

String sensorType;
String sensorValue;

//int odczyt;

float light = 0; //używane sensory
float humidity = 0;
float temperature = 0;

volatile int sensorQuantity = 3; //ilość sensorów

unsigned long screenRefreshDelay = 500; //co ile milisekund ma być odświeżony ekran
unsigned long screenRefreshDelayMillis = 0; //wartość pomocnicza
unsigned long sensorChangeDelay = 5000; //co ile milisekund ma być zmienony aktualnie wyświetlany sensor
unsigned long sensorChangeDelayMillis = 0; //wartość pomocnicza

bool automaticSensorChange = true;



void setup()
{
  Serial.begin(9600);
  dht.setup(DHT11_PIN);
  pinMode(button, INPUT_PULLUP);
  lcd.begin(16, 2);
}

void loop()
{
  sensorTypeUpDate();
  screenRefreshsss();
  if (automaticSensorChange == true)
    sensorChangeByTime();
  sensorChangeByButton();
}


void sensorChangeByTime () {
  if (millis() - sensorChangeDelayMillis > sensorChangeDelay) {
    sensorChangeDelayMillis = millis();
    changeSensor();
    lcd.clear();
  }
}

void sensorChangeByButton () {
  if (digitalRead(button) == LOW) {
    changeSensor();
    unsigned long autamaticSensorChangeDelay = millis();
    bool automaticSensorChangeDone = false;
    while (digitalRead(button) == LOW) {
      if (millis() - autamaticSensorChangeDelay > 2000 && automaticSensorChangeDone == false) {
        automaticSensorChange = !automaticSensorChange;
        automaticSensorChangeDone = true;
      }
    }
    sensorChangeDelayMillis = millis();
    lcd.clear();
  }
}


void changeSensor () {
  actualSensor++;
  if (actualSensor > sensorQuantity)
    actualSensor = 1;
}


void sensorTypeUpDate() {
  Serial.println(actualSensor);

  switch (actualSensor) {
    case 1:
      Serial.println("wszedl w 1 petle");
      int odczyt;
      odczyt = analogRead(A0);
      light = map(odczyt, 0, 1023, 0, 100);
      sensorType = "Jasnosc:";
      sensorValue = String(light) + "%";
      break;

    case 2:
      Serial.println("wszedl w 2 petle");
      humidity = dht.getHumidity();
      if (dht.getStatusString() == "OK") {
        sensorType = "Wilgotnosc:";
        sensorValue = String(humidity) + "RH%";
      }
      break;

    case 3:
      Serial.println("wszedl w 3 petle");
      temperature = dht.getTemperature();
      if (dht.getStatusString() == "OK") {
        sensorType = "Temperatura:";
        sensorValue = String(temperature) + "*C";
      }
      break;
  }
}


void screenRefreshsss () {
  if (millis() - screenRefreshDelayMillis > screenRefreshDelay) {
    screenRefreshDelayMillis = millis();

    lcd.setCursor(0, 0);
    lcd.print(sensorType);
    lcd.setCursor(0, 1);
    lcd.print(sensorValue);
  }
}

Funkcja sensorTypeUpDate wywoływana jest w pętli głównej programu. Natomiast zmienna actualSensor, zmienia się po wciśnieciu przycisku lub po upływie 5 sekund. Zmianę po upływie czasu można wyłączyć przytrzymując przycisk przez ponad 2 sekundy.

Link do komentarza
Share on other sites

5 godzin temu, Olo_1994 napisał:

Serial.println(actualSensor);

No i co Ci wyświetla ta linijka w sensorTypeUpDate()? Tak na marginesie to do funkcji można przekazywać parametry - nigdzie tego nie stosujesz.

Link do komentarza
Share on other sites

21 godzin temu, Olo_1994 napisał:

int odczyt;
odczyt = analogRead(lightSensor);

Wszystko zaczyna działać poprawnie, mimo że oba zapisy są poprawne.

Warto doczytać o tym problemie tutaj:

http://cpp0x.pl/kursy/Kurs-C++/Poziom-1/Warunek-wielokrotnego-wyboru-switch-case/17

W akapicie: "Tworzenie zmiennych wewnątrz switch'a" jest dokładnie opisane jak korzystać w takim wypadku z case.

Ten problem powinien wyłapać kompilator, ale być może masz "zbyt luźno" skonfigurowany.

  • Pomogłeś! 1
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.