Гуру, объясните по времени
- Войдите на сайт для отправки комментариев
Втр, 22/05/2018 - 16:39
Задача:
Есть текущее время в формате
YY,MM,DD,HH,mm
Берется с RTC.
Раз в час происходит событие и данные записываются в ячейку EEPROM.
Написал код который записывает туда все в цикличном режиме.
Требуется, время от времени смотреть что было ,скажем 30 часов назад.
И что бы выводились значения времени.
Для этого в первые 6 ячеек пишем 01,адрес записанной ячейки,2-год,3-месяц,4-день,5-час,6-минута.
Т.е. записали в ячейку значения датчика, записали время записи, записали номер записи.
Зная номер записи нужно определять время записи, зная сколько часов назад была она произведена.
И выводить в нужном формате.
Как это реализовать ?
Только расчет времени.
Остальное уже сделал.
Цель: уместить в EEPROM 336 значений
24*14(данные за две недели)
И знать какое значение привязано к какому времени.
значения типа byte.
342 байта еепром задействовано.
Переписывать раз в час первые 7 байт на 11+лет хватит.
Проблема именно в том,
Что скажем последний раз записали в ячейку 300,-значения первых двух байт.
В этот момент было время(следующие 5 байт)
А вот если посмотреть что было 100часов назад в ячейке 200 я могу.
А сколько в этот момент времени было нет.
Теоретически -100 часов от того, что записано в памяти, но как вывести.
Минимальная единица - минута?
Минимальная единица - минута?
Да
Номер ячейки вообще не нужен. Год, месяц. число - хранить только для первой записи. Для остальных хранить только смещение в минутах от старта , размер 2 байтв, достаточно на 3 недели.
Общая вместимость зависит от размера данных. При данных в 1 байт в ЕЕПРОМ ардуины Уно поместится как раз 336-340 отсчетов.
Э-ээээ ...
Правильно ли я понимаю, что вся задача сводится к тому - как из текущего времени вычесть 100 часов? - что ж вы такой ерундой форум беспокоите?
Номер ячейки вообще не нужен. Год, месяц. число ...
Для двух недель год тоже не нужен.
Номер ячейки вообще не нужен. Год, месяц. число - хранить только для первой записи. Для остальных хранить только смещение в минутах от старта , размер 2 байтв, достаточно на 3 недели.
Общая вместимость зависит от размера данных. При данных в 1 байт в ЕЕПРОМ ардуины Уно поместится как раз 336-340 отсчетов.
Не понял .
У меня 336 едениц данных по одному байту.
Если я ещё туда смещение добавлю...
Мне нужно, что бы запись по событию происходила, а не по времени.
Ну да, arduinec, это ты расскажешь числа 7го января.
Э-ээээ ...
Правильно ли я понимаю, что вся задача сводится к тому - как из текущего времени вычесть 100 часов? - что ж вы такой ерундой форум беспокоите?
Да именно.
Гугл даже не знаю о чем спросить.
Не понял . У меня 336 едениц данных по одному байту. Если я ещё туда смещение добавлю... Мне нужно, что бы запись по событию происходила, а не по времени.
336 единиц по байту + 336 *2 байт смещения = 1018 байт. А размер ЕЕПРОМ - 1024. Входит.
Как обычно... ТС даже не в состоянии задачу грамотно описать...
Сначала подумайте, потом опишите внятно, потом спрашивайте.
Не понял . У меня 336 едениц данных по одному байту. Если я ещё туда смещение добавлю... Мне нужно, что бы запись по событию происходила, а не по времени.
336 единиц по байту + 336 *2 байт смещения = 1018 байт. А размер ЕЕПРОМ - 1024. Входит.
Вроде у uno nano 512 байт
Или меня Гугл обманул ?
обманул, юзай яндекс :)
[ Вроде у uno nano 512 байт Или меня Гугл обманул ?
атмега168 - 512 байт, атмега328 - 1024
Спасибо дяденьки. Знал бы сразу, какой я дурак, не беспокоил бы вас.
В килобайт то я могу все сразу записать.
И дату в формате int скажем 220518, два байта+ байт данных.
3*336=1008 байт с запасом.
Если принять за нулевое время запуск ардуины, то байта хватит на фиксацию событий 255 минут. 2байта - на 18 часов а 3 байта на 194 дня.
Типа 7-го января контроллер будет пьян и по изменению месяца с 12 на 1 не догадается, что год поменялся :)
arduinec. Ну день ВДВ точно не переживет. Ведь надо разбить головой бутылку и заплыв в фонтане.
Какие нафиг 3 байта, двух мне хватит,
22051862.
Дату выводить /100
Данные%10.
Вааащщще спасибо вам
то есть на часы и минуты уже забили, достаточно только даты? А нафига было форум бередить?
Если принять за нулевое время запуск ардуины, то байта хватит на фиксацию событий 255 минут. 2байта - на 18 часов а 3 байта на 194 дня.
плохо у тебя с арифметикой, Квон :)
Погуглите unix timestamp и не мучайтесь, там все просто.
От, наркоманы праклятые...
Погуглите unix timestamp и не мучайтесь, там все просто.
2 недели в 2 байта не влезут
220518173362
Да, что то рано обрадовался
Не влезет.
А смещение в минутах - влезеть сасвистом.
читайте внимательно сообщение #4
Номер ячейки вообще не нужен. Год, месяц. число - хранить только для первой записи. Для остальных хранить только смещение в минутах от старта , размер 2 байтв, достаточно на 3 недели.
Общая вместимость зависит от размера данных. При данных в 1 байт в ЕЕПРОМ ардуины Уно поместится как раз 336-340 отсчетов.
Раз в две недели переписывать время старта ?
Опять остаётся вопрос изначальный как считать :-)
Ну как обычно считают в 1 дне 24 часа/ в 1 часе 60 минут. Вот и считайте . Абсолютное время старта в минутах + смещение.
байта хватит на фиксацию событий 255 минут. 2байта - на 18 часов а 3 байта на 194 дня
....
обычно считают в 1 дне 24 часа/ в 1 часе 60 минут. Вот и считайте .
Квон, сам бы взял счеты и посчитал, прежде чем спорить Ты только первое число угадал - в 1 байте 255 минут.
В двух байтах - 65536 минут - то есть 1092 часа = 45 дней. С тремя байтами все еще хуже.
Вроде как понял.
Поправьте если не так.
Записываем при первом событии , его время, в формате UnixTime.
При следующем событии вычитаем это время из текущего с точностью до минуты.
Записываем в первые два байта разницу в минутах в формате short, в третий данные.
Через две недели проходит 20160 минут.
А дальше что делать ?
Что то я не вижу очевидного решения.
Носом ткните плз.
Просто везде вычесть из того что есть, и пущай отрицательные числа считает ?
формата short в ардуине нет, вместо этого int
Что делать через 2 недели.... Можно, к примеру, записать в начало новую дату отсчета и во все старые записи записать отрицательное смещение от новой даты.
Ежели RTC - это широкоизвестный модуль DS3231, то на ём может вполне себе стоять "The AT24C32 provides 32,768 bits of serial electrically erasable and programmable read only memory (EEPROM)", что какбэ побольше, чем EEPROM 328-го.
Kakmyc, первое надо решить для себя . Сколько времени должно работать устройство. И время когда прошлые записи уже не актуальны. Вы все же не машину времени делаете. И длительность в год это уже много. А если нужны эти данные, то перепишите на флешку или комп.
Перечитал Ваш пост №4, не увидел сразу.. собственно это то, про что и написал: unix timestamp это смещение от некоей волшебной секунды в мире. Так же и тут: фиксить стартовое время и хранить с каждым замером только смещение в минутах от него. Если хранить 1 байтом, то на каждую запись потребуется 2 байта: смещение в минутах и само значение. Но хватит только на 256 минут и сожрет 512 байт EEPROM. У Нано, Уно и пр. на базе ATmega328 его 1024байта всего. У ATmega128a - кажется 2 кила, а у ATmega2560 все 4 кила..
Если хранить минуты в 2-х байтах, то запись будет занимать уже 3 байта и ограничителем станет размер EEPROM, а влезет не намного больше 340 записей в 328-ю (Нано, Уно), 680 записи в 128-ю или 1360 записи в Мегу 2560. То есть хранить так больше чем за 1360/60=22,7 часа - не получится ни в каком внутреннем EEPROM.
Можно пойти ещё так: пишем стартовое время и храним ТОЛЬКО 1 байт данных. Ибо его смещение и есть количество минут (замеров). Но в таком разе или замеры должны идти строго поминутно и пропуски недопустимы или надо иметь волшебное значение для пропущенного замера. В любом случае замер надо писать с "минутным смещением" от даты старта. Так влезет побольше, до примерно 4090 замеров в Мегу 2560. Это на почти 3-е суток.
Если замеры идут не регулярно, то можно выделить несколько блоков .. скажем иметь место под запись 10-и стартовых дат и по 1 байту дополнительно для указания длины цепочки. То есть вначале EEPROM храним "таблицу": дата + кол-во замеров в цепочке. И далее сами замеры "подряд". Но в этом случае будет сложнее алгоритм вычисления смещения требуемого замера. Надо будет вычислять начало нужной цепочки и уже в ней искать требуемую "минуту" замера. Сильно на подольше все равно не получится. Так, на поизголяться.
Надо больше хранить? Тогда стоит смотреть на подключение SD-карты и отказаться от EEPROM. Или смотреть в сторону подключения внешнего EEPROM большего объема. Их есть много разных, в т.ч. последовательных по SPI или I2C. Или смотреть на возможность "сливать" данные на "большой компьютер" по накоплению..
как-то так. ИМХО, задача плохо продумана с архитектурной стороны..
Перечитал Ваш пост №4, не увидел сразу.. собственно это то, про что и написал: unix timestamp это смещение от некоей волшебной секунды в мире. Так же и тут: фиксить стартовое время и хранить с каждым замером только смещение в минутах от него. Если хранить 1 байтом, то на каждую запись потребуется 2 байта: смещение в минутах и само значение. Но хватит только на 256 минут и сожрет 512 байт EEPROM. У Нано, Уно и пр. на базе ATmega328 его 1024байта всего. У ATmega128a - кажется 2 кила, а у ATmega2560 все 4 кила..
Если хранить минуты в 2-х байтах, то запись будет занимать уже 3 байта и ограничителем станет размер EEPROM, а влезет не намного больше 340 записей в 328-ю (Нано, Уно), 680 записи в 128-ю или 1360 записи в Мегу 2560. То есть хранить так больше чем за 1360/60=22,7 часа - не получится ни в каком внутреннем EEPROM.
Можно пойти ещё так: пишем стартовое время и храним ТОЛЬКО 1 байт данных. Ибо его смещение и есть количество минут (замеров). Но в таком разе или замеры должны идти строго поминутно и пропуски недопустимы или надо иметь волшебное значение для пропущенного замера. В любом случае замер надо писать с "минутным смещением" от даты старта. Так влезет побольше, до примерно 4090 замеров в Мегу 2560. Это на почти 3-е суток.
Если замеры идут не регулярно, то можно выделить несколько блоков .. скажем иметь место под запись 10-и стартовых дат и по 1 байту дополнительно для указания длины цепочки. То есть вначале EEPROM храним "таблицу": дата + кол-во замеров в цепочке. И далее сами замеры "подряд". Но в этом случае будет сложнее алгоритм вычисления смещения требуемого замера. Надо будет вычислять начало нужной цепочки и уже в ней искать требуемую "минуту" замера. Сильно на подольше все равно не получится. Так, на поизголяться.
Надо больше хранить? Тогда стоит смотреть на подключение SD-карты и отказаться от EEPROM. Или смотреть в сторону подключения внешнего EEPROM большего объема. Их есть много разных, в т.ч. последовательных по SPI или I2C. Или смотреть на возможность "сливать" данные на "большой компьютер" по накоплению..
как-то так. ИМХО, задача плохо продумана с архитектурной стороны..
Изначально задача была, считать от времени последнего замера, убавляя час по отношению к предыдущему.
Задача ставилась исходя из того, что один балбес думал , что в 328меге 512 байт ОЗУ.
Но так как их не 512 , а 1024, значит можно тратить два байта на отсчёт времени (изначально почти всю память съедали данные:-).)
Т.е. мы можем выделять те же 336 байт памяти под те же данные, но у нас ещё остаётся 688 байт, а это по два байта на каждую запись данных=372, и ещё 16 байт под временную метку.
Наиболее правильный вариант по моему мнению. Ещё раз спс b707.
В два байта это тип данных short, в максимуме до 32767. А это, в минутах ,куда больше двух недель.
Зная эту цифру и дату начала отсчёта, мы можем вычислить , время с точностью до минуты не вылезая за 2 байта. И один байт использовать для хранения данных.
Мы же записываем не каждую минуту, а раз в час, когда событие.
Вопрос только в том, что делать через две недели, что бы те же данные были актуальны.
Как это вообще будет выглядеть ?
Никакого адекватного алгоритма пока не вижу.
а идея из сообщения #40 чем не устраивает? или вы пока ее не вкурили ? :)
Ну я вроде так и предполагал.
А куда делся short ? В спецификации вроде на месте, 2 байта кушает.
Разве, что int от него ничем не отличается. Но это его проблемы :-)
У вас же циклическая запись, и где-то хранится информация в какую ячейку была произведена запись.
1. Значит все данные до этой ячейки относятся к текущему timestamp, а всё что после к прошлому.
2. Или если цикл не симметричен (начало нового цикла не попадает на первую ячейку), то по смещению времени в последней записаной ячейке - если смещение 20 то от этой ячейики и назад на 20 позиций это текущий timestamp.
Так его и нет! О каких 32767 байтах в EEPROM Вы ведете речь, если их даже в Мега2560 всего 4 кила? Если Вы пишете в локальную EEPROM, то ограничение по размеру даже если вовсе НЕ писать метку времени к каждому замеру, то есть выделять ровно по 1 байту на запись и то хватит .. на трое суток. ВСЕГО.
О каких "двух неделях" речь? Перечитайте. Из своей цитаты я вам оставил самый компактный способ записи, вообще по 1 байту на замер. А для 328-го камня, так и вообще будет швах..
Arhat109-2.
Вы бы хоть прочитали и вдумались.
Объясню ещё раз.
Ставим временную метку(первые несколько байт), ОДИН РАЗ.
При событии пишем следующее:
Количество минут (текущее время минус время штампа,считаем контроллером, переводим это в минуты),
прошедших с момента временного штампа.
За две недели у нас произойдет 336 событий(события происходят раз в час).
На запись каждого события 3 байта.
2 байта на разницу в минутах (20160 ,столько минут в двух неделях, в два байта влазит с запасом).
И один байт данных.
В двух неделях 336 часов.
Нам не надо 32кб EEPROM. Все влезет в 1024 байта, которые есть.
байта хватит на фиксацию событий 255 минут. 2байта - на 18 часов а 3 байта на 194 дня
обычно считают в 1 дне 24 часа/ в 1 часе 60 минут. Вот и считайте .
Квон, сам бы взял счеты и посчитал, прежде чем спорить Ты только первое число угадал - в 1 байте 255 минут.
В двух байтах - 65536 минут - то есть 1092 часа = 45 дней. С тремя байтами все еще хуже.
Оба считаете не в том направлении. На месяц требуется 4 бита, день - 5 бит, час - 5 бит. Так как событие происходит раз в час, то оставшие 2 бита (от 2-х байтов) можно потратить на регистрацию четверти часа. В итоге получаем запись байта данных, а рядом с ним 2 байта даты с точностью до 15 минут. При этом ничего дополнительно считать не потребуется и новые данные можно будет спокойно писать поверх старых.
Kakmuc, Если запись идет "раз в час", то согласен полностью. Но Вас прямо спрашивали про минуты и Вы подтвердили "да". Отсюда и мои предложения. Так бы и писали СРАЗУ, что Вам надо писать только раз в час, но знать время записи с точностью до минуты ..
Kakmuc, Если запись идет "раз в час", то согласен полностью. Но Вас прямо спрашивали про минуты и Вы подтвердили "да". Отсюда и мои предложения. Так бы и писали СРАЗУ, что Вам надо писать только раз в час, но знать время записи с точностью до минуты ..
А вы вообще не читали, что в шапке написано ?
И ники не читаете...
//функция перезаписи всего адресного поля EEPROM
void update_UTS(long currentUT)
{
int current_val;
for(int eepromadrr=3;eepromadrr<1011;eepromadrr+=3)
{
EEPROM_int_read(eepromadrr) { byte raw[2]; for(byte i = 0; i < 2; i++) raw[i] = EEPROM.read(eepromadrr+i); int ¤t_val = (int&)raw; return current_val; } ;
current_val-=20160;
EEPROM_int_write(eepromadrr, current_val) { byte raw[2]; (int&)raw = current_val; for(byte i = 0; i < 2; i++) EEPROM.write(eepromadrr+i, raw[i]); };
}
EEPROM_long_write(0,currentUT) { byte raw[4]; (long&)raw = currentUT; for(byte i = 0; i < 4; i++) EEPROM.write(0+i, raw[i]); };
}
Подскажите, почему не компилируется ?
// запись long
void EEPROM_long_write(int addr, long num) { byte raw[4]; (long&)raw = num; for(byte i = 0; i < 4; i++) EEPROM.write(addr+i, raw[i]); }
// чтение int
int EEPROM_int_read(int addr) { byte raw[2]; for(byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr+i); int &num = (int&)raw; return num; }
// запись int
void EEPROM_int_write(int addr, int num) { byte raw[2]; (int&)raw = num; for(byte i = 0; i < 2; i++) EEPROM.write(addr+i, raw[i]); }
Вот это в комплекте.
Но они компилируются и работают
не компилируется в тихую? То есть компилятор ничего не пишет, просто не компилирует наотрез, ага?
Все понял, сам Чебурашка.
//функция перезаписи всего адресного поля EEPROM
#include
long currentUT;
void setup(){}
void loop(){}
//функция перезаписи всего адресного поля EEPRO.
void update_UTS(long currentUT)
{
int current_val;
for(int eepromadrr=3;eepromadrr<1011;eepromadrr+=3)
{
int current_val;
current_val=EEPROM_int_read(eepromadrr);
current_val-=20160;
EEPROM_int_write(eepromadrr,current_val);
EEPROM_long_write(0, currentUT);
}
}
// запись long
void EEPROM_long_write(int addr, long num) { byte raw[4]; (long&)raw = num; for(byte i = 0; i < 4; i++) EEPROM.write(addr+i, raw[i]); }
// чтение int
int EEPROM_int_read(int addr) { byte raw[2]; for(byte i = 0; i < 2; i++) raw[i] = EEPROM.read(addr+i); int &num = (int&)raw; return num; }
// запись int
void EEPROM_int_write(int addr, int num) { byte raw[2]; (int&)raw = num; for(byte i = 0; i < 2; i++) EEPROM.write(addr+i, raw[i]); }
Вот так должно быть