diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..4261f59 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,68 @@ +# PyCharm-specific files +.idea/ +.shelf/ +workspace.xml +httpRequests/ +dataSources/ +dataSources.local.xml +Bed_level_5m.iml +misc.xml +modules.xml +inspectionProfiles +vcs.xml + + +# Virtual environments +.venv/ +env/ +venv/ + +# Python-specific +__pycache__/ +*.py[cod] +*$py.class + +# Environment and dependency management +*.env +.env.* + +# Logs and temporary files +*.log +*.tmp +*.swp +*.swo + +# Compiled files +*.pyc +*.pyo +*.pyd +*.so +*.dll + +# Jupyter Notebook checkpoints +.ipynb_checkpoints/ + +# Coverage reports +.coverage +htmlcov/ +*.cover +*.coverage.* + +# Distribution and packaging +dist/ +build/ +*.egg-info/ +.eggs/ + +# Testing +*.pytest_cache/ +.tox/ +.nox/ + +# Docker +*.env.docker +docker-compose.override.yml + +# Operating system files +.DS_Store +Thumbs.db diff --git a/README.md b/README.md index 3cbac07..fbb0f75 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,8 @@ # Flashforge-bed-level Flashforge 5M advanture bed leveling visualisation + +F5m does not have an ideal bed level from the factory. +This program can help you to adjust bed level by adjusting screw in the corners +I used Python 3.9 + +![](pic.png) \ No newline at end of file diff --git a/pic.png b/pic.png new file mode 100644 index 0000000..04c7f39 Binary files /dev/null and b/pic.png differ diff --git a/printer.cfg b/printer.cfg new file mode 100644 index 0000000..a44344e --- /dev/null +++ b/printer.cfg @@ -0,0 +1,80 @@ +[include printer.base.cfg] + +[extruder] +step_pin: eboard:PB14 +dir_pin: !eboard:PB15 +enable_pin: !eboard:PB12 +microsteps: 16 +rotation_distance: 4.7 +nozzle_diameter: 0.400 +filament_diameter: 1.750 +heater_pin: eboard:PA8 +sensor_type: Generic 3950 +sensor_pin: eboard:PA0 +#control: pid +#pid_Kp: 20.109 +#pid_Ki: 1.943 +#pid_Kd: 52.031 +min_temp: -100 +max_temp: 350 +min_extrude_temp: 100 +pressure_advance:0.035 +pressure_advance_smooth_time: 0.040 +max_extrude_only_distance:1500.00 +max_extrude_cross_section:1000 + +[verify_heater extruder] +max_error: 290 +check_gain_time:200 +hysteresis: 10 +heating_gain: 10 + +[tmc2209 extruder] +uart_pin: eboard:PB10 +interpolate:True +run_current: 0.8 +hold_current:0.8 +sense_resistor:0.10 +#stealthchop_threshold: 999999 + +[input_shaper] +#shaper_type_x: mzv +#shaper_freq_x: 47.4 +#shaper_type_y: mzv +#shaper_freq_y: 46.2 + +# Save Mesh Data # + +#*# <---------------------- SAVE_CONFIG ----------------------> +#*# DO NOT EDIT THIS BLOCK OR BELOW. The contents are auto-generated. +#*# +#*# [bed_mesh MESH_DATA] +#*# version = 1 +#*# points = +#*# -1.095000, -1.070000, -1.097500, -1.172500, -1.220000 +#*# -0.887500, -0.932500, -1.005000, -1.050000, -1.175000 +#*# -0.762500, -0.887500, -0.995000, -1.062500, -1.110000 +#*# -0.750000, -1.020000, -1.095000, -1.130000, -1.160000 +#*# -1.015000, -1.330000, -1.365000, -1.307500, -1.327500 +#*# x_count = 5 +#*# y_count = 5 +#*# mesh_x_pps = 3 +#*# mesh_y_pps = 3 +#*# algo = bicubic +#*# tension = 0.20000000000000001 +#*# min_x = -105.0 +#*# max_x = 105.0 +#*# min_y = -105.0 +#*# max_y = 105.0 +#*# +#*# [input_shaper] +#*# shaper_type_x = 2hump_ei +#*# shaper_freq_x = 65.2 +#*# shaper_type_y = mzv +#*# shaper_freq_y = 51.8 +#*# +#*# [extruder] +#*# control = pid +#*# pid_kp = 33.297 +#*# pid_ki = 4.723 +#*# pid_kd = 58.686 diff --git a/printer.py b/printer.py new file mode 100644 index 0000000..a8a6c3f --- /dev/null +++ b/printer.py @@ -0,0 +1,135 @@ +# import re +import numpy as np +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import Axes3D +from matplotlib.colors import LinearSegmentedColormap +import matplotlib.image as mpimg +from matplotlib import cm +from matplotlib import use as plot_in_window + +# кладём в корень что ли +FILE_PATH = 'printer.cfg' + +# принудительно заставляем рисовать в окне TkAgg - это соотвествующий бэкенд +plot_in_window('TkAgg') + +def load_data(path): + mesh_data = [] + row = [] + line_count = 0 + + with open(path, 'r') as file: + in_points_section = False + for line in file: + if 'points =' in line: + in_points_section = True + continue + #нашли mesh - считываем + elif in_points_section: + # нам нужны только эти 5 строк из файла + if not line.startswith("#*#"): + break + if line_count > 4: + return mesh_data + #оставляем без всякой фигни в начале + line = line.strip().replace(',','').split(' ')[3:] + try: + row = [float(x) for x in line] + finally: + line_count += 1 + if row: + mesh_data.append(row) + + if not mesh_data or line_count < 5: + print("Файл не тот!") + + return False + + + +def calculate_max_delta_absolute(data): + max_height = np.max(data) + min_height = np.min(data) + max_delta = abs(max_height - min_height) + return max_delta + +def main_draw(data): + # Создание сетки для координат + x = np.arange(data.shape[1]) + y = np.arange(data.shape[0]) + X, Y = np.meshgrid(x, y) + + # Создание цветового градиента + colors = ["#523a28", "#a47551", "#d0b49f", "#e4d4c8", "#f9f1f0"] + # cmap = LinearSegmentedColormap.from_list("custom_cmap", colors) + # cmap = cm.copper + # cmap = cm.gist_earth + cmap = cm.coolwarm + # Создание 3D-графика + # Ширина 10 дюймов, высота 6 дюймов + fig = plt.figure(figsize=(10, 6)) + ax = fig.add_subplot(111, projection='3d') + surf = ax.plot_surface(X, Y, data, cmap=cmap, edgecolor='white', rstride=1, cstride=1) + + + + # Добавление цветовой шкалы + fig.colorbar(surf, shrink=1, aspect=6) + + # Настройка осей + ax.set_xlabel('X ось') + ax.set_ylabel('Y ось') + ax.set_zlabel('Высота') + + # Поворот графика вокруг оси Z + ax.view_init(elev=70, azim=-120) + + # Загрузка изображения + #img = mpimg.imread('F5MTable.png') + + # Добавление изображения в левый нижний угол + + xmin, xmax = 0, -0.05 # Для X координат + ymin, ymax = -1, -0.05 # Для Y координат + + # Преобразование матрицы в строку для отображения без скобок + # data_str = data_str.replace('[','').replace(']','').replace(',','') # Удаляем квадратные скобки и запятые + + # Преобразование сетки высот в строку для отображения без скобок и с выравниванием + data_str = '' + data_rounded = np.round(data, 2) + data_rounded_mirr = data_rounded[::-1] + for row in data_rounded_mirr: + # Форматирование каждого элемента с выравниванием по правому краю в поле шириной 8 символов + row_str = ''.join(f'{value:>8.2f}' for value in row) + data_str += row_str + '\n' + + + # Задаем заголовок фигуры + fig.suptitle('Mesh level F5M Adv', fontsize=16) # Устанавливаем заголовок + # Установка угла обзора + ax.view_init(elev=70, azim=-135) + + delta = calculate_max_delta_absolute(data) + # Установка заголовка графика с матрицей высот + ax.text2D(-0.6, 0.4, f'MAX \u2206 - {delta} мм', color='red', transform=ax.transAxes, fontsize=12, verticalalignment='top') + + ax.text2D(-0.6, 0.3, f'Карта высот:\n ----------------------------------------------------------', \ + transform=ax.transAxes, fontsize=10, verticalalignment='top') + ax.text2D(-0.6, 0.2, f'{data_str}', transform=ax.transAxes, fontsize=10, verticalalignment='top') + ax.text2D(1.2, -0.1, f'автор - @kozyayur', transform=ax.transAxes, fontsize=10, verticalalignment='top',color='blue') + + # Установка заголовка окна + fig.canvas.manager.set_window_title('Mesh level F5M Adv') + + # Выводим + #ax.imshow(img, aspect='auto', extent=(xm in, xmax, ymin, ymax), zorder=10) + plt.show(block=True) + +if __name__ == "__main__": + data= load_data(FILE_PATH) + if data: + data = np.array(data) # вот они роднинькие + main_draw(data) + else: + print("Smth wrong") diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..aa094d9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,2 @@ +numpy +matplotlib