то ли Millis то ли руки

sharkman89
Offline
Зарегистрирован: 05.01.2018

Добрый вечер, помогите разобраться!

Есть емкость в которой вода, пополняется автоматически, как появится давление в питающей системе, должен включиться таймер который отсчитает 5 минут и откроет электромагнитный клапан. в реальности получается что таймер живет своей жизнью. Отсчет  5ти минут не начинается в момент когда давление появилось. А таймер просто обнавляет каждые 5 минут  (previousMillis) с самого включения контроллера.

#define Valve        12         // электромагнитный клапан
#define PressureIn   A3         //  датчик давление в питающей линии

int PressureFilling;             // переменная с датчика давления в питающей воде   
int Pressure;                    //  давление в питающей воде

boolean FillingWater = 0;            // флаг давления в питающей воде

unsigned long previousMillis   = 0;
const long interval   = 300000;   
void setup()
{
  pinMode(Valve, OUTPUT);
}


void loop()
{
 PressureFilling = analogRead(PressureIn);                      // флаг на разрешение пополнения воды
 Pressure = map(PressureFilling, 90 , 920, 0, 4); 
 
 if (Pressure < 1)
{ 
 FillingWater = 0;

}       
           
  if (Pressure >= 2)
{unsigned long currentMillis   = millis();
  if  (currentMillis - previousMillis >= interval)


 { 
 previousMillis = currentMillis;                 
 FillingWater = 1; }
} 
}

 

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

 sharkman89.Я вам точно говорю. Виноваты только ваши руки, или голова. Потому что умная голова кривой код не напишет.

5N62V
Offline
Зарегистрирован: 25.02.2016

sharkman89 пишет:

Добрый вечер, помогите разобраться!

Есть емкость в которой вода, пополняется автоматически, как появится давление в питающей системе, должен включиться таймер который отсчитает 5 минут и откроет электромагнитный клапан. в реальности получается что таймер живет своей жизнью. Отсчет  5ти минут не начинается в момент когда давление появилось. А таймер просто обнавляет каждые 5 минут  (previousMillis) с самого включения контроллера.


Дык выведите все Ваши переменный в монитор порта, и контролируйте состояние. Там и поймете чего куда.

nik182
Offline
Зарегистрирован: 04.05.2015

С 20 по 26 строчки лишние. Достаточно в 28 вместо 2 написать 512 или сколько там получается в19 при нормальном давлении. В 30 надо не if a while и соответственно поправить чтобы 5минут ждал. Можно просто delay использовать. По алгоритму не предполагается в это время что то делать и millis() явно лишний. Потом включить клапан. Вот на сколько не понятно, но можно тоже на делее или опять цикл while с проверкой условия давления или чего ещё.

sharkman89
Offline
Зарегистрирован: 05.01.2018

все немного сложнее)
и все же в чем беда? ведь я приравниваю
unsigned long currentMillis = millis();
только после того как появилось давление???


 #include <Wire.h>                           // Подключаем библиотеку Wire
#include <LiquidCrystal_I2C.h>              // Подключаем библиотеку LiquidCrystal_I2C 
#include <DallasTemperature.h>              // Подключаем библиотеку DallasTempature

#define DS18B20      2          // Указываем, к какому выводу подключена DQ

#define Floater      6          // поплавковый выключатель
#define Buzzer       9          // сигнализация

#define Valve        12         // электромагнитный клапан

