2014-12-06 03:53 PM
Hi,
I'm trying to read a PP Sum Signal with the TIM3_CH4 of my stm32f103rb. The signal of the first channel is recognizable but not steady. What am I doing wrong. TIM3 CH1 2 3 and TIM1 CH2 3 have been used to output the corresponding PWM Signals.
void
initPPM(
void
) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
//enable port B and alternate function
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB |RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
//remap ports
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);
//set clock to TIM3
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
//init port C pin 6 = TIM3 channel 1 to alternate function push-pull
//init port C pin 7 = TIM3 channel 2 to alternate function push-pull
//init port C pin 8 = TIM3 channel 3 to alternate function push-pull
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//init port b15 TIM1 channel 3N
//init port b14 TIM1 channel 2N
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14|GPIO_Pin_15;
GPIO_Init(GPIOB, &GPIO_InitStructure);
//Init Timer3 und 1 Baseconfig
TIM_TimeBaseStructure.TIM_Prescaler = 72-1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_Period = 20000;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
//Init Channels
TIM_OCStructInit(&TIM_OCInitStructure);
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputState_Disable;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_Pulse = 1500;
TIM_OC1Init(TIM3,&TIM_OCInitStructure);
TIM_OC2Init(TIM3,&TIM_OCInitStructure);
TIM_OC3Init(TIM3,&TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_OC2Init(TIM1,&TIM_OCInitStructure);
TIM_OC3Init(TIM1,&TIM_OCInitStructure);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_ARRPreloadConfig(TIM3, ENABLE);
TIM_Cmd(TIM1, ENABLE);
TIM_Cmd(TIM3, ENABLE);
//little hack
TIM1->CCER |=(1<<6)|(1<<7)|(1<<10)|(1<<11);
}
void
initPPMin(
void
) {
GPIO_InitTypeDef GPIO_InitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOC, &GPIO_InitStructure);
TIM_ICStructInit(&TIM_ICInitStructure);
//Init Kanäle
TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;
TIM_ICInitStructure.TIM_ICFilter = 0xf;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInit(TIM3,&TIM_ICInitStructure);
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM2 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 7;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_EnableIRQ(TIM3_IRQn);
//HIER
TIM_ITConfig(TIM3,TIM_IT_CC4,ENABLE);
}
void
TIM3_IRQHandler(
void
) {
if
(TIM3->SR & TIM_IT_Update) {
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
if
(TIM3->SR & TIM_IT_CC4) {
/* Clear TIM3_CH4 Capture compare interrupt pending bit */
TIM_ClearITPendingBit(TIM3, TIM_IT_CC4);
uint16_t tmp = TIM_GetCapture4(TIM3);
if
(tmp > captureValueOld) {
currentPPMin = tmp - captureValueOld;
}
else
{
currentPPMin = captureValueOld + (20000 - tmp);
}
currentPPMin -= 400;
//the low time is allays 400µs
captureValueOld = tmp;
switch
(currentState) {
case
0:
case
1:
case
2:
case
3:
case
4:
case
5:
case
6:
if
(currentPPMin < 200) {
//too short - glitch
}
else
if
(currentPPMin > 5200) {
//too long reset
currentState = 0;
}
else
{
ppmSum[currentState] = currentPPMin;
currentState++;
}
break
;
case
7:
if
(currentPPMin < 800) {
//too short - glitch
}
else
if
(currentPPMin > 2200) {
//too long reset
currentState = 0;
}
else
{
ppmSum[currentState] = currentPPMin;
currentState = 0;
}
break
;
default
:
break
;
}
}
if
(TIM3->SR & TIM_IT_CC3) {
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
}
else
{
printf
(
''missed %u \r\n''
, TIM3->SR);
TIM3->SR = 0xffff;
}
}
Instead of reading 8 channel with 1500 each I read values like:
printf
(
''%d \t %d \t %d \t %d \t %d \t %d \t %d \t %d\r\n''
,ppmSum[0],ppmSum[1],ppmSum[2],ppmSum[3],ppmSum[4],ppmSum[5],ppmSum[5],ppmSum[6],ppmSum[7]);
0 0 0 0 0 0 0 0
1103 0 0 0 0 0 0 0
1215 0 0 0 0 0 0 0
1717 0 0 0 0 0 0 0
2229 0 0 0 0 0 0 0
428 0 0 0 0 0 0 0
428 0 0 0 0 0 0 0
240 0 0 0 0 0 0 0
2654 0 0 0 0 0 0 0
510 0 0 0 0 0 0 0
510 736 0 0 0 0 0 0
246 736 0 0 0 0 0 0
246 736 0 0 0 0 0 0
1171 736 0 0 0 0 0 0
893 736 0 0 0 0 0 0
312 736 0 0 0 0 0 0
566 736 0 0 0 0 0 0
513 736 0 0 0 0 0 0
1147 736 0 0 0 0 0 0
1029 736 0 0 0 0 0 0
282 736 0 0 0 0 0 0
282 736 0 0 0 0 0 0
888 736 0 0 0 0 0 0
680 736 0 0 0 0 0 0
230 346 0 0 0 0 0 0
230 302 1647 0 0 0 0 0
1449 302 1647 0 0 0 0 0
1744 302 1647 0 0 0 0 0
1744 1439 256 0 0 0 0 0
501 552 256 0 0 0 0 0
659 552 256 0 0 0 0 0
860 552 256 0 0 0 0 0
860 552 256 0 0 0 0 0
860 552 256 0 0 0 0 0
860 552 256 0 0 0 0 0
860 552 256 0 0 0 0 0
860 552 256 0 0 0 0 0
665 869 256 0 0 0 0 0
665 869 256 0 0 0 0 0
665 869 256 0 0 0 0 0
519 869 256 0 0 0 0 0
725 869 256 0 0 0 0 0
896 869 256 0 0 0 0 0
433 864 256 0 0 0 0 0
433 864 256 0 0 0 0 0
1688 864 256 0 0 0 0 0
311 864 256 0 0 0 0 0
2816 864 256 0 0 0 0 0
299 1557 256 0 0 0 0 0
4082 317 256 0 0 0 0 0
544 317 256 0 0 0 0 0
544 317 256 0 0 0 0 0
639 317 256 0 0 0 0 0
916 665 256 0 0 0 0 0
1039 665 256 0 0 0 0 0
311 665 256 0 0 0 0 0
1354 665 256 0 0 0 0 0
359 665 256 0 0 0 0 0
359 444 256 0 0 0 0 0
873 444 256 0 0 0 0 0
303 444 256 0 0 0 0 0
303 444 256 0 0 0 0 0
1837 444 256 0 0 0 0 0
509 444 256 0 0 0 0 0
1704 444 256 0 0 0 0 0
1704 1661 731 2401 0 0 0 0
1704 1661 731 2401 0 0 0 0
1704 1661 731 2401 0 0 0 0
303 1661 731 2401 0 0 0 0
599 1661 731 2401 0 0 0 0
391 1661 731 2401 0 0 0 0
391 1661 731 2401 0 0 0 0
#worst-forum-software-ever #worst-forum-software-ever
2014-12-06 04:45 PM
PPM/PP Sum Signal? What's that?
These seem unrelated:
if
(TIM3->SR & TIM_IT_CC3) {
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
2014-12-07 07:18 AM
A PPM Signal see [1]. It consits of 8 pulses each, is 1ms to 2ms high and has a low time of 0.4ms between them. The ninth high is the rest to fill a complete 20ms cycle ( the picture shows this). So I'm expecting values from 1000 to 2000 (with 200 buffer timer) and the last one should be between 6300 and 8300.
On my scope everything looks great. The Update Interrupt appears. I don't need it but have to reset the flag. [1] http://de.wikipedia.org/wiki/Puls-Pausen-Modulation#mediaviewer/File:Fernsteuerungsmodulation.gif2014-12-07 07:59 AM
Ok, so a multi pulse servo type signal.
Is the wave form you are generating correct? Do you have another source to check? Rising edge? Any real value in limiting the Input Capture to 20000 us? Wouldn't letting it go maximal 16-bit simplify the unsigned math? You really don't need to be check/clearing update and other CC you aren't servicing, the flags are irrelevant. Just qualify CC4 as the source. Consider if you can advance a CCR to the point beyond the last pulse based on your ability to identify the first one. Consider if you can generate you PPM signal using toggle mode, and advance the edge of the CCR, either in interrupt, or using DMA to generate the signal from a pattern buffer.2014-12-07 12:51 PM
The waveform is correct (checked with my DSO). I've tried a 5V 50% duty cycle 1kHz square wave from my function generator.
The result is: 30% is correctly recognized as 1000 the rest is somewhere between 2000 and 9000. I need the 20000 to generate a signal on the other 3 channels (to control servos). After changing it to a value of 0xffff there is no big change. The last two things I have no idea how to do that.2014-12-07 11:34 PM
> TIM_ICInitStructure.TIM_ICFilter = 0xf; Are you sure? Do you know what does this exactly do? > currentPPMin = captureValueOld + (20000 - tmp); This is certainly wrong. Make yourself a drawing. > currentPPMin -= 400;
//the low time is allays 400µs I wouldn't do this either, but that's me. JW2014-12-08 12:01 AM
>> TIM_ICInitStructure.TIM_ICFilter = 0xf;
>Are you sure? Do you know what does this exactly do? It filters/debounces the input - tried all 16 values and 0x0 (disabled filter) is giving the worst results. >> currentPPMin = captureValueOld + (20000 - tmp); >This is certainly wrong. Make yourself a drawing. done it twice - give me a hint how it's right. >> currentPPMin -= 400;
//the low time is allays 400µs >I wouldn't do this either, but that's me. with only one channel left I haven't found a better sollution (pwm input needs two CCR). How would you do it?2014-12-08 12:25 AM
>>> TIM_ICInitStructure.TIM_ICFilter = 0xf;
>>Are you sure? Do you know what does this exactly do? > It filters/debounces the input - tried all 16 values > and 0x0 (disabled filter) is giving the worst results. Okay, but why would 0x0F give the best result? How much filtering you expect? And if your signal is THAT bouncy/noisy, why would you expect stable outputs? >>> currentPPMin = captureValueOld + (20000 - tmp); >> This is certainly wrong. Make yourself a drawing. > done it twice - give me a hint how it's right. If previous capture happened atcaptureValueOld == 19900 and this capture happens at tmp == 100, what was the elapsed time and what is the value your formula yields? >>> currentPPMin -= 400;
//the low time is allays 400µs >>I wouldn't do this either, but that's me. >with only one channel left I haven't found a better sollution (pwm input needs two CCR). How would you do it? I would do the ''too short'' test first. This may overflow, and if you use unsigned arithmetic, result in false ''too long''. JW2014-12-08 03:36 AM
>Okay, but wh
y would 0x0F give the best result? How much filtering you expect?
Every value !=0 has the same result so i just eft the last tested one in. >If previous capture happened atcaptureValueOld == 19900 and this capture happens >at tmp == 100, what was the elapsed time and what is the value your formula yields? Thanks corrected it to : if (tmp > captureValueOld) {
currentPPMin = tmp - captureValueOld; } else { currentPPMin = (20000-captureValueOld) + tmp; } currentPPMin -= 400; if(currentPPMin<0)currentPPMin+=400 currentPPMin is of type int32_t2014-12-08 05:23 AM
It's working finally.
semihosting is crashing the timer. It's working fine without it. Thanks for your help!