Многозадачность таймера

Обсуждаем контроллеры компании Atmel.
Ответить
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2309
Зарегистрирован: Пт июл 17, 2009 07:34:07
Откуда: Свердловская обл.

Сообщение uwrtey »

Немного воды:
Делаю дистанционное 3-канальное пропорциональное управление для игрушечного вертолета.
Передатчик посылает ppm сигнал. ( передатчик уже готов, по этому про него молчу )
А вот приемник я пытаюсь сделать на Тини2313, и у меня очень остро не хватает ресурсов этого МК ( а если быть точнее, то у меня не хватает смекалки )
Дело в том, что к микроконтроллеру прицеплен сервопривод для управления по тангажу и два мотора для управления тягой и курсом ( вертолет соосной схемы )
Для управления моторами я хочу сделать два аппаратных ШИМа на таймере_0 ( по этому - таймер_0 пока не трогаем )
Для управления сервоприводом, я соорудил аппаратный ШИМ на таймере_1 и на этом же таймере хочу сделать замер длительности входящих импульсов ( PPM )
Но у меня не получается измерять длительность входящего импульса не сбрасывая таймер! ( таймер сбрасывать нельзя! На нем же ШИМ работает - генерация портится ... )

Если кому интересно то вот тут можно глянуть всю историю разработки этого проекта.

в приложении код который я соорудил, но он:
во первых: обрезан до безобразия... из него вырезана обработка длительности первого и второго канала ( вырезано управление двигателями )
во вторых: измерение длительности сделано неверно...
для радиокот.txt
(11.81 КБ) 272 скачивания
Вот собственно вопрос: как измерять длину входящего импульса с помощью таймера, на котором организован аппаратный ШИМ ???
длительность импульса я измеряю по захвату на ICP.....

Заранее благодарен Всем, кто не прошел мимо и протянул руку помощи!
не зная броду не лезь к вольтмоду
Реклама
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

По внешнему прерыванию сохраняем текущее значение таймера и вычитаем из него значение при предыдущем внешнем прерывании, получится период в тиках таймера.
Контактная информация:
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

Также добавить обработчик по переполнению таймера, в котором считать количество переполнений, на тот случай, если длительность сигнала окажется больше периода ШИМа или если следующий синхроимпульс наступит в следующем периоде, а при расчете длительности учитывать это.
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

Переполнение нужно считать обязательно. И даже не только из-за того, что длительность импульса может быть больше периода таймера, а за-за того, что импульс может начаться очень близко к переполнению таймера. Таймер же крутится постоянно, без ресета.
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Друг Кота
Аватара пользователя
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск

Сообщение Леонид Иванович »

Только нужно учесть, что возможна накладка событий переполнения и захвата, тогда первым будет выполняться обработчик прерывания по захвату, и переполнение будет потеряно. Такую ситуацию нужно отслеживать и корректировать количество переполнений.
Контактная информация:
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2309
Зарегистрирован: Пт июл 17, 2009 07:34:07
Откуда: Свердловская обл.

Сообщение uwrtey »

1) длительность сигнала не может быть больше периода ШИМа
Здесь период ШИМа равен длительности всего пакета ( канал_0 + канал_1 + канал_2 + синхроимпульс ) = 0,02 сек

2) обычно таймер_1 считает до 65536, но в моем случае таймер тикает всего до 40000 - это обусловлено частотой ШИМа
как же мне здесь организовать вычисление если возникнет переполнение ???
не зная броду не лезь к вольтмоду
Реклама
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

Переполнение должно возникнуть при достижении таймером вершины, т.е. OCR1A
Модератор
Аватара пользователя
Сообщения: 4614
Зарегистрирован: Чт мар 18, 2010 23:09:57
Откуда: Планета Земля

Сообщение Аlex »

как же мне здесь организовать вычисление если возникнет переполнение ???
Считать кол-во переполнений и, при подсчёте периода, умножать это число на 40000.
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск

Сообщение Леонид Иванович »

uwrtey писал(а):2) обычно таймер_1 считает до 65536, но в моем случае таймер тикает всего до 40000 - это обусловлено частотой ШИМа как же мне здесь организовать вычисление если возникнет переполнение ???
Что-то типа такого:

a - первый захват
b - второй захват

if(b > a) t = b - a;
else t = 40000 - a + b;
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2309
Зарегистрирован: Пт июл 17, 2009 07:34:07
Откуда: Свердловская обл.

Сообщение uwrtey »

Спасибо Всем... Ответы на основные вопросы я получил.
Если, что-то спрошу еще раз тут.
:beer:
не зная броду не лезь к вольтмоду
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2309
Зарегистрирован: Пт июл 17, 2009 07:34:07
Откуда: Свердловская обл.

Сообщение uwrtey »

вот, что у меня получилось
для радиокот.txt
(13.47 КБ) 237 скачиваний
но, что-то эта программа не работает как нужно ( сервопривод дергается как шальной ) - разбираюсь....
// на сервопривод выводятся очень странные длительности
не зная броду не лезь к вольтмоду
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

uwrtey писал(а): // на сервопривод выводятся очень странные длительности
Не хватает вектора прерывания по переполнению таймера1 и обработчика, в нем нужно создать переменную и увеличивать на единицу при каждом переполнении и сразу на выход, затем по прерыванию ICP1_interruption проверять эту переменную и расчитывать длительность периода сигнала так:
Если кол-во переполнений не ноль, тогда длительность будет равна:
Вершина таймера (OCR1A) минус предыдущее значение ICR (переменная) плюс новое значение ICR плюс (количество переполнений минус 1)*вершину таймера или
OCR1A - old_ICR + new_ICR + (t1_ovf - 1) * OCR1A .
Если кол-во переполнений равно ноль, тогда длительность будет равна:
new_ICR - old_ICR .

P.S. Начальная иниц-я:
old_ICR=0
new_ICR=0
t1_ovf=0


На входе в прерыванме ICP1_interruption:
new_ICR=регистр ICR1

Перед выходом из прерывания ICP1_interruption:
old_ICR=new_ICR
t1_ovf=0
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2309
Зарегистрирован: Пт июл 17, 2009 07:34:07
Откуда: Свердловская обл.

Сообщение uwrtey »

zero648 писал(а):Не хватает вектора прерывания по переполнению таймера1 и обработчика,
Я решил обойтись без прерывания по переполнению. Просто может возникнуть ситуация, когда одновременно произойдут события которые вызывают прерывание по переполнению и прерывание по захвату ( ICP1_interruption ).
Я решил пойти путем, который на мой взгляд проще:
Я сравниваю текущее значение счетчика и значение которое было записано в прошлый раз.
Если текущее значение больше сохраненного в прошлый раз, то считаем так: new_ICR - old_ICR
а если текущее значение меньше сохраненного в прошлый раз, ( значит было переполнение ) то считаем так: OCR1A - old_ICR + new_ICR

********************

кстати, а зачем в твоем варианте вот это действие + (t1_ovf - 1) * OCR1A ???
вот это (t1_ovf - 1) всегда равно нулю :)
соответственно, это + (t1_ovf - 1) * OCR1A - тоже самое, что это +0

шутка что ли такая ? :)))
не зная броду не лезь к вольтмоду
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

Внес так сказать в формулу для универсальности, если длительность сигнала больше периода ШИМа, но если длительность строго меньше периода ШИМа, тогда конечно можно игнорировать.

В том случае если наступает одновременно два события по прерыванию, то первым сработает с большим приоритетом - это будет ICP1_interruption, в таком случае просто на входе в прерывание проверяем бит TOV1 регистра TIFR и просто сбрасываем его вручную TIFR=(1<<TOV1).
Модератор
Аватара пользователя
Сообщения: 13490
Зарегистрирован: Ср ноя 26, 2008 16:34:25
Откуда: Тамбовская обл.

Сообщение ploop »

Переполнение нужно считать обязательно. И даже не только из-за того, что длительность импульса может быть больше периода таймера, а за-за того, что импульс может начаться очень близко к переполнению таймера. Таймер же крутится постоянно, без ресета.
С беззнаковыми выражениями всё будет работать корректно (если длительность не больше периода таймера)
Пусть предыдущее = 250 (8 бит)
Текущее = 4
Длительность = 4-250 = 10 тиков.
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2309
Зарегистрирован: Пт июл 17, 2009 07:34:07
Откуда: Свердловская обл.

Сообщение uwrtey »

