mit einem Button Fenster schließen und gleichzeitig ein script starten

Fragen zu Tkinter.
Antworten
Benutzeravatar
carbonkid
User
Beiträge: 12
Registriert: Mittwoch 8. März 2023, 18:48

Hallo, habe ein Script für meine Steuerung der CNC Fräse. Das script nennt sich M6 und regelt während eines Fräsprogramms den Werkzeugwechsel. Wenn im G-Code M6 zwischen den Fräsoperationen kommt wird das script aufgerufen.
Im script wird dann an einen vorbestimmten Punkt gefahren(move_to_change_tool_ps ) und ein "tkinter Fenster" geht auf. Hier kann man wählen wie es weiter geht. Hat man den neuen Fräser eingespannt klickt man auf "Werkzeug vermessen". Wenn die Messung beendet ist muß man dann auf "Fortsetzen" klicken, das Fenster schließt sich und das eigentliche Fräsprogramm läuft weiter.
Wie könnte man es jetzt machen das wenn man auf "Werkzeug vermessen" klickt das Werkzeug zum Meßpunkt fährt und sich gleichzeitig auch das Fenster schließt und nach der Vermessung das Fräsprogramm automatisch weiter läuft?
Also so das man den "Fortsetzen" Button weglassen kann.

Code: Alles auswählen

import time
import sys
import tkinter as tk

# parameters from the gui
toolChangePosX=float(d.getMachineParam(304))
toolChangePosY=float(d.getMachineParam(305))
toolLengthSensorPosX=float(d.getMachineParam(307))
toolLengthSensorPosY=float(d.getMachineParam(308))
probeIndexToolLength=int(d.getMachineParam(321))
ZtoolLengthMeasureFastProbeSpeed=float(d.getMachineParam(317))
ZtoolLengthMeasureSlowProbeSpeed=float(d.getMachineParam(318))

# where you want the spindel for the change of your tools
X_pos_chang_tool = toolChangePosX
Y_pos_chang_tool = toolChangePosY
Z_pos_chang_tool = 0

# speed of move to reach the above position
vel = 4000

# moving commande, call by Move_to_change_tool_pos() in the macro
def Move_to_change_tool_pos():
    # move Z 
    pos[Z] = Z_pos_chang_tool
    d.moveToPosition(CoordMode.Machine, pos, vel)

    # move to change tool place
    pos[Y] = Y_pos_chang_tool
    pos[X] = X_pos_chang_tool
    d.moveToPosition(CoordMode.Machine, pos, vel)

# name axis when d.getposition respond
X = 0
Y = 1
Z = 2


# Get the tool number from the gcode and name it "new tool".
new_tool = d.getSelectedToolNumber()

# Get the known size in simcnc of the new tool name it "new_tool_length"
new_tool_length = d.getToolLength(new_tool)

# Get the machine's position and name it "position".
pos = d.getPosition(CoordMode.Machine)

# Set in simcnc the tool infos
d.setToolLength (new_tool,new_tool_length)
d.setToolOffsetNumber(new_tool)
d.setSpindleToolNumber(new_tool)

# Create a message box with 3 buttons and execute probing.py or d.enableMachine(False)


