AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi Ablauf für Fräsmaschine programmieren
Thema durchsuchen
Ansicht
Themen-Optionen

Ablauf für Fräsmaschine programmieren

Ein Thema von 100nF · begonnen am 26. Sep 2008 · letzter Beitrag vom 21. Nov 2008
Antwort Antwort
Seite 4 von 7   « Erste     234 56     Letzte »    
markusj

Registriert seit: 9. Dez 2005
Ort: Kandel
408 Beiträge
 
#31

Re: Ablauf für Fräsmaschine programmieren

  Alt 29. Sep 2008, 21:37
Du bekommst damit niemals eine exakt diagonale Bewegung hin, du bewegst deine Achsen immer getrennt.
Noch dazu kommt: Der langsamste Motor bestimmt die Geschwindigkeit. Und die ist niemals die von dir erwartete.
Der Grund: Du arbeitest blockierend und mit Verzögerung.

Dafür habe ich meine Zeitscheiben. Geplant ist folgendes:
Zu einer (linearen) Bewegung gibt es für jede Achse folgenden Datensatz:
- Anzahl zu erledigender Schritte
- Anzahl der zu wartenden Zeitscheiben zwischen zwei Schritten (Geschwindigkeitsfaktor)
- Zeitscheibenzähler

Jede Zeitscheibe wird der Zähler dekrementiert und dann geprüft, ob er null ist.
Für alle Achsen, bei denen dies der Fall ist, werden getoggelt.
Dann wird der Zähler wieder zurückgesetzt auf den Startwert, die Anzahl der zu erledigenden Schritte um eins reduziert, bis diese Anzahl schließlich bei null angekommen ist.
Wenn alle Achsen ihre Zielposition erreicht haben, wird der nächste Job geladen.

@RS232: Im Moment noch gar keine. Die Firmwareentwicklung steht im gerade im Vordergrund, sobald die Firmware so weit ist, dass sie ein Gegenstück braucht, entsteht dieses langsam. Google und die Suchfunze spucken aber diverse Möglichkeiten aus.

mfG & Happy Coding
Markus
Markus
  Mit Zitat antworten Zitat
100nF

Registriert seit: 7. Nov 2004
639 Beiträge
 
#32

Re: Ablauf für Fräsmaschine programmieren

  Alt 30. Sep 2008, 17:53
Zitat:
Du bekommst damit niemals eine exakt diagonale Bewegung hin, du bewegst deine Achsen immer getrennt.
Ja schon, doch die maximale Abweichung kann nur 1 Schritt sein und das würde ich noch akzeptieren...
Aber ist natürlich schon eine schlechte Lösung, das ist mir schon klar!

Das mit den Zeitscheiben (=Timer?!) habe ich so halbwegs verstanden... aber diese 3 Zeitscheiben-Prozeduren müssen doch genau gleichzeitig ausgeführt werden, da bräuchte es doch Threads?!
Das begreife ich irgendwie nicht. Du kannst ja auch nicht bei allen 3 Schrittmotoren exakt im gleichen Moment einen Schritt ausführen oder, eine minimale Verzögerung zwischendrin hast du doch immer?

Naja...also sobald du mal ein bisschen Code zum angucken hast, wäre ich sehr froh wenn du den mal posten könntest. Ich denke, ich probiere jetzt auch mal mit den Übertragungsroutinen zu beginnen. Wenn ich grad Zeit habe schaue ich auch mal wie die Timer so funktionieren...

Zur RS232: Jo hab da schon paar Sachen gefunden, ich verwendete bisher eine Komponente dafür (TApdComPort). Da gibts dann ein PutChar(), PutString() und ein PutBlock(Word). Bräuchte ich da wohl PutBlock (genügt ein Word für das ganze Telegramm)?

mfg
Urban
  Mit Zitat antworten Zitat
markusj

Registriert seit: 9. Dez 2005
Ort: Kandel
408 Beiträge
 
#33

Re: Ablauf für Fräsmaschine programmieren

  Alt 30. Sep 2008, 18:24
Mir ist dieser Beitrag im Forum aufgefallen, diese Form der Ansteuerung schaut doch ganz nett aus, oder?

Zur "gleichzeitigen" Ansteuerung: Der Trick besteht darin, dass ich erst berechne, welche Motoren bewegt werden müssen. Diese sind bei mir alle am PortB angeschlossen, ich kann also mit einer einzigen Zuweisung alle nötigen Pins toggeln.
Wie du bereits erraten hast, findet dieser Teil komplett in der Timer-ISR statt.

