UMFilMON
Der UMFilMON (Ultimaker FIlament Monitor) ist wie der Name bereits impliziert, ein kleiner Sensor, welcher den Filamentfluss überwacht und bei einer leeren Filamentspule oder bei so genanntem "Grinding", den Druck pausiert. In dem Fall kann der Nutzer den Fehler beheben und den Druck im Anschluss fortsetzen.
Vorteile im Überblick
- Zeit sparend
- Höhere Zuverlässigkeit
- Ressourcen Schonend
- Leichte Montage & Inbetriebnahme
Montageanleitung
Bei der Entwicklung war uns besonders der Aspekt der leichten Montage überaus wichtig. In diversen Foren und Blogbeiträgen findet man reichlich Nutzer, welche bereits über die Umsetzung eines solchen Sensors diskutiert haben. Jeder dieser Ansätze war jedoch mit der Anpassung der Firmware und der zusätzlichen Modifikation des Kabelbaums verbunden. Unsere Lösung lässt sich in weniger als 10 Minuten verbauen und Bedarf nur folgende Werkzeuge
- 2mm Inbus
- Flachzange
Nachfolgend wird die Montage in wenigen kurzen Schritten erläutert
- Den UM2 von der Spannung trennen
- Displayabdeckung an der Unterseite des Geräts lösen und abnehmen
- Das Kabel EXP1 abstecken, und dafür das ca. 10cm lange beiliegende Kabel in den entsprechenden Port einstecken
- Nun beide Kabel Kabel in die beiden gegenüber liegenden Ports des Expansion Boards, mit der Aufschrift "Ulti" einstecken.
- Das längere, ca. 45cm lange Kabel in einen der beiden Ports mit der Bezeichnung "FilMON" einstecken und nach hinten, in Richtung Spulenhalter führen
- Displayabdeckung wieder anschrauben.
- Zuletzt den UMFilMON Sensor mit dem langen Kabel verbinden
Inbetriebnahme
Da wir auf Software und Hardwareanpassungen seitens des Ultimakers verzichten wollten, täuscht der Sensor einen Benutzer am Bedienfeld vor.
Damit der Sensor nun den Filamentfluss überwachen kann, führen wir das Filament an der Unterseite des Sensors ein, und durchlaufen nun wie gewohnt den Menüpunkt "Change Filament" des Ultimakers.
Der an der Seite befindliche Taster kann den Sensor sowohl aktivieren als auch deaktiveren.
Aktivieren: Ein kurzer Tastendruck lässt eine kleine rote LED für 3 Sekunde blinken, welche das aktivieren symbolisiert.
Deaktivieren: EIn längerer Tastendruck für ca. 1,5-2 Sekunden lässt die LED kurz aufblicken und dann erlischen - Der Sensor wurde deaktiviert.
Hardware
Der Sensor wurde mit Circuit Studio von Altium Designer designed. Diese Software ist kostenlos und cloud basiert, sodass wir bei vorheriger Kontaktaufnahme Nutzern gerne Zugriff auf das Projekt gewähren.
Der UMFilMON basiert auf einem Atmel Atmega328P, einer sehr rudimentären 8-bit MCU, welche jedoch sehr kostengünstig (ca. 1€) zu haben ist und für unsere Aufgabenstellung vollkommen ausreichend ist. Die Messungen werden von zwei analogen Hallsensoren (DRV5056) durchgeführt, welche in dem nachfolgenden Bild als SEN0 & SEN1 beschriftet sind. Wir haben uns für zwei gegenüberliegenden Sensoren entschieden, da dadurch jede Stellung/Magnetfeldänderung zuverlässig gemessen werden kann.
Um die MCU mit dem UMFilMON Code flashen zu können, haben wir sowohl einen FTDI Bus als auch eine ISP Schnittstelle an der Unterseite integriert. Selbstverständlich ist es auch möglich den AT328P vor dem löten mit einem TQFP32 Programmer zu flashen. Jedoch ist in dem Fall darauf zu achten, den Programmer mit einem 16MHz Quarz, sowie zwei Abblockkondensatoren auszustatten
Bill of Materials
Gerber Files
Wir haben noch einige PCB's, welche wir bei Bedarf gerne verschenken würden! Bei Interesse kontaktieren Sie uns bitte über das Kontaktformular.
We have several PCB's which we would like to make a gift to everyone, who is interested in building the UMFilMON on his own. If you are interested in it, please feel free to use our contact form to get in touch.
Software
Wie bereits erwähnt ist das Board vollständig Arduino IDE kompatibel und lässt sich bei Auswahl des Arduino Nano's, bequem darüber programmieren. Wir empfehlen die Programmierung über einen USBasp Programmer, über die an der Unterseite befindliche ISP Schnittstelle vorzunehmen.
/******************************************************************************* * Copyright 2019 MYBOTSHOP.DE * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ #define BLINK_RATE 500 // Blinking rate of LED #define DEBOUNCE_TIME 150 // Debounce Time of the Button #define LONG_PRESS 1000 // Duration of Long Press #define INTERVAL_SHORT 5999 #define INTERVAL_LONG 5999 // 30 Second duration for the idle #define D2 2 #define LED 3 #define BUTTON 4 #define S1 A0 // Sensor #define S2 A1 #define abs(x) ((int16_t)(x))<0 ? (-x):(x) enum {OFF, BLINK, ON} LedState = OFF , nextState = OFF; volatile bool debounce = LOW, isActive = LOW, isDetected = LOW; volatile uint16_t ButtonPress = 0, Error_Blink = 0, counter = 0, Blink = 0, Duration = 0, INTERVAL = INTERVAL_SHORT, NO_ACTIVITY_TIMELIMIT; void setup() { PCICR |= _BV(PCIE2); PCMSK2 |= _BV(PCINT20); pinMode(LED, OUTPUT); pinMode(2, OUTPUT); pinMode(BUTTON, INPUT_PULLUP); digitalWrite(2, LOW); digitalWrite(LED, LOW); Serial.begin(115200); } void loop() { ButtonState(); // monitors Button state, pressed or LongPressed LEDStatus(); // Controls the LED , OFF or BLINKING detectPulse(); // Reads Pulse from sensor if (!isActive ) { if (abs((uint16_t)millis() - Error_Blink) >= 300) digitalWrite(2, LOW); } } uint8_t detectPulse () { static int16_t lastValue_1, lastValue_2, lastTick = 0; uint16_t presentValue_1, presentValue_2; if (abs((uint16_t)millis() - lastTick) > INTERVAL) { if (isActive) { // read the sensor value for every 1mS presentValue_1 = analogRead(S1); presentValue_2 = analogRead(S2); uint16_t error_1 = presentValue_1 - lastValue_1; uint16_t error_2 = presentValue_2 - lastValue_2; Serial.print("L 1:"); Serial.println(lastValue_1); Serial.print("L 2:"); Serial.println(lastValue_2); error_1 = abs(error_1); error_2 = abs(error_2); if ((error_1 >= 3) || (error_2 >= 3)) { counter = 0; isDetected = HIGH; } lastValue_1 = presentValue_1; lastValue_2 = presentValue_2; lastTick = (uint16_t)millis(); // if counter value exceeds 30000 then sends error signal and turns off the sensor if (isDetected && (counter++ >= NO_ACTIVITY_TIMELIMIT)) { isDetected = LOW; Serial.println("Error detected! Pause printing!"); Error(); } Serial.print("E 1:"); Serial.println(error_1); Serial.print("E 2:"); Serial.println(error_2); } else lastValue_1 = analogRead(S1); lastValue_2 = analogRead(S2); } } // Error State Characteristics void Error() { LedState = BLINK; Duration = 2000; Blink = Error_Blink = (uint16_t)millis(); digitalWrite(2, HIGH); isActive = LOW; nextState = OFF; counter = 0; } // LED Status void LEDStatus() { static uint16_t lastTick = 0; switch (LedState) { case OFF : { digitalWrite(LED, LOW); break; } case BLINK: { if ((abs((uint16_t)millis() - Blink)) < Duration ) { if ((abs((uint16_t)millis() - lastTick)) > BLINK_RATE ) { lastTick = (uint16_t)millis(); digitalWrite(LED, !digitalRead(LED)); // Toggles LED } } else LedState = nextState; break; } case ON: { digitalWrite(LED, HIGH); break; } } } // interrupt for Button press detection ISR(PCINT2_vect) { if (!digitalRead(BUTTON)) { ButtonPress = (uint16_t)millis(); debounce = HIGH; } } // Monitors Button state and press event void ButtonState() { static uint8_t press; uint16_t tick = abs((uint16_t)millis() - ButtonPress); if (debounce && (tick > DEBOUNCE_TIME)) { if (digitalRead(BUTTON) || (tick > LONG_PRESS)) { debounce = LOW; if (tick < LONG_PRESS) // short press { if (++press >= 4 ) { // press = 0; // Duration = 5000; // INTERVAL = INTERVAL_LONG; // NO_ACTIVITY_TIMELIMIT = (25000/(INTERVAL + 1)); // } // else // { Duration = 3000; INTERVAL = INTERVAL_SHORT; NO_ACTIVITY_TIMELIMIT = (25000/(INTERVAL + 1)); } Blink = (uint16_t)millis(); LedState = BLINK; Serial.print("Interval = "); Serial.println(NO_ACTIVITY_TIMELIMIT); digitalWrite(2, LOW); isActive = HIGH; nextState = ON; } else // long press { Error(); } } } }