-
> рекомендуют делать одно холостое преобразования для верности
для верности рекомендуют пользоваться аппноутом по ацп конкретного мк.
-
> [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)
|