Timer "Input Capture" ?

Cesco
Mon Apr 18, 2016 3:42 pm
Hi, i do use timer1 and timer4 for PWM output, works nicely.

Now i want to use pin PA0, timer2 channel1, for input capture. Are there any examples?
With Timer2.setMode(TIMER_CH1,mode) function, what mode must i use? What else must i set?

I have a hard time finding documentation or header files for arduino-stm32 environment. Where should i look?


mrburnette
Mon Apr 18, 2016 4:42 pm
Hello and welcome, Cesco:

The prototype functions for timerx are here

I scanned our site and could not find any hits, but on the old Leaflabs forum, I found 2 discussions that may assist you:

http://forums.leaflabs.com/topic.php?id=1291

http://forums.leaflabs.com/topic.php?id=737&page=2

Good luck. If you get it working, please consider posting an example … the Snippets sub-forum is a good place.

Ray


Cesco
Mon Apr 18, 2016 5:44 pm
Uluckily i found in timer.h :

/* TIMER_INPUT_CAPTURE, TODO: In this mode, the timer can measure the pulse lengths of input signals */

TODO means its not implemented :(


Cesco
Tue Apr 19, 2016 10:27 am
Made it:

#define RX1 PA0 //t2c1

void init_rx()
{
pinMode(RX1, INPUT);

Timer2.setPrescaleFactor(72);

TIMER2->regs.gen->CCMR1 = 0b010000001;
TIMER2->regs.gen->CCMR2 = 0b0;
TIMER2->regs.gen->CCER = 0b0001;

Timer2.attachCompare1Interrupt(ppm_input);
}

uint16_t last;
uint8_t chan = 0;
boolean newrc = false;

void ppm_input(void)
{
uint16_t diff,act;
act = TIMER2->regs.gen->CCR1;

......


mrburnette
Tue Apr 19, 2016 1:13 pm
Congrats!

And thanks for posting the sample code. We also have a ‘snippets’ section that I generally recommend to members for such things, it is just another way to get visibility and socialize the solution.

Ray


RogerClark
Tue Apr 19, 2016 9:46 pm
@cesco

Do you think it would be possible to use your code in the “core” where it currently has TO DO… ?

It would be great if we could.


Cesco
Thu Apr 21, 2016 11:02 am
> Do you think it would be possible to use your code in the “core” where it currently has TO DO… ?

Input capture is quite complex. There are parameters for filter and prescaler, capture units can be cross-linked, lots of complicated goodies.

Concentrating on the basic function, no prescaler, no filter, just parameter for rising or faling edge schould be doable. I did search an NOT find where timer.c is. The file structure is quite hard to understand.


martinayotte
Thu Apr 21, 2016 12:31 pm
Cesco wrote:I did search an NOT find where timer.c is. The file structure is quite hard to understand.

racemaniac
Thu Apr 21, 2016 1:27 pm
martinayotte wrote:Cesco wrote:I did search an NOT find where timer.c is. The file structure is quite hard to understand.

martinayotte
Thu Apr 21, 2016 2:38 pm
All those directories structure is coming from the legacy code of LeafLab, they are not even consistent between STM32F1 and STM32F4, but we need to live with it.

racemaniac
Thu Apr 21, 2016 2:54 pm
martinayotte wrote:All those directories structure is coming from the legacy code of LeafLab, they are not even consistent between STM32F1 and STM32F4, but we need to live with it.

martinayotte
Thu Apr 21, 2016 3:05 pm
The task is too huge for the moment, so nobody wish to brake existing hierarchy.
There also tons of sub-tasks we wished, such as putting much common code between platforms together, but again those are huge too.
Refactoring has always been difficult on any projects, especially when “time is the missing ingredient” … :?

racemaniac
Thu Apr 21, 2016 3:16 pm
martinayotte wrote:The task is too huge for the moment, so nobody wish to brake existing hierarchy.
There also tons of sub-tasks we wished, such as putting much common code between platforms together, but again those are huge too.
Refactoring has always been difficult on any projects, especially when “time is the missing ingredient” … :?

Cesco
Fri Apr 22, 2016 3:40 am
What i did (or what i can remember):

timer.c in STM32F1\system\libmaple\include\libmaple timer_set_mode()
case TIMER_INPUT_CAPTURE:
input_capture_mode(dev, channel);
break;


RogerClark
Fri Apr 22, 2016 7:06 am
Can you zip your files and attach them?

In the mean time I’m going to try to add the code you posted, but I don’t think its complete

Edit

I looked at the code for

attachCompare1Interrupt(ppm_input);

and this function is deprecated.

HardwareTimer.h reads

/** @brief Deprecated; use attachInterrupt(TIMER_CH1, handler) instead. */
void attachCompare1Interrupt(voidFuncPtr handler) {
attachInterrupt(TIMER_CH1, handler);
}


Cesco
Fri Apr 22, 2016 11:44 am
Reading inside interrupt handler:
uint16_t act = TIMER2->regs.gen->CCR1;

mrburnette
Fri Apr 22, 2016 1:00 pm
racemaniac wrote:
<…>
As in all big projects, try to get there with small steps whenever you have some time ^^’.
<…>

RogerClark
Fri Apr 22, 2016 10:03 pm
Hi Ray

The more I look at the HALMX core, the more I appreciate what leaflabs managed to do with libmaple.

Libmaple now looks nimble compared with the vast array of files that are needed to support multiple boards in the HALMX.

Libmaple’s USB Serial seems to take 8k but STMs version appears to take 20k ( of flash ).

But there is nothing to stop us improving, adding to, bug fixing and tidying up libmaple, while at the same time, people can work on HALMX if they want to.

Complaining about libmaple not using the CMSIS etc, seems to be a common sport, but I see hardly anyone doing anything to build anything better (@sheepdoll and @vassilis accepted)


mrburnette
Fri Apr 22, 2016 10:41 pm
RogerClark wrote:
<…>
The more I look at the HALMX core, the more I appreciate what leaflabs managed to do with libmaple. Libmaple now looks nimble compared with the vast array of files that are needed to support multiple boards in the HALMX. Libmaple’s USB Serial seems to take 8k but STMs version appears to take 20k ( of flash ). But there is nothing to stop us improving, adding to, bug fixing and tidying up libmaple, while at the same time, people can work on HALMX if they want to. Complaining about libmaple not using the CMSIS etc, seems to be a common sport, but I see hardly anyone doing anything to build anything better (@sheepdoll and @vassilis accepted)

alexandros
Thu Jan 18, 2018 2:52 pm
sorry guys is that TIMER_INPUT_CAPTURE , avalable in the library ?
i want to use Input capture method , instead of AttachInterrupt i read that is faster MCU/2 speed.

RogerClark
Thu Feb 08, 2018 11:06 pm
Interesting..

I think I can use this in my AC dimmer project


RogerClark
Fri Feb 09, 2018 10:00 pm
I’m trying to add this code to the core

However, there is one thing I don’t understand.

Is only one of the GPIO’s connected to each timer ?

The timer has its input set to

TIMER_CCMR_CCS_INPUT_TI1

But I don’t see how the input GPIO pin is routed to this ??

Edit.

I now see

#define RX1 PA0 //t2c1


RogerClark
Sat Feb 10, 2018 12:10 am
OK.

Just to answer my own question…

As far as I can see from

http://www.st.com/content/ccc/resource/ … 161566.pdf

These are the timers which have an ETR pin

Timer1 PA12 or PE7 (remap)
Timer2 PA0 or PA15 (remap)
Timer3 PD2
Timer4 PE0

But for the Blue Pill and Maple mini etc (F103Cx) only Timer2 can be used if you are using the bootloader, because PA12 (Timer1) is one of the USB signal s.

The remapping of the ETR seems to be controlled by the register AFIO_MAPR (see section 9.4.2 of the reference manual, on page 183)

This has remapping for Timers 1, 2,3 and 4


Bit 12 TIM4_REMAP: TIM4 remapping
This bit is set and cleared by software. It controls the mapping of TIM4 channels 1 to 4 onto
the GPIO ports.
0: No remap (TIM4_CH1/PB6, TIM4_CH2/PB7, TIM4_CH3/PB8, TIM4_CH4/PB9)
1: Full remap (TIM4_CH1/PD12, TIM4_CH2/PD13, TIM4_CH3/PD14, TIM4_CH4/PD15)
Note: TIM4_ETR on PE0 is not re-mapped.

Bits 11:10 TIM3_REMAP[1:0]: TIM3 remapping
These bits are set and cleared by software. They control the mapping of TIM3 channels 1 to
4 on the GPIO ports.
00: No remap (CH1/PA6, CH2/PA7, CH3/PB0, CH4/PB1)
01: Not used
10: Partial remap (CH1/PB4, CH2/PB5, CH3/PB0, CH4/PB1)
11: Full remap (CH1/PC6, CH2/PC7, CH3/PC8, CH4/PC9)
Note: TIM3_ETR on PE0 is not re-mapped.

Bits 9:8 TIM2_REMAP[1:0]: TIM2 remapping
These bits are set and cleared by software. They control the mapping of TIM2 channels 1 to
4 and external trigger (ETR) on the GPIO ports.
00: No remap (CH1/ETR/PA0, CH2/PA1, CH3/PA2, CH4/PA3)
01: Partial remap (CH1/ETR/PA15, CH2/PB3, CH3/PA2, CH4/PA3)
10: Partial remap (CH1/ETR/PA0, CH2/PA1, CH3/PB10, CH4/PB11)
11: Full remap (CH1/ETR/PA15, CH2/PB3, CH3/PB10, CH4/PB11)

Bits 7:6 TIM1_REMAP[1:0]: TIM1 remapping
These bits are set and cleared by software. They control the mapping of TIM1 channels 1 to
4, 1N to 3N, external trigger (ETR) and Break input (BKIN) on the GPIO ports.
00: No remap (ETR/PA12, CH1/PA8, CH2/PA9, CH3/PA10, CH4/PA11, BKIN/PB12,
CH1N/PB13, CH2N/PB14, CH3N/PB15)
01: Partial remap (ETR/PA12, CH1/PA8, CH2/PA9, CH3/PA10, CH4/PA11, BKIN/PA6,
CH1N/PA7, CH2N/PB0, CH3N/PB1)
10: not used
11: Full remap (ETR/PE7, CH1/PE9, CH2/PE11, CH3/PE13, CH4/PE14, BKIN/PE15,
CH1N/PE8, CH2N/PE10, CH3N/PE12)


RogerClark
Sat Feb 10, 2018 1:22 am
OK…

The remaping can already be handled by

afio_remap( AFIO_REMAP_TIM2_PARTIAL_1); //etc


RogerClark
Sat Feb 10, 2018 1:27 am
This does still leave the polarity.

I think this may need to be handled by a new gpio_xxxx function, as would reading the value from the timer


RogerClark
Sat Feb 10, 2018 2:39 am
Looks like Leaflab already wrote the function to get the value

static inline uint16 timer_get_compare(timer_dev *dev, uint8 channel) {
__io uint32 *ccr = &(dev->regs).gen->CCR1 + (channel - 1);
return *ccr;
}


RogerClark
Sat Feb 10, 2018 3:50 am
OK

I’ve added this functionality to the Core

But. I still need to decide how to add input polarity selection

I’ve included an example in the Sensors section, as thats where the Hardware Timer Encoder example is

Grab the latest version of the repo and you can try the example

(Now on to what I really wanted which is the “One Pulse” feature ;-)

/* Example of the Timer Input Capture mode
*
* Thanks to @cesco on the stm32duino.com
*
* This example uses Timer2. Other timers also support this mode, bnt on the F103C
* only Timer 2 has usable external trigger pins. PA0 and PA15
* Because the only other usable pin on the F103C is one of the USB pins.
*
* Upload to your favourite F103Cx
* Open the Serial plotter
* Put your finger on either PA0 or PA15 (depenidng whether you USE the pin remapping)
*
* Observe your local mains frequency in terms of pulse width time.
*
*/

/* Timer2 external trigger can be ether PA0 or PA15.
To use use afio_remap(FIO_REMAP_TIM2_PARTIAL_1) or afio_remap(AFIO_REMAP_TIM2_FULL)
Note. using afio_remap also changes the pins used by Timer2 CH1,CH2,CH3 amd CH4
* See page 184 of the STM32F10x Refernce manual (PDF downloadable from ST.com
*/

//#define USE_REMAP_PIN
#ifdef USE_REMAP_PIN
const int timer2ExternalTriggerPin = PA15;
#else
const int timer2ExternalTriggerPin = PA0;
#endif

volatile boolean hasCapture;
volatile uint16_t captureValue;
volatile uint16_t lastCaptureValue=0;
volatile uint16_t captureDifference=0;

void captureCallback(void) {

hasCapture=true;
captureValue = Timer2.getCompare(1);
captureDifference = captureValue-lastCaptureValue;
lastCaptureValue=captureValue;
}

void setup() {

pinMode(timer2ExternalTriggerPin,INPUT);

#ifdef USE_REMAP_PIN
afio_remap(AFIO_REMAP_TIM2_PARTIAL_1);
#endif

hasCapture = false;

Timer2.setPrescaleFactor(72); // prescaler to count 72,000,000 / 72 counts per second. i.e count microseconds
Timer2.setMode(TIMER_CH1, TIMER_INPUT_CAPTURE);
Timer2.attachCompare1Interrupt(captureCallback);

}

void loop() {

// Printing inside the callback is not a good idea.
// Hence the capture callback sets a flag , which is detected here
if (hasCapture)
{
Serial.println(captureDifference);
hasCapture=false;
}
}


stevestrong
Sat Feb 10, 2018 10:44 pm
What exactly has the example sketch on purpose? To measure the high period of a pulse? Or the time between two input capture events?
Anyway, reading capture values within ISR is not the best method to get precise values.

RogerClark
Sat Feb 10, 2018 10:52 pm
Steve

I just used the code provided by @Cesco

But I now see that it has problems
I think the config is wrong.
The counter seems to free run and the ISR gets called when the input pin changes.

Looking at the original code (from Leaflabs) they thought that there would be a pinMode() for INPUT_CAPTURE, but as you have pointed out on GitHub this only allows very limited functionality

So perhaps this is not the correct way to add this functionality, and instead perhaps the Hardware Timer class should have additional functions

e.g.

TimerX.setInputCaptureMode(args …..)

and also

TimerX.setOnePulseMode(args….)

This would then allow better configuration.


stevestrong
Sat Feb 10, 2018 11:07 pm
Roger, do you refer to this code example: viewtopic.php?f=3&t=2008&p=26987#p27037 ?
This is from @konczakp, not @cesco.

Anyway, you are right, it misses to set the timer in slave mode reset mode (SMS = b100) and to select the right trigger, so that the CCR1 register value is steady after the input signal trigger occurred.

See RM0008 rev.16, p. 383-384, chapter 15.3.6 PWM input mode:
For example, you can measure the period (in TIMx_CCR1 register) and the duty cycle (in TIMx_CCR2 register) of the PWM applied on TI1 using the following procedure (depending on CK_INT frequency and prescaler value):
• Select the active input for TIMx_CCR1: write the CC1S bits to 01 in the TIMx_CCMR1 register (TI1 selected).
• Select the active polarity for TI1FP1 (used both for capture in TIMx_CCR1 and counter clear): write the CC1P to ‘0’ (active on rising edge).
• Select the active input for TIMx_CCR2: write the CC2S bits to 10 in the TIMx_CCMR1 register (TI1 selected).
• Select the active polarity for TI1FP2 (used for capture in TIMx_CCR2): write the CC2P bit to ‘1’ (active on falling edge).
• Select the valid trigger input: write the TS bits to 101 in the TIMx_SMCR register (TI1FP1 selected).
• Configure the slave mode controller in reset mode: write the SMS bits to 100 in the TIMx_SMCR register.
• Enable the captures: write the CC1E and CC2E bits to ‘1 in the TIMx_CCER register.

Me, I am using duty cycle measuring in one of my projects according to this description.

The reference manual has too many examples (with many different options) to be all supported / implemented in the core.
I really cannot see how the HardwareTimer class should be changed to support them.
It would be nice if we would have one example sketch for all of them, even with direct register settings. But I think no one has the necessary time.


RogerClark
Sun Feb 11, 2018 3:03 am
Thanks

I’ll look at that other code


RogerClark
Sun Feb 11, 2018 10:40 am
I’ve reverted the commit that added the Input Capture feature as the code I took from this thread as some major problems :-(

stevestrong
Sun Feb 11, 2018 2:44 pm
I reworked the input capture mode handling and added two examples:
– input capture + one pulse mode
– PWM mode (using input capture) to measure PWM pulse and period width.

https://github.com/stevstrong/Arduino_S … de99ba8ac0


RogerClark
Sun Feb 11, 2018 8:35 pm
Thanks Steve

I will try your code later today.


RogerClark
Mon Feb 12, 2018 7:17 am
Steve

I’ve manually copied your updated files and your HardwareTimerPWMInput demo worked fine.

I’ve not tested this copy of your One Pulse demo, but I presume its the same as the one you posted to the forum, so I will test later to confirm its OK

Your files also included my old demo using @konzpcap’s code, but I think I will delete it, as its the wrong way to do input capture

I may also modify your One Pulse demo to show you to use an external trigger for to the timer

Then I’ll commit the changes back to my repo.

BTW. I presume that you can’t do a PR because your repo is too different from mine.

Thanks

Roger


stevestrong
Mon Feb 12, 2018 8:23 am
[RogerClark – Mon Feb 12, 2018 7:17 am] –
BTW. I presume that you can’t do a PR because your repo is too different from mine.

Indeed, and because Github is still a mystery for me, I didn’t even offer to do a PR. I can do it for individual files on web github, but not for more than one. Sorry.


RogerClark
Mon Feb 12, 2018 8:29 am
No worries

It wasn’t too many files to copy manually ;-)


RogerClark
Tue Feb 13, 2018 8:47 am
OK.

I’ve pushed the updated files from @stevestrong, which work correctly for Input Capture and OnePulse


Leave a Reply

Your email address will not be published. Required fields are marked *