Помогите разобраться с библиотекой iarduino_rtc

Xomyc
Offline
Зарегистрирован: 10.04.2020

Ну точнее там в принципе все понятно. Вот только почему-то функция blinktime() у меня не работает. Экран есть и стандартный 2х16 ардуиновский с I2C, и экранчик TFT от телефона Alcatel. Программа для обычных часов лежит на многих сайтах и там в момент установки времени должен мигать выбранный параметр (секунды, минуты, часы или там что другое). Так вот сами часы работают. Правда повозицца немного с кварцем пришлось. У меня была микросхемка ds1307, купил кварц в Чип и Дип, собрал на макетке - не работает. Повозился, в итоге нашел на старом медиацентре часовой кварт, впаял и все заработало. Так вот часы работают, но при установке не мигает устанавливаемы параметр.

Кроме часов есть два будильника, которые тоже должны мигать при установке, и мигают просто по millis(). Так вот они тоже мигают скажем 2 раза мигнет раз в секунду, потом 2 раза не мигает. Это скажем часы. А минуты могут наоборот не  горят вообще несколько секунл, потом 2 раза мигнут и снова не горят. Или вообще просто не горят. Код щаас приложу. Очищу от мусора и приложу. Всякие Delay вроде убраны отовсюду.

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

Лучший способ разобраться с этой библиотекой - забыть о её существовании, и взять нормальную.

Хотя, у Вас проблемы не с ней, а с Вашим кодом.

b707
Offline
Зарегистрирован: 26.05.2017

Xomyc - по-моему вы второй или даже третий раз спрашиваете про этот блинк. Если он вам так нужен - так напишите его сами, в конце концов это же не функция RTC. а только вывод на экран

Xomyc
Offline
Зарегистрирован: 10.04.2020

Вообще-то это функция RTC. Ну если говорить о blinktime().

А для мигания при установке будильника я свою процедуру написал. Так вот там мигает тоже не ставильно. В первом посте я описал в чем проблема. Но blinktime() вообще не мигает.

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

Щас дочищу код и выложу. К компу дома подойти не могу никак.

b707
Offline
Зарегистрирован: 26.05.2017

Xomyc пишет:

Щас дочищу код и выложу.

не надо код чистить, выкладывайте как есть. А то мы опять будем обсуждать "идеальный" код, а потом окажется что на реальном все работает совсем не так.

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

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

Вас не смущает, что RTC и мигание это совершенно разные области приложения знаний? Одна часы реального времени - должна давать правильное время , другая интерфейсы - красиво показывать на экране то что Вам хочется. Как они могут быть связаны прямо не понятно. Мигание к реальному времени ни как не относится. Исключительно к относительному, т.к. от реального времени ни как не зависит. И в 12 и 24 часа мигать будет одинаково. И даже без RTC, а, например, при вводе количества бутылок пива в заказе мигать тоже должно также как и при установке времени будильника? Может быть не скрещевать ужа и ежа а написать отдельную универсальную библиотеку меню с вводом чисел в мигающую позицию? Тем более, что у LCD1602 и похожих есть команда курсор - в библиотеке LiquidCrystal  blink(); cursor();setCursor(col,row); и прочие. 

Xomyc
Offline
Зарегистрирован: 10.04.2020

b707 пишет:

Xomyc пишет:

Щас дочищу код и выложу.

не надо код чистить, выкладывайте как есть. А то мы опять будем обсуждать "идеальный" код, а потом окажется что на реальном все работает совсем не так.

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

Да там закомментированного больше раза в 3 чем кода. Работает то незакомментированный код! Да и к компу пока подойти не могу.

Xomyc
Offline
Зарегистрирован: 10.04.2020

nik182 пишет:

Тем более, что у LCD1602 и похожих есть команда курсор - в библиотеке LiquidCrystal  blink(); cursor();setCursor(col,row); и прочие. 

Я уже убрал этот дисплей. Думал дело в нем и большой он. Поставил TFT с кноаочного алкателя 128х128.

Xomyc
Offline
Зарегистрирован: 10.04.2020

Вот код. Убрал только закомментированные строки.

#include <OneButton.h>
#include <Wire.h>
#include <iarduino_RTC.h>
#include <UTFT.h>

#define PIN_button 11       // указываем номер вывода arduino, к которому подключена кнопка
#define LCD_PIN 12          // указываем номер вывода arduino, который управляет питанием экрана
#define ALARM_PIN 13        // Пин на работку будильника

OneButton btn1(PIN_button,false);
extern uint8_t BigFont[];                 // задаем шрифт для дисплея
iarduino_RTC watch(RTC_DS1307);           // объявляем переменную time для работы с библиотекой, указывая название модуля RTC_DS1307
UTFT myGLCD(ILI9163,A2,A1,A3,10,A0);      // Объявляем LCD дисплей

uint8_t VAR_mode_SHOW   = 1;      // режим вывода: 1-часы 2-будильники
uint8_t VAR_mode_SET    = 0;      // режим установки времени: 0-нет 1-сек 2-мин 3-час 4-день 5-мес 6-год 7-день_недели
int8_t  VAR_AL_MIN1     = 10;     // Задаем минуты 1-ого будильника
int8_t  VAR_AL_MIN2     = 0;      // Задаем минуты 2-ого будильника
int8_t  VAR_AL_HOUR1    = 9;      // Задаем часы 1-ого будильника
int8_t  VAR_AL_HOUR2    = 22;     // Задаем часы 2-ого будильника
bool    VAR_alarm_FLAG1 = true;   // будильник1 разрешение работы
bool    VAR_alarm_FLAG2 = true;   // будильник2 разрешение работы
bool    VAR_set_direct  = true;   // направление изменения параметров: true в + false в -
bool    VAR_LCD_FLAG    = false;  // Состание экрана (выкл/вкл)
unsigned long AW        = 0;      // Переменная для отсчета времени работы после будильника
unsigned int  beg_dit   = 0;      // Счетчик мигания указателя направления корректировки

void setup() {
  pinMode(PIN_button, INPUT);     // устанавливаем режим работы вывода кнопки, как "вход"
  pinMode(LCD_PIN,    OUTPUT);      // устанавливаем режим работы вывода управления питанием экрана, как "выход"
  pinMode(ALARM_PIN,        OUTPUT);
  watch.begin();                   // инициируем RTC модуль
  myGLCD.InitLCD();
  myGLCD.setFont(BigFont);
  myGLCD.clrScr();
  myGLCD.setContrast(64);
  btn1.attachClick(BTNclick);
  btn1.attachDoubleClick(BTNdoubleclick);
  btn1.attachLongPressStop(LongPressStop);
  btn1.setClickTicks(200);
  btn1.setPressTicks(2000);
}

void loop() {
  btn1.tick();
  if (VAR_mode_SET > 0) watch.blinktime(VAR_mode_SET);                    // мигаем устанавливаемым параметром (если VAR_mode_SET больше 0)
  myGLCD.setColor(255, 255, 255);
  if (VAR_LCD_FLAG) digitalWrite(LCD_PIN,1);
  else digitalWrite(LCD_PIN,0);
  if(millis()%1000==0){                      // если прошла 1 секунда
  myGLCD.print(watch.gettime("H:i:s"), 0, 10);
  myGLCD.print(watch.gettime("d-m-y"), 0, 30);
  myGLCD.print("T1_"+Func_alarm_digits(7,VAR_AL_HOUR1,millis())+":"+Func_alarm_digits(8,VAR_AL_MIN1,millis()), 0, 50);
  myGLCD.print(Func_alarm_en(9,VAR_alarm_FLAG1,millis()), 0, 70);
  myGLCD.print("T2_"+Func_alarm_digits(10,VAR_AL_HOUR2,millis())+":"+Func_alarm_digits(11,VAR_AL_MIN2,millis()), 0, 90);
  myGLCD.print(Func_alarm_en(12,VAR_alarm_FLAG2,millis()), 0, 110);
  if (VAR_mode_SET > 0) {myGLCD.print(Func_show_direct(), 70, 110);}
  if(VAR_alarm_FLAG1){                     // если будильник1 включён
    if(watch.seconds==00){                  // если в текущем времени 0 секунд
      if(watch.minutes==VAR_AL_MIN1){     // если совпали минуты
        if(watch.Hours==VAR_AL_HOUR1){    // если совпали часы
          digitalWrite(ALARM_PIN, HIGH);
          AW = millis();
        }
      }
    }
  }
  if(VAR_alarm_FLAG2){                     // если будильник2 включён
    if(watch.seconds==00){                  // если в текущем времени 0 секунд
      if(watch.minutes==VAR_AL_MIN2){     // если совпали минуты
        if(watch.Hours==VAR_AL_HOUR2){    // если совпали часы
          digitalWrite(ALARM_PIN, HIGH);
          AW = millis();
        }
      }
    }
  }
 }
 if ((AW > 0) && (millis() - AW > 600000)) {digitalWrite(ALARM_PIN, LOW); AW = 0;}
}

void BTNclick() 
{
  if (VAR_LCD_FLAG)
  {
    if (VAR_mode_SET > 0)
    {
      if (VAR_set_direct)
      {
        switch (VAR_mode_SET){                                     // инкремент (увеличение) устанавливаемого значения
        /* сек */ case 1: watch.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
        /* мин */ case 2: watch.settime(-1, (watch.minutes==59?0:watch.minutes+1), -1, -1, -1, -1, -1); break;
        /* час */ case 3: watch.settime(-1, -1, (watch.Hours==23?0:watch.Hours+1),     -1, -1, -1, -1); break;
        /* дни */ case 4: watch.settime(-1, -1, -1, (watch.day==31?1:watch.day+1),         -1, -1, -1); break;
        /* мес */ case 5: watch.settime(-1, -1, -1, -1, (watch.month==12?1:watch.month+1),     -1, -1); break;
        /* год */ case 6: watch.settime(-1, -1, -1, -1, -1, (watch.year==99?0:watch.year+1),       -1); break;
        /* д.н.*/ case 7: VAR_AL_HOUR1++; if (VAR_AL_HOUR1 > 23) VAR_AL_HOUR1 = 0; break;
        /* д.н.*/ case 8: VAR_AL_MIN1++; if (VAR_AL_MIN1 > 59) VAR_AL_MIN1 = 0; break;
        /* д.н.*/ case 9: VAR_alarm_FLAG1 = !VAR_alarm_FLAG1; break;
        /* д.н.*/ case 10: VAR_AL_HOUR2++; if (VAR_AL_HOUR2 > 23) VAR_AL_HOUR2 = 0; break;
        /* д.н.*/ case 11: VAR_AL_MIN2++; if (VAR_AL_MIN2 > 59) VAR_AL_MIN2 = 0; break;
        /* д.н.*/ case 12: VAR_alarm_FLAG2 = !VAR_alarm_FLAG2; break;
        }
      }
      else
      {
        switch (VAR_mode_SET){                                     // инкремент (увеличение) устанавливаемого значения
      /* сек */ case 1: watch.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
      /* мин */ case 2: watch.settime(-1, (watch.minutes==0?59:watch.minutes-1), -1, -1, -1, -1, -1); break;
      /* час */ case 3: watch.settime(-1, -1, (watch.Hours==0?23:watch.Hours-1),     -1, -1, -1, -1); break;
      /* дни */ case 4: watch.settime(-1, -1, -1, (watch.day==1?31:watch.day-1),         -1, -1, -1); break;
      /* мес */ case 5: watch.settime(-1, -1, -1, -1, (watch.month==1?12:watch.month-1),     -1, -1); break;
      /* год */ case 6: watch.settime(-1, -1, -1, -1, -1, (watch.year==0?99:watch.year-1),       -1); break;
      /* д.н.*/ case 7: VAR_AL_HOUR1--; if (VAR_AL_HOUR1 < 0) {VAR_AL_HOUR1 = 23;} break;
      /* д.н.*/ case 8: VAR_AL_MIN1--; if (VAR_AL_MIN1 < 0) {VAR_AL_MIN1 = 59;} break;
      /* д.н.*/ case 9: VAR_alarm_FLAG1 = !(VAR_alarm_FLAG1); break;
      /* д.н.*/ case 10: VAR_AL_HOUR2--; if (VAR_AL_HOUR2 < 0) {VAR_AL_HOUR2 = 23;} break;
      /* д.н.*/ case 11: VAR_AL_MIN2--; if (VAR_AL_MIN2 < 0) {VAR_AL_MIN2 = 59;} break;
      /* д.н.*/ case 12: VAR_alarm_FLAG2 = !(VAR_alarm_FLAG2); break;
        }
      }
    }
    else {VAR_LCD_FLAG = false;}
  }
  else {VAR_LCD_FLAG = true;}
}

void BTNdoubleclick() 
{
  if (VAR_mode_SET > 0) VAR_set_direct = !VAR_set_direct;
}

void LongPressStop() 
{
  if (VAR_LCD_FLAG) {VAR_mode_SET++;if(VAR_mode_SET>12) VAR_mode_SET=0;Serial.println(VAR_mode_SET);}
}


// Функция вывода направления изменения значения параметра
String Func_show_direct()
{
  String dir;
  if (VAR_set_direct)
  {
    if (millis() - beg_dit <= 1000) {dir = "+  ";}
    if (millis() - beg_dit > 1000 && millis() - beg_dit <= 2000) {dir = " + ";}
    if (millis() - beg_dit > 2000 && millis() - beg_dit < 3000) {dir = "  +";}
  }
  else
  {
    if (millis() - beg_dit <= 1000) {dir = "-  ";}
    if (millis() - beg_dit > 1000 && millis() - beg_dit <= 2000) {dir = " - ";}
    if (millis() - beg_dit > 2000 && millis() - beg_dit < 3000) {dir = "  -";}
  }
  if (millis() - beg_dit == 3000) beg_dit = millis();
  return dir;
}

// Функция вывода времени в будильниках
String Func_alarm_digits(uint8_t rz,uint8_t tm,unsigned long sc){
  String rs;
  if (tm < 10) rs = "0"+String(tm);
  else rs = String(tm);
  if (VAR_mode_SET == 0){return rs;}
  else 
  {
    if (rz == VAR_mode_SET)
    {
      if (sc%2 == 0){return rs;}
      else {return "  ";}
    }
    else {return rs;}
  }
}

// Функция вывода включен или нет будильник
String Func_alarm_en(uint8_t rz,bool en,unsigned long sc){
  String rs;
  if (en) rs = "ON ";
  else rs = "OFF";
  if (VAR_mode_SET == 0){return rs;}
  else 
  {
    if (rz == VAR_mode_SET)
    {
      if (sc%2 == 0){return rs;}
      else {return "   ";}
    }
    else {return rs;}
  }
}

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

тут одна из проблем 

