Энкодер и STM32

Кто любит RISC в жизни, заходим, не стесняемся.
a797945
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

Re: Энкодер и STM32

Сообщение a797945 »

Если что - я никого ни к чему не призываю. ;)
Просто вспомнил и написал - как когда-то решил проблему быстородействия процедуры опроса энкодера и при этом еще получил эргономику, какую хотел. Давно дело было и было на avr.
Реклама
auric
Открыл глаза
Сообщения: 79
Зарегистрирован: Ср апр 17, 2019 12:04:23

Re: Энкодер и STM32

Сообщение auric »

[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4101099#p4101099"][uquote="auric",url="/forum/viewtopic.php?p=4101050#p4101050"]и тут на тебе - контроллер считает импульсы - а должен один добавить и тут же по спаду убавить.[/uquote]
Значит, у тебя таймер неправильно настроен. Т.к. в такой ситуации он должен просто на ±1 дрожать!
Я в этих ваших калокубах не понимаю. Поэтому в код и не смотрю. Ну и да: кто сказал, что в самом калокубе нет ошибок?
Привожу код из сниппета:

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

static inline void timers_setup(){
    RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
    /* (1) Configure TI1FP1 on TI1 (CC1S = 01)
           configure TI1FP2 on TI2 (CC2S = 01) */
    /* (2) Configure TI1FP1 and TI1FP2 non inverted (CC1P = CC2P = 0, reset value) */
    /* (3) Configure both inputs are active on both rising and falling edges
          (SMS = 011), set external trigger filter to f_DTS/8, N=6 (ETF=1000) */
    /* (4) Enable the counter by writing CEN=1 in the TIMx_CR1 register. */
    TIM3->CCMR1 = TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0; /* (1)*/
    /* (2) */
    TIM3->SMCR =  TIM_SMCR_ETF_3 | TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1; /* (3) */
    // enable update interrupt
    TIM3->DIER = TIM_DIER_UIE;
    // set ARR to 79 - generate interrupt each 80 counts (one revolution)
    TIM3->ARR = 79;
    // enable timer
    TIM3->CR1 = TIM_CR1_CEN; /* (4) */
    NVIC_EnableIRQ(TIM3_IRQn);
}
Фильтрация настроена?[/uquote]
хочу пообсуждать данный код в разрезе эффективности именно этого фильтра ETF для интерфейса энкодера, кто что думает, я лично считаю, что настройка регистра TIM3->SMCR привязана к External тактированию, собственно с этим сигналом фильтр и работает, а также прескалер на него действует. По идее с энкодерными входами должны работать регистры CCMR1(2) в режиме инпут пинов (каналов как входов). Затем после фильтрации получаться TI1FP1 и TI1FP2, которые и являются тактирующими. Вот только не пойму, как в данном случае должен работать прескалер судя по такой картинке
Изображение
первым работает фильтр выборок, но не совсем понятно, как здесь участвует прескалер, хорошо, если делит частоту таймера по шине и задает этот f_TDS на выборки, а может вообще не делит. Далее выбор фронта или спада (кстати в CIMSIS есть TIM_ICPolarity_BothEdge, который по сути у меня не работает в силу отсутствия аппаратной поддержки).
Почему задумался, да потому что дребезг я отфильтровать расчетным путем не смог, хотел ограничить частотой 70кГц, а в итоге флаг прерывания ловлю даже не досчитав

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

		if (CNT_EN){
			if ((CNT_TIM3_old==1)&&(cnt_dir!=1)&&(TIM3_CNT > 32767))
				CNT_Val_Reg = (s32)(CNT_Val_Reg - 65536), CNT_TIM3_old = 65534, cnt_dir = 1;
			if ((CNT_TIM3_old==65534)&&(cnt_dir!=2)&&(TIM3_CNT < 32767))
				CNT_Val_Reg = (s32)(CNT_Val_Reg + 65536), CNT_TIM3_old = 1, cnt_dir = 2;
		}
и это на 72 МГц частоте.
Хотя настройку на ETF тоже делаю из соображений гарантированности и обыкновенного маразма.
ПыСы: короче ICPrescaler вообще убрал от греха, CKD в регистре SR1 сделал свое дело.

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

 			TIM_ICInitTypeDef TIM_ICInitStructure;

 			//Enter the content in the structure by default
 			TIM_ICStructInit(&TIM_ICInitStructure);
 			//выбрать входной терминал IC1
 			TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
 			//Захват фронт
 			TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
 			//сопоставлен с TI1
 			TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
 			//Настроить входное частотное деление замеряемого сигнала, не делим чтоб не потерять
 			TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
 			//filter value fSAMPLING=fDTS/32, выборка N=8.
 			TIM_ICInitStructure.TIM_ICFilter = 15;
 			//Initialize the specified parameters in TIM_ICInitStructure TIM3
 			TIM_ICInit(TIM3, &TIM_ICInitStructure);
Реклама
tonyk
Это не хвост, это антенна
Сообщения: 1323
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Re: Энкодер и STM32

Сообщение tonyk »

да потому что дребезг я отфильтровать расчетным путем не смог
А посмотреть его осциллографом, измерить длительность и отфильтровать с помощью RC-фильтра и триггера Шмитта не пробовал? Глядя на структуру таймера, я не вижу там настоящего фильтра дребезга, поэтому, ИМХО, твои попытки отфильтровать дребезг были априори обречены на неудачу.
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Энкодер и STM32

Сообщение Eddy_Em »

По этой SPL'ной мешанине вообще непонятно, что там происходит. Но что-то очень похоже, что таймер вообще не в режиме энкодера инициализирован, а в тупом режиме счета по одному каналу!
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Реклама
Эиком - электронные компоненты и радиодетали
auric
Открыл глаза
Сообщения: 79
Зарегистрирован: Ср апр 17, 2019 12:04:23

Re: Энкодер и STM32

Сообщение auric »

[uquote="tonyk",url="/forum/viewtopic.php?p=4107770#p4107770"]
да потому что дребезг я отфильтровать расчетным путем не смог
А посмотреть его осциллографом, измерить длительность и отфильтровать с помощью RC-фильтра и триггера Шмитта не пробовал? Глядя на структуру таймера, я не вижу там настоящего фильтра дребезга, поэтому, ИМХО, твои попытки отфильтровать дребезг были априори обречены на неудачу.[/uquote]
Ну сейчас получилось, дребезг и так таймером обсчитывается, не могу только "быстрый" настолько, что не успеваю выйти из прерывания, потому и выставил верхнюю границу в 70кГц - ее хватает за глаза. Про осцил - если честно такие частоты надо задавать, а не ловить, осцил есть, а вот генератора нема, потому и шел расчетным путем. По поводу дребезга - и работы с RC и триггерами - все это конечно необходимо НО, если сигнал реально идет с частотой 70 кГц, зачем мне его гасить, система должна справляться, а вот то что не попало в диапазон, можно, но для надежности и программа тоже должна справляться.

Добавлено after 8 minutes 22 seconds:
[uquote="Eddy_Em",url="/forum/viewtopic.php?p=4107799#p4107799"]По этой SPL'ной мешанине вообще непонятно, что там происходит. Но что-то очень похоже, что таймер вообще не в режиме энкодера инициализирован, а в тупом режиме счета по одному каналу![/uquote]
не по одному, а по двум, на втором аналогичная настройка и это никакого отношений к настройке интерфейса энкодера не имеет - это настройка фильтра - она же по совместительству настройка capture. Настройка энкодера идет в битах SMS.
Реклама
tonyk
Это не хвост, это антенна
Сообщения: 1323
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Re: Энкодер и STM32

Сообщение tonyk »

Странная логика. У тебя идёт дребезг с энкодера. Не зная параметров дребезга, ни программно, ни аппратно его не возможно подавить. Без подавления дребезга просто не понятно, что там насчитает таймер.

Добавлено after 2 minutes 23 seconds:
Покажи осциллограмму сигналов с энкодера.
Реклама
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Энкодер и STM32

Сообщение Eddy_Em »

А у меня вопрос: что в битах CKD регистра TIM3->CR1? Если там по нулям, то fDTS = fCK_INT, т.е. фильтр просто может и не отработать... А вот если туда двоечку записать, то fDTS будет в четыре раза меньше fCK_INT… А это — уже не 48МГц, а 12МГц. Т.е. при фильтрации fDTS/32 N=8 получим, что таймер будет отсекать все шумы выше ~46.9кГц.
И еще: если на PCLK (APB) нет важной периферии, можно APB prescaler загнать в 1/16, в этом случае fCK_INT будет равна HCLK/8, т.е. 6МГц, если AHB шурует на 48 (только учесть это при конфигурации усартов и прочей периферии, сидящей на APB).
Ну и совсем уж в качестве экспериментов, можно AHB притормозить. Правда, при этом затормозится еще и обращение к памяти, DMA и т.д., и т.п.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Энкодер и STM32

Сообщение Dimon456 »

Eddy_Em, глянь мой код
Спойлер

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

	RCC->AHBENR |= RCC_AHBENR_GPIOAEN; //включить тактирование порта AHB = 48 

	/** TIM3 GPIO Configuration
		 PA6	 ------> TIM3_CH1
		 PA7	 ------> TIM3_CH2
	*/

	// настройка вывода PA6
	  GPIOA->MODER &= ~(GPIO_MODER_MODER6);
	  GPIOA->MODER |= (GPIO_MODER_MODER6_1);	//10 Alternate
	  GPIOA->PUPDR |= GPIO_PUPDR_PUPDR6_0; 		//01 Alternate Function PP Pull-up
	  // настройка вывода PA7
	  GPIOA->MODER &= ~(GPIO_MODER_MODER7);
	  GPIOA->MODER |= (GPIO_MODER_MODER7_1);
	  GPIOA->PUPDR |= GPIO_PUPDR_PUPDR7_0; //01

	/*Configure GPIO pin alternate function */
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_1);
	/*Configure GPIO pin alternate function */
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_1);

	RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;                   //тактирование таймера
	TIM3->CCMR1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;  //полярность сигнала для каждого входа
	TIM3->CCER &= (uint16_t)(~(TIM_CCER_CC1P | TIM_CCER_CC2P));	//	PA6 PA7
	TIM3->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1 | TIM_SMCR_ETF;      //режим энкодера

	TIM3->CR1 |= TIM_CR1_CKD_1;
	TIM3->CCMR1 |= TIM_CCMR1_IC1F_3 | TIM_CCMR1_IC1F_2 | TIM_CCMR1_IC1F_1 | TIM_CCMR1_IC1F_0;
	TIM3->CCMR1 |= TIM_CCMR1_IC2F_3 | TIM_CCMR1_IC2F_2 | TIM_CCMR1_IC2F_1 | TIM_CCMR1_IC2F_0;

	TIM3->ARR = 0xFFFF;       //значение, до которого считает CNT
	TIM3->CNT = 0x1FFF;
	TIM3->CR1 |= TIM_CR1_CEN;