zero648 писал(а):Внес так сказать в формулу для универсальности
ЗдОрово! :beer:
zero648 писал(а):В том случае, если наступает одновременно два события по прерыванию, то первым сработает с большим приоритетом - это будет ICP1_interruption, в таком случае просто на входе в прерывание проверяем бит TOV1 регистра TIFR и просто сбрасываем его вручную TIFR=(1<<TOV1).
такое я еще не делал ...
То-есть проверяем TOV1 и если он равен нулю, то это значит, что ( было переполнение ) наступило два прерывания одновременно ?
не зная броду не лезь к вольтмоду
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

Если было прерывание переполнения то TOV1=1, просто сбрасываются флаги единицей.
Друг Кота
Аватара пользователя
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск

Сообщение Леонид Иванович »

Ну а если переполнение произошло позже захвата, но раньше проверки флага TOV1? Тогда, сбросив флаг, мы потеряем переполнение, и следующий интервал будет измерен неправильно.
Контактная информация:
Вымогатель припоя
Аватара пользователя
Сообщения: 650
Зарегистрирован: Пн июн 18, 2012 12:01:04
Откуда: Челябинская область, Копейск

Сообщение zero648 »

Да, думаю, что лучше этот флаг оставить в покое, даже если будет такая ситуация, когда включатся оба флага одновременно, все равно флаг TOV1 мы уже будем учитывать в следующем прерывании захвата, поэтому все должно быть ровно. Единственно, что если переполнение сработает на один такт раньше захвата, в этом случае у нас будет расчитана длина импульса с погрешностью на время обработки переполнения, то этот обработчик можно залепить прямо в таблице векторов и выделить целый регистр, а не переменную, если конечно следующий по таблице вектор нам не нужен, типа вот так:

.org OVF1addr
inc t1_ovf
reti
Друг Кота
Аватара пользователя
Сообщения: 4779
Зарегистрирован: Сб апр 02, 2011 12:40:46
Откуда: Минск

Сообщение Леонид Иванович »

zero648 писал(а):если переполнение сработает на один такт раньше захвата, в этом случае у нас будет расчитана длина импульса с погрешностью на время обработки переполнения
Не понял, при чем здесь длительность обработчика? Захват производится аппаратно, не важно, что в это время выполняется.

Что касается потерянного переполнения, то требуется коррекция. И дело не только в точном совпадении событий захвата и переполнения. В сиситеме может быть разрешено какое-то третье прерывание, или могут быть участки программы, где прерывания запрещаются. Если в это время произойдут события захвата и переполнения, их обработка будет отложена. Затем первым будет обрабатываться событие захвата. Вот здесь надо проверять, есть ли флаг переполнения и корректировать число захватов. Более того, нужно проверять, установился флаг переполнения до захвата (тогда корректировать надо), или после захвата (тогда корректировать не надо). Сделать такую проверку можно по захваченному значению. Если, скажем, захвачено число меньше половины максимального кода таймера, значит переполнение произошло до захвата. Соответственно, это всё будет работать только тогда, когда длительность обработчиков третьих прерываний или время запрета прерываний не превышает половины периода таймера. Вот код обработчиков прерывания захвата и переполнения из программы тахометра:
Спойлер

Код: Выделить всё

//------------------------- Прерывание по захвату: ---------------------------

#pragma vector = TIMER1_CAPT_vect
__interrupt void Timer_Cap(void)
{
  switch(State)
  {
  case FM_START:                     //фаза запуска измерения частоты
    {
      Tb = ICR1;                     //захват таймера в начале интервала
      Tn = 0;                        //инициализация количества переполнений
      if(Tb < MAX_CNT && (TIFR & (1 << TOV1)))
        Tn--;              //коррекция, если переполнение было до захвата
      Np = 0;                        //инициализация количества импульсов
      State = FM_COUNT;              //переход к фазе измерения частоты
      break;
    }
  case FM_COUNT:                     //фаза измерения частоты
    {
      Np++;
      break;
    }
  case FM_STOP:                      //фаза завершения измерения частоты
    {
      Te = ICR1;                     //захват таймера в конце интервала
      if(Te < MAX_CNT && (TIFR & (1 << TOV1)))
        Tn++;              //коррекция, если переполнение было до захвата
      Np++;
      State = FM_DONE;               //измерение частоты закончено
      break;
    }
  }
}

//----------------------- Прерывание по переполнению: ------------------------

#pragma vector = TIMER1_OVF_vect
__interrupt void Timer_Ovf(void)
{
  if((State == FM_COUNT) || (State == FM_STOP)) Tn++; //подсчет переполнений
}
Контактная информация:
Ответить

Вернуться в «AVR»