Не могу разобраться с управлением через модуль реального времени DS3231

RamasTex

✩✩✩✩✩✩✩
11 Ноя 2020
23
3
Всем привет. Такая тема. Подкинул значит модуль реального времени DS3231 к Arduino и с его помощью зажигаю светодиод в нужное мне время. Но задача в том, что бы он работал определённый интервал времени, который задаётся пользователем. Пробую использовать таймер на Millis который отсчитает время и светодиод погаснет. Но светодиод светит всего 1 секунду и гаснет. Может кто сталкивался с подобным. И знает в чем дело.
C++:
#include "GyverEncoder.h" //библитека для энкодера
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <LiquidCrystal_I2C.h>
#include <iarduino_RTC.h>
#include <Wire.h> 

unsigned long work_time =(long)1*1000;
unsigned long period_timer=(long)1*1000;
unsigned long work_timer;

#define ENCODER_TYPE 0      // тип энкодера (0 или 1). Если энкодер работает некорректно (пропуск шагов), смените тип
#define ENC_REVERSE 0       // 1 - инвертировать энкодер, 0 - нет
#define CLK 3
#define DT 2
#define SW 1

LiquidCrystal_I2C lcd(0x27,20,4); 
iarduino_RTC watch(RTC_DS3231);

int hour1,mi1,sek1,thisM3,thisS3,thisH3,thisS4;

boolean flag;//флаг на сработку

Encoder enc1(CLK, DT, SW);  // для работы c кнопкой
int8_t  arrowPos5 = 0;

void setup() {
  // put your setup code here, to run once:
pinMode(4,OUTPUT);
  lcd.init();                     //инициализируем дисплей
  lcd.backlight();
  watch.begin();                  // Инициируем работу с модулем времени
   enc1.setType(ENCODER_TYPE);
}

void loop() {
  // put your main code here, to run repeatedly:
  lcd.setCursor(0, 0);
   lcd.print("<Cyclic timer>");
   lcd.setCursor(0, 1);
   lcd.print("Turn on-");
   lcd.setCursor(0, 2);
   lcd.print("Work time");
   lcd.setCursor(1, 3);
   lcd.print("Back");
   lcd.setCursor(8, 3);
   lcd.print("Time");
   lcd.setCursor(12, 3);
   lcd.print(watch.gettime("H:i:s"));
    enc1.tick();
     if (enc1.isTurn())
     {
       int increment= 0;  // локальная переменная направления
  // получаем направление   
    if (enc1.isRight()) increment = 1;
    if (enc1.isLeft()) increment = -1;
    arrowPos5 += increment;  // двигаем курсор
    arrowPos5 = constrain(arrowPos5, 0, 5 - 1); // ограничиваем
    increment = 0;  // обнуляем инкремент
    if (enc1.isRightH())
     changeSettingsCiclictimerWork(-1);
    else if (enc1.isLeftH())
      changeSettingsCiclictimerWork(1);
    changeSetCiclictimerWork();
     }
     CiclictimerWork();
}
void changeSetCiclictimerWork()
{
  switch (arrowPos5) {
  case 0: drawArrowCiclictimerWork(9, 1);
  break;
   case 1: drawArrowCiclictimerWork(12, 1);
  break;
   case 2: drawArrowCiclictimerWork(15, 1);
  break;
   case 3: drawArrowCiclictimerWork(9, 2);
  break;
   case 4: drawArrowCiclictimerWork(0, 3);
  break;
   }
   lcd.setCursor(10, 1);
  if (thisH3 < 10) lcd.print(0);
  lcd.print(thisH3);
  lcd.setCursor(13, 1);
  if (thisM3 < 10) lcd.print(0);
  lcd.print(thisM3);
  lcd.setCursor(16, 1);
  if (thisS3 < 10) lcd.print(0);
  lcd.print(thisS3);
   lcd.setCursor(10, 2);
  if (thisS4 < 10) lcd.print(0);
  lcd.print(thisS4);
}
void drawArrowCiclictimerWork(byte col, byte row) {
  lcd.setCursor(9, 1); lcd.print(" ");
  lcd.setCursor(12, 1); lcd.print("h");
  lcd.setCursor(15, 1); lcd.print("m");
  lcd.setCursor(18, 1); lcd.print("s");
  lcd.setCursor(9, 2); lcd.print(":");
  lcd.setCursor(12, 2); lcd.print("s");
  lcd.setCursor(0, 3); lcd.print(" ");
  lcd.setCursor(col, row); lcd.write(126);
}
//установка времени начала полива и продолжительности полива
void changeSettingsCiclictimerWork(int increment)
{
if (arrowPos5 == 0){
thisH3 += increment;
if (thisH3<0)
thisH3=0;
if (thisH3>23)
thisH3=23;
}
else
{
if (arrowPos5 == 1)
thisM3 += increment;
if (thisM3<0)
thisM3=0;
if (thisM3 > 59) {
        thisM3 = 0;
        thisH3++;
}
if(arrowPos5 == 2)
thisS3 += increment;
if (thisS3<0)
thisS3=0;
if (thisS3 > 59) {
        thisS3 = 0;
        thisM3++;
}
}
if (arrowPos5 == 3)
thisS4 += increment;
if (thisS4<0)
thisS4=0;
if (thisS4>99)
thisS4=99;
}
void CiclictimerWork()
{
 watch.gettime();
   Serial.print(watch.Hours);
   Serial.print(watch.minutes);
   Serial.print(watch.seconds);
   hour1= int(watch.Hours);
   mi1= int(watch.minutes);
   sek1= int(watch.seconds);
   if ((hour1==thisH3)&&(mi1== thisM3)&&(sek1==thisS3))
  {
  digitalWrite(4,1);
   flag=true;
 }
  else
  {
  if ( (((long)millis() - work_timer) > (work_time*thisS4)) && flag) {
    flag = false;            // сброс флага на выполнение
     period_timer = millis();
   digitalWrite(4,0);
  }
  }
  }
 

Вложения

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,302
Москва
Ну так.. У Вас включение и выключение встречается по одному разу, что очень хорошо.
Выключение проверяется в том случае. если не надо включать, что то же замечательно.
Значит проблема только в одном, в условии:
C++:
if ( (((long)millis() - work_timer) > (work_time * thisS4)) && flag) {
      flag = false;            // сброс флага на выполнение
      period_timer = millis();
      digitalWrite(4, 0);
    }
выведите в монитор порта все переменные из условия и попробуйте посчитать на калькуляторе что выходит, думаю что сами найдете проблему.
 
  • Лойс +1
Реакции: RamasTex

RamasTex

✩✩✩✩✩✩✩
11 Ноя 2020
23
3
Читаю монитор порта значения милис там дичь
вот такое число 15431125338 постоянно меняется
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,302
Москва
То , что значение миллис постоянно меняется это нормально. но при перезапуске платы оно должно быть небольшим = равно время работы в секундах умножить на 1000.
Вы там во всю меняете типы данных , вот это например: (long). Может и в этом проблема.
 
  • Лойс +1
Реакции: RamasTex

Эдуард Анисимов

★★★★★★✩
23 Сен 2019
2,410
976
58
Марий-Эл
Есть два варианта. Выставляете Alarm на нужное время, при срабатывании зажигаете светодиод.
Аларму присваиваете ткущее значение + необходимый промежуток. Аларм срабатывает,гасите светодиод.

Вариант два, если Аларм должен быть всегда фиксированный и тормошить туда сюда не катит.
Эта микросхема имеет два будильника.

Аларм1 настраиваем на нужное время.
Аларм2 = Аларм1 + Нужная пауза.
Всё это дело вешается на прерывание. Срабатывает Аларм1 - зажигаем диод. Срабатывает Аларм2 - гасим светодиод.
 
Изменено:
  • Лойс +1
Реакции: RamasTex

RamasTex

✩✩✩✩✩✩✩
11 Ноя 2020
23
3
Ок. понятно, остаётся только узнать, что есть прерывания
 

RamasTex

✩✩✩✩✩✩✩
11 Ноя 2020
23
3
Просто нужно знать какая переменная для отсчёта времени используется. Вернее тип переменной. К времени когда включился светодиод прибавить время работы. Получить изменённую переменную, а потом просто проверять условие с каждым тиком. И когда условие сойдётся выключится светодиод. Такой вариант думаю сойдет, а мож я уже бред несу
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,302
Москва
Это есть в описании функции millis - unsigned long

Я уже много раз объяснял почему нельзя прибавлять. Надо сравнивать время прошедшее с момента включения светодиода до текущего момента. И если это время больше заданного интервала - выключать светодиод.
 
  • Лойс +1
Реакции: RamasTex

RamasTex

✩✩✩✩✩✩✩
11 Ноя 2020
23
3
Время лучше в секунды перевести. Я правильно Вас понял