Pwm Decoder Entegresi varmı?

Başlatan gambit1244, 14 Ocak 2012, 20:36:25

muhittin_kaplan

Zayıf olan C bilgim le tek kanalı yukarda bahsettiğim şekilde örnekleme alarak duty ve peryot ölçebiliyorum. Ama gerisi gelmedi.
tek kanalı al ve usarttan gönder hepsi bu

SpeedyX

#46
Meseleyi şimdi anladım.

Bunun için 8 pini meşgul edip kafayı kırmaya gerek yokki :)

Hepsini diyotlarla tek bir CCP ye vereceğiz (yani OR'layacağız), sonra;
3 değişkenimiz olacak
PPMindex, CurrentEdge ve PreviousEdge.
CCP ile yükelen/düşen kenar okuyup süreyi bir öncekinden çıkararak (CurrentEdge - PreviousEdge) dalga boyunu bulacağız.
Bu dalga boyu 5ms den büyükse SYNC PAUSE denen sinyal gelmiş demektir,
hemen PPMindex = 0; yapıp çıkacağız.
Sıradaki okumada 5ms den daha küçük bir sinyal gelecek ve bu KANAL1 e ait olan PWM sinyali olacak.
Daha sonrakiler de sırasıyla KANAL2-3-4-5-6....
PPMindex i arttırarak her kesmede bir kanalın bilgisini okuyup bir diziye kaydedeceğiz, son kanalı da başarıyla okuduğumuzda Frame geçerlidir anlamında bir flagı aktif edeceğiz, başka bir yerde de bu bilgilere ihtiyacı olan kod parçası geçerli frame olduğunu görüp dizi değişkenden süreleri alarak işlem yapacak ve frame flagını sıfırlayacak. Eğer gürültüden yada başka bir problemden dolayı PPMindex son kanala (7) gelemediyse o frame kullanılmayacak.

Ne zaman 5ms den büyük bir sinyal geldiyse o SYNC sinyalidir.

Burada 5ms değerini genel olarak verdim, alıcının dökümanında yazması lazım.

Scope dan kontrol et, dediğim gibi "1" de kalma süresi 5ms den uzun olan bir SYNC sinyali olması gerekiyor.

EDIT:
Ben de okumadan, resimlere bakarak cevap yazmışım, iyildirim ile aynı şeyleri diyorum aslında...

yamak

@Gambit;
Hocam kumanda da siz hiç modifikasyon yaptınız mı? Yoksa alıcı devresini tamamen kumandanı çıkışlarına göre mi ayarladınız? Bir de kumandayı nereden temin ettiniz?

gambit1244

Alıntı yapılan: yamak - 16 Ocak 2012, 02:39:03
@Gambit;
Hocam kumanda da siz hiç modifikasyon yaptınız mı? Yoksa alıcı devresini tamamen kumandanı çıkışlarına göre mi ayarladınız? Bir de kumandayı nereden temin ettiniz?

hocam kumanda hazır kumanda kds k7xII
alıcısı aynı marka
alıcının pwm çıkışlarına direk servo bağlıyorum hiç devrem falan yok ortada devreyi yapıcaz inş.
[email]tufan_ozbek@hotmail.com[/email] Yesterday is history. Tomorrow is a mystery. Today is a gift aslında bütün mesele bu.

iyildirim

SpeedyX hocam,
Bazı alıcılarda senkron bilgisini içeren sinyal ayrı bir pin ile dışarı taşınıyor. Benim alıcımda var.  Bu pini de dahil edip OR larsak tam olarak dediğiniz gibi yapılabilir. Ama alıcıda senkron sinyali dişarı taşınmamış ise bu durumda kanal numarasını bildiğimiz bir kanalı işlemcide ayrıca GPIO pinine girip, yükselen kenar kesmesi sırasında bu pinin durumuna bakıp, pin  HIGH ise şu anda extra bağladığımız kanal aktif şeklinde bir senkronizasyon kurmak da mümkün.

Kumanda modifikasyonu içinde kullanılan verici alıcı çifti ne kadar basitse, modifikasyon da o kadar basit oluyor denebilir.

Benim 6 kanal heli kumandasında bir mikro ADC ile potları okuyup, tek bir pinden sıralı çıkış veriyor. Bu pinin çıkışıda RF vericinin girişine bağlı.

Manuel modda heliye e-CCPM modda karıştırılmış sinyaller gidiyor.  Ki kumandanın orijinali de bu.

Manuelden yarı otomatik moda geçip,  komutların servoları değilde, heliyi kontrol etmesi için için boş olan 5 kanala bağlı head lock gyro için kullanılan anahtarı kullanıyorum. Bu durumda kendi işlemcim potları okuyup RF modüle kendi ürettiği  karıştırılmamış darbeleri gönderebiliyor.   
Alıcıda modifikasyon gerekmiyor. Sadece kontrol işlemcisi 5 kanala bakıp servo darbelerine müdahalemi edecek yoksa tamamen kendi mi üreteceğine  karar veriyor.

Standart PPM kullanan bütün alıcı vericilerde bu yöntem çalışabilir. 
Standart'a göre max duty 2ms olduğundan teorik olarak max 10 kanala kadar standart PPM çalışabiliyor. 

Aynı şekilde alıcı tarafta RF çıkışına bir çengel atılırsa elde edilen sinyalin işlenmesi de aynen SpeedyX in söylediği gibi olacak.

Çok kanallı alıcı-vericilerin bazılarında baştaki 1 ms boşluk süresi azaltılıp yer açılmaya çalışılan DIY sistemleri nette gördüm. Vericide azaltılan miktar alıcıda duty'ye ekleniyor. Bazılarında da 50Hz  frekans örneğin 25Hz'e düşürülüp, alıcı tarafında son gelen duty değeri 50Hz de gönderiliyor. Yani son duty değerinde iki puls gönderiliyor.
Ki bu tip modifikasyonlarda yukarıda bahsedilen OR lama yöntemi çalışmayacak.

SpeedyX

Universal birşey yapmak bir timer ve 7 pine bakar ozaman.
Neden günlerdir tartışıyoruz ki, hadi yapalım? :)

// Kanalları sırasıyla PORTÖ nün 0. pininden itibaren bağlıyoruz.
#define KanalSayisi 7
#define TimerInterruptInverval 100 // [us]
#define PPMPeriod	20 // [ms]
#define FULLPERIOD	(PPMPeriod*1000/*20ms period*/ / TimerInterruptInverval) // [us] - Periyodun timer cinsinden degeri, 100us lik timer da 20ms icin 200

volatile uint8 DolulukOrani[KanalSayisi];	// [%] Buradan surekli doluluk orani okuyabilirsiniz

__irq Timer()
{
   static int KanalSayaci[KanalSayisi];
   static uint8 SayiciAktif = 0;
   static uint8 SayiciPasif = 0;

   SayiciAktif = PORTÖ & 0x7F; // ilk 7 bit

   for(int i=0;i<KanalSayisi;i++)
   {
	  if(SayiciAktif & (1<<i))
	  {
		 KanalSayici[i]++;
		 SayiciPasif &= ~(1<<i);
	  }
	  else
	  {
		 if(!(SayiciPasif & (1<<i)))
		 {
			DolulukOrani[i] = (uint8)((uint16)KanalSayici[i] * 100) / FULLPERIOD;
			KanalSayici[i] = 0;
			SayiciPasif |= (1<<i);
		 }
	  }
   }
}


Doğru oldu sanki  8)

gambit1244

bende ccs c ile bişeyler yaptım :D
butona bastığımda "yükseldi" bıraktığımda ise "düştü" yazıyor
araya timer ekleyip sonucu bir değişkene attımmı tamamdır :D
int x=0;
//*********** CCP1 KESMESİ ******************
#INT_CCP1   // INT_CCP1 kesmesi fonksiyonu
void yakala1_kesmesi ()
{
if(x==0)
{
printf("yukseldi"); //burada sinyal yükseldi ve ben saymaya başladım
setup_ccp1(CCP_CAPTURE_fe); // ccp1 düşen kenarı aktif ettim
x=1;
}
else
{
printf("dustu"); //burda sıfıra düştü ve bende saymayı durdurdum
setup_ccp1(CCP_CAPTURE_re);// ccp1 yükselen kenarı aktif ettim
x=0;
//sayım sonucunu bir değişkene attım
}
   
  
}
[email]tufan_ozbek@hotmail.com[/email] Yesterday is history. Tomorrow is a mystery. Today is a gift aslında bütün mesele bu.

iyildirim

SpeedyX hocam, timer kesmesi kullanamayız. Ölçmeye çalıştığımız zaten timer değeri.  Çok ufak zaman aralıkları ile Timer kesmesi kullanırsak da işlemcinin kesmeye girip çıkmaktan iflahı kesilir.   Yada çözünürlük çok düşer.

