Hallo Leute,
mein Name ist Bastian und ich bin neu hier im Forum. Ich steige grade erst in die Welt des Arduinos bzw. des Programmierens ein, deshalb habe ich noch nicht viel Ahnung. Aber ich gebe mir Mühe.
Ich möchte mit einem Arduino UNO ein TTL Signal eines Längenmessgeräts auslesen. Eine Schaltung interpoliert das eigentliche Sinussignal und gibt ein TTL-Quadratursignal aus. Über ein geschirmtes Kabel werden die beiden Signale A und B und die entsprechend invertierten Signale A' und B' zur Auswertelektronik geführt, wo aus den Signalen jeweils wieder die reinen Signale A und B gemacht werden. Diese kommen an meinem Arduino über Pin 9 und 10 an.
Laut der Angaben des Herstellers sollen die beiden Eingänge mit 100 kHz abgefragt werden.
Dazu habe ich diesen Code übernommen und die Timereinstellungen entsprechend angepasst. Die Abfrage findet nun mit 250 kHz statt, was ein bisschen viel ist. Allerdings weiß ich nicht, wie ich die Clock Select Bits wählen muss um mit einem entsprechenden Teiler auf die 100 HZ zu kommen. Wobei eine höhere Abfragefrequenz ja eigentlich nicht schaden kann. Oder?
Hier der verwendete Code:
// Copyright (C) 2014 Ralf Hübben - www.meinDUINO.de
// An die Pins 9 und 10 ist der Encoder angeschlossen
#define encoderA 9
#define encoderB 10
// Globale Variablen zur Auswertung in der
// Interrupt-Service-Routine (ISR)
volatile int8_t altAB = 0;
volatile int encoderWert = 0;
// 1/1 Auflösung
int8_t schrittTab[16] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
/*************************************************************
*
* Interrupt Service Routine
*
* Wird aufgerufen, wenn der entsprechende Interrupt
* ausgelöst wird
*
*************************************************************/
ISR(TIMER1_COMPA_vect) {
altAB <<= 2;
altAB &= B00001100;
altAB |= (digitalRead(encoderA) << 1) | digitalRead(encoderB);
encoderWert += schrittTab[altAB];
}
/*************************************************************
*
* void setup()
*
* Wird einmal beim Programmstart ausgeführt
*
*************************************************************/
void setup() {
pinMode(encoderA, INPUT);
pinMode(encoderB, INPUT);
noInterrupts(); // Jetzt keine Interrupts
TIMSK1 |= (1<<OCIE1A); // Timer 1 Output Compare A Match Interrupt Enable
TCCR1A = 0; // "Normaler" Modus
// WGM12: CTC-Modus einschalten (Clear Timer on Compare match)
// Stimmen OCR1A und Timer überein, wird der Interrupt
// ausgelöst
// Bit CS11<<1 setzen, Teiler ist 64
TCCR1B = (1<<WGM12) | (1<<CS11);
// Frequenz = 16.000.000 / (64) Teiler aus CSxx = 250.000 Hz
// Überlauf bei 19, weil die Zählung bei 0 beginnt
OCR1A = 19;
interrupts(); // Interrupts wieder erlauben
Serial.begin(115200);
}
/*************************************************************
*
* void loop()
*
* Wird immer wieder durchlaufen
*
*************************************************************/
void loop() {
while(true) {
Serial.println(encoderWert);
delay(1000);
}
}
Zunächst sollen einfach nur die gezählten Änderungen mit Hilfe des Serial Displays dargestellt werden (später dann auf einem LCD). Das funktioniert auch schon ganz gut, die Änderungen werden addiert wenn ich den Weg verändere, gehe ich wieder auf die Ursprungsposition zurück, landet auch der Zähler wieder bei Null.
Aber: Das funktioniert nur bei sehr langsamen Verfahrgeschwindigkeiten (irgendwo um 5 mm pro Sekunde). Laut Hersteller sollen aber 1000 mm pro Sekunde bei 100 kHz Abfragefrequenz gut möglich sein. Verfahre ich schneller, dann gehen Schritte verloren und der Zähler landet nicht wieder bei Null.
Habt ihr Ideen? Was ich so gelesen habe sollte der Arduino UNO mit 100 kHz noch klarkommen, oder?
Sind irgendwo Fehler oder ein "Flaschenhals"?
Wie gesagt, ich habe noch nicht viel Ahnung und ein solches Projekt ist auch wahrscheinlich eher nichts für Anfänger. Aber man lernt ja nur dazu, wenn man sich den Herausforderungen stellt.
Ich denke, dass ich die Funktionsweise des obigen Codes halbwegs verstanden habe.
Vielen Dank schon mal für eure Hilfe!
Gruß
Bastian