Ich hatte mir zuerst Gedanken über die Programmstruktur gemacht und dann mit den Bresenham-Routinen angefangen.
Daraufhin habe ich das Kommunikationsprotokoll und die dazugehörigen Routinen so entworfen, dass alle anderen (zu diesem Zeitpunkt ja noch nicht existenten) Module damit arbeiten können.

Im Moment optimiere ich meine Bresenham-Berechnungen "etwas", bei Kreisen mit einem Radius von weniger als ~30000 Schritten schafft der µC ~65k Punkte + Fifo-Zuweisung in einer Sekunde, allerdings ohne Positionskontrolle.

Als nächstes kommt dann vermutlich zuerst einmal das Motor-Management oder der G-Code-Interpreter, das muss ich erst noch sehen.
Das wird dann vermutlich auch der Teil der für dich interessanter ist.

mfG
Markus
Markus
  Mit Zitat antworten Zitat
100nF

Registriert seit: 7. Nov 2004
639 Beiträge
 
#34

Re: Ablauf für Fräsmaschine programmieren

  Alt 1. Okt 2008, 18:10
okay, ich hab mal was zusammengekritzelt...
Delphi-Quellcode:
var
  Befehl_vorhanden,
  Maschine_Bereit: boolean;

  Schritte_X,
  Schritte_Y,
  Schritte_Z,
  Geschwindigkeitsfaktor_X,
  Geschwindigkeitsfaktor_Y,
  Geschwindigkeitsfaktor_Z,
  GF_Down_X,
  GF_Down_Y,
  GF_Down_Z: Integer;

procedure main; // die Hauptprozedur des Programmes
begin
  Alles_Initialisieren; // z.B. die Serielle Schnittstelle initialisieren, Pins auf Ausgang schalten usw.

  begin Endlosschleife // Läuft ewigs durch, hört nie auf =)
    RS232_Senden_Empfangen; // Siehe weiter unten

    if Befehl_Vorhanden and Maschine_Bereit then // Wenn ein Befehl vorhanden ist und kein Fräsvorgang in arbeit ist...
      Befehl_auswerten; // ...wird der Befehl ausgewertet (siehe weiter unten)
  end;
end;


procedure RS232_Senden_Empfangen;
begin
  Buffer_mit_Empfangsdaten_füllen; // Was in der Zwischenzeit empfangen wurde, wird in den Buffer geladen

  If Buffer_voll then // wenn der Buffer voll ist...
    Sende_Wartebefehl_an_PC; //... wird dem PC mitgeteilt dass er warten muss mit der Übermittlung
  
  If Buffer_leer then // Wenn der Buffer leer ist...
  begin
    Befehl_vorhanden := false; // Wird die Variable auf false gesetzt...
    Sende_Bereit_an_PC; // ...und dem PC mitgeiteilt dass er wieder Daten senden soll
  end
  else
    Befehl_vorhanden := true; // Wenn der Buffer nicht leer ist, wird die Variable auf true gesetzt
end;

procedure Befehl_auswerten; // Wertet den Empfangenen Befehl aus
begin
  Buffer_auslesen; // Der Empfangsfuffer der RS232 wird ausgelesen
  Buffer_splitten(Startbyte, Message_Size, Command_Byte, Payload, Command_Byte, Checksumme, Stopbyte); // Das Telegramm wird in die einzelnen bestandteile zerlegt
  
  // Startbyte usw überprüfen...

  Case Command_Byte of // Wenn der Befehl...
    Kalibrieren: Prozedur_Kalibrieren(Payload); // ...eine Kalibrierung ankündigt, wird diese ausgeführt
    G-Code: Run_G-Code(Payload); //...ein G-Code ankündigt, wird dieser weiterverarbeitet
  End;
end;

procedure Run_G-Code(Payload: G-Code); // Der Empfangene G-Code wird verarbeitet
begin
  Befehl_auslesen; // Liest aus dem Payload heraus, ob M0, M1, G00, G01 usw.
  
  Case Payload.Befehl of // Enthält "M0", "G00" usw.
    M0: ... ;
    M1: ... ;
    ...
    G00: Fahre_Zu_Position(Payload.X, Payload.Y, Payload.Z, schnell); // Die Fräse muss schnell an die angekündigte Position fahren
    G01: Fahre_Zu_Position(Payload.X, Payload.Y, Payload.Z, schnell); // Die Fräse muss an die angekündigte Position fahren
    ...
  end;
end;


