Projekt Drehachse für Fräsmaschine

Hallo zusammen,
ich habe ebenfalls den Verdacht es liegt an der seriellen Schnittstelle, doch ich habe zur Zeit keine andere Anzeigemöglichkeit für die Drehgeschwindigkeit. Später kann ich darauf verzichten, doch zur Inbetriebnahme habe ich schlechte Karten.
Ich könnte mir auch vorstellen, dass die Float-Werte ein Problem darstellen. Ich werde mal versuchen auf die Periodendauer statt die Drehzahl zu gehen.
Das wird dann vielleicht besser.

Hallo,
mir fällt gerade noch auf, dass auch die Sinusfunktion ein Problem sein könnte. Ich benutze den Sinus ja nur als Hilfsgröße um ein Rechtecksignal zu erzeugen. Gibt es da vielleicht eine bessere Lösung?
Gruß
DrFlopp

DrFlopp:
Hallo zusammen,
ich habe ebenfalls den Verdacht es liegt an der seriellen Schnittstelle, doch ich habe zur Zeit keine andere Anzeigemöglichkeit für die Drehgeschwindigkeit. Später kann ich darauf verzichten, doch zur Inbetriebnahme habe ich schlechte Karten.
Ich könnte mir auch vorstellen, dass die Float-Werte ein Problem darstellen. Ich werde mal versuchen auf die Periodendauer statt die Drehzahl zu gehen.
Das wird dann vielleicht besser.

Wenn die Seriele Schnittstelle das Nadelöhr ist dann erhöhe die Baudrate.

schreibe statt
Serial.begin(9600); // initialize the serial port:

Serial.begin(115200); // initialize the serial port:
und ändere den Wert auch im Terminal.

Eine Bautrate von 9600 verbraucht ca 1 mSek pro übertragenen Byte und bremst den Controller aus wie delay().

Grüße Uwe

Ich habe das schon öfter probiert, scheinbar macht das mein PC nicht mit. Immer wenn ich einen schnellere Überttragugsrate ausprobiere kommt nur Schrott heraus.
Gruß
DrFlopp

Hast Du den Wert unten rechts in Terminal des IDE auch geändert?

Grüße Uwe

Also am serial port liegt es definitiv nicht, jedenfalls wenn man nicht auf dem selben board das trigger signal in loop() erzeugt. Ich habe gerade mit 2 arduinos herumprobiert.

Ich schicke ein 5kHz signal auf den interrupt pin (digital2) und verwende die micros() funktion fuer gute zeitaufloesung.

Da ich mal davon ausgehe, dass du keine HF spindel hast, nehme ich von nun an 1kHz als signal, was bei 16 pulsen per revolution ca. 3750 rpm entspricht.

micros() hat eine granularitaet von 4µs, was hier ca. +- 10rpm entspricht. Daher macht speed als float-variable keinen sinn.

Hier der code fuer den frequenz generator:

void setup() {
// put your setup code here, to run once:
DDRD |= _BV(PD2);
}

void loop() {
// put your main code here, to run repeatedly:
//delayMicroseconds(500); // fuer hohe RPM
delay(10); // fuer niedrige RPM
PORTD &= ~_BV(PD2); // low
//delayMicroseconds(500);
delay(10);
PORTD |= _BV(PD2); // high
}

und dein code in etwas veraenderter/verkuerzter form:

int i; // Getriebeübersetzung
int s; // Sinunsfunktion

////
int R = 12; // Rechteckausgang
////

int Dir = 9; // Rechteckausgang
int En = 8; // Rechteckausgang
double w; // Omega

////
unsigned int RPM; // Spindeldrehzahl pro minute
#define PPR 16UL // pulse per revolution
////

volatile unsigned long T1; //Zeitstepel 1
volatile unsigned long T2; //Zeitstepel 2

// Encoder Interruptports
#define A 2 //Belegung der Encoderkanale A

void setup() {
i=40;
pinMode(R,OUTPUT);
pinMode(En,OUTPUT); //Enable Pin
pinMode(Dir,OUTPUT); //Direction Pin
pinMode(13,OUTPUT); // fuer diagnose LED

Serial.begin(9600); // initialize the serial port:

attachInterrupt(0,CHAInt, RISING); // Interrupt 0 führt CHAInt aus mit steigender Flanken
pinMode(A,INPUT); // Pin2 als Input
digitalWrite(A,HIGH); // Interne Pull Ups benutzt
}