#define Light        A0         //  датчик освещенности
#define Overflow     A1         //  датчик переполнения
#define Leakage      A2         //  датчик разлива
#define Thief        A3         //  датчик взлома
#define PressureIn   A6         //  датчик давление в питающей линии (80PSI)
#define PressureOut  A7         //  датчик уровня(давления) воды в бочке (5PSI)


 
byte simvol[8]     = {B11100,B10100,B11100,B00000,B00000,B00000,B00000,B00000,}; // Символ градуса
byte bukva_B[8]    = {B11110,B10000,B10000,B11110,B10001,B10001,B11110,B00000,}; // Буква "Б"
byte bukva_G[8]    = {B11111,B10001,B10000,B10000,B10000,B10000,B10000,B00000,}; // Буква "Г"
byte bukva_D[8]    = {B01111,B00101,B00101,B01001,B10001,B11111,B10001,B00000,}; // Буква "Д"
byte bukva_ZH[8]   = {B10101,B10101,B10101,B11111,B10101,B10101,B10101,B00000,}; // Буква "Ж"
byte bukva_Z[8]    = {B01110,B10001,B00001,B00010,B00001,B10001,B01110,B00000,}; // Буква "З"
byte bukva_I[8]    = {B10001,B10011,B10011,B10101,B11001,B11001,B10001,B00000,}; // Буква "И"
byte bukva_IY[8]   = {B01110,B00000,B10001,B10011,B10101,B11001,B10001,B00000,}; // Буква "Й"
byte bukva_L[8]    = {B00011,B00101,B01001,B01001,B01001,B01001,B11001,B00000,}; // Буква "Л"
byte bukva_P[8]    = {B11111,B10001,B10001,B10001,B10001,B10001,B10001,B00000,}; // Буква "П"
byte bukva_Y[8]    = {B10001,B10001,B10001,B01010,B00100,B01000,B10000,B00000,}; // Буква "У"
byte bukva_F[8]    = {B00100,B11111,B10101,B10101,B11111,B00100,B00100,B00000,}; // Буква "Ф"
byte bukva_TS[8]   = {B10010,B10010,B10010,B10010,B10010,B10010,B11111,B00001,}; // Буква "Ц"
byte bukva_CH[8]   = {B10001,B10001,B10001,B01111,B00001,B00001,B00001,B00000,}; // Буква "Ч"
byte bukva_Sh[8]   = {B10101,B10101,B10101,B10101,B10101,B10101,B11111,B00000,}; // Буква "Ш"
byte bukva_Shch[8] = {B10101,B10101,B10101,B10101,B10101,B10101,B11111,B00001,}; // Буква "Щ"
byte bukva_Mz[8]   = {B10000,B10000,B10000,B11110,B10001,B10001,B11110,B00000,}; // Буква "Ь"
byte bukva_Tz[8]   = {B11000,B01000,B01000,B01110,B01001,B01001,B01110,B00000,}; // Буква "Ъ"
byte bukva_IYI[8]  = {B10001,B10001,B10001,B11001,B10101,B10101,B11001,B00000,}; // Буква "Ы"
byte bukva_Yu[8]   = {B10010,B10101,B10101,B11101,B10101,B10101,B10010,B00000,}; // Буква "Ю"
byte bukva_Ya[8]   = {B01111,B10001,B10001,B01111,B00101,B01001,B10001,B00000,}; // Буква "Я"

LiquidCrystal_I2C lcd(0x3f,16,2);           // Задаем адрес и размер дисплея
OneWire oneWire(DS18B20);                   
DallasTemperature sensors(&oneWire);

const byte averageFactor = 20;   // сглаживание

int Level;                       // уровень воды в бочке
int Value = 0;                   // переменная с датчика уровня воды в бочке
int Pressure;                    //  давление в питающей воде
int PressureFilling;             // переменная с датчика давления в питающей воде   
int LightSensor;                 // показания с датчика освещенности
int ThiefSensor;                 // показания с датчика взлома
int OverflowSensor;              // показания с датчика перелива
int LeakageSensor;               // показания с датчика разлива



boolean FloatSwitch = 0;             // флаг поплавка 
boolean FillingWater = 0;            // флаг давления в питающей воде
boolean ALARM_L1 = 0;                //аларм перелив( в случае OverflowSwitch HIGH, перейдет в HIGH и останется таковым даже если OverflowSwitch LOW) 
boolean ALARM_L2 = 0;                // аларм разлив ( в случае LeakageSwitch HIGH, перейдет в HIGH и останется таковым даже если LeakageSwitch LOW) 
boolean ALARM_F1 = 0;                // аларм взлома ( в случае LeakageSwitch HIGH, перейдет в HIGH и останется таковым даже если LeakageSwitch LOW) 
  


unsigned long previousMillis   = 0;  //  
unsigned long previousMillis_1 = 0;  //
unsigned long previousMillis_2 = 0;  //      
const long interval   = 300000;        // интервал для пополнения воды
const long interval_1 = 3000;         // интервал для сигнализации (Разлив, Перелив)
const long interval_2 = 1000;         // интервал для сигнализации (Взлом)


