Перейти к содержанию
    

Измерение временных интервалов

Не пойму, к чему эти обсуждения наилучшего кода, если задачка поставлена некорректно.

Как уже было отмечено выше, точность 1 ppm на практике (используя типичный кварц) недостижима, поэтому увеличение разрядности счётчика таймера, применение однотактового аппаратного захвата и увеличение частота кварца никак не смогут улучшить ситуацию с относительной точностью измерения (которая в процентах).

А если МК тактирован частотой 1 МГц достаточной точности и имеет аппаратный захват, то задача решается даже на 8-битном таймере, используя только прерывание захвата. А если нужно экономить энергию спящим режимом, то придётся использовать прерывание захвата и прерывание переполнения таймера, причём не обязательно того же самого таймера, по которому производится захват.

Изменено пользователем CD_Eater

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как померять? Используя ГЛИН (генератор пилы) и внутренний АЦП АВРки. Внешней обвязки- два триггера и генератор тока на операционнике.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

все хорошо ребята - мона конечно извращаться с АВР с аппаратным захватом, но тут парень был прав, если в результате возникнет несколько прерываний, то не факт, что все там работает аппаратно, а вы это все понимает - паралельно, но там не все параллельно, проверить просто - забейте проц в постоянное прерывание, а лучше создайте множественные случаи прерывания, проц может просто умереть, у меня так было, и не из-за программы, а потому что сбивалась декодировка кодов внутри этой продвинутой РИСК-архитектуры.

 

:) Вы сами поняли что вы написали???

 

А как вы узнали что "сбивалась декодировка кодов внутри этой продвинутой РИСК-архитектуры" :biggrin:

 

Это мне напоминает рассказ одного рыбака, который рассказывал следующее:

 

Ну бросаю пол-дня -- нифига. Ну потом нацепил наживку в виде лягушки и выбрасываю на берег. И медленно стягиваю в воду. :) Понимаешь она (щука) стоит в воде и ждёт повернувшись мордой к берегу. А тут моя лягушка. :biggrin: Ну и вытащил одну.

 

 

Короче приятно иметь знакомого, который запросто посмотрит внутрь процессора или сквозь толщу воды и заглянет в мозги щуки. А тут мозги подруги жизни (их там не много вроде), и то - сплошные потёмки. :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У меня ситуация, когда память Тини13 (1кь) заполнена на 960 байт, при этом ОЗУ 64 байт и его мало. Та-же прога, но адаптированная к Меге8 работает без проблем (512 байт ОЗУ).

К чему бы это? Размер программы вообще роли не играет, а 64байта ОЗУ + столько же eeprom это на самом деле даже много c учетом, что программа на Asm.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

все хорошо ребята - мона конечно извращаться с АВР с аппаратным захватом, но тут парень был прав, если в результате возникнет несколько прерываний, то не факт, что все там работает аппаратно, а вы это все понимает - паралельно, но там не все параллельно, проверить просто - забейте проц в постоянное прерывание, а лучше создайте множественные случаи прерывания, проц может просто умереть, у меня так было, и не из-за программы, а потому что сбивалась декодировка кодов внутри этой продвинутой РИСК-архитектуры.

 

:) Вы сами поняли что вы написали???

....................................

:bb-offtopic: Дык, посмотрите, откуда парень пишет. У них там анашу на каждом углу продают вполне легально...

Прошу прощенья за оффтоп.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Ну вот, опоздал к началу обсуждения, как всегда, впрочем(:-)

Как можно измерить временные интервалы дительностью несколько секунд на AVRах с точностью до микросекунды? При том что кварц стоит на 1 МГц? Емкости таймера-счетчика 16 бит для такой задачи не хватает...

Задача достаточно простая, а предлагаемые решения, на мой взгляд, слишком сложные. По-моему, сделать надо вот что.

 

Прежде всего, подключить измеряемый сигнал к схеме захвата, на таймер1 подать системный клок и выделить две 3-байтовые переменные, скажем, Т3-Т2-Т1 для хранения времени начала измеряемого интервала и Т6-Т5-Т4 для хранения времени конца интервала.

 

Затем надо написать программу со следующим алгоритмом.

 

1) Обнулить Т3 и Т6.

 

2) Стоять здесь и ждать первого захвата.

 

3) Переписать значение из регистра захвата в Т2-Т1.

 

4) Проверить наличие переноса из таймера1. При наличии переноса добавить единицу к Т6.

 

5) Проверить наличие второго захвата, если нет захвата перейти к п.4.

 

6) После захвата переписать значение из регистра захвата в Т5-Т4.

 

7) Вычислить разность двух переменных Т6-Т5-Т4 и Т3-Т2-Т1, которая даст длительность интервала в микросекундах, если системная частота равна 1 МГц. Выдать результат, куда надо.

 