procedure Fahre_Zu_Position(X, Y, Z, Geschwindigkeit); // Die Position X, Y, Z wird mit der entsprechenden Geschwindigkeit angefahren
begin
  Maschine_Bereit := false; // Damit Keine zweite Befehlsauswertung stattfinden kann

  Schritte_X := X - Istposition_X; // Die Differenz zwischen Soll- und Istposition ermitteln
  Schritte_Y := Y - Istposition_Y;
  Schritte_Z := Z - Istposition_Z;

  Geschwindigkeitsfaktor_X_berechnen; // Die Wartezeit zwischen den einzelnen Pins ein-/ausschalten berechnen
  Geschwindigkeitsfaktor_Y_berechnen;
  Geschwindigkeitsfaktor_Z_berechnen;

  GF_Down_X := Geschwindigkeitsfaktor_X; // Variable setzten
  GF_Down_Y := Geschwindigkeitsfaktor_Y;
  GF_Down_Z := Geschwindigkeitsfaktor_Z;

  timer_X_Intervall := Geschwindigkeit; // Den Intervall für die Geschwindigkeit
  timer_Y_Intervall := Geschwindigkeit;
  timer_Z_Intervall := Geschwindigkeit;

  timer_X_aktivieren; // Die Timer werden aktiviert
  timer_Y_aktivieren;
  timer_Z_aktivieren;
end;

procedure Timer_x; // 3 Mal das "selbe" für X, Y, Z)
begin
  GF_Down_X := GF_Down_X - 1; // Die Wartezeit wird immer eines weniger
  
  if GF_Down_X = 0 then // Wenn die Wartezeit gleich Null ist...
  begin
    If Pin_Ein then // ...Wird der Takt-Pin getoggelt
      Pin_aus
    else
      Pin_ein;
    
    GF_Down_X := Geschwindigkeitsfaktor_X; // ...wird die Wartezeit wieder heraufgesetzt

    Schritte_X := Schritte_X - 1; // ...wird die Anzahl zu erledigender Schritte verringert

    If Schritte_X = 0 then // Wenn alle Schritte ausgeführt wurden...
    begin
      Timer_X_deaktivieren; // ...wird der Timer_X deaktiviert
      If (Schritte_Y = 0) and (Schritte_Z = 0) then //...und wenn alle Schritte (X, Y, Z) ausgeführt wurden...
        Maschine_Bereit := true; //...wird die Bereitschaft auf true gestellt damit der nächste Befehl verarbeitet werden kann
    end;
  end;
end;
hast du dir das in ungefähr so vorgestellt?
Soll natürlich nur den Ablauf darstellen, ich programmier den µC natürlich nicht in Delphi^^

mfg
Urban
  Mit Zitat antworten Zitat
markusj

Registriert seit: 9. Dez 2005
Ort: Kandel
408 Beiträge
 
#35

Re: Ablauf für Fräsmaschine programmieren

  Alt 1. Okt 2008, 19:43
Zitat von urbanbruhin:
okay, ich hab mal was zusammengekritzelt...
... hast du dir das in ungefähr so vorgestellt?
Soll natürlich nur den Ablauf darstellen, ich programmier den µC natürlich nicht in Delphi^^
Jein:

Für das Senden/Empfangen von Kommandos gibt es zwei FiFos und zwei Prozeduren.
Die für das Senden erstellt das Kommandotelegramm an den PC und speichert es in den Fifo. Das Übertragen übernimmt (oh Überraschung) ein Interrupt, der beim Füllen des TX-Puffers aktiviert wird und bei leerem Puffer deaktiviert wird (Für alle Kenner: Es handelt sich um den UDRE-Interrupt (USART Data Register Empty)).
Beim Empfangen ist es ähnlich, der Receive-Interrupt schaufelt die Daten in den Fifo und setzt intern verschiedene Warn-Flags für einen fast vollen oder vollen RX-Fifo.
Die fürs Empfangen zuständige Prozedur tritt erst hier auf den Plan und wird in der Main-Schleife angepollt. Sie prüft Schritt für Schritt die ankommenden Bytes durch.
Der Trick ist, dass nicht wie bei dir ein Kommando auf einmal ausgelesen wird, sondern es gibt eine Statusvariable für die verschiedenen Zustände. Die Zerlegung findet dann Schrittweise in einer State-Machine statt (Case-Selektor anhand der Statusvariable), wenn ein Schritt durch ist, schaltet er den nächsten aktiv.
Die Dekodierung erfolgt deshalb schrittweise, weil in der Zwischenzeit sonst keine weiteren Punkte berechnet werden können. Dazu aber nun.

Das war der Kommunikationsteil, nun die Auswertung und Ansteuerung.
Für ankommende G-Codes gibt es bei der Kommando-Dekodierung im entsprechenden Schritt eine Subroutine, die den (vereinfachten) G-Code aus der Payload dann in die intern verwendete Struktur überführt und in einen G-Code-Fifo packt.

Nach der Kommando-Dekodierung wird die G-Code-Dekodierung aufgerufen, die entweder einen G-Code dekodiert und in den Ansteuerungs-Fifo abspeichert, oder aber komplexe G-Codes (Kreis!) oder Steuerungs-G-Codes (u.a. die M-Befehle) direkt verarbeitet.

Die Motorsteuerung selbst findet im bereits erklärten Timer-Interrupt statt und kann bereits von Natur aus Linien zeichnen, da zu jeder Achse die Parameter der zurückzulegenden Schritte sowie die Geschwindigkeit festgelegt werden. Das Verhältnis der Geschwindigkeiten zueinander bestimmt die Richtung der Linie, die Schrittzahl die Länge.
Die Berechnung der Schritte findet ZUSAMMEN in einem Timer-Interrupt statt, dort werden dann die Pins gewackelt.
Ist ein solcher Task abgearbeitet, wird der nächste Datensatz aus dem Ansteuerungs-Fifo geholt.

Kreise werden "einfach" als Linien mit höchstens einem Schritt je Achse abgelegt, was zwar häufige FiFo-Operatinen zufolge hat, es aber ermöglicht, ein durchgängiges Konzept zu verwenden.
Gleichzeitig erfordert es aber auch, dass die Kreisberechnungen, die nun in der Main-Schleife stattfinden, häufig genug den FiFo auffüllen können. Deshalb muss die Kommando-Dekodierung aufgeteilt werden, um den FiFo auf gar keine Fall leerlaufen zu lassen.

Die Berechnung erfolgt also möglichst unabhängig von den Interrupts, die ISRs können relativ kurz bleiben, eine zeitnahe Reaktion ist so gewährleistet.

mfG
Markus
Markus
  Mit Zitat antworten Zitat
100nF

Registriert seit: 7. Nov 2004
639 Beiträge
 
#36

Re: Ablauf für Fräsmaschine programmieren

  Alt 1. Okt 2008, 20:35
okay, jetzt ist mir einiges klarer geworden

Zitat:
Nach der Kommando-Dekodierung wird die G-Code-Dekodierung aufgerufen, die entweder einen G-Code dekodiert und in den Ansteuerungs-Fifo abspeichert, oder aber komplexe G-Codes (Kreis!) oder Steuerungs-G-Codes (u.a. die M-Befehle) direkt verarbeitet.
kann es dann aber nicht sein, dass z.B. ein M-Befehl ausgeführt wird, bevor er ausgeführt werden soll? Also wenn Der Pc den Befehl schickt: "G01 X:100 Y:100" und sofort danach "M3". Dann wird der G-Befehl in den Ansteuerungs-FIFO geschaufelt, und sofort danach das M3 ausgeführt wird, auch wenn die Position 100.100 nicht erreicht ist?

Ausserdem kann ich mir unter dem FIFO in der Praxis noch nichts vorstellen...
Benutzt du dafür eine Variable, ein Array? Oder wie sieht das aus?

Und kann der Ansteuerungs-FIFO nicht überfüllt werden, wenn eine kreisberechnung ausgeführt wird?

Werde später dann mal meinen "Code" nochmal überarbeiten, ich finde sowas irgendwie noch nützlich. Erstens ist es eine gute Vorlage wenn ich mit dem programmieren beginne, und zweitens kann ich ohne grosse Worte mitteilen wie ich mir den Ablauf vorstelle

Ach ja, also bei der kommunikationsgeschichte komm ich noch nicht 100% nach, aber das liegt daran dass ich das Grundprinzip der seriellen Datenübertragung noch nicht ganz verstanden habe, also in welcher Form ich die Daten empfange usw. Werde mal schauen ob ich da was gutes zum lesen finde...

Gruss
Urban
  Mit Zitat antworten Zitat
markusj

Registriert seit: 9. Dez 2005
Ort: Kandel
408 Beiträge
 
#37

Re: Ablauf für Fräsmaschine programmieren

  Alt 1. Okt 2008, 21:59