Eğer OR lanmış birleşik sinyal taşıyan pin yöntemini kullanacaksak External INT veya IC kesmesi kullanmamız gerekli. Birde senkronizasyon için GPIO pinine saf hali girilmiş herhangi bir kanal.   
Yükselen kenar da timer sıfırla, düşen kenarda timer değerini oku yapmamız lazım.

Bende bir ara dsPIC için bir kod örneği paylaşmştım.  Ama konuyu hatırlayamadım.

Hazır universal birşey yapmaya çalışıyorsak, bunu STM32F4 için yapsak, bana da lazım. Henüz işlemciyi yeterince tanımıyorum. Hatta mümkünse DMA kullansın, period değerlerini direkt RAM dan okuyalım.

muhittin_kaplan

Hocam RC Alıcıda Modifikasyona gitmeden değerleri ölçmemiz gerek.
Ben timer kesmesi ile 10us lik zamanlarda doğru değer alabiliyorum. 100us olduğunda hatalı değer alıyorum.

muhittin_kaplan



iki kanal arasında (ardışık gelen) ki zaman farkı (birinin düşen diğerinin yükselen) 2.3us.
eğer or işlemine tabi tutarsak 2.3us lik zamanda timer'ı sıfırlama tekrardan kurma işlemlerini yapması gerek. bu esnada Capture pini yakalayabilir mi ?

muhittin_kaplan



Önceki mesajımdaki Kumanda FLYSKY 9CH 2.4gH Bu mesajımda verdiğim ise Futaba 6Ch 72MHz ve bunda iki kanal arasında hiç geçikme yok. Eğer OR layıp işlem yapacak olursak nasıl olur ?

muhittin_kaplan

STM32f100 CM3 için PWM input Buldum Ama CMIS le hazırlanmış sanırım. Bunu 32F4 e göre yazmayı düşünüyorum.

/**
  ******************************************************************************
  * @file    TIM/PWM_Input/main.c 
  * @author  MCD Application Team
  * @version V3.5.0
  * @date    08-April-2011
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"

/** @addtogroup STM32F10x_StdPeriph_Examples
  * @{
  */

/** @addtogroup TIM_PWM_Input
  * @{
  */ 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TIM_ICInitTypeDef  TIM_ICInitStructure;

/* Private function prototypes -----------------------------------------------*/
void RCC_Configuration(void);
void GPIO_Configuration(void);
void NVIC_Configuration(void);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief   Main program
  * @param  None
  * @retval None
  */
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f10x_xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f10x.c file
     */     
       
  /* System Clocks Configuration */
  RCC_Configuration();

  /* NVIC configuration */
  NVIC_Configuration();

  /* Configure the GPIO ports */
  GPIO_Configuration();

  /* TIM3 configuration: PWM Input mode ------------------------
     The external signal is connected to TIM3 CH2 pin (PA.01), 
     The Rising edge is used as active edge,
     The TIM3 CCR2 is used to compute the frequency value 
     The TIM3 CCR1 is used to compute the duty cycle value
  ------------------------------------------------------------ */

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);

  /* Select the TIM3 Input Trigger: TI2FP2 */
  TIM_SelectInputTrigger(TIM3, TIM_TS_TI2FP2);

  /* Select the slave Mode: Reset Mode */
  TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

  /* Enable the Master/Slave Mode */
  TIM_SelectMasterSlaveMode(TIM3, TIM_MasterSlaveMode_Enable);

  /* TIM enable counter */
  TIM_Cmd(TIM3, ENABLE);

  /* Enable the CC2 Interrupt Request */
  TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);

  while (1);
}

/**
  * @brief  Configures the different system clocks.
  * @param  None
  * @retval None
  */
void RCC_Configuration(void)
{
  /* TIM3 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

  /* GPIOA clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
}

/**
  * @brief  Configure the GPIO Pins.
  * @param  None
  * @retval None
  */
void GPIO_Configuration(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  /* TIM3 channel 2 pin (PA.07) configuration */
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  GPIO_Init(GPIOA, &GPIO_InitStructure);
}

/**
  * @brief  Configure the nested vectored interrupt controller.
  * @param  None
  * @retval None
  */
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the TIM3 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  while (1)
  {}
}

#endif

/**
  * @}
  */ 

/**
  * @}
  */ 

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

fatihinanc

