Skocz do zawartości
Olo_1994

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

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.

Udostępnij ten post


Link to post
Share on other sites

@Olo_1994, jakiego typu jest zmienna "actualSensor"? Jakie wartości się w niej znajdują? Może tylko "wydaje Ci się", że jest tam 1/2/3?

Udostępnij ten post


Link to post
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.

Udostępnij ten post


Link to post
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ą.

Udostępnij ten post


Link to post
Share on other sites

@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.

Udostępnij ten post


Link to post
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.

Udostępnij ten post


Link to post
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.

Udostępnij ten post


Link to post
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

Udostępnij ten post


Link to post
Share on other sites

Pokaż fragment gdzie actualSensor przyjmuje wartość. Pokazałeś wiele kodu ale nie to. Pokaż jak wywołujesz tę funkcję ze switch. Bez tego trudno cokolwiek powiedzieć.

Udostępnij ten post


Link to post
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.

Udostępnij ten post


Link to post
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.

Udostępnij ten post


Link to post
Share on other sites

Przez 5 sekund wyświetla "1", przez kolejne 5 sekund "2", przez kolejne 5 sekund "3" i tak w pętli.

 

Udostępnij ten post


Link to post
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

Udostępnij ten post


Link to post
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!

Gość
Napisz odpowiedź...

×   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...