Blue Pill counting number of pulses using timers

Post here all questions related to LibMaple core if you can't find a relevant section!
Kovaxant
Posts: 7
Joined: Wed Mar 18, 2020 7:39 am

Blue Pill counting number of pulses using timers

Post by Kovaxant »

Hello everyone!

My first post and asking for help already. I'm new to all this arduino and Blue Pill stuff. Had to learn a lot to solve a problem.
What I'm trying to do is count the number of pulses every second for 5ms. I'm using counters for time interrupts and for counting the number of pulses.
I have checked with my oscilloscope that the board gets the pulses at the proper pin. When copilling I get no errors, but the serial shows 67 pulses counted while there should be more than 200 (I'm feeding it a 44100 Hz signal). Moreover it "counts" those 67 pulses with no signal attached. Every now and then it shows 85 counted pulses. I could use some help.

Cheers, Domagoj

Here''s the code:

Code: Select all

/*
Pulses counter

*/

#define COUNT_RATE 1000000  // in microseconds; gives 1Hz toggles
#define COUNT_TIME 5000 // in microseconds; gives 5ms count time

uint16_t timer3CH1CounterValue;

void setup()
{
  Serial.begin(115200);
  
  // setup PA6 (Timer3 channel 1) as input (capture input mode)
  pinMode(PA6, INPUT);
    
  // setup timer 2 interrupt after COUNT_RATE microseconds
  Timer2.setMode(TIMER_CH1, TIMER_OUTPUTCOMPARE);
  Timer2.setPeriod(COUNT_RATE); // in microseconds
  Timer2.setCompare(TIMER_CH1, 1); // Overflow
  Timer2.attachInterrupt(TIMER_CH1, count_pulses);
}

void loop()
{
}

void count_pulses(void) // configure timers, starts counting
{
  // stop the timers before configuring them
  Timer3.pause();
  Timer4.pause();
  
  // setup timer 3 channels 1 and 2 capture on rising edge
  Timer3.setMode(TIMER_CH1, TIMER_INPUT_CAPTURE); 
   
  Timer3.refresh(); // reset the counter to 0, update configuration
  
  Timer3.getCompare(TIMER_CH1); // clear capture flag NEEDED?
   
  // setup timer 4 interrupt after COUNT_TIME microseconds
  Timer4.setMode(TIMER_CH1, TIMER_OUTPUTCOMPARE);
  Timer4.setPeriod(COUNT_TIME); // in microseconds
  Timer4.setCompare(TIMER_CH1, 1); // Overflow
  Timer4.attachInterrupt(TIMER_CH1, stop_count);
  
  Timer4.refresh(); // reset the counter to 0, update configuration
  
  // start the timers 3 and 4
  Timer3.resume();
  Timer4.resume();  
}

void stop_count(void) // stops counting, displays number of counts  
{
  // get the number of counts
  timer3CH1CounterValue = Timer3.getCount();
    
  // stop the timers
  Timer3.pause();
  Timer4.pause();
  
  // display the number of counts
  Serial.print("Count 1: ");
  Serial.println(timer3CH1CounterValue);
}
[code]
by stevestrong » Wed Mar 18, 2020 1:38 pm
I knew I have posted a similar example already somewhere.
Now i have found it: https://web.archive.org/web/20190316154 ... =18&t=3804
Go to full post
ag123
Posts: 1668
Joined: Thu Dec 19, 2019 5:30 am
Answers: 25

Re: Blue Pill counting number of pulses using timers

Post by ag123 »

i think the timers has some sort of schmitt triggers (edge triggering) so perhaps if it isn't square waves at the right level it may not trigger?
for non-square waves you may need a separate comparator prior the pin. if you want on chip solution stm32f303 has comparators on chip
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: Blue Pill counting number of pulses using timers

Post by stevestrong »

I don't understand why do you need 3 timers to count some pulses...
Can you describe your logic?
Kovaxant
Posts: 7
Joined: Wed Mar 18, 2020 7:39 am

Re: Blue Pill counting number of pulses using timers

Post by Kovaxant »

stevestrong wrote: Wed Mar 18, 2020 9:00 am I don't understand why do you need 3 timers to count some pulses...
Can you describe your logic?
Hi,
This code is just a part of the project of controlling the functions of a hifi DAC. Intention is to have it count "in the background". As I understand that is accomplished using hardware timers. Now, this is probably not the most elegant way (I'm all ears) but it should work. Any pointers regarding the code guys?

I do appreciate the help and the discussion.
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: Blue Pill counting number of pulses using timers

Post by stevestrong »

I suggest to make a simple sketch for only counting the pulses.
But first you should describe the logic how do you want to achieve the counting with those timers.
How exact should be the 5 ms measuring period?

You could use the slave gated mode to achieve your goal, see RM0008 15.3.14.
Kovaxant
Posts: 7
Joined: Wed Mar 18, 2020 7:39 am

Re: Blue Pill counting number of pulses using timers

Post by Kovaxant »

stevestrong wrote: Wed Mar 18, 2020 9:22 am I suggest to make a simple sketch for only counting the pulses.
But first you should describe the logic how do you want to achieve the counting with those timers.
How exact should be the 5 ms measuring period?

You could use the slave gated mode to achieve your goal, see RM0008 15.3.14.
I have tested independently both interrupt timers with LEDs and oscilloscope - they perform as intended. Getting the pulse count is not working as I can tell. Exact measuring period is not a high priority. Digital audio is distributed in strict frequencies, so there is a lot of tolerance available with the number of counts. I am not trying to measure frequency with great accuracy. Timer2 issues an interrupt every second and starts the function "count_pulses". "Count_pulses" starts the actual pulses counter - Timer3 and Timer4 which stops the counting after 5ms by calling "stop_count". Then

Code: Select all

timer3CH1CounterValue = Timer3.getCount();
should get the number of pulses which later get to be displayed.

RM0008 15.3.14. that is way out of my league. As much as I can tell slave gated mode cannot measure signals of around 25MHz? I could be mistaken.
But from what I have red it works up to several 100s of KHz. Pls DO correct me if I'm wrong, I'm very very new to all of this.
stevestrong
Posts: 502
Joined: Fri Dec 27, 2019 4:53 pm
Answers: 8
Location: Munich, Germany
Contact:

Re: Blue Pill counting number of pulses using timers

Post by stevestrong »

For 1 sec IRQ you don need any compare channel, just use the update interrupt for that.
I would do it like this:

Code: Select all

Timer2.init();
Timer2.pause(); // stop the timer
Timer2.setPeriod(COUNT_RATE);
Timer2.refresh();
Timer2.attachInterrupt(TIMER_UPDATE, count_pulses); // should be done after refresh() !!!
Timer2.resume(); // start the timer
I am not sure about the Timer3 and 4 settings, check the reference manual for how to setup the timers to use external clock mode.
ABOSTM
Posts: 60
Joined: Wed Jan 08, 2020 8:40 am
Answers: 7

Re: Blue Pill counting number of pulses using timers

Post by ABOSTM »

Hi Kovaxant ,
Can you tell us which core you are using?

Reading your sketch, I think there is a misunderstanding:
In the principle, in Input Capture mode, timer counter is running, and input signal triggers the capture. It means for example that on rising edge the counter value will be stored in register and accessible with getCount().
So with input capture you can measure time between pulses but you will not count pulses.
InputCapture doesn't really match your need.

Nevertheless there are possibilities to achieve your needs:
* simple, using Arduino API, but not very efficient
Use 1 timer to count your 5ms
Attach an interrupt on an input GPIO, and in the associated callback increment your pulse count.
This will not be efficient due to software overhead for interruption callback() treatment which will occurs at the input frequency 44KHz and thus I am not sure you will be able to reach you goal. It depends on callback duration/implementation. I would suggest to test with lower frequency first.

* More complex using HAL API, but much more efficient
It is possible to use full STM32 Hardware performances, but this is not accessible by Arduino API (at least Arduino_Core_STM32).
Reminder HAL API can be used directly in Arduino sketch.
Idea is to use Timer Hardware capability that allows to count at external signal rate... without software overhead.
RM0008 15.3.3 is much more interesting, specially "External clock source mode 2".
A second timer can be used to measure 50ms, or you can simply use standard Arduino delay()
Kovaxant
Posts: 7
Joined: Wed Mar 18, 2020 7:39 am

Re: Blue Pill counting number of pulses using timers

Post by Kovaxant »

stevestrong wrote: Wed Mar 18, 2020 10:52 am For 1 sec IRQ you don need any compare channel, just use the update interrupt for that.
I would do it like this:

Code: Select all

Timer2.init();
Timer2.pause(); // stop the timer
Timer2.setPeriod(COUNT_RATE);
Timer2.refresh();
Timer2.attachInterrupt(TIMER_UPDATE, count_pulses); // should be done after refresh() !!!
Timer2.resume(); // start the timer
I am not sure about the Timer3 and 4 settings, check the reference manual for how to setup the timers to use external clock mode.
'class HardwareTimer' has no member named 'init' is what the compiler has to say on subject. Looks like you are using a different library.

Code: Select all

  Timer2.pause(); // stop the timer
  Timer2.setPeriod(COUNT_RATE);
  Timer2.refresh();
  Timer2.attachInterrupt(TIMER_CH1, count_pulses); // should be done after refresh() !!!
  Timer2.resume(); // start the timer
This worked fine. So thank you for that piece of code. :D
Kovaxant
Posts: 7
Joined: Wed Mar 18, 2020 7:39 am

Re: Blue Pill counting number of pulses using timers

Post by Kovaxant »

ABOSTM wrote: Wed Mar 18, 2020 12:34 pm Hi Kovaxant ,
Can you tell us which core you are using?

Reading your sketch, I think there is a misunderstanding:
In the principle, in Input Capture mode, timer counter is running, and input signal triggers the capture. It means for example that on rising edge the counter value will be stored in register and accessible with getCount().
So with input capture you can measure time between pulses but you will not count pulses.
InputCapture doesn't really match your need.

Nevertheless there are possibilities to achieve your needs:
* simple, using Arduino API, but not very efficient
Use 1 timer to count your 5ms
Attach an interrupt on an input GPIO, and in the associated callback increment your pulse count.
This will not be efficient due to software overhead for interruption callback() treatment which will occurs at the input frequency 44KHz and thus I am not sure you will be able to reach you goal. It depends on callback duration/implementation. I would suggest to test with lower frequency first.

* More complex using HAL API, but much more efficient
It is possible to use full STM32 Hardware performances, but this is not accessible by Arduino API (at least Arduino_Core_STM32).
Reminder HAL API can be used directly in Arduino sketch.
Idea is to use Timer Hardware capability that allows to count at external signal rate... without software overhead.
RM0008 15.3.3 is much more interesting, specially "External clock source mode 2".
A second timer can be used to measure 50ms, or you can simply use standard Arduino delay()
In preferences I found the following link which I got following some online tutorial:

http://dan.drown.org/stm32duino/package ... index.json

It seems that I am heading straight to the HAL land. Any pointers how to use HAL drivers in an Arduino sketch?

Regards, Domagoj
Post Reply

Return to “General discussion”