Skip to main content
P S
Associate
March 16, 2018
Solved

How to read 4 fast pulses

  • March 16, 2018
  • 5 replies
  • 3367 views
Posted on March 16, 2018 at 16:55

Hi All,

I am just getting started with stm32. I am using a stm32f031 mcu and am trying to read an input signal from a flight controller. The protocol used puts out a series of 4 pulses that vary from 1us to 2.6us in width with a 1us in between ( proshot protocol). I have used input capture with a timer for slower speed pulses but I have no luck with reading such short pulse durations. I am looking for clues as to how to read this? It seems input capture with interrupts is just too slow? Is DMA the solution here? can DMA read the 4 pulses one after another like this and store in an array? I am really new at this and I have spent a lot of time trying things than find out it could never work so this time I am asking first. Thanks for your help!

    This topic has been closed for replies.
    Best answer by Tesla DeLorean
    Posted on March 16, 2018 at 18:08

    DMA should be quite capable of sub-microsecond acquisition.

    You'd look to maximally clock a TIM (ie PSC=0, ARR=0xFFFF), use the TIMx_CHx pin in input capture mode, where the same TIMx_CCx trigger was available to a DMA controller, and have a large enough time stamp capture buffer to hold all events on the time line.

    The F0 being somewhat constraining as it only has 16-bit TIM

    5 replies

    Tesla DeLorean
    Tesla DeLoreanBest answer
    Guru
    March 16, 2018
    Posted on March 16, 2018 at 18:08

    DMA should be quite capable of sub-microsecond acquisition.

    You'd look to maximally clock a TIM (ie PSC=0, ARR=0xFFFF), use the TIMx_CHx pin in input capture mode, where the same TIMx_CCx trigger was available to a DMA controller, and have a large enough time stamp capture buffer to hold all events on the time line.

    The F0 being somewhat constraining as it only has 16-bit TIM

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    P S
    P SAuthor
    Associate
    March 16, 2018
    Posted on March 16, 2018 at 20:17

    Thanks for your quick reply Clive One. Your posts have already helped me out hugely in this project! I have a brushless motor control working but I have never used DMA before. I am unclear about the 'large enough time stamp capture buffer'. Would that mean if I am detecting on the rising and falling edges..  would I need a buffer to hold 8 events?  What does the DMA capture, the duration of a pulse or the timer count at each rise fall event?

    henry.dick
    Associate II
    March 16, 2018
    Posted on March 16, 2018 at 21:17

    '

    can DMA read the 4 pulses one after another like this and store in an array?'

    sounds like you are trying to read the times of input transitions.

    two approaches:

    1) dma, as you had suggested. ideally you can couple it with input filtering so there is an interrupt at end of each set of such transitions.

    2) find a chip with input capture buffers so the transitions are stored locally.

    the first approach is more universal but can be hard to pull-off. the 2nd one requires a new/different chip.

    P S
    P SAuthor
    Associate
    March 17, 2018
    Posted on March 17, 2018 at 03:16

    Thanks , its working as expected with DMA

    T J
    Senior III
    March 18, 2018
    Posted on March 18, 2018 at 00:55

    How did you arrange it ?

    DMA from the port J (for example) ? dumped into a 4k buffer type arrangement ?

    How do you calculate the time of start and time of end of each bit ?

    I thought the DMA had to fight to get hold of the bus, so you would not have a guaranteed time byte stream if it was interrupted.

    Michal Dudka
    Lead
    March 18, 2018
    Posted on March 18, 2018 at 09:26

    You can use timer in 'PWM input mode'. Configure timer to reset with rising edge and to capture time with falling edge of your signal. Configure timer to generate DMA request with capture event. It creates only one time stamp for one pulse. Probably there will be some 'delay' in timer reset, like one or two cycles, but it will be negligible error if you want distinguish 1 and 2.6us pulses.

    P S
    P SAuthor
    Associate
    March 18, 2018
    Posted on March 18, 2018 at 19:44

    This is my most likely terrible way of getting the intervals. I just have the dma_buffer big enough that it will contain at least one full cycle. When i find the blank space I store then difference between the next few time stamps. Its rough so I need to further process the output. I need to figure out when its safe to read the dma_buffer or that i am not reading a section that's in the middle of being changed.

    void computeProshotDMA(){

    int lastnumber = dma_buffer[0];

    for ( int j = 1 ; j < input_buffer_size; j++){

    if(((dma_buffer[j] - lastnumber) > 8000) && ((dma_buffer[j] - lastnumber) < 20000)){ // blank space

    propulse[0] = dma_buffer[j+1] - dma_buffer[j];

    propulse[1] = dma_buffer[j+3] - dma_buffer[j+2];

    propulse[2] = dma_buffer[j+5] - dma_buffer[j+4];

    propulse[3] = dma_buffer[j+7] - dma_buffer[j+6];

    break;

    }

    lastnumber = dma_buffer[j];

    }

    }

    dudka.michal.001 wrote:

    You can use timer in 'PWM input mode'. Configure timer to reset with rising edge and to capture time with falling edge of your signal. Configure timer to generate DMA request with capture event. It creates only one time stamp for one pulse. Probably there will be some 'delay' in timer reset, like one or two cycles, but it will be negligible error if you want distinguish 1 and 2.6us pulses.

    I have tried this and am having no luck, It seems every way I try and configure it i am only getting the rising or falling intervals. Ie I am expecting pulse durations of 80 80 80 80 after a 10,000 count blank. But am seeing 10250, 250 , 250, 250 for example.

    Michal Dudka
    Lead
    March 18, 2018
    Posted on March 18, 2018 at 21:38

    It's probably wrong timer configuration. May be some image can help - this is one configuration fo ''PWM input capture'':

    0690X00000604UPQAY.jpg

    Because you are not interesed in capturing period, you will not use Capture 2. Configure Capture 1 to catch falling edge from ''indirect'' source. Next configure TI2FP2 to detect rising edge. Set up Slave Mode Controller to reset timer. Example follows:

    icinit.TIM_Channel = TIM_Channel_2; icinit.TIM_ICFilter = 0x0;  icinit.TIM_ICPolarity = TIM_ICPolarity_Rising;  icinit.TIM_ICPrescaler = TIM_ICPSC_DIV1; icinit.TIM_ICSelection = TIM_ICSelection_DirectTI; // TI2FP2 TIM_ICInit(TIM3, &icinit);

    icinit.TIM_Channel = TIM_Channel_1; icinit.TIM_ICFilter = 0x0;  icinit.TIM_ICPolarity = TIM_ICPolarity_Falling;  icinit.TIM_ICPrescaler = TIM_ICPSC_DIV1;  icinit.TIM_ICSelection = TIM_ICSelection_IndirectTI; // signal from channel 2 (TI2FP1) TIM_ICInit(TIM3, &icinit);

    TIM_SelectInputTrigger(TIM3,TIM_TS_TI2FP2); // Event for Reset Controller from rising edge TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset); // Reset timer with that event

    next configure DMA to transfer data from Capture 1 register to memory (i think you want use circular mode). Enable DMA ''transfer complete'' interrupt (which will indicate that burst is over and collected data waits for you). Enable DMA request in timer (request from Capture1 event). 

    There will be one more problem with enabling timer. You must do it in ''pause'' between pulse bursts. Bursts have to be separated by some time (roughly more then ~5-10us). You can identify this ''pause''  by few clever or stupid ways. Stupid (but sufficient) one is:

    1. init, but not start, some timer (TIM6 for example)

    2. wait for falling edge at line (wait for log.1 then wait for log.0)

    3. (re)start that timer (TIM6)

    4. wait until timer counts to ~5us or to falling edge, if falling edge comes soon, go to point 3.

    5. if your timer counts to 5us without detecting next falling edge, you are in ''pause'' time and you can start main timer (TIM3 in this example). If you are worry that two bursts can rarely comes without sufficient ''pause'' you can set up DMA to take 8 values and enable also ''half transfer'' interrupt. Then you can processing old data and capturing new in same time.