Using the analog comparator to build a frequency counter with the Teensy 4.0

LukasFun

Member
Hello everyone,

I would like to use the analog comparator of the Teensy 4.0 (page 3425 of the manual and onward) to build a frequency counter.

I would like to set it to generate an interrupt when the value of my pin of choice exceeds a certain value and another when the value falls below a certain other value. I then want to attach my own ISRs to the two individual interrupts.

How would I go about this?

Or is there another way of building a frequency counter with the Teensy 4.0 that doesn't require constantly polling the analog pin?
 
Not sure your principle of using the analog comparator in this way is the best method for creating a Frequency Counter. There is an "overhead" in time to be paid for calling an ISR subroutine and if you do this on every zero crossing, then you will waste a lot of cpu time just dumping registers and reloading them later. It will limit how fast the Frequency Counter can work.

Maybe a better way is to use the analog comparator to provide clock pulses into a counter, then set a timer running for a fixed period. The number of pulses that is counted by the timer in that fixed period will give you the frequency of what is driving the analog comparator. That's how most commercial Frequency Counters work. You then only call your ISR at the end of the timer fixed period, which will be much less frequent than every half cycle (hence more efficient).

Good to learn how things work, so good to have the original idea. There are code examples in the Forum which show how the comparator can be used. You need to learn how to use the search feature of the Forum in order to find them. Then diligently examine that code to try guess what its doing.

So two jobs as a preliminary for your project: (1) learn how to use a counter with a clock signal on a timed interval basis, then (2) learn how to use the analog comparator "stand alone". You have to do these for yourself, or else you don't learn anything. Once you have these two under your belt, then you replace the clock signal in the counter with that output from the comparator (often called an "external clock") - and your almost there for your target idea.
 
Comparator Stand-Alone Test

Here is a little help with using a T4 Analog Comparator. It uses the peripheral ACMP3. Normally, the ACMP3 output is available on pin AD_B1_14 (see page 295 of iMXRT1060 Ref Manual Rev2). But this is on the underside of the T4 board on Teensy 4 pin 26. I like to use breadboard for experimental testing, so I have employed the XBAR1 cross trigger component to re-route ACMP3_OUT to Teensy 4 pin 2, which is available topside and from my breadboard.

Here is a small fully working sketch that you can check out. Its purpose is to take a small analog signal from a signal generator and "threshold" it via the comparator against an internal DAC preset to a voltage set halfway between 3v3 and GND. The input is to pin 18, and the output is then a square wave signal of amplitude 3v3 on pin2...

Code:
//TestT4 ACMP3
//-------------------
//Date: 22 JUL 2020
//Author: TelephoneBill
//Purpose: Test of using the Teensy 4.0 ACMP3 Comparator
//Version: 1v00

//DEFINE variables
//================
int LED = 13;

//SETUP routine
//=============
void setup() {
  //Initialize the digital pin 13 as an output for LED.
  pinMode(LED, OUTPUT);

  //Enable ACMP3 to threshold an analogue a.c. input signal - 9 code steps below
  //Note: Signal is via 0.1 mfd into pin 18. 10 turn 10K pot across 3v3 and GND with wiper also to pin 18.
  //Set 10K pot to central position (5K). This will bias the d.c. voltage on pin 18 to midway 3v3 and GND.
  //ACMP3 input is pin 18 (ACMP3_IN0 = AD_B1_01 : Default connection - no need for muxing)
  //Voltage reference (INM7) is 6-bit internal DAC, VIN2 = VDD (3.3v)
  //ACMP3_OUT (output) is on T4 pin 2 (via XBAR1 and EMC_04)
  //Comparator output state is available if desired - read "CMP3_SCR" register least significant bit
  CCM_CCGR2 |= CCM_CCGR2_XBAR1(CCM_CCGR_ON);  //(1) turn clock on for xbara1
  XBARA1_SEL3 = 0x001C;                       //(2) this connects XBAR1_INOUT6 to XBAR1_IN28 (ACMP3_OUT)
  IOMUXC_SW_MUX_CTL_PAD_GPIO_EMC_04 = 3;      //(3) ALT3 connects XBAR1_INOUT6 to T4 Pin 2
  IOMUXC_GPR_GPR6 |= 0b00000000000001000000000000000000; //(4) IOMUXC_XBAR_DIR_SEL_6 = 1 (direction select for XBAR_INOUT6)
  CCM_CCGR3 |= 0x03000000;                    //(5) enable clocks to CG12 of CGR3 for ACMP3
  CMP3_CR0 = 0b00000000;                      //(6) FILTER_CNT=0; HYSTCTR=0
  CMP3_CR1 = 0b00010111;                      //(7) SE=0, high power, COUTA, output pin, enable; mode #2A
  CMP3_DACCR = 0b11011111;                    //(8) Set DAC = 1/2 of VIN2 (3.3v) = 1.65v 
  CMP3_MUXCR = 0b00000111;                    //(9a) CMP_MUX_PSEL(0) | CMP_MUX_MSEL(7) Input pins select;
                                              //(9b)   plus = IN0 (pin 18), minus = DAC (code 7). PSTM = 0 (Pass Through Mode Disabled)
}

//MAIN LOOP routine
//=================
void loop() {
  digitalWrite(LED, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(100);
  digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
  delay(900);
}

Here is a screen shot from my scope of the sketch in action, together with a photo of the physical test configuration...

T4Comp02.jpg T4Comp01.jpg

Ignore the copper foil covering the processor (its from another previous experiment). The Teensy input pin needs to be biased very close to the threshold voltage, so I have used a 10 turn 10K pot connected across 3v3 and GND, with the wiper fed to pin 18. Also connected to pin 18 is that yellow 0.1 mfd capacitor from the signal generator, which is the route for the small a.c. signal (100KHz and 500mV pk to pk). The pot has been turned 5 turns so the bias voltage is somewhere near to 1.65 volts.

You can see some noise induced glitches on the scope shot on Trace1 (sine input) when Trace2 changes state (sq wave output). Notice that the point of positive going transition on Trace1 is slightly more positive than that for the negative going transition. This is the hysteresis of the comparator.

You can test the comparator before connecting a sine wave just by carefully twiddling the 10K pot knob around the mid-way position. A voltmeter on the output pin 2 will show a change of logic state as the bias is raised slightly above or slightly below the threshold voltage. This is a good way to make sure you have the bias adjusted correctly before connecting the sine wave input.

Have fun with this "stand-alone" experiment of a T4 Comparator - I did :rolleyes:
 
Last edited:
This is a nice example, but I was able to accomplish the same result myself. The problem is that the hysteresis levels provided by the built in analog comparator are not always enough, hence I asked about setting two different compare voltages.

Is this possible or is there some other way like changing the reference voltage for the digital pins on the fly (which is probably a bad idea) or is the answer simply "too bad, build your own Schmitt trigger"?

Also, it would be appreciated if you could provide links to other threads that talk about the things you mention (specifically using a counter with an external clock signal) instead of saying "learn how to use the search feature of the Forum".
 
I would consider an external comparator, many to choose from with various speeds, set the hysteresis explicitly as
well as the reference point (commonly this comes from the input signal via a low pass filter, so its self-setting, or
you level shift with a capacitor (AC coupled)
 
This is a nice example, but I was able to accomplish the same result myself. The problem is that the hysteresis levels provided by the built in analog comparator are not always enough, hence I asked about setting two different compare voltages.

Is this possible or is there some other way like changing the reference voltage for the digital pins on the fly (which is probably a bad idea) or is the answer simply "too bad, build your own Schmitt trigger"?

Also, it would be appreciated if you could provide links to other threads that talk about the things you mention (specifically using a counter with an external clock signal) instead of saying "learn how to use the search feature of the Forum".

An old thread I know, but in case someone else comes across it as I've just done....

Simplest way to add controlled hysteresis is with two resistors. For the above example, insert a series resistor into the input pin 18, say 1k. Then a second resistor, say 47k, from the output pin 2 to pin 18.

Comp.jpg

When the input signal is low then so is the output signal. This causes the input on p18 to be a little lower than the source signal due to the 47k pulling it down via the 1k.
When a positive going signal edge reaches the comparator threshold, the output goes high and hence the 47k that was pulling down now pulls up, which in turn requires the source signal to reduce by a hysteresis amount before the input on p18 drops below the comparator threshold. Tweak the value to suit the amount of hysteresis required.
 
Back
Top