Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SAMD21 micros() problem #684

Open
Peter28357 opened this issue Oct 14, 2022 · 5 comments
Open

SAMD21 micros() problem #684

Peter28357 opened this issue Oct 14, 2022 · 5 comments

Comments

@Peter28357
Copy link

Peter28357 commented Oct 14, 2022

Hello all,
this is my first time here and I am not sure that my assumption is correct.
The aim of the program is to decode a Manchester signal. The LED_BULITIN indicates a failure and gives a trigger for the oscilloscope.
From time to time the calculation of the „intervalBahnsignalMicros“ goes wrong and the decoding of the signal is corrupted!
This failure was never seen on a NANO_Every platform, but on different SAMD21 platforms like NANO 33 IoT, ARDUINO_Zero, MKR_Zero and MKR WIFI 1010.
Thanks for your help.

ArduinoSamd21_MicrosProblem_v2_Overview
ArduinoSamd21_MicrosProblem_v2_Zoom

Sketch:

/* for arduino:
*/

volatile const unsigned long UnsignedLongMax = 4294967295;


volatile const int pinISR = 10;
volatile const int pinISR_Interval = 9;

volatile const int interruptPin_Bahnsignal = 12;


volatile word BahnsignalWord = 0;
volatile bool Calculate = false;


volatile const word SW_Car = 32;                                    // SW=SpurWechsel
volatile word SW_CarArray[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};

volatile word BahnWordArray[11] = {0, 4096, 512, 128, 512, 514, 516, 518, 520, 128, 522};
volatile int BahnWordArrayBitLength[11] = {1, 13, 10, 8, 10, 10, 10, 10, 10, 8, 10};


volatile unsigned long intervalWhileWaitMicros = 0;
volatile unsigned long previousWhileWaitMicros = 0;
volatile unsigned long currentWhileWaitMicros  = 0;

volatile unsigned long intervalBahnsignalMicros = 0;
volatile unsigned long previousBahnsignalMicros = 0;
volatile unsigned long currentBahnsignalMicros  = 0;

volatile unsigned long intervalCalculateMicros = 0;
volatile unsigned long previousCalculateMicros = 0;
volatile unsigned long currentCalculateMicros  = 0;


volatile int BahnWord = 1;
volatile bool BahnWordSync = false;
volatile word BahnWords[11];


// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------


void setup() {

  pinMode(interruptPin_Bahnsignal, INPUT);
  attachInterrupt(digitalPinToInterrupt (interruptPin_Bahnsignal), ISR_BahnsignalDecodePur, CHANGE);

  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(pinISR, OUTPUT);
  pinMode(pinISR_Interval, OUTPUT);

}


// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------


void loop() {
  digitalWrite(pinISR, LOW);
  digitalWrite(pinISR_Interval, LOW);

  if (Calculate == true) {
    currentCalculateMicros = micros();
    if (currentCalculateMicros < previousCalculateMicros) {
      intervalCalculateMicros = currentCalculateMicros + (UnsignedLongMax - previousCalculateMicros);
    }
    else {
      intervalCalculateMicros = currentCalculateMicros - previousCalculateMicros;
    }

    if (intervalCalculateMicros > 2000) {

      if (BahnWord == 4) {
        SW_CarArray[1] = (BahnWordArray[4] & SW_Car) >> 5;

        if (SW_CarArray[1] == 0) {
          digitalWrite(LED_BUILTIN, HIGH);
        }
        else {
          digitalWrite(LED_BUILTIN, LOW);
        }
      }

      if (BahnWord == 6) {
        SW_CarArray[2] = (BahnWordArray[6] & SW_Car) >> 5;

        if (SW_CarArray[2] == 0) {
          digitalWrite(LED_BUILTIN, HIGH);
        }
        else {
          digitalWrite(LED_BUILTIN, LOW);
        }
      }


      if (BahnWord == 8) {
        SW_CarArray[3] = (BahnWordArray[8] & SW_Car) >> 5;

        if (SW_CarArray[3] == 0) {
          digitalWrite(LED_BUILTIN, HIGH);
        }
        else {
          digitalWrite(LED_BUILTIN, LOW);
        }
      }


      if (BahnWord == 10) {
        SW_CarArray[4] = (BahnWordArray[10] & SW_Car) >> 5;

        if (SW_CarArray[4] == 0) {
          digitalWrite(LED_BUILTIN, HIGH);
        }
        else {
          digitalWrite(LED_BUILTIN, LOW);
        }
      }


      if (BahnWord == 5) {
        SW_CarArray[5] = (BahnWordArray[5] & SW_Car) >> 5;

        if (SW_CarArray[5] == 0) {
          digitalWrite(LED_BUILTIN, HIGH);
        }
        else {
          digitalWrite(LED_BUILTIN, LOW);
        }
      }


      if (BahnWord == 7) {
        SW_CarArray[6] = (BahnWordArray[7] & SW_Car) >> 5;

        if (SW_CarArray[6] == 0) {
          digitalWrite(LED_BUILTIN, HIGH);
        }
        else {
          digitalWrite(LED_BUILTIN, LOW);
        }
      }

      Calculate = false;
    }
  }

}


// -------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------