void setup()
{
  Serial.begin(9600);
  sensors.begin();                     // DS18B20
  lcd.init();                          // Инициализация lcd    
  lcd.backlight();                     // Включаем подсветку
  pinMode(Valve, OUTPUT);              //клапан
  pinMode(Floater, INPUT);             // поплавок
  pinMode(PressureIn, INPUT);          // питающая вода
  pinMode(PressureOut, INPUT);         // уровень воды
  pinMode(Buzzer, OUTPUT);             // сигнализация
 
}
void loop()
{
  Serial.println(PressureFilling);         ///////////////////////////////////////////////////////////////////////////
  lcd.createChar(1, simvol);               // Создаем символ под номером 1
  lcd.createChar(2, bukva_B);              // ...
  lcd.createChar(3, bukva_Tz);             // ...
  lcd.createChar(4, bukva_L);              // ...
  lcd.createChar(5, bukva_P);              // ...
  lcd.createChar(6, bukva_I);              // ...
  lcd.createChar(7, bukva_Z);              // ...

  OverflowSensor = analogRead(Overflow);   // считываем датчик перелива
  LeakageSensor = analogRead(Leakage);     // считываем датчик разлива
  ThiefSensor = analogRead(Thief);         // считываем датчик взлома
  
  unsigned long currentMillis_1 = millis(); 
  unsigned long currentMillis_2 = millis(); 
  
   FloatSwitch = digitalRead(Floater);                   //считываем положение попловка

 PressureFilling = analogRead(PressureIn);               // считываем показания питающей воды
 Pressure = map(PressureFilling, 90 , 920, 0, 6);        // переводим значение в кг/см2
 
 if (Pressure < 1)
{ 
 FillingWater = 0;             // пополнение запрещено

}       
           
else  if (Pressure >=2)
{unsigned long currentMillis   = millis();
  if  (currentMillis - previousMillis >= interval)


 { 
 previousMillis = currentMillis;                 
 FillingWater = 1;             // пополнение разрешено
 }           
} 

 int newValue = analogRead(PressureOut);      // считываем показания уровня в бочке                       
  if (averageFactor > 0)                      // усреднение показаний для устранения "скачков"
  {      
  Value = (Value * (averageFactor - 1) + newValue) / averageFactor;  
                                              // <новое среднее> = (<старое среднее>*19 + <текущее значение>) / 20 
  } else {
   Value = newValue;                          // не делаем усреднений, что прочитали то и считаем выводом
  }
 Level = map(Value, 180 , 440, 0, 290);       // переводим значение в Литры





 LightSensor = analogRead(Light);              // включение/ выключение подсветки экрана в зависимости от освещения
 if (LightSensor <= 850)
 {
 lcd.backlight();
 }
 else
 {
 lcd.noBacklight();
 }
 
  sensors.requestTemperatures();              // Считываем показания температуры
 

   if (ThiefSensor <= 700)                    // взвод аларма взлома
{ ALARM_F1 = 1; }
 else if(OverflowSensor >= 30)                // взвод аларма перелива
{ ALARM_L1 = 1; }
 else if(LeakageSensor  >= 30)                // взвод аларма разлива
{ ALARM_L2 = 1; }


 if (ALARM_F1 == 1)                            // действия при взломе( в дальнейшем сделаю через switch)
  {
 lcd.setCursor(0,0);  case 
 lcd.print("    BH\6MAH\6E    ");
 lcd.setCursor(0,1);
 lcd.print("     B\7\4OM!     ");
 digitalWrite (Valve, HIGH);
 unsigned long currentMillis_2 = millis();
  tone(Buzzer,4000,1000); 
  
  if  (currentMillis_2 - previousMillis_2 >= interval_2 )  
  {
   previousMillis_2 = currentMillis_2;  
   lcd.setCursor(0,0);
   lcd.print("                ");
   lcd.setCursor(0,1);
   lcd.print("                ");
  
    
 }
 }

 else if (ALARM_L1 == 1 && ALARM_L2 == 1)        
{
 lcd.setCursor(0,1);
 lcd.print("\5EPE\4\6B \6 PA\7\4\6B");
 unsigned long currentMillis_1 = millis(); 
 tone(Buzzer,4000,3000);
   if  (currentMillis_1 - previousMillis_1 >= interval_1 )  
  {
   previousMillis_1 = currentMillis_1;   
   lcd.setCursor(0,1);
   lcd.print("                ");
    
  }
}
 
 
else if (ALARM_L1 == 1)
{
 lcd.setCursor(0,1);
 lcd.print("    \5EPE\4\6B     ");
 tone(Buzzer,4000,3000);
  unsigned long currentMillis_1 = millis(); 
   if  (currentMillis_1 - previousMillis_1 >= interval_1 )  
  {
   previousMillis_1 = currentMillis_1;   
   lcd.setCursor(0,1);
   lcd.print("                ");
    
  } 
}

else if (ALARM_L2 == 1)
{
 lcd.setCursor(0,1);
 lcd.print("    PA\7\4\6B      ");
 tone(Buzzer,4000,3000);
   if  (currentMillis_1 - previousMillis_1 >= interval_1 )  
  {
   previousMillis_1 = currentMillis_1;   
   lcd.setCursor(0,1);
   lcd.print("                ");
    
  }
}

 else
{
  lcd.setCursor(0,1);                            //...
  lcd.print("            ");                     //...
  lcd.setCursor(12,1);                           // Устанавливаем курсор на 1 строку, ячейка 12 
  lcd.print(int(sensors.getTempCByIndex(0) ));   // Выводим показания температуры
  lcd.print(" ");
  lcd.setCursor(14,1);                           // ...
  lcd.print("\1");                               // Выводим символ градуса
  lcd.setCursor(15,1);                           // ... 
  lcd.print("C");                                // Выводим текст 


 lcd.setCursor(4,0);                             //...
 lcd.print("  O\2\3EM:");                        //...
 lcd.print(Level);                               // вывод колличества воды на дисплей
 lcd.print(" ");                                 //...
 lcd.setCursor(15,0);                            //...
 lcd.print("\4");                                //...




 if (FloatSwitch == 1 && FillingWater == 1 && ALARM_L1 == 0 && ALARM_L2 == 0 )  // открытие клапана на пополнение
{ 
 digitalWrite (Valve, LOW);
 lcd.setCursor(0,0);
 lcd.print("^^");

}
 else
{ 
 digitalWrite (Valve, HIGH);
 lcd.setCursor(0,0);
 lcd.print("  ");
}
}              
 }

 

