Quellcode für bltouch

"""Modul zum Steuern und Auslesen des Nivellierungssensors.

Das Modul bltouch.py verwendet die **pigpio** Bibliothek zur Generierung eines 
PWM Signals, über welches sich die Sonde des Nivellierungssensors BLTouch 
steuern lässt. Außerdem wird die Bibliothek **RPi.GPIO** verwendet, mit welcher 
sich Pin-Interrupts erzeugen lassen.

"""

import RPi.GPIO as GPIO
import pigpio
import time
import numpy


[Doku]class Touchsensor():
[Doku] def __init__(self, grundeinstellungen): """Wird aufgerufen wenn ein Touchsensor-Objekt erzeugt wird. Grundeinstellungen wie Pin-Konfiguration, Timingeinstellungen oder PWM-Parameter werden ausgelesen und in lokale Variabeln gespeichert. Args: grundeinstellungen (dict): Aus dem Config-File eingelesene Grundeinstellungen des Roboters. """ # Profil Array deklarieren self.profil = [] # Z-Abstastung self.z_offset = 0 # Flag self.beruehrt = False # Pinkonfiguration self.pwm_pin = int(grundeinstellungen['gpio_bltouch_pwm']) self.interrupt_pin = int(grundeinstellungen['gpio_bltouch_endschalter']) # PWM Frequenz self.pwm_frequenz = int(grundeinstellungen['bl_pwm_frequenz']) # Stösselpsotionsmaxima self.obere_position = int(grundeinstellungen['bl_obere_position']) self.untere_position = int(grundeinstellungen['bl_untere_position']) # Pulsweite für Selbsttest self.selbsttest = int(grundeinstellungen['bl_selbsttest']) # Anzahl der Wiederholungen auf einem X Punkt self.wiederholungen = int(grundeinstellungen['bl_wiederholungen']) # Sicherheitsfaktor damit Sonde nicht ins Leere fährt self.sicherheitsfaktor = float( grundeinstellungen['bl_sicherheitsfaktor']) # Profilsamples self.samples_pro_punkt = int( grundeinstellungen['bl_samples_pro_punkt']) # Z-Abstand zu Optik welche nach dem Abtasten eines Punktes # angefahren wird self.z_abtasthub = float(grundeinstellungen['bl_z_abtasthub']) # Initialisierung self.pwm = pigpio.pi() self.pwm.set_mode(self.pwm_pin, pigpio.OUTPUT) self.pwm.set_PWM_frequency(self.pwm_pin, self.pwm_frequenz)
[Doku] def interrupt_routine(self, dummyvariable): """Die ISR (Interrupt Service Routine) wird aufgerufen sobald ein Interrupt am GPIO0 auftritt. Note: Ein Interrupt wird bei steigender Flanke (RISING) getriggert. Die Dummyvariable darf nicht gelöscht werden, sonst funktionieren die Interrupts nicht! Args: dummyvariable (-): Kein Verwendung, dient nur als Dummy """ print("Interrupt ausgelöst.") # Sonde hochziehen self.sonde_heben() # Flag auf berührt setzten self.beruehrt = True return
[Doku] def z_einzel_abtastung(self, grbl): """Taset die Oberfläche einer Optik einmalig ab. Diese Methode wird aufgerufen, wenn der Z-Offset (Abstand zwischen Optik und Nivellierungssensor) erfasst werden soll. Note: Mittels Abtastung des Z-Offset, lässt sich der Reinigungsablauf beschleunigen, da das CNC-Positionierungssystem den Kopf im Eilgang absenkt und sich erst kurz vor Berührung an die Oberfläche herantastet. Args: grbl (object): Objekt zur Kommunikation mit dem CNC-Controller. """ print("Z-Tastwert wird aufgenommen ...") # Z-Offset setzen (optional), normalerweise 0, kenn bei Bedarf geändert # in negative Richtung geändert werden. z_aktuell = 0 # Kurz warten time.sleep(1) # Stoessl senken self.sonde_senken() # Den Reinigungskopf senken, solange die Oberfläche nichtg berührt wird. while not self.beruehrt: z_aktuell -= 0.01 cmd = "G01 Z" + str(z_aktuell) + " F1500" grbl.gcode_senden(cmd) time.sleep(0.015) # Z-Position erfassen self.z_offset = float(grbl.z_position) time.sleep(1) # Flag zurücksetzten self.beruehrt = False
[Doku] def profil_aufzeichnen(self, grbl, samples, radius, fortschritt_signal): """Zeichnet ein Profil durch Abtastung von mindestens 3 Punkten der Optikoberfläche auf. Args: grbl (object): Objekt zur Kommunikation mit dem CNC-Controller. samples (int): Anzahl der abzutastenden Punkte. radius (float): Radius der Linse in mm (nicht der Oberflächenradius!). fortschritt_signal (signal): Signal vom Typ *(float)*. Dient zur Aktualisierung des Ladebalkens. Returns: list: Gibt eine Liste mit Koordinatenpaaren [X:Z] *(str)* zurück. """ # Mögliche alte Profildaten vor der Neuaufnahme löschen profil = [] # Fortschittsvariable initialisieren fortschritt = 0 print("Profil wird aufgezeichnet ...") # Auflösung berechnen aufloesung = (radius - self.sicherheitsfaktor) / (samples - 1) print("Abtastauflösung beträgt", aufloesung, "mm abgetastet.") print("Abtasthub beträgt", self.z_abtasthub, "mm.") print("Zeichne mit", self.samples_pro_punkt, "Samples pro Punkt auf ...") for i in range(samples): print("Koordinate", i + 1, "von", samples, "wird aufgenommen.") # Punktliste wieder leeren punkt = [] # Mehrere Wiederholungen pro Punkt und den Mittelwert nehmen for j in range(self.samples_pro_punkt): time.sleep(2) # Aktuelle Position abfragen x_aktuell = float(grbl.x_position) z_aktuell = float(grbl.z_position) # Sonde senken self.sonde_senken() # Warten time.sleep(2) while not self.beruehrt: z_aktuell -= 0.01 cmd = "G01 Z" + str(z_aktuell) + " F1500" grbl.gcode_senden(cmd) time.sleep(0.02) # X- und Z-position auslesen und speichern x_pos = grbl.x_position z_pos = grbl.z_position punkt.append(float(z_pos)) time.sleep(2) # Z-Schlitten hochfahren z_aktuell += self.z_abtasthub cmd = "G01 Z" + str(z_aktuell) + " F1500" grbl.gcode_senden(cmd) self.beruehrt = False # Debug Ausgabe print("Datenpunkte:", punkt) median_z_pos = numpy.median(punkt) print("Median des Abtastpunktes: ", str(median_z_pos)) # Koordinaten dem Oberflächenprofil anhängen profil.append(str(x_pos) + ":" + str(median_z_pos)) # X-Schlitten zur nächsten Abtastposition verschieben x_aktuell -= aufloesung cmd = "G01 X" + str(x_aktuell) + " F500" grbl.gcode_senden(cmd) time.sleep(1) # Fortschrittsbalken aktualisieren fortschritt += 100 / samples fortschritt_signal.emit(fortschritt) # Auf sichere Z-position fahren cmd = "G01 Z0 F1000" grbl.gcode_senden(cmd) print("Profil erfolgreich aufgezeichnet.") return profil
[Doku] def touchsensor_initialisieren(self): """Initialsiert den Nivellierungssensor indem ein Selbsttest durchgeführt wird. Die Mehtode initialisert außerdem die Interrupt-Funktion am Pin GPIO0. Note: Beim Selbsttest wird die Sonde des Sensors 10x gehoben und wieder gesenkt. Returns: list: Gibt eine Liste mit Koordinatenpaaren [X:Z] *(str)* zurück. """ print("Initialisierung des Touchsensors...") # Sonde hochziehen self.sonde_heben() # Selbsttest durchführen self.selbst_test() # Interrupts aktivieren GPIO.setmode(GPIO.BCM) GPIO.setup(self.interrupt_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP) GPIO.add_event_detect( self.interrupt_pin, GPIO.RISING, callback=self.interrupt_routine, bouncetime=200)
[Doku] def sonde_stellen(self, pulsweite): """Erzeugt das PWM Signal am Pin GPIO24 des Raspberry PI. Note: GPIO-Pin ist in den Grundeinstellungen unter ``gpio_bltouch_pwm`` zu finden. Args: pulsweite (int): Pulsweite des PWM-Signales in :math:`{\\mu s}` """ # PWM Signal generieren self.pwm.set_servo_pulsewidth(self.pwm_pin, pulsweite)
[Doku] def sonde_senken(self): """Fährt die Sonde des Nivellierungssensors aus. Note: Pulsweite für die untere Position, lässt sich in den Grundeinstellungen unter ``bl_untere_position`` ändern. Args: pulsweite (int): Pulsweite des PWM-Signales in :math:`{\\mu s}` """ print("Sonde wird ausgefahren.") self.sonde_stellen(self.untere_position)
[Doku] def sonde_heben(self): """Fährt die Sonde des Nivellierungssensors ein. Note: Pulsweite für die obere Position, lässt sich in den Grundeinstellungen unter ``bl_obere_position`` ändern. Args: pulsweite (int): Pulsweite des PWM-Signales in :math:`{\\mu s}` """ print("Sonde wird eingefahren.") self.sonde_stellen(self.obere_position)
[Doku] def selbst_test(self): """Führt einen Selbsttest des Sensors durch. Note: Pulsweite für den Selbsttest lässt sich in den Grundeinstellungen unter ``bl_selbsttest`` ändern. """ print("Touchsensor Selbsttest wird durchgeführt.") self.sonde_stellen(self.selbsttest)