Нужна помощь новичку в написании цикла (Сушильная камера)

VadimR89
Offline
Зарегистрирован: 27.03.2019

Доброго времени суток, уважаемые. Написал программу управления сушильной камеры. Протестировал, все отлично работает, но хочу ее усовершенствовать, для более ефективной работы. Имеется нагревательный елемент и вытяжной вентилятор. В программе присутствуют значения максимальной/минимальной температуры и влажности, по которым сейчас все работает. Но, управление вытяжкой, по наблюдениям, хотелось бы переписать в следующей логике: если влажность превышает установленное максимальное значение, включается вытяжка, и работает до тех пор, пока значение влажности не снизится на 10%. После этого вытяжка выключается и ожидает подъема влажности на 5%, снова включается и работает до снижения на 10% от предыдущего значения, и таким "ступенчастым" снижением до установленного минимального значения. 

К примеру, если максимальное значение MaxHum = 100, то математически работа выглядит следующим образом:

H1 = MaxHum = 100 - на выходе логическиая 1

H2 = (H1 - 10) = 90 - на выходе логический 0

H3 = (H2 + 5) = 95 - на выходе логическая 1

H4 = (H3 - 10) = 85 - на выходе логический 0

H5 = (H4 + 5) = 90 - на выходе логическая 1 и так далее  

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

svm
Онлайн
Зарегистрирован: 06.11.2016

VadimR89 пишет:

если влажность превышает установленное максимальное значение, включается вытяжка, и работает до тех пор, пока значение влажности не снизится на 10%. После этого вытяжка выключается и ожидает подъема влажности на 5%, снова включается и работает до снижения на 10% от предыдущего значения, и таким "ступенчастым" снижением до установленного минимального значения. 

У Вас алгоритм прекрасно описан, введите флаг что идет осушение или пауза. По окончанию паузы меняете флаг и так в цикле, пока не достигнете требуемой влажности. Если не хотите переписывать всю программу, то введите дополнительные переменные вместо 10 и 5. Хотя программа будет небольшая и менять эти значения не составит труда.

А еще лучше выложите свой код, тогда будет что обсуждать и советовать.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

VadimR89 пишет:

Написал программу 

Где она?

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015
VadimR89
Offline
Зарегистрирован: 27.03.2019
#include <LiquidCrystal_I2C.h>
#include "DHT.h"   // подключаем библиотеку для DHT11
#include <Wire.h>

LiquidCrystal_I2C LCD1 (0x27, 16, 2); //адрес LCD1
LiquidCrystal_I2C LCD2 (0x26, 16, 2); //адрес LCD2
LiquidCrystal_I2C LCD3 (0x3f, 16, 2); //адрес LCD3


#define DHT1PIN 2 //пин датчика 1
#define DHT2PIN 3 //пин датчика 2
#define DHT3PIN 4 //пин датчика 3
#define DHT1TYPE DHT22  //тип датчика 1
#define DHT2TYPE DHT22  //тип датчика 2
#define DHT3TYPE DHT22  //тип датчика 3
#define HEATER A2 // пин реле обогревателя
#define FAN A3 // пин реле вытяжного вентилятора
#define MOSFET 8 // транзистор вентилятора охлаждения

DHT DHT1(DHT1PIN, DHT1TYPE); 
DHT DHT2(DHT2PIN, DHT2TYPE); 
DHT DHT3(DHT3PIN, DHT3TYPE); 


const int GreenLED1 = 13; // индикация чтения датчика 1
const int GreenLED2 = 12; // индикация чтения датчика 2
const int GreenLED3 = 11; // индикация чтения датчика 3
const int Button = 5; // пин кнопки переключения 
int Sensor = 1; // переменная для переключения датчиков в операторе CASE
int flag = 0; 

float minTemp = 24; // значение минимальной температуры
float maxTemp = 30; // значение максимальной температуры
float minHum = 50; // значение минимальной влажности
float maxHum = 75; // значение максимальной влажности

void setup() {
  DHT1.begin();
  DHT2.begin();
  DHT3.begin();
  LCD1.init();
  LCD1.backlight();
  LCD2.init();
  LCD2.backlight();
  LCD3.init();
  LCD3.backlight();
  pinMode(HEATER, OUTPUT);
  pinMode(FAN, OUTPUT);
  pinMode(MOSFET, OUTPUT); 
  pinMode(GreenLED1, OUTPUT);
  pinMode(GreenLED2, OUTPUT);
  pinMode(GreenLED3, OUTPUT);
  pinMode(Button, INPUT);

}