Zitat von urbanbruhin:
okay, jetzt ist mir einiges klarer geworden
Zitat:
Nach der Kommando-Dekodierung wird die G-Code-Dekodierung aufgerufen, die entweder einen G-Code dekodiert und in den Ansteuerungs-Fifo abspeichert, oder aber komplexe G-Codes (Kreis!) oder Steuerungs-G-Codes (u.a. die M-Befehle) direkt verarbeitet.
kann es dann aber nicht sein, dass z.B. ein M-Befehl ausgeführt wird, bevor er ausgeführt werden soll? Also wenn Der Pc den Befehl schickt: "G01 X:100 Y:100" und sofort danach "M3". Dann wird der G-Befehl in den Ansteuerungs-FIFO geschaufelt, und sofort danach das M3 ausgeführt wird, auch wenn die Position 100.100 nicht erreicht ist?
Wenn man beim Programmieren nicht aufpasst - ja
Tatsächlich ist es so, dass es verschiedene Steuerkommandos gibt, die sich verschiedenartig auswirken. Ein Wartezeitbefehl hindert mich nicht daran, schon das nächste Kommando vorzuberechnen, auch ein M3 (Frässpindel Drehrichtung Uhrzeigersinn einschalten) vermutlich nicht, je nach dem wo diese Kommandos interpretiert und umgesetzt werden, und ob eine serielle Abarbeitung garantiert ist.
Unter Umständen muss der Interpreter seine Arbeit aber auch unterbrechen, z.Bsp. bei einem Werkzeugwechsel-Befehl (außer du hast das Geld, dir diese Mechanik einzubauen ). In diesem Falle steuern die Motoren ihre Zielposition an und gehen dann, mangels neuer Befehle, auf Standby.

Klar ist auf jeden Fall, dass eine serielle Abarbeitung der G-Codes GARANTIERT sein muss.

Zitat von urbanbruhin:
Ausserdem kann ich mir unter dem FIFO in der Praxis noch nichts vorstellen...
Benutzt du dafür eine Variable, ein Array? Oder wie sieht das aus?

Und kann der Ansteuerungs-FIFO nicht überfüllt werden, wenn eine kreisberechnung ausgeführt wird?
FiFo: Ein Array voller Daten, die in der Reihenfolge gelesen werden, in der sie geschrieben wurden. (First in, First out)
Die praktische Umsetzung erfolgt anhand eines Lese- und eines Schreibzeigers, kommt ein Datensatz, wird er geschrieben und der Schreibzeiger eins erhöht. Zudem wird der Counter der die Anzahl der Bytes im Puffer angibt ebenfalls hochgezählt.
Beim Auslesen wird das gelesen, worauf der Lesezeiger gerade zeigt, danach wird dieser eine Speicherstelle weitergeschoben und dann der Counter um eins runtergezählt.
Erreicht einer der Zeiger das Ende des Arrays, wird er auf das erste Element zurückgesetzt. So kann man das Array unendlich lange mit Daten befüllen und wieder auslesen, man sollte nur darauf achten, dass man seine eigenen Daten nicht überschreibt oder liest wo es nichts gibt (dafür der Counter).

Die Kreisberechnung wird natürlich nur aufgerufen, wenn der FiFo noch ausreichend Platz hat. Die Kreisberechnung liefert bei einem Aufruf immer den nächsten Punkt zurück, daraufhin muss dann noch geprüft werden, ob mit diesem Schritt das Ziel dann erreicht ist oder eben nicht.
Meine FiFo-Implementation verhindert ferner ein Überlaufen, ist dieser voll wird ein false (0 bei C) zurückgegeben

Zitat von urbanbruhin:
Ach ja, also bei der kommunikationsgeschichte komm ich noch nicht 100% nach, aber das liegt daran dass ich das Grundprinzip der seriellen Datenübertragung noch nicht ganz verstanden habe, also in welcher Form ich die Daten empfange usw. Werde mal schauen ob ich da was gutes zum lesen finde...
RS232 überträgt die Daten byteweise, daher ist mein "Protokoll" oder besser gesagt, Containerformat, entsprechend ausgelegt.
Ein ATMega (also auch dein M128) hat einen zweistufigen Eingangspuffer. Der vor dir verborgene Teil enthält die Bits, die gerade empfangen werden.
Sobald ein Byte "voll" ist, landet es im UDRn, dem USART Data Register n (wobei n beim Mega128 null oder eins sein kann, der M128 hat nämlich zwei USARTs). An dieser Stelle kann ein Interrupt aufgerufen werden, der die Daten in eine Variable deiner Wahl transportiert, oder du pollst deinen UART auf neue Daten und blockierst dabei die Ausführung anderer Dinge.
Markus
  Mit Zitat antworten Zitat
100nF

Registriert seit: 7. Nov 2004
639 Beiträge
 
#38

Re: Ablauf für Fräsmaschine programmieren

  Alt 3. Okt 2008, 23:35