sadman41
Offline
Зарегистрирован: 19.10.2016

sharkman89 пишет:

Есть емкость в которой вода, пополняется автоматически, как появится давление в питающей системе, должен включиться таймер который отсчитает 5 минут и откроет электромагнитный клапан. в реальности получается что таймер живет своей жизнью. Отсчет  5ти минут не начинается в момент когда давление появилось. А таймер просто обнавляет каждые 5 минут  (previousMillis) с самого включения контроллера.

По каким признакам вы понимаете, что отсчет не начался и в какой строчке он должен начинаться, по вашему мнению?

sharkman89
Offline
Зарегистрирован: 05.01.2018

отсчет должен начинаться только после того как появилось давление

118 else  if (Pressure >=2)
119 {unsigned long currentMillis   = millis();
120   if  (currentMillis - previousMillis >= interval)
121  
122  
123  {
124  previousMillis = currentMillis;                
125  FillingWater = 1;             // пополнение разрешено
126  }          

я подключал вместо датчика давления фоторезистор (таким образом что если датчик видит свет условие выполняется)

таймер ставил не 5 минут , а 30 секунд

запускал контроллер с накрытым фоторезистором, ждал 20 секунт и открывал его, в моем понимании спустя 30 секунд на экране должна появиться индикация (^^)

258 lcd.print("^^");

    но индикация появляется через 10 секунд, то есть контроллер начинае отсчет сразу с момента запуска.

если запустить и держать фоторезистор накрытым дольше интервала, то при открытии фоторезистора, индикация наполнения появляется сразу.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016
/**/
// датчик давления
const byte pressurePin =/*пин*/A3; //  датчик давление в питающей линии
const int pressureLevel = 500; //уровень срабатывания
boolean FillingWater;    // флаг давления в питающей воде
boolean oldFillingWater;    // флаг давления в питающей воде
boolean readFillingWater() {
  return (analogRead(pressurePin) > pressureLevel);
}
//клапан
const byte ValvePin =/*пин*/12;        // электромагнитный клапан
const long interval   = 300000;
unsigned long past   = 0;
bool ValveON = 0; // флаг срабатывания
//-------main---------------
void setup() {
  // датчик давления
  FillingWater = readFillingWater();
  //клапан
  pinMode(ValvePin, OUTPUT);
  digitalWrite(ValvePin, LOW); //клапан выключен
}
void loop() {
  unsigned long mill = millis();
  // датчик давления
  oldFillingWater = FillingWater;
  FillingWater = readFillingWater();
  if (!oldFillingWater && FillingWater) { // если давление только что подскочило
    past   = mill;
    ValveON = 1;
  }
  if (!FillingWater) { // если давление упало
    ValveON = 0;
    digitalWrite(ValvePin, LOW); //клапан выключен
  }
  //клапан
  if (ValveON && mill - past >= interval) { // если давление держится уже опред время
    ValveON = 0;
    digitalWrite(ValvePin, HIGH); //клапан включен
  }
}
/*Скетч использует 938 байт (3%) памяти устройства. Всего доступно 30720 байт.
  Глобальные переменные используют 16 байт (0%) динамической памяти, оставляя 2032 байт для локальных переменных. Максимум: 2048 байт.
*/

 

sadman41
Offline
Зарегистрирован: 19.10.2016

sharkman89 пишет:

отсчет должен начинаться только после того как появилось давление

запускал контроллер с накрытым фоторезистором, ждал 20 секунт и открывал его, в моем понимании спустя 30 секунд на экране должна появиться индикация (^^)

258 lcd.print("^^");

    но индикация появляется через 10 секунд, то есть контроллер начинае отсчет сразу с момента запуска.

если запустить и держать фоторезистор накрытым дольше интервала, то при открытии фоторезистора, индикация наполнения появляется сразу.

Давайте на коротком скетче разбираться для начала. На том, что в сообщении #1. Куда нужно воткнуть этот print() (обойдемся Serial.println()), в какую строку?

bwn
Offline
Зарегистрирован: 25.08.2014

sharkman89 пишет:

запускал контроллер с накрытым фоторезистором, ждал 20 секунт и открывал его, в моем понимании спустя 30 секунд на экране должна появиться индикация (^^)

Не, от чо мне нравится, так это изобретательность для эмуляции событий.
Помню на закате СССР, служил в Красной Армии и на подхвате у телефонистов монтировал сигналку пожарную и от воров в новом магазине строителей РоАЭС. Комиссия значит усе принимает, вдруг нас кличут, а я один в этот момент на узле был. Ну, собрался, пошел. Прихожу и оуеваю, посреди магаза лестница четырехметровая стоит и пожарную этот хрен-председатель уже зажигалкой проверил.))) Теперь размышляет, как проверить от воров. Говорю, так зачем же дело стало, бери стул и в витрину его, в витрину. Не соглашается, дорого типа, не должно так быть. На вопрос, вот прежде чем лестницу переть и лезть наверх костры разводить, может лучше позвонить было и я бы тебе два выключателя контрольных в подсобке показал, задумался.

