Counting rising edges on two different pins doesn't work properly :(

Hi everyone,

Hardware: NUCLEO-F767ZI (NUCLEO-F767ZI | Mbed)

I’m trying to detect rising edges on two different pins: PF_14 and PF_15.

I provided some signals locally (using the same board: NUCLEO-F767ZI). I used PD_12 and PD_13 to create two PWM signals and I wired these two pins to the counter pins PF_14 and PF_15.

Here is my output:
Count1: 0 Count2: 1
Count1: 1000 Count2: 1
Count1: 2000 Count2: 1
Count1: 3000 Count2: 1
Count1: 4000 Count2: 1
Count1: 5000 Count2: 1
Count1: 6000 Count2: 1

As you see the first counter is detecting 1000 edges/s which matches the frequency of myPWM1. However, I don’t get why counter2 is only detecting 1 edge ( not 1 edge/s). It’s also interesting that when myPWM1 and myPWM2 share the same frequency the counters are working properly and detect the same amount of edges per second.

Here is my code:

<>

#include “mbed.h”

PwmOut myPWM1(PD_12);
PwmOut myPWM2(PD_13);

class Counter {
public:
Counter(PinName pin)
: _interrupt(
pin) { // create the InterruptIn on the pin specified to Counter
_interrupt.rise(
callback(this, &Counter::increment)); // attach increment function of
// this counter instance
}

void increment() { _count++; }

int read() { return _count; }

private:
InterruptIn _interrupt;
volatile int _count;
};

Counter counter1(PF_14);
Counter counter2(PF_15);

int main() {
while (1) {
myPWM1.period(1.0 / 500.0f);
myPWM1.write(0.5f);

myPWM2.period(1.0 / 1000.0f);
myPWM2.write(0.5f);
printf("Count1: %d\t Count2: %d\n", counter1.read(), counter2.read());
ThisThread::sleep_for(1000ms);

}
}

<>

I apreciate you’re help!

best regards,
Yassine

Hello,

first of all, place this out of while loop, it makes no sense.

Did you try it with another pins?

BR, Jan

Hi JohnnyK,

sorry somehow I forgot it inside the loop.

Yes I’ve tried it multiple times with different pins. It didn’t work.

best regards,
Yassine

Hi,

I think that the problem is you are using same PWM channel.
PD_12 = PWM4/1
PD_13 = PWM4/2

If I change the myPWM1 pin from PD_12 to PA_0 (PWM2/1), it works as expected.

Count1: 0. Count2: 0
Count1: 500. Count2: 1000
Count1: 1001. Count2: 2002
Count1: 1502. Count2: 3004
Count1: 2003. Count2: 4006
Count1: 2504. Count2: 5008
Count1: 3005. Count2: 6010
Count1: 3506. Count2: 7012
Count1: 4007. Count2: 8014
Count1: 4508. Count2: 9016
Count1: 5009. Count2: 10018
Count1: 5510. Count2: 11020
Count1: 6011. Count2: 12022
Count1: 6512. Count2: 13024

Thanks,
Toyo

it works. Do you have any idea why it doesn’t work when I put it in my main code ?

Here is the code:

#include “mbed.h”
#include
#include
#include

// Parameter des Einspritzsignals
AnalogIn t_oefnen(PA_3);
AnalogIn t_einspritzen(PC_0);
DigitalIn BM1_BM2(PB_8); // Auswahl des Betriebsmodus
AnalogIn KW_position(PC_3);

// Ausgang des Einspritzsignals
PwmOut einspritzung(PE_11);

// Parameter zur Pumpensteuerung
AnalogIn frequenz(PF_3);
AnalogIn tastgrad(PF_5);
PwmOut pwm_pumpe(PB_9); // Ausgang zur Pumpenstueuerung

// Kurbelwellensignal
PwmOut myPWM1(PD_13);
// Nockemwellensignal
PwmOut myPWM2(PA_0);

// test area
DigitalOut led(LED1);

const int teeth_count = 80; // Gesamtzahl der Zähne
volatile float time_between_edges = 0.0f;
const int Winkel_offset = 47; // Gesamtzahl der Zähne

class Counter {
public:
Counter(PinName pin)
: _interrupt(
pin) { // create the InterruptIn on the pin specified to Counter
_interrupt.fall(
callback(this, &Counter::increment)); // attach increment function of
// this counter instance
}

void increment() { _count++; }

int read() { return _count; }

void reset() { _count = 0; }

private:
InterruptIn _interrupt;
volatile int _count;
};

Counter counter1(PF_14);
Counter counter2(PF_15);

int main() {

BM1_BM2.mode(PullUp);

//KW-Signal
myPWM1.period(1.0 / 10000.0f);
myPWM1.write(0.5f);
//NW-Signal
myPWM2.period(1.0 / 10.0f);
myPWM2.write(0.5f);

Timer t1; // create a Timer object
t1.start(); // start the timer

Timer t2; // create a Timer object
t2.start(); // start the timer

int prev_count = 0;

// int prev_count = 0;
while (1) {

// Potisdaten auslesen:

float pot01_value, pot02_value, pot03_value, pot04_value, pot05_value,
      wait_time01, wait_time02, wait_time03;

pot01_value = t_oefnen.read();
wait_time01 = pot01_value * 10.0f;

pot02_value = t_einspritzen.read();
wait_time02 = pot02_value * 10.0f;

pot03_value = KW_position.read();
wait_time03 = pot03_value * 10.0f;

// Pumpensteuerung
pot04_value = 1.0 / (frequenz.read() * 1000.0);
pot05_value = tastgrad.read();

pwm_pumpe.period(pot04_value);
pwm_pumpe.write(pot05_value);

if (BM1_BM2 == true) {
    
for (int i = 0; i <= 1000; i++) {

//printf(“Starting the loop\n”);

    if (BM1_BM2 == false) {
        break; // stop the loop if BM1_BM2 is false
    }
    led = 1;
    // read and process t_oefnen
    einspritzung.write(1);
    wait_us(wait_time01 * 1000);

    // read and process t_einspritzen
    einspritzung.period(1.0f / 15000.0f);
    einspritzung.write(0.5f);
    wait_us(wait_time02 * 1000);

    // read and process t_wiederholung
    einspritzung.write(0);

    printf("wait_time01: %f \t wait_time02: %f \n", wait_time01*1000, wait_time02*1000);
}


} else {
  led = 0;
  int count1 = counter1.read();
  float period = std::chrono::duration<float>{t1.elapsed_time()}
                     .count(); // get the elapsed time since start
  float rpm = ((count1 / period) * 60.0) /
              teeth_count; // Drehzahl in U/min berechnen

  int count2 = counter2.read();

  if (count2 > prev_count) { // Second edge detected      // read and
                             // process t_oefnen

    wait_us(wait_time03 * 1000);
    einspritzung.write(1);
    wait_us(wait_time01 * 1000);

    // read and process t_einspritzen

    einspritzung.period(1.0f / 15000.0f);
    einspritzung.write(0.5f);
    wait_us(wait_time02 * 1000);

    // read and process t_wiederholung

    einspritzung.write(0);
    time_between_edges =
        std::chrono::duration<float>{t2.elapsed_time()}.count();
    // printf("Elapsed time: %lld s\n", t.elapsed_time().count());
    t2.stop();  // Stop the timer to prevent it from continuing to run in
                // the background
    t2.reset(); // Reset the timer for the next measurement
    t2.start(); // Start the timer again for the next measurement
  }

  printf("count1: %d \t prev_count: %d \t count2: %d  \n", count1,prev_count, count2 );
  prev_count = count2;

  t1.reset(); // reset the timer

  counter1.reset();
  counter2.reset();

  ThisThread::sleep_for(1000ms);
}

}
}

I apreciate your help!

best regards,
ezzow

Hi,

PE_11    PWM1/2
PB_9     PWM4/4
PD_13    PWM4/2
PA_0     PWM2/1

You are still using same channel of the PWM.
Or, the Timer instance probably conflict timer resource with PWM?

Ups! I thought shared pwm channels cause problems only in interruptIn. It’s working properly.

many thanks!

Do you have any idea where can I find these kind of limitations?

best regards,
ezzow

Because the hardware has limited resource. The PwmOut is implemented to use timer resource for STM32.
You can not set different timer values to single hardware timer.

Thanks,
Toyo

1 Like

Below on this page is a description about PWM pins - ST - pinout_labels - | Mbed

BR, Jan

2 Likes