Geschwindigkeit eines Encoders mit arduino Mega ausgeben

Hallo,

ich möchte bei einem Pendelversuch die Geschwindigkeit des Pendelsta mit Hilfe eines Encoders von der Firma Sick (https://www.mysick.com/eCat.aspx?go=FinderSearch&C...) messen. Der Encoder ist oben an der Welle angebracht. Nun möchte ich die Signale mit meinem arduino MEGA auswerten. Da ich eher weniger Vorkenntnisse in Sachen Mikrocontroller-Programmierung habe, habe ich mich mal im Internet nach Quellcodes umgesehen. Dabei bin ich dann auf diesen Code gestoßen.

const int sensorPin = 2;
const int sensorInterrupt = 0;
const int timeoutValue = 5;

unsigned long lastPulseTime;
volatile unsigned long interval = 0;
volatile uint8_t timeoutCounter;

bool blink = false;

void setup()
{
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);    // enable internal pullup (if Hall 
sensor needs it)
  attachInterrupt(sensorInterrupt, sensorIsr, RISING);
  Serial.begin(9600);
  lastPulseTime = micros();
  timeoutCounter = 0;
}

void sensorIsr()
{
  unsigned long now = micros();
  interval = now - lastPulseTime;
  lastPulseTime = now;
  timeoutCounter = timeoutValue;
}

void loop()
{
  Serial.print(" RPM ");
  unsigned int rpm;
  if (timeoutCounter != 0)
  {
    noInterrupts();
    --timeoutCounter;
    unsigned long copyInterval = interval;
    interrupts();
    rpm = (unsigned int)(60000000UL/copyInterval);
  }
  else
  {
    rpm = 0;
  }
  Serial.println(rpm);
  delay(500);
}

Jedoch werden hier die Z-Signale (1 Signal pro Umdrehung) des Drehgebers ausgewertet. Dies ist bei mir aber nicht möglich, da mein Pendel immer nur ca. ein fünftel Umdrehung macht. Deshalb muss ich in meinem Fall den A-Kanal auswerten. Dies würde reichen, da ich nur die Geschwindigkeit und nicht die Richtung bestimmen will.

Nun wollte ich Fragen, ob mir irgendeiner sagen kann, wie ich diesen Code ändern muss, damit er für meine Vorgaben richtig ist. Oder hat mir irgendjemand noch einen anderen Code oder Programmier-Ansätze mit dem ich mein Problem lösen kann.

Hallo,

Dein Link hat bei mir nur eine Fehlermeldung gebracht. Vielleicht kannst Du da noch mal drauf gucken?

Gruß, Ralf

Ah entschuldigung. Vielleicht geht dieser:
https://www.mysick.com/eCat.aspx?go=DataSheet&Cat=Row&At=Fa&Cult=German&Category=Produktfinder&ProductID=71840

TLEINS8: Jedoch werden hier die Z-Signale (1 Signal pro Umdrehung) des Drehgebers ausgewertet. Dies ist bei mir aber nicht möglich, da mein Pendel immer nur ca. ein fünftel Umdrehung macht. Deshalb muss ich in meinem Fall den A-Kanal auswerten. Dies würde reichen, da ich nur die Geschwindigkeit und nicht die Richtung bestimmen will.

Laut Datenblatt handelt es sich um einen Drehgeber, der "vom Benutzer programmierbar" ist und "bis zu 10000 Impulse pro Umdrehung abgeben kann.

Wer hat Dir den Drehgeber auf nur einen einzigen Impuls pro Umdrehung programmiert? Und warum?

Wenn Du nur einen einzigen Impuls pro Pendeldurchgang bekommst, dann kannst Du keine "Geschwindigkeit" (Winkelgeschwindigkeit, Geschwindigkeit der Pendelspitze), sondern nur die "Frequenz" oder die "Periodendauer" der Pendelschwingung messen.

Wenn Du tatsächlich während des Pendelns die sich ständig schneller/langsamer werdende "Geschwindigkeit" des Pendels (null an den Totpunkten, Maximalgeschwindigkeit am unteren Punkt) messen möchtest, müßte der Drehgeber erst umprogrammiert werden, dass er mindestens wieder 1000 Impulse pro Sekunde abgibt.

