Compare commits
	
		
			5 Commits
		
	
	
		
			124580f82a
			...
			89a88463ef
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 89a88463ef | |||
| 3e8e19e8dc | |||
| d220479709 | |||
| f49bbdb664 | |||
| 412127fce5 | 
							
								
								
									
										21
									
								
								LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | MIT License | ||||||
|  |  | ||||||
|  | Copyright (c) 2025 Manuel Weiser | ||||||
|  |  | ||||||
|  | Permission is hereby granted, free of charge, to any person obtaining a copy | ||||||
|  | of this software and associated documentation files (the "Software"), to deal | ||||||
|  | in the Software without restriction, including without limitation the rights | ||||||
|  | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||||
|  | copies of the Software, and to permit persons to whom the Software is | ||||||
|  | furnished to do so, subject to the following conditions: | ||||||
|  |  | ||||||
|  | The above copyright notice and this permission notice shall be included in all | ||||||
|  | copies or substantial portions of the Software. | ||||||
|  |  | ||||||
|  | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||||
|  | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||||
|  | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||||
|  | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||||
|  | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||||
|  | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||||||
|  | SOFTWARE. | ||||||
							
								
								
									
										124
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										124
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,10 +1,8 @@ | |||||||
| # FilaMan - Filament Management System | # FilaMan - Filament Management System | ||||||
|  |  | ||||||
| A comprehensive filament management system combining ESP32-based hardware for weight measurement and NFC tag reading/writing with a web interface for managing filament spools in conjunction with Bambu Lab AMS and Spoolman. | FilaMan is a filament management system for 3D printing. It uses ESP32 hardware for weight measurement and NFC tag management.  | ||||||
|  | Users can manage filament spools, monitor the status of the Automatic Material System (AMS) and make settings via a web interface.  | ||||||
| ## Project Overview | The system integrates seamlessly with [Bambulab](https://bambulab.com/en-us) 3D printers and [Spoolman](https://github.com/Donkie/Spoolman) filament management as well as the [Openspool](https://github.com/spuder/OpenSpool) NFC-TAG format. | ||||||
|  |  | ||||||
| FilaMan is designed to streamline the management of filament spools for 3D printing. The system consists of an ESP32 microcontroller that handles weight measurement and NFC tag operations, and a web interface that allows users to manage filament spools, monitor AMS (Automatic Material System) status, and interact with Spoolman and Bambu Lab printers. |  | ||||||
|  |  | ||||||
| ### ESP32 Hardware Features | ### ESP32 Hardware Features | ||||||
| - **Weight Measurement:** Using a load cell with HX711 amplifier for precise weight tracking. | - **Weight Measurement:** Using a load cell with HX711 amplifier for precise weight tracking. | ||||||
| @@ -12,13 +10,15 @@ FilaMan is designed to streamline the management of filament spools for 3D print | |||||||
| - **OLED Display:** Shows current weight, connection status (WiFi, Bambu Lab, Spoolman). | - **OLED Display:** Shows current weight, connection status (WiFi, Bambu Lab, Spoolman). | ||||||
| - **WiFi Connectivity:** WiFiManager for easy network configuration. | - **WiFi Connectivity:** WiFiManager for easy network configuration. | ||||||
| - **MQTT Integration:** Connects to Bambu Lab printer for AMS control. | - **MQTT Integration:** Connects to Bambu Lab printer for AMS control. | ||||||
| - **Data Persistence:** Stores calibration data in EEPROM. | - **NFC-Tag NTAG215:** Use NTAG215 because of enaught space on the Tag | ||||||
| - **Watchdog Timer:** Ensures system stability. |  | ||||||
|  |  | ||||||
| ### Web Interface Features | ### Web Interface Features | ||||||
| - **Real-time Updates:** WebSocket connection for live data updates. | - **Real-time Updates:** WebSocket connection for live data updates. | ||||||
| - **NFC Tag Management:** Write filament data to NFC tags. | - **NFC Tag Management:**  | ||||||
| - **AMS Integration:**  | 	- Write filament data to NFC tags. | ||||||
|  | 	- uses NFC-Tag Format of [Openspool](https://github.com/spuder/OpenSpool) | ||||||
|  | 	- so you can use it with automatic Spool detection in AMS | ||||||
|  | - **Bambulab AMS Integration:**  | ||||||
|   - Display current AMS tray contents. |   - Display current AMS tray contents. | ||||||
|   - Assign filaments to AMS slots. |   - Assign filaments to AMS slots. | ||||||
|   - Support for external spool holder. |   - Support for external spool holder. | ||||||
| @@ -28,6 +28,9 @@ FilaMan is designed to streamline the management of filament spools for 3D print | |||||||
|   - Update spool weights automatically. |   - Update spool weights automatically. | ||||||
|   - Track NFC tag assignments. |   - Track NFC tag assignments. | ||||||
|  |  | ||||||
|  | ### If you want to support my work, i would be happy to get a coffe | ||||||
|  | <a href="https://www.buymeacoffee.com/manuelw" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a> | ||||||
|  |  | ||||||
| ## Detailed Functionality | ## Detailed Functionality | ||||||
|  |  | ||||||
| ### ESP32 Functionality | ### ESP32 Functionality | ||||||
| @@ -39,13 +42,51 @@ FilaMan is designed to streamline the management of filament spools for 3D print | |||||||
| - **User Interactions:** The web interface allows users to interact with the system, select filaments, write NFC tags, and monitor AMS status. | - **User Interactions:** The web interface allows users to interact with the system, select filaments, write NFC tags, and monitor AMS status. | ||||||
| - **UI Elements:** Includes dropdowns for selecting manufacturers and filaments, buttons for writing NFC tags, and real-time status indicators. | - **UI Elements:** Includes dropdowns for selecting manufacturers and filaments, buttons for writing NFC tags, and real-time status indicators. | ||||||
|  |  | ||||||
|  | ## Hardware Requirements | ||||||
|  |  | ||||||
|  | ### Components | ||||||
|  | - **ESP32 Development Board:** Any ESP32 variant. | ||||||
|  | [https://amzn.eu/d/aXThslf](url) | ||||||
|  | - **HX711 Load Cell Amplifier:** For weight measurement. | ||||||
|  | [https://amzn.eu/d/1wZ4v0x](url) | ||||||
|  | - **OLED Display:** 128x64 SSD1306. | ||||||
|  | [https://amzn.eu/d/dozAYDU](url) | ||||||
|  | - **PN532 NFC Module:** For NFC tag operations. | ||||||
|  | [https://amzn.eu/d/8205DDh](url) | ||||||
|  | - **NFC-Tag:** [https://amzn.eu/d/fywy4c4](url) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | ### Pin Configuration | ||||||
|  | | Component          | ESP32 Pin | | ||||||
|  | |-------------------|-----------| | ||||||
|  | | HX711 DOUT        | 16        | | ||||||
|  | | HX711 SCK         | 17        | | ||||||
|  | | OLED SDA          | 21        | | ||||||
|  | | OLED SCL          | 22        | | ||||||
|  | | PN532 IRQ         | 32        | | ||||||
|  | | PN532 RESET       | 33        | | ||||||
|  | | PN532 SCK  	    | 14        | | ||||||
|  | | PN532 MOSI    	| 13        | | ||||||
|  | | PN532 MISO       	| 12        | | ||||||
|  | | PN532 CS/SS       | 15        | | ||||||
|  |  | ||||||
|  | ## Software Dependencies | ||||||
|  |  | ||||||
|  | ### ESP32 Libraries | ||||||
|  | - `WiFiManager`: Network configuration | ||||||
|  | - `ESPAsyncWebServer`: Web server functionality | ||||||
|  | - `ArduinoJson`: JSON parsing and creation | ||||||
|  | - `PubSubClient`: MQTT communication | ||||||
|  | - `Adafruit_PN532`: NFC functionality | ||||||
|  | - `Adafruit_SSD1306`: OLED display control | ||||||
|  | - `HX711`: Load cell communication | ||||||
|  |  | ||||||
| ## Installation | ## Installation | ||||||
|  |  | ||||||
| ### Prerequisites | ### Prerequisites | ||||||
| - **Software:** | - **Software:** | ||||||
|   - [PlatformIO](https://platformio.org/) in VS Code |   - [PlatformIO](https://platformio.org/) in VS Code | ||||||
|   - [Spoolman](https://github.com/Donkie/Spoolman) instance |   - [Spoolman](https://github.com/Donkie/Spoolman) instance | ||||||
|   - Bambu Lab printer (optional for AMS integration) |  | ||||||
| - **Hardware:** | - **Hardware:** | ||||||
|   - ESP32 Development Board |   - ESP32 Development Board | ||||||
|   - HX711 Load Cell Amplifier |   - HX711 Load Cell Amplifier | ||||||
| @@ -57,7 +98,7 @@ FilaMan is designed to streamline the management of filament spools for 3D print | |||||||
| ### Step-by-Step Installation | ### Step-by-Step Installation | ||||||
| 1. **Clone the Repository:** | 1. **Clone the Repository:** | ||||||
|     ```bash |     ```bash | ||||||
|     git clone https://github.com/yourusername/FilaMan.git |     git clone https://github.com/ManuelW77/Filaman.git | ||||||
|     cd FilaMan |     cd FilaMan | ||||||
|     ``` |     ``` | ||||||
| 2. **Install Dependencies:** | 2. **Install Dependencies:** | ||||||
| @@ -73,62 +114,6 @@ FilaMan is designed to streamline the management of filament spools for 3D print | |||||||
|     - Configure WiFi settings through the captive portal. |     - Configure WiFi settings through the captive portal. | ||||||
|     - Access the web interface at `http://filaman.local` or the IP address. |     - Access the web interface at `http://filaman.local` or the IP address. | ||||||
|  |  | ||||||
| ## Hardware Requirements |  | ||||||
|  |  | ||||||
| ### Components |  | ||||||
| - **ESP32 Development Board:** Any ESP32 variant. |  | ||||||
| - **HX711 Load Cell Amplifier:** For weight measurement. |  | ||||||
| - **Load Cell:** Weight sensor. |  | ||||||
| - **OLED Display:** 128x64 SSD1306. |  | ||||||
| - **PN532 NFC Module:** For NFC tag operations. |  | ||||||
| - **Connecting Wires:** For connections. |  | ||||||
|  |  | ||||||
| ### Pin Configuration |  | ||||||
| | Component          | ESP32 Pin | |  | ||||||
| |-------------------|-----------| |  | ||||||
| | HX711 DOUT        | 16        | |  | ||||||
| | HX711 SCK         | 17        | |  | ||||||
| | OLED SDA          | 21        | |  | ||||||
| | OLED SCL          | 22        | |  | ||||||
| | PN532 IRQ         | 32        | |  | ||||||
| | PN532 RESET       | 33        | |  | ||||||
|  |  | ||||||
| ## Software Dependencies |  | ||||||
|  |  | ||||||
| ### ESP32 Libraries |  | ||||||
| - `WiFiManager`: Network configuration |  | ||||||
| - `ESPAsyncWebServer`: Web server functionality |  | ||||||
| - `ArduinoJson`: JSON parsing and creation |  | ||||||
| - `PubSubClient`: MQTT communication |  | ||||||
| - `Adafruit_PN532`: NFC functionality |  | ||||||
| - `Adafruit_SSD1306`: OLED display control |  | ||||||
| - `HX711`: Load cell communication |  | ||||||
|  |  | ||||||
| ### External Services |  | ||||||
| - **Bambu Lab Printer:** For AMS integration. |  | ||||||
| - **Spoolman:** For filament management. |  | ||||||
|  |  | ||||||
| ## API Communication |  | ||||||
|  |  | ||||||
| ### Spoolman Integration |  | ||||||
| The system communicates with Spoolman using its REST API for: |  | ||||||
| - Fetching spool information. |  | ||||||
| - Updating spool weights. |  | ||||||
| - Managing NFC tag assignments. |  | ||||||
|  |  | ||||||
| ### Data Format |  | ||||||
| ```json |  | ||||||
| { |  | ||||||
|   "version": "2.0", |  | ||||||
|   "protocol": "openspool", |  | ||||||
|   "color_hex": "FFFFFF", |  | ||||||
|   "type": "PLA", |  | ||||||
|   "min_temp": 200, |  | ||||||
|   "max_temp": 220, |  | ||||||
|   "brand": "Vendor", |  | ||||||
|   "sm_id": "1234" |  | ||||||
| } |  | ||||||
| ``` |  | ||||||
|  |  | ||||||
| ## Documentation | ## Documentation | ||||||
|  |  | ||||||
| @@ -159,4 +144,7 @@ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file | |||||||
|  |  | ||||||
| ## Availability | ## Availability | ||||||
|  |  | ||||||
| The code can be tested and the application can be downloaded from the [GitHub repository](https://github.com/yourusername/FilaMan). | The code can be tested and the application can be downloaded from the [GitHub repository](https://github.com/ManuelW77/Filaman). | ||||||
|  |  | ||||||
|  | ### If you want to support my work, i would be happy to get a coffe | ||||||
|  | <a href="https://www.buymeacoffee.com/manuelw" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a> | ||||||
| @@ -32,12 +32,6 @@ | |||||||
|                 .then(data => { |                 .then(data => { | ||||||
|                     if (data.healthy) { |                     if (data.healthy) { | ||||||
|                         document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials saved!'; |                         document.getElementById('bambuStatusMessage').innerText = 'Bambu Credentials saved!'; | ||||||
|                         // Erstelle und zeige den Reboot-Button |  | ||||||
|                         const rebootBtn = document.createElement('button'); |  | ||||||
|                         rebootBtn.innerText = 'Reboot now'; |  | ||||||
|                         rebootBtn.className = 'reboot-button'; |  | ||||||
|                         rebootBtn.onclick = () => window.location.href = '/reboot'; |  | ||||||
|                         document.getElementById('bambuStatusMessage').appendChild(rebootBtn); |  | ||||||
|                     } else { |                     } else { | ||||||
|                         document.getElementById('bambuStatusMessage').innerText = 'Error while saving Bambu Credentials.'; |                         document.getElementById('bambuStatusMessage').innerText = 'Error while saving Bambu Credentials.'; | ||||||
|                     } |                     } | ||||||
|   | |||||||
| @@ -845,20 +845,6 @@ input[type="submit"]:disabled, | |||||||
|     animation: dots 1s steps(3, end) infinite; |     animation: dots 1s steps(3, end) infinite; | ||||||
| } | } | ||||||
|  |  | ||||||
| .reboot-button { |  | ||||||
|     background-color: #ff0000; |  | ||||||
|     color: white; |  | ||||||
|     padding: 10px 20px; |  | ||||||
|     border: none; |  | ||||||
|     border-radius: 4px; |  | ||||||
|     margin-left: 10px; |  | ||||||
|     cursor: pointer; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| .reboot-button:hover { |  | ||||||
|     background-color: #cc0000; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Bambu Settings Erweiterung */ | /* Bambu Settings Erweiterung */ | ||||||
| .bambu-settings { | .bambu-settings { | ||||||
|     background: white; |     background: white; | ||||||
| @@ -880,7 +866,7 @@ input[type="submit"]:disabled, | |||||||
| } | } | ||||||
|  |  | ||||||
| .bambu-settings .input-group input { | .bambu-settings .input-group input { | ||||||
|     width: 100%; |     width: 95%; | ||||||
| } | } | ||||||
|  |  | ||||||
| #bambuStatusMessage { | #bambuStatusMessage { | ||||||
|   | |||||||
| @@ -30,17 +30,26 @@ int ams_count = 0; | |||||||
| String amsJsonData;  // Speichert das fertige JSON für WebSocket-Clients | String amsJsonData;  // Speichert das fertige JSON für WebSocket-Clients | ||||||
| AMSData ams_data[MAX_AMS];  // Definition des Arrays | AMSData ams_data[MAX_AMS];  // Definition des Arrays | ||||||
|  |  | ||||||
| bool saveBambuCredentials(const String& bambu_ip, const String& bambu_serialnr, const String& bambu_accesscode) { | bool saveBambuCredentials(const String& ip, const String& serialnr, const String& accesscode) { | ||||||
|  |     if (BambuMqttTask) { | ||||||
|  |         vTaskDelete(BambuMqttTask); | ||||||
|  |     } | ||||||
|  |      | ||||||
|     JsonDocument doc; |     JsonDocument doc; | ||||||
|     doc["bambu_ip"] = bambu_ip; |     doc["bambu_ip"] = ip; | ||||||
|     doc["bambu_accesscode"] = bambu_accesscode; |     doc["bambu_accesscode"] = accesscode; | ||||||
|     doc["bambu_serialnr"] = bambu_serialnr; |     doc["bambu_serialnr"] = serialnr; | ||||||
|  |  | ||||||
|     if (!saveJsonValue("/bambu_credentials.json", doc)) { |     if (!saveJsonValue("/bambu_credentials.json", doc)) { | ||||||
|         Serial.println("Fehler beim Speichern der Bambu-Credentials."); |         Serial.println("Fehler beim Speichern der Bambu-Credentials."); | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     // Dynamische Speicherallokation für die globalen Pointer | ||||||
|  |     bambu_ip = ip.c_str(); | ||||||
|  |     bambu_accesscode = accesscode.c_str(); | ||||||
|  |     bambu_serialnr = serialnr.c_str(); | ||||||
|  |  | ||||||
|     vTaskDelay(100 / portTICK_PERIOD_MS); |     vTaskDelay(100 / portTICK_PERIOD_MS); | ||||||
|     if (!setupMqtt()) return false; |     if (!setupMqtt()) return false; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,12 +7,13 @@ bool saveJsonValue(const char* filename, const JsonDocument& doc) { | |||||||
|         Serial.println(filename); |         Serial.println(filename); | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|     return true; |  | ||||||
|     if (serializeJson(doc, file) == 0) { |     if (serializeJson(doc, file) == 0) { | ||||||
|         Serial.println("Fehler beim Serialisieren von JSON."); |         Serial.println("Fehler beim Serialisieren von JSON."); | ||||||
|         file.close(); |         file.close(); | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     file.close(); |     file.close(); | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -213,9 +213,16 @@ void setupWebserver(AsyncWebServer &server) { | |||||||
|  |  | ||||||
|         JsonDocument doc; |         JsonDocument doc; | ||||||
|         if (loadJsonValue("/bambu_credentials.json", doc) && doc.containsKey("bambu_ip")) { |         if (loadJsonValue("/bambu_credentials.json", doc) && doc.containsKey("bambu_ip")) { | ||||||
|             html.replace("{{bambuIp}}", doc["bambu_ip"].as<String>() ? doc["bambu_ip"].as<String>() : "");             |             String bambuIp = doc["bambu_ip"].as<String>(); | ||||||
|             html.replace("{{bambuSerial}}", doc["bambu_serialnr"].as<String>() ? doc["bambu_serialnr"].as<String>() : ""); |             String bambuSerial = doc["bambu_serialnr"].as<String>(); | ||||||
|             html.replace("{{bambuCode}}", doc["bambu_accesscode"].as<String>() ? doc["bambu_accesscode"].as<String>() : ""); |             String bambuCode = doc["bambu_accesscode"].as<String>(); | ||||||
|  |             bambuIp.trim(); | ||||||
|  |             bambuSerial.trim(); | ||||||
|  |             bambuCode.trim(); | ||||||
|  |  | ||||||
|  |             html.replace("{{bambuIp}}", bambuIp ? bambuIp : "");             | ||||||
|  |             html.replace("{{bambuSerial}}", bambuSerial ? bambuSerial : ""); | ||||||
|  |             html.replace("{{bambuCode}}", bambuCode ? bambuCode : ""); | ||||||
|         }    |         }    | ||||||
|  |  | ||||||
|         request->send(200, "text/html", html); |         request->send(200, "text/html", html); | ||||||
| @@ -251,6 +258,11 @@ void setupWebserver(AsyncWebServer &server) { | |||||||
|         bambu_serialnr.trim(); |         bambu_serialnr.trim(); | ||||||
|         bambu_accesscode.trim(); |         bambu_accesscode.trim(); | ||||||
|  |  | ||||||
|  |         if (bambu_ip.length() == 0 || bambu_serialnr.length() == 0 || bambu_accesscode.length() == 0) { | ||||||
|  |             request->send(400, "application/json", "{\"success\": false, \"error\": \"Empty parameter\"}"); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         bool success = saveBambuCredentials(bambu_ip, bambu_serialnr, bambu_accesscode); |         bool success = saveBambuCredentials(bambu_ip, bambu_serialnr, bambu_accesscode); | ||||||
|  |  | ||||||
|         request->send(200, "application/json", "{\"healthy\": " + String(success ? "true" : "false") + "}"); |         request->send(200, "application/json", "{\"healthy\": " + String(success ? "true" : "false") + "}"); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user