Timer1 läuft nicht

Hallo,

ich bin momentan dabei einen bestehenden Code umzuschreiben. Es geht um die Steuerung eines Diskettenlaufwerks mit einem Arduino. Mit dem angehängten Code läuft zu Beginn der Lesekopf des Laufwerks an seine Startposition, somit ist es also definitiv richtig verkabelt und funktionstüchtig.

Eigentlich erwarte ich jedoch, dass der Lesekopf im Anschluss hin und herfährt, da an Indexposition 2 von currentPeriod ein Wert über 0 angegeben ist.

Wenn ich mit dem Multimeter zwischen Pin zwei und GND auf Durchgang messe, merke ich, dass dieser Pin permanent gegen Masse gezogen wird, obwohl er ja eigentlich pulsen sollte.

Ich vermute, nach stundenlanger, ergebnisloser Suche, dass es ein Problem mit dem Timer handelt.

Das mit der TimerOne Library mitgelieferte ISRBlink Beispiel funktioniert jedoch einwandfrei.

Wie kann ich bei meiner Fehlersuche am Besten vorgehen?

#include <TimerOne.h>

byte led_13 = 13;  // LED an Pin 13

boolean run_once = 1;  // Wird für Reset einmal ausgeführt

const byte FIRST_PIN = 2;  // Erster belegter Pin der angeschlossenen Laufwerke
const byte LAST_PIN = 3;   // Letzter belegter Pin der angeschlossenen Laufwerke

byte MAX_POSITION[] = {                    // Speicherung der Endpositionen der Leseköpfe (nur gerade Indexstellen)
  0, 0, 158, 0, 158, 0, 158, 0, 158, 0, 158, 0, 158, 0, 158, 0, 158, 0};

byte currentPosition[] = {                                   // Speicherung der momentanen Positionen der Leseköpfe
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};  // (Nur die geraden Speicherstellen werden hierfür verwendet)

/*

 Das folgende Array hält jeweils den Status der zwei Laufwerk_Anschlüsse fest.
 
 Gerade Indexstellen verwalten die einzelnen Schrittvorgänge.
 Ungeraden Indexstellen geben die momentane Richtung des Schrittmotors an. 
 
 LOW = vorwärts, HIGH = rückwärts
 
 */
 
boolean currentState[] = {
  0, 0, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW
};

/*

 Intervallsteuerung (nur gerade Indexstellen, 0 = aus)
 
 Jedes einzelne Intervall wird mit der bei der Initialisierung des Timers festgelegten
 Zeitdauer an Mikrosekunden multipliziert.
 
 */

unsigned int currentPeriod[] = {
  0, 0, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

// Intervall_Durchlauf_Zähler

unsigned int currentTick[] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
};

void setup()
  {
  
  pinMode(2, OUTPUT); // Schrittsteuerung Laufwerk 1
  pinMode(3, OUTPUT); // Richtungssteuerung Laufwerk 1
  
  pinMode(4, OUTPUT); // Schrittsteuerung Laufwerk 2
  pinMode(5, OUTPUT); // Richtungssteuerung Laufwerk 2
  
  pinMode(6, OUTPUT); // Schrittsteuerung Laufwerk 3
  pinMode(7, OUTPUT); // Richtungssteuerung Laufwerk 3
  
  pinMode(8, OUTPUT); // Schrittsteuerung Laufwerk 4
  pinMode(9, OUTPUT); // Richtungssteuerung Laufwerk 4
  
  pinMode(10, OUTPUT); // Schrittsteuerung Laufwerk 5
  pinMode(11, OUTPUT); // Richtungssteuerung Laufwerk 5
  
  pinMode(12, OUTPUT); // Schrittsteuerung Laufwerk 6
  pinMode(13, OUTPUT); // Richtungssteuerung Laufwerk 6
  
  pinMode(led_13, OUTPUT);  // LED an Pin 13
  
  pinMode(14, OUTPUT); // Schrittsteuerung Laufwerk 7
  pinMode(15, OUTPUT); // Richtungssteuerung Laufwerk 7
  
  pinMode(16, OUTPUT); // Schrittsteuerung Laufwerk 8
  pinMode(17, OUTPUT); // Richtungssteuerung Laufwerk 8
  
  Timer1.initialize(40); // Initialisiert einen Timer mit einer definierten minimalen Intervallzeit von 40 Mikosekunden
  Timer1.attachInterrupt(tick);  // "tick" wird von nun an permanent alle 40 Mikosekunden augferufen

}


void loop()
{
  if(run_once)  // Laufwerke resetten und im Anschluss zwei Sekunden warten
  {
    run_once = 0;
    resetAll();
    delay(2000);
  }
}

// Funktionen:

// tick() wird über den Timer Interrupt regelmäßig aufgerufen
// togglePin(byte pin, byte direction_pin)  beschaltet die Ausgänge nach einer best. Logik



// Zusatzfunktionen:

// reset(byte pin)
// resetAll()

void tick()  // Wird vom Timer Interrupt in einem definierten Intervall regelmäßig aufgerufen
{
  digitalWrite( 13, digitalRead( 13 ) ^ 1 );  // LED an Pin 13 ein-und ausschalten
  
  /* 
   
   Wenn ein Intervall für den Schrittsteueranschluss 2 festgelegt wurde,
   wird hochgezählt und der Anschluss beim Erreichen der Intervalldauer getoggelt
      
   */
   
  if(currentPeriod[2] > 0)                  // Wenn für den Anschluss 2 ein Intervall festgelegt wurde
  {
    currentTick[2]++;                       // Intervallzähler um eins hochzählen
    if(currentTick[2] >= currentPeriod[2])  // Ist ein Intervall vergangen
    {
      togglePin(2, 3);                      // Schrittmotor über weitere Funktion bewegen
      currentTick[2] = 0;                   // Neues Intervall starten
    }
  }
}

void togglePin(byte step_pin, byte direction_pin)  // step_pin = Schrittsteuerung, direction_pin = Richtungssteuerung
{
  if (currentPosition[step_pin] >= MAX_POSITION[step_pin])  // Beim Erreichen der oberen Endposition
  {
    currentState[direction_pin] = HIGH;  // die neue Fahrtrichtung des Lesekopfes protokollieren
    digitalWrite(direction_pin, HIGH);   // und die Richtungsänderung des Lesekopfes einleiten, damit dieser zurückläuft
  } 
  else if (currentPosition[step_pin] <= 0)    // Beim Erreichen der unteren Endposition
  {
    currentState[direction_pin] = LOW;   // die neue Fahrtrichtung des Lesekopfes protokollieren
    digitalWrite(direction_pin, LOW);    // und die Richtungsänderung des Lesekopfes einleiten, damit dieser wieder hochläuft
  }

  if (currentState[direction_pin] == HIGH)  // Die neue Position je nach Fahrtrichtung ermitteln
  {
    currentPosition[step_pin]--;  // Lesekopf soll einen Schritt zurückfahren
  } 
  else
  {
    currentPosition[step_pin]++;  // Lesekopf soll einen Schritt vorfahren
  }

  digitalWrite(step_pin, currentState[step_pin]);     // Lesekopf um einen Schritt bewegen
  currentState[step_pin] = ~currentState[step_pin];
}

// Zusatzfunktionen:

void reset(byte pin)  // Den Lesekopf eines Laufwerks zurücksetzen
{
  digitalWrite(pin+1, HIGH); // Go in reverse
  for (byte s = 0; s < MAX_POSITION[pin]; s += 2)  //Half max because we're stepping directly (no toggle)
  {
    digitalWrite(pin, HIGH);
    digitalWrite(pin, LOW);
    delay(5);
  }
  currentPosition[pin] = 0; // We're reset.
  digitalWrite(pin+1, LOW);
  currentPosition[pin+1] = 0; // Ready to go forward.
}

void resetAll(){

  // Old one-at-a-time reset
  //for (byte p=FIRST_PIN;p<=PIN_MAX;p+=2){
  //  reset(p);
  //}

  //Stop all notes (don't want to be playing during/after reset)
  for (byte p=FIRST_PIN;p<=LAST_PIN;p+=2){
    currentPeriod[p] = 0; // Stop playing notes
  }

  // New all-at-once reset
  for (byte s=0;s<80;s++){ // For max drive's position
    for (byte p=FIRST_PIN;p<=LAST_PIN;p+=2){
      digitalWrite(p+1,HIGH); // Go in reverse
      digitalWrite(p,HIGH);
      digitalWrite(p,LOW);
    }
    delay(5);
  }

  for (byte p=FIRST_PIN;p<=LAST_PIN;p+=2){
    currentPosition[p] = 0; // We're reset.
    digitalWrite(p+1,LOW);
    currentState[p+1] = 0; // Ready to go forward.
  }

}

