Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Эмуляция энкодера.
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Jenya7
Что бы проверить работу таймера в режиме энкодера я решил эмулировать на двух ножках AB сигналы.
Код
void TIM7_IRQHandler(void)
{
   switch (enc_state)
   {
       case 0:
           GPIOF->BSRR = GPIO_Pin_9;   //1
           GPIOF->BRR = GPIO_Pin_10;   //0
       break;
       case 1:
           GPIOF->BSRR = GPIO_Pin_9;   //1
           GPIOF->BSRR = GPIO_Pin_10;  //1
       break;
       case 2:
           GPIOF->BRR = GPIO_Pin_9;   //0
           GPIOF->BSRR = GPIO_Pin_10; //1
       break;
       case 3:
           GPIOF->BRR = GPIO_Pin_9;   //0
           GPIOF->BRR = GPIO_Pin_10; //0
       break;
   }
  
   if(enc_state == 3)
     enc_state = 0;
   else
     enc_state++;
  
   TIM7->SR = 0;
}

По идее должно работать как на картинке, сигналы сдвинуты на 90 градусов, но на скопе я вижу сигналы в одной фазе. Это скоп так показывает или у меня ошибка?
k155la3
Задайте состояния выходов для энкодера таблицей.
И прокручивайте ее по кругу - наиболее приближенная к реальному энкодеру эмуляция.
(закрашенные сектора на диске - таже таблица)
Jenya7
Цитата(k155la3 @ Jul 24 2017, 11:03) *
Задайте состояния выходов для энкодера таблицей.
И прокручивайте ее по кругу - наиболее приближенная к реальному энкодеру эмуляция.
(закрашенные сектора на диске - таже таблица)

это то что я делаю в коде - прокручиваю состояния каждый тайм слот (1-2-3-4).

снизил частоту и подключил светодиоды на выходы. мигают одновременно. значит скоп тут не виноват.

пробовал выставлять выход через ODR
Код
void TIM7_IRQHandler(void)
{
   switch (enc_state)
   {
       case 0:
           //ENC_PORT->BSRR |= ENC_PIN_A;  //1
           //ENC_PORT->BRR |= ENC_PIN_B;   //0
           ENC_PORT->ODR = 0x200;
       break;
       case 1:
           //ENC_PORT->BSRR |= ENC_PIN_A;  //1
           //ENC_PORT->BSRR |= ENC_PIN_B;  //1
             ENC_PORT->ODR = 0x600;
       break;
       case 2:
           //ENC_PORT->BRR |= ENC_PIN_A;   //0
           //ENC_PORT->BSRR |= ENC_PIN_B;  //1
           ENC_PORT->ODR = 0x400;
       break;
       case 3:
           //ENC_PORT->BRR |= ENC_PIN_A;   //0
           //ENC_PORT->BRR |= ENC_PIN_B;   //0
         ENC_PORT->ODR = 0x000;
          
       break;
   }
  
   if(enc_state == 3)
     enc_state = 0;
   else
     enc_state++;
  
   TIM7->SR = 0;
}

тот же результат

если я ставлю 4 брекпойнта - в каждом кейсе - то я вижу что состояния выходов меняются по таблице (10 11 01 00). но когда код бежит они мигают одновременно.
k155la3
скорее всего глючек не в приведенном коде, а "наружи",
в виде "накладки" нескольких выдач в порт.
Попробуйте максимально "растянуть" осцилграфом импульсы, и ВОЗМОЖНО найдутся утерянные
фазы выдачи.
Jenya7
Цитата(k155la3 @ Jul 24 2017, 12:13) *
скорее всего глючек не в приведенном коде, а "наружи",
в виде "накладки" нескольких выдач в порт.
Попробуйте максимально "растянуть" осцилграфом импульсы, и ВОЗМОЖНО найдутся утерянные
фазы выдачи.

я вывел ножки на светодиоды. частота мигания раз в 4 секунды. тут невооруженным глазом все видно. что интересно что по брейкпоинтам отрабатывается правильно - первый зажигается потом второй первый гаснет потом второй. а без остановок зажигаются и гаснут одновременно.
Эдди
А таймер случайно в ту же ногу не выдает импульсы?
Jenya7
Цитата(Эдди @ Jul 24 2017, 12:38) *
А таймер случайно в ту же ногу не выдает импульсы?

нет. я вижу два светодиода мигают.
esaulenka
Тут прерывание срабатывает два раза.
После команды сброса флажка прерывания надо что-то типа __DSB(); или просто несколько nop'ов.
Jenya7
Цитата(esaulenka @ Jul 24 2017, 12:57) *
Тут прерывание срабатывает два раза.
После команды сброса флажка прерывания надо что-то типа __DSB(); или просто несколько nop'ов.