def measurement():
    ###
    #Settings
    ###
    # probe index
    probeIndex = probeIndexToolLength
    # probing start position [X, Y, Z]
    probeStartAbsPos = [toolLengthSensorPosX, toolLengthSensorPosY, 0]
    # Axis Z probing end position (absolute)
    zEndPosition = -122
    # the absolute position of the Z axis of the probe contact for the reference tool
    refToolProbePos = -120.220
    # approach velocity (units/min)
    #vel = 15000
    # probing velocity (units/min)
    fastProbeVel = ZtoolLengthMeasureFastProbeSpeed
    slowProbeVel = ZtoolLengthMeasureSlowProbeSpeed
    # lift up dist before fine probing
    goUpDist = 5
    # delay (seconds) before fine probing
    fineProbingDelay = 0.2
    # other options
    moveX = True
    moveY = True
    checkFineProbingDiff = False
    fineProbeMaxAllowedDiff = 0.1

    ###
    #Measurement
    ###
    d.setSpindleState(SpindleState.OFF)
    toolNr = d.getSpindleToolNumber()
    if(toolNr == 0):
      sys.exit("Tool(0) has no tool lenght offset. Probing failed!")

    # get current absolute position
    pos = d.getPosition(CoordMode.Machine)

    # lift up Z to absolute 0
    pos[Axis.Z.value] = 0;
    d.moveToPosition(CoordMode.Machine, pos, vel)

    # go to XY start probe position
    if(moveX == True):
      pos[Axis.X.value] = probeStartAbsPos[Axis.X.value]
    if(moveY == True):
      pos[Axis.Y.value] = probeStartAbsPos[Axis.Y.value]
    d.moveToPosition(CoordMode.Machine, pos, vel)

    # go to Z start probe position
    pos[Axis.Z.value] = probeStartAbsPos[Axis.Z.value]
    d.moveToPosition(CoordMode.Machine, pos, vel)

    # start fast probing
    pos[Axis.Z.value] = zEndPosition;
    probeResult = d.executeProbing(CoordMode.Machine, pos, probeIndex, fastProbeVel)
    if(probeResult == False):
      sys.exit("fast probing failed!")
  
    # get fast probe contact position
    fastProbeFinishPos = d.getProbingPosition(CoordMode.Machine)

    # lift-up Z
    d.moveAxisIncremental(Axis.Z, goUpDist, vel)
    # delay
    time.sleep(fineProbingDelay)
    # start fine probing
    probeResult = d.executeProbing(CoordMode.Machine, pos, probeIndex, slowProbeVel)
    if(probeResult == False):
      sys.exit("slow probing failed!")
  
    # get fine probe contact position
    probeFinishPos = d.getProbingPosition(CoordMode.Machine)

    # check diff between fast and fine probing
    probeDiff = abs(fastProbeFinishPos[Axis.Z.value] - probeFinishPos[Axis.Z.value])
    if(probeDiff > fineProbeMaxAllowedDiff and checkFineProbingDiff == True):
      errMsg = "ERROR: fine probing difference limit exceeded! (diff: {:.3f})".format(probeDiff)
      sys.exit( errMsg)

    # calculate and set tool length
    toolOffset = probeFinishPos[Axis.Z.value] - refToolProbePos
    d.setToolLength(toolNr, toolOffset)

    # lift Z to abs 0
    pos[Axis.Z.value] = 0
    d.moveToPosition(CoordMode.Machine, pos, vel)

    # finish
    print("Werkzeug Nr.:{:d} Werkzeuglänge: {:.4f}".format(toolNr, toolOffset))
    
    
    
def stop():
    d.enableMachine(False)

def toggle_blink():
    if message_label.cget("foreground") == "black":
        message_label.config(fg="red")
    else:
        message_label.config(fg="black")
    root.after(500, toggle_blink)  # Toggle every 500 milliseconds

def show_custom_message_box():
    global root, message_label

    root = tk.Tk()
    root.title("M6 Werkzeugwechsel")
    root.geometry("700x300+{}+{}".format(int(root.winfo_screenwidth()/2 - 350), int(root.winfo_screenheight()/2 - 150)))
    root.minsize(width=680, height=280)
    root.maxsize(width=750, height=350)
    
    custom_font = ('Helvetica', 12)  # Define a custom font 

    message_label = tk.Label(root, text="!!!G-Code M6 Werkzeugwechsel!!! \n\nBitte Fräser Nummer #"  + str(new_tool) + " einsetzten. \n\nDanach wählen Sie aus wie sie fortfahren möchten.", font=custom_font)
    message_label.pack(padx=50, pady=50)

    toggle_blink()  # Start blinking

    # Make the window always on top
    root.wm_attributes("-topmost", 1)

    
    def on_closing():
        d.enableMachine(False)  # Disable the machine if the X button is clicked
        root.destroy()  # close messagebox

    button_frame = tk.Frame(root)
    button_frame.pack()

    continuer_button = tk.Button(button_frame, text="\u25B6 Fortsetzen ", command=root.destroy, font=custom_font)
    continuer_button.pack(side=tk.LEFT, padx=30, pady=30)

    measurement_button = tk.Button(button_frame, text="Werkzeug vermessen", command=measurement, font=custom_font)
    measurement_button.pack(side=tk.LEFT, padx=30, pady=30)

    stop_button = tk.Button(button_frame, text="\u25A0 STOP", command=stop, fg="white", bg="red", font=custom_font)
    stop_button.pack(side=tk.RIGHT, padx=30, pady=30)

    # Captures the window close event
    root.protocol("WM_DELETE_WINDOW", on_closing)

    root.mainloop()

