Hallo,
ich bin absoluter Neuling und versuche mich an dem Arduino Mega2560.
Ich möchte gerne von einem Motor die Drehzahl auslesen.
Dazu habe ich von der Firma TR-Electronic einen Drehgeber (IMV36-00003).
Programmieren würde ich dies sehr gerne mit Matlab bzw. Simulink, da ich einen PID-Regler aufbauen will (dies ist aber momentan noch nicht in Sicht).
Wie bekomme ich das am besten hin? Hat mir jemand einen Tipp?
Also als erstes fehlt mir der Link zu Deiner Hardware (dem Drehgeber).
Wie möchtest Du den Arduino mit Matlab/Simulink programmieren? Das sind Programme, die auf einem PC laufen, also gehe ich davon aus, dass Du Deine Applikation irgendwie zweiteilen willst, ein Teil erledigt der Arduino, den anderen übernimmt der PC, aber Du hast uns noch nicht verraten, wie diese Aufteilung aussehen soll. Einen PID-Regler kannst Du auch auf dem Arduino realisieren, dafür bräuchtest Du den PC nicht. Du solltest uns also genauer erklären, wie Dein Projekt aussehen soll, bzw. was Du erreichen willst.
Also zu meinem Projekt:
Ich möchte mit dem Arduino und dem Drehgeber die Momentan-Drehzahl eines Motors auslesen.
Diese Drehzahlwerte sollen dann auf dem Serial-Port ausgelesen werden.
Dies möchte ich gerne mit Simulink auf den Arduino programmieren.
Hoffe mal ich habe dies jetzt verständlich erklärt
Das ist C und AVR allgemein und muss daher angepasst werden (vor allem die Interrupts), aber die Algorithmen funktionieren im Prinzip genauso auf dem Arduino.
Oder funktioniert der anders als einfach nur zwei phasenverschobene Impulse auszugeben? Das ist aus dem Datenblatt nicht ganz ersichtlich.
Du kannst den Arduino nicht direkt mit Simulink programmieren. Das normale ist die Standard Arduino IDE. Außerdem gibt es noch Eclipse (was aber kompliziert einzurichten ist), oder das VisualMicro Plugin für VisualStudio (nur die Vollversion), bzw. Atmel Studio (gibts kostenlos).
Programmiert wird aber in C/C++.Wenn du da etwas graphisch Visualisieren möchtest musst die die Daten mit Serial raus schicken (über USB) und auf dem PC entsprechend einlesen und verarbeiten.
Ok, kannte ich nicht. Dann lad dir das halt mal runter und probiere es aus
Mir scheint das aber nicht wirklich eine vernünftige Alternative zur direkten Programmierung zu sein. Von der Beschreibung ist das eher zum Lernen gedacht und nicht für richtige Anwendungen.
Hab ich breits schon und habe schon ein paar sachen gemacht. Vorteile ist, dass man PID-Regler einfach auslegen kann da einem
die gesamte Simulink-Bib zur verfügung steht. Da das Ziel des Projekts ist einen solchen Regler aufzubauen würde ich es sehr gerne in Simulink machen.
Der Regler ist auch nicht das momentane Problem, ich benötige erst einmal alle Datenquellen.
Und eben die erste wäre die Drehzahl.
Das heißt, dass Ihr noch nicht mit der Simulink-Toolbox gearbeitet habt für Arduino
Das ist eben das Problem mit sowas. Libraries für verschiedene Hardware findest du genug. Die sind aber halt alle in C geschrieben. Das hatte ich auch schon bei anderen Sachen, wo eine Plattform ein paar gute Eigenschafte hatte, aber durch den schlechten Support im Vergleich zu anderen Optionen unattraktiv wurde.
Hallo,
du hattest wohl recht! Werde das Problem so in die Hand nehmen!
Habe schon mal angefangen die Geschwindikeit aufzunehmen.
Jedoch stimmt dabei etwas nicht…ich mache nichts am Drehgeber aber mal kommt 0 dann mal 300 als ergebnis heraus
Das Datenblatt des Drehgeber den ich verwende habe ich im Anhang
Hier mal die Programmierung:
void setup() {
pinMode(2, INPUT); // Eingangspin auf Eingang
Serial.begin(9600);
attachInterrupt(0, readmicros, RISING ); // Interrupt 0 auf Routine
}
volatile unsigned long dauer=1; // microsekunden
volatile unsigned long last=0; // Zählerwert
long drehzahl; // selbstredend
char buf[17]; // Pufferstring für sprintf
long faktor=0.029296875; // faktor = 60 Sekunden / Inkrementale des Drehgebers -> Umdrehungen pro Minute
void readmicros() { // Interrupt-Routine
unsigned long m = micros(); // Microsekunden auslesen
dauer = m - last; // Differenz letzte
last = m; // Letzten Wert merken
}
void loop() { // Hauptprogramm
drehzahl = faktor*dauer; // Drehzahl ausrechnen
Serial.println(drehzahl); // Puffer ausgeben
delay(500);
}
micros() und millis() funktionieren in Interrupt-Routinen nicht korrekt (d.h. sie werden nicht inkrementiert), da der Timer mit dem diese gezählt werden selbst mit einem Interrupt läuft.
Serenifly:
micros() und millis() funktionieren in Interrupt-Routinen nicht korrekt (d.h. sie werden nicht inkrementiert), da der Timer mit dem diese gezählt werden selbst mit einem Interrupt läuft.
Es ist richtig, dass sie innerhalb der interrupt-Routine nicht incrementiert werden.
Aber das tut ja nichts zur Sache, da readmicros() ja schnell vorbei ist.
Ein Problem ist, dass sich keiner für die gemessene dauer zwischen zwei Interrupten interessiert, denn loop() hängt meist im delay.
Das zweite Problem ist, dass dauer größer als ein byte ist, und daher nicht immer am Stück in loop übernommen wird.
Das dritte Problem ist, dass ein long eine ganze Zahl (integer) ist, und bei
long faktor=0.029296875;
der Compiler fies grinst, weil es syntaktisch richtig ist, aber kein Unterschied zu
long faktor = 0;
Was passiert denn bei
void loop() {
noInterrupts();
unsigned long d = dauer;
interrupts();
Serial.println(d*2929/100000);
delay(500);
}
Damit kriegst du wenigstens alle halbe Sekunde die gerade letzte dauer mit Umrechnung angezeigt.
Ob du lieber einen Mittelwert der letzten halben Sekunde haben willst, musst du wissen.
Serenifly:
micros() und millis() funktionieren in Interrupt-Routinen nicht korrekt (d.h. sie werden nicht inkrementiert), da der Timer mit dem diese gezählt werden selbst mit einem Interrupt läuft.
Es ist richtig, dass sie innerhalb der interrupt-Routine nicht incrementiert werden.
Aber das tut ja nichts zur Sache, da readmicros() ja schnell vorbei ist.
Innerhalb der Interrupt-Routine werden micros() und millis() nicht incrementiert, zwischen den Interrupt-Routine-Aufrufen aber schon. Die Interrupt-Routine soll so kurz wie möglich sein und ist deshalb schnell abgearbeitet. Die Zeit wird ein klein wenig zu langsam sein aber das ist meist unbedeutend für die korrekte Funktion des Sketches.
Jedoch bekomm ich beim Kompilieren folgenden Fehler:
sketch_jul24a.ino: In function ‘void HandleInterruptA()’:
sketch_jul24a:37: error: invalid type argument of ‘unary *’
Hier mein aktueller Code:
#include <digitalWriteFast.h> // library for high performance reads and writes by jrraines
// see http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1267553811/0
// and http://code.google.com/p/digitalwritefast/
// Quadrature encoders
#define c_EncoderInterrupt 4
#define c_EncoderPinA 19
#define c_EncoderPinB 25
#define EncoderIsReversed
volatile bool _EncoderBSet;
volatile long _EncoderTicks = 0;
void setup()
{
Serial.begin(115200);
// Quadrature encoders
// encoder
pinMode(c_EncoderPinA, INPUT); // sets pin A as input
digitalWrite(c_EncoderPinA, LOW); // turn on pullup resistors
pinMode(c_EncoderPinB, INPUT); // sets pin B as input
digitalWrite(c_EncoderPinB, LOW); // turn on pullup resistors
attachInterrupt(c_EncoderInterrupt, HandleInterruptA, RISING);
}
void loop()
{
Serial.print(_EncoderTicks);
Serial.print("\t");
delay(20);
}
// Interrupt service routines for the left motor's quadrature encoder
void HandleInterruptA()
{
// Test transition; since the interrupt will only fire on 'rising' we don't need to read pin A
_EncoderBSet = digitalReadFast(c_EncoderPinB); // read the input pin
// and adjust counter + if A leads B
#ifdef EncoderIsReversed
_EncoderTicks -= _EncoderBSet ? -1 : +1;
#else
_EncoderTicks += _EncoderBSet ? -1 : +1;
#endif
}
Gibts noch einen Tipp wie ich den Code am besten erweiteren kann in Richtung Geschwinkigkeit?
Zeitfunktionen kann ich ja nicht anwenden bezüglich der Interrupts so wie ich das jetzt mitbekommen habe.