Oder möchtest Du nur die Frequenz/Periodendauer des Pendels messen?

Du kannst ohne Probleme den Z-Ausgang verwenden wenn Du den Enkoder so montierst, daß der Home Index im Bereich der Bewegung ist, am besten wenn das in Pendel vertikaler Stellung ist.

@jurs man kann die Länge des Home Impuls messen und daraus die Gechwindigkeit errechnen, falls dieser nicht durch die Elektronik konstant gehalten wird. Einfacher geht es mit einer Lichtschranke.

Grüße Uwe

Ich habe das Programm im Internet gefunden. Mein Drehgeber gibt mir ja auch 10000 impulse pro Umdrehung wenn ich anstatt den Z-Kanal den A-Kanal an das Board anschließe.

Ich möchte während dem Fall Schwingen des Pendels so oft wie möglich die aktuelle Geschwindigkeit ausgeben lassen.

TLEINS8: Mein Drehgeber gibt mir ja auch 10000 impulse pro Umdrehung wenn ich anstatt den Z-Kanal den A-Kanal an das Board anschließe.

Ah verstehe: Nur der Z-Kanal liefert einen Impuls, der A-Kanal 10000 pro Umdrehung. Schön, schön.

TLEINS8: Ich möchte während dem Fall Schwingen des Pendels so oft wie möglich die aktuelle Geschwindigkeit ausgeben lassen.

Begrenzender Faktor dürfte dabei die "Ausgabe" sein, was hast Du vorgesehen? Serielle Schnittstelle auf 115200 Baud?

Ich kalkuliere gerade mal: Wenn Du Klartextausgaben machst und einen Ausgabewert des Controllers mit sechs signifikanten Stellen vorsiehst (z.B. "Mikrosekunden pro Impuls"), dann fallen an pro Messwert: - sechs signifikante Stellen - eine Stelle Dezimalpunkt - 2 Zeichen Zeilentrenner CRLF = 9 Zeichen pro Messwert

Bei 115200 Baud gehen ca. 11520 Zeichen pro Sekunde über die Leitung, Du bekommst also im Höchstfall: 11520/9 = 127 Messwerte pro Sekunde auf dem seriellen Monitor im Klartext ausgegeben.

Reicht das? Oder wie stellst Du Dir die Ausgabe vor und mit welcher Frequenz soll gemessen werden, falls das nicht reicht?

TLEINS8: Ich habe das Programm im Internet gefunden. Mein Drehgeber gibt mir ja auch 10000 impulse pro Umdrehung wenn ich anstatt den Z-Kanal den A-Kanal an das Board anschließe.

Ich möchte während dem Fall Schwingen des Pendels so oft wie möglich die aktuelle Geschwindigkeit ausgeben lassen.

Willst Du die Maximalgeschwindigkeit oder die Momentangeschwindigkeit? Die momentangeschwindigkeit schwankt zwischen null und Maximalgeschwindigkeit.

127 Messwerte pro Sekunde wäre völlig ausreichend.

Ich möchte die Momentangeschwindigkeit ausgeben.

TLEINS8: 127 Messwerte pro Sekunde wäre völlig ausreichend.

Ich möchte die Momentangeschwindigkeit ausgeben.

Dann hört es sich ja vergleichsweise einfach an:

Man müßte nun nur 1. per Interrupt die auftretenden Impulse und die dafür benötigte Zeit aufsummieren. 2. in einer engen Loop die aufsummierten Werte für Impulse und Zeit in eine Geschwindigkeit umrechnen (Impulse/Zeit, und zwar als Gleitkommazahl) und dann den Wert auf Serial ausgeben.

Dein Sketch versucht offenbar nicht "Impulse/Zeit" zu berechnen, sondern "Umdrehungen pro Minute", und der Wert soll als ganzzahliger Integer-Wert geliefert werden (also nur ganze Umdrehungen pro Minute). Das dürfte nicht das sein, was Du möchtest.

Probier mal, 1. und 2. wie genannt umzusetzen, dann solltest Du entsprechende Werte für die Geschwindigkeit auf den seriellen Monitor bekommen. Um mehr Messungen pro Sekunde zu erhalten, müßte die Baudrate (im Sketch und im seriellen Monitor) von 9600 auf 115200 hochgesetzt werden.

TLEINS8: 127 Messwerte pro Sekunde wäre völlig ausreichend.

Ich möchte die Momentangeschwindigkeit ausgeben.

Finde ich sinnlos da die Zahlen sich dauernd ändern. Grüße Uwe

Ich hab jetzt mal ein kleines Programm geschrieben:

unsigned long zaehler = 0;
unsigned long zeit = 0;
unsigned long startzeit = 0;
unsigned long messzeit = 1000000; // Messintervall in Mikrosekunden
float frequenz;
float rps;
float geschwindigkeit;
float phi = 3.141592654;

void setup()
{
   Serial.begin(9600);
   
   // wenn das Signal an Pin D2 (Interrupt 0) von LOW auf HIGH wechselt,
   // wird die Funktion "Messung" aufgerufen  
   attachInterrupt(0, Messung, RISING);
   
   startzeit=micros();
   Serial.print("Frequenz: ");
}

void loop()
{
   // leer
}

void Messung()
{
   
   zaehler++;
   if ((micros()-startzeit) >= messzeit)
   {
     frequenz= zaehler / 0.01;
     Serial.print("Frequenz: ");
     Serial.print(zaehler);
     Serial.println(" Hz");
     
     rps= frequenz/10000;
     geschwindigkeit = rps * phi;
     
      Serial.print("Umdrehungen/s: ");
     Serial.print(rps);
     Serial.println(" m/s");
     
     Serial.print("Geschwindigkeit: ");
     Serial.print(geschwindigkeit);
     Serial.println(" m/s");
     zaehler = 0;
     startzeit=micros();
     
  
   } 
}

Jedoch erscheint bei mir auf dem Monitor nichts. Woran könnte das liegen. Hat jemand eine Idee? Signale werden erkannt. An dem kann es nicht liegen.

Ohne deinen Code bis ins Detail verinnerlicht zu haben - die Unmengen an lahmen seriellen Ausgaben haben in der ISR nichts zu suchen!

Diese Ausgaben habe ich auch nur zur Kontrolle programmiert. Die kommen später alle Weg. Bis auf die Geschwindigkeitsausgabe natürlich. Aber an dem kann es ja wohl kaum liegen, dass ich nichts angezeigt bekomme.

Es lag wohl doch daran :) Weil seitdem ich die ganzen Ausgaben gelöscht habe, funktioniert mein Programm.

Danke für den Tipp!

Jetzt hätte ich nur noch eine kleine Frage was mein Ausgabefenster betrifft. Kann ich meine Daten von meinem Fenster auch irgendwie abspeichern? Da gibt es ja den Button "Senden". Aber irgendwie komm ich nicht drauf wie das funktionieren soll. :)

Mit diesem Button hast du die Möglichkeit, dem Arduino eine Zeichenfolge zu schicken. Du kannst aber die Inhalte des Ausgabefensters markieren und zum weiteren Gebrauch kopieren, da sind die Tastenkürzel Strg+a (alles markieren), Strg+c (kopieren) und Strg+v (einfügen) deine besten Freunde. ;)

Die Serial.print Ausgabe in Deinem DEMO Sketch braucht selbst über 30mS für die Ausgabe. Wenn ein weiterer Impuls (Interrupt) vom Encoder kommt wird dieser nicht verarbeitet. Grüße Uwe

Ah okay. Gibt es da irgendeine Möglichkeit, dies zu verhindern. Sodass keine Impulse unter Umständen verloren gehen?

Ja, die Interruptfunktion so kurz wie möglich halten, also ohne serial.print. Grüße Uwe

Du kannst die Serial-Ausgabe alle paar Sekunden in der Loop machen und dort den aktuellen Stand des Zählers ausgeben.