Событие millis()

301sem
Offline
Зарегистрирован: 14.01.2021

Всем привет. Не могу реализовать событие по времени. Суть такая. На экране каждую секунду выводится время, температура и влажность в помещении. Каждые 5 секунда должен включаться насос на 3 секунды и выключиться. Код привел. Время идет, температура и влажность меняется, все выводится на экран. А функция Watering не работает. Подскажите в чем ошибка

#include <Wire.h>
#include <DHT.h>
#include <iarduino_OLED_txt.h>
#include <iarduino_RTC.h>
#include <Adafruit_Sensor.h>

#define  Pump_1       8
#define  SENSOR_1     A2
#define  MIN_S1       535                   
#define  MAX_S1       215
#define  Humidity_1   60

#define  Pump_2       9
#define  SENSOR_2     A3
#define  MIN_S2       535                   
#define  MAX_S2       215
#define  Humidity_2   60

#define  DHTPIN       2
#define  DHTTYPE      DHT22

iarduino_RTC time(RTC_DS1302, 10, 8, 9);                      
iarduino_OLED_txt myOLED(0x3C);
DHT dht(DHTPIN, DHTTYPE);

void Watch (void);                                        //  Объявляем функцию в которой будут выполняться действия зависящие от состояния энкодера и режима
void TempAndHumidity (void);                                        //  Объявляем функцию в которой будет обновляться информация дисплея в зависимости от режима, подрежима, выбранного таймера и значений массива valArray
void Watering (void);

String str_airtemp;
String str_airhumidity;
String str_humidity_S1;
String str_humidity_S2;
String str_CurrentTime;

extern uint8_t MediumFontRus[];    
extern uint8_t SmallFontRus[];

unsigned long start_timer, end_timer;
uint32_t sensor_1, sensor_2;
uint32_t raw = 0;
uint32_t wait = 5 * 1000;      //Прерывание
uint32_t pumping = 1 * 1000;  //Время полива
uint32_t vkl = 1;
uint32_t otkl = 0;

const char* strM="JanFebMarAprMayJunJulAugSepOctNovDec";  // Определяем массив всех вариантов текстового представления текущего месяца.
const char* sysT=__TIME__;                                // Получаем время компиляции скетча в формате "SS:MM:HH".
const char* sysD=__DATE__;                                // Получаем дату  компиляции скетча в формате "MMM:DD:YYYY", где МММ - текстовое представление текущего месяца, например: Jul.
//  Парсим полученные значения sysT и sysD в массив i:    // Определяем массив «i» из 6 элементов типа int, содержащий следующие значения: секунды, минуты, часы, день, месяц и год компиляции скетча.
const int i[6] {(sysT[6]-48)*10+(sysT[7]-48), (sysT[3]-48)*10+(sysT[4]-48), (sysT[0]-48)*10+(sysT[1]-48), (sysD[4]-48)*10+(sysD[5]-48), ((int)memmem(strM,36,sysD,3)+3-(int)&strM[0])/3, (sysD[9]-48)*10+(sysD[10]-48)};


void setup() {
    Serial.begin(9600);
    time.begin();
    //time.settime(i[0],i[1],i[2],i[3],i[4],i[5]);                                            
    time.settime(__TIME__);                                                
    myOLED.begin();
    myOLED.setFont(MediumFontRus);
    dht.begin();    
  }

void loop() {
  if(millis() % 1000 == 0)
  {
  Watch();
  TempAndHumidity();
  
  delay(1);
  }
  
  if(millis() % 5000 == 0)
  {
  Watering();
    
  delay(1);
  }
}  

void Watch (void)
  {
    myOLED.print(time.gettime("H:i:s"), OLED_C, 1);
  }  


void TempAndHumidity (void)
{
  int AirTemp = round(dht.readTemperature());
  str_airtemp = "Темп:" + String(AirTemp) + "*C";
  myOLED.print(str_airtemp,OLED_C,4);
  
  int AirHumidity = round(dht.readHumidity());
  str_airhumidity = "Влаж:" + String(AirHumidity) + "%";
  myOLED.print(str_airhumidity,OLED_C,7);
}
  
void Watering (void)
{start_timer = millis();
    digitalWrite(Pump_1,vkl);//насос включается
    Serial.println(String(time.gettime("H:i:s"))+"-Включился");
                   
    if (millis() - start_timer >= 3000)       //полив
    {
    digitalWrite(Pump_1,otkl);                   //насос выключается
    Serial.println(String(time.gettime("H:i:s"))+"-Отлючился");
    
    }
}

 

301sem
Offline
Зарегистрирован: 14.01.2021
void Watch (void);                                        //  Объявляем функцию в которой будут выполняться действия зависящие от состояния энкодера и режима
027
void TempAndHumidity (void);                                        //  Объявляем функцию в которой будет обновляться информация дисплея в зависимости от режима, подрежима, выбранного таймера и значений массива valArray

Эти комментарии не читайте, забыл убрать

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

Вот так никогда не делайте

if (millis() % 1000 == 0)
...
if (millis() % 5000 == 0)

millis() может проскочить мимо (тем более, что у Вас длительные операции с датчиками) и никогда на быть кратным 5000.

Делайте, как Вы делайте в строке №103.

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Даже интересно каким образом условие в строке 103 может выполнится, учитывая строку 99 ?

Kakmyc
Offline
Зарегистрирован: 15.01.2018

Ну и опять же как сказал Петрович, если в строке 65 выражение в круглых скобках будет истинным, то никогда не выполнится строка 73, потому что там и delay(1) и куча тяжёлых функции.

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

Kakmyc
Offline
Зарегистрирован: 15.01.2018

ЕвгенийП пишет:

Вот так никогда не делайте

if (millis() % 1000 == 0)
...
if (millis() % 5000 == 0)

millis() может проскочить мимо (тем более, что у Вас длительные операции с датчиками) и никогда на быть кратным 5000.

Делайте, как Вы делайте в строке №103.

Так тоже не надо, он сначала переменную к миллис приводит, а потом пытается проверить ее на условие millis()-start_timer>=3000.
Включим насос и никогда не выключим...
Соседи будут рады такому автополиву.

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020
301sem
Offline
Зарегистрирован: 14.01.2021

как оно сейчас "работает" знаю, а как сделать что работало как надо, догадаться не могу

301sem
Offline
Зарегистрирован: 14.01.2021

к сожалению не помогло(

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Что не помогло то? Выкладывай....

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

301sem пишет:

к сожалению не помогло(


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

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

Kakmyc пишет:
Даже интересно каким образом условие в строке 103 может выполнится, учитывая строку 99 ?
А и не обратил внимания. Заметил первое, дальше не глядел. Старею :(

301sem
Offline
Зарегистрирован: 14.01.2021
void Watering (void)
{
  if(millis() - start_timer >= 5000) {
  sensor_1 = analogRead(SENSOR_1);             // Читаем "сырые" данные с датчика,
  sensor_1 = map(sensor_1, MIN_S1, MAX_S1, 0, 100);  // адаптируем значения от 0 до 100
  sensor_2 = analogRead(SENSOR_2);             // Читаем "сырые" данные с датчика,
  sensor_2 = map(sensor_2, MIN_S2, MAX_S2, 0, 100);  // адаптируем значения от 0 до 100
  str_humidity_S1 = "Влажность датчика 1 = " + String(sensor_1) + "%"; 
  str_humidity_S2 = "Влажность датчика 2 = " + String(sensor_2) + "%";
   
 start_timer = millis();
    state = 1;
    digitalWrite(Pump_1,state);//насос включается
    Serial.println(String(time.gettime("H:i:s"))+"-Включился");
  }
                   
    if(state == 1 && millis() - start_timer >= pumping)        //полив
    {
    state = 0;
    digitalWrite(Pump_1,state);                   //насос выключается
    Serial.println(String(time.gettime("H:i:s"))+"-Отключился");
    }
Получилось так. Но так наверно не очень грамотно.
И появилась преблемка, что секунды на дисплее в момент включения насоса "00".
Например, секунды идут: 01,02,03,04, в момент включения насоса 00, 06,07,08,09,00,11 и т.д. 

 

301sem
Offline
Зарегистрирован: 14.01.2021


void setup() {
    Serial.begin(9600);
    time.begin();
    //time.settime(i[0],i[1],i[2],i[3],i[4],i[5]);                                            
    time.settime(__TIME__);                                                
    myOLED.begin();
    myOLED.setFont(MediumFontRus);
    dht.begin();    
  }

void loop() {
  if (millis() - currentTime > 1000) 
  { 
  currentTime = millis();
  Watch();
  TempAndHumidity();
  }
  
  Watering();
  }  

void Watch (void)
  {
    myOLED.print(time.gettime("H:i:s"), OLED_C, 1);
  }  


void TempAndHumidity (void)
{
  int AirTemp = round(dht.readTemperature());
  str_airtemp = "Темп:" + String(AirTemp) + "*C";
  myOLED.print(str_airtemp,OLED_C,4);
  
  int AirHumidity = round(dht.readHumidity());
  str_airhumidity = "Влаж:" + String(AirHumidity) + "%";
  myOLED.print(str_airhumidity,OLED_C,7);
}
  
void Watering (void)
{
  if(millis() - start_timer >= 5000) {
  sensor_1 = analogRead(SENSOR_1);             // Читаем "сырые" данные с датчика,
  sensor_1 = map(sensor_1, MIN_S1, MAX_S1, 0, 100);  // адаптируем значения от 0 до 100
  sensor_2 = analogRead(SENSOR_2);             // Читаем "сырые" данные с датчика,
  sensor_2 = map(sensor_2, MIN_S2, MAX_S2, 0, 100);  // адаптируем значения от 0 до 100
  str_humidity_S1 = "Влажность датчика 1 = " + String(sensor_1) + "%"; 
  str_humidity_S2 = "Влажность датчика 2 = " + String(sensor_2) + "%";
    start_timer = millis();
    state = 1;
    digitalWrite(Pump_1,state);//насос включается
    Serial.println(String(time.gettime("H:i:s"))+"-Включился");
  }
                   
    if(state == 1 && millis() - start_timer >= pumping)        //полив
    {
    state = 0;
    digitalWrite(Pump_1,state);                   //насос выключается
    Serial.println(String(time.gettime("H:i:s"))+"-Отлючился");
    }
}

 

 

301sem
Offline
Зарегистрирован: 14.01.2021

Хоть немножко то правильно? грамотнее?

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Работает? Что еще-то нужно? ))

ЗЫ: на помпе нужно бы конденсатор припаять. Примерно на 100нФ (это с маркировкой 104). Дабы помехи давить

301sem
Offline
Зарегистрирован: 14.01.2021

Конденсатор поставлю, как только насос придет)

Работает, но в момент запуска насоса, на часах вместо секунд 00 показывает. Значит что-то не так. Да и потом, надо чтобы правильно работало и код красивый был. А не, пардон, га*нокод какой-то

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

301sem пишет:

Конденсатор поставлю, как только насос придет)

