Auch wenn es gerade mal etwas Offtopic ist, beschäfftigt mich diese Thema doch sehr. Denn ich habe seit geraumer Zeit (über 750 Druckstunden) beide Drucker im Einsatz und möchte hier kurz mein Fazit festhalten.
Und natürlich die Optimierungen die ich an meinen Druckern vorgenommen habe! 😉
Spoiler: Einen von beiden habe ich wieder verkauft…..

Bambu Lab X1C

Tolle Software

Zunächst mal muss ich sagen, das meiner Meinung nach Bambu die beste Software-Integration hat:
Slicer installieren -> Objekt slicen -> Upload zum Drucker -> automatischer Wechsel zur Live-Kamera -> druckt
Das ist echt sehr gut gelöst und hat bei mir dafür gesorgt das meine Drucker quasi rund um die Uhr laufen, da ich neue Druckjobs aus der Ferne (also von der Arbeit aus) starten und mit der eingebauten Kamera auch überwachen kann.

Super Tempo und Qualität

Wie ja allgemein bekannt ist sind die Bambu Drucker schnell. Sehr schnell und liefern dabei auch noch gute Qualität. Auch das hat mir am Bambu gefallen.

Schlechte Hardware

Zumindest in meinem Fall muss ich sagen, das ich von der Hardware des X1C nicht begeistert bin. Ich hatte schon innerhalb der ersten 80 Druckstunden 21 (!!) – ja, ich habe eine Strichliste geführt – Probleme. Von den 21 Problemen waren 11 Filamentstörungen im AMS, 9 nicht erkannte Ablösungen vom Druckbett so das es viel Spaghetti gab und sogar einmal einen verstopften Extruder und es war nötig den kompletten Extruder auseinander zu bauen um das zu fixen.
Sowas hasse ich sehr: Denn ich habe keine Lust ständig die Maschine zu zerlegen – das Ding muss laufen.

Original Prusa XL

Super Hardware

Im Vergleich zum Bambo X1C finde ich die Hardware von Prusa deutlich zuverlässiger. Ganz objektiv hatte ich in den ersten 80 Druckstunden mit dem Prusa XL keine (also 0 !!) Probleme. Nicht mit dem Filament (das selbe Filament wie beim X1C), nicht mit den Druckköpfen (habe eine 5-Kopf Maschine) und auch nicht mit der Druckbetthaftung. Bei Prusa gilt nach wie vor und auch beim XL: Drucken -> Warten -> fertig

Super Tempo und Qualität

Mit der neuen Firmware (ab 5.1.2) ist der Prusa XL (fast) genau so schnell wie der X1C bei gleicher oder sogar besserer Qualität. Ich habe zu Testzwecken die Drucker gegeneinander antreten lassen (1-Farb-Druck) und bei einem 8:20 Stunden Job war der Prusa nur 2:30 Minuten langsamer (mit Stoppuhr gemessen). Gleiche Schichtdicke, gleiches Filament. Qualität bei Prusa minimal besser aber bei beiden auf sehr hohem Level.

Software Integration nicht vergleichbar

Leider hängt Prusa mit der Software im Vergleich zum Bambu aber etwas hinterher. Und damit meine ich nicht das Slicen, sondern das drum herum. Synchronisierung der eingelegten Farben im AMS mit dem Slicer, das Live-Bild der Kamera, usw. Da kann Prusa noch deutlich aufholen.

Die Entscheidung

Aufgrund der zuverlässigeren Hardware (und auch wegen des größeren Bauraums und des besseren Material- und Farbwechsel) habe ich mich dazu entschieden den Prusa XL zu behalten und den Bambu wieder zu verkaufen – wenn es mir gelingt die defizite in der Software-Integration von Prusa sinnvoll auszugleichen.
Meiner Meinung nach sind das vor allem folgende Punkte:

  • Drucken aus der Ferne (nicht unbedingt vom Handy, aber mindestens Mal von einem Arbeitsplatz auf der Arbeit)
  • Überwachen des Drucks mittels Kamera

Ebenso war mir wichtig nicht unbedingt auf eine Cloud angewiesen zu sein (vor allem nicht wenn ich zu Hause bin und drucken will) und den Drucker nicht permanent eingeschaltet lassen zu müssen, wenn es mal eine längere Druckpause geben sollte.

Also: Bambu verkauft. Prusa XL neben den schon vorhandenen Prusa Mini aufgebaut und an die Verbesserungen gemacht.

Die Verbesserungen

Drucker nicht permanent eingeschaltet lassen

Drucken aus der Ferne

Der Original Prusa XL hat Netzwerk und PrusaConnect/PrusaLink bereits eingebaut. Beim Original Prusa Mini konnte ich ein ESP8266 nachrüsten. Damit kann ich auf beiden PrusaConnect/PrusaLink aktivieren. PrusaLink zum drucken aus dem lokalen Netzwerk und PrusaConnect zum drucken aus der Ferne.

Dabei bin ich darüber gestolpert das ich die beiden Prusas nicht mit PrusaConnect verbinden konnte. Es zeigte sich das beide Geräte beim Booten versuchen die aktuelle Uhrzeit aus dem Internet zu holen – von einem offensichtlich fest in der Firmware hinterlegten NTP Server. Das ist nötig für die SSL-Kommunikation. Meine Firewall hatte es jedoch unterbunden, so dass eine Zuordnung zu PrusaConnect erstmal nicht möglich war. Nachdem ich das dann korrigiert hatte, klappt es wunderbar.

Druckersteuerung und Überwachung sind damit aus der Ferne möglich – aber ohne Kamerabild.

Überwachung der Drucker mit Kamera

Eigentlich ist es eine Schande das Prusa bei einer so teuren Maschine wie dem Prusa XL nicht schon ab Werk eine Kamera verbaut. Und noch viel befremdlicher ist die favorisierte Lösung “Stell ein altes Handy vor deinen Drucker und nutze die eingebaute Kamera als Webcam”. Ein altes Handy zu nutzen war für mich nicht “die richtige” Lösung.
Aber PrusaConnect bietet eine API an womit man Kamerabilder hochladen und im Portal sichtbar machen kann. Leider nur Standbilder und kein Live-Stream, aber zur Überwachung völlig ausreichend.

Also brauchte ich eine Kamera. Bzw. zwei, da ich den Prusa Mini ja auch überwachen will.
Nachdem ich mehrere (China) Webcams ausprobiert hatte – alle hatten einen Cloudzwang – und ich nicht 250 € und mehr pro Kamera für etwas professionelles ausgeben wollte war klar: selber bauen.

Dann noch schnell Halterungen für die Prusa XL und den Prusa Mini sowie ein Gehäuse gedruckt – fertig. Die Stromversorgung mache ich über mit Tasmota Steckdose – so kann ich auch die Kameras aus der Ferne an- und abschalten.

Es werde Licht

Fazit

Auch wenn mit meinen Anpassungen die Software-Integration bei Prusa (noch) nicht ganz so gut wie bei Bambu ist, so muss ich doch sagen das ich mit der Lösung mehr als zufrieden bin:
Ich kann komfortabel von überall drucken. Kann die Drucker live überwachen und kann die Drucker bei Bedarf aus der Ferne an- und abschalten.

Wie der aufmerksame Leser weiß, haben sich in den letzten Monaten einige Dinge in meinem Leben verändert. Daher komme ich lange nicht mehr so viel zum basteln wie in der Vergangenheit, aber die aktuelle Energiekriese hat mich zu folgendem Projekt inspiriert.

Ich bin mal durch das Haus gegangen und habe Steckernetzteile gezählt, bzw. diverse Microcontroller und Raspberrys und war erschrocken, wie viele kleine Verbraucher sich so angesammelt haben – die Meisten davon habe ich ja hier dokumentiert. 🙂

Wild entschlossen habe ich angefangen diese zu hinterfragen und ggf. auch einfach als “unnötig” zu deklarieren. So sind z.B. jetzt alle Spielekonsolen über eine schaltbare Steckdose deaktiviert und viele Dinge die ohnehin wenig oder garnicht benutzt wurden sind entsorgt oder verkauft.

Auch mein Heizungs-Raspberry, der tatsächlich nichts anderes mehr tut als auf das S0 Signal von einem Stromzähler zu hören und 1-Wire Temperatursensoren auszulesen, kam mir doch etwas oversized vor und mit diesem Projekt löse ich ihn durch einen ESP8266 ab. Natürlich bleibt ein Steckernetzteil erhalten, die Stromaufnahme ist aber trotzdem geringer und ich konnte so auch noch die Funktionalität erweitern.

Die Stromzähler

Die Schaltung auf dem Steckbrett

Und los ging die Bastelei! (endlich!) Die Schaltung war auf dem Breadboard schnell zusammen gesteckt. Tatsächlich bin ich bei der Hardware nur über den S0 gestolpert. Bei den Zählern haben die 3.3V des ESP leider nicht ausgereicht für eine zuverlässige Erfassung. Ein Blick ins Datenblatt und es war klar das es mindestens 5V sein müssen. Da mein Steckernetzteil 5V hat, habe ich also für den S0 direkt diese Spannung genommen und mit einem Spannungsteiler die Spannung für die GPIOs angepasst.

S0 Stromzähler Steckbrett
S0 Stromzähler Schaltung

Die Platine sieht in einem kleine 3D-Druck-Gehäuse dann so aus. (Natürlich gibts zu dem Gehäuse auch noch einen Deckel…

S0 Stromzähler mit 1-Wire Temperaturmessung auf Lochrasterplatine

Der Arduino Quellcode

Die Software besteht grundsätzlich aus zwei Teilen. Einmal dem Arduino Sketch für den ESP8266 und einem PHP-Script als Gegenstück, welches auf meinem NAS läuft und die Werte in die Datenbank schreibt.

Der ESP macht folgendes:
1. Per Interrupt auf steigende Flanken auf den 3 GPIOs hören um dann einen Zähler hochzuzählen
2. Nach 60 Sekunden die aktuellen Temperaturen auszulesen
3. Und das alles als JSON an das PHP-Script zu senden

Da mein NAS irgendwie träge ist und der erste Versuch des Datensendens mit einem Fehler abbricht, wiederhole ich als Workaround das Senden einfach so lange, bis es geklappt hat.

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <Ticker.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define INT_PIN1 13
#define INT_PIN2 12
#define INT_PIN3 14

#define temperatureBus 4
#define addressTempVorlauf "28CF8D2905000054"
#define addressTempRuecklauf "281A8C29050000B6"
#define addressTempGruen "28E92729050000DE"
#define addressTempBraun "28F78B2905000084"

Ticker timer;
OneWire oneWire(temperatureBus);
DallasTemperature sensors(&oneWire);

float powerEG, powerOG, powerHeizung = 0;
volatile unsigned long intCounter[3];
int numberTempSensors;
float temperatureVorlauf = -1;
float temperatureRuecklauf = -1;
DeviceAddress tempDeviceAddress;
bool dataReadyToSend = false;
String httpRequestData = "";
WiFiClient client;
HTTPClient http;
bool isReady = false;


void ICACHE_RAM_ATTR isr1()
{
  intCounter[0]++;
}
void ICACHE_RAM_ATTR isr2()
{
  intCounter[1]++;
}
void ICACHE_RAM_ATTR isr3()
{
  intCounter[2]++;
}

String getDeviceAddressAsHex() {
  String result = "";
  char hexVal[2];
  for (uint8_t i = 0; i < 8; i++) {
    hexVal[0] = 0x0;
    hexVal[1] = 0x0;
    sprintf(hexVal, "%02X\0" , tempDeviceAddress[i]);
    result += hexVal;
  }
  return result;
}

bool sendDataToServer()
{
  if (WiFi.status() == WL_CONNECTED) {        
    if (http.begin(client, "http://<ip-vom-nas>/scripts/powermeasurement.php")) {
      http.addHeader("Content-Type", "application/json");
      http.setTimeout(50);
      
      httpRequestData = "{\"powerog\":" + String(powerOG) + ",";
      httpRequestData += "\"powereg\":" + String(powerEG) + ",";
      httpRequestData += "\"powerheizung\":" + String(powerHeizung) + ",";
      httpRequestData += "\"tempvorlauf\":" + String(temperatureVorlauf) + ",";
      httpRequestData += "\"tempruecklauf\":" + String(temperatureRuecklauf) + "}";
      Serial.println("Sending request " + httpRequestData);
      Serial.flush();
  
      int httpResponseCode = http.POST(httpRequestData);
      http.end();                   
      if (httpResponseCode != 200)
      {
        return false;
      }
      return true;
      
    } else  {
      // Serial.println("UNABLE TO CONNECT");
      return false;
    }           
  } else {
    // Serial.println("WiFi Disconnected");
    return false;
  }
}

void readTemperatures() 
{
  sensors.requestTemperatures();
  delay(1000);

  temperatureVorlauf = -1;
  temperatureRuecklauf = -1;
  for (int i = 0; i < numberTempSensors; i++) {    
    if (sensors.getAddress(tempDeviceAddress, i)) {
      float temp = sensors.getTempC(tempDeviceAddress);            
      String deviceAddress = getDeviceAddressAsHex();      
      if (deviceAddress == addressTempVorlauf) {
        temperatureVorlauf = temp;
      } else if (deviceAddress == addressTempRuecklauf) {
        temperatureRuecklauf = temp;
      }
    }    
  } 
}

void onTimerTick()
{
  noInterrupts();
  powerOG = intCounter[0]; powerOG = powerOG * 60 / 2000;
  powerEG = intCounter[1]; powerEG = powerEG * 60 / 2000;
  powerHeizung = intCounter[2]; powerHeizung = powerHeizung * 60 / 1000;

  intCounter[0] = 0;
  intCounter[1] = 0;
  intCounter[2] = 0;
  interrupts();
  
  dataReadyToSend = true;
}

void setup() {
  Serial.begin(115200);
  Serial.println("Init ports");
  
  pinMode(INT_PIN1, INPUT);
  pinMode(INT_PIN2, INPUT);
  pinMode(INT_PIN3, INPUT);

  Serial.println("Starting wifi");
  IPAddress ip(192, 168, X, Y);
  IPAddress gateway(192, 168, X, Z); 
  IPAddress subnet(255, 255, 255, 0); 
  WiFi.config(ip, gateway, subnet);
  WiFi.begin("<ssid>", "<password>");
  WiFi.hostname("esp-stromzaehler");
  Serial.println("Warte auf Verbindung");   
  while (WiFi.status() != WL_CONNECTED)
  {    
    Serial.print(".");
    delay(500);
  }   
  Serial.print("Mit Wlan verbunden. IP Adresse: ");
  Serial.println(WiFi.localIP());
  Serial.flush();

  Serial.println("Starting sensors");
  sensors.begin();
  numberTempSensors = sensors.getDeviceCount();
  Serial.print(numberTempSensors, DEC);
  Serial.println(" Devices found");  
  for (int i = 0; i < numberTempSensors; i++) {
    if (sensors.getAddress(tempDeviceAddress, i)) {
      Serial.print("Found device ");
      Serial.print(i, DEC);
      Serial.print(" at Address ");
      Serial.print(getDeviceAddressAsHex());
      Serial.println();
    } else {
      Serial.print("Found ghost at ");
      Serial.print(i, DEC);
      Serial.println();
    }
  }

  Serial.println("Starting timer");
  timer.attach(60, onTimerTick);
  
  Serial.println("Setting interrupts");
  attachInterrupt(digitalPinToInterrupt(INT_PIN1), isr1, RISING);
  attachInterrupt(digitalPinToInterrupt(INT_PIN2), isr2, RISING);
  attachInterrupt(digitalPinToInterrupt(INT_PIN3), isr3, RISING);
  
  Serial.println("Setup done...");
  isReady = true;
}

void loop() {
  if (isReady == true)
  {
    readTemperatures();
    
    if (dataReadyToSend == true)
    {
      dataReadyToSend = false;
 
      while (sendDataToServer() == false)
      {
        delay(250);
      }
      Serial.println("sending data ok");
    }     
  }
}

Der PHP Quellcode

Und hier noch das bischen PHP (als Quick&Dirty Script), welches die per JSON gesendeten Werte entgegen nimmt, in die MySQL-Datenbank (ebenfalls auf dem NAS) schreibt und dann noch an den Homeserver schickt.

<?php

/*** INIT ***/
date_default_timezone_set ("Europe/Berlin");
$mysql = mysqli_connect("192.168.X.Y", "<benutzer>", "<passwort>");
if (!$mysql) {
    die('Verbindung schlug fehl: ' . mysqli_error());
}
mysqli_select_db ($mysql, "heizung");


/*** Read Data ***/
$postData = file_get_contents('php://input');
if (strlen($postData) < 10) {
	return;
}
$data = json_decode($postData);
if (!is_object($data)) {
	return;
}
$powerOG = $data->powerog;
$powerEG = $data->powereg;
$powerHeizung = $data->powerheizung;
$tempVorlauf = $data->tempvorlauf;
$tempRuecklauf = $data->tempruecklauf;


/*** Temperaturen ***/
// Daten in Datenbank schreiben
$query = "INSERT INTO temperaturen SET datum = NOW(), `fbh-vorlauf` = '" . (floatval($tempVorlauf)) . "', `fbh-ruecklauf` = '" . (floatval($tempRuecklauf)) . "' ";
mysqli_query($mysql, $query);

# Alte Datensaetze loeschen
$query = "DELETE FROM temperaturen WHERE DATE_SUB(now(), INTERVAL 365 DAY) >= datum";
mysqli_query($mysql, $query);


/*** Energie ***/
// neue daten einfügen
$query = "INSERT INTO stromverbrauch SET datum = NOW(), verbrauch = '" . (floatval($powerHeizung)) . "', verbrauch_eg = '" . (floatval($powerEG)) . "', verbrauch_og = '" . (floatval($powerOG)) . "' ";
mysqli_query($mysql, $query);

// alte daten loeschen
$query = "DELETE FROM stromverbrauch WHERE DATE_SUB(now(), INTERVAL 365 DAY) >= datum";
mysqli_query($mysql, $query);


/*** HOMESERVER DATEN ***/
$data = "";
$data .= "WP-Stromverbrauch=\"".(floatval($powerHeizung))."\"\r\n";
$data .= "WP-HK-Vorlauf=\"".(floatval($tempVorlauf))."\"\r\n";
$data .= "WP-HK-Ruecklauf=\"".(floatval($tempRuecklauf))."\"\r\n";
if (($socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) {
    echo "socket_create() fehlgeschlagen: Grund: " . socket_strerror(socket_last_error()) . "\n";
}
$result = socket_connect($socket, "192.168.X.Z", 11108);
if ($result === false) {
    echo "socket_connect() fehlgeschlagen.\nGrund: ($result) " . socket_strerror(socket_last_error($socket)) . "\n";
}
socket_write($socket, $data, strlen($data));
socket_close($socket);

echo "1";
?>

Damit werden jetzt die gemessenen Werte vom ESP in die Datenbank geschrieben und gleichzeitig auch nochmal an den Homeserver geschickt. Dieser nutzt die Infos “ist die Heizung an?” oder “ist die Klimaanlage an?” an verschiedenen Stellen in der programmierten Logik im sinnvolle Entscheidungen zu treffen – und der alte Raspberry ist jetzt ausgemustert.

Jetzt soll das hier aber kein 3D Drucker test werden. Davon gibt es schon mehr als genug und ich kann diese einfach nur bestätigen: Druck starten -> wiederkommen -> perfekt 😉

Jetzt sollte mein neuer Drucker aber auch ein neues zu Hause bekommen und nicht einfach nur auf der Werkbank stehen. Gerade der Filamentwechsler soll wohl eine Menge Platz brauchen (noch nicht zusammen gebaut). Und wenn ich ABS oder ASA Drucke, muss ich da auch noch eine Kiste drum rum bauen können und die Abluft irgendwie nach draußen bekommen.

Darum habe ich mich für ein Regal auf Rollen entschieden.

Regal auf Rollen mit 3D Drucker und Filamentrollen
Regal auf Rollen mit 3D Drucker und Filamentrollen

Von unten nach oben ist meine Aufteilung jetzt so: Lager und Ersatzteile, Mülleimer und Werkzeug, Drucker und Rollen in Benutzung, Filamentlager.

Filament Guide für Prusa MK3S
Filament Guide für Prusa MK3S

Dann hatte ich noch eine alte PTZ Webcam herum liegen. Diese habe ich mit Kabelbindern links am Regal befestigt, damit ich den Druck beobachten kann ohne im Raum sein zu müssen.

Kamera und 3D Drucker
Kamera und 3D Drucker

Obwohl, oder vielleicht gerade weil, der Prusa MK3S wirklich solide und robust aufgebaut ist, vibriert das ganze Holzbrett beim verfahren der Y-Achse. Darum habe ich eine Teppichfliese untergelegt, welche die Vibrationen deutlich dämpft.

Für die Halterung der Spulen habe ich mir auch etwas ausgedacht. Diese habe ich auf der rechten Seite mit einer Gewindestange montiert. Da ich viel mit den 3KG Spulen arbeite, war mir eine M8 Stange zu dünn. Daber bin ich auf M12 gegangen.

Zunächste habe ich übliche Stuhlwinkel am Regal festgeschraubt. Auf diese Winkel habe ich dann eine kleine Aufnahme für die Gewindestange geschraubt. Hier gibt es die STL-Datei der Aufnahme.

Stuhlwinkeln und Aufnahme der M12 Gewindestange
Stuhlwinkeln und Aufnahme der M12 Gewindestange
Aufnahme M12 Gewindestange
Aufnahme der M12 Gewindestange

Hier gibt es meine STL-Dateien des Universal Rollenhalters für M12 Stangen. Ich habe 3 Varianten gemacht, kurz, mittel und lang. Für die 3KG Rollen nehme ich die großen, für alle anderen den mittleren.

Universal Rollenhalter mittel
Universal Rollenhalter mittel
Universal Rollenhalter lang
Universal Rollenhalter lang
Universal Rollenhalter nuss
Universal Rollenhalter Nuss
Kugellager für M12 Gewindestangen
Kugellager für M12 Gewindestangen
Rollenhalter ohne Rolle auf Achse
Rollenhalter ohne Rolle auf Achse
Filamentrollen im Regal
Filamentrollen im Regal

Wie schon angekündigt hat mein letzter Raspberry mit meiner Zigbee-Steuerung seine SD-Karte zerlegt – was ja immer ein Damoklesschwert über dem Kopf eines jeden ist, der die kleinen PCs mit SD-Karte betreibt und dort auch Datenbanken o.ä. drauf laufen lässt.

Da die PIs ab Version 3 aber auch endlich (ordentlich) aus dem Netzwerk booten können, habe ich mich entschieden nach und nach allen PIs die SD-Karte weg zu nehmen und nur noch über das Netzwerk zu arbeiten. Hier ist die kleine Anleitung dazu:

Verwendet wurden:
– QNAP NAS
– Raspberry PI 3 B V1.2

Vorbereitung DHCP Server

  • Damit der PI aus dem Netzwerk booten kann habe ich meinen DHCP Server so konfiguriert, das er immer die gleiche IP vergibt
  • Außerdem habe ich noch folgende DHCP Optionen gesetzt:
  • “Vendor encapsulated options” = Raspberry Pi Boot
  • “TFTP Servername” = 192.168.x.y (das ist die IP vom NAS)
  • “Bootfile Name” = bootcode.bin

Vorbereitung Raspberry Pi

  • Wie üblich mit dem Raspberry Pi Imager eine (neue) SD-Karte beschrieben und das Betriebssystem “Raspberry Pi OS Lite” installiert (ohne grafische Oberfläche)
  • Dann das System hochgefahren und die grundlegende Installation abgeschlossen (raspi-config, usw.)
  • Damit der Pi über das Netzwerk booten kann, muss ein Eintrag in der /boot/config.txt geändert werden (ganz am Ende)
nano /boot/config.txt
program_usb_boot_mode=1
  • Anschließend den PI neu starten und die Zeile wieder entfernen. Die Einstellung bleibt dauerhaft erhalten.
  • Der Erfolg kann nach dem Neustart wie folgt überprüft werden
vcgencmd otp_dump | grep 17
Ergebniss: 17:3020000a

Einrichtung QNAP NAS

  • Als erstes habe ich die Freigabe “Public” per NFS freigegeben. Hier soll später das Root-Dateisystem liegen und auch die Dateien für den Bootvorgang werde ich hier ablegen. Dazu muss der NFS-Dienst ggf. vorher in der Systemsteuerung aktiviert werden.
  • Gastzugang per Samba/Windows wird für “Public” deaktiviert, bzw. auf “kein Zugriff” gestellt
  • Auf der Public-Freigabe erstellle ich einen Ordner “pxeboot”
  • In dem Ordner “pxeboot” erstelle ich dann pro Raspberry einen weiteren Unterordner. Hier z.b. “zigbee”
  • Und in dem Ordner “zigbee” erzeuge ich dann noch einen Ordner “boot”
  • Außerdem brauche ich für den Netzwerkboot noch einen TFTP Server, der auf den QNAP-NAS wie folgt konfiguriert wird
  • Nun starte ich den Pi einmal ohne die SD-Karte neu und schaue in die Log-Datei “Public\pxeroot\opentftpd.log”. Dort steht jetzt drin welche Dateien gefunden/nicht gefunden wurden. Bei der Datei “start.elf” ist auch ein Unterordner zu sehen, der die Seriennummer des PIs darstellt. Diese merke ich mir, denn ich muss im nächsten Schritt einen passenden Symlink anlegen
  • Darum melde ich mich auf der Console des NAS per SSH an und mittels “ln -s /share/Public/pxeroot/zigbee/boot /share/Public/pxeroot/<seriennummer>” erzeuge ich einen Symlink mit der passenden Seriennummer, der in das boot-Verzeichniss des entsprechenden PIs zeigt

Kopieren der Daten

  • Zunächst melde ich mich am Pi an und mounte die NFS-Freigabe. Anschließend kopiere die gesamte Root-Partition auf die NFS-Freigabe
sudo mount.nfs 192.168.X.Y:/Public/pxeroot/zigbee /mnt
sudo rsync -xa --exclude /mnt / /mnt/
  • Nachdem der Kopiervorgang abgeschlossen ist (kann etwas dauern) müssen noch ein paar Dateien angepasst werden.
  • Zunächst “nano /mnt/etc/fstab”. Es wird alles entfernt außer “proc” und die vier tmpfs sowie das NFS-Root werden hinzugefügt
proc /proc proc defaults 0 0
192.168.X.Y:/Public/pxeroot/zigbee	/ 	nfs 	defaults 	0 	0
tmpfs /tmp tmpfs defaults,noatime,nosuid,size=100m 0 0
tmpfs /var/tmp tmpfs defaults,noatime,nosuid,size=30m 0 0
tmpfs /var/log tmpfs defaults,noatime,nosuid,mode=0755,size=100m 0 0
tmpfs /var/run tmpfs defaults,noatime,nosuid,mode=0755,size=2m 0 0
  • Dann fahre ich den Pi herunter und lege die SD-Karte in meinen PC ein (da wo ich diese auch beschrieben habe). Ich kopiere den ganzen Inhalt, also die ganzen .elf-Dateien, config.txt usw. in den Boot-Ordner auf der Netzwerkfreigabe
  • Die Datei “bootcode.bin” jedoch kopiere ich direkt in den Ordner “pxeroot”
  • Dann wird noch die “cmdline.txt” im Boot-Ordner angepasst:
dwc_otg.lpm_enable=0 console=serial0,115200 console=tty1 root=/dev/nfs nfsroot=192.168.X.Y:/Public/pxeroot/zigbee rw vers=3 ip=dhcp rootfstype=nfs smsc95xx.turbo_mode=N elevator=deadline rootwait

Neustart des Raspberry Pi

Jetzt müsste der Pi ohne SD-Karte neu gestartet werden können. Er wird nach ca. 5 Sekunden vom Netzwerk booten und das System wird bis auf eine Fehlermeldung bzgl. der SWAP-Datei ganz normal hoch fahren.

Dann sind noch folgende, abschließende Arbeiten zu tun:

  • Deinstallieren von “dphys-swapfile” und erstellen und einbinden einer manuell erzeugten SWAP-Datei
sudo apt-get remove --purge dphys-swapfile
sudo rm /var/swap
sudo update-rc.d dphys-swapfile remove
 
sudo dd if=/dev/zero of=/var/swap bs=1M count=1024
sudo losetup /dev/loop0 /var/swap
sudo mkswap /dev/loop0
sudo swapon /dev/loop0

vi /etc/rc.local
echo "Swap einbinden"
sleep 3
losetup /dev/loop0 /var/swap
mkswap /dev/loop0
swapon /dev/loop0
  • Außerdem mache ich noch ein bischen Tuning
vi /etc/default/rcS
ASYNCMOUNTNFS=no 

vi /etc/sysctl.conf
vm.min_free_kbytes=12288
  • Dann noch ein abschließender Neustart und die Konfiguration ist abgeschlossen.

Fluch und Segen zugleich bei mir: Ich mache immer mehrere Projekte parallel auf. So auch dieses hier. Denn ich wollte immer schon mal einen Lasercutter haben und als ich dann in einer Zeitschrift vom diesem “China-Kracher” gehört habe, habe ich mir nun auch einen solchen zugelegt.

Wichtig: Das hier ist keine Kaufempfehlung für das Gerät. Es ist meinem Empfinden nach nicht wirklich sicher und sieht an einigen Stellen aus wie “mal schnell zusammen geklöppelt”.

Aktuell bin ich dabei ein paar Modifikationen vorzunehmen. Und von diesen möchte ich hier berichten.

K40 Lasercutter
K40 Lasercutter, frisch aus der Packung

Der Laser hat auf den ersten Blick folgende Dinge, die ich verbessern, bzw. optimieren werde:

Meine geplanten Optimierungen

  1. Viele kleine Detailverbesserungen an der Verkabelung, Erdung und Kühlung
  2. Keinen Deckelschalter. D.h. der Laser feuert weiter, wenn der Deckel geöffnet wird
  3. Abenteuerliche Wasserkühlung. Die Wasserpumpe die in einen Eimer soll, mit lose rum hängenden Schlauchenden ist nicht wirklich vertrauenserweckend
  4. Das Druckbett lässt nur kleine Bauteile zu, die fummelig eingespannt werden sollen

Kleinigkeiten:

Zunächst habe ich mal die wesentlichen Dinge überprüft. Z.B. “Ist das Gehäuse geerdet”. Es ist zwar eine Erdungsschraube hinten rechts vorgesehen, aber wurde diese montiert nachdem das Gehäuse lackiert wurde. Sie hat also keinen Kontakt zum Gehäuse. Das habe ich mit etwas Schmiergelpapier nachgeholt und dann einmal alle Masseanschlüsse durchgemessen (0 Ohm!)

Hochspannungsnetzteil
Hochspannungsnetzteil ohne Folie

Dann viel mir auf, das auf meinen Netzteil noch eine blaue Folie klebte. Ich kann mir vorstellen das diese die Wärmeabfuhr des Hochspannungsnetzteils nicht verbessert und habe Sie einfach abgezogen.

Wo ich gerade am Netzteil zugange war viel mir auf, das trotz Aderendhülsen ein paar feine Litze aus den Hülsen heraus ragten. Diese habe ich neu gecrimpt bzw. einfach abgeschnitten.

Deckelschalter

Damit man nicht “im Trott” während des Laserns einfach den Deckel aufmacht und die Finger oder noch schlimmer die Augen in Kontakt mit dem (unsichtbaren !) Laserstrahl kommen, soll sich dieser automatisch abstellen, wenn man den Deckel öffnet. Dazu habe ich einen Microschalter in den Deckel eingebaut und diesen in Reihe mit dem vorhandenen “Laser An”-Schalter geschaltet.

Die rosafarbenen Kabel sind original. Ich habe eines davon durchtrennt und meinen Schalter einfach dazwischen geschaltet. Somit müssen beide Schalter geschlossen sein, damit der Laser feuert.

Deckelschalter im Deckel
Deckelschalter im Deckel
Schalter Durchgeschleift
Schalter Durchgeschleift

Wasserkühlung

Als nächstes steht die Wassserkühlung an. Ich nutze dazu Komponenten für PC Wasserkühlungen und werde einen geschlossenen Wasserkreislauf mit Ausgleichsbehälter und aktiver Kühlung bauen. Die Teile sind schon angekommen, aber ich hatte noch keine Gelegenheit diese zu verbauen. Zumal ich auch noch Halterungen für den Ausgleichsbehälter und natürlich den Kühler entwerfen muss.

Druckbett

Auch für das Druckbett habe ich bisher nur eine Übergangslösung. Die mit ausgelieferte Aluminiumplatte war nicht nur krumm, sondern diese hat natürlich auch das Potential den auftreffenden Laserstrahl wieder nach oben zu reflektieren.

Ich habe diese also erstmal mit einem Gitter (möglichst nicht verbogen) aus dem Baumarkt ersetzt. Der Vorteil dabei: Dadurch das ich das Gitter auf die Schrauben liege bin ich mit der Oberkannte des Gitters nun wieder genau im Fokus des Lasers.

Neues, temporäres Druckbett
Neues, temporäres Druckbett
Neues Druckbett Detail
Neues Druckbett Detail