На плате энкодера еще два резистора по 10кОм впаяны, на подтяжку.
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Энкодер и STM32

Сообщение Eddy_Em »

Dimon456, и что, все равно не фильтрует?
А если APB prescaler на 1/16?
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Dimon456
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Re: Энкодер и STM32

Сообщение Dimon456 »

Eddy_Em писал(а):и что, все равно не фильтрует?
Ну как сказать, один тик плохо отрабатывает, особенно при навигации в меню жутко не удобно, может на два три пункта перескочить.
У меня нет хорошего видео, что нашел
Спойлерсмотреть на нижнюю строку, левые цифры, где 5008, это энкодер
Все таки аппаратная поддержка, не программная.
Но так и хочется кондерчики поставить, думаю на 1nF сойдет.
Eddy_Em писал(а):А если APB prescaler на 1/16?
не пробовал.
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Энкодер и STM32

Сообщение Eddy_Em »

Можно вообще по RC-фильтру килогерц на 10 воткнуть.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
U-M
Первый раз сказал Мяу!
Сообщения: 35
Зарегистрирован: Ср сен 25, 2019 17:46:33

Re: Энкодер и STM32

Сообщение U-M »

Доброго дня. Если не против, вклинюсь со своим вопросом.

Энкодер обычный, алиэкспресс-китайский ЕС11, кажется 15 импульсов на оборот, на синей круглой плате. В его обвязке уже есть резисторы подтяжки к питанию и конденсаторы к земле.