########################################################
# macro start
########################################################
#print ("Manual change tool Start")

#Turn off the spindle
d.setSpindleState(SpindleState.OFF) 

# if new tool length = zero, execute Move_to_change_tool_pos
if new_tool_length == 0:  
    Move_to_change_tool_pos()

#call the message box display function
show_custom_message_box()

#print ("Manual change tool finish")
Gruß Daniel
Sirius3
User
Beiträge: 17688
Registriert: Sonntag 21. Oktober 2012, 17:20

Da das ganze Programm eh nur aus Spaghetticode mit vielen globalen Variablen besteht und die GUI einfriert, sobald Du auf "Werkzeug vermessen" klickst, kannst Du Dir den ganzen GUI-Quatsch auch schenken und einfach nur eine Messagebox aufmachen, dann hast Du auch kein Problem.
Benutzeravatar
carbonkid
User
Beiträge: 12
Registriert: Mittwoch 8. März 2023, 18:48

Sirius3 hat geschrieben: Mittwoch 31. Januar 2024, 20:24 Da das ganze Programm eh nur aus Spaghetticode mit vielen globalen Variablen besteht und die GUI einfriert, sobald Du auf "Werkzeug vermessen" klickst, kannst Du Dir den ganzen GUI-Quatsch auch schenken und einfach nur eine Messagebox aufmachen, dann hast Du auch kein Problem.
Wärst du so nett mir nochmal in deutsch zu erklären was du genau meinst bzw. was ist bei dir der Gui Quatsch? Steh grad auf dem Schlauch...
Gruß Daniel
Benutzeravatar
Dennis89
User
Beiträge: 1108
Registriert: Freitag 11. Dezember 2020, 15:13

Hallo,

GUI = Graphical User Interface

Das Programm läuft so aber gar nicht, zumindest kann ich die Stelle nicht finden wo `d` definiert wird.

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
carbonkid
User
Beiträge: 12
Registriert: Mittwoch 8. März 2023, 18:48

Nein das ist auch nicht das ganze Programm, sondern nur das "Erweiterungsscript" für den Werkzeugwechsel. Mir ging es ja auch nur um das tkinter Fenster was sich öffnet und dann eben wieder schließt wenn man auf Fortsetzen klickt.
Ich dachte halt man kann das sparen und den Button "Werkzeug messen" kombinieren. Naja die eigentliche Funktion ist ja gegeben, dann bleibt es wie es ist.
Gruß Daniel
Benutzeravatar
Dennis89
User
Beiträge: 1108
Registriert: Freitag 11. Dezember 2020, 15:13

Die Lösung wurde dir schon vorgeschlagen, benutze eine Messagebox.

Zum Beispiel:

Code: Alles auswählen

from tkinter import messagebox

def main():
    messagebox.showinfo('Werkzeugwechsel', 'Vorsicht, ich fahre zum WWP!')

if __name__ == '__main__':
    main()
Für mehr:
https://docs.python.org/3/library/tkint ... gebox.html

Grüße
Dennis
"When I got the music, I got a place to go" [Rancid, 1993]
Benutzeravatar
carbonkid
User
Beiträge: 12
Registriert: Mittwoch 8. März 2023, 18:48

Naja Lösung vorgeschlagen kann man so und so sehen ;-)
Nur nochmal zum Verständnis, das vorhandene Fenster was von "show_custom_message_box" definiert wird soll ersetzt werden oder
geht es darum wie diese messagebox programmiert ist?
Ich hab halt leider nicht viel Ahnung vom Programmieren, das ist jetzt nur Mittel zum Zweck...ich tuh mir damit auch nicht gerade leicht...
Gruß Daniel
__deets__
User
Beiträge: 14439
Registriert: Mittwoch 14. Oktober 2015, 14:29