also ich hab jetzt nochmal kurz an meinem "code" gearbeitet. fehlt natürlich noch sehr vieles, hab einfach mal angefangen den code abzuändern.
Delphi-Quellcode:
var
  Befehl_vorhanden,
  Maschine_Bereit: boolean;

  Schritte_X,
  Schritte_Y,
  Schritte_Z,
  Geschwindigkeitsfaktor,
  GF_Down_X,
  GF_Down_Y,
  GF_Down_Z: Integer;

  Sende_FiFo,
  Empfangs_FiFo,
  G-Code_FiFo: Array;

procedure main; // die Hauptprozedur des Programmes
begin
  Alles_Initialisieren; // z.B. die Serielle Schnittstelle initialisieren, Pins auf Ausgang schalten usw.

  begin Endlosschleife // Läuft ewigs durch, hört nie auf =)
    If Empfangs_FiFo_leer then // Wenn der Buffer leer ist...
    begin
      Befehl_vorhanden := false; // Wird die Variable auf false gesetzt...
      RS232_Senden(Warte_auf_Befehl); // ...und dem PC mitgeiteilt dass er wieder Daten senden soll
    end
    else
      Befehl_vorhanden := true; // Wenn der Buffer nicht leer ist, wird die Variable auf true gesetzt

    If Empfangs_FiFo_voll then // wenn der Buffer voll ist...
      RS232_Senden(PC_muss_warten); //... wird dem PC mitgeteilt dass er warten muss mit der Übermittlung

    Befehl_auswerten; // ...wird der Befehl ausgewertet (siehe weiter unten)

    if Befehl_Vorhanden and Maschine_Bereit then // Wenn ein Befehl vorhanden ist und kein Fräsvorgang in arbeit ist...
      Run_G-Code;
  end;
end;


procedure RS232_Senden(Sendedaten);
begin
  Sende_FiFo_mit_Sendedaten_füllen; // Was in der Zwischenzeit empfangen wurde, wird in den Buffer geladen

  // Der Sende_FiFo wird wieder geleert sobald die Übertragung per Interrupt stattgefunden hat
end;

procedure RS232_Empfangen; // Wird per Interrupt ausgelöst (Sobald etwas empfangen wird)
begin
  Empfangs_FiFo_mit_Empfangsdaten_füllen; // Was in der Zwischenzeit empfangen wurde, wird in den Empfangs_FiFo geladen
end;

procedure Befehl_auswerten; // Wertet den Empfangenen Befehl aus
begin
  Empfangs_FiFo_auslesen; // Der Empfangsfuffer der RS232 wird ausgelesen
  Empfangs_FiFo_splitten(Startbyte, Message_Size, Command_Byte, Payload, Command_Byte, Checksumme, Stopbyte); // Das Telegramm wird in die einzelnen bestandteile zerlegt
  
  // Startbyte usw überprüfen...

  Case Command_Byte of // Wenn der Befehl...
    Kalibrieren: Prozedur_Kalibrieren(Payload); // ...eine Kalibrierung ankündigt, wird diese ausgeführt
    G-Code: G-Code_FiFo_hinzufügen(Payload); //...ein G-Code ankündigt, wird dieser in den G-Code_FiFo geschrieben
  End;
end;

procedure Run_G-Code(G-Code); // Der Empfangene G-Code wird verarbeitet
begin
  Befehl_auslesen; // Liest aus dem Payload heraus, ob M0, M1, G00, G01 usw.
  
  Case G-Code.Befehl of // Enthält "M0", "G00" usw.
    M0: ... ;
    M1: ... ;
    ...
    G00: Fahre_Zu_Position(Payload.X, Payload.Y, Payload.Z, schnell); // Die Fräse muss schnell an die angekündigte Position fahren
    G01: Fahre_Zu_Position(Payload.X, Payload.Y, Payload.Z, schnell); // Die Fräse muss an die angekündigte Position fahren
    ...
  end;

  G-Code_FiFo_Anweisung entfernen; // Der ausgeführte Befehl wird aus der FiFo entfernt - oder muss man das nicht machen?
end;


procedure Fahre_Zu_Position(X, Y, Z, Geschwindigkeit); // Die Position X, Y, Z wird mit der entsprechenden Geschwindigkeit angefahren
begin
  Maschine_Bereit := false; // Damit Keine zweite Befehlsauswertung stattfinden kann

  Schritte_X := X - Istposition_X; // Die Differenz zwischen Soll- und Istposition ermitteln
  Schritte_Y := Y - Istposition_Y;
  Schritte_Z := Z - Istposition_Z;

  Geschwindigkeitsfaktor_berechnen; // Die Wartezeit zwischen den einzelnen Pins ein-/ausschalten berechnen

  GF_Down_X := Geschwindigkeitsfaktor; // Variable setzten
  GF_Down_Y := Geschwindigkeitsfaktor;
  GF_Down_Z := Geschwindigkeitsfaktor;

  timer_Intervall := Geschwindigkeit; // Den Intervall für die Geschwindigkeit

  timer_aktivieren; // Der Timer wird aktiviert