8) Переписать Т6-Т5-Т4 в Т3-Т2-Т1.

 

9) Перейти к п.4.

 

Трёх байт должно хватить на длительности до 16 секунд, если надо больше, то взять 4-х байтные переменные и т.д. Относительная точность измерения будет определяться только погрешностью системной частоты +-1*Е-6.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

=GM=, использование арифметических операций предполагает различную длину кода при наличии или отсутствии переноса что введет нелинейность по выполненнию программы. Это можно скомпенсировать если алгоритм сделать на ассемблере а все операции засимметрировать там где это нужно noopьами для одинакового времени выполнения при любом внутреннем состоянии счетчиков.

Или же измерив интервал, скорректировать результат посредством прибавления произведения коэффициента ошибок на соответствуюшее им количество переносов , что опять таки предполагает использование ассемблера

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

=GM=, использование арифметических операций предполагает различную длину кода при наличии или отсутствии переноса что введет нелинейность по выполненнию программы. Это можно скомпенсировать если алгоритм сделать на ассемблере а все операции засимметрировать там где это нужно noopьами для одинакового времени выполнения при любом внутреннем состоянии счетчиков.

Или же измерив интервал, скорректировать результат посредством прибавления произведения коэффициента ошибок на соответствуюшее им количество переносов , что опять таки предполагает использование ассемблера

 

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

 

Если честно, ничего не понял, что вы написали(:-(. Какое использование арифметических операций? Измерение делается на аппаратном уровне, от программы требуется только запомнить начальное и конечное время, учесть переносы таймера1, ну и вычислить разность времен, чтобы получить частоту.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Правильно говорите - я то невнимательно прочитал подумал что поллингом считаете а флаги не в счет. Извиняюсь за ошибку. А даташит вообше то говорит Вашими словами .)

 

Можно и не анализировать флаги poll'om (правильно ли я понял?) а все делать в прерываниях, хотя для критического случая совпадения overflow с capture придется таки флаг overflow анализировать при исполнении прерывания в capture - overflow по приоритету ниже чем capture.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подправил немного код GetSmart и defunct

- добавил сохранение SREG в прерываниях

- добавил сброс флага TOV1 в TIFR если делали коррекцию

 

.def  AL = R24
.def  Const0 = R8
.def  Const1 = R9
.def  _Sreg  = R10
....
    ldi   AL, 1
    mov   Const1, AL
    clr   Const0
...

; обработчик Input Capture:
TIM1_CAPT:
    in    _Sreg,SREG
    in    R4, ICR1L
    in    R5, ICR1H
    tst   R5
    brne  _do_not_correct_result
    in    AL, TIFR
    andi  AL, (1 << TOV1)
    breq  _do_not_correct_result
    out   TIFR, AL
    add   R2, Const1
    adc   R3, Const0
_do_not_correct_result:
    mov   R6, R2
    mov   R7, R3
    out   SREG,_Sreg
; <-- 32-х битный результат в четверке регистров R7-R6-R5-R4 (MSB R7)
    reti
     

; обработчик Timer Overflow:
TIM1_OVF:
    in    _Sreg,SREG
    add   R2, Const1; Инкрементировать старшие 16 бит 32-х битного счетчика
    adc   R3, Const0; учет переноса.
    out   SREG,_Sreg
    reti

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Задача достаточно простая, а предлагаемые решения, на мой взгляд, слишком сложные...
Основная проблема, как уже и написал уважаемый CD_Eater, заключается в том, как сделать опорный генератор, чтобы на 1с измеряемого интервала получить погрешность (а не временнОе разрешение) в 1 мкС.

Сама же методика измерения, предложенная в теме, в том числе и Вами, вопросов не вызывает.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Задача достаточно простая, а предлагаемые решения, на мой взгляд, слишком сложные...
Основная проблема, как уже и написал уважаемый CD_Eater, заключается в том, как сделать опорный генератор, чтобы на 1с измеряемого интервала получить погрешность (а не временнОе разрешение) в 1 мкс.

Сама же методика измерения, предложенная в теме, в том числе и Вами, вопросов не вызывает.

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

 

На мой взгляд, погрешность метода (при наличии абсолютно точного генератора) составляет 1 мкс для секундного интервала при 1МГц системном клоке. Естественно, неточность генератора увеличивает погрешность. Хотя тут вопрос, может ли помочь тот факт, что кратковременная нестабильность (на секундном интервале) кварцевого генератора достигает 1Е-9..1Е-12?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Забавно. На этой странице всех повело совсем не в ту степь, о которой тема. Это как дайте кому-нить палец, дак он и всю руку оттяпает. Сам AVR пропал куда-то чтобы разъяснить, но в его вопросе нет слов о стабильности кварцев, а значит этот критерий точности не рассматривается. Есть слова о проце AVR и о 16 битном таймере. Если обращать внимание на них, то ответ уже давно дан положительный. Причём в условиях задачи это получается максимально возможная точность устройства, ну как 10-битный АЦП, у которого реальная точность всегда поменьше 10 бит из-за разных причин. То же и здесь. В силу разного времени прихода фронтов на шкале 1 мкс запросто может возникнуть "ошибка" вплоть до 1 мкс, от которой в данной схеме никак не избавиться. А вот всякие разговоры о точности и стабильности кварцев только дискредитируют авторов и вообще на мой взгляд какое-то балоболство.

 

=GM=

Причём тут кратковременная нестабильность в 1Е-9..1Е-12, если долговременная будет в 10000 раз хуже? Автоподстройки здесь нет и кратковременная нестабильность не спасает. А вообще, точность кварца при изготовлении наверно 1Е-4 и все разговоры о температурной и прочей нестабильности - бред какой-то.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Подправил немного код GetSmart и defunct

- добавил сохранение SREG в прерываниях

- добавил сброс флага TOV1 в TIFR если делали коррекцию

 

.def  AL = R24
.def  Const0 = R8
.def  Const1 = R9
.def  _Sreg  = R10
....
    ldi   AL, 1
    mov   Const1, AL
    clr   Const0
...

; обработчик Input Capture:
TIM1_CAPT:
    in    _Sreg,SREG
    in    R4, ICR1L
    in    R5, ICR1H
    tst   R5
    brne  _do_not_correct_result
    in    AL, TIFR
    andi  AL, (1 << TOV1)
    breq  _do_not_correct_result
    out   TIFR, AL
    add   R2, Const1
    adc   R3, Const0
_do_not_correct_result:
    mov   R6, R2
    mov   R7, R3
    out   SREG,_Sreg
; <-- 32-х битный результат в четверке регистров R7-R6-R5-R4 (MSB R7)
    reti
     

; обработчик Timer Overflow:
TIM1_OVF:
    in    _Sreg,SREG
    add   R2, Const1; Инкрементировать старшие 16 бит 32-х битного счетчика
    adc   R3, Const0; учет переноса.
    out   SREG,_Sreg
    reti

 

Хочу немного покритиковать программу.

 

1) От возникновения прерывания захвата до команды "in AL,TIFR" может пройти от 12 до 15 МЦ, т.е. достаточно много времени, чтобы произошел перенос от переполнения, следовательно, возможна ошибка в определении времени.

 