О! __DSB(); помогло, спасибо. а что эта инструкция делает?

описание такое
Цитата
The Data Synchronization Barrier (DSB) acts as a special kind of memory barrier. The DSB operation will complete when all explicit memory accesses before this instruction have completed. No instructions after the DSB will be executed until the DSB instruction has completed, that is, when all of the pending accesses have completed.


но как это влияет на обработку прерывания?
esaulenka
Никогда _достаточно_ глубоко не разбирался, но суть в том, что флажок прерывания где-то застревает на несколько тактов. Если он сбрасывается последней инструкцией в обработчике, есть высокая вероятность, что контроллер прерываний решит, что он всё ещё установлен, и вызовет обработчик ещё раз.
Jenya7
Цитата(esaulenka @ Jul 24 2017, 13:47) *
Никогда _достаточно_ глубоко не разбирался, но суть в том, что флажок прерывания где-то застревает на несколько тактов. Если он сбрасывается последней инструкцией в обработчике, есть высокая вероятность, что контроллер прерываний решит, что он всё ещё установлен, и вызовет обработчик ещё раз.

понял. спасибо.

если сбрасывать флаг TIM7->SR = 0; вначале прерывания а не в конце тоже помогает. чудеса.
Эдди
А частота какая? Странно, что такой небольшой кусок кода не успевает выполниться между переполнениями таймера.
Jenya7
Цитата(Эдди @ Jul 24 2017, 15:25) *
А частота какая? Странно, что такой небольшой кусок кода не успевает выполниться между переполнениями таймера.

до 4kHz выставлял

я тут подумал. есть моторы с высокими RPM. у меня может произойти переполнение счетчика на полном прогоне. я что то не нашел опции прескейлера входной частоты.
k155la3
Цитата(Jenya7 @ Jul 24 2017, 13:53) *
. . .
я тут подумал. есть моторы с высокими RPM. у меня может произойти переполнение счетчика на полном прогоне. я что то не нашел опции прескейлера входной частоты.

я посмотрел бы на приоритеты прерываний + errata.pdf sm.gif
ps - А что за чип ?



Jenya7
Цитата(k155la3 @ Jul 24 2017, 16:46) *
я посмотрел бы на приоритеты прерываний + errata.pdf sm.gif
ps - А что за чип ?

а при чем тут прерывания.
чип STM32F303VCT6. при частоте энкодера 400 герц счетчик переполняется за минуту. у меня может возникнуть система с большим прогоном , больше минуты. логически было предположить что входные сигналы A/B можно поделить чтоб увеличить дальность. но я такой опции не нашел.
Эдди
Заведите отдельный счетчик, и в прерывании UE инкрементируйте/декрементируйте, смотря в какую сторону прерывание произошло.
Jenya7
Цитата(Эдди @ Jul 24 2017, 18:33) *
Заведите отдельный счетчик, и в прерывании UE инкрементируйте/декрементируйте, смотря в какую сторону прерывание произошло.

ну это да. как вариант. но это уже не полностью аппаратное решение.
Эдди
Можно почитать ST'шный RM по поводу связывания таймеров. Только я сомневаюсь, что оно автоматом в обе стороны будет работать.
Еще есть в интернете уйма инструкций, но их или на хале, или на spl пишут, что совсем некошерно.
RM от ST так и говорит: ведомый таймер будет инкрементировать счетчик по каждому событию UPD, а оно генерится как в "плюс", так и в "минус", т.е. без софтовой проверки регистра счетчика в прерывании не обойтись. Ну и вопрос еще - как обрабатывать "дрыгание" энкодера вблизи нуля.
uriy
Для генерации такого сигнала не нужны никакие прерывания.
Нужно запустить таймер в режиме Output compare mode OCxM=011 (toggle on match)
Вот тут есть кое что http://www.micromouseonline.com/2016/02/05...le-phase-stm32/
Для себя делал на CubeMX. Тоже нужно было эмулировать энкодер 3 фазный.
Александр1986
Всем привет. Ребята помогите разобраться с маркировкой сервопривода. Что это означает: 19bit M-Turn Abs ???
XVR
Цитата(Александр1986 @ Aug 15 2017, 13:40) *
Всем привет. Ребята помогите разобраться с маркировкой сервопривода. Что это означает: 19bit M-Turn Abs ???

Видимо обозначает, что это не сервопривод rolleyes.gif
Возможно это энкодер, а обозначает видимо - 19 бит, многооборотный, абсолютный. Что в свою очередь обозначат, что энкодер выдает абсолютное угловое положение на 19 битной параллельной шине и крутить его можно как угодно, внутренних упоров нет.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2024 Invision Power Services, Inc.