Эксперимент проходит на STM32F103C8.
Таймер настроен для работы с энкодером так:
Спойлер

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

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 1;
  htim3.Init.CounterMode = TIM_COUNTERMODE_CENTERALIGNED3;
  htim3.Init.Period = 100;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  sConfig.EncoderMode = TIM_ENCODERMODE_TI1;
  sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
  sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC1Filter = 15;
  sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC2Filter = 15;
  if (HAL_TIM_Encoder_Init(&htim3, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
Значение забирается так:
Спойлер

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

encoder_counter = __HAL_TIM_GET_COUNTER(&htim3);
Тут диапазон счетчика энкодера от 0 до 100, без перехода через 0 или через 100, с шагом 1.
При достижении минимального или максимального значения счетчика, если продолжать вращение в ту же сторону дальше, счетчик начинает колебаться у своего достигнутого значения.
Например, досчитали-докрутили до 0, продолжаем крутить в сторону уменьшения дальше, счетчик меняется в диапазоне 0-1-0-0-0-1-0 и т.п.
Или досчитали до 100, крутим в сторону увеличения дальше, видим 100-99-100-99-98 и т.п.
Скорость вращения вала при этом не важна. Если вал оставить в покое в любом своем положении и любом значении счетчика, то самопроизвольного плавания значения нет.
Параметр Input Filter менять пробовал, результата не видно.
При вращении не на границах счета, этого эффекта нет.
Справочно - этот-же энкодер на ардуине ведет себя адекватно.

Есть-ли решение проблемы такого эффекта у энкодера?
Аватара пользователя
Eddy_Em
Собутыльник Кота
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01
Контактная информация:

Re: Энкодер и STM32

Сообщение Eddy_Em »

U-M, как-то странно у вас настроен энкодер. Не должно такого быть: после 0 должно следовать 99, 98 и так далее; аналогично после 100 должно идти 0, 1, 2 и т.д.
Каловскую портянку вряд ли кто читать будет. Дайте нормальный код инициализации!
P.S. А таймер случаем не в center-aligned mode?
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
U-M
Первый раз сказал Мяу!
Сообщения: 35
Зарегистрирован: Ср сен 25, 2019 17:46:33

Re: Энкодер и STM32

Сообщение U-M »

Да, таймер в aligned mode 3.
Аватара пользователя
alex_
Опытный кот
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

Re: Энкодер и STM32

Сообщение alex_ »

Здрасти :))
У меня иная проблема, опыта в СТМ пока не много поэтому сильно не пинайте.

