Alarm.alarmRepeat и память

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

kpik, выкладываю ваш скетч в моем варианте. Точнее сразу в двух.

Первый - каждое утро в 6 утра задает звонки на текущий день. Параметр число алармов #define dtNBR_ALARMS в библиотеке TimeAlarm.h должен быть установлен как <максимальное число звонков в день +1>

/* (c) B707 2017 */ 

#include <Wire.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <avr/pgmspace.h>

#define alarm_day(x)  pgm_read_byte(alarms + x*3) 
#define alarm_hour(x) pgm_read_byte(alarms + x*3 +1)
#define alarm_min(x)  pgm_read_byte(alarms + x*3 + 2)

// *****  Расписание звонков : день недели, час, минуты *****
// 0b01010100  - дни недели согласно Time.h - Sun - Sat 1..7
//   |||||||
//   ||||||Sun
//   |||||Mon
//   ||||Thu
//   .....
//   |
//   Sat
const byte PROGMEM alarms[][3] =
{
  { 0b01111100, 7, 55},
  { 0b01111100, 8, 0},
  { 0b00000100, 8, 40},
  { 0b00000100, 8, 50},
  { 0b00000100, 9, 30},
  { 0b01111100, 9, 40},
  { 0b00000100, 10, 20},
  { 0b01111100, 10, 35},
  { 0b00000100, 11, 15},
  { 0b01111100, 11, 30},
  { 0b00000100, 12, 10},
  { 0b00000100, 12, 20},
  { 0b00000100, 13, 00},
  { 0b00000100, 13, 5},
  { 0b01111100, 13, 40},
  { 0b00000100, 14, 20},
  { 0b01111100, 14, 30},
  { 0b00000100, 15, 10},
  { 0b00000100, 15, 20},
  { 0b00000100, 16, 0},
  { 0b01111100, 16, 10},
  { 0b00000100, 16, 55},
  { 0b00000100, 17, 5},
  { 0b00000100, 17, 45},
    
  { 0b01111000, 8, 40},
  { 0b01111000, 8, 50},
  { 0b01111000, 9, 50},
  { 0b01111000, 10, 45},
  { 0b01111000, 11, 45},
  { 0b01111000, 12, 30},
  { 0b01111000, 12, 35},
  { 0b01111000, 13, 20},
  { 0b01111000, 14, 25},
  { 0b01111000, 15, 15},
  { 0b01111000, 15, 25},
  { 0b01111000, 16, 15},
  { 0b01111000, 17, 0},
  { 0b01111000, 17, 10},
  { 0b01111000, 17, 55},
  {0,  0,  0}			// признак конца массива 
};

// **** Установка звонков на текущий день *****
void todayAlarms() {
  int day_of_week_now = weekday();	// день недели 
  int hour_now = hour();		// текущее время - часы
  int minute_now = minute();		// минуты
  byte i = 0;
  while (alarm_day(i) != 0) 		// просматриваем расписание звонков			
    { if ((alarm_day(i) & (1<< day_of_week_now)) != 0) 
        {   // если строка расписания действует сегодня
        if ( (alarm_hour(i) > hour_now) || ((alarm_hour(i) == hour_now) && (alarm_min(i) > minute_now)))  
           { // если текущее время меньше времени звонка - установить Аларм
            Alarm.alarmOnce(day_of_week_now,alarm_hour(i),alarm_min(i),0,rele);
            }
       }
     i++;  
  }
}    

void rele(){

  Serial.println("text");    
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  pinMode(12, OUTPUT);
  Serial.print("Turning pin 13 LED off at ");
  digitalClockDisplay();
  Serial.println("Завершение настройки....");
}


void setup()
{
  Serial.begin(9600);
  Serial.println("Загружаем настройки..."); 
   setSyncProvider(RTC.get); 
  if (timeStatus() != timeSet) 
    Serial.println("Не удалось получить время!");
  else
    Serial.println("Время успешно получено!");
    todayAlarms();				// при старте программы уставнавливаем звонки на ближ. день
    Alarm.alarmRepeat(6,11,22,todayAlarms);     // каждый день утром в 6:11:22 устанавливаем звонки на сегодня

}
void  loop(){  
  digitalClockDisplay();
  Alarm.delay(1000);
}
void digitalClockDisplay()
{
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); 
}

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

Второй - задает только ближайший звонок, таким образом число алармов в библиотеке можно оставить по умолчанию - 6 шт, что экономит память. Следующий звонок устанавливается автоматически, в процедуре rele()

#include <Wire.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <avr/pgmspace.h>

#define alarm_day(x)  pgm_read_byte(alarms + x*3) 
#define alarm_hour(x) pgm_read_byte(alarms + x*3 +1)
#define alarm_min(x)  pgm_read_byte(alarms + x*3 + 2)
#define alarm_AM(x)   (alarm_hour(x) * 60 + alarm_min(x))

const byte PROGMEM alarms[][3] =
{
  { 0b01111100, 7, 55},
  { 0b01111100, 8, 0},
  { 0b00000100, 8, 40},
  { 0b00000100, 8, 50},
  { 0b00000100, 9, 30},
  { 0b01111100, 9, 40},
  { 0b00000100, 10, 20},
  { 0b01111100, 10, 35},
  { 0b00000100, 11, 15},
  { 0b01111100, 11, 30},
  { 0b00000100, 12, 10},
  { 0b00000100, 12, 20},
  { 0b00000100, 13, 00},
  { 0b00000100, 13, 5},
  { 0b01111100, 13, 40},
  { 0b00000100, 14, 20},
  { 0b01111100, 14, 30},
  { 0b00000100, 15, 10},
  { 0b00000100, 15, 20},
  { 0b00000100, 16, 0},
  { 0b01111100, 16, 10},
  { 0b00000100, 16, 55},
  { 0b00000100, 17, 5},
  { 0b00000100, 17, 45},
    
  { 0b01111000, 8, 40},
  { 0b01111000, 8, 50},
  { 0b01111000, 9, 50},
  { 0b01111000, 10, 45},
  { 0b01111000, 11, 45},
  { 0b01111000, 12, 30},
  { 0b01111000, 12, 35},
  { 0b01111000, 13, 20},
  { 0b01111000, 14, 25},
  { 0b01111000, 15, 15},
  { 0b01111000, 15, 25},
  { 0b01111000, 16, 15},
  { 0b01111000, 17, 0},
  { 0b01111000, 17, 10},
  { 0b01111000, 17, 55},
  {0,  0,  0}
};


int findNextAlarm() {
  int day_of_week_now = weekday();
  int min_AM_now = hour() *  60 + minute();
  int next_alarm_time = 24*60;
  int al_ind = -1;
  byte i = 0;
  while (alarm_day(i) != 0)
    { if ((alarm_day(i) & (1<< day_of_week_now)) != 0) {
        if ( alarm_AM(i) > min_AM_now)  {
            if (alarm_AM(i) < next_alarm_time) 
             {next_alarm_time = alarm_AM(i);
              al_ind = i;}
            }
       }
     i++;  
  }
 return al_ind; 
}
void setNextAlarm() {

  int next_alarm = findNextAlarm();
  if (next_alarm != -1) 
    Alarm.alarmOnce(alarm_hour(next_alarm),alarm_min(next_alarm),0,rele);
}    

