
Celem tego projektu jest stworzenie taniej i kompaktowej alternatywy dla systemów takich jak OctoPrint, które wymagają urządzenia takiego jak np. raspberryPi. W obecnej fazie, ESP32 zostało połączone z płytą główną drukarki oraz został stworzony prosty interfejs HTML, dzięki któremu możemy zdalnie połączyć się z urządzeniem i wysyłać komendy G-code przez pole tekstowe oraz używać kilku przycisków które obsługują najczęściej używane komendy.
1. Płytka ESP32
2. Przewody
3. Drukarka 3D
lutownica
O projekcie:
Celem tego projektu jest stworzenie taniej i kompaktowej alternatywy dla systemów takich jak OctoPrint, które wymagają urządzenia takiego jak np. raspberryPi. W obecnej fazie, ESP32 zostało połączone z płytą główną drukarki oraz został stworzony prosty interfejs HTML, dzięki któremu możemy zdalnie połączyć się z urządzeniem i wysyłać komendy G-code przez pole tekstowe oraz używać kilku przycisków które obsługują najczęściej używane komendy.
Co dalej:
Następne kroki rozwoju projektu składają się z usprawnień graficznych interfejsu, dodanie monitorów temperatur oraz statusu drukarki, możliwość zdalnego przesyłania plików oraz obsługa zdalnego uruchamiania drukarki. Dodatkowo aby ułatwić użytkownikowi integracje systemu z drukarką można stworzyć nakładkę z pinami pogo, pozwalającą na szybkie i niewymagające lutowania połączenie systemu z płytą główną, co pozwoli na nieskomplikowaną wymianę elementów w urządzeniu.

