Можно ли сделать цикл внутри switch - case?

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

Добрый вечер, корифеи!

Воздравляю всех с наступившим Новым годом! Пользуюясь новогодними каникулами, решил засесть за освоение Ардуины, благо появилась практическая задача - сделать плату управления для увлажнителя воздуха, взамен бессовестно сожженной в ходе экспериментов. Дело идет со скрипом (последний раз сталкивался с программированием больше 25 лет тому назад, и то это был бейсик на ZX-Spectrum. Благодаря интернету и этому форуму в частности, дело потихоньку продвигается, но заранее прошу больно не пинать за чайниковские вопросы и корявость кода - как-никак первый блин.

Споткнулся я вот на чем: после опроса датчика влажности, измеренное значение записывается в переменную HumCurrent, далее к ней обращаюсь из модуля управления скоростью вентилятора case 0 - это режим автоматической работы, в котором вентилятор автоматически должен включаться при выполнении условия HumCurrent <= HumTarget (целевая влажность), и соответственно выключаться, когда это условие не верно. Засада в том, что проверка условия и изменение состояния выхода MotorFan происходит однократно, при нажатии кнопки ButtonSpeed и выполнения условия для запуска case 0. А надо чтобы то что в строках 104-108 крутилось постоянно, пока активен case 0. Подскажите - как это реализовать, уже весь мозг сломал - ничего на ум не приходит.

#define DEBUG 1 // включение отладки

#include "Bounce2.h"
Bounce bouncer1 = Bounce(); //создаем экземпляр класса Bounce
Bounce bouncer2 = Bounce(); //создаем экземпляр класса Bounce

#include "stDHT.h"
DHT sens(DHT11); // Указать датчик DHT11, DHT21, DHT22

const int PumpWater = 3;
const int MotorOsc = 4;
const int MotorFan = 5;
const int LedPower = 13;
const int LedOsc = 6;
const int LedAutoSpeed = 7;
const int LedLowSpeed = 8;
const int LedMedSpeed = 9;
const int LedHighSpeed = 11;
const int Buzzer = 10;

const int SensorDht = 14;
const int ButtonPower = 15;
const int ButtonSpeed = 16;
const int ButtonOsc = 17;
const int ButtonHum = 18;
const int SensorLevel = 19;

boolean PowerOn = false;

long DHTpreviousMillis = 0; // время, когда датчик влажности опрашивался в последний раз
const long DHTinterval = 1000;   // интервал опроса датчика влажности

int HumTarget = 50;   // Влажность, которую нужно поддерживать
int HumCurrent;   // Влажность, которую измерили датчиком

int StatusOsc = 0;    // статус кнпки OSC для Bounce
int StatusSpeed = 0;  // статус кнпки Speed для Bounce
byte SpeedNumber = 3;  // номер скорости вентилятора

void setup() {
  //устанавливаем PIN A0-A5 в режим входа и включаем подтяжку
  for (int pin = 14; pin <= 19; ++pin) {
    pinMode(pin, INPUT);
    digitalWrite(pin, HIGH);
  }
  // устанавливаем PIN D3-D13 в режим выхода
  for (int pin = 3; pin <= 13; ++pin) {
    pinMode(pin, OUTPUT);
    digitalWrite(pin, LOW);
  }

  bouncer1 .attach(ButtonOsc); // устанавливаем кнопку
  bouncer1 .interval(50); // устанавливаем параметр stable interval = 50 мс
  bouncer2 .attach(ButtonSpeed); // устанавливаем кнопку
  bouncer2 .interval(50); // устанавливаем параметр stable interval = 50 мс

  if (DEBUG == 1) {
    Serial.begin(9600);
    Serial.print("Starting, target humidity set to: ");
    Serial.print(HumTarget);
    Serial.println("%.");
  }
}
void loop() {
  // Считываем показания датчика влажности
  int h = sens.readHumidity(SensorDht); 
  if (isnan(h)) {
    Serial.println("Не удается считать показания"); // проверяем, были ли ошибки при считывании и, если были, начинаем заново
    return;
  }
  HumCurrent = h; //сохраняем измеренную влажность
  // делаем паузу перед следующим измерением
  unsigned long DHTcurrentMillis = millis();
  if (DHTcurrentMillis - DHTpreviousMillis > DHTinterval) {
    DHTpreviousMillis = DHTcurrentMillis;  // сохраняем время последнего переключения
   // включаем вывод отладочной инфорамции в COM порт
   if (DEBUG == 1) {
    Serial.print("Humidity: ");
    Serial.print(h);
    Serial.println(" %\t");
   }
  }
  // Управление скоростью вентилятора

  if (bouncer2.update()) { //Ждем нажатия кнопки нажата, если произошло событие
    if ((bouncer2.read() == 0) && StatusSpeed == 0) { //если кнопка Speed нажата и перемення StatusSpeed равна 0 , то ...
      SpeedNumber = ++SpeedNumber;
      if (SpeedNumber > 4) SpeedNumber = 1;
      StatusSpeed = 1;
      tone(Buzzer, 3000, 100);
    }
    if (digitalRead(ButtonSpeed) == HIGH && StatusSpeed == 1) { //если кнопка Speed не нажата и переменная StatusSpeed равна 1 ,то ...
      StatusSpeed = 0; //обнуляем переменную StatusOsc
    }

    switch (SpeedNumber)
    {
      case 0: //автоматический режим выбора скорости, основанный на показаниях датчика
        {
          digitalWrite(LedAutoSpeed, HIGH);
          digitalWrite(LedLowSpeed, LOW);
          digitalWrite(LedMedSpeed, LOW);
          digitalWrite(LedHighSpeed, LOW);
          if (HumCurrent <= HumTarget) { // сравниваем полученное с датчика значение с целевым 
            digitalWrite(MotorFan, HIGH); // если влажность ниже целевого значения - включаем вентилятор
          } else {
            digitalWrite(MotorFan, LOW); // если влажность выше целевого значения - выключаем вентилятор
          }
          break;
        }
      case 1: //минимальная скорость работы вентиляторы
        {
          digitalWrite(LedAutoSpeed, LOW);
          digitalWrite(LedLowSpeed, HIGH);
          digitalWrite(LedMedSpeed, LOW);
          digitalWrite(LedHighSpeed, LOW);
          analogWrite(MotorFan, 102);
          break;
        }
      case 2: //средняя скорость работы вентилятора
        {
          digitalWrite(LedAutoSpeed, LOW);
          digitalWrite(LedLowSpeed, LOW);
          digitalWrite(LedMedSpeed, HIGH);
          digitalWrite(LedHighSpeed, LOW);
          analogWrite(MotorFan, 153);
          break;
        }
      case 3: //максимальная скорость работы вентилятора
        {
          digitalWrite(LedAutoSpeed, LOW);
          digitalWrite(LedLowSpeed, LOW);
          digitalWrite(LedMedSpeed, LOW);
          digitalWrite(LedHighSpeed, HIGH);
          analogWrite(MotorFan, 204);
          break;
        }

      default: // если ни одно из перечисленных
        {
          SpeedNumber = 0;
        }
    } // конец switch
  }// конец опроса кнопки SPEED

  // опрос кнопки OSC и управление OSC
  if (bouncer1.update()) { //если произошло событие
    if ((bouncer1.read() == 0) && StatusOsc == 0) { //если кнопка OSC нажата и перемення StatusOsc равна 0 , то ...
      digitalWrite(MotorOsc, !digitalRead(MotorOsc));
      StatusOsc = 1;
      tone(Buzzer, 3000, 100);
    }
    if (digitalRead(ButtonOsc) == HIGH && StatusOsc == 1) { //если кнопка OSC не нажата и переменная StatusOsc равна - 1 ,то ...
      StatusOsc = 0; //обнуляем переменную StatusOsc
    }
  }
  // конец опроса кнопки OSC 
  
}

 

kalapanga
Offline
Зарегистрирован: 23.10.2016

Нарисуйте алгоритм Вашей программы на бумажке, сравните с тем, что написано. Наверняка найдёте расхождения. Есть путаница. 

В строке 85 Вы проверяете изменилось ли состояние кнопки. И только если изменилось Вы управаляете вентилятором. Вытащите Ваш switch из этого условия наружу. Если изменилось состояние кнопки, то прочитать и запомнить состояние кнопки. Внутри условия всё. А дальше уже switch разбирает, что нужно делать.

Ещё смотрите. Комментарий в строке 72 видите? На самом деле вы сейчас не делаете паузу между измерениями. Вы только отладочную информацию через временной интервал выводите, а измерение строки 65-71 у Вас делается каждый цикл loop, так часто датчик дёргать не надо. Измерение как раз нужно поставить перед Вашей печатью влажности в сериал.

Вообщем ошибки все логические, проверяйте, возможно есть ещё.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Dinosaur пишет:
Дело идет со скрипом (последний раз сталкивался с программированием больше 25 лет тому назад, и то это был бейсик на ZX-Spectrum.

Подскажите - как это реализовать, уже весь мозг сломал - ничего на ум не приходит.

Ну это и понятно. Парадигма программирования поменялась. Можно и по старой работать, но проекты будут попроще.

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

qwone пишет:
Ну это и понятно. Парадигма программирования поменялась. Можно и по старой работать, но проекты будут попроще.

По старой - сложновато будет, спектрум где теперь найти )))

Dinosaur
Dinosaur аватар
Offline
Зарегистрирован: 01.01.2018

kalapanga пишет:
В строке 85 Вы проверяете изменилось ли состояние кнопки. И только если изменилось Вы управаляете вентилятором. Вытащите Ваш switch из этого условия наружу. Если изменилось состояние кнопки, то прочитать и запомнить состояние кнопки. Внутри условия всё. А дальше уже switch разбирает, что нужно делать.

Вы правы, путанницы в коде хоть отбавляй. В голове то оно все по полочкам, а в код сразу уложить не получается. Спасибо за Ваш совет с выносом switch, действительно помогло.

kalapanga пишет:
Ещё смотрите. Комментарий в строке 72 видите? На самом деле вы сейчас не делаете паузу между измерениями. Вы только отладочную информацию через временной интервал выводите, а измерение строки 65-71 у Вас делается каждый цикл loop, так часто датчик дёргать не надо. Измерение как раз нужно поставить перед Вашей печатью влажности в сериал.

Спасибо и за эту подсказку - поправил.