end;

procedure Timer;
begin
  GF_Down_X := GF_Down_X - 1; // Die Wartezeit wird immer eines weniger
  GF_Down_Y := GF_Down_Y - 1;
  GF_Down_Z := GF_Down_Z - 1;
  
  if GF_Down_X = 0 then // Wenn die Wartezeit gleich Null ist...
  begin
    If Pin_X_Ein then // ...Wird der Takt-Pin getoggelt
      Pin_X_aus
    else
      Pin_X_ein;
    
    GF_Down_X := Geschwindigkeitsfaktor; // ...wird die Wartezeit wieder heraufgesetzt

    Schritte_X := Schritte_X - 1; // ...wird die Anzahl zu erledigender Schritte verringert
  end;

  if GF_Down_Y = 0 then // Wenn die Wartezeit gleich Null ist...
  begin
    If Pin_Y_Ein then // ...Wird der Takt-Pin getoggelt
      Pin_Y_aus
    else
      Pin_Y_ein;
    
    GF_Down_Y := Geschwindigkeitsfaktor; // ...wird die Wartezeit wieder heraufgesetzt

    Schritte_Y := Schritte_Y - 1; // ...wird die Anzahl zu erledigender Schritte verringert
  end;

  if GF_Down_Z = 0 then // Wenn die Wartezeit gleich Null ist...
  begin
    If Pin_Z_Ein then // ...Wird der Takt-Pin getoggelt
      Pin_Z_aus
    else
      Pin_Z_ein;
    
    GF_Down_Z := Geschwindigkeitsfaktor; // ...wird die Wartezeit wieder heraufgesetzt

    Schritte_Z := Schritte_Z - 1; // ...wird die Anzahl zu erledigender Schritte verringert
  end;
     
  If (Schritte_X = 0) and (Schritte_Y = 0) and (Schritte_Z = 0) then //wenn alle Schritte (X, Y, Z) ausgeführt wurden...
  begin
    Maschine_Bereit := true; //...wird die Bereitschaft auf true gestellt damit der nächste Befehl verarbeitet werden kann
    Timer_deaktivieren; // ...wird der Timer deaktiviert
  end:
end;
naja, ist bestimmt nocht nicht so wie du dir das vorstellst, aber ich geh jetzt erstmal schlafen^^

mfg
Urban

EDIT: hab den code noch kurz bisschen abgeändert
  Mit Zitat antworten Zitat
markusj

Registriert seit: 9. Dez 2005
Ort: Kandel
408 Beiträge
 
#39

Re: Ablauf für Fräsmaschine programmieren

  Alt 4. Okt 2008, 00:32
Ich schmier mal schnell einen Pseudo-Pseudo-Code hin, damit du dich nicht so quälen musst. Du bist nämlich noch ein gutes Stück von mir entfernt.
Es stellt sich aber dennoch die Frage, ob es Sinn macht, meine Gedankengebäude nachzuprogrammieren wenn ich das Konzept noch nicht einmal vollständig durchdacht habe.

Noch ein Hinweis zu deiner Maschine_Bereit Sache: Sinn und Zweck der Fifos ist es doch gerade, DAS unnötig zu machen. Die Maschine soll nahtlos ihren Job abarbeiten, ohne beim PC immer nerven zu müssen. Die CNC baut sich einen FiFo auf und arbeitet DEN schrittweise ab.
Der PC selbst soll möglichst wenig mit allem zu tun haben, was Verzögerungen bewirkt, optimal ist es, wenn die Motion-Control schon nach dem letzten Schritt "weiß" wo sie als nächstes hinfährt, dieses Element aus dem Motion-Fifo holt und beim nächsten Timer-Interrupt einfach weiterarbeiten kann.

Delphi-Quellcode:
var rx_fifo, tx_fifo, gcode_fifo, motion_fifo : TFifo;
var rx_errors, decode_state : byte;

procedure main; //alles hat einen anfang
  begin
  while (true) do
    begin
    command_decode; //kommandodekodierung
    gcode_preprocessor; //g-code-interpretierung;
    end;
  end;
  
 procedure rs232_receive;
  begin
  if not rx_fifo.add(rx_register) then
    rx_errors := rx_errors or FEHLERCODE_FÜR_VOLLEN_FIFO;
    else
    begin
    if rx_fifo.size-5 < rx_fifo.count then
      rx_errors := rx_errors or WARNCODE_FÜR_FAST_VOLLEN_FIFO;
    end;
  end;
  