void loop() {
cli();
unsigned long T1_temp = T1; // in microsekunden
unsigned long T2_temp = T2;
sei();

unsigned long DELTA = T2 - T1;

RPM = (unsigned int)( 1000000UL * 60UL / ( PPR * DELTA ) );

Serial.print("rpm: ");
Serial.println(RPM);
Serial.print("delta T in microsekunden: ");
Serial.println(DELTA);
}

void CHAInt ()
{
// PORTB |= _BV(PB5); // L-LED (13) an
if( PIND & _BV(PD2) )
{
T1 = T2;
T2 = micros();
}
// PORTB &= ~_BV(PB5); //L-LED (13) aus
}

Das funktioniert wunderbar, wohlgemerkt mit 2 boards. Beides auf einem laufen zu lassen ist verboten. Sollte der sinn deiner 'sinus' funktion darin bestehen auf dem selben board das rechtecksignal zu erzeugen, welches dann wiederum den interrupt triggert... autsch!

Das Ziel des Projektes ist es, eine Drehachse mit der Spindel synchron zu bewegen, das ist wichtig um damit schrägverzahnte Zahnräder fräsen zu können. Das Rechtecksignal benötige ich um einen Schrittmotor anzusteuern der den Rundtisch bewegt. Ich trigger also nicht den Inerrupt sonder den Stepp-Pin für den Stepperdriver.

@ madworm:
Vielen Dank für Deinen Code, ich habe natürlich einpaar Anfängerfragen. Ist es besser die Rechnung in einer Formel auszudrücken oder in zwei Formeln:

"unsigned long DELTA = T2 - T1;
RPM = (unsigned int)( 1000000UL * 60UL / ( PPR * DELTA ) );"

Wann benutzt man eine Variablendeklaration in der Loop und warum? Ich habe das bei den Experten schon so oft gesehen, dass ich glaube das muss Vorteile bringen.

