STM32F103 TIM4 Encoder Mode interrupt sorunum

Başlatan gokhangokcen, 05 Ekim 2020, 11:45:34

gokhangokcen

Merhabalar, Atollic True Studio ve cubemx kullanarak enkoder okumaya çalışıyorum. Kodlarımın ilgili kısımları şu şekilde;

uint16_t encPos = 0;
uint16_t deger = 0;

HAL_TIM_Encoder_Start_IT(&htim4, TIM_CHANNEL_ALL);

int main(){

while(1){
encPos = TIM4->CNT;
}

}


static void MX_TIM4_Init(void)
{

  /* USER CODE BEGIN TIM4_Init 0 */

  /* USER CODE END TIM4_Init 0 */

  TIM_Encoder_InitTypeDef sConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM4_Init 1 */

  /* USER CODE END TIM4_Init 1 */
  htim4.Instance = TIM4;
  htim4.Init.Prescaler = 0;
  htim4.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim4.Init.Period = 65535;
  htim4.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim4.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
  sConfig.IC1Polarity = TIM_ICPOLARITY_BOTHEDGE;
  sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC1Filter = 10;
  sConfig.IC2Polarity = TIM_ICPOLARITY_BOTHEDGE;
  sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
  sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
  sConfig.IC2Filter = 10;

  //TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_1;
  if (HAL_TIM_Encoder_Init(&htim4, &sConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim4, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM4_Init 2 */

  /* USER CODE END TIM4_Init 2 */

}

void TIM4_IRQHandler(void)
{
	deger++;
	HAL_TIM_IRQHandler(&htim4);

}

çözemediğim/anlam veremediğim garip bir durum var. Kesme hem düşen hem yükselen kenarda kesme üretmesi için kurulduğu halde kesmeye sadece enkoder'dan gelen A-B fazlarının yükselen kenarında gerçekleşiyor. Fakat encPos diye ana programda okuduğum değer ise olması gerektiği gibi hem düşen yem yükselen kenarlarda artıyor. Elimde 32 pulse encoder var 1 tur çevirdiğimde tim4->cnt değeri 128 olup, değer değişkeni ise 64 oluyor.Acaba nerede yanlış yapıyorum?
Bildiğini paylaşmak, Allah'ın verdiği öğrenme yeteneğinin zekatıdır.

z

#1
Encoderin tek kanalinina gelen kabloyu sokup cevirdiginde 1 turda kac pals aliyorsun bir kontrol et. (Quadrature encoder ve ardindaki sayac aptallasir ama int icindeki soft sayacin dogru calismasi lazim.)

Ardindan soktugun kanali takip diger kanalinkini sok. ayni deneyi bir daha tekrarla.

En azindan int rutinindeki sayac icerigi bir ipucu verecektir.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

gokhangokcen

Alıntı yapılan: z - 05 Ekim 2020, 16:59:05Encoderin tek kanalinina gelen kabloyu sokup cevirdiginde 1 turda kac pals aliyorsun bir kontrol et. (Quadrature encoder ve ardindaki sayac aptallasir ama int icindeki soft sayacin dogru calismasi lazim.)

Ardindan soktugun kanali takip diger kanalinkini sok. ayni deneyi bir daha tekrarla.

En azindan int rutinindeki sayac icerigi bir ipucu verecektir.

z üstad denedim tek kablo ile 1 ve 0 oluyor sayaç ileri doğru ya da geri doğru ilerleyemiyor. debug modunda baktığımda ise kesme bloğunada hiç girmiyor.
Bildiğini paylaşmak, Allah'ın verdiği öğrenme yeteneğinin zekatıdır.

Mucit23

STM32F10x'de Timer için birkaç farklı kesme kanalı var.

TIM_IT_CC1
TIM_IT_CC2
TIM_IT_CC3
TIM_IT_CC4
TIM_IT_TRIGGER
TIM_IT_UPDATE
TIM_IT_BREAK
TIM_IT_COM

Sen programda HAL_TIM_Encoder_Start_IT(&htim4, TIM_CHANNEL_ALL); diyince CC1 ve CC2 kesmelerini aktif ediyor. Emin değilim ama bu sorun Input Capture bölümündeki bölücüden kaynaklı olabilir. Gerçi ayalarda TIM_ICPSC_DIV1 olarak belirtmişsin. Input Capture Donanımı ile alakalı bir sorun olabilir.

Bence farklı kesme kaynaklarını dene.


gokhangokcen

@Mucit23  üstad bahsettiklerini tam olarak anlamadım. Normalde kesme oluşturdum. Hem alçalan hemde yükselen için. Zaten encoder okumak için oluşturulan kesme;

HAL_TIM_Encoder_Start_IT(&htim4, TIM_CHANNEL_ALL);

diye biliyorum. Encoder pozisyon değiştirdiğinde bütün kanallar için kurdum. Ayarlarda ise sConfig.EncoderMode = TIM_ENCODERMODE_TI12; hem 1. kanal hem 2. kanal için ayarladım. Kesme kenarlarını düşen ve yükselen için kurdum. ama yinede istediğimi başaramadım.
Bildiğini paylaşmak, Allah'ın verdiği öğrenme yeteneğinin zekatıdır.

Murat Mert

@gokhangokcen senin durumu merak edip arduino encoder modülü aldım. Modül bir turda 20 palslik bir ürün. Bağlantı ve programı yaptım her palsde timer counter +4 değer veriyor ama elim ile çok ağır çevirince  palsler arasında 1,2,3,4 artıyor. Birde dış kesme ile yapıp denmek lazım...
mert07

Murat Mert

PB ve PB1 external kesmesi kullandım yine +4 atlıyor hatta bazen hızlı yapınca +5 ve +6 bile oldu ;D
mert07

gokhangokcen

Alıntı yapılan: Murat Mert - 18 Ekim 2020, 12:58:10PB ve PB1 external kesmesi kullandım yine +4 atlıyor hatta bazen hızlı yapınca +5 ve +6 bile oldu ;D

benim mevzu anlık değişim mevzusu değil. Main içinde tim4 cnt değeri (encoder pulse okunan değişken) Kesme için dallanan bir alt program var.
int main(){

while(1){
encPos = TIM4->CNT;
}

}

void TIM4_IRQHandler(void){

deger++;

}

şeklinde. 1 tur sonunda değer değişkeninin değeri 64 olurken encPos değişkeninin değeri 128 oluyor. Kesme bloğunun içine pulse'lerin düşen kenarında girmiyor.
Bildiğini paylaşmak, Allah'ın verdiği öğrenme yeteneğinin zekatıdır.

Murat Mert

TIM_ENCODERMODE_TI12
Bu komut ile 2 kanal verisi aynı anda okuyor. kanaldan gelen veri 2 bilgi diğer kanaldan da 2 veri geliyor her puls da toplam 4 veri ediyor.

TIM_ENCODERMODE_TI1
Bu komut da 1. kanaldan her pulda 2 data gelir buda her pulda 2 artış yapıyor.
En azından benim encoder de öyle  :D
mert07