procedure rs232_transmit;
  var out_buf : byte;
  begin
  if tx_fifo.get(@out_buf) then
    tx_register = out_buf
    else disable_rs232_transmit_interrupt;
  end;
  
procedure command_decode;
  begin
  case decode_state of
    wait_for_startflag : //eingangsfifo nach startflag durchsuchen und bei gefundenem startflag die nächste stufe scharfschalten
    read_message_size : //sobald ein byte gekommen ist, als message_size interpretieren + nächsten schritt aktivieren
    receiving_telegram : //warten (nachsehen, danach funktion verlassen wenn nicht alles da) bis alle angekündigten bytes da sind, danach nächster schritt
    check_stopflag : //prüfen ob das telegramm tatsächlich da ein ende hat wo es eines haben sollte, wenn ja: weiter
    check_cmd_code : //doppelten commandocode prüfen, weiter wenn ok,
    check_sum : //checksumme prüfen, weiter wenn ok
    launch_parser : //payload an den parser übergeben, z.bsp für gcode
    rst_wait_stopflag : //wenn ein fehler aufgetreten ist, überspringen wir hier solange eingehende bytes, bis ein stopflag dabei ist, danach schritt eins scharfschalten
  if rx_errors <> 0 then //irgendwann beim dekodieren oder empfangen ist ein fehler aufgetreten, das teilen wir dem master mit
    begin
    if transmit_command(receive_error,@rx_errors,sizeof(rx_errors)) then
      rx_errors := 0; //transfer erfolgreich, wir können den fehler löschen.
    end;
  end;
  
procedure gcode_preprocessor;
  begin
  //mach was sinnvolles mit dem gcode, abhängig vom aktuellen zustand berechnungen anstelle, neue codes aus dem gcode_fifo entnehmen und interpretieren und dann in den motion_fifo einfügen oder oder
  end;
  
procedure timer1_interrupt;
  begin
  //zu toggelnde pins ermitteln
  //toggeln
  //distanzen updaten etc.
  //zurücktoggeln
  //wenn job done, neuen nachladen oder in idle-mode gehen
  end;
mfG
Markus
Markus
  Mit Zitat antworten Zitat
100nF

Registriert seit: 7. Nov 2004
639 Beiträge
 
#40

Re: Ablauf für Fräsmaschine programmieren

  Alt 4. Okt 2008, 09:45
Zitat:
Es stellt sich aber dennoch die Frage, ob es Sinn macht, meine Gedankengebäude nachzuprogrammieren wenn ich das Konzept noch nicht einmal vollständig durchdacht habe.
ich denke das ist nicht so schlecht, denn so sehe ich mal andere (bessere) möglichen Varianten, wie man das lösen könnte.
Ich will ja auch nicht einfach nur deinen Code 1:1 abschreiben, doch beim Grundgerüst komme ich ohne Hilfe wohl nirgens hin, und wenn ich das habe kann ich vermutlich den Rest relativ selbständig machen.
Und wenn dein Konzept aus irgendeinem Grund nicht funktionieren würde, dann wäre das auch halb so wild weil ich auch so schon einiges lernen konnte!

Und danke für deinen "Code"!

Vielleicht werde ich dieses Wochenende mal mit dem Programmieren beginnen...

Ach ja, hast du deine Schrittmotorplatinen (L297/L298) selbst gemacht? Ich hab nämlich mal 3 Platinen mit der "Direct-Toner"-Methode gemacht, doch nur eine davon war nach langem nachbessern funktionstüchtig
Danach hatte ich die Schnauze voll von dem riesen Aufwand, und hab mal nach Platinen-Ätz-Service gesucht. Da hab ich aber gemerkt dass das vom Preis her überhaupt nicht in Frage kommt. Also wenn du deine Platinen selbst gemacht hast, würdest du auch für ein bisschen Geld nochmal 3 von diesen machen?

mfg
Urban

EDIT: Ich habe ja mal was von Threads geschrieben. Nun hab ich in der Hilfedatei des C-Controls mal bisschen gelesen, und ich würde meinen dass das eigentlich eine gute Sache ist für diese Anwendung. z.B. Das Senden/Empfangen der RS232 kann man doch sehr gut in einem Thread plazieren denke ich mal. Und vielleicht auch deine "command_decode"-Prozedur. Naja, wenn ich schon die Möglichkeit habe, Threads zu benutzen, sollte ich es mir wohl auch zu nutzen machen
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 4 von 7   « Erste     234 56     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:33 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz