ardoinshik, то что вы начали изначально делать -это неправильно. Программе не нужны данные в том формате, в котором они удобны человеку. У вас гигантская избыточность массивов. Какой смысл в каждой ячейке хранить полную дату? наверняка в схемах алармов есть или повторы или закономерности, используя которые можно принципиально изменить всю логистику хранения и упаковать в гораздо меньшие объёмы.
1. Не совсем понятно, зачем для хранения времени использовать текстовые строки, когда как раз на этот случай придумали unixtime.
2. Не разбирался с особенностями реализации PROGMEM, но по смыслу это должны быть статические констранты. У Вас нескаолько нестандартное описание массива myStrings для этого случая. Что в этом случае делает компилятор, я не знаю, но, судя по тому, что у Вас происходит перерасход оперативной памяти квалификатор PROGMEM попросту игнорируется. Опишите, как пололжено: с квалификатором const и вне пределов функции.
Компилятор avr-gcc не умеет хранить массив строк во флеш напрямую. Это можно сделать способами, которые я указал ранее. При этом для сравнения строки во флеш и ОЗУ нужно использовать функцию strcmp_P, специально для этого предназначенную.
Подскажите пож-та код, в котором в переменную можно занести дату и время хотя бы одного будильника с помощью unixtime? А потом бы как то сравнить её с данными с модуля времени, который выдает в виде "01.12.2016" и "09:26:00"...
Этого кода в результирующем файле не будет (на картинке я это показал, там 4 асм команды и call Serial.println() для каждой строки, где идёт обращение к Date[n]). 0x0820 - это вызов метода println().
На этапе компиляции любое обращение к объекту Dates через оператор индексирования развернётся в готовый указатель на область flash, где содержится строка. Ключевое слово inline означает включить тело функции operator[] в место вызова, а оптимизация сократит код функции до значения указателя, которое известно на момент компиляции. Поэтому не важно к какой строке мы обращаемся.
П.С. Т.е. я не совсем правльно пояснил, сам inline не сократит код, это сделает оптимизатор. inline лишь уберёт лишний вызов.
это как бы хорошо, НО! это же какое-то безобразие - я пишу код и желаю, что бы исполнялся switch, а не происходило обращение к индексу.
"Коль праведно то, чего он вожделеет, то то чего ты вожделеешь - грешно" О.Хаям
Размер структуры равен 4 байтам, также как и для time_t, которая обычно 32-разрядная. Таким образом удобно заполнять массив вручную и просто преобразовать в srtuct tm и затем в time_t для сравнения со значениями от rtc, которые наверняка тоже можно получить не в строковом формате. Либо вообще по полям делать сравнение.
Я забыл, что методы print(...) реализованы только для переменных, расположенных в ОЗУ, кроме строк, указатели на которые специально указаны. Печатается билиберда, т.к. указатели берутся для флеш, а используются для ОЗУ. Тут всё немного сложнее получается.
Нужно копировать содержимое флеши в ОЗУ:
int n = sizeof( dt) / sizeof( MYDATETIME );
for ( int i = 0; i < n; i++ )
{
MYDATETIME tmp;
memcpy_P( & tmp, & dt[i], sizeof( MYDATETIME ) );
Serial.println( tmp.fields.hour );
}
Спасибо, так работает. Как теперь склеить значения tmp.fields.Х чтобы получитьchar* вот такого вида "01.12.201611:30:20" ? Именно в таком виде модуль реального времени выдает дату и время, после маленькой склейки:
Т.е. Serial.print(result) выдает 01.12.201615:45:20
Надо ведь ещё как-то ноль добавить к числам, которые меньше 10
Кстати, теперь стало понятно, почему PROGMEM игнорируется и память переполняется. Это происходит потому, что каждую строку массива нужно объявлять в отдельную строку, это такая фишка PROGMEM. На середине страницы объяснено и разжевано если кому-то интересно
Думается мне, что кроме строковых методов там должны быть методы, которые возвращают дату и время в других форматах. Лучше использовать их, например, getHour() или getTime(). С их помощью было бы проще делать сравнение.
посмотрел другие библиотеки, думаю что не смогу сам. uni, вы можете помочь за вознаграждение?(если в этой ветке форума не запрещено договариваться). через teamviewer например, могу написать вам на почту через часа эдак четыре
Подскажите пож-та код, в котором в переменную можно занести дату и время хотя бы одного будильника с помощью unixtime? А потом бы как то сравнить её с данными с модуля времени, который выдает в виде "01.12.2016" и "09:26:00"...
Смотрите в стандартных римерах Ардуино.
Еще, кажется, чуть ли не в любую библиотеку RTC входит функция преобразования.
Зачем использовать библиотеку, а потом преобразовывать ? Обращайтесь напрямую к регистрам RTC, это и упростит преобразования и уменьшит размер кода. Например так:
#include <Wire.h>
#define DS3231_I2C_ADDRESS 0x68
byte seconds, minutes, hours, day, date, month, year;
char weekDay[4];
byte tMSB, tLSB;
float temp3231;
void setup()
{
Wire.begin();
Serial.begin(9600);
//set control register to output square wave on pin 3 at 1Hz
Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
Wire.write(0x0E); //выставляемся в 14й байт
Wire.write(B00000000); //сбрасываем контрольные регистры
Wire.write(B10001000); //выставляем 1 на статус OSF и En32kHz
Wire.endTransmission();
}
void loop() {
watchConsole(); //читаем консоль. Если нажата "T" читаем из консоли следующий 7 байт и устанавливаем время.
get3231Date(); //получаем данные
//и потом их выводим через Serial.print()
Serial.print(weekDay); Serial.print(", "); Serial.print(month, DEC); Serial.print("/"); Serial.print(date, DEC); Serial.print("/"); Serial.print(year, DEC); Serial.print(" - ");
Serial.print(hours, DEC); Serial.print(":"); Serial.print(minutes, DEC); Serial.print(":"); Serial.print(seconds, DEC);
Serial.print(" Temperature: "); Serial.print(get3231Temp());Serial.print("; ");
Serial.println(get3231Register(0x0F)); //получаем и выводим статусовый регистр
delay(1000);
}
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
void watchConsole()
{
if (Serial.available()) { // Look for char in serial queue and process if found
if (Serial.read() == 84) { //If command = "T" Set Date
set3231Date();
get3231Date();
Serial.println(" ");
}
}
}
void set3231Date()
{
//T(sec)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(year)
//T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99)
//Example: 02-Feb-09 @ 19:57:11 for the 3rd day of the week -> T1157193020209
seconds = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.
minutes = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
hours = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
day = (byte) (Serial.read() - 48);
date = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
month = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
year = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
Wire.beginTransmission(DS3231_I2C_ADDRESS); //начали сессию
Wire.write(0x00); //поставляемся в нулевой байт для чтения данных
Wire.write(decToBcd(seconds));
Wire.write(decToBcd(minutes));
Wire.write(decToBcd(hours));
Wire.write(decToBcd(day));
Wire.write(decToBcd(date));
Wire.write(decToBcd(month));
Wire.write(decToBcd(year));
Wire.endTransmission();//закрыли сессию
}
byte get3231Register(byte regNo) {
// send request to receive data starting at register regNo
Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
Wire.write(regNo); // start at register regNo
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 1); // request one byte
if(Wire.available()) return Wire.read();
}
void set3231Register(byte regNo, byte value) {
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(regNo);
Wire.write(value);
Wire.endTransmission();
}
void get3231Date()
{
// send request to receive data starting at register 0
Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address
Wire.write(0x00); // start at register 0
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes
if(Wire.available()) {
seconds = Wire.read(); // get seconds
minutes = Wire.read(); // get minutes
hours = Wire.read(); // get hours
day = Wire.read();
date = Wire.read();
month = Wire.read(); //temp month
year = Wire.read();
//Конвертация происходит очень просто - битовым оператором & мы очищаем МЛАДШИЕ (0,1,2,3) четыре бита , сдвигаем все вправо на 4 позиции (очищенные биты
//вылезут при этом с левой стороны и результат умножаем на 10, т.к. в старших битах хранится информация о десятках секунд.
//После этого битовым оператором & очищаем СТАРШИЕ (4,5,6,7)четыре бита и получаем секунды. Затем суммируем десятки секунд и единиц.
seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111));
minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111));
hours = (((hours & B00110000)>>4)*10 + (hours & B00001111));
day = (day & B00000111); // 1-7
date = (((date & B00110000)>>4)*10 + (date & B00001111)); // 1-31
month = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow
year = (((year & B11110000)>>4)*10 + (year & B00001111));
}
else {
//oh noes, no data!
}
switch (day) {
case 1:
strcpy(weekDay, "Mon");
break;
case 2:
strcpy(weekDay, "Tue");
break;
case 3:
strcpy(weekDay, "Wed");
break;
case 4:
strcpy(weekDay, "Thu");
break;
case 5:
strcpy(weekDay, "Fri");
break;
case 6:
strcpy(weekDay, "Sat");
break;
case 7:
strcpy(weekDay, "Sun");
break;
}
}
float get3231Temp()
{
//temp registers (11h-12h) get updated automatically every 64s
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.write(0x11);
Wire.endTransmission();
Wire.requestFrom(DS3231_I2C_ADDRESS, 2);
if(Wire.available()) {
tMSB = Wire.read(); //2's complement int portion
tLSB = Wire.read(); //fraction portion
temp3231 = (tMSB & B01111111); //do 2's math on Tmsb
temp3231 += ( (tLSB >> 6) * 0.25 ); //only care about bits 7 & 8
}
else {
//oh noes, no data!
}
return temp3231;
}
В зависимости от точности будильника ,объем занимаемый им может колебаться от 1 до 3 байт. Информация о годе, месяце числе и дне недели абсолютно не нужна. Она может быть получена при просмотре массива будильником простым вычислением. Вот что остается для получения времени, если убрать все лишнее
#include <Wire.h>
byte minutes, hours;
void setup()
{
//Serial.begin(9600); // this is here so that we can print the result
}
void loop()
{
Wire.beginTransmission(0x68); // обращаемся устройству 0x68 (RTC)
Wire.write(0x01); // устанавливаем начальный адрес
Wire.endTransmission(); // конец передачи
Wire.requestFrom((0x68), 2); // запрашиваем 3 байт
minutes = Wire.read(); // get minutes
hours = Wire.read(); // get hours
minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111));
hours = (((hours & B00110000)>>4)*10 + (hours & B00001111));
//Serial.print(hours,DEC); Serial.print(":"); Serial.println(minutes,DEC);
delay(1000);
}
нельзя математически просчитать времена срабатывания будильников, дан их список и в нем нет закономерностей.
Я имел в виду вычисление не времени срабатывания будильника, а даты. Её можно вычислить, для этого в начале группы будильников на конкретную дату установить флаг смены даты.
(551%) динамической памяти
это не ошибка - это ИИ пытается убежать в реал
ardoinshik, то что вы начали изначально делать -это неправильно. Программе не нужны данные в том формате, в котором они удобны человеку. У вас гигантская избыточность массивов. Какой смысл в каждой ячейке хранить полную дату? наверняка в схемах алармов есть или повторы или закономерности, используя которые можно принципиально изменить всю логистику хранения и упаковать в гораздо меньшие объёмы.
1. Не совсем понятно, зачем для хранения времени использовать текстовые строки, когда как раз на этот случай придумали unixtime.
2. Не разбирался с особенностями реализации PROGMEM, но по смыслу это должны быть статические констранты. У Вас нескаолько нестандартное описание массива myStrings для этого случая. Что в этом случае делает компилятор, я не знаю, но, судя по тому, что у Вас происходит перерасход оперативной памяти квалификатор PROGMEM попросту игнорируется. Опишите, как пололжено: с квалификатором const и вне пределов функции.
Компилятор avr-gcc не умеет хранить массив строк во флеш напрямую. Это можно сделать способами, которые я указал ранее. При этом для сравнения строки во флеш и ОЗУ нужно использовать функцию strcmp_P, специально для этого предназначенную.
Спасибо всем за ответы.
Подскажите пож-та код, в котором в переменную можно занести дату и время хотя бы одного будильника с помощью unixtime? А потом бы как то сравнить её с данными с модуля времени, который выдает в виде "01.12.2016" и "09:26:00"...
Этого кода в результирующем файле не будет (на картинке я это показал, там 4 асм команды и call Serial.println() для каждой строки, где идёт обращение к Date[n]). 0x0820 - это вызов метода println().
На этапе компиляции любое обращение к объекту Dates через оператор индексирования развернётся в готовый указатель на область flash, где содержится строка. Ключевое слово inline означает включить тело функции operator[] в место вызова, а оптимизация сократит код функции до значения указателя, которое известно на момент компиляции. Поэтому не важно к какой строке мы обращаемся.
П.С. Т.е. я не совсем правльно пояснил, сам inline не сократит код, это сделает оптимизатор. inline лишь уберёт лишний вызов.
это как бы хорошо, НО! это же какое-то безобразие - я пишу код и желаю, что бы исполнялся switch, а не происходило обращение к индексу.
"Коль праведно то, чего он вожделеет, то то чего ты вожделеешь - грешно" О.Хаям
Можно использовать такую промежуточную структуру для работы со временем компактно и понятно:
typedef union _MYDATETIME { struct { uint32_t mday : 5; // 0 - 31 uint32_t mon : 4; // 0 - 15 uint32_t year : 6; // 0 - 63 uint32_t hour : 5; // 0 - 31 uint32_t min : 6; // 0 - 63 uint32_t sec : 6; // 0 - 63 } fields; uint32_t time; } * PMYDATETIME, MYDATETIME; const MYDATETIME dt[] PROGMEM = { // d - день месяца - [ 1 to 31 ] // m - месяц, начиная с Января - [ 0 to 11 ] // y - год, начиная с 2000 // H - часы - [ 0 to 23 ] // M - минуты - [ 0 to 59 ] // S - секунды - [ 0 to 59 ] // d m y H M S { fields: { 14, 10, 16, 00, 00, 00 } }, // 0 { fields: { 14, 10, 16, 01, 00, 00 } }, // 1 { fields: { 14, 10, 16, 02, 00, 00 } }, // 2 { fields: { 14, 10, 16, 03, 00, 00 } }, // 3 { fields: { 14, 10, 16, 04, 00, 00 } }, // 4 { fields: { 14, 10, 16, 05, 00, 00 } }, // 5 { fields: { 14, 10, 16, 06, 00, 00 } }, // 6 };Использовать так, например:
Serial.println( sizeof( MYDATETIME ) ); Serial.println( dt[0].fields.year ); Serial.println( dt[1].fields.hour );Размер структуры равен 4 байтам, также как и для time_t, которая обычно 32-разрядная. Таким образом удобно заполнять массив вручную и просто преобразовать в srtuct tm и затем в time_t для сравнения со значениями от rtc, которые наверняка тоже можно получить не в строковом формате. Либо вообще по полям делать сравнение.
Пытаюсь сделать перебор минут, используя ваш код:
int i; for (i=0;i<=6;i=i+1){ Serial.println( dt[i].fields.min ); }На выходе получаю непонятные значения:
15
0
0
48
0
0
32
32
0
0
48
10
0
32
32
0
0
48
11
0
32
32
0
Этих значений даже нет в массиве.
Если же просто вот так сделать:
То получаю правильные минуты из массива.
(в ступоре)
а я бы делал через int - хранение минут от предшествующей даты )))
Укладываемся в 1500 int-ов
Я забыл, что методы print(...) реализованы только для переменных, расположенных в ОЗУ, кроме строк, указатели на которые специально указаны. Печатается билиберда, т.к. указатели берутся для флеш, а используются для ОЗУ. Тут всё немного сложнее получается.
Нужно копировать содержимое флеши в ОЗУ:
int n = sizeof( dt) / sizeof( MYDATETIME ); for ( int i = 0; i < n; i++ ) { MYDATETIME tmp; memcpy_P( & tmp, & dt[i], sizeof( MYDATETIME ) ); Serial.println( tmp.fields.hour ); }Спасибо, так работает. Как теперь склеить значения tmp.fields.Х чтобы получить
char* вот такого вида "01.12.201611:30:20" ? Именно в таком виде модуль реального времени выдает дату и время, после маленькой склейки:Т.е. Serial.print(result) выдает 01.12.201615:45:20
Надо ведь ещё как-то ноль добавить к числам, которые меньше 10
Кстати, теперь стало понятно, почему PROGMEM игнорируется и память переполняется. Это происходит потому, что каждую строку массива нужно объявлять в отдельную строку, это такая фишка PROGMEM. На середине страницы объяснено и разжевано если кому-то интересно
Думается мне, что кроме строковых методов там должны быть методы, которые возвращают дату и время в других форматах. Лучше использовать их, например, getHour() или getTime(). С их помощью было бы проще делать сравнение.
В используемой библиотеке нет других методов. надо попробовать другую библиотеку
посмотрел другие библиотеки, думаю что не смогу сам. uni, вы можете помочь за вознаграждение?(если в этой ветке форума не запрещено договариваться). через teamviewer например, могу написать вам на почту через часа эдак четыре
Мне сейчас некогда этим заниматься. Попросите кого-нить другого, тут найдутся, я думаю.
Спасибо всем за ответы.
Подскажите пож-та код, в котором в переменную можно занести дату и время хотя бы одного будильника с помощью unixtime? А потом бы как то сравнить её с данными с модуля времени, который выдает в виде "01.12.2016" и "09:26:00"...
Смотрите в стандартных римерах Ардуино.
Еще, кажется, чуть ли не в любую библиотеку RTC входит функция преобразования.
Зачем использовать библиотеку, а потом преобразовывать ? Обращайтесь напрямую к регистрам RTC, это и упростит преобразования и уменьшит размер кода. Например так:
#include <Wire.h> #define DS3231_I2C_ADDRESS 0x68 byte seconds, minutes, hours, day, date, month, year; char weekDay[4]; byte tMSB, tLSB; float temp3231; void setup() { Wire.begin(); Serial.begin(9600); //set control register to output square wave on pin 3 at 1Hz Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address Wire.write(0x0E); //выставляемся в 14й байт Wire.write(B00000000); //сбрасываем контрольные регистры Wire.write(B10001000); //выставляем 1 на статус OSF и En32kHz Wire.endTransmission(); } void loop() { watchConsole(); //читаем консоль. Если нажата "T" читаем из консоли следующий 7 байт и устанавливаем время. get3231Date(); //получаем данные //и потом их выводим через Serial.print() Serial.print(weekDay); Serial.print(", "); Serial.print(month, DEC); Serial.print("/"); Serial.print(date, DEC); Serial.print("/"); Serial.print(year, DEC); Serial.print(" - "); Serial.print(hours, DEC); Serial.print(":"); Serial.print(minutes, DEC); Serial.print(":"); Serial.print(seconds, DEC); Serial.print(" Temperature: "); Serial.print(get3231Temp());Serial.print("; "); Serial.println(get3231Register(0x0F)); //получаем и выводим статусовый регистр delay(1000); } // Convert normal decimal numbers to binary coded decimal byte decToBcd(byte val) { return ( (val/10*16) + (val%10) ); } void watchConsole() { if (Serial.available()) { // Look for char in serial queue and process if found if (Serial.read() == 84) { //If command = "T" Set Date set3231Date(); get3231Date(); Serial.println(" "); } } } void set3231Date() { //T(sec)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(year) //T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99) //Example: 02-Feb-09 @ 19:57:11 for the 3rd day of the week -> T1157193020209 seconds = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result. minutes = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48)); hours = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48)); day = (byte) (Serial.read() - 48); date = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48)); month = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48)); year = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48)); Wire.beginTransmission(DS3231_I2C_ADDRESS); //начали сессию Wire.write(0x00); //поставляемся в нулевой байт для чтения данных Wire.write(decToBcd(seconds)); Wire.write(decToBcd(minutes)); Wire.write(decToBcd(hours)); Wire.write(decToBcd(day)); Wire.write(decToBcd(date)); Wire.write(decToBcd(month)); Wire.write(decToBcd(year)); Wire.endTransmission();//закрыли сессию } byte get3231Register(byte regNo) { // send request to receive data starting at register regNo Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address Wire.write(regNo); // start at register regNo Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 1); // request one byte if(Wire.available()) return Wire.read(); } void set3231Register(byte regNo, byte value) { Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(regNo); Wire.write(value); Wire.endTransmission(); } void get3231Date() { // send request to receive data starting at register 0 Wire.beginTransmission(DS3231_I2C_ADDRESS); // 104 is DS3231 device address Wire.write(0x00); // start at register 0 Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 7); // request seven bytes if(Wire.available()) { seconds = Wire.read(); // get seconds minutes = Wire.read(); // get minutes hours = Wire.read(); // get hours day = Wire.read(); date = Wire.read(); month = Wire.read(); //temp month year = Wire.read(); //Конвертация происходит очень просто - битовым оператором & мы очищаем МЛАДШИЕ (0,1,2,3) четыре бита , сдвигаем все вправо на 4 позиции (очищенные биты //вылезут при этом с левой стороны и результат умножаем на 10, т.к. в старших битах хранится информация о десятках секунд. //После этого битовым оператором & очищаем СТАРШИЕ (4,5,6,7)четыре бита и получаем секунды. Затем суммируем десятки секунд и единиц. seconds = (((seconds & B11110000)>>4)*10 + (seconds & B00001111)); minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111)); hours = (((hours & B00110000)>>4)*10 + (hours & B00001111)); day = (day & B00000111); // 1-7 date = (((date & B00110000)>>4)*10 + (date & B00001111)); // 1-31 month = (((month & B00010000)>>4)*10 + (month & B00001111)); //msb7 is century overflow year = (((year & B11110000)>>4)*10 + (year & B00001111)); } else { //oh noes, no data! } switch (day) { case 1: strcpy(weekDay, "Mon"); break; case 2: strcpy(weekDay, "Tue"); break; case 3: strcpy(weekDay, "Wed"); break; case 4: strcpy(weekDay, "Thu"); break; case 5: strcpy(weekDay, "Fri"); break; case 6: strcpy(weekDay, "Sat"); break; case 7: strcpy(weekDay, "Sun"); break; } } float get3231Temp() { //temp registers (11h-12h) get updated automatically every 64s Wire.beginTransmission(DS3231_I2C_ADDRESS); Wire.write(0x11); Wire.endTransmission(); Wire.requestFrom(DS3231_I2C_ADDRESS, 2); if(Wire.available()) { tMSB = Wire.read(); //2's complement int portion tLSB = Wire.read(); //fraction portion temp3231 = (tMSB & B01111111); //do 2's math on Tmsb temp3231 += ( (tLSB >> 6) * 0.25 ); //only care about bits 7 & 8 } else { //oh noes, no data! } return temp3231; }В зависимости от точности будильника ,объем занимаемый им может колебаться от 1 до 3 байт. Информация о годе, месяце числе и дне недели абсолютно не нужна. Она может быть получена при просмотре массива будильником простым вычислением. Вот что остается для получения времени, если убрать все лишнее
#include <Wire.h> byte minutes, hours; void setup() { //Serial.begin(9600); // this is here so that we can print the result } void loop() { Wire.beginTransmission(0x68); // обращаемся устройству 0x68 (RTC) Wire.write(0x01); // устанавливаем начальный адрес Wire.endTransmission(); // конец передачи Wire.requestFrom((0x68), 2); // запрашиваем 3 байт minutes = Wire.read(); // get minutes hours = Wire.read(); // get hours minutes = (((minutes & B11110000)>>4)*10 + (minutes & B00001111)); hours = (((hours & B00110000)>>4)*10 + (hours & B00001111)); //Serial.print(hours,DEC); Serial.print(":"); Serial.println(minutes,DEC); delay(1000); }нельзя математически просчитать времена срабатывания будильников, дан их список и в нем нет закономерностей. Сейчас попробую ваш первый код
нельзя математически просчитать времена срабатывания будильников, дан их список и в нем нет закономерностей.
Я имел в виду вычисление не времени срабатывания будильника, а даты. Её можно вычислить, для этого в начале группы будильников на конкретную дату установить флаг смены даты.
нельзя математически просчитать времена срабатывания будильников, дан их список и в нем нет закономерностей. Сейчас попробую ваш первый код
кем дан? пристрели этого упоротого дятла.