Можно ли сделать цикл внутри 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, действительно помогло.
Спасибо и за эту подсказку - поправил.