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