sharkman89
Offline
Зарегистрирован: 05.01.2018
#define Valve        12         // электромагнитный клапан
#define PressureIn   A3         //  датчик давление в питающей линии

int PressureFilling;             // переменная с датчика давления в питающей воде   
int Pressure;                    //  давление в питающей воде

boolean FillingWater = 0;            // флаг давления в питающей воде

unsigned long previousMillis   = 0;
const long interval   = 30000;   
void setup()
{
  Serial.begin(9600);
  pinMode(Valve, OUTPUT);
}


void loop()
{Serial.println(FillingWater);
 PressureFilling = analogRead(PressureIn);                      // флаг на разрешение пополнения воды
 Pressure = map(PressureFilling, 90 , 920, 0, 4); 
 
 if (Pressure > 3)
{ 
 FillingWater = 0;

}       
           
  if (Pressure <= 2)
{unsigned long currentMillis   = millis();
  if  (currentMillis - previousMillis >= interval)


 { 
 previousMillis = currentMillis;                 
 FillingWater = 1; }
} 
}

получается то же самое, 

FillingWater = 1

через 30 секунд даже если первых 15 секунд условие

(Pressure <= 2)

небыло соблюдено(((

sharkman89
Offline
Зарегистрирован: 05.01.2018

qwone спасибо за код, буду пытаться интегрировать его в свой, правда пока сложновато для меня  в понимании)

 

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

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

sharkman89
Offline
Зарегистрирован: 05.01.2018

ЗАРАБОТАЛО!!! ОГРОМНОЕ СПАСИБО)