void ISR_BahnsignalDecodePur() {
  digitalWrite(pinISR, HIGH);

  currentBahnsignalMicros = micros();

  if (currentBahnsignalMicros < previousBahnsignalMicros) {
    intervalBahnsignalMicros = currentBahnsignalMicros + (UnsignedLongMax - previousBahnsignalMicros);
  }
  else {
    intervalBahnsignalMicros = currentBahnsignalMicros - previousBahnsignalMicros;
  }


  if ((intervalBahnsignalMicros > 85) && (intervalBahnsignalMicros < 135)) {
    digitalWrite(pinISR_Interval, HIGH);

    previousBahnsignalMicros = currentBahnsignalMicros;
    BahnsignalWord = BahnsignalWord << 1;
    
    if (digitalRead(interruptPin_Bahnsignal) == LOW) {
      bitSet(BahnsignalWord, 0);
    }

    if (BahnsignalWord >= 4096) {
      BahnWordSync = true;
    }
    return;
  }


  if (intervalBahnsignalMicros > 5700 ) {
    if (BahnWordSync == true) {
      if (BahnsignalWord >= 4096) {
        BahnWord = 1;
      }
      BahnWordArray[BahnWord] = BahnsignalWord;
      BahnsignalWord = 0;
      bitSet(BahnsignalWord, 0);
      Calculate = true;
      BahnWord = BahnWord + 1;
      if (BahnWord >= 11) {
        BahnWord = 1;
      }
      previousBahnsignalMicros = currentBahnsignalMicros;
      previousCalculateMicros = currentBahnsignalMicros;
      return;
    }
    else {
      previousBahnsignalMicros = currentBahnsignalMicros;
      previousCalculateMicros = currentBahnsignalMicros;
      BahnsignalWord = 0;
      bitSet(BahnsignalWord, 0);
      Calculate = false;
      BahnWord = 1;
      return;
    }
  }

}


// -------------------------------------------------------------------------------------


void WhileWaitMicros(unsigned long WaitMicros) {
  previousWhileWaitMicros = micros();
  do {
    currentWhileWaitMicros  =  micros();

    if (currentWhileWaitMicros < previousWhileWaitMicros) {
      intervalWhileWaitMicros = currentWhileWaitMicros + (UnsignedLongMax - previousWhileWaitMicros);
    }
    else {
      intervalWhileWaitMicros = currentWhileWaitMicros - previousWhileWaitMicros;
    }

  } while ( intervalWhileWaitMicros < WaitMicros );
}

// -------------------------------------------------------------------------------------
@Peter28357
Copy link
Author

More detailed data (Version v3)
The additional output "pinISR_NotComplete" indicates that the decimal value of the Manchester word is below 128 and definitely wrong.
Additional Watch values show the last 25 read micros values read in the ISR. Failures are now very good documented.

ArduinoSamd21_MicrosProblem_v3_Overview

ArduinoSamd21_MicrosProblem_v3_Zoom

ArduinoSamd21_MicrosProblem_v3_Areas

ArduinoSamd21_MicrosProblem_v3_Watch

Two examples for the running oscilloscope with triggering on line D4 "pinISR_NotComplete". You can see how often a wrong measurement will be done. This will not occur on a NANO_Every platform!

2022-10-27.11-16-40.mp4
2022-10-27.11-20-37.mp4

Zero_Arduino_v3_ino.txt

@Peter28357
Copy link
Author

More detailed data (Version v3)
The additional output "pinISR_NotComplete" indicates that the decimal value of the Manchester word is below 128 and definitely wrong.
Additional Watch values show the last 25 read micros values read in the ISR. Failures are now very good documented.

ArduinoSamd21_MicrosProblem_v3_Overview

ArduinoSamd21_MicrosProblem_v3_Zoom

ArduinoSamd21_MicrosProblem_v3_Areas

ArduinoSamd21_MicrosProblem_v3_Watch

Two examples for the running oscilloscope with triggering on line D4 "pinISR_NotComplete". You can see how often a wrong measurement will be done. This will not occur on a NANO_Every platform!

2022-10-27.11-16-40.mp4
2022-10-27.11-20-37.mp4

Zero_Arduino_v3_ino.txt

@Peter28357 Peter28357 reopened this Oct 30, 2022
@Peter28357
Copy link
Author

Workaround with TC3 (Version v4)
The 16 bit TC3 is ok for my solution.
Now it is working perfect for the time critical measurements of 50µs and 100µs.

ArduinoSamd21_MicrosProblem_v4_Overview

ArduinoSamd21_MicrosProblem_v4_Zoom

ArduinoSamd21_MicrosProblem_v4_Areas

ArduinoSamd21_MicrosProblem_v4_Watch

ArduinoSamd21_MicrosProblem_v4_Workaround

2022-10-30.17-35-21.mp4

Zero_Arduino_v4_ino.txt

@JAndrassy
Copy link
Contributor

  if (currentBahnsignalMicros < previousBahnsignalMicros) {
    intervalBahnsignalMicros = currentBahnsignalMicros + (UnsignedLongMax - previousBahnsignalMicros);
  }
  else {
    intervalBahnsignalMicros = currentBahnsignalMicros - previousBahnsignalMicros;
  }

has always the same result as

intervalBahnsignalMicros = currentBahnsignalMicros - previousBahnsignalMicros;

https://arduino.stackexchange.com/questions/12587/how-can-i-handle-the-millis-rollover/12588#12588

@Peter28357
Copy link
Author

@JAndrassy
Thanks to your comment
For me:
If no timer overflow, the current is always greater or equal than the previous -> the else branch will be calculated
e.g. current = 30, previous = 10, -> interval = 20

If an timer overflow, the current is smaller than the previous -> only at this case the if branch will be calculated
e.g. current = 30, previous = 4294967285, LongMax = 4294967295 -> interval = 40

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants