arduino / arduino/ArduinoCore-samd

SAMD21 micros() problem

Open
#684 5 comments 0 reactions 0 assignees View on GitHub
Dominant language
C
Stars
502
Forks
740
PR merge metrics
No merged PRs in 30d

Description

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](https://user-images.githubusercontent.com/115471058/195798239-32c922fb-3843-4e76-b402-6dccbfe5007e.png)
![ArduinoSamd21_MicrosProblem_v2_Zoom](https://user-images.githubusercontent.com/115471058/195798359-ca728123-0779-4b45-9119-6e2c871e2df9.png)

Sketch:

```c++
/* 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 );
}

// -------------------------------------------------------------------------------------
```

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with the posted sketch, especially the ISR_BahnsignalDecodePur() and WhileWaitMicros() entry points that call micros(), and reproduce the timing failure on the listed SAMD21 boards and the NANO Every. Done would require identifying a reproducible cause for the incorrect intervalBahnsignalMicros value and documenting or correcting the behavior with evidence from the affected platforms.

Written by the indexing model from the issue text.

Assessment

Tech stack
arduino, cpp
Domain
embedded-iot
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.