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

Thread: Teensy 4.1 - automatic interrupt every 1 and 10 seconds?

  1. #1
    Junior Member
    Join Date
    Jan 2021
    Posts
    5

    Teensy 4.1 - automatic interrupt every 1 and 10 seconds?

    I want to measure a frequency of 2-3khz very precise.
    For that I simply used a counter in a while loop.
    Code:
      for (int i = 0; i < 10; i++) {
        while (digitalReadFast(9) == HIGH)
          duration++;
        delayMicroseconds(1); //just for stability
        while (digitalReadFast(9) == LOW)
          duration++;
        delayMicroseconds(1);
      }
    The results accuracy was ok, but every second the duration was a bit shorter (one peak) and every ten second the duration was shorter over a few points.
    Here's a plot of the signal:
    Click image for larger version. 

Name:	rauschen.jpg 
Views:	20 
Size:	65.6 KB 
ID:	23481

    Because the peaks are always with the sam timedifference, I thought that the problem would be, that two interrupts trigger at 1 and 0.1Hz. I tried to stop them with cli(); but that didn't change anything. I'd say it got even worse...
    So is this an interrupt, that I can't disable or what else could it be?

    I am using a Teensy 4.1 with Teensyduino 1.53 and Arduino 1.8.5 on Windows.

    P.s. just adding the durations over 10s doesn't work for me, because I need to have the data with at least 80Hz.

  2. #2
    Senior Member
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    1,422

  3. #3
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    23,958
    Quote Originally Posted by herbert23 View Post
    or what else could it be?
    Maybe something in the rest of your code, which we can't see.

    You're somehow getting this data into a graph. Maybe you're using Serial.print() or other USB communication? USB has very non-deterministic timing, which can even vary depending on the CPU load on your PC, since USB implements end-to-end flow control.

    But even if you solve all those issues, using a busy loop which counts iterations is a terrible approach.

    You should really use FreqMeasure which is based on hardware timer input capture. That hardware is designed to give you perfectly deterministic timing measurement because it uses dedicated timer hardware to capture the period of each waveform cycle.

    If you really want to use polling loops with digitalReadFast(), at the very least read ARM_DWT_CYCCNT when you detect the change, rather than depending on the poorly defined speed of the code's execution.

  4. #4
    Junior Member
    Join Date
    Jan 2021
    Posts
    5
    First of all thanks for your answers.

    I tried to use the FreqMeasure library but it didn't seem to be better...

    Quote Originally Posted by PaulStoffregen View Post
    Maybe you're using Serial.print() or other USB communication?
    Yes, I print out the duration to record it with my computer. So that's probably the problem.
    But as I didn't expected I get a peak every 10s even if I use the cycle counter. So I used a Usb ttl converter and printed it out over Serial1.

    Quote Originally Posted by PaulStoffregen View Post
    ARM_DWT_CYCCNT
    That's exactly what I was looking for, because with that I should get a better accuracy. I didn't knew that the Teensy comes with this feature.

    Now the signal is better, to improve it, I have to make my oscillator more stable. (at the moment I'm just using an Operational amplifier as Comparator => not a real rectangle waveform, the voltage isn't rising fast enough)

    Thank you very much for your help!

  5. #5
    Junior Member
    Join Date
    Jan 2021
    Posts
    5
    So today I upgraded my oscillator to get less noise from it.
    That worked out fine, but I think that the teensy is putting in noise aggain.
    I went down a bit with the sampling rate to about 30Hz. Now it looks something like this:
    Click image for larger version. 

Name:	rauschen_muster_50Hz.jpg 
Views:	9 
Size:	49.4 KB 
ID:	23543
    Every 4 or 5 samples I get one peak to the top and one to the bottom. I used a program with a loop and the cycle counter. I also tried to use the program in which I count how often the loop is repeated, but I got the same results.

    If I just use a higher sampling rate, I get the same pattern. Here's the data at ~500Hz:
    Click image for larger version. 

Name:	rauschen_muster_500Hz.jpg 
Views:	10 
Size:	41.4 KB 
ID:	23542

    Here's the code I used:
    Code:
    int32_t dauer, dauer2;
    void setup() {
      Serial1.begin(115200);
      pinMode(21, INPUT);
    }
    void loop() {
      dauer = ARM_DWT_CYCCNT;
      for (long i = 0; i < 5; i++) {
        while (digitalReadFast(21) == HIGH);
        delayMicroseconds(30); //just for stability
        while (digitalReadFast(21) == LOW);
        delayMicroseconds(30);
      }
      Serial1.println(dauer - dauer2);
      dauer2 = dauer;
    }
    So does anyone know what the problem could be here?

  6. #6
    Senior Member
    Join Date
    Jul 2020
    Posts
    900
    Yes, as has been pointed out, you should be using a hardware counter and probably via the FreqMeasure library, not
    using a software counter.

  7. #7
    Junior Member
    Join Date
    Jan 2021
    Posts
    5
    First of all thank you for your reply!
    Quote Originally Posted by MarkT View Post
    you should be using a hardware counter
    As I mentioned before, the resolution of the hardware counter isn't high enough for me. I can get a resolution of 0.03Hz. So without noise, I would have a ratio of 1:80000.
    With the software version, I have a ratio of about 300000:1 with the noise.

    I realised that the noise was every few samples and so the frequency of the noise changed, if the frequency I print the blaues out changes. Beause I am counting the clock cycles these peaks shouldn't be thera anymore, if I add them afterwards. To check this theory I printed out the frequency of the oscillator with 1.2khz and than added them on my computer to get around 120Hz. The results were quite good. I couldn't see the peaks anymore.

    Next I just used Serial.flush() after every print. After that, the signal was very good. At the moment, I'm only having about 80 clock cycles noise, that comes from radiation and stuff like that.

    Thanks aggain for your help.

  8. #8
    Senior Member
    Join Date
    Jul 2020
    Posts
    900
    As far as I can see you can just use available() and read() in the FreqMeasure library repeatedly for as long as you
    want to get the total elapsed time for many cycles, giving you the accuracy you want using the hardware to
    guarantee accurate timings.

  9. #9
    Junior Member
    Join Date
    Jan 2021
    Posts
    5
    Quote Originally Posted by MarkT View Post
    as long as you want
    So, that's my main problem. I have to measure the frequency with a frequency of above 80Hz. So for me it isn't possible to just add everything over a minute or something like that.

Posting Permissions

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