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()
Как стало понятно при тестировании кода, размер данных в ОЗУ в первую очередь зависит от числа созданных экземпляров таймера Alarm.alarmRepeat - "алармов", все остальное на расход ОЗУ влияет мало.
Скетч из сообщения #8 после исправления ошибок занимал 7840 байт флеша и 1524 байт ОЗУ. Правда, эти цифры мало что значат, так как реально скетч не работал - для составления расписания на неделю требуется установить примерно 120 "алармов", в то время как уже при 80 расход ОЗУ превышал 80%.
Первый скетч из предыдущего сообщения имеет размер 7638 байт и требует 982 байта ОЗУ. Для упрощения алгоритма в нем задаются сразу все звонки на текущий день, что означает установку порядка 25 -30 "алармов", поэтому использование оперативки в нем довольно высокое. Его кардинальное отличие от предыдущего - в нем помещается все расписание и даже есть запас на расширение.
Второй исправленный скетч задает "аларм" только на один следующий звонок. Когда аларм срабатывает - устанавливается следующий. Размер этого кода такой же, как предыдущий, но за счет снижения числа таймеров размер занятого ОЗУ снизился до 718 байт. Главное преимущество этого кода - он допускает почти неограниченное расщирение расписания - до нескольких тысяч событий.
Оба кода, подскажите пожалуйста в каком месте я туплю?
ну почему обязательно тупите, программа же не тестировалась совсем, скорее всего там есть ошибки.
Что касается функции rele(), то в первом коде она целиком взята из вашего кода сообщения 8, я не менял в ней ни байта. Обратите внимание, что в ней на 12 пин ничего не выводится, пин только обьявляется как OUTPUT. Вероятно, вы сами отключили управление реле для тестирования.
Для того, чтобы понять, в чем дело - я попрошу вставить вот эти строки в первый код вместо строки 78 и выложить вывод программы
осталось попробовать на реальных звонках. Это только вы на своей стороне можете сделать, у меня звонков нет :)
Звонки подаются пока отлично, вы бы не могли подсказать как правильно вывести на экран дата / время и желательно через сколько реле сработает?
почему-то мой дисплей 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
Если это проблематично то не стоит, вы и так очень помогли!
почему-то мой дисплей 16,2 через i2c конфликтует с реле.
я так понимаю конфликт библиотек, при использовании двух кодов реле не срабатывает, без кода дисплея все отлично срабатывает (использовал на вашем варианте №1)
не вполне понимаю, о каких библиотеках вы говорите - обьясните подробнее. Насколько мне кажется, реле вообще не использует библиотек - там же просто один цифровой пин, который вы переключаете HIGH-LOW
не вполне понимаю, о каких библиотеках вы говорите - обьясните подробнее. Насколько мне кажется, реле вообще не использует библиотек - там же просто один цифровой пин, который вы переключаете 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...
}
kpik, у вас не реле конфликтует, а команда "tone". Уберите ее - и экран будет работать. Это известная вещь, tone с очень многими библиотеками не работает.
kpik, у вас не реле конфликтует, а команда "tone". Уберите ее - и экран будет работать. Это известная вещь, tone с очень многими библиотеками не работает.
Подскажите пожалуйста на что ее можно заменить чтоб осталась возможность использовать пищик? Там также без коментирования digitalClockDisplay() не удается запуститься.
Подскажите пожалуйста на что ее можно заменить чтоб осталась возможность использовать пищик? Там также без коментирования digitalClockDisplay() не удается запуститься.
попробуйте поставить между пищиком и ардуино резистор на 150-300 Ом, некоторым помогает.
Насчет проблем с digitalClockDisplay() - насколько я вижу, вы из своего последнего кода эту процедуру совсем убрали(может ошиблись?) - поэтому и вызов ее, конечно же, надо закомментировать.
kpik. я что-то запутался. Давайте решать проблемы последовательно. Если из второго кода сообщения 68 удалить операторы tone - реле срабатывает? LCD экран работает нормально?
Не совсем понимаю, чего это LCD и tone() конфликтует, но есть "пищики" активные и пассивные. Пассивным нужен tone(), а у активных мультивибратор интегрирован - им достаточно только за управляющийх хвост дернуть.
А пищик, как ты говоришь, буззер по-нашему, можно и активный поставить. 60р за десяток. Как пинанина играть, канешь, не будет, но события сопрвождать писком - вполне гадицца.
kpik. я нашел в вашем коде ошибку. Она, как ни странно. в том. что вы в loop() перешли с delay на миллис. Дело в том, что библиотека TimeAlarms для своей работы нуждается в наличии оператора Alarm.delay() в loop(). А вы эту функцию оттуда убрали и запихнули ее в rele. где ей совсем не место.
Вместо delay(1) на строке 177 вставьте Alarm.delay(200);, а в rele в строке 252 замените Alarm.delayна обычный. Возможно после этого и буззер заработает :)
Длительность Alarm.delay(200); в строке 177 примерная - возможно ее придется подобрать между 50 и 300. чтобы и кнопки быстро отрабатывали, и часы показывалисб правильно, и звонки не пропускались.
и еще добавка - функция Func_buttons_control(), так, как она написана сейчас - непригодна для этой программы. Ее надо либо переписать, либо выкинуть совсем. Все эти циклы "ждем, пока кнопка нажата" - несовместимы с правильной работой часов и звонков.
kpik. я нашел в вашем коде ошибку. Она, как ни странно. в том. что вы в loop() перешли с delay на миллис. Дело в том, что библиотека TimeAlarms для своей работы нуждается в наличии оператора Alarm.delay() в loop(). А вы эту функцию оттуда убрали и запихнули ее в rele. где ей совсем не место.
Вместо delay(1) на строке 177 вставьте Alarm.delay(200);, а в rele в строке 252 замените Alarm.delayна обычный. Возможно после этого и буззер заработает :)
Длительность Alarm.delay(200); в строке 177 примерная - возможно ее придется подобрать между 50 и 300. чтобы и кнопки быстро отрабатывали, и часы показывалисб правильно, и звонки не пропускались.
Да вы правы, после изменений все разаробало.
Буззер + лсд + реле
ошибок нет.
кнопки мне не нужны, как их правильно выпилить? Выпилил функцию + обращение к ней.
да, кстати - у вас на время звонка часы на дисплее будут останавливаться. Чтобы это поправить, нужно переписать функцию rele.
Если извращаться, то можно вместо digitalWrite() сделать tone() с duration, а на выходе сделать сигнал плоским и зеленым (конденсатором, вроде это реализуют).
подскажите пожалуйста как вывести количество минут до следующего аларма? в 172 строке.
В том варианте кода, который вы выбрали - то есть с алармами сразу на весь день - это не так просто. Нужно каждый раз выполнять поиск по таблице звонков и искать следующий звонок. Фактически, нужно перетащить сюда функцию FindNextAlarm() из второго варианта кода и слегка ее доработать. Во втором варианте- там проще, поскольку следующий звонок и так вычисляется.
b707, не вопрос, давайте использовать ваш варинт кода №2.
kpik. без обид, но у меня много работы. Прошу понять меня правильно - если будут проблемы с моим кодом, я готов его править и дальше, но вносить новые фенечки я не подписывался. Попробуйте сами. Будут вопросы - всегда поможем.
kpik. без обид, но у меня много работы. Прошу понять меня правильно - если будут проблемы с моим кодом, я готов его править и дальше, но вносить новые фенечки я не подписывался. Попробуйте сами. Будут вопросы - всегда поможем.
kpik, функция findNextAlarm() возвращает индекс следующего аларма в таблице alarms, или -1, если в текущий сутках больше алармов нет. Извлечь из таблицы часы и минуты, зная индекс - можно макросами в строках 7-10.
Но вообще-то я предлагал вам попробовать сделать это самостоятельно и обращаться в случае проблем... это значит сначала написать код, а потом задавать вопросы.
да уж.... сначала это выглядело, что человек просит помочь разобраться в неработающем коде. Но чем дальше, тем яснее, что своего кода тут нет ни строчки - все натащено из тнета.
Автар! Денег я не просил и не прошу, но грамоту от директора школы я точно заслужил :)))
да уж.... сначала это выглядело, что человек просит помочь разобраться в неработающем коде. Но чем дальше, тем яснее, что своего кода тут нет ни строчки - все натащено из тнета.
Чаще вспоминайте классиков, обзаведитесь тряпками и затыкайте ими все щели, чтобы в них неожиданно и коварно не проникало милосердие
Знаете, когда нашего коллегу Mr.Privet, так же как Вас сейчас обуял зуд благотворительности, а потом он (опять же, подобно Вам) понял чем это заканчивается, я посоветовал ему прочитать короткую притчу великого Марка Твена. Очень косветую и Вам: прочитайте вот здесь главу "БЛАГОДАРНЫЙ ПУДЕЛЬ" с продолжением - не пожалеете, она очень короткая и много времени не отнимет:)
Там в конце есть хороший совет, данный умирающим врачом:
"Когда несчастный просит у вас помощи и вы сомневаетесь, к какому результату приведет ваша благотворительность, дайте волю вашим сомнениям и убейте просителя" :--)))))
kpik, выкладываю ваш скетч в моем варианте. Точнее сразу в двух.
Первый - каждое утро в 6 утра задает звонки на текущий день. Параметр число алармов #define dtNBR_ALARMS в библиотеке TimeAlarm.h должен быть установлен как <максимальное число звонков в день +1>
Второй - задает только ближайший звонок, таким образом число алармов в библиотеке можно оставить по умолчанию - 6 шт, что экономит память. Следующий звонок устанавливается автоматически, в процедуре rele()
Оба кода компилируются без ошибок, но проверить в реальной работе не могу.
По расходу памяти.
Как стало понятно при тестировании кода, размер данных в ОЗУ в первую очередь зависит от числа созданных экземпляров таймера Alarm.alarmRepeat - "алармов", все остальное на расход ОЗУ влияет мало.
Скетч из сообщения #8 после исправления ошибок занимал 7840 байт флеша и 1524 байт ОЗУ. Правда, эти цифры мало что значат, так как реально скетч не работал - для составления расписания на неделю требуется установить примерно 120 "алармов", в то время как уже при 80 расход ОЗУ превышал 80%.
Первый скетч из предыдущего сообщения имеет размер 7638 байт и требует 982 байта ОЗУ. Для упрощения алгоритма в нем задаются сразу все звонки на текущий день, что означает установку порядка 25 -30 "алармов", поэтому использование оперативки в нем довольно высокое. Его кардинальное отличие от предыдущего - в нем помещается все расписание и даже есть запас на расширение.
Второй исправленный скетч задает "аларм" только на один следующий звонок. Когда аларм срабатывает - устанавливается следующий. Размер этого кода такой же, как предыдущий, но за счет снижения числа таймеров размер занятого ОЗУ снизился до 718 байт. Главное преимущество этого кода - он допускает почти неограниченное расщирение расписания - до нескольких тысяч событий.
в епром или прогмем можно запхать все возможные времена звонков.
На текущий день задавать только индексы оттуда
в епром или прогмем можно запхать все возможные времена звонков.
На текущий день задавать только индексы оттуда
так вроде так и сделано. Или я не понял, что ты имешь в виду.
Да. Я с пахмелья неразлядел. Сорри.
Спасибо, затестим, отпишусь обязательно!
kpik, выкладываю ваш скетч в моем варианте. Точнее сразу в двух.
Оба кода компилируются без ошибок, но проверить в реальной работе не могу.
Ошибок нет, но, на 12 пине не дергает реле, я так понимаю не выполняется void rele(), так как даже в консоли нет ни одной из 3-ех надписей.
Ошибок нет, но, на 12 пине не дергает реле, я так понимаю не выполняется void rele(), так как даже в консоли нет ни одной из 3-ех надписей.
который из двух кодов вы пробовали?
Что касается 12 пина - в вашем коде в функции rele он и не должен дергаться - вы на него ничего не выводите.
который из двух кодов вы пробовали?
Что касается 12 пина - в вашем коде в функции rele он и не должен дергаться - вы на него ничего не выводите.
Оба кода, подскажите пожалуйста в каком месте я туплю?
Оба кода, подскажите пожалуйста в каком месте я туплю?
ну почему обязательно тупите, программа же не тестировалась совсем, скорее всего там есть ошибки.
Что касается функции rele(), то в первом коде она целиком взята из вашего кода сообщения 8, я не менял в ней ни байта. Обратите внимание, что в ней на 12 пин ничего не выводится, пин только обьявляется как OUTPUT. Вероятно, вы сами отключили управление реле для тестирования.
Для того, чтобы понять, в чем дело - я попрошу вставить вот эти строки в первый код вместо строки 78 и выложить вывод программы
забавно .... но так быть не должно.
Ладно, видимо все-таки придется сначала отладить код :)
Вечером оттестирую и выложу исправленный вариант.
kpik - нашел ошибку
Замените в обоих скетчах первые три дефайна на код
В коде 1 это строки с 9 по 11, во втором - с 7 по 9-ую.
Скомпилировал и проверил на Нано - алармы ставятся правильно.
kpik - нашел ошибку
Замените в обоих скетчах первые три дефайна на код
В коде 1 это строки с 9 по 11, во втором - с 7 по 9-ую.
Скомпилировал и проверил на Нано - алармы ставятся правильно.
Да, вы как всегда правы! Теперь указываются алармы правильно!
Теперь указываются алармы правильно!
осталось попробовать на реальных звонках. Это только вы на своей стороне можете сделать, у меня звонков нет :)
осталось попробовать на реальных звонках. Это только вы на своей стороне можете сделать, у меня звонков нет :)
Звонки подаются пока отлично, вы бы не могли подсказать как правильно вывести на экран дата / время и желательно через сколько реле сработает?
почему-то мой дисплей 16,2 через i2c конфликтует с реле.
пробовал вот с этим кодом, но наличие кнопок не столь важно
я так понимаю конфликт библиотек, при использовании двух кодов реле не срабатывает, без кода дисплея все отлично срабатывает (использовал на вашем варианте №1)
ЧЧ:ММ ДД.ММ.ГГГГ
rele: ММ minut
Если это проблематично то не стоит, вы и так очень помогли!
почему-то мой дисплей 16,2 через i2c конфликтует с реле.
я так понимаю конфликт библиотек, при использовании двух кодов реле не срабатывает, без кода дисплея все отлично срабатывает (использовал на вашем варианте №1)
не вполне понимаю, о каких библиотеках вы говорите - обьясните подробнее. Насколько мне кажется, реле вообще не использует библиотек - там же просто один цифровой пин, который вы переключаете HIGH-LOW
не вполне понимаю, о каких библиотеках вы говорите - обьясните подробнее. Насколько мне кажется, реле вообще не использует библиотек - там же просто один цифровой пин, который вы переключаете HIGH-LOW
вот рабочий код пищик+реле+в консоль выводит, а вот ниже код тот же самый но с выводом часов на первой строке (так по идее планировалось)
kpik, у вас не реле конфликтует, а команда "tone". Уберите ее - и экран будет работать. Это известная вещь, tone с очень многими библиотеками не работает.
kpik, у вас не реле конфликтует, а команда "tone". Уберите ее - и экран будет работать. Это известная вещь, tone с очень многими библиотеками не работает.
Подскажите пожалуйста на что ее можно заменить чтоб осталась возможность использовать пищик? Там также без коментирования digitalClockDisplay() не удается запуститься.
Подскажите пожалуйста на что ее можно заменить чтоб осталась возможность использовать пищик? Там также без коментирования digitalClockDisplay() не удается запуститься.
попробуйте поставить между пищиком и ардуино резистор на 150-300 Ом, некоторым помогает.
Насчет проблем с digitalClockDisplay() - насколько я вижу, вы из своего последнего кода эту процедуру совсем убрали(может ошиблись?) - поэтому и вызов ее, конечно же, надо закомментировать.
Я как раз указал тот код который запустился с укаанием даты и времени на дисплее, но не срабатывала реле во время аларма.
Сопротивление на питание или на пин?
kpik. я что-то запутался. Давайте решать проблемы последовательно. Если из второго кода сообщения 68 удалить операторы tone - реле срабатывает? LCD экран работает нормально?
Не совсем понимаю, чего это LCD и tone() конфликтует, но есть "пищики" активные и пассивные. Пассивным нужен tone(), а у активных мультивибратор интегрирован - им достаточно только за управляющийх хвост дернуть.
не срабатывает реле, время на часах идет, ошибок нет:
sadman41, полностью с вами согласен, как бы логики не видно.
ну вы прям чемпион по лаконичности :)
что именно не срабатывает, если есть ошибки - копируйте текст, если работает, но не так - описывайте симптомы...
Не-не, меня не впутывайте, у меня своего кода тонны... b707 ввязался забесплатно - пусть расхлебывает ))
sadman41, обещанного три года ждут, а вот если всеми силами то можно и за два управиться?!
sadman41, обещанного три года ждут, а вот если всеми силами то можно и за два управиться?!
kpik. вы б лучше написали. что именно и как не работает.
Сорри, не увидел, что вы исправили сообщение выше.
А пищик, как ты говоришь, буззер по-нашему, можно и активный поставить. 60р за десяток. Как пинанина играть, канешь, не будет, но события сопрвождать писком - вполне гадицца.
kpik. я нашел в вашем коде ошибку. Она, как ни странно. в том. что вы в loop() перешли с delay на миллис. Дело в том, что библиотека TimeAlarms для своей работы нуждается в наличии оператора Alarm.delay() в loop(). А вы эту функцию оттуда убрали и запихнули ее в rele. где ей совсем не место.
Вместо delay(1) на строке 177 вставьте Alarm.delay(200);, а в rele в строке 252 замените Alarm.delayна обычный. Возможно после этого и буззер заработает :)
Длительность Alarm.delay(200); в строке 177 примерная - возможно ее придется подобрать между 50 и 300. чтобы и кнопки быстро отрабатывали, и часы показывалисб правильно, и звонки не пропускались.
и еще добавка - функция Func_buttons_control(), так, как она написана сейчас - непригодна для этой программы. Ее надо либо переписать, либо выкинуть совсем. Все эти циклы "ждем, пока кнопка нажата" - несовместимы с правильной работой часов и звонков.
kpik. я нашел в вашем коде ошибку. Она, как ни странно. в том. что вы в loop() перешли с delay на миллис. Дело в том, что библиотека TimeAlarms для своей работы нуждается в наличии оператора Alarm.delay() в loop(). А вы эту функцию оттуда убрали и запихнули ее в rele. где ей совсем не место.
Вместо delay(1) на строке 177 вставьте Alarm.delay(200);, а в rele в строке 252 замените Alarm.delayна обычный. Возможно после этого и буззер заработает :)
Длительность Alarm.delay(200); в строке 177 примерная - возможно ее придется подобрать между 50 и 300. чтобы и кнопки быстро отрабатывали, и часы показывалисб правильно, и звонки не пропускались.
Да вы правы, после изменений все разаробало.
Буззер + лсд + реле
ошибок нет.
кнопки мне не нужны, как их правильно выпилить? Выпилил функцию + обращение к ней.
кнопки мне не нужны, как их правильно выпилить? Выпилил функцию + обращение к ней.
просто закомментировать вызов в loop.
просто закомментировать вызов в loop.
Спасибо сработало без ошибок, еще огромная просьба, подскажите пожалуйста как вывести количество минут до следующего аларма? в 172 строке.
да, кстати - у вас на время звонка часы на дисплее будут останавливаться. Чтобы это поправить, нужно переписать функцию rele.
Ну этого уже я не обещал :)
b707, осталавливаться вообще, или просто не показываться на лсд? Второй вариант не кретичен :)
да, кстати - у вас на время звонка часы на дисплее будут останавливаться. Чтобы это поправить, нужно переписать функцию rele.
Если извращаться, то можно вместо digitalWrite() сделать tone() с duration, а на выходе сделать сигнал плоским и зеленым (конденсатором, вроде это реализуют).
подскажите пожалуйста как вывести количество минут до следующего аларма? в 172 строке.
В том варианте кода, который вы выбрали - то есть с алармами сразу на весь день - это не так просто. Нужно каждый раз выполнять поиск по таблице звонков и искать следующий звонок. Фактически, нужно перетащить сюда функцию FindNextAlarm() из второго варианта кода и слегка ее доработать. Во втором варианте- там проще, поскольку следующий звонок и так вычисляется.
b707, не вопрос, давайте использовать ваш варинт кода №2.
b707, осталавливаться вообще, или просто не показываться на лсд? Второй вариант не кретичен :)
замирать. Все 5 сек звонка на часах будет 12:40:00, а потом сразу 12:40:05
замирать. Все 5 сек звонка на часах будет 12:40:00, а потом сразу 12:40:05
Часы не выводят СЕКУНДЫ (только часы+минуты), так что это будет не заметно :)
b707, не вопрос, давайте использовать ваш варинт кода №2.
kpik. без обид, но у меня много работы. Прошу понять меня правильно - если будут проблемы с моим кодом, я готов его править и дальше, но вносить новые фенечки я не подписывался. Попробуйте сами. Будут вопросы - всегда поможем.
kpik. без обид, но у меня много работы. Прошу понять меня правильно - если будут проблемы с моим кодом, я готов его править и дальше, но вносить новые фенечки я не подписывался. Попробуйте сами. Будут вопросы - всегда поможем.
Хорошо спасибо!
Друзья, подскажите пожалуйста, как мне извлечь из данного кода Час и Минуты следующего аларма?
А вы в этих школах кем работаете - трудовиком?
kpik, функция findNextAlarm() возвращает индекс следующего аларма в таблице alarms, или -1, если в текущий сутках больше алармов нет. Извлечь из таблицы часы и минуты, зная индекс - можно макросами в строках 7-10.
Но вообще-то я предлагал вам попробовать сделать это самостоятельно и обращаться в случае проблем... это значит сначала написать код, а потом задавать вопросы.
А вы в этих школах кем работаете - трудовиком?
да уж.... сначала это выглядело, что человек просит помочь разобраться в неработающем коде. Но чем дальше, тем яснее, что своего кода тут нет ни строчки - все натащено из тнета.
Автар! Денег я не просил и не прошу, но грамоту от директора школы я точно заслужил :)))
да уж.... сначала это выглядело, что человек просит помочь разобраться в неработающем коде. Но чем дальше, тем яснее, что своего кода тут нет ни строчки - все натащено из тнета.
Чаще вспоминайте классиков, обзаведитесь тряпками и затыкайте ими все щели, чтобы в них неожиданно и коварно не проникало милосердие
да уж.... сначала это выглядело, ...
Знаете, когда нашего коллегу Mr.Privet, так же как Вас сейчас обуял зуд благотворительности, а потом он (опять же, подобно Вам) понял чем это заканчивается, я посоветовал ему прочитать короткую притчу великого Марка Твена. Очень косветую и Вам: прочитайте вот здесь главу "БЛАГОДАРНЫЙ ПУДЕЛЬ" с продолжением - не пожалеете, она очень короткая и много времени не отнимет:)
Там в конце есть хороший совет, данный умирающим врачом:
"Когда несчастный просит у вас помощи и вы сомневаетесь, к какому результату приведет ваша благотворительность, дайте волю вашим сомнениям и убейте просителя" :--)))))