Teensy 4.1 - FreqMeasure a Inductive Sensor Pulse

Hello Community,

in my project i want to measure the RPM of a motor with an Inductive Proximity Sensor with 400Hz for further processing.
I am using an Octocoupler to decouple and reduce the noisy electrical signal of the Sensor before processing it to the Teensy 4.1.
The measured output is very strange. With a constant PWM on the motor the measured frequency is given following:

Slow Rotation:
13223.13
137994.48
1034.39
291262.13
460122.69
619834.69
511945.41
397877.97
393700.78
163755.45
7.50
13.82
53.15
8.74
14.17
3.57
62086.09
14.18
310559.00
213068.19
4.30
28.46
281.54
13.00
712.08
360576.94
292968.75
12.97
663716.81
622406.63
563909.75
519031.16
461538.47
539568.38
306122.44
294695.47
265957.44
4.91
14.32
24.44
10.72

Faster Rotation:
9.53
110.51
1.08
85.38
60.99
124.33
110.32
164.87
1.07
90.47
328.13
110.49
250.22
199.73
213.93
230.53
90.76
249.69
249.84
250.01
199.93
250.02
1.08
166.55
142.59
166.11
248.97
1.07
124.37
165.65
175.30
57.36
249.00
66.45
1.08
90.33
165.47
110.32
248.30
248.12
66.13
248.04
198.43
141.80
1.08
124.03
110.35
248.24
63.38
185.90
90.09
61.91
65.93
31.10
1.05
30.37
27.02

Code is just the example code for FreqMeasure-Library:
Code:
#include <Arduino.h>
#include <FreqMeasure.h>

void setup() {
  Serial.begin(57600);
  FreqMeasure.begin();
}

double sum=0;
int count=0;

void loop() {
  if (FreqMeasure.available()) {
    // average several reading together
    sum = sum + FreqMeasure.read();
    count = count + 1;
    if (count > 30) {
      float frequency = FreqMeasure.countToFrequency(sum / count);
      Serial.println(frequency);
      sum = 0;
      count = 0;
    }
  }
}

Input Pin is Pin 22. Ground from the Lower side of the Octocoupler and the Teensy 4.1 are connected.
The sensor and the electric circuit is working. With Pi Pico i can measure the RPM quite well. At this point i think the Teensy 4.1 is causing the problems, but i dont know.

I would be very thankful for some hints or an explanation.
Thanks
 
For a decent hint or explanation more information is needed. It looks like pin 22 sees a lot of noise or maybe the level of the measured signal is too low.
What exact optocoupler are you using? How is that optocoupler actually hooked up? Can you show us a photo of your setup?

Paul?
 
Hey Paul,

here is the electric circuit diagram. Edit: Pin 4 is Pin 22 connected in my circuit.
RPM Measurement.jpg

Although the Sensor is for minimum 6V, 5V does the Job. I checked it with an oscilloscope. I also get a clean Low and High on the Low side of the octocoupler.
 
You can get a better sense of what's getting through to the processor if you do the frequency averaging at a regular interval, such as 1-Hz. When speed is relatively constant, you should see a consistent number of edges.

Code:
#include <Arduino.h>
#include <FreqMeasure.h>

void setup() {
  Serial.begin(57600);
  while (!Serial && millis()<2000) {}
  FreqMeasure.begin();
}

double sum=0;
int count=0;
elapsedMillis ms = 0;
uint32_t seconds = 0;

void loop() {
  while (FreqMeasure.available()) {
    // average several reading together
    sum = sum + FreqMeasure.read();
    count = count + 1;
  }
  if (ms >= 1000) {
    ms -= 1000;
    seconds++;
    float frequency = 0;
    if (count > 0)
      frequency = FreqMeasure.countToFrequency(sum / count);
    Serial.printf( "sec=%8d    count=%6d    freq=%12.2f\n", seconds, count, frequency );
    sum = 0;
    count = 0;
  }
}
 
You can get a better sense of what's getting through to the processor if you do the frequency averaging at a regular interval, such as 1-Hz. When speed is relatively constant, you should see a consistent number of edges.

Code:
#include <Arduino.h>
#include <FreqMeasure.h>

void setup() {
  Serial.begin(57600);
  while (!Serial && millis()<2000) {}
  FreqMeasure.begin();
}

double sum=0;
int count=0;
elapsedMillis ms = 0;
uint32_t seconds = 0;

void loop() {
  while (FreqMeasure.available()) {
    // average several reading together
    sum = sum + FreqMeasure.read();
    count = count + 1;
  }
  if (ms >= 1000) {
    ms -= 1000;
    seconds++;
    float frequency = 0;
    if (count > 0)
      frequency = FreqMeasure.countToFrequency(sum / count);
    Serial.printf( "sec=%8d    count=%6d    freq=%12.2f\n", seconds, count, frequency );
    sum = 0;
    count = 0;
  }
}