Gruß Chris

So- weitere Stunden später:

Wenn tick aufgerufen wird, wird..

if(currentPeriod[2] > 0)                  // Wenn für den Anschluss 2 ein Intervall festgelegt wurde
  {
    currentTick[2]++;                       // Intervallzähler um eins hochzählen
    if(currentTick[2] >= currentPeriod[2])  // Ist ein Intervall vergangen
    {
      togglePin(2, 3);                      // Schrittmotor über weitere Funktion bewegen
      currentTick[2] = 0;                   // Neues Intervall starten
    }
  }

..nicht aufgerufen.

Kann mir das jmd. erklären? currentPeriod[2] ist doch eindeutig größer als 0. :0

Gruß Chris

currentPeriod ist nicht volatile definiert, somit geht der Compiler davon aus, dass er es wegoptimieren darf, wenn es nicht aufgerufen wird. Da tick nur per Interrupt aufgerufen wird, kriegt der Compiler davon nichts mit und geht von einer separaten Benutzung aus.

Also: alle Variablen, die Du global definierst und die im Interrupt-Kontext (also einem Interrupt-Handler) benutzt werden, als "volatile" deklarieren.

Bsp:

volatile unsigned int currentPeriod[] = {
  0, 0, 1000, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

Ok, geht aber noch immer nicht.

Total verrückt: Verwende ich eine andere Indexnummer desselben Arrays (auch ohne volatile), geht's auf einmal! :astonished:

Ein Beispiel:

#include <TimerOne.h>

byte led_13 = 13;  // LED an Pin 13

boolean run_once = 1;  // Wird für Reset einmal ausgeführt

const byte FIRST_PIN = 2;  // Erster belegter Pin der angeschlossenen Laufwerke
const byte LAST_PIN = 3;   // Letzter belegter Pin der angeschlossenen Laufwerke

byte MAX_POSITION[] = {                    // Speicherung der Endpositionen der Leseköpfe (nur gerade Indexstellen)
  0, 0, 158, 0, 158, 0, 158, 0, 158, 0, 158, 0, 158, 0, 158, 0, 158, 0};

byte currentPosition[] = {                                   // Speicherung der momentanen Positionen der Leseköpfe
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};  // (Nur die geraden Speicherstellen werden hierfür verwendet)

/*

 Das folgende Array hält jeweils den Status der zwei Laufwerk_Anschlüsse fest.
 
 Gerade Indexstellen verwalten die einzelnen Schrittvorgänge.
 Ungeraden Indexstellen geben die momentane Richtung des Schrittmotors an. 
 
 LOW = vorwärts, HIGH = rückwärts
 
 */
 
boolean currentState[] = {
  0, 0, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW
};

/*

 Intervallsteuerung (nur gerade Indexstellen, 0 = aus)
 
 Jedes einzelne Intervall wird mit der bei der Initialisierung des Timers festgelegten
 Zeitdauer an Mikrosekunden multipliziert.
 
 */

unsigned int currentPeriod[] = {
  0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

// Intervall_Durchlauf_Zähler

unsigned int currentTick[] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
};

void setup()
  {
  
  pinMode(2, OUTPUT); // Schrittsteuerung Laufwerk 1
  pinMode(3, OUTPUT); // Richtungssteuerung Laufwerk 1
  
  pinMode(4, OUTPUT); // Schrittsteuerung Laufwerk 2
  pinMode(5, OUTPUT); // Richtungssteuerung Laufwerk 2
  
  pinMode(6, OUTPUT); // Schrittsteuerung Laufwerk 3
  pinMode(7, OUTPUT); // Richtungssteuerung Laufwerk 3
  
  pinMode(8, OUTPUT); // Schrittsteuerung Laufwerk 4
  pinMode(9, OUTPUT); // Richtungssteuerung Laufwerk 4
  
  pinMode(10, OUTPUT); // Schrittsteuerung Laufwerk 5
  pinMode(11, OUTPUT); // Richtungssteuerung Laufwerk 5
  
  pinMode(12, OUTPUT); // Schrittsteuerung Laufwerk 6
  pinMode(13, OUTPUT); // Richtungssteuerung Laufwerk 6
  
  pinMode(led_13, OUTPUT);  // LED an Pin 13
  
  pinMode(14, OUTPUT); // Schrittsteuerung Laufwerk 7
  pinMode(15, OUTPUT); // Richtungssteuerung Laufwerk 7
  
  pinMode(16, OUTPUT); // Schrittsteuerung Laufwerk 8
  pinMode(17, OUTPUT); // Richtungssteuerung Laufwerk 8
  
  Timer1.initialize(40); // Initialisiert einen Timer mit einer definierten minimalen Intervallzeit von 40 Mikosekunden
  Timer1.attachInterrupt(tick);  // "tick" wird von nun an permanent alle 40 Mikosekunden augferufen

}


void loop()
{
  if(run_once)  // Laufwerke resetten und im Anschluss zwei Sekunden warten
  {
    run_once = 0;
    resetAll();
    delay(2000);
  }
}

// Funktionen:

// tick() wird über den Timer Interrupt regelmäßig aufgerufen
// togglePin(byte pin, byte direction_pin)  beschaltet die Ausgänge nach einer best. Logik



// Zusatzfunktionen:

// reset(byte pin)
// resetAll()

void tick()  // Wird vom Timer Interrupt in einem definierten Intervall regelmäßig aufgerufen
{
  digitalWrite( 13, digitalRead( 13 ) ^ 1 );  // LED an Pin 13 ein-und ausschalten
  
  /* 
   
   Wenn ein Intervall für den Schrittsteueranschluss 2 festgelegt wurde,
   wird hochgezählt und der Anschluss beim Erreichen der Intervalldauer getoggelt
      
   */
   
  if(currentPeriod[3] > 0)                  // Wenn für den Anschluss 2 ein Intervall festgelegt wurde
  {
    currentTick[2]++;                       // Intervallzähler um eins hochzählen
    if(currentTick[2] >= currentPeriod[2])  // Ist ein Intervall vergangen
    {
      togglePin(2, 3);                      // Schrittmotor über weitere Funktion bewegen
      currentTick[2] = 0;                   // Neues Intervall starten
    }
  }
}

void togglePin(byte step_pin, byte direction_pin)  // step_pin = Schrittsteuerung, direction_pin = Richtungssteuerung
{
  if (currentPosition[step_pin] >= MAX_POSITION[step_pin])  // Beim Erreichen der oberen Endposition
  {
    currentState[direction_pin] = HIGH;  // die neue Fahrtrichtung des Lesekopfes protokollieren
    digitalWrite(direction_pin, HIGH);   // und die Richtungsänderung des Lesekopfes einleiten, damit dieser zurückläuft
  } 
  else if (currentPosition[step_pin] <= 0)    // Beim Erreichen der unteren Endposition
  {
    currentState[direction_pin] = LOW;   // die neue Fahrtrichtung des Lesekopfes protokollieren
    digitalWrite(direction_pin, LOW);    // und die Richtungsänderung des Lesekopfes einleiten, damit dieser wieder hochläuft
  }

  if (currentState[direction_pin] == HIGH)  // Die neue Position je nach Fahrtrichtung ermitteln
  {
    currentPosition[step_pin]--;  // Lesekopf soll einen Schritt zurückfahren
  } 
  else
  {
    currentPosition[step_pin]++;  // Lesekopf soll einen Schritt vorfahren
  }

  digitalWrite(step_pin, currentState[step_pin]);     // Lesekopf um einen Schritt bewegen
  currentState[step_pin] = ~currentState[step_pin];
}

// Zusatzfunktionen:

void reset(byte pin)  // Den Lesekopf eines Laufwerks zurücksetzen
{
  digitalWrite(pin+1, HIGH); // Go in reverse
  for (byte s = 0; s < MAX_POSITION[pin]; s += 2)  //Half max because we're stepping directly (no toggle)
  {
    digitalWrite(pin, HIGH);
    digitalWrite(pin, LOW);
    delay(5);
  }
  currentPosition[pin] = 0; // We're reset.
  digitalWrite(pin+1, LOW);
  currentPosition[pin+1] = 0; // Ready to go forward.
}

void resetAll(){

  // Old one-at-a-time reset
  //for (byte p=FIRST_PIN;p<=PIN_MAX;p+=2){
  //  reset(p);
  //}

  //Stop all notes (don't want to be playing during/after reset)
  for (byte p=FIRST_PIN;p<=LAST_PIN;p+=2){
    currentPeriod[p] = 0; // Stop playing notes
  }

  // New all-at-once reset
  for (byte s=0;s<80;s++){ // For max drive's position
    for (byte p=FIRST_PIN;p<=LAST_PIN;p+=2){
      digitalWrite(p+1,HIGH); // Go in reverse
      digitalWrite(p,HIGH);
      digitalWrite(p,LOW);
    }
    delay(5);
  }

  for (byte p=FIRST_PIN;p<=LAST_PIN;p+=2){
    currentPosition[p] = 0; // We're reset.
    digitalWrite(p+1,LOW);
    currentState[p+1] = 0; // Ready to go forward.
  }

}

Ich checks grad überhaupt nicht mehr.

Gruß Chris

Hast Du alle Variablen, die Du in tick() (und allen Routinen, die daraus aufgerufen werden) verwendest, "volatile" deklariert? In meinem Post war nur ein Beispiel, damit ist es noch nicht getan.

Nein, ich hatte dies nur mit currentPeriod gemacht.

Gruß Chris

Nun ist alles volatiliert, geht aber trotzdem noch immer nicht (mit Indexposition 2):

#include <TimerOne.h>

volatile byte led_13 = 13;  // LED an Pin 13

volatile boolean run_once = 1;  // Wird für Reset einmal ausgeführt

volatile const byte FIRST_PIN = 2;  // Erster belegter Pin der angeschlossenen Laufwerke
volatile const byte LAST_PIN = 3;   // Letzter belegter Pin der angeschlossenen Laufwerke

volatile byte MAX_POSITION[] = {                    // Speicherung der Endpositionen der Leseköpfe (nur gerade Indexstellen)
  0, 0, 158, 0, 158, 0, 158, 0, 158, 0, 158, 0, 158, 0, 158, 0, 158, 0};

volatile byte currentPosition[] = {                                   // Speicherung der momentanen Positionen der Leseköpfe
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};  // (Nur die geraden Speicherstellen werden hierfür verwendet)

/*

 Das folgende Array hält jeweils den Status der zwei Laufwerk_Anschlüsse fest.
 
 Gerade Indexstellen verwalten die einzelnen Schrittvorgänge.
 Ungeraden Indexstellen geben die momentane Richtung des Schrittmotors an. 
 
 LOW = vorwärts, HIGH = rückwärts
 
 */
 
volatile boolean currentState[] = {
  0, 0, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW
};

/*

 Intervallsteuerung (nur gerade Indexstellen, 0 = aus)
 
 Jedes einzelne Intervall wird mit der bei der Initialisierung des Timers festgelegten
 Zeitdauer an Mikrosekunden multipliziert.
 
 */

volatile unsigned int currentPeriod[] = {
  0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};

// Intervall_Durchlauf_Zähler

volatile unsigned int currentTick[] = {
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
};

void setup()
{ 
  pinMode(2, OUTPUT); // Schrittsteuerung Laufwerk 1
  pinMode(3, OUTPUT); // Richtungssteuerung Laufwerk 1
  
  pinMode(led_13, OUTPUT);  // LED an Pin 13
  
  Timer1.initialize(8000); // Initialisiert einen Timer mit einer definierten minimalen Intervallzeit von 40 Mikosekunden
  Timer1.attachInterrupt(tick);  // "tick" wird von nun an permanent alle 40 Mikosekunden augferufen
}


void loop()
{
  if(run_once)  // Laufwerke resetten und im Anschluss zwei Sekunden warten
  {
    run_once = 0;
    resetAll();
    delay(2000);
  }
}

// Funktionen:

// tick() wird über den Timer Interrupt regelmäßig aufgerufen
// togglePin(byte pin, byte direction_pin)  beschaltet die Ausgänge nach einer best. Logik



// Zusatzfunktionen:

// reset(byte pin)
// resetAll()

void tick()  // Wird vom Timer Interrupt in einem definierten Intervall regelmäßig aufgerufen
{
  if(currentPeriod[2] > 0)                      // Wenn für den Anschluss 2 ein Intervall festgelegt wurde
  {
    currentTick[2]++;                       // Intervallzähler um eins hochzählen
    if(currentTick[2] >= currentPeriod[2])  // Ist ein Intervall vergangen
    {
      togglePin(2, 3);                      // Schrittmotor über weitere Funktion bewegen
      currentTick[2] = 0;                   // Neues Intervall starten
    }
  }
}

void togglePin(byte step_pin, byte direction_pin)  // step_pin = Schrittsteuerung, direction_pin = Richtungssteuerung
{
  if (currentPosition[step_pin] >= MAX_POSITION[step_pin])  // Beim Erreichen der oberen Endposition
  {
    currentState[direction_pin] = HIGH;  // die neue Fahrtrichtung des Lesekopfes protokollieren
    digitalWrite(direction_pin, HIGH);   // und die Richtungsänderung des Lesekopfes einleiten, damit dieser zurückläuft
  } 
  else if (currentPosition[step_pin] <= 0)    // Beim Erreichen der unteren Endposition
  {
    currentState[direction_pin] = LOW;   // die neue Fahrtrichtung des Lesekopfes protokollieren
    digitalWrite(direction_pin, LOW);    // und die Richtungsänderung des Lesekopfes einleiten, damit dieser wieder hochläuft
  }

  if (currentState[direction_pin] == HIGH)  // Die neue Position je nach Fahrtrichtung ermitteln
  {
    currentPosition[step_pin]--;  // Lesekopf soll einen Schritt zurückfahren
  } 
  else
  {
    currentPosition[step_pin]++;  // Lesekopf soll einen Schritt vorfahren
  }

  digitalWrite(step_pin, currentState[step_pin]);     // Lesekopf um einen Schritt bewegen
  currentState[step_pin] = ~currentState[step_pin];
}

// Zusatzfunktionen:

void reset(byte pin)  // Den Lesekopf eines Laufwerks zurücksetzen
{
  digitalWrite(pin+1, HIGH); // Go in reverse
  for (byte s = 0; s < MAX_POSITION[pin]; s += 2)  //Half max because we're stepping directly (no toggle)
  {
    digitalWrite(pin, HIGH);
    digitalWrite(pin, LOW);
    delay(5);
  }
  currentPosition[pin] = 0; // We're reset.
  digitalWrite(pin+1, LOW);
  currentPosition[pin+1] = 0; // Ready to go forward.
}

void resetAll(){

  // Old one-at-a-time reset
  //for (byte p=FIRST_PIN;p<=PIN_MAX;p+=2){
  //  reset(p);
  //}

  //Stop all notes (don't want to be playing during/after reset)
  for (byte p=FIRST_PIN;p<=LAST_PIN;p+=2){
    currentPeriod[p] = 0; // Stop playing notes
  }

  // New all-at-once reset
  for (byte s=0;s<80;s++){ // For max drive's position
    for (byte p=FIRST_PIN;p<=LAST_PIN;p+=2){
      digitalWrite(p+1,HIGH); // Go in reverse
      digitalWrite(p,HIGH);
      digitalWrite(p,LOW);
    }
    delay(5);
  }

  for (byte p=FIRST_PIN;p<=LAST_PIN;p+=2){
    currentPosition[p] = 0; // We're reset.
    digitalWrite(p+1,LOW);
    currentState[p+1] = 0; // Ready to go forward.
  }

}

Könnte es daran liegen, dass Deine Rundenzeiten nicht stimmen?

  Timer1.initialize(8000); // Initialisiert einen Timer mit einer definierten minimalen Intervallzeit von 40 Mikosekunden

Die Intervallzeit wird ca. 8ms sein und nicht 40µs.

Wie stellst Du sonst fest, ob der Code ausgeführt wird? Ich sehe keinen Code, der z.B. eine LED einschaltet oder dergleichen.

Daran, dass sich der Schrittmotor, wenn ich anstatt currentPeriod[2] das hier schreibe !currentPeriod[2], bewegt wie er soll.

Da es sich um einen aus meiner Sicht äußerst merkwürdigen Fall handelt, werde ich den Code demnächst so zusammenkürzen, dass nur noch das Kernproblem übrig bleibt.

Gruß Chris

Edit: Es war ein Denkfehler meinerseits. Innerhalb von resetAll() werden bei Inbetriebnahme sämtliche für die Intervallspeicherung relevanten Stellen von currentPeriod[] auf null gesetzt. Da dies lediglich jede zweite Stelle betrifft, ging es mit manchen der Indexstellen und mit manchen nicht. Hat mich einen kompletten Nachmittag gekostet- sehr ärgerlich. Ich weiss schon, warum es mir im Normalfall lieber ist, den Code von Grund auf selber zu programmieren, wenn mir dies möglich erscheint.