050  if(millis()%1000==0){                      // если прошла 1 секунда

у тебя в лупе стока науеверчено, что == 0  может быть только случайно.  

А так, весь код -> фпамойку();

Xomyc
Offline
Зарегистрирован: 10.04.2020

Ну за меня все равно никто не напишет.

А чего там в лупе науеверчено?

Задаем шрифт дисплея, выводим 4 строки на экран и отрабатываем будильник. Все.

А какие-нибудь конкретные предложения есть? То что науеверчено я и сам понимаю. Все что кассается часов содран в инете. При чем этот код в инете очень много где лежит.

 

050  if(millis()%1000==0){                      // если прошла 1 секунда

Не моя строка, но она ведь работает. Честно говоря особо о ней не задумывался. Так понимаю ее вообще можно убрать.

b707
Offline
Зарегистрирован: 26.05.2017

Xomyc пишет:

А какие-нибудь конкретные предложения есть? То что науеверчено я и сам понимаю. Все что кассается часов содран в инете. При чем этот код в инете очень много где лежит.

 

050  if(millis()%1000==0){                      // если прошла 1 секунда

Не моя строка, но она ведь работает. Честно говоря особо о ней не задумывался. Так понимаю ее вообще можно убрать.

то есть вы в этом коде вообще нифига не понимаете? - то что написал Дед и есть самое что ни на есть конкретное предложение - исправьте эту строчку -  шанс, что именно она портит мигание цифр на экране - процентов этак 80

Xomyc
Offline
Зарегистрирован: 10.04.2020

Так я и спросил что исправить?

Как я понимаю эту строчку.

Если целое значение от деления millis() на 1000 равно 0, код работает. Т.е. он срабатывает только каждую целую секунду.

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

b707
Offline
Зарегистрирован: 26.05.2017

Xomyc пишет:

Попробую убрать эту строчку.

"заставь дурака ..."

Не надо убирать. Идея исполнять код раз в секунду - абсолютно верная. Другой вопрос, что строка эта задачу решает плохо. Попробуйте задуматься, будет ли она работать, если это условие проверяется реже, чем раз в 1 мс?

Ну как поймете, в чем проблема - попробуйте исправить

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

Я когда то так делал:

//в переменных

uint32_t blink_timer;
boolean blink_flag;

//В цикле

if(millis()-blink_timer>=500){
blink_timer=millis();
blink_flag=!blink_flag;
}

//Отображение так

if(blink)печатаем данные else печатаем пробелы

 

Xomyc
Offline
Зарегистрирован: 10.04.2020

b707 пишет:

Попробуйте задуматься, будет ли она работать, если это условие проверяется реже, чем раз в 1 мс?

Ну как поймете, в чем проблема - попробуйте исправить

А почему она выполняется реже, чем раз в 1мс? Я прошу прощения, я совсем начинающий программист так сказать, и в теории вроде как loop как раз каждую 1 мс отрабатывает? Ну если нет всяких дилеев. А их нет.

Или я что-то не то говорю?

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

А вы на практике проверьте скоко луп выполняется.

b707
Offline
Зарегистрирован: 26.05.2017

Xomyc пишет:

А почему она выполняется реже, чем раз в 1мс? Я прошу прощения, я совсем начинающий программист так сказать, и в теории вроде как loop как раз каждую 1 мс отрабатывает? Ну если нет всяких дилеев. А их нет.

Откуда вы взяли эту "теорию" про выполнение ЛУП раз в 1мс - я не знаю. но ничего общего с правдой она не имеет. Луп выполняется так часто, как успевает. Совсем пустой ЛУП выполняется сотни тысяч раз в секунду, а по мере его заполнения все медленее и медленее. Например вывод всего одного символа в Сериал на "дефолтной скорости" 9600 как раз примерно занимает 1мс. Соответственно вот такой loop:

void loop() {
Serial.println("Hello!");
}

уже будет оборачиватся не быстрее 5-7мс. а это всего одна строчка!

А теперь сравните со своим кодом. Там и куча вычислений, и работа с часами. и . главное - вывод на ТФТ экран... Все это время и время.

 

Xomyc
Offline
Зарегистрирован: 10.04.2020

sadman41 пишет:
А вы на практике проверьте скоко луп выполняется.

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

Ну разве что:

unsigned int X

void setup() {
X=millis()
}

void loop() {
if millis() - X == 1000
{
   X = millis()
  //выполняем основной код
}
}

Больше ничего в голову не приходит.

b707
Offline
Зарегистрирован: 26.05.2017

Xomyc пишет:

Подскажите как реализовать, чтобы точно раз в секунду выполнялся.

Ну разве что:

unsigned int X

void setup() {
X=millis()
}

void loop() {
if millis() - X == 1000
{
   X = millis()
  //выполняем основной код
}
}

Больше ничего в голову не приходит.

это совсем неработоспособный код. И кроме того, он ничем не отличается от millis%1000

А зачем вам "точно"? - какая разница, покажете вы на часах время через 1000 мс или через 1002 мс? - вы сможете заметить разницу?

А точность самих часов не пострадает, вы же время с RTC берете, значит точность времени с точностью обновления нэкрана не связано никак

Xomyc
Offline
Зарегистрирован: 10.04.2020

Да мне не важно! Никто просто не говорит как это сделать! Подскажите код как это сделать. У меня личного опыта в написании кодов для микроконтроллеров с гулькин фиг. Я занимался много программированием, но на Delphi, на Java, на PowerShell  в конце концов. Там таких задач нет, как рассчет секунд, вот я и не знаю что делать.

b707
Offline
Зарегистрирован: 26.05.2017

Xomyc пишет:

Да мне не важно! Никто просто не говорит как это сделать! Подскажите код как это сделать.

ах еще и не важно? - "не знаю и знать не хочу, дайте готовое решение!" - в таком ключе продолжать неинтересно

Xomyc
Offline
Зарегистрирован: 10.04.2020

b707 пишет:

А зачем вам "точно"? - какая разница, покажете вы на часах время через 1000 мс или через 1002 мс? - вы сможете заметить разницу?

ВОт я и говорю, что мне не важно.

Xomyc
Offline
Зарегистрирован: 10.04.2020

b707 пишет:

Xomyc пишет:

Да мне не важно! Никто просто не говорит как это сделать! Подскажите код как это сделать.

ах еще и не важно? - "не знаю и знать не хочу, дайте готовое решение!" - в таком ключе продолжать неинтересно

Вы коверкаете мои слова не вчитавшись в них.

Это что вирус влияет! Все такие заведенные! Одно слово из текста схватил и давай ругацца!

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

Хотус, не надо ловить точно (==) момент - это ненадёжно, определяйте, что лимит перебран (>=)

Xomyc
Offline
Зарегистрирован: 10.04.2020

sadman41 пишет:

Хотус, не надо ловить точно (==) момент - это ненадёжно, определяйте, что лимит перебран (>=)

Вот спасибо! Идею понял! Ну вот так:

unsigned int X

void setup() {
X=millis()
}

void loop() {
if (millis() - X >= 1000)
{
   X = millis()
  //выполняем основной код
}
}

Но правда это никак не влияет.

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020
//Макрос таймера на миллис
#define every(x) \
  static uint32_t tmr;\
  bool flag = millis() - tmr >= (x);\
  if (flag) tmr = millis();\
  if (flag)
//======================

void setup() {
...
}

void loop() {
every(1000) {
//Здесь код будет выполнятся каждую секунду
...
    }
}

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Xomyc пишет:

Но правда это никак не влияет.

Да счас - а вот так:

unsigned int X

void setup() {
X=millis()
}

void loop() {
if (millis() - X >= 1000)
{
   X = millis()
  //выполняем основной код
}
//А тут опрашиваем кнопки
}

 

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020
unsigned long X = 0;

 void setup() {
 X=millis(); 
} 
void loop() { 
if (millis() - X >= 1000) {
 X = millis(); //Сброс таймера 
//выполняем основной код каждую секунду 
} 
}

 

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

millis же возвращает unsigned long а не unsigned int

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

Oreshek пишет:

//Макрос таймера на миллис
#define every(x) \
  static uint32_t tmr;\
  bool flag = millis() - tmr >= (x);\
  if (flag) tmr = millis();\
  if (flag)
//======================

void setup() {
...
}

void loop() {
every(1000) {
//Здесь код будет выполнятся каждую секунду
...
    }
}

так низзя. Этот макрос чуть сложнее пишется.

При таком написании, у Вас этот макрос только раз в пределах функции/блока использовать можно, второе использование даст повторное объявление переменных tmr и flag.

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Да, но там разве нужно использовать его больше одного раза в loop?

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

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

так низзя. Этот макрос чуть сложнее пишется.

Как?

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

Не, ну я ж проблему описал - она то понятна, так ведь? А как писать - думаю Вы и сами разберётесь. Ну, или посмотрите, например,  макрос ATOMIC_BLOCK в файле C:\Arduino\arduino-1.8.12\hardware\tools\avr\avr\include\util\atomic.h, там вроде эта проблема решена.

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

Oreshek пишет:

Да, но там разве нужно использовать его больше одного раза в loop?

А почему нет? Если мы двумя "светодиодами мигаем" с разными интервалами? Мало ли подобных процессов? Раз в секунду освещённость замерить, раз в минуту температуру  - и что, специально ради Вашего макроса функции создавать? Зачем, когда его можно просто нормально написать?

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

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

Oreshek пишет:

Да, но там разве нужно использовать его больше одного раза в loop?

А почему нет? Если мы двумя "светодиодами мигаем" с разными интервалами? Мало ли подобных процессов? Раз в секунду освещённость замерить, раз в минуту температуру  - и что, специально ради Вашего макроса функции создавать? Зачем, когда его можно просто нормально написать?

Да, я понимаю что можно лучше его написать, а так он подходит только если в этом блоке не нужно больше 1 интервала.

А если нужно больше то уже использовать обычный таймер.

ну или в крайнем случае можно в разные блоки засунуть))

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Так как то

#define PERIOD1   1000
#define PERIOD2   2000
#define PERIOD3   3000

unsigned long timer1, timer2, timer3;

void setup(void) {
...
}

void loop(void) {
if (millis() - timer1 > PERIOD1) {
...
}

if (millis() - timer2 > PERIOD2) {
...
}

if (millis() - timer3 > PERIOD3) {
...
}
}

 

Green
Offline
Зарегистрирован: 01.10.2015

А так?

#define every(ms)         _every(ms,__LINE__)
#define _every(ms,ln)     __every(ms,ln)
#define __every(ms,ln)    static uint32_t _##ln; \
                          if (millis() - _##ln >= (ms) && (_##ln = millis()))
                            

 

Xomyc
Offline
Зарегистрирован: 10.04.2020

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

#include <OneButton.h>
#include <Wire.h>
#include <iarduino_RTC.h>
#include <UTFT.h>

#define PIN_button 12       // указываем номер вывода arduino, к которому подключена кнопка
#define LCD_PIN 11          // указываем номер вывода arduino, который управляет питанием экрана
#define ALARM_PIN 13        // Пин на работку будильника

OneButton btn1(PIN_button,false);
extern uint8_t BigFont[];                 // задаем шрифт для дисплея
iarduino_RTC watch(RTC_DS1307);           // объявляем переменную time для работы с библиотекой, указывая название модуля RTC_DS1307
UTFT myGLCD(ILI9163,A2,A1,A3,10,A0);      // Объявляем LCD дисплей

uint8_t VAR_mode_SHOW   = 1;      // режим вывода: 1-часы 2-будильники
uint8_t VAR_mode_SET    = 0;      // режим установки времени: 0-нет 1-сек 2-мин 3-час 4-день 5-мес 6-год 7-день_недели
int8_t  VAR_AL_MIN1     = 10;     // Задаем минуты 1-ого будильника
int8_t  VAR_AL_MIN2     = 0;      // Задаем минуты 2-ого будильника
int8_t  VAR_AL_HOUR1    = 9;      // Задаем часы 1-ого будильника
int8_t  VAR_AL_HOUR2    = 22;     // Задаем часы 2-ого будильника
bool    VAR_alarm_FLAG1 = true;   // будильник1 разрешение работы
bool    VAR_alarm_FLAG2 = true;   // будильник2 разрешение работы
bool    VAR_set_direct  = true;   // направление изменения параметров: true в + false в -
bool    VAR_LCD_FLAG    = false;  // Состание экрана (выкл/вкл)
bool    VAR_chet        = true;  // Флаг, показывающий четная или нечетная секунда
unsigned long AW        = 0;      // Переменная для отсчета времени работы после будильника
unsigned long WS        = 0;      // Переменная для отработки скрипта раз в секунду
unsigned int  beg_dit   = 0;      // Счетчик мигания указателя направления корректировки

void setup() {
  pinMode(PIN_button, INPUT);     // устанавливаем режим работы вывода кнопки, как "вход"
  pinMode(LCD_PIN,    OUTPUT);      // устанавливаем режим работы вывода управления питанием экрана, как "выход"
  pinMode(ALARM_PIN,        OUTPUT);
  watch.begin();                   // инициируем RTC модуль
  myGLCD.InitLCD();
  myGLCD.setFont(BigFont);
  myGLCD.clrScr();
  myGLCD.setContrast(64);
  btn1.attachClick(BTNclick);
  btn1.attachDoubleClick(BTNdoubleclick);
  btn1.attachLongPressStop(LongPressStop);
  btn1.setClickTicks(200);
  btn1.setPressTicks(2000);
}

void loop() {
  btn1.tick();
  if(millis() - WS >= 1000){                      // если прошла 1 секунда
    WS = millis();
    VAR_chet = !VAR_chet;
    myGLCD.setColor(255, 255, 255);
    if (VAR_LCD_FLAG) digitalWrite(LCD_PIN,1);
    else digitalWrite(LCD_PIN,0);
    myGLCD.print(Func_clock_digits(), 0, 10);
    myGLCD.print(Func_cal_digits(), 0, 30);
    myGLCD.print("T1_"+Func_alarm_digits(7,VAR_AL_HOUR1)+":"+Func_alarm_digits(8,VAR_AL_MIN1), 0, 50);
    myGLCD.print(Func_alarm_en(9,VAR_alarm_FLAG1), 0, 70);
    myGLCD.print("T2_"+Func_alarm_digits(10,VAR_AL_HOUR2)+":"+Func_alarm_digits(11,VAR_AL_MIN2), 0, 90);
    myGLCD.print(Func_alarm_en(12,VAR_alarm_FLAG2), 0, 110);
    if (VAR_mode_SET > 0) {myGLCD.print(Func_show_direct(), 70, 110);}
    if(VAR_alarm_FLAG1){                     // если будильник1 включён
      if(watch.seconds==00){                  // если в текущем времени 0 секунд
        if(watch.minutes==VAR_AL_MIN1){     // если совпали минуты
          if(watch.Hours==VAR_AL_HOUR1){    // если совпали часы
            digitalWrite(ALARM_PIN, HIGH);
            AW = millis();
          }
        }
      }
    }
    if(VAR_alarm_FLAG2){                     // если будильник2 включён
      if(watch.seconds==00){                  // если в текущем времени 0 секунд
        if(watch.minutes==VAR_AL_MIN2){     // если совпали минуты
          if(watch.Hours==VAR_AL_HOUR2){    // если совпали часы
            digitalWrite(ALARM_PIN, HIGH);
            AW = millis();
          }
        }
      }
    }
  }
  if ((AW > 0) && (millis() - AW > 600000)) {digitalWrite(ALARM_PIN, LOW); AW = 0;}
}

void BTNclick() 
{
  if (VAR_LCD_FLAG)
  {
    if (VAR_mode_SET > 0)
    {
      if (VAR_set_direct)
      {
        switch (VAR_mode_SET){                                     // инкремент (увеличение) устанавливаемого значения
        /* сек */ case 1: watch.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
        /* мин */ case 2: watch.settime(-1, (watch.minutes==59?0:watch.minutes+1), -1, -1, -1, -1, -1); break;
        /* час */ case 3: watch.settime(-1, -1, (watch.Hours==23?0:watch.Hours+1),     -1, -1, -1, -1); break;
        /* дни */ case 4: watch.settime(-1, -1, -1, (watch.day==31?1:watch.day+1),         -1, -1, -1); break;
        /* мес */ case 5: watch.settime(-1, -1, -1, -1, (watch.month==12?1:watch.month+1),     -1, -1); break;
        /* год */ case 6: watch.settime(-1, -1, -1, -1, -1, (watch.year==99?0:watch.year+1),       -1); break;
        /* д.н.*/ case 7: VAR_AL_HOUR1++; if (VAR_AL_HOUR1 > 23) VAR_AL_HOUR1 = 0; break;
        /* д.н.*/ case 8: VAR_AL_MIN1++; if (VAR_AL_MIN1 > 59) VAR_AL_MIN1 = 0; break;
        /* д.н.*/ case 9: VAR_alarm_FLAG1 = !VAR_alarm_FLAG1; break;
        /* д.н.*/ case 10: VAR_AL_HOUR2++; if (VAR_AL_HOUR2 > 23) VAR_AL_HOUR2 = 0; break;
        /* д.н.*/ case 11: VAR_AL_MIN2++; if (VAR_AL_MIN2 > 59) VAR_AL_MIN2 = 0; break;
        /* д.н.*/ case 12: VAR_alarm_FLAG2 = !VAR_alarm_FLAG2; break;
        }
      }
      else
      {
        switch (VAR_mode_SET){                                     // инкремент (увеличение) устанавливаемого значения
      /* сек */ case 1: watch.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
      /* мин */ case 2: watch.settime(-1, (watch.minutes==0?59:watch.minutes-1), -1, -1, -1, -1, -1); break;
      /* час */ case 3: watch.settime(-1, -1, (watch.Hours==0?23:watch.Hours-1),     -1, -1, -1, -1); break;
      /* дни */ case 4: watch.settime(-1, -1, -1, (watch.day==1?31:watch.day-1),         -1, -1, -1); break;
      /* мес */ case 5: watch.settime(-1, -1, -1, -1, (watch.month==1?12:watch.month-1),     -1, -1); break;
      /* год */ case 6: watch.settime(-1, -1, -1, -1, -1, (watch.year==0?99:watch.year-1),       -1); break;
      /* д.н.*/ case 7: VAR_AL_HOUR1--; if (VAR_AL_HOUR1 < 0) {VAR_AL_HOUR1 = 23;} break;
      /* д.н.*/ case 8: VAR_AL_MIN1--; if (VAR_AL_MIN1 < 0) {VAR_AL_MIN1 = 59;} break;
      /* д.н.*/ case 9: VAR_alarm_FLAG1 = !(VAR_alarm_FLAG1); break;
      /* д.н.*/ case 10: VAR_AL_HOUR2--; if (VAR_AL_HOUR2 < 0) {VAR_AL_HOUR2 = 23;} break;
      /* д.н.*/ case 11: VAR_AL_MIN2--; if (VAR_AL_MIN2 < 0) {VAR_AL_MIN2 = 59;} break;
      /* д.н.*/ case 12: VAR_alarm_FLAG2 = !(VAR_alarm_FLAG2); break;
        }
      }
    }
    else {VAR_LCD_FLAG = false;}
  }
  else {VAR_LCD_FLAG = true;}
}

void BTNdoubleclick() 
{
  if (VAR_mode_SET > 0) VAR_set_direct = !VAR_set_direct;
}

void LongPressStop() 
{
  if (VAR_LCD_FLAG) {VAR_mode_SET++;if(VAR_mode_SET>12) VAR_mode_SET=0;}
}


// Функция вывода направления изменения значения параметра
String Func_show_direct()
{
  String dir;
  if (VAR_mode_SET > 0)
  {
    if (VAR_set_direct)
    {
      if (VAR_chet) {dir = "+ ";}
      else {dir = " +";}
    }
    else
    {
      if (VAR_chet) {dir = "- ";}
      else {dir = " -";}
    }
  }
  else {dir = "  ";}
  return dir;
}

// Функция вывода времени в часах
String Func_clock_digits(){
  String rs;
  if (VAR_mode_SET > 0 && !VAR_chet)
  {
    switch (VAR_mode_SET){
      case 3: rs = "  "+String(watch.gettime(":i:s"));break;
      case 2: rs = String(watch.gettime("H:"))+"  "+String(watch.gettime(":s"));break;
      case 1: rs = String(watch.gettime("H:i:"))+"  ";break;
    }
  }
  else
  {
    switch (VAR_mode_SET){
      case 0: rs = watch.gettime("H:i:s");break;
      case 1: rs = watch.gettime("H:i:s");break;
      case 2: rs = watch.gettime("H:i:s");break;
      case 3: rs = watch.gettime("H:i:s");break;
    }
  }
  return rs;
}

// Функция вывода даты в часах
String Func_cal_digits(){
  String rs;
  if (VAR_mode_SET > 0 && !VAR_chet)
  {
    switch (VAR_mode_SET){
      case 4: rs = "  "+String(watch.gettime("-m-y"));break;
      case 5: rs = String(watch.gettime("d-"))+"  "+String(watch.gettime("-y"));break;
      case 6: rs = String(watch.gettime("d-m-"))+"  ";break;
    }
  }
  else
  {
    switch (VAR_mode_SET){
      case 0: rs = watch.gettime("d-m-y");break;
      case 4: rs = watch.gettime("d-m-y");break;
      case 5: rs = watch.gettime("d-m-y");break;
      case 6: rs = watch.gettime("d-m-y");break;
    }
  }
  return rs;
}

// Функция вывода времени в будильниках
String Func_alarm_digits(uint8_t rz,uint8_t tm){
  String rs;
  if (tm < 10) rs = "0"+String(tm);
  else rs = String(tm);
  if (VAR_mode_SET > 0)
  {
    if (rz == VAR_mode_SET)
    {
      if (VAR_chet) {rs = "  ";}
    }
  }
  return rs;
}

// Функция вывода включен или нет будильник
String Func_alarm_en(uint8_t rz,bool en){
  String rs;
  if (en) rs = "ON ";
  else rs = "OFF";
  if (VAR_mode_SET > 0)
  {
    if (rz == VAR_mode_SET)
    {
      if (VAR_chet) {rs = "  ";}
    }
  }
  return rs;
}

Осталась маленька проблеммка с OneButton.h.

Вроде я поставил удержание 2000, а нажатие 200. Что-то очень долго приходится держать удержание, секунд 5, и при двойном клике иногда обычный клик срабатывает.

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Green пишет:

А так?

#define every(ms)         _every(ms,__LINE__)
#define _every(ms,ln)     __every(ms,ln)
#define __every(ms,ln)    static uint32_t _##ln; \
                          if (millis() - _##ln >= (ms) && (_##ln = millis()))
                            

 

Я в программирование не настолько силён.

Можете хоть чуть чуть пояснить что здесь происходит?

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Xomyc пишет:

Осталась маленька проблеммка с OneButton.h.

Вроде я поставил удержание 2000, а нажатие 200. Что-то очень долго приходится держать удержание, секунд 5, и при двойном клике иногда обычный клик срабатывает.

Попробуйте библиотеку gyverButton, удобная, и без косяков(вроде бы)!

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

Чем твоя "своя мигалка для часов", отличается от той что я тут запостил ?
Названием переменных ?
Ты не ученик гивера часом ?
У того тоже все "свое" с гитхаба надергано.

Xomyc
Offline
Зарегистрирован: 10.04.2020

Oreshek пишет:

Попробуйте библиотеку gyverButton, удобная, и без косяков(вроде бы)!

С нее и начал вчера. Весь день с ней провозился, так она и не заработала. Даже обычное нажатие только к вечеру запустил.

Oreshek
Oreshek аватар
Offline
Зарегистрирован: 19.04.2020

Kakmyc пишет:
Чем твоя "своя мигалка для часов", отличается от той что я тут запостил ? Названием переменных ? Ты не ученик гивера часом ? У того тоже все "свое" с гитхаба надергано.

Это вы к кому обращаетесь?

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

Oreshek пишет:

Kakmyc пишет:
Чем твоя "своя мигалка для часов", отличается от той что я тут запостил ? Названием переменных ? Ты не ученик гивера часом ? У того тоже все "свое" с гитхаба надергано.

Это вы к кому обращаетесь?

К ТС'у

Xomyc
Offline
Зарегистрирован: 10.04.2020

Нет, Гайвера я конечно знаю, много чего у него по первости содрал. Гирлянду на  елку, лампу рассвет с эффектами. Но мигалку для часов только что сам написал.

А с гитхаба почему не брать, если все ссылки на библиотеки туда идут?

В общем вроде и кнопки добил. Теперь нормально. Поставил клик 400 и удержание 1000.

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

Oreshek пишет:

Так как то

Не, ну это не спортивно! Давайте одним макросом! Это же гораздо интереснее!

Xomyc
Offline
Зарегистрирован: 10.04.2020

Oreshek пишет:

Green пишет:

А так?

#define every(ms)         _every(ms,__LINE__)
#define _every(ms,ln)     __every(ms,ln)
#define __every(ms,ln)    static uint32_t _##ln; \
                          if (millis() - _##ln >= (ms) && (_##ln = millis()))
                            

 

Я в программирование не настолько силён.

Можете хоть чуть чуть пояснить что здесь происходит?

Тоже присоединюсь к вопросу. Что за конструкция

_##ln

 

Green
Offline
Зарегистрирован: 01.10.2015

Это что бы использовать где не попадя и ниочём не думать.)

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

Xomyc пишет:

Нет, Гайвера я конечно знаю, много чего у него по первости содрал. Гирлянду на  елку, лампу рассвет с эффектами. Но мигалку для часов только что сам написал.

А с гитхаба почему не брать, если все ссылки на библиотеки туда идут?

В общем вроде и кнопки добил. Теперь нормально. Поставил клик 400 и удержание 1000.

Ну я и говорю "сам".
Мало ли, что тебе тут писали:
http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/pomogite-razob...

Xomyc
Offline
Зарегистрирован: 10.04.2020

Kakmyc пишет:
Xomyc пишет:

Нет, Гайвера я конечно знаю, много чего у него по первости содрал. Гирлянду на  елку, лампу рассвет с эффектами. Но мигалку для часов только что сам написал.

А с гитхаба почему не брать, если все ссылки на библиотеки туда идут?

В общем вроде и кнопки добил. Теперь нормально. Поставил клик 400 и удержание 1000.

Ну я и говорю "сам". Мало ли, что тебе тут писали: http://arduino.ru/forum/pesochnitsa-razdel-dlya-novichkov/pomogite-razobratsya-s-bibliotekoi-iarduinortc-0#comment-531517

Не совсем понял на что ссылка! На эту же тему? В кодах там вроде ничего похожего на то что я написал нет. Ну кроме того, что то высвечивается скажем минута, то нет. Но это по умолчанию понятно. Просто если есть готовая функция, зачем самому писать? А если не нарвался хотя бы раз, то как знать будешь, что она не работает?