void rele(){

  Serial.println("text");    
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  pinMode(12, OUTPUT);
  Serial.print("Turning pin 13 LED off at ");
  digitalClockDisplay();
  setNextAlarm();
  Serial.println("Завершение настройки....");
}


void setup()
{
  Serial.begin(9600);
  Serial.println("Загружаем настройки..."); 
   setSyncProvider(RTC.get); 
  if (timeStatus() != timeSet) 
    Serial.println("Не удалось получить время!");
  else
    Serial.println("Время успешно получено!");
    setNextAlarm();
    Alarm.alarmRepeat(6,11,22,setNextAlarm);

}
void  loop(){  
  digitalClockDisplay();
  Alarm.delay(1000);
}
void digitalClockDisplay()
{
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); 
}

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

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

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

По расходу памяти.

Как стало понятно при тестировании кода, размер данных в ОЗУ в первую очередь зависит от числа созданных экземпляров таймера Alarm.alarmRepeat - "алармов", все остальное на расход ОЗУ влияет мало.

Скетч из сообщения #8 после исправления ошибок занимал 7840 байт флеша и 1524 байт ОЗУ. Правда, эти цифры мало что значат, так как реально скетч не работал - для составления расписания на неделю требуется установить примерно 120 "алармов", в то время как уже при 80 расход ОЗУ превышал 80%.

Первый скетч из предыдущего сообщения имеет размер 7638 байт и требует 982 байта ОЗУ. Для упрощения алгоритма в нем задаются сразу все звонки на текущий день, что означает установку порядка 25 -30 "алармов", поэтому использование оперативки в нем довольно высокое. Его кардинальное отличие от предыдущего - в нем помещается все расписание и даже есть запас на расширение.

Второй исправленный скетч задает "аларм" только на один следующий звонок. Когда аларм срабатывает - устанавливается следующий. Размер этого кода такой же, как предыдущий, но за счет снижения числа таймеров размер занятого ОЗУ снизился до 718 байт. Главное преимущество этого кода - он допускает почти неограниченное расщирение расписания - до нескольких тысяч событий.

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

в епром или прогмем можно запхать все возможные времена звонков.

На текущий день задавать только индексы оттуда

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

DetSimen пишет:

в епром или прогмем можно запхать все возможные времена звонков.

На текущий день задавать только индексы оттуда

так вроде так и сделано. Или я не понял, что ты имешь в виду.

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

Да. Я с пахмелья неразлядел. Сорри.

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

Спасибо, затестим, отпишусь обязательно!

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

b707 пишет:

kpik, выкладываю ваш скетч в моем варианте. Точнее сразу в двух.

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

 

Ошибок нет, но, на  12 пине не дергает реле, я так понимаю не выполняется void rele(), так как даже в консоли нет ни одной из 3-ех надписей. 

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

kpik пишет:

Ошибок нет, но, на  12 пине не дергает реле, я так понимаю не выполняется void rele(), так как даже в консоли нет ни одной из 3-ех надписей. 

который из двух кодов вы пробовали?

Что касается 12 пина - в вашем коде в функции rele он и не должен дергаться - вы на него ничего не выводите.

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

b707 пишет:

 

который из двух кодов вы пробовали?

Что касается 12 пина - в вашем коде в функции rele он и не должен дергаться - вы на него ничего не выводите.

 

Оба кода, подскажите пожалуйста в каком месте я туплю?

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

kpik пишет:

Оба кода, подскажите пожалуйста в каком месте я туплю?

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

Что касается функции rele(), то в первом коде она целиком взята из вашего кода сообщения 8, я не менял в ней ни байта. Обратите внимание, что в ней на 12 пин ничего не выводится, пин только обьявляется как OUTPUT.   Вероятно, вы сами отключили управление реле для тестирования.

 

Для того, чтобы понять, в чем дело - я попрошу вставить вот эти строки в первый код вместо строки 78 и выложить вывод программы

Serial.print("Set alarm: ");
Serial.print(day_of_week_now);
Serial.print(" ");
Serial.print(alarm_hour(i));
Serial.print(":");
Serial.println(alarm_min(i));
Alarm.alarmOnce(day_of_week_now,alarm_hour(i),alarm_min(i),0,rele);

 

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

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

забавно .... но так быть не должно.

Ладно,  видимо все-таки придется сначала отладить код :)

Вечером оттестирую и выложу исправленный вариант.

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

kpik - нашел ошибку

Замените в обоих скетчах первые три дефайна на код

#define alarm_day(x)  pgm_read_byte(&alarms[x][0]) 
#define alarm_hour(x) pgm_read_byte(&alarms[x][1])
#define alarm_min(x)  pgm_read_byte(&alarms[x][2])

В коде 1 это строки с 9 по 11, во втором - с 7 по 9-ую.

Скомпилировал и проверил на Нано - алармы ставятся правильно.

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

b707 пишет:

kpik - нашел ошибку

Замените в обоих скетчах первые три дефайна на код

#define alarm_day(x)  pgm_read_byte(&alarms[x][0]) 
#define alarm_hour(x) pgm_read_byte(&alarms[x][1])
#define alarm_min(x)  pgm_read_byte(&alarms[x][2])

В коде 1 это строки с 9 по 11, во втором - с 7 по 9-ую.

Скомпилировал и проверил на Нано - алармы ставятся правильно.

 

 

Да, вы как всегда правы! Теперь указываются алармы правильно!

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

kpik пишет:

 Теперь указываются алармы правильно!

осталось попробовать на реальных звонках. Это только вы на своей стороне можете сделать, у меня звонков нет :)

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

b707 пишет:

осталось попробовать на реальных звонках. Это только вы на своей стороне можете сделать, у меня звонков нет :)

 

Звонки подаются пока отлично, вы бы не могли подсказать как правильно вывести на экран дата / время и желательно через сколько реле сработает? 

 

почему-то мой дисплей 16,2 через i2c конфликтует с реле. 

пробовал вот с этим кодом, но наличие кнопок не столь важно

// Подключаем библиотеки:
#include <Wire.h>                            // подключаем библиотеку для работы с шиной I2C
#include <LiquidCrystal_I2C.h>               // подключаем библиотеку для работы с LCD дисплеем
#include <iarduino_RTC.h>                    // подключаем библиотеку для работы с RTC модулем
LiquidCrystal_I2C lcd(0x27,16,2);            // объявляем  переменную для работы с LCD дисплеем, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2)
iarduino_RTC time(RTC_DS1307);               // объявляем  переменную для работы с RTC модулем,  указывая название модуля
// Объявляем переменные и константы:
const uint8_t PIN_button_SET  = 8;           // указываем номер вывода arduino, к которому подключена кнопка SET
const uint8_t PIN_button_UP   = 9;           // указываем номер вывода arduino, к которому подключена кнопка UP
const uint8_t PIN_button_DOWN = 10;           // указываем номер вывода arduino, к которому подключена кнопка DOWN
      uint8_t VAR_mode_SHOW   = 1;           // режим вывода: 1-время 2-дата
      uint8_t VAR_mode_SET    = 0;           // режим установки времени: 0-нет 1-сек 2-мин 3-час 4-день 5-мес 6-год 7-день_недели