2) Вполне возможно, что если прерывания TIM1_OVF и TIM1_CAPT возникли в течение указанного периода, то прерывание TIM1_OVF выполнится после TIM1_CAPT и ПОВТОРНО скорректирует результат в r3-r2 (не уверен на все 100, надо проверять).

 

3) Вход в прерывание TIM1_CAPT означает конец интервала измерения и наличие правильного времени в r5-r4 за исключением возможного последнего переноса. Но поскольку перенос из r5-r4 в r7-r6 возможен в одном единственном случае, когда содержимое r5-r4 переходит из состояния 0xFFFF в 0x0000, содержимое регистров r5-r4 надо проверять на 0.

 

В соответствии со сказанным ниже приведена исправленная программа обработки.

.def       temp   =r16
.def       savreg  =r10

; обработчик Input Capture:
TIM1_CAPT: in     savreg,SREG
           in     R4,ICR1L    ;точные два младших
           in     R5,ICR1H    ;байта времени
           movw   r6,r2       ;два старших байта времени
           mov    temp,r4     ;с возможным переносом
           or     temp,r5     ;во время захвата
           brne   nocarry     ;не было переноса
           subi   r6,-1       ;учтем
           sbci   r7,-1       ;перенос
nocarry:   out    SREG,Sreg
           reti

; обработчик Timer Overflow:
TIM1_OVF:  in     savreg,SREG
           subi   r2,-1       ;
           sbci   r3,-1       ;
           out    SREG,savreg
           reti

 

Ну и последнее, в подобных случаях предпочитаю использовать конструкцию

           subi   r2,-1       ;
           sbci   r3,-1       ;

Вместо эквивалентной

           add    R2,сonst1   ;
           adc    R3,сonst0   ;

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

           mov    temp,r4    ;с возможным переносом
           or     temp,r5    ;во время захвата
           brne   nocarry    ;не было переноса

Плохая идея. Хуже чем было. Там (r5:r4) может быть и 10 и 100, если например выполнялось третье высокоприоритетное прерывание. А после его завершения началось прерывание CAPT.

-----------

PS. У кого длиннее? :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...