Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 5 of 5

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

  1. #1
    Junior Member
    Join Date
    Oct 2019

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

    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?

  2. #2
    Senior Member
    Join Date
    Mar 2015
    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.

  3. #3
    Senior Member
    Join Date
    Mar 2015

    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...

    //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)
      digitalWrite(LED, LOW);    // turn the LED off by making the voltage LOW
    Here is a screen shot from my scope of the sketch in action, together with a photo of the physical test configuration...

    Click image for larger version. 

Name:	T4Comp02.jpg 
Views:	9 
Size:	77.7 KB 
ID:	21075 Click image for larger version. 

Name:	T4Comp01.jpg 
Views:	7 
Size:	101.2 KB 
ID:	21076

    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
    Last edited by TelephoneBill; 07-22-2020 at 10:12 AM.

  4. #4
    Junior Member
    Join Date
    Oct 2019
    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".

  5. #5
    Senior Member
    Join Date
    Jul 2020
    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)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts