то ли Millis то ли руки
- Войдите на сайт для отправки комментариев
Вс, 04/02/2018 - 00:54
Добрый вечер, помогите разобраться!
Есть емкость в которой вода, пополняется автоматически, как появится давление в питающей системе, должен включиться таймер который отсчитает 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; }
}
}
sharkman89.Я вам точно говорю. Виноваты только ваши руки, или голова. Потому что умная голова кривой код не напишет.
Добрый вечер, помогите разобраться!
Есть емкость в которой вода, пополняется автоматически, как появится давление в питающей системе, должен включиться таймер который отсчитает 5 минут и откроет электромагнитный клапан. в реальности получается что таймер живет своей жизнью. Отсчет 5ти минут не начинается в момент когда давление появилось. А таймер просто обнавляет каждые 5 минут (previousMillis) с самого включения контроллера.
Дык выведите все Ваши переменный в монитор порта, и контролируйте состояние. Там и поймете чего куда.
С 20 по 26 строчки лишние. Достаточно в 28 вместо 2 написать 512 или сколько там получается в19 при нормальном давлении. В 30 надо не if a while и соответственно поправить чтобы 5минут ждал. Можно просто delay использовать. По алгоритму не предполагается в это время что то делать и millis() явно лишний. Потом включить клапан. Вот на сколько не понятно, но можно тоже на делее или опять цикл while с проверкой условия давления или чего ещё.
все немного сложнее)
и все же в чем беда? ведь я приравниваю
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(" "); } } }Есть емкость в которой вода, пополняется автоматически, как появится давление в питающей системе, должен включиться таймер который отсчитает 5 минут и откроет электромагнитный клапан. в реальности получается что таймер живет своей жизнью. Отсчет 5ти минут не начинается в момент когда давление появилось. А таймер просто обнавляет каждые 5 минут (previousMillis) с самого включения контроллера.
По каким признакам вы понимаете, что отсчет не начался и в какой строчке он должен начинаться, по вашему мнению?
отсчет должен начинаться только после того как появилось давление
118elseif(Pressure >=2)119{unsignedlongcurrentMillis = millis();120if(currentMillis - previousMillis >= interval)121122123{124previousMillis = currentMillis;125FillingWater = 1;// пополнение разрешено126}я подключал вместо датчика давления фоторезистор (таким образом что если датчик видит свет условие выполняется)
таймер ставил не 5 минут , а 30 секунд
запускал контроллер с накрытым фоторезистором, ждал 20 секунт и открывал его, в моем понимании спустя 30 секунд на экране должна появиться индикация (^^)
258lcd.print("^^");но индикация появляется через 10 секунд, то есть контроллер начинае отсчет сразу с момента запуска.
если запустить и держать фоторезистор накрытым дольше интервала, то при открытии фоторезистора, индикация наполнения появляется сразу.
/**/ // датчик давления 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 байт. */отсчет должен начинаться только после того как появилось давление
запускал контроллер с накрытым фоторезистором, ждал 20 секунт и открывал его, в моем понимании спустя 30 секунд на экране должна появиться индикация (^^)
258lcd.print("^^");но индикация появляется через 10 секунд, то есть контроллер начинае отсчет сразу с момента запуска.
если запустить и держать фоторезистор накрытым дольше интервала, то при открытии фоторезистора, индикация наполнения появляется сразу.
Давайте на коротком скетче разбираться для начала. На том, что в сообщении #1. Куда нужно воткнуть этот print() (обойдемся Serial.println()), в какую строку?
запускал контроллер с накрытым фоторезистором, ждал 20 секунт и открывал его, в моем понимании спустя 30 секунд на экране должна появиться индикация (^^)
Не, от чо мне нравится, так это изобретательность для эмуляции событий.
Помню на закате СССР, служил в Красной Армии и на подхвате у телефонистов монтировал сигналку пожарную и от воров в новом магазине строителей РоАЭС. Комиссия значит усе принимает, вдруг нас кличут, а я один в этот момент на узле был. Ну, собрался, пошел. Прихожу и оуеваю, посреди магаза лестница четырехметровая стоит и пожарную этот хрен-председатель уже зажигалкой проверил.))) Теперь размышляет, как проверить от воров. Говорю, так зачем же дело стало, бери стул и в витрину его, в витрину. Не соглашается, дорого типа, не должно так быть. На вопрос, вот прежде чем лестницу переть и лезть наверх костры разводить, может лучше позвонить было и я бы тебе два выключателя контрольных в подсобке показал, задумался.
#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; } } }получается то же самое,
через 30 секунд даже если первых 15 секунд условие
небыло соблюдено(((
qwone спасибо за код, буду пытаться интегрировать его в свой, правда пока сложновато для меня в понимании)
Обычное событийное программирование. Правда реализовано примитивно . Событие ValveON взводится , если давление превысило границу , и сбрасывается если давление упало или же истекло время для открытия кланана. Разумеется при низком давлении кланан закрывается и если событие ValveON было вкл, то сбрасывается. Можно описать в классах, но это для вас окажется сложнее.
ЗАРАБОТАЛО!!! ОГРОМНОЕ СПАСИБО)