Du kannst doch einfach am Ende des measurement root.destroy aufrufen.
Benutzeravatar
carbonkid
User
Beiträge: 12
Registriert: Mittwoch 8. März 2023, 18:48

__deets__ hat geschrieben: Donnerstag 1. Februar 2024, 17:48 Du kannst doch einfach am Ende des measurement root.destroy aufrufen.
Das war mein erster Versuch. Allerdings nur im Simulationsmodus der Steuerungssoftware zuhause am PC.
Da bekam ich gleich eine Fehlermeldung aber das kann daran liegen das ich das nicht in die "def_measurement" mit rein geschrieben habe sondern außerhalb direkt drunter.
Na werde das mal die Tage direkt an der Maschine testen.
Aber danke für den Hinweis, würde mich ja freuen wenn es so einfach zu lösen ist.
Gruß Daniel
__deets__
User
Beiträge: 14439
Registriert: Mittwoch 14. Oktober 2015, 14:29

Joa. Ohne Code und Fehlermeldung kann man dazu ja nicht so viel sagen.
Benutzeravatar
carbonkid
User
Beiträge: 12
Registriert: Mittwoch 8. März 2023, 18:48

__deets__ hat geschrieben: Donnerstag 1. Februar 2024, 21:52 Joa. Ohne Code und Fehlermeldung kann man dazu ja nicht so viel sagen.
Den Code des scripts hab ich ja gepostet, den ganzen Programmcode der Steuerungssoftware würde ja völlig den Rahmen sprengen. Das ist eine gekaufte Software die man über scripte erweiteren kann.
Oben genanntes wird durch den Befehl M6 im GCode aufgerufen. M6 steht einfach nur für Werkzeugwechsel.
Dieses script greift wiederum die Parameter ab die man in der Bedienoberfläche eingibt.

Die Fehlermeldung lautet: "name root is not defind"

War vorhin an der Maschine testen. Was soll ich sagen, es funktioniert einwandfrei wenn man root.destroy mit in die Funktion schreibt.
Danke und bis zum nächsten script ;-)
Gruß Daniel
__deets__
User
Beiträge: 14439
Registriert: Mittwoch 14. Oktober 2015, 14:29

Nein, den Code hattest du nicht gepostet. Du hast erzählt was du vermeintlich getan hast, und dann war da irgendwas mit einer Fehlermeldung. Dazu kann man nunmal nichts sagen. Das du da oben anderen Code gepostet hast, hat ja damit nix zu tun.

Von der restlichen Software hat auch keiner geredet.
Benutzeravatar
__blackjack__
User
Beiträge: 12940
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@carbonkid: Im oben gezeigten Code ist `root` definiert. Global und bevor es benutzt wird. Global sollte es nicht sein. Aber dann muss man halt auch ordentlich programmieren. Also zum Beispiel echte Funktionen schreiben und nicht nur ``def`` missbrauchen um Codeabschnitten einen Namen zu geben. Funktionen sollten eigentlich in sich geschlossen sein. Alles was sie ausser Konstanten benötigen wird als Argument(e) übergeben, und Ergebnisse als Rückgabewerte an den Aufrufer zurück gegeben. Statt das alles über globale Variablen zu machen, wo am Ende keiner mehr so leicht durchsteigt. Das ``global``-Schlüsselwort hat in einem sauberen Programm nichts zu suchen.

Variablen sollten auch nicht sinnlos umbenannt werden. Also nicht einen Wert an einen Namen binden, nur um den dann später an einen anderen Namen zu binden und den dann zu benutzen.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (PascalCase).

Namen sollten keine kryptischen Abkürzungen enthalten oder gar nur daraus bestehen. Der Name soll dem Leser vermitteln was der Wert dahinter im Programm bedeutet, nicht zum rätseln zwingen. Wenn man `velocity` meint, sollte man nicht nur `vel` schreiben.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten