-
Салют камрады!
Нужен совет по написанию маленького менеджера памяти для EEPROM на ардуине (AVR), если конкретно то Nano. не реализация в коде, а сама идея.
Задача: Есть девайс на Arduino Nano, в которой встроенный в МК EEPROM емкостью 512 байт в первых 32 байтах хранит конфиг девайса(почти статичен), а остальное пространство отдается под хранение динамических данных. Ресурс у EEPROM ограничен в 100тыс перезаписей.
Девайс замеряет потребление энергии и сохраняет съеденное в переменную S длиной 4 байта. Необходимо раз в 10 сек дампить эти 4 байта съеденных миллиамперов в EEPROM так как девайс может быть обесточен в любой момент, а продолжать считать съеденное должен с последней сохраненной записи, а не с нуля.
Нужно придумать какой то менеджер eeprom, который будет более менее равномерно расходовать ресурс этой флеш памяти(аналогично тому что в любом SSD-диске есть в контроллере), периодически меняя расположения записываемого числа по пространству 32-512.
Думал писать в пределы конфига(там есть еще место) адрес расположения созраняемого числа и периодически его менять используя счетчик, который также сохранять в пределах конфига. Типа каждые 10-20 включений контроллера(каждый раз он будет сохранять значение счетчика в eeprom при включении) будет рандомно меняться адрес размещения сохраняемого числа и записываться в другие 4 ячейки. Но тогда будет изнашиваться место размещения счетчика.
Может есть какие то более красивые реализации подобного менеджера? мож кто сталкивался?
-
4 байта каждые 10 сек = 24 байта в минуту = 1440 в час то есть за час все успеет перезатереться три раза
отказываемся от запоминания адреса хвоста, добавляем rtc и замешиваем текущую позицию для записи чтения на текущем времени внутри текущего часа.
но так как нужны часы, а часам нужны ноги, то проще сразу прикрутить внешнюю флешку.
-
> [1] rrrrr © (27.01.17 23:24) > 4 байта каждые 10 сек = 24 байта в минуту = 1440 в час > то есть за час все успеет перезатереться три раза > > отказываемся от запоминания адреса хвоста, > добавляем rtc и замешиваем текущую позицию для записи чтения > на текущем времени внутри текущего часа. > > но так как нужны часы, а часам нужны ноги, то проще сразу > прикрутить внешнюю флешку.
Не, девайс уже собран, RTC некуда ему цеплять уже ни по ногам, ни по габаритам и памяти для бибилиотеки RTC мало, уже 70% использовано, а при 75+ он уже ругается что может глючить(ведь там ОЗУ неявно еще используются по всякие динамические выделения)
-
Записывай счётчик вместе с байтом. Только помнится мне... Как там EEPROM организована? - эти байты ведь строками пишутся, так что в пределах строки разницы нет куда писать, ну и ресурс надо разделить где-то на 16. Я не прав?
-
> [3] Inovet © (28.01.17 00:13) > Записывай счётчик вместе с байтом. Только помнится мне... > Как там EEPROM организована? - эти байты ведь строками пишутся, > так что в пределах строки разницы нет куда писать, ну и > ресурс надо разделить где-то на 16. Я не прав?
Не, в eeprom AVR пишется все побайтно. на внешних eeprom(на ARM32 ардуине предстоит тоже самое делать) через i2c вроде блочно(строками) пишется, пока не ковырялся. Пока бы в простом варианте осилить.
-
Ну тогда после старта ищем в памяти максимальное значение счётчика - это и будет последняя запись, следующие записи сохраняем в следующие ячейки с увеличением счётчика. Только при поиске последней записи по максимальному значению счётчика, смотрим переход на 0, если в следующей записи что-то больше 0, значит текущая последняя. Размер счётчика надо сделать 6 бит.
-
> [5] Inovet © (28.01.17 00:45) > 6 бит.
10
-
Я тоже парился этой темой, в итоге sd карту припаял и писал в нее невзирая на ФС. Гораздо больше пространства для маневра.
-
Ну а так самое просто что прихошло мне тогда: Зануляешь пространство. Пришешь счет в любое место. Когда считаешь, что настало время (раз в сто обновлений, например) смещаешь счет (случайно, но можно для гарантии равномерности на 1 байт), а предыдущий зануляешь.
+ Можно припаять емкость к питанию и отслеживать пропадание внешнего питания и писать только при его прекращении. У меня да этого руки не дошли, бизнес распался (
-
> [8] DayGaykin © (28.01.17 09:18) > Ну а так самое просто что прихошло мне тогда: > Зануляешь пространство. Пришешь счет в любое место. Когда > считаешь, что настало время (раз в сто обновлений, например) > смещаешь счет (случайно, но можно для гарантии равномерности > на 1 байт), а предыдущий зануляешь. > > + Можно припаять емкость к питанию и отслеживать пропадание > внешнего питания и писать только при его прекращении. У > меня да этого руки не дошли, бизнес распался (
Тоже думал о "бесперебойнике", даже купил готовый модуль для этого - маленькая бздюлька с microusb для зарядки, просто usb для питания устройств и парой деталек бустера/зарядника и контакты под припайку LiOn батарейки 18650 или другого формфактора. Модуль для создания простейшего повербанка. Вместо разъема ЮСб проводами ардуину питать. Но бустер дает такие пульсации что измерение напряжения невозможно точное(а оно нужно). Потому отказался. С емкостями тут не пойдет - надо суперкап для того чтобы напряжение нужное держалось. Да и девайс сильно усложнять и удорожать сильно(проект открытый вобщем то).
Попробую пару способов тогда.
СД карту можно, но все упирается в габариты и стоимость конечного изделия. Плюс опять же - памяти не хватат уже. В притык уже кодом забито. Бибилиотека SD-шная много места занимает.
-
перелезать на arm 1. чипы как минимум не дороже 2. больше рама, больше ног, больше периферии.
-
3. проще разрабатывать
-
> Ресурс у EEPROM ограничен в 100тыс перезаписей.
это лишь гарантированный ресурс. на практике на порядок больше, я так вообще уже пару лет жду, когда сдохнет. Кроме того, ты уверен, что у встроенной еепром такой маленький ресурс? У большинства мк ресурс еепром не равен ресурсу флэши контроллера и значительно больше.
-
перепутал нули :) да, сотня тысяч для встроенной норма.
-
а менеджер простой. перебираешь в цикле чтением все адреса по порядку, пока не встретится 0. по этому адресу пишешь новые данные, по адресу+1 записываешь 0. если адреса кончились, а 0 не вернулся - запись с начального адреса. если адрес+1 вылез за диапазон - запись 0 в начальный адрес. Итого: имеем запись по кругу, возможность чтения истории за некий период.
-
> [10] rrrrr © (28.01.17 12:12) > перелезать на arm > 1. чипы как минимум не дороже > 2. больше рама, больше ног, больше периферии.
На АРМ я перейду, точнее это будет контроллер как развитие нынешнего. Нынешний девайс нужен для простой вещи - глушить бензиновый двигатель удаленно с пульта, определять не пропала ли связь пульта и приемника, следить за напряжением и расходом АКБ и включать поисковую сирену. На АРМ будет уже концепция IoT и все будет передаваться в облако, плюс еще стопицот функций и снимаемых параметров с датчиков на модели. Но размеры ардуины с ARM слишком большие для простых функций. Кроме того у АРМ нет своего EEPROm - он там палюбас внешний. Для этого у меня есть модуль i2c c RTC и EEPROМ совмещенный.
Мне Nano ардуинки для нынешнего девайся - за глаза совершенно. Проект предназначен для свободного повторения любым имеющим навыки ЛУТа и умением держать паяльник.
> перебираешь в цикле чтением все адреса по порядку, пока > не встретится 0. по этому адресу пишешь новые данные, по > адресу+1 записываешь 0. если адреса кончились, а 0 не вернулся > - запись с начального адреса. если адрес+1 вылез за диапазон > - запись 0 в начальный адрес. > Итого: имеем запись по кругу, возможность чтения истории > за некий период.
Вот наверно так и буду реализовывать. Правда чтение всего eeprom побайтно медленновато, несколько секунд.
-
Считываешь адрес счётчика. Пишешь по этому адресу. Читаешь по этому адресу. Если запись-чтение не идентичны - меняешь адрес счётчика и повторяешь процедуру
-
как замена RTC - кварц 32к прямо на ноги асинхронного таймера меги. ( питание от батарейки через диод и переход в powerdown по снижению питания )
-
> Правда чтение всего eeprom побайтно медленновато
это нужно лишь один раз, после включения, вследствие потери счетчика. или после ресета (если нет возможности сохранять счетчик в защищеном от сброса месте).
-
> NoUser © (28.01.17 13:40) [17]
ртс необходима лишь для гарантированного значения времени. для выполнения каких-то действий с неким периодом совершенно лишнее.
-
> [14] kilkennycat © (28.01.17 13:06)
Тоже хорошо, только нет возможности посчитать уже использованный ресурс, но на это можно забить.
-
И ещё не должно быть ноль в состоянии.
-
> чтение всего eeprom побайтно медленновато, несколько секунд. это опытное значение или из описания на mcu ?
> ртс необходим лишь для гарантированного значения времени я и не спорю - просто дешёвый вариант для меги.
-
> [22] NoUser © (28.01.17 14:02) > > чтение всего eeprom побайтно медленновато, несколько секунд. > это опытное значение или из описания на mcu ? > > > ртс необходим лишь для гарантированного значения времени > я и не спорю - просто дешёвый вариант для меги.
ща схожу на почту за эмулятором монитора из Латвии и с делаю замер. Скетч с очисткой всего eeprom выполняется секунды 3-4. Может запись дольше сильно идет ченм чтение, специально не замерял. Попробую в микросекундах померять чтение.
-
> kilkennycat © (28.01.17 13:06) [14] > Итого: имеем запись по кругу, возможность чтения истории за некий период.
и в два раза меньший срок службы устройства. (и какой это будет период?, если rtc-а нет) ;))
-
> с очисткой всего eeprom выполняется секунды 3-4. Может запись дольше сильно идет чем чтение
Ага.
> Попробую в микросекундах померять чтение. В начале операции запрети прерывания, запусти какой-нибудь внутренний таймер - после останови, посмотри значение.
> Скетч ... ах да, я то меги прямиком зашиваю, - а есть возможность видеть асм выхлоп?
-
> NoUser © (28.01.17 14:12) [24] > и в два раза меньший срок службы устройства. (и какой это > будет период?, если rtc-а нет) ;))
при чем здесь в два раза срок? как посчитал? как периоды относятся к часам реального времени?
-
> NailMan © (28.01.17 14:06) [23]
не надо читать и писать всё постоянно. записываешь лишь свои данные и ноль на следующий адрес. читаешь всё только после потери счетчика адреса для его восстановления.
-
> kilkennycat © (28.01.17 14:36) [26] ох.
> при чем здесь в два раза срок? как посчитал?
Фраза "возможность чтения истории за некий период" говорит о том, что каждая новая запись происходит по новому указателю. А это значит, что к каждой записи прицеплен хвост, который, в данном случаи, увеличивает количество записываемых данных в два раза, пропорционально уменьшая ресурс носителя.
> как периоды относятся к часам реального времени?
по заданию видно, что период измерения/накопления также зависит от наличия основного питания.
> kilkennycat © (28.01.17 14:40) [27] >записываешь лишь свои данные и ноль на следующий адрес. читаешь всё только после потери счетчика адреса для его восстановления
Если имеется ввиду отсутствие изменения адреса на каждую новую запись, то это уже другая редакция алгоритма.
-
> NoUser © (28.01.17 15:19) [28]
да, это я не подумал, запись маркера действительно уменьшает.
> Если имеется ввиду отсутствие изменения адреса на каждую > новую запись, то это уже другая редакция алгоритма.
нет, почему, адрес меняется. алгоритм один и тот же. хранение адреса позволяет лишь избежать постоянного поиска адреса.
> по заданию видно, что период измерения/накопления также > зависит от наличия основного питания. >
хм.. не вижу. я вижу лишь "каждые 10 секунд". но даже если и от наличия питания какое-то условие, то всё равно не видно требования сохранения определенной даты.
-
> [28] NoUser © (28.01.17 15:19) > к каждой записи прицеплен хвост, который, в данном случаи, > увеличивает количество записываемых данных в два раза
А при записи счётчика в одну ячейку во сколько раз?
-
Ну и, может кто забыл, что можно писать байтами, но уложить в них инфу и ещё что-то в свободные биты.
-
да. и еще, тз как всегда неполное. если счетчик адреса теряется редко, то его хранением вполне можно пренебречь.
-
> [32] kilkennycat © (28.01.17 16:00) > да. и еще, тз как всегда неполное. если счетчик адреса теряется > редко, то его хранением вполне можно пренебречь.
Устройство будет эксплуатироваться так - в начале дня приезжаем на поле где будем летать, включаю модель, девайс включается. Я захожу в интерактивное меню(с помощью единственного органа управления) и там делаю сброс счетчика потребленных мА. Устройство сразу начинает считать энергию (мА/час) с нуля(предполагаем что АКб заряжена) и дампить каждые 10 сек в eeprom съеденные мА. Полетав и выключив модель, обесточив девайс и включив снова при следующем полете девайс считывает сохраненное значение съеденных мА и продолжает считать прибавляя к нему расход за следующую сессию пока девайс запитан. Пока девайс работает он все шлет в последовательный порт и на БТ-модуль где я с мабилы могу посмотреть все нужное в реальном времени. Чуть попозжа я еще вопросик задам - есть какой то глюк-мутант в счетчиках и вычислении среднего арифметического. Я не могу никак понять в чем косяк. Надо видео записать с демонстрацией. Вот проект собственной персоной если интересно https://github.com/NailAlex/KillSwitchDuinoЭто сам скетч https://github.com/NailAlex/KillSwitchDuino/blob/master/KillSwitchduino/KillSwitchduino.ino
-
> [30] А при записи счётчика в одну ячейку во сколько раз?
>> Если запись-чтение не идентичны - меняешь адрес счётчика
Можно совместить алгоритмы и не хранить адрес счётчика а искать его при старте по хвостовому маркеру (например, 0xFFFFFFFF, так как при первичной инициализации на подготовку 'базы' нужна будет ~одна команда и ~10ms)
-
> NailMan © (28.01.17 16:13) [33]
ресурсов еепром гарантированно хватит на 11 суток непрерывной работы если писать в одно место. при батарейном питании сбои маловероятны. никакого маркера записывать необходимости нет. если 11 суток непрерывной работы мало, то при включении счетчик адреса устанавливается в ноль, абсолютно пофиг, если до этого он уже десять раз подряд всегда был ноль (то есть девайс включался менее чем на 10 секунд) и всё пишется по кругу.
-
если подвесищь внешнюю еепром, то можешь круглосуточно писать полгода в одно место. соответственно, если летать 2 часа ежедневно, то на 5 лет хватит.
-
Ща напишу скетч с замером скорости чтения и записи в eeprom. А вот еще один вопросец с видеодемонстрацией https://www.youtube.com/watch?v=8ZyyDDmC0bEДевайс получает на пин с аппаратным прерыванием PPM-сигнал(разновидность PWM), который имеет прямой импульс определенной длины(1000-2000мкс) кодирующий положение стика(или тумблера) от 0-100%. Количество импульсов(пакетов) за секунду ВСЕГДА 50 при нормальном приеме. В скетче сделал обработчик прерывания на этом пину(any change) и вычисляется длительность импульса в мкс(точность 4мкс) и определяется тумблер вверх или вниз опущен, плюс считается количество нажатий и самое главное - количество пакетов. Так как счетчик быстрый, там же в обработчике прерывания я определяю максимальное значение счетчика пакетов и потом я в обработчике программного таймера(отрабатывается раз в 250мс) я раз в секунду его обнуляю. Также я суммирую это значение пакетов за одну секунду и вычисляю среднее арифметическое количества пакетов за прошедшую секунду, если качество приема хреновое, то оно будет отличаться от 50, если меньше 1 то сигнал пропал и появляется алерт. В течение работы какое то время все считается нормально, потом среднее значение за секунду становится 32 и нарастает до 50 потом все повторяется(на видео показано). Вот как считаю каждые 250мс(4 раза в сек) MainSWPacketsSum += MaxMainSWPacketsCounter;
if (MainSWCounterReset_time==0) else
MainSWPacketsSum = 0;
MaxMainSWPacketsCounter = 0;
MainSWCounterReset_time = 3;
} else MainSWCounterReset_time--;
Выясняя почему происходит такой сброс я уже мозг сломал раза 2. Переписывал раза 4 счетоводство - все время такая байда получается. Причем в порт вывожу LastMaxMainSWPacketsCounter и LastMainSWPacketsAverage, чтобы сами счетчики не трогать. Никак не пойму в чем косяк.
-
на мой взгляд, невозможно определить косяк, не видя всей картины. хрен знает, что у тебя там с прерываниями, кто кого успевает обработать, а кого нет.
-
* ~одна команда => стирание всего eeprom > глюк-мутантПри чтении/записи 16-битных регистров в/в используется один на весь кристалл скрытый временный регистр. Но перенос в память этих 16-битных регистров не атомарный (два 8-битных mov). А значит может возникнуть ситуация, когда в момент чтения регистров АЦП происходит прерывание, в обработчике которого, например, есть чтение 16-битного таймера с затиранием этого временного регистра. И, кажется, при смени канала АЦП рекомендуют делать одно холостое преобразования для верности. P.S. float Voltage = (RawValue * V_REF * 1000) / 1024.0; и вселенной не грозит тепловая смерть )))
-
> рекомендуют делать одно холостое преобразования для верности
для верности рекомендуют пользоваться аппноутом по ацп конкретного мк.
-
> [38] kilkennycat © (28.01.17 17:09) > на мой взгляд, невозможно определить косяк, не видя всей > картины. хрен знает, что у тебя там с прерываниями, кто > кого успевает обработать, а кого нет.
прерывание всего одно - любое изменение на пине-приемника сигналов. Если пришел HIGH запоминаем значение внутреннего счетчика микросекунд, если LOW - смотрим разницу равную длительности импульса, прибавляю счетчик пакетов и обрабатываю нажатия.
Других прерываний нет. Таймер программный - работает на основне внутреннего счетчика миллисекунд. Увеличивает MaxMainSWPacketsCounter обработчик прерывания, а обнуляет обработчик софт-таймера. Все волатильно объявленно чтобы работать могло в прерываниях.
Толи какая то интерференция появляется и в 1 из 4 значений на суммирование попадает MaxMainSWPacketsCounter=0 и среднее значение уменьшается до 32. но почему тогда оно постепенно повышается, ведь в следующую секунду сумма начинается с нуля считаться и среднее вычисляется аналогично предыдущей секунде? Вот непонятное совсем поведение ломающее мозг.
-
Замерял время чтения/записи eeprom в arduino nano запись 512 байт заняло 3.416с чтение 512 байт заняло на грани разрешающей способности таймера микросекунд - 4мкс.
Что то разница чумовая какая то!
-
> прерывание всего одно
а таймерное? раз накапливается, значит не происходит обнуление. раз не происходит обнуление - значит, не вызывается обработчик обнуления. а раз он не вызывается, значит косяк с прерываниями. либо возврат не туда, либо вытесняется приоритетным.
-
> запись 512 байт заняло 3.416с
невероятно долго. что там за мк на этой ардуине?
-
> [43] kilkennycat © (28.01.17 17:36) > а таймерное? > раз накапливается, значит не происходит обнуление. раз не > происходит обнуление - значит, не вызывается обработчик > обнуления. а раз он не вызывается, значит косяк с прерываниями. > либо возврат не туда, либо вытесняется приоритетным.
таймер софтовый. в начале loop() он апдейтится и если время прошло, то отрабатывается. Сам таймер не мой - сторонний, но они все одинаково сделаны. > [44] kilkennycat © (28.01.17 17:38) > > > запись 512 байт заняло 3.416с > > невероятно долго. что там за мк на этой ардуине? http://arduino.ru/Hardware/ArduinoBoardNanoс ATMega328 которая.
-
> Других прерываний нет. У тебя может и нет, а что там ардуина натыкала?
> Вот как считаю каждые 250мс(4 раза в сек) Как знаешь что прошло =250мс?
Что такое MaxMainSWPacketsCounter?
- На время выполнения куска кода выключи прерывания.
- Форсируй значения получаемые с улицы и смотри на результат.
-
ага, вот > прерывание всего одно -> прибавляю счетчик пакетов(MaxMainSWPacketsCounter++) ? а потом с активным флагом прерывания: ? MainSWPacketsSum += MaxMainSWPacketsCounter;
..
LastMaxMainSWPacketsCounter = MaxMainSWPacketsCounter;
..
MaxMainSWPacketsCounter = 0;
-
-
> [46] NoUser © (28.01.17 18:07) > > Других прерываний нет. > У тебя может и нет, а что там ардуина натыкала?
На пинах могут быть всякие внутренние таймеры для счетчиков и генератора звукового. для пользователя они скрыты, но для Nano вроде ограничений нет в использовании. в Mega2650 там есть некоторые ограничения с прерываниями на определенных пинах из-за такой совмещенки.
> > Вот как считаю каждые 250мс(4 раза в сек) > Как знаешь что прошло =250мс?
Задаю при создании таймера int tickEvent = m_timer.every(250, MainTimerHandler);
пауз не использую внутри. Потому время отработки обработчика зависит только от выполнения кода. Можно сделать замер времени в микросекундах, сколько тратится времени.
> Что такое MaxMainSWPacketsCounter?
В обработчике прерывания на пине: if (MainSWPacketsCounter>MaxMainSWPacketsCounter) {MaxMainSWPacketsCounter=MainSWPacketsCounter;}
если выводить MainSWPacketsCounter в рендер - он будет выдавать разные числа отличные от 50, так как вывод может произойти в произвольное время по отношению к времени подсчета пакетов. Потому я получаю максимальное число пакетов за секунду и вывожу его. если именно связь хреновая, то максимальное число пакетов за секунду будет отличаться от 50, так как чего то не досчитается.
> - На время выполнения куска кода выключи прерывания.
в части вычисления именно среднего арифметического количества пакетов отключать прерывания?
> - Форсируй значения получаемые с улицы и смотри на результат.
не понял
-
> в части вычисления именно среднего арифметического количества > пакетов отключать прерывания?
да. если отключение прерываний не спасёт, то >> Форсируй значения "В обработчике прерывания на пине": MaxMainSWPacketsCounter=50; > если именно связь хреновая, то максимальное число пакетов > за секунду будет отличаться от 50, так как чего то не досчитается
- а это ещё что за вводная? )) - так связь? хреновая или не досчитается?
-
> [50] NoUser © (28.01.17 19:10) > > если именно связь хреновая, то максимальное число пакетов > > > за секунду будет отличаться от 50, так как чего то не > досчитается > > - а это ещё что за вводная? )) > - так связь? хреновая или не досчитается?
так как девайс работает с PPM-сигналом с жестко регламентированными 50гц пакетами длительностью пачки по 20мс(полезный сигнал на единственный канал 1-2мс), то качественная связь если количество пакетов в секунду =50, если <50 - значит хреноватая, если <1 то сигнал лост. Подсчет количества пакетов - это простой способ определения наличия сигнала и его качества. Так как в нынешнем виде сигнал генерирует сам девайс(к нему подключена перемычка сервисного режима и потенциометр), и сигнал сразу переходит с генерирующей ноги на приемную, то сигнал плохим быть не может по определению. При подключении реального приемника без сервисного режима могут быть пропуски если линк между передатчиком и приемником нарушается, но это нужно специально постараться сделать и это не просто.
-
> Подсчет количества пакетов - это простой способ определения > наличия сигнала и его качества
ясно, а что там с noInterrupts()/interrupts() ? .. Смотрю эту ардуину - вместо разгребания завалов дуино-кода есть только желание узнать как туда свой бинарник вдвинуть. ))
-
> [52] NoUser © (28.01.17 19:44) > ясно, а что там с noInterrupts()/interrupts() ?
попробовал - все то же самое, через энное время идет провал в показаниях.
-
теперь добавь Counter=50 и смотрим дальше )
-
Оп, думаю на видео всё ок! Просто синхра плывёт.
Ключевой вопрос "Как знаешь что прошло =250мс?"
Выводи в лог дельту к-н TickCounter-a из MainTimerHandler
у тебя m_timer.every(250, MainTimerHandler); завязан на void loop() { m_timer.update(); .... } и не синхронизирован с таймером, - просто флаг, что прошло ~250 мс. Если, например на 42мс больше, то следующий флаг ты увидишь через 250-42, вот и недочёт в пределах 1 секунды. (Average то у тебя железные 50 )
-
> kilkennycat © (28.01.17 17:18) [40]http://www.atmel.com/Images/Atmel-2545-8-bit-AVR-Microcontroller-ATmega48-88-168_Datasheet.pdf
28.5.1 ADC Input Channels
When changing channel selections, the user should observe the following guidelines to ensure that the
correct channel is selected:
...
• In Free Running mode, always select the channel before starting the first conversion. The channel
selection may be changed one ADC clock cycle after writing one to ADSC. However, the simplest
method is to wait for the first conversion to complete, and then change the channel selection. Since
the next conversion has already started automatically, the next result will reflect the previous
channel selection. Subsequent conversions will reflect the new channel selection.
The user is advised not to write new channel or reference selection values during Free Running mode.
Вспомнил, чтобы эту рекомендацию с датиша обойти, я не учитывал первое измерение после смены канала АЦП в режиме непрерывного преобразования для того, чтобы не потерять синхру преобразований на остановке/перезапуске АЦП.
-
> [55] NoUser © (28.01.17 21:01) > Оп, думаю на видео всё ок! Просто синхра плывёт. > > Ключевой вопрос "Как знаешь что прошло =250мс?" > > Выводи в лог дельту к-н TickCounter-a из MainTimerHandler > > > у тебя > m_timer.every(250, MainTimerHandler); > завязан на > void loop() { > m_timer.update(); > .... > } > и не синхронизирован с таймером, - просто флаг, что прошло > ~250 мс. > Если, например на 42мс больше, то следующий флаг ты увидишь > через 250-42, вот и недочёт в пределах 1 секунды. (Average > то у тебя железные 50 )
Написал базу менеджера еепрома. Сделал так - 6 байт запись: 0xFAFA и 4 байта Float. при смене адреса(+6 байт) старое затираю нулями. При старте ищу FAFA и читаю сохраненку. Так как у меня 480 байт пространство, то выходит 80 смещений, если делать раз в 10 сек то выходит 13 с небольшим минут полета на одну перезапись пространства. Вполне нормально, обычно больше 10-13 мин не летаю(как и многие другие). Ресурс в 100тыс полетов меня устраивает)))) Теперь только разобраться с корректной записью float в еепром и приступить к косяку со считаловом.
Возможно придется сделать какой то свой хитропопый таймер(не хочу во внутренний аппаратный миллисекундный внедряться). Либо проверять что прошло 250мс с предыдущего срабатывания, либо отсчитывать после прохода обработчика. Думается второй даст наращивание времени, а первый будет учитывать длительность работы обработчика(она же разная каждый раз) особенно когда идет запись в еепром - 8мс на байт, а мне при дампе надо записать 6 байт или 12 при смене адреса записи. Все измерения в начале обработчика, вся остальная логика с медленными периодическими действиями в конце. тогда можно считать что по измерениям будет точно 250мс проходить, а тормозным действиям пофиг.
Кста на видео Average как раз плывет, а не Maх, он то как раз и железный. Там так - SwPos(On/Off)|MaxPackets|AverPackets|PressCount
-
>девайс может быть обесточен в любой момент этим моментом может быть запись в EEPROM после чего я бы не поручился что весь EEPROM не будет стерт Так что реши вопрос сначала с этим а уже потом как читать/писать, посмотри поиском на www.electronix.ru может что найдешь
-
> Кста на видео Average как раз плывет- покажи в логе сумму импульсов и время. >>девайс может быть обесточен в любой момент > этим моментом может быть запись в EEPROMвнутри есть сторожевик по питанию - если включен, его хватает чтобы eeprom не портилась, а вот новое фа-фа полностью записать это ... можно так: struct TREC
;
typedef TREC __eeprom EEREC;
typedef EEREC* PEEREC;
void Write(PEEREC pRec, float &Data)
bool Read(PEEREC pRec, float &Data)
-
> [57] NailMan © (29.01.17 20:11) > старое затираю нулями.
В 2 раза ресурс меньше, чем со счётчиком.
-
> внутри есть сторожевик по питанию - если включен, его хватает > чтобы eeprom не портилась
его назначение формирование сброса после установки питания. это как это он умудряется защитить еепром от незавершения операции?
-
> обычно больше 10-13 мин не летаю
менеджер записи ненужен вообще.
-
> [58] GEN++ © (29.01.17 22:07) > >девайс может быть обесточен в любой момент > этим моментом может быть запись в EEPROM после чего > я бы не поручился что весь EEPROM не будет стерт > Так что реши вопрос сначала с этим а уже потом как читать/писать, > > посмотри поиском на www.electronix.ru может что найдешь
Так как девайс имеет трехцветный светодиод с индикацией режимов, я могу на момент записи в еепром моргать ярким синим цветом, чтобы пользователь выключал в 10 сек промежуток.
-
>Так как девайс имеет трехцветный светодиод с индикацией режимов, я могу на момент записи в еепром моргать ярким синим цветом, чтобы пользователь выключал в 10 сек промежуток.
Правильно, любая разработка это разрешение системы компромиссов. Но, поверьте моему опыту, данное решение из серии худших. Закон падающих кирпичей и бутербродов пока никто не отменял.
Здесь надо уметь задерживать падение питание устройства примерно на 50 мл сек по отношению к падению внешнего питания и уметь сообщать о "просадке" питания контроллеру. Само Arduino nano c 19 mA потребления поддерживать на питании не особо правильно. IMHO - сделать в виде мезонина на базе ATtiny24/44/84 (0.3mA при тактовой 1 MHz) внешнюю "умную" и защищенную от пропадания питания EEPROM (либо от ATtiny - 128 байт либо внешнюю). Кстати, при "износе" EEPROM мезонина легко текущий мезонин заменить на новый.
Связь с основным устройством по SPI либо аппаратному либо программному
-
> [64] GEN++ © (30.01.17 13:34) > >Так как девайс имеет трехцветный светодиод с индикацией > режимов, я могу на момент записи в еепром моргать ярким > синим цветом, чтобы пользователь выключал в 10 сек промежуток. > > Правильно, любая разработка это разрешение системы компромиссов. > Но, поверьте моему опыту, данное решение из серии худших. > Закон падающих кирпичей и бутербродов пока никто не отменял. > > Здесь надо уметь задерживать падение питание устройства > примерно на 50 мл сек по отношению к падению внешнего питания > и уметь сообщать о "просадке" питания > контроллеру. Само Arduino nano c 19 mA потребления поддерживать > на питании > не особо правильно. > IMHO - сделать в виде мезонина на базе ATtiny24/44/84 (0.3mA > при тактовой 1 MHz) > внешнюю "умную" и защищенную от пропадания питания EEPROM > (либо от ATtiny - 128 байт либо внешнюю). Кстати, при "износе" > EEPROM мезонина легко текущий мезонин заменить на новый. > > Связь с основным устройством по SPI либо аппаратному либо > программному
Весь девайс сейчас жрет до 372ма(при включенной сирене) и до 150ма при нормальном режиме. В целом можно типа такой бздюльки включить в состав железки http://www.ebay.com/itm/0-047F-5-5V-Memory-Backup-Capacitor-Supercap-/152399363846детектор наличия напряжения во входной сети - не вопрос, можно сбацать по типу как на старших ардуинах детектится и коммутируется питание между Vin/USB. внешние eeprom есть у меня на i2c, на ARM32 контроллере чтобы тоже самое делать(конфиг держать и помнить потребление).
-
> kilkennycat © (30.01.17 07:36) [61] >> внутри есть сторожевик по питанию - если включен, его хватает чтобы eeprom не портилась > его назначение формирование сброса после установки питания.
"для верности рекомендуют пользоваться аппноутом по ацп конкретного мк"
> это как это он умудряется защитить еепром от незавершения операции?
не знаю, я такого не говорил.
-
> NoUser © (30.01.17 14:43) [66]
Ок. давай сначала уточним, что ты имеешь ввиду под "внутри сторожевик по питанию".
-
-
> NoUser © (31.01.17 13:23) [68] > http://fusecalc.mirmk.ru/help/help04.htm
ну и где же тут аппноут ;) Хорошо, уже лучше. стало ясно, какой именно сторожевик по питанию используется. И он по-прежнему формирует сигнал сброса. NoUser © (30.01.17 00:11) [59]
>>девайс может быть обесточен в любой момент > этим моментом может быть запись в EEPROM
внутри есть сторожевик по питанию - если включен, его хватает чтобы eeprom не портилась, NoUser © (30.01.17 14:43) [66] > это как это он умудряется защитить еепром от незавершения операции?
не знаю, я такого не говорил.Нет никаких противоречий?
-
> И он по-прежнему формирует сигнал сброса. И это хорошо, тк при проcадке питания ядро не выполнит какую-нибудь случайную команду, например записи eeprom. ("хватает чтобы eeprom не портилась")
А примитивную реализацию проверки, записан ли полностью пакет данных, я указал. (лучше, конечно же, использовать контрольную сумму)
-
Спасибо всем за участие в главной теме, реализовал менеджер с постоянным адресом
поле для данных 480байт. в пределах заголовка хранятся 2 байта под адрес. Также есть в памяти счетчик дампов, который каждую сессию начинается с начала.
В начале, при инициализации, читаю адрес размещения записи, читаю запись по адресу, сразу увеличиваю адрес +4(сохраняю этот адрес в eeprom) и начинаю цикл. Каждые 10 сек происходит дамп значения мА в eeprom по текущему адресу, спустя 50 циклов увеличиваю адрес +4, сохраняю его, зануляю счетчик дампов и все начинается заново.
Место куда пишется адрес изменяется в 50 раз реже чем дамп. Если я включаю девайс на короткое время(менее чем на 500сек), он сразу сместит адрес для дампа, освежив позицию.
на время пока идет дамп(короткий только значения мА или полный с перезаписью адреса) я моргаю свободной лампочкой. В третьей версии платы я реализую бэкап ардуины с помощью переключателя входного питания и суперконденсатора на 0.33F. Этого должно хватить на дамп и "корректное закрытие". Потом это пригодится на полном контроллере, где придется еще закрывать запись на карту SD.
Останется разобраться с кривотой счета - я это вынесу за пределы таймера и сделаю в основном(быстром) обработчике стейтов. Там же и увеличу частоту считывания тока, так как испытания показали очень резкие изменения значения проходящего тока от 150мА до 7.5А кратковременно(сервы то на парамодели с усилием 45кг на см две штуки стоят).
-
> NoUser © (01.02.17 20:19) [70]
предположим, запись уже началась, то есть идет выполнение команды (это не моментальный процесс), и посреди его питание стало нулем.
-
> [72] kilkennycat © (02.02.17 03:02) > > > NoUser © (01.02.17 20:19) [70] > > предположим, запись уже началась, то есть идет выполнение > команды (это не моментальный процесс), и посреди его питание > стало нулем.
сразу нулем не станет, так как на реальных девайсах есть: 1) сглаживающие емости 10-47мкФ на выходе регулятора питания 5В 2) комплексный С-фильтр(1-0.1-0.01мкФ) непосредственно у самого девайса( и еще у самого МК).
Эти емкости поддержат какое то время напряжение в силу своей инерциальности и накопленного заряда.
-
> NailMan © (02.02.17 10:50) [73] Эти емкости поддержат какое то время напряжение в силу своей инерциальности и накопленного заряда.
тут ключевое слово "какое-то". О фильтре у девайса и самого мк можно вообще забыть, даже в самых экономичных условиях они разрядятся за десятые доли мс (это до 0, то есть, до того момента, когда мк помрет еще меньше времени пройдет). Вспоминаем время обработки операций с еепром - единицы мс. Конечно, 47 мкФ это уже веселее, и может даже вытянуло бы... но есть пару но: во-первых, нет гарантии что он начнет разряжаться прямо перед записью, а во-вторых, у меня предчувствие, что не только мк на нем сидит.
Это, конечно, грубые подсчеты. Но думаю, подсчет точного энергопотребления и потерь еще сильней испортит картину.
-
> NailMan ©
но это я так, придираюсь :) на самом деле, сам бы я плюнул на это: далеко не всегда еепромка сваливается, умножаем это на далеко не всегда пропадающее питание, и вовзводим в степень неособой важности данных - получаем бесконечный пофигизм на данный случай.
-
сделал замер времени выполнения таймерного(каждые 250мс) обработчика где математика идет - тот проход(раз в сек) на котором математика по всем событиям считается выполняется за 25.6мс. Если в этот проход попадает дамп потребления в еепром - 35.6мс, в остальные проходы(когда проходы холостые) - 200мкс.
Вывожу в каждый проход обработчика значения суммы и максимального количества пакетов - сразу видно этот провал в показаниях спустя какое то время. Приду домой - покажу видос.
Сделал обнуление счетчика максимального количества пакетов не в таймерном обработчике, а в обработчике аппаратного прерывания через внешний флаг, который в таймерном присваиваю true, когда надо обнулить. При этом даже откючал прерывание на время этого присваивания, а потом включал - все равно идет провал. была мысля что в обработчике прерывания переменная увеличивается 50раз в секунду и в какой то момент попадает на момент обнуления в таймерном обработчике и получается что сброс гадит счетчику. Но получается что косяк в чет то другом.
-
>kilkennycat >нет гарантии что он начнет разряжаться прямо перед записью,
В Десятку!!....!! Повторюсь: пока не будет надежно защищен процесс записи в EEPROM, разработка ПО будет по принципу "хотели как лучше, а получилось- как получилось"
-
> [77] GEN++ © (02.02.17 19:40) > Повторюсь: пока не будет надежно защищен процесс записи > в EEPROM
Все будет в материнской плате v3.0. Суперкап на 0.2-0.33Ф на 5.5В. Чтоб заряжался минуты 3-4 пока на земле проходит проверки. Поддерживать должон дофига времени. Задетектит пропадание входного питания и завершит запись и перестанет дампить. далее отключение будет безопасным.
-
Если так заморачиваться с надежностью, то всё-таки и еепром надо внешнюю или вообще, как говорил выше GEN++, отдельный логгер.
-
> [79] kilkennycat © (03.02.17 05:04) > Если так заморачиваться с надежностью, то всё-таки и еепром > надо внешнюю или вообще, как говорил выше GEN++, отдельный > логгер.
Сие изделие слишком мало по свои основным задачам чтобы даже суперкап ставить, суперкап будет на полный контроллер. Задача нынешнего девайса - просто удаленно коммутировать грязную цепь, смотреть за напряжением в чистой и пикать когда ее попросят. счет энергии - моя прихоть на будущее и вообще это опция. Полный контроллер(в планах) - это будет уже полноценный бортовой самописец авиационный, с логгированием в 2 места(SD и облако в инете) и сбором 36 параметров с разных устройств и выводом на 3 дисплея. Тут то и придется делать бэкап без вариантов. И eeprom будет внешняя.
-
И то я не очень верю в суперкап - мне проще поставить пальчиковый или мизинчиковый LiOn акк и готовый модуль бустер/зарядник на 1А на питание ардуины. Этот модуль чуть больше гнезда USB на плату и предназначен для создания полноценного повербанка или же заряжаемого бэкапа на датчики всякие с 5В блочком питания. Возможно так будет проще. Когда застендирую девайс - будет время экспериментов.
-
Разобрался я с алгоритмом высчитывания пакетов PPM-сигнала и глюков с подсчетом среднего за секунду. Провели с коллегой сегодня мозговой штурм с разбором кода очень притязательно. Это было нечто.
Вся засада в провалах была в том, что потоки счета пакетов в обработчике аппаратного прерывания и суммирование с вычислением среднего арифметического каждые 250мс были рассинхронизированы. Плюс моя ошибка была в том что я лимитировал счетчик пакетов 50, а не тем сколько было пакетов за прошедшую секунду. В итоге получалось что набегал рассинхрон по времени счета пакетов и инкрементации в сумму и получалось какое то левое значение.
Пределал код так что в аппаратном обработчике счетчик пакетов, и его максимум(после его бэкапа) сбрасывается спустя 1млн микросекунд и вывожу я этот бэкап в порт. никаких сумм и средних значений теперь не нужно - стало все как должно было быть. Теперь можно также определять не только отвал сигнала, но и его RSSI - тобишь выводить в порт шкалой качество сигналов, ведь если за 1млн микросекунд придет 34 пакета, это будет зафиксировано четко.
Вот мне и наука при работе с аппаратными прерываниями, век живи и век учись!
Так что обе проблемы были решены.
|