Вопрос соединения таймеров, возможно ли такое: я подключил энкодер к таймеру Т4 всё работает, но как то нужно настроить прерывание(допустим через каждых 100 тиков этого таймера), полагаю что прерывание по переполнению делать не вариант, потеряем текущее абсолютное значение (0-0xffff), есть идея параллельно к счётному входу подключить второй таймер который бы и генерил прерывание по переполнению к примеру каждые 100 импульсов?
Или это можно как то иначе реализовать? Но только не через прерывания, прерывание должно быть одно и только после делителя импульсов.

В чём собственно суть: на цепи лежит объект, цепь при этом перемещается, на цепи установлен инкрементальный энкодер, в зоне измерения установлен датчик и через допустим 1-5-10 см нужно считывать значения с датчика при этом запоминается значение счётчика в момент начала и конца объекта чтобы потом вычислить итоговую длину.
tonyk
Это не хвост, это антенна
Сообщения: 1323
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Re: Энкодер и STM32

Сообщение tonyk »

alex_ писал(а):на цепи лежит объект, цепь при этом перемещается, на цепи установлен инкрементальный энкодер
У таймеров-счётчиков есть модуль сравнения. Берёшь текущее значение счётчика, добавляешь или вычитаешь из него нужное количество импульсов, разрешеаешь прерывание от этого канала сравнения- и в путь.
Управлял конвейером. Энкодера не было, управлял шаговым двигателем, но суть таже самая.
Аватара пользователя
alex_
Опытный кот
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

Re: Энкодер и STM32

Сообщение alex_ »

Ну как вариант, если не получиться таймеры синхронизировать. Пока пытаюсь T4 master->T12 save
tonyk
Это не хвост, это антенна
Сообщения: 1323
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Re: Энкодер и STM32

Сообщение tonyk »

[uquote="alex_",url="/forum/viewtopic.php?p=4434284#p4434284"]Ну как вариант, если не получиться таймеры синхронизировать.[/uquote]
Зачем их синхронизировать? TIM2 и TIM5 имеют аж 32 бита. Впрочем, для большинства задач хватает 16 бит.

Ещё обрати внимание на флаги прерываний. Возможно, тебе понадобиться отключить флаг перехода счётчика через ноль, оставив только сигналы от модуля сравнений.
Аватара пользователя
alex_
Опытный кот
Сообщения: 781
Зарегистрирован: Сб июн 01, 2013 22:24:21
Откуда: ПФО

Re: Энкодер и STM32

Сообщение alex_ »

Мне нужно чтобы они работали синхронно, Т4 хранит значение текущего положения цепи(0-0xffff), в Т12 записываем максимальное значение при постижении которого(TIM12_ARR = 20-50-150) счётчик сбрасывается в ноль и формируется прерывание. Хочу сделать всё на аппаратном уровне без заморочки с регистрами сравнения.
tonyk
Это не хвост, это антенна
Сообщения: 1323
Зарегистрирован: Вт ноя 19, 2019 06:10:18

Re: Энкодер и STM32

Сообщение tonyk »

alex_ писал(а):счётчик сбрасывается в ноль и формируется прерывание. Хочу сделать всё на аппаратном уровне без заморочки с регистрами сравнения.
Так ведь если формируется прерывание, то что сложного в нём сбросить счётчик? :))
Если уж так хочется, чтобы всё делалось автоматически, то можно задействовать DMA для записи нуля, хотя, ИМХО, зачем такой изврат?
Ответить

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