void setup() {

  pinMode(PIN_button_SET,  INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
  pinMode(PIN_button_UP,   INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
  pinMode(PIN_button_DOWN, INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
  delay(300);                                // ждем 300мс
  time.begin();                              // инициируем RTC модуль
  lcd.begin();                                // инициируем LCD дисплей
  lcd.backlight();                           // включаем подсветку LCD дисплея
}
void loop(){
  if(millis()%1000==0){                      // если прошла 1 секунда
      lcd.setCursor(3, 0);                   // устанавливаем курсор в позицию: столбец 0, строка 0
      lcd.print(time.gettime("d.m.Y"));              // выводим текст
      lcd.setCursor(4, 1);                   // устанавливаем курсор в позицию: столбец 0, строка 1
    if(VAR_mode_SHOW==1){                    // если установлен режим вывода времени
      lcd.print(time.gettime("H:i:s"));      // выводим время
    }
    if(VAR_mode_SHOW==2){                    // если установлен режим вывода даты
      lcd.print("SCHOOL4.ORG.UA");  // выводим дату
    }
    delay(1);                                // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс
  }
  Func_buttons_control();                    // передаём управление кнопкам
}
// Функция управления кнопками:
void Func_buttons_control(){
  uint8_t i=0;
  time.blinktime(VAR_mode_SET);                                  // мигаем устанавливаемым параметром (если VAR_mode_SET больше 0)
//Если часы находятся в режиме установки даты/времени
  if(VAR_mode_SET){
//  Если нажата кнопка UP
    if(digitalRead(PIN_button_UP  )){
      while(digitalRead(PIN_button_UP)){delay(50);}              // ждём пока мы не отпустим кнопку UP
      switch (VAR_mode_SET){                                     // инкремент (увеличение) устанавливаемого значения
      /* сек */ case 1: time.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
      /* мин */ case 2: time.settime(-1, (time.minutes==59?0:time.minutes+1), -1, -1, -1, -1, -1); break;
      /* час */ case 3: time.settime(-1, -1, (time.Hours==23?0:time.Hours+1),     -1, -1, -1, -1); break;
      /* дни */ case 4: time.settime(-1, -1, -1, (time.day==31?1:time.day+1),         -1, -1, -1); break;
      /* мес */ case 5: time.settime(-1, -1, -1, -1, (time.month==12?1:time.month+1),     -1, -1); break;
      /* год */ case 6: time.settime(-1, -1, -1, -1, -1, (time.year==99?0:time.year+1),       -1); break;
      /* д.н.*/ case 7: time.settime(-1, -1, -1, -1, -1, -1, (time.weekday==6?0:time.weekday+1) ); break;
      }
    }
//  Если нажата кнопка DOWN
    if(digitalRead(PIN_button_DOWN)){
      while(digitalRead(PIN_button_DOWN)){delay(50);}            // ждём пока мы её не отпустим
      switch (VAR_mode_SET){                                     // декремент (уменьшение) устанавливаемого значения
      /* сек */ case 1: time.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
      /* мин */ case 2: time.settime(-1, (time.minutes==0?59:time.minutes-1), -1, -1, -1, -1, -1); break;
      /* час */ case 3: time.settime(-1, -1, (time.Hours==0?23:time.Hours-1),     -1, -1, -1, -1); break;
      /* дни */ case 4: time.settime(-1, -1, -1, (time.day==1?31:time.day-1),         -1, -1, -1); break;
      /* мес */ case 5: time.settime(-1, -1, -1, -1, (time.month==1?12:time.month-1),     -1, -1); break;
      /* год */ case 6: time.settime(-1, -1, -1, -1, -1, (time.year==0?99:time.year-1),       -1); break;
      /* д.н.*/ case 7: time.settime(-1, -1, -1, -1, -1, -1, (time.weekday==0?6:time.weekday-1) ); break;
      }
    }
//  Если нажата кнопка SET
    if(digitalRead(PIN_button_SET)){
      while(digitalRead(PIN_button_SET)){                        // ждём пока мы её не отпустим
        delay(10);
        if(i<200){i++;}else{lcd.clear();}                        // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран
      }
      if(i<200){                                                 // если кнопка SET удерживалась меньше 2 секунд
        VAR_mode_SET++;                                          // переходим к следующему устанавливаемому параметру
        if(VAR_mode_SHOW==1 && VAR_mode_SET>3){VAR_mode_SET=1;}  // возвращаемся к первому устанавливаемому параметру
        if(VAR_mode_SHOW==2 && VAR_mode_SET>7){VAR_mode_SET=4;}  // возвращаемся к первому устанавливаемому параметру
      }else{                                                     // если кнопка SET удерживалась дольше 2 секунд, то требуется выйти из режима установки даты/времени
        VAR_mode_SET=0;                                          // выходим из режима установки даты/времени
      }
    }
//Если часы находятся в режиме вывода даты/времени
  }else{
//  Если нажата кнопка SET
    if(digitalRead(PIN_button_SET)){
      while(digitalRead(PIN_button_SET)){delay(10);              // ждём пока мы её не отпустим
        if(i<200){i++;}else{lcd.clear();}                        // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран
      }
      if(i<200){                                                 // если кнопка SET удерживалась меньше 2 секунд
        lcd.clear();                                             // стираем экран
        VAR_mode_SHOW=VAR_mode_SHOW==1?2:1;                      // меняем режим вывода: дата/время
      }else{                                                     // если 
        if(VAR_mode_SHOW==1){VAR_mode_SET=1;}                    // если установлен режим вывода времени, то устанавливаемый параметр - секунды
        if(VAR_mode_SHOW==2){VAR_mode_SET=4;}                    // если установлен режим вывода даты,    то устанавливаемый параметр - день
      }
    }
  }
}

 

 

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

 

ЧЧ:ММ ДД.ММ.ГГГГ

rele: ММ minut

 

Если это проблематично то не стоит, вы и так очень помогли!

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

kpik пишет:

почему-то мой дисплей 16,2 через i2c конфликтует с реле. 

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

не вполне понимаю, о каких библиотеках вы говорите - обьясните подробнее. Насколько мне кажется, реле вообще не использует библиотек - там же просто один цифровой пин, который вы переключаете HIGH-LOW

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

b707 пишет:

не вполне понимаю, о каких библиотеках вы говорите - обьясните подробнее. Насколько мне кажется, реле вообще не использует библиотек - там же просто один цифровой пин, который вы переключаете HIGH-LOW

 

/* (c) B707 2017


Первый - каждое утро в 6 утра задает звонки на текущий день. Параметр число алармов #define dtNBR_ALARMS в библиотеке TimeAlarm.h должен быть установлен как <максимальное число звонков в день +1>


Первый скетч из предыдущего сообщения имеет размер 7638 байт и требует 982 байта ОЗУ. Для упрощения алгоритма в нем задаются сразу все звонки на текущий день, что означает установку порядка 25 -30 "алармов", поэтому использование оперативки в нем довольно высокое. Его кардинальное отличие от предыдущего - в нем помещается все расписание и даже есть запас на расширение.

*/ 

#include <Wire.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <avr/pgmspace.h>

#define alarm_day(x)  pgm_read_byte(&alarms[x][0]) 
#define alarm_hour(x) pgm_read_byte(&alarms[x][1])
#define alarm_min(x)  pgm_read_byte(&alarms[x][2])
const int buzzer = 3;
// *****  Расписание звонков : день недели, час, минуты *****
// 0b01010100  - дни недели согласно Time.h - Sun - Sat 1..7
//   |||||||
//   ||||||Sun
//   |||||Mon
//   ||||Thu
//   .....
//   |
//   Sat
const byte PROGMEM alarms[][3] =
{
  { 0b01111100, 7, 55},
  { 0b01111100, 8, 0},
  { 0b00000100, 8, 40},
  { 0b00000100, 8, 50},
  { 0b00000100, 9, 30},
  { 0b01111100, 9, 40},
  { 0b00000100, 10, 20},

    
  { 0b01111000, 8, 40},
  { 0b01111000, 8, 50},
  { 0b01111000, 9, 50},
  { 0b01111000, 10, 45},
  { 0b01111000, 11, 45},
  { 0b01111000, 12, 30},
  {0,  0,  0}      // признак конца массива 
};

// **** Установка звонков на текущий день *****
void todayAlarms() {
  int day_of_week_now = weekday();  // день недели 
  int hour_now = hour();    // текущее время - часы
  int minute_now = minute();    // минуты
  byte i = 0;
  while (alarm_day(i) != 0)     // просматриваем расписание звонков     
    { if ((alarm_day(i) & (1<< day_of_week_now)) != 0) 
        {   // если строка расписания действует сегодня
        if ( (alarm_hour(i) > hour_now) || ((alarm_hour(i) == hour_now) && (alarm_min(i) > minute_now)))  
           { // если текущее время меньше времени звонка - установить Аларм
            Alarm.alarmOnce(day_of_week_now,alarm_hour(i),alarm_min(i),0,rele);
            }
       }
 
  }
}    

void rele(){
Serial.println("Начало подачи звонка..."); 


// пищик
tone(buzzer, 2000);
delay(1000);
noTone(buzzer);

  
// реле
digitalWrite(12, HIGH);
Alarm.delay(5000);
digitalWrite(12, LOW);


Serial.println("Конец подачи звонка..."); 
}


void setup()
{
  Serial.begin(9600);
  Serial.println("Загружаем настройки..."); 
   setSyncProvider(RTC.get); 
  if (timeStatus() != timeSet) 
    Serial.println("Не удалось получить время!");
  else
    Serial.println("Время успешно получено!");
    todayAlarms();        // при старте программы уставнавливаем звонки на ближ. день
    Alarm.alarmRepeat(6,11,22,todayAlarms);     // каждый день утром в 6:11:22 устанавливаем звонки на сегодня

  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
   pinMode(12, OUTPUT);
  pinMode(buzzer, OUTPUT);
  Serial.print("LED на 13 pin выключен в ");
  digitalClockDisplay();
  Serial.println("Завершение настройки....");
}
void  loop(){  
  digitalClockDisplay();
  Alarm.delay(1000);

  
}
void digitalClockDisplay()
{
  Serial.print(hour());
  printDigits(minute());
  printDigits(second());
  Serial.println(); 
}

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

вот рабочий код пищик+реле+в консоль выводит, а вот ниже код тот же самый но с выводом часов на первой строке (так по идее планировалось)

 

// Подключаем библиотеки:
#include <Wire.h>                            // подключаем библиотеку для работы с шиной I2C
#include <LiquidCrystal_I2C.h>               // подключаем библиотеку для работы с LCD дисплеем
#include <iarduino_RTC.h>                    // подключаем библиотеку для работы с RTC модулем
LiquidCrystal_I2C lcd(0x27,16,2);            // объявляем  переменную для работы с LCD дисплеем, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2)
iarduino_RTC time(RTC_DS1307);               // объявляем  переменную для работы с RTC модулем,  указывая название модуля


#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <avr/pgmspace.h>


const int buzzer = 3;


#define alarm_day(x)  pgm_read_byte(&alarms[x][0]) 
#define alarm_hour(x) pgm_read_byte(&alarms[x][1])
#define alarm_min(x)  pgm_read_byte(&alarms[x][2])

// *****  Расписание звонков : день недели, час, минуты *****
// 0b01010100  - дни недели согласно Time.h - Sun - Sat 1..7
//   |||||||
//   ||||||Sun
//   |||||Mon
//   ||||Thu
//   .....
//   |
//   Sat
const byte PROGMEM alarms[][3] =
{
  { 0b01111100, 7, 55},
  { 0b01111100, 8, 0},
  { 0b00000100, 8, 40},
  { 0b00000100, 8, 50},

  { 0b01111000, 8, 40},
  { 0b01111000, 8, 50},
  { 0b01111000, 9, 50},
  { 0b01111000, 10, 45},
  { 0b01111000, 11, 45},

  {0,  0,  0}      // признак конца массива 
};

// **** Установка звонков на текущий день *****
void todayAlarms() {
  int day_of_week_now = weekday();  // день недели 
  int hour_now = hour();    // текущее время - часы
  int minute_now = minute();    // минуты
  byte i = 0;
  while (alarm_day(i) != 0)     // просматриваем расписание звонков     
    { if ((alarm_day(i) & (1<< day_of_week_now)) != 0) 
        {   // если строка расписания действует сегодня
        if ( (alarm_hour(i) > hour_now) || ((alarm_hour(i) == hour_now) && (alarm_min(i) > minute_now)))  
           { // если текущее время меньше времени звонка - установить Аларм
        
        
        Alarm.alarmOnce(day_of_week_now,alarm_hour(i),alarm_min(i),0,rele);





/*
 * проверка кода с выводом в консоль
 *
Serial.print("Set alarm: ");
Serial.print(day_of_week_now);
Serial.print(" ");
Serial.print(alarm_hour(i));
Serial.print(":");
Serial.println(alarm_min(i));
Alarm.alarmOnce(day_of_week_now,alarm_hour(i),alarm_min(i),0,rele);

*/




            
            }
       }
    
  }
}    


// Объявляем переменные и константы:
const uint8_t PIN_button_SET  = 8;           // указываем номер вывода arduino, к которому подключена кнопка SET
const uint8_t PIN_button_UP   = 9;           // указываем номер вывода arduino, к которому подключена кнопка UP
const uint8_t PIN_button_DOWN = 10;           // указываем номер вывода arduino, к которому подключена кнопка DOWN
      uint8_t VAR_mode_SHOW   = 1;           // режим вывода: 1-время 2-дата
      uint8_t VAR_mode_SET    = 0;           // режим установки времени: 0-нет 1-сек 2-мин 3-час 4-день 5-мес 6-год 7-день_недели
void setup() {

  pinMode(PIN_button_SET,  INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
  pinMode(PIN_button_UP,   INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
  pinMode(PIN_button_DOWN, INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
  delay(300);                                // ждем 300мс
  time.begin();                              // инициируем RTC модуль
  lcd.begin();                                // инициируем LCD дисплей
  lcd.backlight();                           // включаем подсветку LCD дисплея




  Serial.begin(9600);
  Serial.println("Загружаем настройки..."); 
   setSyncProvider(RTC.get); 
  if (timeStatus() != timeSet) 
    Serial.println("Не удалось получить время!");
  else
    Serial.println("Время успешно получено!");

// digitalClockDisplay();


    
    todayAlarms();        // при старте программы уставнавливаем звонки на ближ. день
    Alarm.alarmRepeat(6,11,22,todayAlarms);     // каждый день утром в 6:11:22 устанавливаем звонки на сегодня




  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
   pinMode(12, OUTPUT);
  pinMode(buzzer, OUTPUT);
  Serial.print("LED на 13 pin выключен в ");
//  digitalClockDisplay();
  Serial.println("Завершение настройки....");


}
void loop(){
  if(millis()%1000==0){                      // если прошла 1 секунда
      lcd.setCursor(3, 0);                   // устанавливаем курсор в позицию: столбец 0, строка 0
      lcd.print(time.gettime("H:i d.m.Y"));              // выводим время + дату
      lcd.setCursor(4, 1);                   // устанавливаем курсор в позицию: столбец 0, строка 1
    if(VAR_mode_SHOW==1){                    // если установлен режим вывода времени
      lcd.print(ostalos: );      // выводим остаток минут до реле ...пока не выводим...
    }
    if(VAR_mode_SHOW==2){                    // если установлен режим вывода даты
      lcd.print("");  // выводим дату
    }
    delay(1);                                // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс
  }
  Func_buttons_control();                    // передаём управление кнопкам
}
// Функция управления кнопками:
void Func_buttons_control(){
  uint8_t i=0;
  time.blinktime(VAR_mode_SET);                                  // мигаем устанавливаемым параметром (если VAR_mode_SET больше 0)
//Если часы находятся в режиме установки даты/времени
  if(VAR_mode_SET){
//  Если нажата кнопка UP
    if(digitalRead(PIN_button_UP  )){
      while(digitalRead(PIN_button_UP)){delay(50);}              // ждём пока мы не отпустим кнопку UP
      switch (VAR_mode_SET){                                     // инкремент (увеличение) устанавливаемого значения
      /* сек */ case 1: time.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
      /* мин */ case 2: time.settime(-1, (time.minutes==59?0:time.minutes+1), -1, -1, -1, -1, -1); break;
      /* час */ case 3: time.settime(-1, -1, (time.Hours==23?0:time.Hours+1),     -1, -1, -1, -1); break;
      /* дни */ case 4: time.settime(-1, -1, -1, (time.day==31?1:time.day+1),         -1, -1, -1); break;
      /* мес */ case 5: time.settime(-1, -1, -1, -1, (time.month==12?1:time.month+1),     -1, -1); break;
      /* год */ case 6: time.settime(-1, -1, -1, -1, -1, (time.year==99?0:time.year+1),       -1); break;
      /* д.н.*/ case 7: time.settime(-1, -1, -1, -1, -1, -1, (time.weekday==6?0:time.weekday+1) ); break;
      }
    }
//  Если нажата кнопка DOWN
    if(digitalRead(PIN_button_DOWN)){
      while(digitalRead(PIN_button_DOWN)){delay(50);}            // ждём пока мы её не отпустим
      switch (VAR_mode_SET){                                     // декремент (уменьшение) устанавливаемого значения
      /* сек */ case 1: time.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
      /* мин */ case 2: time.settime(-1, (time.minutes==0?59:time.minutes-1), -1, -1, -1, -1, -1); break;
      /* час */ case 3: time.settime(-1, -1, (time.Hours==0?23:time.Hours-1),     -1, -1, -1, -1); break;
      /* дни */ case 4: time.settime(-1, -1, -1, (time.day==1?31:time.day-1),         -1, -1, -1); break;
      /* мес */ case 5: time.settime(-1, -1, -1, -1, (time.month==1?12:time.month-1),     -1, -1); break;
      /* год */ case 6: time.settime(-1, -1, -1, -1, -1, (time.year==0?99:time.year-1),       -1); break;
      /* д.н.*/ case 7: time.settime(-1, -1, -1, -1, -1, -1, (time.weekday==0?6:time.weekday-1) ); break;
      }
    }
//  Если нажата кнопка SET
    if(digitalRead(PIN_button_SET)){
      while(digitalRead(PIN_button_SET)){                        // ждём пока мы её не отпустим
        delay(10);
        if(i<200){i++;}else{lcd.clear();}                        // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран
      }
      if(i<200){                                                 // если кнопка SET удерживалась меньше 2 секунд
        VAR_mode_SET++;                                          // переходим к следующему устанавливаемому параметру
        if(VAR_mode_SHOW==1 && VAR_mode_SET>3){VAR_mode_SET=1;}  // возвращаемся к первому устанавливаемому параметру
        if(VAR_mode_SHOW==2 && VAR_mode_SET>7){VAR_mode_SET=4;}  // возвращаемся к первому устанавливаемому параметру
      }else{                                                     // если кнопка SET удерживалась дольше 2 секунд, то требуется выйти из режима установки даты/времени
        VAR_mode_SET=0;                                          // выходим из режима установки даты/времени
      }
    }
//Если часы находятся в режиме вывода даты/времени
  }else{
//  Если нажата кнопка SET
    if(digitalRead(PIN_button_SET)){
      while(digitalRead(PIN_button_SET)){delay(10);              // ждём пока мы её не отпустим
        if(i<200){i++;}else{lcd.clear();}                        // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран
      }
      if(i<200){                                                 // если кнопка SET удерживалась меньше 2 секунд
        lcd.clear();                                             // стираем экран
        VAR_mode_SHOW=VAR_mode_SHOW==1?2:1;                      // меняем режим вывода: дата/время
      }else{                                                     // если 
        if(VAR_mode_SHOW==1){VAR_mode_SET=1;}                    // если установлен режим вывода времени, то устанавливаемый параметр - секунды
        if(VAR_mode_SHOW==2){VAR_mode_SET=4;}                    // если установлен режим вывода даты,    то устанавливаемый параметр - день
      }
    }
  }
}



void rele(){
Serial.println("Zvonok Zvonok Zvonok Zvonok Zvonok"); 

// реле + пищик
  digitalWrite(12, HIGH);
  Alarm.delay(5000);
  digitalWrite(12, LOW);

 tone(buzzer, 2000); // Send 1KHz sound signal...
  delay(1000);        // ...for 1 sec
  noTone(buzzer);     // Stop sound...

}

 

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

kpik, у вас не реле конфликтует, а команда "tone". Уберите ее - и экран будет работать. Это известная вещь, tone с очень многими библиотеками не работает.

 

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

b707 пишет:

kpik, у вас не реле конфликтует, а команда "tone". Уберите ее - и экран будет работать. Это известная вещь, tone с очень многими библиотеками не работает.

 

 

Подскажите пожалуйста на что ее можно заменить чтоб осталась возможность использовать пищик? Там также без коментирования digitalClockDisplay() не удается запуститься.

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

kpik пишет:

Подскажите пожалуйста на что ее можно заменить чтоб осталась возможность использовать пищик? Там также без коментирования digitalClockDisplay() не удается запуститься.

попробуйте поставить между пищиком и ардуино резистор на 150-300 Ом, некоторым помогает.

Насчет проблем с digitalClockDisplay() - насколько я вижу, вы из своего последнего кода эту процедуру совсем убрали(может ошиблись?) - поэтому и вызов ее, конечно же, надо закомментировать.

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

Я как раз указал тот код который запустился с укаанием даты и времени на дисплее, но не срабатывала реле во время аларма.

 

Сопротивление на питание или на пин?

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

kpik. я что-то запутался. Давайте решать проблемы последовательно. Если из второго кода сообщения 68 удалить операторы tone - реле срабатывает? LCD экран работает нормально?

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

Не совсем понимаю, чего это LCD и tone() конфликтует, но есть "пищики" активные и пассивные. Пассивным нужен tone(), а у активных мультивибратор интегрирован - им достаточно только за управляющийх хвост дернуть.

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

не срабатывает реле, время на часах идет, ошибок нет:

// Подключаем библиотеки:
#include <Wire.h>                            // подключаем библиотеку для работы с шиной I2C
#include <LiquidCrystal_I2C.h>               // подключаем библиотеку для работы с LCD дисплеем
#include <iarduino_RTC.h>                    // подключаем библиотеку для работы с RTC модулем
LiquidCrystal_I2C lcd(0x27,16,2);            // объявляем  переменную для работы с LCD дисплеем, указывая параметры дисплея (адрес I2C = 0x27, количество столбцов = 16, количество строк = 2)
iarduino_RTC time(RTC_DS1307);               // объявляем  переменную для работы с RTC модулем,  указывая название модуля


#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <avr/pgmspace.h>


//const int buzzer = 3;


#define alarm_day(x)  pgm_read_byte(&alarms[x][0]) 
#define alarm_hour(x) pgm_read_byte(&alarms[x][1])
#define alarm_min(x)  pgm_read_byte(&alarms[x][2])

// *****  Расписание звонков : день недели, час, минуты *****
// 0b01010100  - дни недели согласно Time.h - Sun - Sat 1..7
//   |||||||
//   ||||||Sun
//   |||||Mon
//   ||||Thu
//   .....
//   |
//   Sat
const byte PROGMEM alarms[][3] =
{
  { 0b01111100, 7, 55},
  { 0b01111100, 8, 0},
  { 0b00000100, 8, 40},
  { 0b00000100, 8, 50},
  { 0b00000100, 9, 30},
  { 0b01111100, 9, 40},
  { 0b00000100, 10, 20},
  { 0b01111100, 10, 35},
  { 0b00000100, 11, 15},
  { 0b01111100, 11, 30},
  { 0b00000100, 12, 10},
  { 0b00000100, 12, 20},
  { 0b00000100, 13, 00},
  { 0b00000100, 13, 5},
  { 0b01111100, 13, 40},
  { 0b00000100, 14, 20},
  { 0b01111100, 14, 30},
  { 0b00000100, 15, 10},
  { 0b00000100, 15, 20},
  { 0b00000100, 16, 0},
  { 0b01111100, 16, 10},
  { 0b00000100, 16, 55},
  { 0b00000100, 17, 5},
  { 0b00000100, 17, 45},
    
  { 0b01111000, 8, 40},
  { 0b01111000, 8, 50},
  { 0b01111000, 9, 50},
  { 0b01111000, 10, 45},
  { 0b01111000, 11, 45},
  { 0b01111000, 12, 30},
  { 0b01111000, 12, 35},
  { 0b01111000, 13, 20},
  { 0b01111000, 14, 50}, //25
  { 0b01111000, 15, 15},
  { 0b01111000, 15, 25},
  { 0b01111000, 16, 15},
  { 0b01111000, 17, 0},
  { 0b01111000, 17, 10},
  { 0b01111000, 17, 55},
  {0,  0,  0}      // признак конца массива 
};

// **** Установка звонков на текущий день *****
void todayAlarms() {
  int day_of_week_now = weekday();  // день недели 
  int hour_now = hour();    // текущее время - часы
  int minute_now = minute();    // минуты
  byte i = 0;
  while (alarm_day(i) != 0)     // просматриваем расписание звонков     
    { if ((alarm_day(i) & (1<< day_of_week_now)) != 0) 
        {   // если строка расписания действует сегодня
        if ( (alarm_hour(i) > hour_now) || ((alarm_hour(i) == hour_now) && (alarm_min(i) > minute_now)))  
           { // если текущее время меньше времени звонка - установить Аларм
        
        
        Alarm.alarmOnce(day_of_week_now,alarm_hour(i),alarm_min(i),0,rele);





/*
 * проверка кода с выводом в консоль
 *
Serial.print("Set alarm: ");
Serial.print(day_of_week_now);
Serial.print(" ");
Serial.print(alarm_hour(i));
Serial.print(":");
Serial.println(alarm_min(i));
Alarm.alarmOnce(day_of_week_now,alarm_hour(i),alarm_min(i),0,rele);

*/




            
            }
       }
     i++;  
  }
}    


// Объявляем переменные и константы:
const uint8_t PIN_button_SET  = 8;           // указываем номер вывода arduino, к которому подключена кнопка SET
const uint8_t PIN_button_UP   = 9;           // указываем номер вывода arduino, к которому подключена кнопка UP
const uint8_t PIN_button_DOWN = 10;           // указываем номер вывода arduino, к которому подключена кнопка DOWN
      uint8_t VAR_mode_SHOW   = 1;           // режим вывода: 1-время 2-дата
      uint8_t VAR_mode_SET    = 0;           // режим установки времени: 0-нет 1-сек 2-мин 3-час 4-день 5-мес 6-год 7-день_недели
void setup() {

  pinMode(PIN_button_SET,  INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
  pinMode(PIN_button_UP,   INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
  pinMode(PIN_button_DOWN, INPUT);           // устанавливаем режим работы вывода кнопки, как "вход"
  delay(300);                                // ждем 300мс
  time.begin();                              // инициируем RTC модуль
  lcd.begin();                                // инициируем LCD дисплей
  lcd.backlight();                           // включаем подсветку LCD дисплея




  Serial.begin(9600);
  Serial.println("Загружаем настройки..."); 
   setSyncProvider(RTC.get); 
  if (timeStatus() != timeSet) 
    Serial.println("Не удалось получить время!");
  else
    Serial.println("Время успешно получено!");

// digitalClockDisplay();


    
    todayAlarms();        // при старте программы уставнавливаем звонки на ближ. день
    Alarm.alarmRepeat(6,11,22,todayAlarms);     // каждый день утром в 6:11:22 устанавливаем звонки на сегодня




  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
   pinMode(12, OUTPUT);
 // pinMode(buzzer, OUTPUT);
  Serial.print("LED на 13 pin выключен в ");
//  digitalClockDisplay();
  Serial.println("Завершение настройки....");


}
void loop(){
  if(millis()%1000==0){                      // если прошла 1 секунда
      lcd.setCursor(0, 0);                   // устанавливаем курсор в позицию: столбец 0, строка 0
      lcd.print(time.gettime("H:i   d.m.y"));              // выводим время + дату
      lcd.setCursor(0, 1);                   // устанавливаем курсор в позицию: столбец 0, строка 1
    if(VAR_mode_SHOW==1){                    // если установлен режим вывода времени
      lcd.print("ostalos:  ** min");      // выводим остаток минут до реле ...пока не выводим...
    }
    if(VAR_mode_SHOW==2){                    // если установлен режим вывода даты
      lcd.print("");  // выводим дату
    }
    delay(1);                                // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс
  }
  Func_buttons_control();                    // передаём управление кнопкам
}
// Функция управления кнопками:
void Func_buttons_control(){
  uint8_t i=0;
  time.blinktime(VAR_mode_SET);                                  // мигаем устанавливаемым параметром (если VAR_mode_SET больше 0)
//Если часы находятся в режиме установки даты/времени
  if(VAR_mode_SET){
//  Если нажата кнопка UP
    if(digitalRead(PIN_button_UP  )){
      while(digitalRead(PIN_button_UP)){delay(50);}              // ждём пока мы не отпустим кнопку UP
      switch (VAR_mode_SET){                                     // инкремент (увеличение) устанавливаемого значения
      /* сек */ case 1: time.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
      /* мин */ case 2: time.settime(-1, (time.minutes==59?0:time.minutes+1), -1, -1, -1, -1, -1); break;
      /* час */ case 3: time.settime(-1, -1, (time.Hours==23?0:time.Hours+1),     -1, -1, -1, -1); break;
      /* дни */ case 4: time.settime(-1, -1, -1, (time.day==31?1:time.day+1),         -1, -1, -1); break;
      /* мес */ case 5: time.settime(-1, -1, -1, -1, (time.month==12?1:time.month+1),     -1, -1); break;
      /* год */ case 6: time.settime(-1, -1, -1, -1, -1, (time.year==99?0:time.year+1),       -1); break;
      /* д.н.*/ case 7: time.settime(-1, -1, -1, -1, -1, -1, (time.weekday==6?0:time.weekday+1) ); break;
      }
    }
//  Если нажата кнопка DOWN
    if(digitalRead(PIN_button_DOWN)){
      while(digitalRead(PIN_button_DOWN)){delay(50);}            // ждём пока мы её не отпустим
      switch (VAR_mode_SET){                                     // декремент (уменьшение) устанавливаемого значения
      /* сек */ case 1: time.settime(0,                                   -1, -1, -1, -1, -1, -1); break;
      /* мин */ case 2: time.settime(-1, (time.minutes==0?59:time.minutes-1), -1, -1, -1, -1, -1); break;
      /* час */ case 3: time.settime(-1, -1, (time.Hours==0?23:time.Hours-1),     -1, -1, -1, -1); break;
      /* дни */ case 4: time.settime(-1, -1, -1, (time.day==1?31:time.day-1),         -1, -1, -1); break;
      /* мес */ case 5: time.settime(-1, -1, -1, -1, (time.month==1?12:time.month-1),     -1, -1); break;
      /* год */ case 6: time.settime(-1, -1, -1, -1, -1, (time.year==0?99:time.year-1),       -1); break;
      /* д.н.*/ case 7: time.settime(-1, -1, -1, -1, -1, -1, (time.weekday==0?6:time.weekday-1) ); break;
      }
    }
//  Если нажата кнопка SET
    if(digitalRead(PIN_button_SET)){
      while(digitalRead(PIN_button_SET)){                        // ждём пока мы её не отпустим
        delay(10);
        if(i<200){i++;}else{lcd.clear();}                        // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран
      }
      if(i<200){                                                 // если кнопка SET удерживалась меньше 2 секунд
        VAR_mode_SET++;                                          // переходим к следующему устанавливаемому параметру
        if(VAR_mode_SHOW==1 && VAR_mode_SET>3){VAR_mode_SET=1;}  // возвращаемся к первому устанавливаемому параметру
        if(VAR_mode_SHOW==2 && VAR_mode_SET>7){VAR_mode_SET=4;}  // возвращаемся к первому устанавливаемому параметру
      }else{                                                     // если кнопка SET удерживалась дольше 2 секунд, то требуется выйти из режима установки даты/времени
        VAR_mode_SET=0;                                          // выходим из режима установки даты/времени
      }
    }
//Если часы находятся в режиме вывода даты/времени
  }else{
//  Если нажата кнопка SET
    if(digitalRead(PIN_button_SET)){
      while(digitalRead(PIN_button_SET)){delay(10);              // ждём пока мы её не отпустим
        if(i<200){i++;}else{lcd.clear();}                        // фиксируем, как долго удерживается кнопка SET, если дольше 2 секунд, то стираем экран
      }
      if(i<200){                                                 // если кнопка SET удерживалась меньше 2 секунд
        lcd.clear();                                             // стираем экран
        VAR_mode_SHOW=VAR_mode_SHOW==1?2:1;                      // меняем режим вывода: дата/время
      }else{                                                     // если 
        if(VAR_mode_SHOW==1){VAR_mode_SET=1;}                    // если установлен режим вывода времени, то устанавливаемый параметр - секунды
        if(VAR_mode_SHOW==2){VAR_mode_SET=4;}                    // если установлен режим вывода даты,    то устанавливаемый параметр - день
      }
    }
  }
}



void rele(){
Serial.println("Zvonok Zvonok Zvonok Zvonok Zvonok"); 

// реле + пищик
  digitalWrite(12, HIGH);
  Alarm.delay(5000);
  digitalWrite(12, LOW);

 //tone(buzzer, 2000); // Send 1KHz sound signal...
 // delay(1000);        // ...for 1 sec
 // noTone(buzzer);     // Stop sound...

}

 

sadman41, полностью с вами согласен, как бы логики не видно.

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

ну вы прям чемпион по лаконичности :)

что именно не срабатывает, если есть ошибки - копируйте текст, если работает, но не так - описывайте симптомы...

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

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

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

sadman41, обещанного три года ждут, а вот если всеми силами то можно и за два управиться?!

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

kpik пишет:

sadman41, обещанного три года ждут, а вот если всеми силами то можно и за два управиться?!

kpik. вы б лучше написали. что именно и как не работает.

 

Сорри, не увидел, что вы исправили сообщение выше.

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

А пищик, как ты говоришь, буззер по-нашему, можно и активный поставить. 60р за десяток. Как пинанина играть, канешь, не будет, но события сопрвождать писком - вполне гадицца.

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

kpik. я нашел в вашем коде ошибку. Она, как ни странно. в том. что вы в loop() перешли с delay на миллис. Дело в том, что библиотека TimeAlarms для своей работы нуждается в наличии оператора Alarm.delay() в loop(). А вы эту функцию оттуда убрали и запихнули ее в rele. где ей совсем не место.

Вместо delay(1) на строке 177 вставьте Alarm.delay(200);, а в rele в строке 252 замените Alarm.delayна обычный. Возможно после этого и буззер заработает :)

 

Длительность Alarm.delay(200); в строке 177 примерная -  возможно ее придется подобрать между 50 и 300. чтобы и кнопки быстро отрабатывали, и часы показывалисб правильно, и звонки не пропускались.

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

и еще добавка - функция Func_buttons_control(), так, как она написана сейчас - непригодна для этой программы. Ее надо либо переписать, либо выкинуть совсем. Все эти циклы "ждем, пока кнопка нажата" - несовместимы с правильной работой часов и звонков.

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

b707 пишет:

kpik. я нашел в вашем коде ошибку. Она, как ни странно. в том. что вы в loop() перешли с delay на миллис. Дело в том, что библиотека TimeAlarms для своей работы нуждается в наличии оператора Alarm.delay() в loop(). А вы эту функцию оттуда убрали и запихнули ее в rele. где ей совсем не место.

Вместо delay(1) на строке 177 вставьте Alarm.delay(200);, а в rele в строке 252 замените Alarm.delayна обычный. Возможно после этого и буззер заработает :)

 

Длительность Alarm.delay(200); в строке 177 примерная -  возможно ее придется подобрать между 50 и 300. чтобы и кнопки быстро отрабатывали, и часы показывалисб правильно, и звонки не пропускались.

 

Да вы правы, после изменений все разаробало.

Буззер + лсд + реле

 

ошибок нет.

 

 

кнопки мне не нужны, как их правильно выпилить? Выпилил функцию + обращение к ней.

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

kpik пишет:

кнопки мне не нужны, как их правильно выпилить? Выпилил функцию + обращение к ней.

просто закомментировать вызов в loop.

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

b707 пишет:

просто закомментировать вызов в loop.

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

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

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

Ну этого уже я не обещал :)

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

b707, осталавливаться вообще, или просто не показываться на лсд? Второй вариант не кретичен :)

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

b707 пишет:

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

Если извращаться, то можно вместо digitalWrite() сделать tone() с duration, а на выходе сделать сигнал плоским и зеленым (конденсатором, вроде это реализуют).

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

kpik пишет:

подскажите пожалуйста как вывести количество минут до следующего аларма? в 172 строке.

В том варианте кода, который вы выбрали - то есть с алармами сразу на весь день - это не так просто. Нужно каждый раз выполнять поиск по таблице звонков и искать следующий звонок. Фактически, нужно перетащить сюда функцию FindNextAlarm() из второго варианта кода и слегка ее доработать. Во втором варианте- там проще, поскольку следующий звонок и так вычисляется.

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

b707, не вопрос, давайте использовать ваш варинт кода №2.

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

kpik пишет:

b707, осталавливаться вообще, или просто не показываться на лсд? Второй вариант не кретичен :)

замирать. Все 5 сек звонка на часах будет 12:40:00, а потом сразу 12:40:05

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

b707 пишет:

замирать. Все 5 сек звонка на часах будет 12:40:00, а потом сразу 12:40:05

 

Часы не выводят СЕКУНДЫ (только часы+минуты), так что это будет не заметно :)

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

kpik пишет:

b707, не вопрос, давайте использовать ваш варинт кода №2.

kpik. без обид, но у меня много работы. Прошу понять меня правильно - если будут проблемы с моим кодом, я готов его править и дальше, но вносить новые фенечки я не подписывался. Попробуйте сами.  Будут вопросы - всегда поможем.

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

b707 пишет:

 

kpik. без обид, но у меня много работы. Прошу понять меня правильно - если будут проблемы с моим кодом, я готов его править и дальше, но вносить новые фенечки я не подписывался. Попробуйте сами.  Будут вопросы - всегда поможем.

 

Хорошо спасибо!

kpik
kpik аватар
Offline
Зарегистрирован: 09.11.2017

Друзья, подскажите пожалуйста, как мне извлечь из данного кода Час и Минуты следующего аларма?

#include <Wire.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <avr/pgmspace.h>

#define alarm_day(x)  pgm_read_byte(&alarms[x][0]) 
#define alarm_hour(x) pgm_read_byte(&alarms[x][1])
#define alarm_min(x)  pgm_read_byte(&alarms[x][2])
#define alarm_AM(x)   (alarm_hour(x) * 60 + alarm_min(x))

const byte PROGMEM alarms[][3] =
{
  { 0b01111100, 7, 55},
  { 0b01111100, 8, 0},
  { 0b00000100, 8, 40},
  { 0b00000100, 8, 50},
  { 0b00000100, 9, 30},
  { 0b01111100, 9, 40},
  { 0b00000100, 10, 20},
  { 0b01111100, 10, 35},
  { 0b00000100, 11, 15},
  { 0b01111100, 11, 30},
  { 0b00000100, 12, 10},
  { 0b00000100, 12, 20},
  { 0b00000100, 13, 00},
  { 0b00000100, 13, 5},
  { 0b01111100, 13, 40},
  { 0b00000100, 14, 20},
  { 0b01111100, 14, 30},
  { 0b00000100, 15, 10},
  { 0b00000100, 15, 20},
  { 0b00000100, 16, 0},
  { 0b01111100, 16, 10},
  { 0b00000100, 16, 55},
  { 0b00000100, 17, 5},
  { 0b00000100, 17, 45},
    
  { 0b01111000, 8, 40},
  { 0b01111000, 8, 50},
  { 0b01111000, 9, 50},
  { 0b01111000, 10, 45},
  { 0b01111000, 11, 45},
  { 0b01111000, 12, 30},
  { 0b01111000, 12, 35},
  { 0b01111000, 13, 20},
  { 0b01111000, 14, 25},
  { 0b01111000, 15, 15},
  { 0b01111000, 15, 25},
  { 0b01111000, 16, 15},
  { 0b01111000, 17, 0},
  { 0b01111000, 17, 10},
  { 0b01111000, 17, 55},
  {0,  0,  0}
};


int findNextAlarm() {
  int day_of_week_now = weekday();
  int min_AM_now = hour() *  60 + minute();
  int next_alarm_time = 24*60;
  int al_ind = -1;
  byte i = 0;
  while (alarm_day(i) != 0)
    { if ((alarm_day(i) & (1<< day_of_week_now)) != 0) {
        if ( alarm_AM(i) > min_AM_now)  {
            if (alarm_AM(i) < next_alarm_time) 
             {next_alarm_time = alarm_AM(i);
              al_ind = i;}
            }
       }
     i++;  
  }
 return al_ind; 
}
void setNextAlarm() {

  int next_alarm = findNextAlarm();
  if (next_alarm != -1) 
    Alarm.alarmOnce(alarm_hour(next_alarm),alarm_min(next_alarm),0,rele);
}    

void rele(){

  Serial.println("text");    
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  pinMode(12, OUTPUT);
  Serial.print("Turning pin 13 LED off at ");
  setNextAlarm();
  Serial.println("Завершение настройки....");
}


void setup()
{
  Serial.begin(9600);
  Serial.println("Загружаем настройки..."); 
   setSyncProvider(RTC.get); 
  if (timeStatus() != timeSet) 
    Serial.println("Не удалось получить время!");
  else
    Serial.println("Время успешно получено!");
    setNextAlarm();
    Alarm.alarmRepeat(6,11,22,setNextAlarm);

}
void  loop(){  
  Alarm.delay(1000);
}

 

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

А вы в этих школах кем работаете - трудовиком? 

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

kpik,  функция findNextAlarm() возвращает индекс следующего аларма в таблице alarms,  или -1, если в текущий сутках больше алармов нет. Извлечь из таблицы часы и минуты, зная индекс -  можно макросами в строках 7-10.

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

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

sadman41 пишет:

А вы в этих школах кем работаете - трудовиком? 

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

Автар! Денег я не просил и не прошу, но грамоту от директора школы я точно заслужил :)))

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

b707 пишет:

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

Чаще вспоминайте классиков, обзаведитесь тряпками и затыкайте ими все щели, чтобы в них неожиданно и коварно не проникало милосердие

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

b707 пишет:

да уж.... сначала это выглядело, ...

Знаете, когда нашего коллегу Mr.Privetтак же как Вас сейчас обуял зуд благотворительности, а потом он (опять же, подобно Вам) понял чем это заканчивается, я посоветовал ему прочитать короткую притчу великого Марка Твена. Очень косветую и Вам: прочитайте вот здесь главу "БЛАГОДАРНЫЙ ПУДЕЛЬ" с продолжением  - не пожалеете, она очень короткая и много времени не отнимет:)

Там в конце есть хороший совет, данный умирающим врачом:

"Когда несчастный просит у вас помощи и вы сомневаетесь, к какому результату приведет ваша благотворительность, дайте волю вашим сомнениям и убейте просителя" :--)))))