Was bedeutet das UL (#define PPR 16UL, 1000000UL * 60UL)?

Viele Grüße
DrFlopp

'UL' steht fuer 'unsigned long'.

Bei der berechnung ist ja derauf zu achten, dass die zahlen auch in die variablen 'hineinpassen'.

Wenn man z.b.

Serial.println(1000*1000);

verwendet, dann wuerde man als ergebnis '1000000' erwarten, bekommt aber '19690'. Der compiler nimmt bei ZAHLEN ohne weitere spiezifikationen an, dass es signed integer sind (-32768...32767). Hier sind 30*32768 uebergelaufen und 19690 ist der rest.

Durch spiezifikation mit 'UL' sage ich der maschine deutlich, dass sie die zahl als unsigned 32bit variable zu betrachten hat (0...4.3Mrd), dann rechnet er 'richtig'.

Die deklaration der variable innerhalb einer funktion hat den vorteil, dass sie ausserhalb nicht mehr vorhanden ist. Man kann so z.b. bei geschachtelten funktionen den selben variablen namen verwenden, weil die aeussere funktion die in der inneren definierte nicht sieht. Weiterhin steht der speicher fuer diese variablen beim verlassen der funktion wieder zur verfuegung. Globale variablen leben ewig.

Ich habe die formel in 2 teile geteilt, weil ich das uebersichtlicher finde. Ausserdem habe ich 'DELTA' fuer die serielle ausgabe benoetigt.

Bezueglich der spindel:

Also der drehtisch soll sich z.b. mit der z-position des fraeskopfes bewegen. Ich dachte schon, das sollte phasen-starr mit der spindel-rotation selbst sein.

Oder meinst du doch soetwas?

Hallo Madworm,
vielen Dank für deine Erklärung die helfen mir wirklich sehr, ich verstehe immer mehr was da passiert.
Synchronität nicht mit der Z-Bewegung sondern mit der Spindeldrehzahl wie Deine erste Vermutung. Die Spindeldrehzal ist aber nicht sehr groß < 200 RPM. In späteren Schritten könnte ich mir vorstellen die Drehachse auch mit den anderen Maschinenachsen zu kombinieren. Aber erst mal barauche ich die Kombination mit der Spindel.
Ich muss jetzt erst noch ein anderes Projet weiter bringen, heute Abend werde ich das ausprobieren. Ich bin gespannt und freue mich schon darauf.
Vielen Dank
DrFlopp

Machbar ist es jedenfalls.

Hallo Madworm,
vielen Dank für das Video, das muss doch hinzubekommen sein.
Ich habe deinen Code jetzt ausprobiert, ich habe dabei die Übertragungsrate und das ein und ausschalten des Interrupts variirt. Ich habe die Spindel mit konstant 150 RPM rotieren lassen. Im Anhang findes Du ein Textdokument mit den Daten aus dem Terminal-Fenster. Ich bilde mir ein einen Einfluß der Übertragungsrate und der Interruptfunktion erkennen zu können.
Befriedigend ist das aber irgend wie nicht oder?
Gruß DrFlopp

Messung.txt (2.84 KB)

Unter meinen idealbedingungen kann ich das nicht nachvollziehen. Ich habe mir ca. 5 minuten die ausgabe angesehen, nicht 1x gab es falsche rpm werte. Ich wuerde sagen, du hast ein problem mit der signalqualitaet des encoders. Wenn dein oszilloskop einen masken-test kann, dann koenntest du mal nach ausreissern in der pulslaenge des encodersignals suchen. Vielleicht langt es auch schon einen schmitt-trigger einzufuegen, der die pulsform aufraeumt. Oder ein staerkerer externer pull-up widerstand + RC filter gegen unrat auf der leitung.

Die viel zu hohen drehzahlen entsprechen ja zu kurzen zeiten, also wird der interrupt zu oft ausgeloest. Das ist fakt. Mit einem 'mono-flop' koenntest du dafuer sorgen, dass ein puls vom encoder einen puls wohl definierter laenge erzeugt. Die pulsdauer kann man dann so einstellen, dass ein zu frueh einsetzender falscher puls ignoriert wird. Mit einem nicht re-trigger baren mono-flop dazwischen sollte die drehzahl niemals hoeher als X gemessen werden koennen.

http://www.datasheetcatalog.org/datasheets/120/375514_DS.pdf

Hallo Leute,
ich habe jetzt eine neue Encoderscheibe gefertigt. Damit bekomme ich recht gute Werte für die Drehzahl. Allerdings nur solange ich den Schrittmotor nicht anschließe. Die Schrittmotorströme scheinen das Encodersignal zu Stören. Ich werde jetzt mal versuchen die Schrirmung für das Motorkabel aufzulegen. Ich werde die Motorseitige Schirmung mal auf Masse legen, die treiberseitig versuche ich es dnn mal mit dem GND-Pin.
Ich habe die Regelung jetzt von Drehzahl auf Delta-T umgestellt. Dann benötige ich wesentlich weniger Divisions-Operationen und Float-Daten, sollte also besser funktionieren.

Habt Ihr bessere Ideen?
Gruß DrFlopp

Hallo Leute,
ich habe jetzt das Problem eingegrenzt. Wenn ich dis Spannungs versorgung für den Motor am PololuBoard anschließe bekomme ich keine Probleme mit dem Encoder. Ich habe jetzt die Schirmung des Motorkabels auf beiden seiten aufgelegt. Motorseite am Gehäuse, Treiberseite auf den Minuspol der Versorgung.
Hat jemand eine Idee wo ich noch nach dem Fehler suchen kann?
Viel Grüße
DrFlopp

Es ist eine Menge geschafft. Ich habe den Encoder jetzt deutlich verbessert, ich habe die Sromversorgung der Lichtschrane jetzt vollständig über den Arduono laufen, früher noch über die Fräsmaschine. Die neue Encoderscheibe liefert wesentlich sauberere Signale. Jetzt ist ganz deutlich zusehen wenn ich die serielle Kommunikation einschalte habe ich größere Ausfälle in der Regelung als wenn ich sie ausschalte. Bei ausgeschalteter serieller Kommunikation habe ich aber immer noch einen stotternden Lauf. Ich habe noch einen Smoosing Filter eingebaut, doch das hilft nicht sehr viel. Als nächstes versuche ich ein Notchfilter, ich weiß aber noch nicht so genau wie ich das programmieren soll.
Viele Grüße
DrFlopp

Hallo Leute,
ich habe nun ein Notch-filter ausprobiert in dem ich gesagt habe bitte keine Abweichngen von mehr als 10% zulassen. Das Ergebnis war nicht befriedigend. Ich weiß nicht warum aber ich bin auf die Idee gekommen die Schiermung des Motorkabels auf der Aktorseite vom Gehäuse zu lösen und siehe da alles ist GUT!!!. Die Karre Läuft Freude große Freude, Hi Hi!!
Guß DrFlopp

Hallo Leute,
die gestrige Euphorie war vielleicht estwas verfrüht. Heute ging wieder nichts. Ich habe jetzt das Encoder Kabel auch geschirmt, das funktiniert jetzt. Ich habe nur noch geringe Schwankungen in den Messwerten, die ich auf Ungleichmäßigkeiten in der Spindeldrehzahl zurück führe, also sollte das funktionieren.
Jetzt hatte ich das Problem, dass mein Steppertreiber sehr heiß wurde. Ich habe einen kleinen 12V Lüfter mit auf die Platiene gebaut, und blase den Pololu-Treiber an. Der wird dadurch so gut gekühlt, dass man ihn auch anfassen kann.
Doch kaum dass man ein Problem gelöst hat kommt auch gleich das nächte. Ich erreiche nicht mehr die erforderliche Drehzahl am Stepper. Ich habe im Allegro Datenblatt gelesen, dass der Chipp 2 Microsecunden minimale Periodendauer verträgt.

Meine erforderliche Periodendauer liegt bei 5516 micros() bei minimaler Spindeldrehzahl. Das schafft der Motor nicht mehr. Bei ca 16000 micros() läuft er noch sehr sauber.
Wo kann das Problem liegen?
Viele Grüße
DrFlopp

Da der stepper in erster naeherung eine induktivitaet ist, geht sein drehmoment ja mit steigender step-frequenz nach unten da XL mit der frequenz steigt. Der motor sollte sich also bei zu hoher step-frequenz sehr leicht mit den fingern stoppen lassen.

Zur kompensation muss die versorgungsspannung fuer die motoren merklich angehoben werden, damit der strom in den wicklungen schnell genug ansteigen kann. Die maximal zulaessige spannung legt der treiber fest.

Hallo Madworm,
das Problem ist gefunden, ich habe den Stepp pin auf den Arduino Pin 10 gelegt. Parallel hatte ich das Signal auch auf den LED-Pin 13 gelegt. Mit dem Ociloskop konnte ich dann nachmessen, dass ich auf dem LED-Pin 13 ein schönes Rechteck liegen katte, doch auf dem PIN10 eine konstante Ppannung. Dann habe ich den PIN 9 ausprobier, mit dem selben Ergebnis. Ein kurzer Blick auf das Board zeigt PIN 9 und PIN10 sind PWM-Ports, PIN13 nicht - Scheinbar ist das der Grund. Kann das jemand erklären?
Viele Grüße
DrFlopp

madworm:
Da der stepper in erster naeherung eine induktivitaet ist, geht sein drehmoment ja mit steigender step-frequenz nach unten da XL mit der frequenz steigt. Der motor sollte sich also bei zu hoher step-frequenz sehr leicht mit den fingern stoppen lassen.

Zur kompensation muss die versorgungsspannung fuer die motoren merklich angehoben werden, damit der strom in den wicklungen schnell genug ansteigen kann. Die maximal zulaessige spannung legt der treiber fest.

madworm
Das stimmt nur zum Teil.
Das stimmt für Spannungsgesteuerte Schrittmotore. Bei dieser Ansteuerung kannst Du die Spannung aber nicht über die Nennspannung des Schrittmotors erhöhen da ansonsten bei langsamer Drehzahl der Strom zu groß wird.
Stromgesteuerte Schrittmotore mit dem Entsprechenden Treiber begrenzen den Strom und so kann der Motor nicht durchbrennen. Für diese Ansteuerung beraucht es ca die 4-fache Nennspannung des Motors.
Grüße Uwe