3D Drucker Augen zu und kapazitiv testen

Im Rahmen einer kleinen Umbauaktion des Druckers habe ich auch den optischen Sensor gegen einen kapazitiven Nährungesschalter getauscht. Das ging nicht so leicht wie erwartet. Der optische Näherungsschalter wird zum Einstellen der X- und Z-Achse verwendet. Diese Konfiguration kann mit einem kapazitiven Sensor nicht durchgeführt werden, da der Sensor wesentlich größer ist als die kleine Platine des optischen Sensors.

Druckkopf mit vorläufig angebrachtem kapazitiven Sensor zur Druckbettbestimmung

Im Hintergrund der Abbildung kann man den neuen Endschalter der X-Achse erkennen. Der wird, wie der Endschalter der Y-Achse am Duet Board an den Pins neben dem Z-Motor. Dabei wird der Schalter wie der Y-Endschalter angeschlossen. Die LED auf dem Duet Board soll nun leuchten, wenn der Endschalter nicht betätigt wird. Die Löcher zur Montage des Tasters sind im X-Achstenträger schon vorhanden und müssen nicht neu angebracht werden.

Der schwierigste Teil ist es den Endtaster jetzt als Quelle für den Nullpunkt zu etablieren. Dazu muss die Firmware geändert werden. Dank 3D-ES gibt es aber ein script, mit dem man sich das git Repository von dc42 herunterladen kann. Dort muss in der Auswahl allerdings der dev tree und nicht der duet tree aus.

   – git clone -b duet ${FW_REPO}/${FIRMWARE} ${FIRMWARE}
   + git clone -b dev ${FW_REPO}/${FIRMWARE} ${FIRMWARE}

Nachdem das Repository heruntergeladen wurde kann mit 

   ./make.sh && ./make.sh install

Der Code kompiliert und installiert werden. Die zu ändernden Werte befinden sich in der Datei „Platform.h“ bei Zeile 120

   – #define Z_PROBE_AXES {true, false, true}
   + #define Z_PROBE_AXES {false, false, true}

Damit wird der Firmware gesagt, dass nur noch die Z-Achse mit Hilfe des Z-Sensors genullt werden soll. Alle anderen Achsen haben eigene Endstops.

Bei der Einstellung des Z-Nullpunkts kann wie in der Anleitung beschrieben vorgegangen werden, nur dass man jetzt einen definierten Schaltpunkt hat und daher der Wert keine Rolle spielt. Ich habe mich langsam an den Nullpunkt herangetastet und dann 1,5mm nach oben gefahren. Der Schaltpunkt des Sensors habe ich dann so eingestellt, dass er gerade an diesem Punkt schaltet. Dann den Punkt noch einmal angefahren und der neue Wert für M31 stand fest.

   M31 Z1.66 P600

Wobei der Wert bei P wie oben schon beschrieben relativ egal ist, da der Sensor einen Schaltpunkt hat ab dem er dann von 0V auf einen festen Wert springt. Dieser Wert ist meistens die Betriebsspannung des Sensors. In unserem Fall ist das aber ehr hinderlich, da der Sensor mit 12V betrieben werden muss. Also ein Spannugnsteiler zwischen Signal und Masse, sodass ein ca. 3V starkes Signal am ADC Eingang anliegt. Den Sensor, wie den Taster für die X-Achse, als einfacher Enschalter zu verwenden scheitert, da der Sensor auf Versorgungsspannung schaltet und nicht auf GND, wie es von den Endschaltern getan ist. Hier kann man eventuell noch etwas verbessern.

Alle Änderungen in der Firmware des Ormerod werden in meinem github Repository eingespielt und stehen zur Verwendung zur Vefügung.

3D Drucker der zweite Akt

Ein paar Drucke sind erfolgreich beendet worden, es sind sogar ein paar brauchbare Sachen dabei herausgekommen. Aber was wäre denn ein RepRap, wenn er nicht direkt mit besseren Teilen erweitert wird. Wie im ersten Bericht schon beschrieben sind die Zahnräder für die Z-Achse bereits ersetzt. Heute habe ich das Flachbandkabel für das beheizte Druckbett mit einem 1,5 mm² Kabel ersetzt. Das ist jetzt wesentlich leichter zu verlegen und blockiert nicht die komplette Steuerplatine. Weiterhin habe ich das Netzteil so angeschlossen, dass ich über G-Code Befehle die 12V Steuerspannung zu und abschalten kann. Das benötigt allerdings eine angepasste Firmware. Ich habe es heute mit der Version von dc42 versucht. Die bringt auch gleich eine neue Weboberfläche mit. Somit ist jetzt lediglich die Logik mit dem Standbystrom des Netzteil verbunden und bei bedarf wird die komplette Energie des Netzteils hinzugeschaltet.

Ormerod 1 mit erhöhtem Druckbett und neuem Kabelbaum für den Heizer

Das Software update hat allerdings auch seine Nachteile mit sich gebracht. Einmal führte es dazu, dass der X-Achsen Motor falsch herum angesteuert wurde. Im Nachhinein sind jetzt alle Achsenmotoren gleich angeschlossen und es funktioniert wieder. Ein weiteres Problem, das leider weiterhin besteht ist, dass der Vorgang des Nullens der Z-Achse das Koordinatensystem verschiebt. Und das führt dazu, dass die Punkte für den automatischen Bettabgleich nicht mehr an den ursprünglichen Punkten zu finden sind. Ich hatte aber heute keine Zeit mehr die Punkte anzupassen und zu testen, ob ich mit neuen Referenzpunkten auf ein annehmbares Ergebnis komme. Laut dc42 liegt dieser Fehler an einem Bug in der RepRapPro Firmware, die auch in sinem Fork nicht behoben wurde. Der Bug tritt auf, wenn Achsenkompensation verwendet wird. Eine weitere Untersuchung folgt. Update: Die heute erschienene Version 0.78t zeigt dieses Verhalten nicht mehr.

Geplant sind weitere Erweiterungen, wie ein Schwingungsdämpfer, sowie ein Schutz für den Lüfter. Auch werde ich auf lange Sicht den optischen Sensor gegen einen kapazitiven tauschen, ich habe nämlich heute einige Tests gemacht, die sehr vielversprechend auf die Reproduzierbarkeit der Ergebnisse gelaufen sind. Das Problem des optischen Sensors ist, neben der Empfindlichkeit gegenüber Tageslicht, die ungleichen Refektionseigenschaften der unterschiedlichen Tastpunkte. Mit dem kapazitiven Sensor habe ich an zwei unterschiedlichen Stellen den Nullpunkt einwandfrei bestimmen können.

Ein weiterer geplanter Umbau ist die Neustrukturierung des X-Auslegers. Dort wird im Moment eine M5 Gewindestange verwendet um den Arm nach obern und unten zu verfahren. Ich habe mir überlegt die vorhandenen Kunststoffteile so neu zu drucken, dass die Kraft nicht mehr von der Seite, sondern zwischen Führungslinie und Biegekraft liegt, also auf einer Achse mit dem Ausleger. Außerdem soll die M5 Spindel gegen eine stabilere und spielfreie Tr10x2 Trapezspindel getaucht werden. Der Motor wird auch nicht über Zahnräder die Achse antreiben, sondern direkt über eine Kupplung. Dieser Umbau benötigt allerdings einen funktionierenden Drucker, also erst einmal die Fehler der Achsenkompensation auftreiben und eliminieren.

3D Drucker Ahoy!

Ich habe mir vor einigen Tagen ein RepRap Ormerod Bausatz gekauft. Das Aufbauen war nicht sonderlich schwer und die Verkabelung ebenfalls sehr einfach. Innerhalb von 6 Stunden stand der Drucker komplett zusammengebaut auf dem Tisch. Probleme gab es dann beim Einstellen der Software. Die Kommunikationsschnittstelle mit dem Board ist nicht sonderlich stabil. Teilweise gehen Nachrichten verloren und so sind die ersten Tests nicht sonderlich viel versprechend gewesen. Die Elektronik dann aber vom 5V Pfad des Netzteils zu betreiben und die 12V lediglich für Heizung und Motoren zu verwenden hat die Stabilität wieder zurück gebracht. Das nächste Problem, das konstant aufgetreten ist, hat mit dem Infrarot-Sensor der Z-Achse zu tun. Die Z-Achse soll Berührungslos genullt werden. Dazu befindet sich an einer bestimmten Stelle eine weiße Fläche auf der Druckplatte. Der Sensor wird von oben zu dieser Fläche bewegt und die reflektierte IR-Strahlung wird registriert. Daraus ergibt sich für ein knappen Berühren der Oberfläche mit dem Druckkopf ein Wert von ungefähr 980 mit einem Rauschen im bereich von +- 3. Dabei sitzt der Sensor ca. 2 mm über dem Druckbett. Wenn der Druckkopf ein Zehntel Millimeter weiter hochgefahren wird, sinkt der Wert um ungefähr 2, was bei dem vorherrschenden Signal-Rausch-Abstand keine gut detektierbare Messwertänderung ist. Die Sensitivität des Sensors ist im Abstand von 4 mm am größten. Da werden dann Messwerte im Berich 650 generiert die pro Zehntel Millimeter um 10 bis 15 abnehmen. In diesem Bereich kann dann mit dem vorherrschenden Offset genullt werden. Interessanterweise ist der Wert des Sensors aber abhängig von welcher Richtung man auf die Stelle fährt. Wenn der Sensorkopf von untern, also von hohen Sensorwerten auf die Stelle gefahren wird, zeiugt er einen höheren Wert an, als wenn er von oben auf die gleiche Stelle gefahren wird. Dieses Verhalten hat zu einigen Abdrücken im Druckbett geführt. Ich habe es jetzt zumindest reproduzierbar hinbekommen. Die Nulk-Funktion der X-Achse liefert immer wieder den gleichen Punkt über dem Druckbett. Allerdings 0,5 mm zu hoch. Diese waren so reproduzierbar, dass ich mir nicht die Mühe gemacht habe herauszufinden weshalb. Sogar die automatische Druckbettabgleichung funktioniert mit diesem Offset jetzt auch einwandfrei.

RepRapPro Ormerod mit Tower of Pi

Eine Bewertung zum Ormerod und weitere Baudetails spare ich mir an dieser Stelle. Es gibt genügend davon im Internet zu finden. [0] [1] [2] Allerdings werde ich in der Nächsten Zeit einige Veränderungen an dem Drucker vornehmen. Darunter fällt das Auswechseln der Zahnräder, sowie der Gewindestange, die hat nämlich eine leichte Biegung. Auch der Druckbettschlitten wird ersetzt, sobald ich die Achsen kalibriert habe.

Links: Originale Zahnräder für die Z-Achse
Rechts: Neue Zahnräder mit Pfeilverzahung für mehr Laufruhe und Stabilität

Wie in den Bildern nicht unbedingt sichtbar ist, sind die Zahnräder gerade verzahnt und haben auf Grund der Fertigungstoleranzen der gedruckten Bauteile teilweise sehr große Reibungskräfte, wenn man sie unglücklich kombiniert. Die Teile auf der rechten Seite werden die Ersatzteile für die Zahnräder sein. Allerdings laufen die gerade relativ gut und ich werde die neue Gewindestange für die neuen Zahnräder verwenden. Erstaunlicherweise sind die Drucke so präzise, dass es bis auf die Kante der ersten Schicht keine Nachbearbeitung der Teile benötigt. Und das waren eine der ersten Drucke ohne Kalibrierung der Achsenlänge und der Winkel.

Pläne für den nächsten 3D Drucker stehen schon, denn jetzt kann ich mir den selbst drucken.

Dual-Energy Radiographie

Grundlagen

Die Möglichkeiten verschiedene Gewebedichten in Röntgenstrahlung darzustellen sind begrenzt. Knochen haben eine wesentlich höhere Dichte als Gewebe. Das führt bei Röntgenaufnahmen zum Abdecken von Gewebeinformationen. Eine Methode diese Informationen zu erhalten ist, die Knochenstrukturen in Röntgenaufnahmen zu isolieren und zu subtrahieren. Diese Technik wird Dual-Energy Radiologie genannt, da zwei Aufnahmen mit unterschiedlicher Strahlungsenergie dafür benötigt werden. Eine Aufnahme mit geringer Energie bildet Gewebestrukturen und Knochen ab. Eine zweite Aufnahme mit höherer Energie bildet nur Knochenstrukturen ab. Mit Hilfe der Dämpfungskoeffizienten der verschiedenen Gewebe bei verschiedener Energie können die Dicken der Gewebeschichten ermittelt werden.

Dämpfungen von Knochen und Gewebe bei verschiedenen Energien [0]

Berechnung

Die Intensität einer digitalen Röntgenaufnahme wird für jedes Pixel bestimmt als:
$$ I_{lo} = \mu_{tlo} x{t} + \mu_{blo} x_{b} $$
Und
$$ I_{hi} = \mu_{thi} x{t} + \mu_{bhi} x_{b} $$
Wobei mit \(\mu_{tlo}\) der lineare Dämpfungskoeffizient der niederenergetischen Röntgenstrahlung in Gewebe , mit \(x_{t}\) die Gewebedicke, mit \mu_{blo} der lineare Dämpfungskoeffizient der Knochenstruktur bei niederenergetischen Röntgenstrahlung und mit \(x_{b}\) der Dicke der Knochenstruktur bezeichnet wird. Ebenfalls gelten diese Werte für die Hochenergetische Strahlungsaufnahme mit \(\mu_{thi}\) und \(\mu_{bhi}\) als Dämpfungskoeffizienten. Beide dieser Bilder beinhaltet Informationen über Knochendicke und Gewebedicke.

Wenn nun die gewichtete Addition beider Bilder mit dem Korrekten Faktor \(k_{lo}\) oder \(k_{hi}\) durchgeführt wird:
$$ I = k_{lo} I_{lo} + k_{hi} I_{hi} $$ (1)
Kann entweder die Kochenstruktur, oder die Gewebestruktur ausgebledet werden.
Aus (1) ergibt sich
$$ I = ( k_{lo} \mu_{tlo} + k_{hi} \mu_{thi} ) x_{t} + ( k_{lo} \mu_{blo} + k_{hi} \mu_{bhi} ) x_{b} $$
 Bei korrekter Wahl der Koeffizienten kann zum Beispiel \(x_{t} = 0\) erreicht werden und das Gewebe aus der Aufnahme ausgeblendet werden.
\( k_{lo} \mu_{tlo} + k_{hi} \mu_{thi} = 0\). Daher, \(k_{lo} \mu_{tlo} = – k_{hi} \mu_{thi}\), und
$$\frac{k_{hi}}{k_{lo}} = – \frac{\mu_{tlo}}{\mu_{thi}}$$

Dies zeigt, dass das Ausblenden der Gewebestruktur im Ergebnisbild erreicht werden kann, wenn das Verhältnis der Faktoren das negative Verhältnis von Gewebe bei beiden Strahlungsenergien ist. Gleiches gilt für das Ausblenden der Knochenstruktur.

Software

Das ganze wird nun in Software abgebildet [1]. Es stehen zwei Röntgenaufnahmen mit unterschiedlichem Energiewerten zur Verfügung. Die Aufnahmen sind im 8bit BMP Format abgespeichert. Jedes Pixel hat also einen Wert von 0 … 255. Beide Bilder werden als Bitmap-Objekt geladen:
https://gist.github.com/anonymous/d5e8d7776dc396d2b03b.js
Um auf den Speicherbereich der Bitmap-Objekte zugreifen zu dürfen, müssen diese daraufhin gesperrt werden. Mit einem direkten Zugriff auf die Speicherbereiche der beiden Bilder kann eine Schleife schneller jeden Pixelwert bearbeiten, als würde jeder Pixel einzeln geladen werden müssen.

Um die Werte abspeichern zu können steht noch ein Array mit double Werten und eins mit int Werten zur Verfügung. Der erste Schritt ist es die beiden Bilder zu addieren. Dabei werden die Pixelwerte des niederenergetischen Bildes mit dem Faktor \(k_{lo}\) multipliziert und die Werte des hochenergetischen Bildes mit \(k_{hi}\).
Anschließend wird der Minimal und Maximalwert des Ergebnisses ermittelt und die neuen Werte in das Integer-Array eingetragen.
https://gist.github.com/anonymous/c156e6ed0097feb82274.js
Das Integer-Array dient als Quelle für die Ergebnisbilddaten und nach erfolgreichem Kopieren derselben können die drei Speicherbereiche wieder freigegeben werden.

https://gist.github.com/anonymous/9f1eb25a96af15409999.js

[0] http://www.icru.org/
[1] https://github.com/DasBasti/dual-energy-imaging