#57
Hocam deneyemedim ama şöyle bir örnek buldum ST örneklerinin içerisinde.
Sınavlardan sonra deneyeceğim ama ben de merak ettim :)
/**
  ******************************************************************************
  * @file    TIM/InputCapture/main.c 
  * @author  MCD Application Team
  * @version V1.0.0
  * @date    30-September-2011
  * @brief   Main program body
  ******************************************************************************
  * @attention
  *
  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
  *
  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
  ******************************************************************************
  */ 

/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx.h"

/** @addtogroup STM32F4xx_StdPeriph_Examples
  * @{
  */

/** @addtogroup TIM_Input_Capture
  * @{
  */ 

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
TIM_ICInitTypeDef  TIM_ICInitStructure;

/* Private function prototypes -----------------------------------------------*/
void TIM_Config(void);

/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Main program
  * @param  None
  * @retval None
  */
int main(void)
{
  /*!< At this stage the microcontroller clock setting is already configured, 
       this is done through SystemInit() function which is called from startup
       file (startup_stm32f4xx.s) before to branch to application main.
       To reconfigure the default setting of SystemInit() function, refer to
       system_stm32f4xx.c file
     */     
       
  /* TIM1 Configuration */
  TIM_Config();

  /* TIM1 configuration: Input Capture mode ---------------------
     The external signal is connected to TIM1 CH2 pin (PE.11)  
     The Rising edge is used as active edge,
     The TIM1 CCR2 is used to compute the frequency value 
  ------------------------------------------------------------ */

  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
  TIM_ICInitStructure.TIM_ICFilter = 0x0;

  TIM_ICInit(TIM1, &TIM_ICInitStructure);
  
  /* TIM enable counter */
  TIM_Cmd(TIM1, ENABLE);

  /* Enable the CC2 Interrupt Request */
  TIM_ITConfig(TIM1, TIM_IT_CC2, ENABLE);

  while (1);
}

/**
  * @brief  Configure the TIM1 Pins.
  * @param  None
  * @retval None
  */
void TIM_Config(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;
  NVIC_InitTypeDef NVIC_InitStructure;
  
  /* TIM1 clock enable */
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);

  /* GPIOA clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
  
  /* TIM1 channel 2 pin (PE.11) configuration */
  GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_11;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOE, &GPIO_InitStructure);

  /* Connect TIM pins to AF2 */
  GPIO_PinAFConfig(GPIOE, GPIO_PinSource11, GPIO_AF_TIM1);
  
  /* Enable the TIM1 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
  
}

#ifdef  USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t* file, uint32_t line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  while (1)
  {}
}

#endif

/**
  * @}
  */ 

/**
  * @}
  */ 

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/


http://tech.munts.com/MCU/Frameworks/ARM/stm32f4/libs/STM32F4xx_DSP_StdPeriph_Lib_V1.0.0/Project/STM32F4xx_StdPeriph_Examples/TIM/InputCapture/
Kainat dediğimiz kitap, yazıldığı dil ve harfler öğrenilmedikçe anlaşılamaz.  (Galileo Galilei)

SpeedyX

#58
10us lik timer kesmesi kullanırsanız benim yazdığım kod doğru çalışır ama sürekli timer da durması hoş değil tabii.

@Muhittin, senin kumandanda SYNC pini yok öyle mi?

Ozaman sıradaki seçenek bir timer ve 7 adet interrupt özellikli pin. Olur mu?
(Bu pinlerin hepsini hem diyotlarla bir interrupt özellikli pine verip hem de bir port a tek tek bağlarsak da aynı kapıya çıkar )

O da olmazsa lowpass+ADC veya ayrı işlemci+SPI

muhittin_kaplan

hocam iki çeşit kumandanın çıkışlarını ölçtüm
birinci kumada: kanallar arasındaki sinyallerin arasında 2,3us var
ikinci kumanda: kanallar arasında boşluk görülmedi.

şimdi OR yapıp Sync için PWM Giriş Kanal1 i kullanacak olsak dahi ikinci kumanda da çalışmayacak.birinci de çalıştırabiliriz.

Benim en az okumam gereken Kanal sayısı 5 ve ST32F100 CM3 discovery yada 32F400 CM4 ile timer ve CP kullanarak INPUT PWM metodu ile yapmayı planlıyorum. Verilen örnek de doğrudan registerler kullanılmamış(CMIS kullanmışlar sanırım). Sağolsun Bunalmış Hoca reg. ile çalışmaya başlattı. Bizde Her Bayramda Namaz Kılacak Cemaat gibi "Nasıl Kılınıyordu" Diyoruz.
Buradaki çekincem bu işlemciyi böyle bir iş için meşgul etmek.