Можно ли сделать цикл внутри switch - case?
- Войдите на сайт для отправки комментариев
Добрый вечер, корифеи!
Воздравляю всех с наступившим Новым годом! Пользуюясь новогодними каникулами, решил засесть за освоение Ардуины, благо появилась практическая задача - сделать плату управления для увлажнителя воздуха, взамен бессовестно сожженной в ходе экспериментов. Дело идет со скрипом (последний раз сталкивался с программированием больше 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 }
Нарисуйте алгоритм Вашей программы на бумажке, сравните с тем, что написано. Наверняка найдёте расхождения. Есть путаница.
В строке 85 Вы проверяете изменилось ли состояние кнопки. И только если изменилось Вы управаляете вентилятором. Вытащите Ваш switch из этого условия наружу. Если изменилось состояние кнопки, то прочитать и запомнить состояние кнопки. Внутри условия всё. А дальше уже switch разбирает, что нужно делать.
Ещё смотрите. Комментарий в строке 72 видите? На самом деле вы сейчас не делаете паузу между измерениями. Вы только отладочную информацию через временной интервал выводите, а измерение строки 65-71 у Вас делается каждый цикл loop, так часто датчик дёргать не надо. Измерение как раз нужно поставить перед Вашей печатью влажности в сериал.
Вообщем ошибки все логические, проверяйте, возможно есть ещё.
Подскажите - как это реализовать, уже весь мозг сломал - ничего на ум не приходит.
По старой - сложновато будет, спектрум где теперь найти )))
Вы правы, путанницы в коде хоть отбавляй. В голове то оно все по полочкам, а в код сразу уложить не получается. Спасибо за Ваш совет с выносом switch, действительно помогло.
Спасибо и за эту подсказку - поправил.