Teensy 4.1 - automatic interrupt every 1 and 10 seconds?

Status
Not open for further replies.

herbert23

Member
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:
rauschen.jpg

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.
 
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.
 
First of all thanks for your answers.

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

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.

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!
 
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:
rauschen_muster_50Hz.jpg
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:
rauschen_muster_500Hz.jpg

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?
 
Yes, as has been pointed out, you should be using a hardware counter and probably via the FreqMeasure library, not
using a software counter.
 
First of all thank you for your reply!
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.
 
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.
 
Status
Not open for further replies.
Back
Top