Alarm.alarmRepeat и память

b707
Онлайн
Зарегистрирован: 26.05.2017

Евгений, фиг с ним, я не жалею. Мне было интересно.

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

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

 

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

 

Что поповоду что я прошу как сделать то как сделать это, ну простите, хотел по лучше а действительно весь код написал b707, это его творения я не спорю! Он очень хороший человек!

 

Также хочется чтоб тут остался код чтоб и другие смогли собрать с маленьким умом и большим сердцем :)

sadman41
Онлайн
Зарегистрирован: 19.10.2016

kpik пишет:
Ну блин 21 век, а директора жмуться на небольшую автоматику, ну не пойму я этого хоть убейте.

Вариант #1 - директору нужно провести "автоматику" по бухгалтерии и согласовать расходы в каком-нибудь управлении. А там могут указать, что раз есть автоматика, то штатную ставку "дежурный" можно и сократить. Но на этой ставочке может сидеть какая-нибудь внучка... или жучка... А кнопки за нее жмут бабушки.

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

Вариант #3 - директору пофиг. Она обеспечила учебный процесс? Обеспечила. У нее всё подстрижено, покрашено, выборы проходят без сучка-задоринки. А прогресс - это где-нибудь в другом месте пусть будет. Бабушки? Ну, бабушек много - они не закончатся.

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

В планах эту шайтан автоматику поместить в коробку из АБС-пластика, ну и рабом в местре есть огнетушитель. Что по поводу сертификации, я столько вижу что закупается (где и по чем) ну это не серьездно :)

К сожалению, я наблюдаю описанный вами вариант №3

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

b707
Онлайн
Зарегистрирован: 26.05.2017

kpik пишет:

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

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

Выложите последнюю версию кода, который у вас (у нас :) получился.

 

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

b707 пишет:

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

 

Спасибо разобрался элементарным вычитанием текщего времени от аларма.

b707
Онлайн
Зарегистрирован: 26.05.2017

kpik пишет:

Спасибо разобрался элементарным вычитанием текщего времени от аларма.

Вычитать проще всего, переведя текущее время и время аларма в минуты от полуночи. Во втором коде можно взять  для этого макрос alarm_AM()

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

b707, подскажите пожалуйста, вот в у меня как бы показывает правильное время до аларма, но после замирает экран с 1 минутой оставшейся до аларма (реле срабатывает и дальше просто зависает как экран так и вывод алармов на реле)

int zH,zM,chasNow,minNow,next_alarm;
void  loop(){
if(millis()%1000==0){                          // если прошла 1 секунда
      lcd.setCursor(0, 0);                       // устанавливаем курсор в позицию: столбец 0, строка 0
      lcd.print(time.gettime("H:i   d.m.y"));   // выводим время + дату
      lcd.setCursor(3, 1);                       // устанавливаем курсор в позицию: столбец 0, строка 1
      lcd.print(L"Еще: ");   
    
next_alarm = findNextAlarm();
zH= alarm_hour(next_alarm);
zM= alarm_min(next_alarm);
chasNow=hour();
minNow=minute(); 
lcd.print(ost(chasNow,minNow,zH,zM));      // выводим остаток минут
lcd.print(L" мин.");
Alarm.delay(200);          // приостанавливаем на 0.2 с, чтоб не выводить время несколько раз за 1мс
}
}

int ost (int tecH, int tecM, int zapH, int zapM)
{
  int tec,zap,ostatok;
  tec=tecH*60+tecM;
  zap=zapH*60+zapM;
  ostatok=zap-tec;
  return ostatok;
}

по сути это как: включил если урок то показывает сколько осталось когда закончился урок сработало реле и зависло, после берем ресетим и получаем вывод аларма на переменке...переменка закончилась сработало реле, и выводит новое время до аларма (до конца урока) и возвращаемся к началу что после окончания урока сработало реле и завис...

 

в двух словах: с урока на перемену НЕ переходит, но с перемены ПЕРЕХОДИТ на урок как реле так и "остаток минут" на экране, но бывет и проскакивает но редко.

b707
Онлайн
Зарегистрирован: 26.05.2017

kpik чего-то в корне неправильного я в коде не вижу. Но я бы такой использовать не стал.  Два момента мне в нем не нравятся - точное сравнение миллис с 1000 (строка 3) - может срабатывать через раз. И то, что Alarm.delay и у вас вызывается только при совпадении с условием строки 3.

насчет ПЕРЕМЕНЫ и УРОКА фразы не понял - разве они в коде как-то отличаются?

 

b707
Онлайн
Зарегистрирован: 26.05.2017

кстати, если у вас на часах только минуты - зачем вы обновляете экран раз в секунду? - обновляйте только при смене минут

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

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

b707 пишет:

кстати, если у вас на часах только минуты - зачем вы обновляете экран раз в секунду? - обновляйте только при смене минут

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

Отличная идея с частотой обновления, спасибо.

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

 

весь код:

 

/*

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


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



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


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

*/
int ost(int,int,int,int);
// Подключаем библиотеки:
#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 <LCD_1602_RUS.h>
LCD_1602_RUS lcd(0x27, 16, 2);


#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 int buzzer = 3;
const byte PROGMEM alarms[][3] =
{
	// будни
  { 0b01111100, 7, 55},
  { 0b01111100, 8, 0},
	// пн
  { 0b00000100, 8, 40},
  { 0b00000100, 8, 50},
  { 0b00000100, 9, 30},
  { 0b00000100, 9, 40},
  { 0b00000100, 10, 20},
  { 0b00000100, 10, 35},
  { 0b00000100, 11, 15},
  { 0b00000100, 11, 30},
  { 0b00000100, 12, 10},
  { 0b00000100, 12, 20},
  { 0b00000100, 13, 0},
  { 0b00000100, 13, 5},
  { 0b00000100, 13, 35},
  { 0b00000100, 13, 40},
  { 0b00000100, 14, 20},
  { 0b00000100, 14, 30},
  { 0b00000100, 15, 10},
  { 0b00000100, 15, 20},
  { 0b00000100, 16, 0},
  { 0b00000100, 16, 10},
  { 0b00000100, 16, 55},
  { 0b00000100, 17, 5},
  { 0b00000100, 17, 45},

    // вт-пн
  { 0b01111000, 8, 45},
  { 0b01111000, 8, 55},
  { 0b01111000, 9, 40},
  { 0b01111000, 9, 50},
  { 0b01111000, 10, 35},
  { 0b01111000, 10, 45},
  { 0b01111000, 11, 30},
  { 0b01111000, 11, 45},
  { 0b01111000, 12, 30},
  { 0b01111000, 12, 35},
  { 0b01111000, 13, 20},
  { 0b01111000, 13, 40},
  { 0b01111000, 14, 25},
  { 0b01111000, 14, 30},
  { 0b01111000, 15, 15},
  { 0b01111000, 15, 25},
  { 0b01111000, 16, 10},
  { 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);


/*
 * проверка кода с выводом в консоль для кода 1
 *
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);

*/

}    

void rele(){

Serial.println("Начинаем звонить..."); 

// буззер
 tone(buzzer, 2000); // Send 2KHz sound signal...
  delay(1000); 
  noTone(buzzer); 
  
// реле
  digitalWrite(12, HIGH);
  delay(7000);  // 10 сек
  digitalWrite(12, LOW);

Serial.println("Завершаем звонить...");

setNextAlarm();

}


void setup()
{
  
  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("Время успешно получено!");
    setNextAlarm();
    Alarm.alarmRepeat(6,11,22,setNextAlarm);

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

int zH,zM,chasNow,minNow,next_alarm;
void  loop(){
if(millis()%1000==0){                          // если прошла 1 секунда
      lcd.setCursor(0, 0);                       // устанавливаем курсор в позицию: столбец 0, строка 0
      lcd.print(time.gettime("H:i   d.m.y"));   // выводим время + дату
      lcd.setCursor(3, 1);                       // устанавливаем курсор в позицию: столбец 0, строка 1
      lcd.print(L"Еще: ");   
    
next_alarm = findNextAlarm();
zH= alarm_hour(next_alarm);
zM= alarm_min(next_alarm);
chasNow=hour();
minNow=minute(); 
lcd.print(ost(chasNow,minNow,zH,zM));      // выводим остаток минут
lcd.print(L" мин.");
Alarm.delay(200);          // приостанавливаем на 0.2 с, чтоб не выводить время несколько раз за 1мс
}
}

int ost (int tecH, int tecM, int zapH, int zapM)
{
  int tec,zap,ostatok;
  tec=tecH*60+tecM;
  zap=zapH*60+zapM;
  ostatok=zap-tec;
  return ostatok;
}






 

b707 пишет:

насчет ПЕРЕМЕНЫ и УРОКА фразы не понял - разве они в коде как-то отличаются?

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

b707
Онлайн
Зарегистрирован: 26.05.2017

kpik пишет:

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

пусть тренируются в устном счете ....

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

b707 пишет:

пусть тренируются в устном счете ....

Ну вроде уже получилось, так почему не доделать?)

да и часы что-то сильно начали спешить за 2-3 часа на +3 минуты (DS1307) надеюсь глюк модуля, жду DS3231

b707 пишет:

Два момента мне в нем не нравятся - точное сравнение миллис с 1000 (строка 3) - может срабатывать через раз. И то, что Alarm.delay и у вас вызывается только при совпадении с условием строки 3.

 

так что вытащить все из условия?

b707
Онлайн
Зарегистрирован: 26.05.2017

kpik пишет:

так что вытащить все из условия?

вообще уберите условие с миллис, вместо этого сначала поставьте Alarm.delay(1000). а потом проверяйте минуты на часах на изменение - и только если сменились, выводите новое время и рассчитывайте остаток до звонка

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

kpik пишет:

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

Как же не отличаются. Отличаются чётностью. Все времена звонков на урок - нечётные, а на перемену - чётные.