Skocz do zawartości

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


Pomocna odpowiedź

Napisano

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.

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

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.

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

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

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.

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.

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

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

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

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.

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

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...