void loop() { 
  
  float h1 = DHT1.readHumidity(); // переменная значения влажности датчика 1
  float t1 = DHT1.readTemperature(); // переменная значения температуры датчика 1
  float h2 = DHT2.readHumidity(); // переменная значения влажности датчика 2
  float t2 = DHT2.readTemperature(); // переменная значения температуры датчика 2
  float h3 = DHT3.readHumidity(); // переменная значения влажности датчика 3
  float t3 = DHT3.readTemperature(); // переменная значения температуры датчика 3

  if (digitalRead(Button) == HIGH && flag == 0)
  { Sensor++; //переключение управляющего датчика
    flag = 1;
    if (Sensor > 3)
    {
      Sensor = 1;
    }
  }
  if (digitalRead(Button) == LOW && flag == 1)
  { flag = 0;
  }



  if (isnan(t1) || isnan(h1)) { // при отсутсвии сигнала пишем надпись на дисплее
    LCD1.setCursor(0, 0);
    LCD1.print("Failed read DHT1 ");
    LCD1.setCursor(0, 1);
    LCD1.print("Check sensor    ");
    digitalWrite(GreenLED1, HIGH); // светодиод горит постоянно 
  }
  else {
    digitalWrite(GreenLED1, HIGH);// индикация обновления данных
    LCD1.setCursor(0, 0); //выведеные символов на дисплей
    LCD1.print("Hum:  "); //
    LCD1.setCursor(6, 0); //
    LCD1.print(h1); //
    LCD1.setCursor(11, 0); //
    LCD1.print(" "); //
    LCD1.setCursor(12, 0); //
    LCD1.print("%   "); //
    LCD1.setCursor(0, 1); //
    LCD1.print("Temp: "); //
    LCD1.setCursor(6, 1); //
    LCD1.print(t1); //
    LCD1.setCursor(11, 1); //
    LCD1.print(" "); //
    LCD1.setCursor(12, 1); //
    LCD1.print("C"); //
    digitalWrite(GreenLED1, LOW);




  }
  if (isnan(t2) || isnan(h2)) { // при отсутсвии сигнала пишем надпись на дисплее
    LCD2.setCursor(0, 0);
    LCD2.print("Failed read DHT2 ");
    LCD2.setCursor(0, 1);
    LCD2.print("Check sensor    ");
    digitalWrite(GreenLED2, HIGH); // светодиод горит постоянно 
  }
  else {
    digitalWrite(GreenLED2, HIGH);// индикация обновления данных
    LCD2.setCursor(0, 0); //выведеные символов на дисплей
    LCD2.print("Hum:  "); //
    LCD2.setCursor(6, 0); //
    LCD2.println(h2); //
    LCD2.setCursor(11, 0); //
    LCD2.print(" "); //
    LCD2.setCursor(12, 0); //
    LCD2.print("%   "); //
    LCD2.setCursor(0, 1); //
    LCD2.print("Temp: "); //
    LCD2.setCursor(6, 1); //
    LCD2.println(t2); //
    LCD2.setCursor(11, 1); //
    LCD2.print(" "); //
    LCD2.setCursor(12, 1); //
    LCD2.print("C"); //
    digitalWrite(GreenLED2, LOW);



  }
  if (isnan(t3) || isnan(h3)) { // при отсутсвии сигнала пишем надпись на дисплее
    LCD3.setCursor(0, 0);
    LCD3.print("Failed read DHT3 ");
    LCD3.setCursor(0, 1);
    LCD3.print("Check sensor    ");
    digitalWrite(GreenLED3, HIGH); // светодиод горит постоянно 
  }
  else {
    digitalWrite(GreenLED3, HIGH);// индикация обновления данных
    LCD3.setCursor(0, 0); //выведеные символов на дисплей
    LCD3.print("Hum:  "); //
    LCD3.setCursor(6, 0); //
    LCD3.println(h3); //
    LCD3.setCursor(11, 0); //
    LCD3.print(" "); //
    LCD3.setCursor(12, 0); //
    LCD3.print("%   "); //
    LCD3.setCursor(0, 1); //
    LCD3.print("Temp: "); //
    LCD3.setCursor(6, 1); //
    LCD3.println(t3); //
    LCD3.setCursor(11, 1); //
    LCD3.print(" "); //
    LCD3.setCursor(12, 1); //
    LCD3.print("C"); //
    digitalWrite(GreenLED3, LOW);



  } //переключение управляющего датчика кнопкой
  switch (Sensor) {
    case 1:
      LCD1.setCursor(15, 0);
      LCD1.print("M");
      if (h1 > maxHum)// установка вытяжки
        digitalWrite (FAN, LOW);
      else if (h1 < minHum)
        digitalWrite (FAN, HIGH);

      if (t1 < minTemp)//установка обогревателя
      { digitalWrite (HEATER, HIGH);
        digitalWrite (MOSFET, HIGH);
      }
      else if (t1 > maxTemp)
      { digitalWrite (HEATER, LOW);
        digitalWrite (MOSFET, LOW);
      }

      break;
    case 2:
      LCD2.setCursor(15, 0);
      LCD2.print("M");
      if (h2 > maxHum)
        digitalWrite (FAN, LOW);
      else if (h2 < minHum)
        digitalWrite (FAN, HIGH);
        
      if (t2 < minTemp)//установка обогревателя
      { digitalWrite (HEATER, HIGH);
        digitalWrite (MOSFET, HIGH);
      }
      else if (t2 > maxTemp)
      { digitalWrite (HEATER, LOW);
        digitalWrite (MOSFET, LOW);
      }
      
      break;
    case 3:
      LCD3.setCursor(15, 0);
      LCD3.print("M");
      if (h3 > maxHum)
        digitalWrite (FAN, LOW);
      else if (h3 < minHum)
        digitalWrite (FAN, HIGH);
        
      if (t3 < minTemp)//установка обогревателя
      { digitalWrite (HEATER, HIGH);
        digitalWrite (MOSFET, HIGH);
      }
      else if (t3 > maxTemp)
      { digitalWrite (HEATER, LOW);
        digitalWrite (MOSFET, LOW);
      }
      
      break;
  }
  
  delay(2000);
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Можно было и в первом посте поправить, да и код более 30-50 строк принято сворачивать, в опциях посмотрите

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

VadimR89 пишет:
если влажность превышает установленное максимальное значение, включается вытяжка, и работает до тех пор, пока значение влажности не снизится на 10%. После этого вытяжка выключается и ожидает подъема влажности на 5%, снова включается и работает до снижения на 10% от предыдущего значения, и таким "ступенчастым" снижением до установленного минимального значения.

Ну, вот прямо так как рассказываете и пишите, кто ж Вам не даёт?

int goal = 100; // текущая цель, которой ждём
bool currentState = false; // текущее состояние нагревателя

//
//	Возвращает true, если цель достигнута
// при этом, если нагреватель включён, то цель достигнута, 
//	когда текущая влажность меньше цели, а если нагреватель
// выключен, то когда текущая влажность больше цели
//
bool goalAchieved(const int currentHumidity) {
	return currentState ? currentHumidity <= goal : currentHumidity >= goal;
}

//
//	Возвращает текущую влажность
//
int getHumidity(void) {
	return ......
}

void loop(void) {
	if (goalAchieved(getHumidity())) {
		// назначаем новую цель. Если нагреватель был включен,
		// то новая цель больше текущей на 10%, а если нагреватель
		// был выключен, то меньше текущей на те же 10%
		if (currentState) goal += goal / 10;
		else goal -= goal / 10;
		// меняем состояние нагревателя
		currentState = !currentState;
	}
}

Здесь нет обработки конечного значение, т.к. Вы его не очень чётко прописали и я его не понял, но вставите сами.

VadimR89
Offline
Зарегистрирован: 27.03.2019
 case 2:
      LCD2.setCursor(15, 0);
      LCD2.print("M");
      if (h1 > maxHum && CurrentState == false)
      digitalWrite (FAN, LOW);   
      CurrentState != CurrentState; //true, вытяжка
      currentHum = h1;
      if (h1 < currentHum - 10 && CurrentState == true)
      digitalWrite (FAN, HIGH);
      CurrentState != CurrentState; // false, ожидание
      currentHum = h1;
      if (h1 > currentHum + 5 && CurrentState == false)
      digitalWrite (FAN, LOW);
      CurrentState != CurrentState;// true, вытяжка 

 

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Ну, Вы сделали как я сказал? Получилось?

VadimR89
Offline
Зарегистрирован: 27.03.2019

Еще не пробовал заливать, устройство в другом месте. Расписал логику на листе бумаги, потом перевел на понятный ардуине язык, максимально упростил, иполучилось так. Ну вроде как должно работать. При таком коде первое включение происходит по достижению значения maxHum. В первом ЕСЛИ переменной currentHum не существует (в начале кода ей не присвоено никакого значения) , флаг, вроде как и не нужен, булеан изначально false, на всякий поставил. Только "currentHum = h1" вконце добавить для обновления переменной, ну и сами значения 5, 10 прописать как переменные, для удобства. Цикл так должен работать по двум параметрам: постоянно обновляемой currentHum и флагом CurrentState. Или я что-то упустил.... Компиляция ошибок не выдает.

VadimR89
Offline
Зарегистрирован: 27.03.2019
С кодом выше не работает, вернее работает, но вытяжка включена постоянно. Добавил в начале еще одно условие:

if (h1 < maxHum && CurrentState == false)

{digitalWrite (FAN, HIGH);

CurrentState = CurrentState;}

При включении всей системы, уровень влажности всегда ниже максимальной, тоесть это условие соблюдается вначале, следовательно вытяжка выключена, CurrentState остается false. Но при этом вытяжка включается по достижению maxHum и выключается при значениях ниже maxHum, больше никаких действий не происходит.

Возможно "CurrentState != CurrentState" заменить на "CurrentState == false/true"?

  

 

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Ну, я же Вам написал как надо делать, причём тут Ваш "код выше"? Сделайте как я написал и покажите код, если что не так. Только целиком - не огрызки.