cancel
Showing results for 
Search instead for 
Did you mean: 

Reading PPM Sum signal not working

adminiator
Associate II
Posted on December 07, 2014 at 00:53

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
9 REPLIES 9
Posted on December 07, 2014 at 01:45

PPM/PP Sum Signal? What's that?

These seem unrelated:


if
(TIM3->SR & TIM_IT_CC3) {

TIM_ClearITPendingBit(TIM3, TIM_IT_Update);

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
adminiator
Associate II
Posted on December 07, 2014 at 16:18

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.gif

Posted on December 07, 2014 at 16:59

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.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
adminiator
Associate II
Posted on December 07, 2014 at 21:51

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.

Posted on December 08, 2014 at 08:34

> 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.   JW  

adminiator
Associate II
Posted on December 08, 2014 at 09:01

>> 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? 

Posted on December 08, 2014 at 09:25

>>> 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''.    JW   

adminiator
Associate II
Posted on December 08, 2014 at 12:36

>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_t     

adminiator
Associate II
Posted on December 08, 2014 at 14:23

It's working finally.

semihosting is crashing the timer. It's working fine without it.

Thanks for your help!