Alright thx. Tried it.
My output:
sec= 64 count= 117 freq= 2.01
sec= 65 count= 136 freq= 2.33
sec= 66 count= 101 freq= 101.07
sec= 67 count= 105 freq= 3.54
sec= 68 count= 122 freq= 4.12
sec= 69 count= 111 freq= 110.85
sec= 70 count= 94 freq= 3.17
sec= 71 count= 131 freq= 4.42
sec= 72 count= 108 freq= 108.75
sec= 73 count= 124 freq= 4.19
sec= 74 count= 123 freq= 123.86
sec= 75 count= 123 freq= 1.42
sec= 76 count= 106 freq= 1.82
sec= 77 count= 141 freq= 1.22
sec= 78 count= 113 freq= 3.81
sec= 79 count= 120 freq= 1.04
sec= 80 count= 114 freq= 3.85
sec= 81 count= 119 freq= 2.04
sec= 82 count= 122 freq= 4.12
sec= 83 count= 122 freq= 1.40
sec= 84 count= 127 freq= 2.18
sec= 85 count= 119 freq= 4.02
sec= 86 count= 124 freq= 121.67
sec= 87 count= 116 freq= 117.85
sec= 88 count= 106 freq= 1.82
sec= 89 count= 132 freq= 4.45
sec= 90 count= 101 freq= 102.58
sec= 91 count= 116 freq= 3.91
sec= 92 count= 138 freq= 2.37
sec= 93 count= 131 freq= 4.42
sec= 94 count= 117 freq= 3.95
sec= 95 count= 108 freq= 109.57
sec= 96 count= 121 freq= 1.39
sec= 97 count= 118 freq= 119.69
sec= 98 count= 128 freq= 4.32
sec= 99 count= 119 freq= 120.59
sec= 100 count= 103 freq= 101.22
sec= 101 count= 144 freq= 2.47
sec= 102 count= 128 freq= 126.43
sec= 103 count= 109 freq= 3.68
sec= 104 count= 136 freq= 139.49
sec= 105 count= 110 freq= 1.89
sec= 106 count= 104 freq= 3.51
sec= 107 count= 110 freq= 109.46
sec= 108 count= 130 freq= 128.82
sec= 109 count= 132 freq= 134.35
sec= 110 count= 137 freq= 2.35
sec= 111 count= 125 freq= 1.08
sec= 112 count= 103 freq= 101.98
sec= 113 count= 134 freq= 132.24
sec= 114 count= 113 freq= 3.81
sec= 115 count= 112 freq= 1.92
sec= 116 count= 125 freq= 124.39
sec= 117 count= 106 freq= 105.36
sec= 118 count= 124 freq= 4.18
sec= 119 count= 101 freq= 3.41
sec= 120 count= 110 freq= 3.71
sec= 121 count= 116 freq= 114.92
sec= 122 count= 114 freq= 1.31
sec= 123 count= 123 freq= 4.15
sec= 124 count= 118 freq= 1.02
sec= 125 count= 118 freq= 2.02
sec= 126 count= 128 freq= 127.59
sec= 127 count= 105 freq= 3.55
sec= 128 count= 115 freq= 114.31
sec= 129 count= 119 freq= 4.01

Count seems nearly consistent, depending on the entry in the if statement.

Dont know, why frequency behaves this way. Im setting everything up with PlatformIO, it it matters.
 
You need to look at that signal. Or if you can’t, modify the code to see more detail. When count and freq are close, it means you have relatively equal pulse widths. When freq is very low, it means sum is large. Add sum to the display to see if that’s true, and then start printing individual values returned by FreqMeasure.read() to determine what the “bad” ones look like.
 
I tried the FreqMeasur Code with output of the sum on an Arduino Uno too.
Uno results:
sec= 92 count= 33 frequency= 33.04 sum= 15978950.00
sec= 93 count= 33 frequency= 33.06 sum= 15969776.00
sec= 94 count= 33 frequency= 33.04 sum= 15980739.00
sec= 95 count= 33 frequency= 33.08 sum= 15962220.00
sec= 96 count= 33 frequency= 33.12 sum= 15941412.00
sec= 97 count= 33 frequency= 33.14 sum= 15933907.00
sec= 98 count= 33 frequency= 33.10 sum= 15953205.00

Teensy 4.1 results:
sec= 7 count= 102 freq= 103.96 sum= 3221225472
sec= 8 count= 114 freq= 112.83 sum= 3959422976
sec= 9 count= 113 freq= 111.68 sum= 3825205248
sec= 10 count= 101 freq= 102.68 sum= 2617245696
sec= 11 count= 99 freq= 1.70 sum= 4163895296
sec= 12 count= 106 freq= 3.58 sum= 2751463424
sec= 13 count= 91 freq= 1.56 sum= 3249537024
sec= 14 count= 98 freq= 3.31 sum= 178257920
sec= 15 count= 120 freq= 119.15 sum= 536870912
sec= 16 count= 115 freq= 117.36 sum= 3355443200

I see clearly that the Teensy counts to much and the sum is different up to two times 10.
Here is exemplary a snippet of the FreqMeasure.read():
sec= 8 count= 86 freq= 84.97 sum= 1543503872
4456470
6774
113
266
4461761
41
23
235
4462652
340
144
19
4461877
42
4461837
22
27
222
4463056
4463298
4463953
46
56
4463898

Too many small Interrupt-Times. Am i right for identifying it for an indicator of a bouncing signal? But why does that phenomen not happen on the other MCUs (e.g. UNO)? Or is my teensy somehow damaged?
 
I suspect it's because the T4.1 is going so much faster and can react to more bouncing (ringing) signals.
 
I suspect it's because the T4.1 is going so much faster and can react to more bouncing (ringing) signals.

Agree. Have you looked at the signal with a scope? If you modify your setup() function to include writeAnalog(0,128) as shown below, and jumper pin 0 to pin 22, you can see whether you get good count and frequency with a known good 3.3v square wave. If pin 0 is not available, use a different pin. You should get ~4482 Hz.

Code:
void setup() {
  Serial.begin(57600);
  while (!Serial && millis()<2000) {}
  analogWrite( 0, 128 );
  FreqMeasure.begin();
}
 
I could inspect the Signal. Cant Upload it here due to whatever.
The Signal isnt as clean as i thought using an octocoupler. I need to debounce the Signal for sure. I ordered a Schmitt-Trigger and im going to hardware debounce the signal when it arrives.
As a workaround i just implemented that every reading under F_BUS_ACTUAL / 400 Hz (max Measure Frequency of the Sensor) is discarded.

I get the following nearly stable Frequency and count Output:
sec= 1527 count= 16 freq= 16.12 sum= 167772160
sec= 1528 count= 17 freq= 0.57 sum= 1578106880
sec= 1529 count= 18 freq= 18.08 sum= 2181038080
sec= 1530 count= 16 freq= 16.04 sum= 3992977408
sec= 1531 count= 17 freq= 0.57 sum= 2182086656
sec= 1532 count= 18 freq= 0.61 sum= 3888119808
sec= 1533 count= 17 freq= 0.57 sum= 4089446400
sec= 1534 count= 16 freq= 16.05 sum= 268435456
sec= 1535 count= 18 freq= 18.02 sum= 3422552064

Now i got another Question: Why are there so many computed frequencies under 1, when the Code uses the following line? (count is sum/count)
return (float)F_BUS_ACTUAL / (float)count;
 
Now i got another Question: Why are there so many computed frequencies under 1, when the Code uses the following line? (count is sum/count)
return (float)F_BUS_ACTUAL / (float)count;

"sum" is a double, so I'm just guessing that you might not be using correct specifier in your print statement. Could you please try the program below, first with pin 0 jumpered to pin 22, and then with your signal, and post the first few seconds of output for both? Here is what it produces for me with pin 0 jumpered to pin 22. I'm using Arduino 1.8.19 and TD 1.58b3 on Windows.

Code:
sec =        1   count =   3209  sum =  107437339  freq =  4480.29
sec =        2   count =   4482  sum =  149990131  freq =  4482.29
sec =        3   count =   4483  sum =  150023594  freq =  4482.29
sec =        4   count =   4482  sum =  149990131  freq =  4482.29
sec =        5   count =   4482  sum =  149990130  freq =  4482.29


Code:
#include <Arduino.h>
#include <FreqMeasure.h>

void setup() {
  Serial.begin(57600);
  while (!Serial && millis()<2000) {}
  analogWrite( 0, 128 );
  FreqMeasure.begin();
}

double sum=0;
uint32_t count=0;
elapsedMillis ms = 0;
uint32_t seconds = 0;

void loop() {
  while (FreqMeasure.available()) {
    sum = sum + FreqMeasure.read();
    count = count + 1;
  }
  if (ms >= 1000) {
    ms -= 1000;
    seconds++;
    float frequency = 0;
    if (count > 0) {
      frequency = FreqMeasure.countToFrequency( (uint32_t)(sum/count + 0.5) );
    }
    Serial.printf( "sec = %8lu   count = %6lu  sum = %10.0lf  freq = %8.2f\n", seconds, count, sum, frequency );
    sum = 0;
    count = 0;
  }
}
 
The Signal isnt as clean as i thought using an octocoupler. I need to debounce the Signal for sure
Before adding a schmitt-trigger, I would focus on why the output of the optocoupler is not as clean as expected.
You stated that the signals on low-side of the opto are "a clean Low and High". I assume you measured over pins 1 & 2 of the opto? What are the actual voltages? I'm asking because you can then calculate the LED current and check whether that is enough to drive the opto output transistor to a sufficiently low level. I'm guessing there is not a clean low level at Teensy pin 22.

Paul
 
Back
Top