Работает, но в момент запуска насоса, на часах вместо секунд 00 показывает. Значит что-то не так. Да и потом, надо чтобы правильно работало и код красивый был. А не, пардон, га*нокод какой-то

Т.е. сейчас насоса нет? 

Насчет нуля ничего не скажу - не вижу используемых библиотек. Наверное, что-то не так ))

Красивый код - это со временем придет. Возможно. Да и потом любой "спец" может любой код говнокодом обозвать )))

301sem
Offline
Зарегистрирован: 14.01.2021

Насоса пока нет, едет) пока только 2 датчика влажности почвы есть.

Библиотеки:

#include <Wire.h>
#include <DHT.h>
#include <iarduino_OLED_txt.h>
#include <iarduino_RTC.h>
#include <Adafruit_Sensor.h>

#define  Pump_1       8
#define  SENSOR_1     A2
#define  MIN_S1       535                   
#define  MAX_S1       215
#define  Humidity_1   60

#define  Pump_2       9
#define  SENSOR_2     A3
#define  MIN_S2       535                   
#define  MAX_S2       215
#define  Humidity_2   60

#define  DHTPIN       2
#define  DHTTYPE      DHT22

iarduino_RTC time(RTC_DS1302, 10, 8, 9);                      
iarduino_OLED_txt myOLED(0x3C);
DHT dht(DHTPIN, DHTTYPE);

И получается вот такое:

23:00:00-Включился
23:00:37-Отлючился
23:00:00-Включился
23:00:42-Отлючился
23:00:00-Включился
23:00:47-Отлючился
23:00:00-Включился
...
v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Не больно хвалят эту библиотеку

301sem
Offline
Зарегистрирован: 14.01.2021

Если в коде все верно, буду копать в сторону библиотек! Спасибо огромное, Уважаемый v258)

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

По логу уже вижу, что на все про все уходит 5 секунд, а по условию вроде должно быть 5 + 3 = 8 секунд. Или нет?

301sem
Offline
Зарегистрирован: 14.01.2021

Опрос датчиков проводится каждые 5 секунд. Если значение датчика ниже заданного, на 3 секунды включается насос.

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

301sem пишет:

Если значение датчика ниже заданного, на 3 секунды включается насос.

Нету в коде никакого если. Насос включается каждые пять секунд в любом случае 

301sem
Offline
Зарегистрирован: 14.01.2021

Пардон, ввожу в заблуждение. Это то, что хочу реализовать. Сейчас для понимания как функция миллис работает пытаюсь реализовать, чтобы каждые 5 секунд включался насос на 3 секунды.

v258
v258 аватар
Offline
Зарегистрирован: 25.05.2020

Ну это получилось

301sem
Offline
Зарегистрирован: 14.01.2021

еще раз спасибо!)

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

v258 пишет:
Да и потом любой "спец" может любой код говнокодом обозвать )))

Точно! А на вопрос "какое же это говно?" ответит, "не знаю, в сортах говна не разбираюсь" :-)