Ustaw odpowiedni# Konfiguracja UART1 (np. TX: GPIO17, RX: GPIO16)
uart = UART(1, baudrate=115200, tx=17, rx=16)
# Zmienna do przechowywania danych otrzymanych przez UART
uart_data = ""
# Funkcja wysyłania G-code
def send_gcode(gcode_command):
uart.write(gcode_command + "\n") # Send the G-code command followed by a newline
time.sleep(0.5) # Give time for the printer to process the command
print("Wysłano: ", gcode_command)
# Read the response from the printer
if uart.any():
response = uart.read()
print("Response from printer: ", response)
return response.decode('utf-8') # Odczytanie odpowiedzi z UART
return "Brak odpowiedzi od drukarki"
# Oczekiwanie na odpowiedź od drukarki (można dostosować czas oczekiwania)
# Funkcja do łączenia się z Wi-Fi
def connect_wifi():
ssid = '' # Zmień na swoją nazwę sieci Wi-Fi
password = '' # Zmień na swoje hasło do Wi-Fi
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect(ssid, password)
print('Łączenie z siecią Wi-Fi...')
while not wlan.isconnected():
time.sleep(1)
print('Połączono z Wi-Fi')
print('Adres IP:', wlan.ifconfig()[0])
# Funkcja do dekodowania URL (ręcznie zamienia %20 na spację i inne znaki)
def url_decode(url):
url = url.replace('%20', ' ')
url = url.replace('%3D', '=')
url = url.replace('%2F', '/')
url = url.replace('%3A', ':')
url = url.replace('%0A', '')
return url
# Funkcja do odczytu danych z UART i aktualizacji zmiennej
#def read_uart_data():
# global uart_data
# while True:
# data = uart.read()
# if data:
# uart_data = uart_data + data.decode('utf-8') # Dodajemy nowe dane do bufora
# time.sleep(0.1)
# Konfiguracja serwera HTTP
def web_server():
addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]
s = socket.socket()
s.bind(addr)
s.listen(1)
print('Serwer nasłuchuje na', addr)
while True:
cl, addr = s.accept()
cl.settimeout(10.0)
# Strona HTML z przyciskami
response = """<!DOCTYPE html>
<html>
<head>
<title>Kontrola Drukarki 3D</title>
<style>
body { font-family: Arial, sans-serif; text-align: center; }
button { font-size: 20px; padding: 10px 20px; margin: 10px; }
textarea { width: 300px; height: 100px; margin-top: 10px; }
#responseLog { max-height: 200px; overflow-y: scroll; border: 1px solid #ccc; padding: 10px; margin-top: 20px; }
#uartLog { width: 100%; height: 200px; margin-top: 20px; padding: 10px; border: 1px solid #ccc; overflow-y: scroll; font-family: monospace; }
</style>
</head>
<body>
<h1>Kontrola drukarki 3D</h1>
<!-- Przesuwanie osi X -->
<button onclick="sendCommand('G1 X1 F1500')">X+1</button>
<button onclick="sendCommand('G1 X10 F1500')">X+10</button>
<button onclick="sendCommand('G1 X-1 F1500')">X-1</button>
<button onclick="sendCommand('G1 X-10 F1500')">X-10</button>
<!-- Przesuwanie osi Y -->
<button onclick="sendCommand('G1 Y1 F1500')">Y+1</button>
<button onclick="sendCommand('G1 Y10 F1500')">Y+10</button>
<button onclick="sendCommand('G1 Y-1 F1500')">Y-1</button>
<button onclick="sendCommand('G1 Y-10 F1500')">Y-10</button>
<!-- Przesuwanie osi Z -->
<button onclick="sendCommand('G1 Z1 F1500')">Z+1</button>
<button onclick="sendCommand('G1 Z10 F1500')">Z+10</button>
<button onclick="sendCommand('G1 Z-1 F1500')">Z-1</button>
<button onclick="sendCommand('G1 Z-10 F1500')">Z-10</button>
<!-- Pole tekstowe do wprowadzania G-code -->
<textarea id="gcodeInput" placeholder="Wpisz komende G-code..."></textarea><br>
<button onclick="sendCommandFromText()">Wyslij komende G-code</button>
<!-- Przycisk do nagrzewania hotendu -->
<button onclick="sendCommand('M104 S200')">Nagrzej hotend</button>
<!-- Przycisk do nagrzewania stolu -->
<button onclick="sendCommand('M140 S60')">Nagrzej stol</button>
<!-- Log odpowiedzi z drukarki -->
<h2>Odpowiedz z drukarki:</h2>
<div id="responseLog"></div>
<script>
// Funkcja wysylajaca komende do serwera
function sendCommand(command) {
console.log("Wyslano komende: " + command);
// Zapewnienie, że komenda jest przesylana poprawnie
const urlCommand = 'command=' + encodeURIComponent(command);
fetch('/send?' + urlCommand)
.then(response => response.text())
.then(data => {
updateResponseLog(command, data);
});
}
// Funkcja wysylajaca komende z pola tekstowego
function sendCommandFromText() {
const gcodeCommand = document.getElementById('gcodeInput').value;
sendCommand(gcodeCommand);
document.getElementById('gcodeInput').value = ''; // Wyczysć pole tekstowe po wyslaniu
}
// Funkcja aktualizujaca log z odpowiedzia
function updateResponseLog(command, response) {
const responseLog = document.getElementById('responseLog');
// Pokaż tylko ostatnia wyslana komende i odpowiedz
responseLog.innerHTML = `<strong>Komenda:</strong> ${command}<br><strong>Odpowiedz:</strong> ${response}`;
}
// Funkcja aktualizująca log z UART
function updateUartLog(data) {
const uartLog = document.getElementById('uartLog');
uartLog.innerHTML = data; // Zaktualizuj dane UART
}
</script>
</body>
</html>
"""
# Obsługuje żądanie /send i /get_uart_data
try:
query = cl.recv(1024)
if 'GET / HTTP/1.1' in str(query):
cl.send('HTTP/1.1 200 OK\r\n')
cl.send('Content-Type: text/html\r\n\r\n')
cl.send(response)
elif 'GET /send?command=' in str(query):
start = str(query).find('command=') + 8 # Przesunięcie o 8, aby zaczynało się od 'command='
end = str(query).find(' HTTP')
command = str(query)[start:end]
if command:
# Dekodowanie URL
decoded_command = url_decode(command)
print("Dekodowana komenda:", decoded_command)
response_from_printer = send_gcode(decoded_command)
cl.send('HTTP/1.1 200 OK\r\n')
cl.send('Content-Type: text/html\r\n\r\n')
cl.send(response_from_printer)
except Exception as e:
print("Błąd podczas obsługi zapytania:", e)
finally:
cl.close()
# Uruchomienie Wi-Fi i serwera
connect_wifi()
send_gcode('G91')
send_gcode('G28')
send_gcode('M140 S20')
send_gcode('M104 S20')
# Uruchomienie funkcji odczytu danych z UART w osobnym wątku (oddzielny wątek można stworzyć w bardziej zaawansowanej wersji)
#import _thread
#_thread.start_new_thread(read_uart_data, ())
# Uruchomienie serwera
web_server()