Frequency dropped reading problem

xenington

Well-known member
Hi Everyone

I have been measuring the frequency of some square waves around 40KHz on a Teensy 4.1. The code is a variation of freqMeasureMulti and uses flexPWM to measure the time between rising edges on pins 0, 1, 2 and 3. It works great - most of the time anyway.

At random times and on random pins, there is a dropped reading. Some serial monitor readout:

3823 3618 3715 3629
3824 3619 3716 3628
3822 3617 3715 3628
3821 3616 3714 3626
3824 3619 3716 3629
3822 3617 3714 3627
3822 3617 3715 3627
3824 3619 2 3628
3824 3618 3717 3630
3823 3618 3714 3630
3822 3616 3714 3626
3823 3620 3716 3638
3817 3618 3714 3626
3821 3618 3714 3630

The signals are being put through an SN74AHC to shift the level from 5v on the sensor side down to 3.3v on the Teensy. I thought this might be the cause. However, placing various sized bypass capacitors on the VCC pin and power supply, using a range of pull down resistors on the input pins of 1K through 1M and the shortest connections I can get away with doesn't help. Even so, the nice folks at TI are looking into it.

Could it be the Teensy doing it? Seeing the same rising edge twice perhaps? My scope shows a nice clean wave with vertical rising and falling edges and square corners. If anyone has any suggestions they would be most welcome.

Thanks for your help.
Dean
 
It is attached. You may need the IMXRT1060 manual to hand.

Thank you for your help.
 

Attachments

  • SN74_Test.ino
    8.8 KB · Views: 26
When I just ran this code, I noticed one reading that is high:

3819 3617 3723 3643
3820 3617 3724 3644
35891 3617 35794 35714
3820 3617 3724 3642
3821 3618 3724 3644

Further down the same run are more 'dropped' readings though:

3819 3614 3724 3643
3820 3619 3724 3644
14 3617 3724 3643
3821 3618 3725 3644
3821 3618 3724 3645
 
OK, I've been doing some tests with modified versions of the above code and used ARM_DWT_CYCCNT to time bits of the isr, I get hundreds of the following serial monitor readout - all exactly the same except for miniscule variations in the sensor readings (+-5 at most):

0 3804 141
1 3579 84
2 3713 69
3 3638 71
3734 1074 4879

0, 1, 2, 3 = sensor/pin identifier, 3804 column = sensor readings, 141 column = time: insideLoopEnd - insideLoopStart
3734 = time: insideLoopStart - beforeLoop, 1074 = time: afterLoop - insideLoopEnd, 4879 = time: afterLoop - beforeLoop

Then, occasionally, there are drops like these:

0 13 141
1 3579 84
2 3713 69
3 3637 71
3694 1070 4835

0 3806 141
1 3581 84
2 3714 69
3 12 71
3734 1018 4823

Just for fun, a double count (interesting how it still takes less time overall than the normal readout above):

0 3651 141
1 7165 84
2 3614 69
3 3686 71
3732 1074 4877

Here is the modified isr:
Code:
uint32_t beforeLoop, insideLoopStart, insideLoopEnd, afterLoop;

void freqCapture()              // isr to capture frequencies, FlexPWM E-Capture p.3060, isr takes <1 μS to run
{
beforeLoop = ARM_DWT_CYCCNT;

  GPT1_SR |= GPT_SR_OF1;        // clear interval timer interrupt flag p.2964
 
  for (byte i = 0; i < sensorNumber; i ++) {                // repeat for each sensor being used

insideLoopStart = ARM_DWT_CYCCNT;

    IMXRT_FLEXPWM_t *Pflexpwm = freqPin[i].Pflexpwm;        // get Pflexpwm
    uint8_t subModule = freqPin[i].subModule;               // get subModule number
    uint16_t capture1 = 0, capture2 = 0, captureDiff = 0;   // set variables to hold capture values
    uint8_t inpABX = freqPin[i].inputABX;                   // get A, B or X
    uint8_t freq_Order = freqPin[i].freqOrder;              // order in which to save readings to array: 1T 1B 2T 2B 3T 3B 4T 4B 5T 5B 6T 6B 7T 7B 8T 8B

    switch (inpABX) {
      case 'A':
        capture1 = Pflexpwm->SM[subModule].CVAL2;     // 1st edge capture value (number IPBus ticks), p.3121
        capture2 = Pflexpwm->SM[subModule].CVAL3;     // 2nd edge capture value (number IPBus ticks), p.3123
        Pflexpwm->SM[subModule].CAPTCTRLA |= FLEXPWM_SMCAPTCTRLA_ARMA;    // ARMA = 0 (stop capture), p.3110 
        break;
      case 'B':
        capture1 = Pflexpwm->SM[subModule].CVAL4;     // 1st edge capture value (number IPBus ticks), p.3124
        capture2 = Pflexpwm->SM[subModule].CVAL5;     // 2nd edge capture value (number IPBus ticks), p.3126
        Pflexpwm->SM[subModule].CAPTCTRLB |= FLEXPWM_SMCAPTCTRLB_ARMB;    // ARMB = 0 (stop capture), p.3110     
        break;
      case 'X':
        capture1 = Pflexpwm->SM[subModule].CVAL0;     // 1st edge capture value (number IPBus ticks), p.3118
        capture2 = Pflexpwm->SM[subModule].CVAL1;     // 2nd edge capture value (number IPBus ticks), p.3119
        Pflexpwm->SM[subModule].CAPTCTRLX |= FLEXPWM_SMCAPTCTRLX_ARMX;    // ARMX = 0 (stop capture), p.3110 
        break;
    }
    captureDiff = capture2 - capture1;    // calculate difference between captures
    freqBuff[freq_Order] = captureDiff;   // store readings in volatile buffer

insideLoopEnd = ARM_DWT_CYCCNT;
Serial.print(freq_Order);
Serial.print("  ");
Serial.print(freqBuff[freq_Order]);
Serial.print("  ");
Serial.print(insideLoopEnd - insideLoopStart);
Serial.println("  ");
  } 
  asm volatile ("dsb");
  asm volatile ("isb");

afterLoop = ARM_DWT_CYCCNT;
Serial.print(insideLoopStart - beforeLoop);
Serial.print("  ");
Serial.print(afterLoop - insideLoopEnd);
Serial.print("  ");
Serial.println(afterLoop - beforeLoop);
Serial.println();
}

Thinking it might be crosstalk on the Teensy board, I tried pins 0, 2, 4 and 6 instead of 0, 1, 2 and 3 - same problem.
As far as hardware goes, so far I have tried: swapping the Teensy, swapping the sensors, swapping the SN74, removing the pull down resistors from the SN74 and the bypass capacitors, changing the power supply and removing everything else from the breadboard...

Not sure if it helps, but here is the breadboard circuit. The resistors are 10K. The blue cap is 10nF, the small brown cap is 100nF and the large brown cap is 1uF. The Vin for the Teensy and sensors is 5v and the SN74 Vcc is 3.3v taken from the Teensy. The sensors are FG3+ magnetic flux sensors. The scope pics are: left - signal after passing through the SN74, right - raw signal from sensors before the SN74. Vertical div is 1v and horizontal div is 5uS.

Any suggestions?

IMG_0517_small.JPG
IMG_0520_small.JPG
IMG_0521_small.JPG
 
Nobody willing to hazard a guess?

Another scope shot. This time the top of the raw input (0.5uS time divisions). The earlier shots were taken without the cable shielding being grounded which makes some noise apparent.

IMG_0550_small.JPG
 
Yes the raw signal from the sensor's needed Schmitt-trigger inputs to handle the very slow rise times (for CMOS logic signals anything over 30ns rise time is "slow", and over 100ns rise time may completely misbehave).
 
Very slow edges can generate 100's or 1000's of edges in some cases, many logic inputs are not designed to handle slow inputs (a CMOS gate acts as a high gain analog amplifier if inputs are near the mid-rail voltage).
 
The datasheet for the SN74 gives a maximum transition time of 100nS/V at 3.3v. Estimating from my ancient scope, I'd say the transition time of my input is 250uS between 0.9v and 2.5v - an order of magnitude greater (edit: actually 3 orders greater).

I will look for a slower alternative and report back.

Thank you Mark T.
 
All logic families require fast inputs unless they are Schmitt-trigger. Most often used is the 74HC14 which is a hex-inverter with Schmitt-trigger inputs. If you don't need inversion you simply chain 2 stages together. I'd guess the 74xx14 are the highest volume selling logic chips of all time!

BTW you picked 74AHC series which is about 3 times faster (*) than the normal 74HC series and should only be used with careful choice of layout and a good understanding of high speed propagation of signals - use 74HC in general unless there's a reason not to.

(*) Typically rise and fall rates are 2V/ns, meaning a stray capacitance of only 5pF will see induced currents of 10mA, plenty to cause crosstalk issues without good layout design.
 
Last edited:
Thank you.

I have been reading the datasheets for 74HC14 and 74HCT14. Can they be used for translation as well as inverting/buffering? It doesn't specifically say that they can, but could 5v be safely applied to the inputs if the Vcc is 3.3v? The absolute maximum rating is 7v with a recommended input voltage of Vcc (the HCT gives Vcc + 0.5v). It also says that the input voltage may be exceeded as long as the current limit is not. The current on the inputs will be about 4mA in my case, quite a bit less than the 20mA maximum.
 
Can they be used for translation as well as inverting/buffering? It doesn't specifically say that they can, but could 5v be safely applied to the inputs if the Vcc is 3.3v?

No, but similar parts like 74LCX14 are specifically designed for 5V tolerance.
 
I have some MC74LCX14 on order. They are 14-pin SOIC package so I created a small 'breakout' board for use on the breadboard. An Inkscape file is attached if anyone wants it. If you want another format, let me know.
 

Attachments

  • Board_MC74LCX14.zip
    5.1 KB · Views: 25
Just to let Mark T and Paul know that the problem has gone away. The MC74LCX14's are working fine.

Thank you both very much for your help.
 
Back
Top