Кремень FMZ Реклама
Kremen FMHM Реклама

Добавление коэффициента компенсации геометрических особенностей и сохранения в EEPROM, в автоматической калибровки на Marlin

Erzay 3D
Идет загрузка
Загрузка
15.01.2019
3487
12
Техничка

Подпишитесь на автора

Подпишитесь на автора, если вам нравятся его публикации. Тогда вы будете получать уведомления о его новых статьях.

Отписаться от уведомлений вы всегда сможете в профиле автора.

3
Добавление коэффициента компенсации геометрических особенностей и сохранения в EEPROM, в автоматической калибровки на Marlin

Добрый день, Уважаемые читатели!

Я хотел бы продолжить тему с разработками и процессами этапов разработок относящихся к 3D принтерам, все работы проходили/ проходят в рамках текущего стартап проекта 'Erzay3D'. Сниппет кода является продолжением статьи Добавление RGB Светодиодную ленту к Marlin .

Выравнивание неровностей на печатающей платформе является, пожалуй, наиболее важным из оперативных действий необходимых для любого FDM 3D принтера особенно если говорить о дельта конструкции. Невозможно собрать абсолютно идентичный принтер с другим, при условии что сборка является ручной. Поэтому настройка уровня стола является индивидуальной для каждого 3D принтера. Если печатная платформа не отрегулирована по уровню, то печатающая головка может находиться высоко от площадки построения в целом или одного из краёв, в связи с чем, подавайемый пластик будет находится слишком высоко от поверхности печати и вызывать плохое сцепление и точность, или печатающая головка может находится слишком близко, что может вызвать кляксы пластика на печатной поверхности и затор экструдера или же деформации сопла, прогревающей поверхности вплоть до выхода из строя функционала принтера. Существует несколько способов настройки уровня стола, самый популярный это ручная настройка, подкручивая вручную винты, тем самым изменяя положения стола, но для идеальной настройки потребуется множество итераций и подобную процедуру нужно делать не один раз. В этой статье будет рассмотрена автоматическая калибровка реализованная с помощью датчиков и математических расчётов микроконтроллера. Функционал данной системы имеется и в прошивки «Marlin». С помощью четырёх датчиков и печатающей платформы (3 датчиков служат стартом для начала движения тяговых и один находится на самой печатающей головке) и ранее заданных параметров, алгоритм распределяет точки по площади печатающей платформы и отправляет печатающую головку в данные координаты. С помощью датчика установленного на печатающей головки, в каждой точке за меряется глубина от старта движения тяговых, таким образом строится матрица значений, затем совершается их интерполяция и отклонения записывается в буферную память. Исходя из этих значений при печати учитываются эта вновь сформированная плоскость для печати с учётом её неровностей.

Нашей команде удалось выявить некоторые недочёты переделать эту систему :

- выполнять автоматическую калибровку перед каждой печати очень неудобно и на это тратиться лишнее время, такой способ был выбран по причине того что у датчиков определяющих старт движения тяговых имеются погрешности от 200 до 400 микрон (при механических датчиках), и разумеется если после выполнения калибровки отправить оси на парковку то погрешность в построенной матрицы будет в 200-400 микрон, а эти значения плачевны для печати. Мы же нашли выход из этой проблемы, установив оптические датчики на парковку тяговых с погрешность в 10-20 микрон, установив индукционный датчик на печатающую головку использующий для проб глубин точек с погрешностью в 1-5 микрон( на сегодняшний день ушли от индукционного датчика, в связи с проблемами описанными далее, на наш взгляд датчик давления отрабатывает функционал лучше). Посадили движение тяговых на линейные направляющие, что уменьшило вибрацию и увеличило точность что не немаловажно влияет на погрешности измерений. И установили запись параметров автоматический калибровки в энергонезависимую память что позволит выполнять калибровку раз в 10-20 печатей и ненужно её запускать перед каждой печатью, это позволило значительно упростить и улучшить данный процесс;

- также выяснилось одна из проблем в погрешности самой калибровки, это связано с тем что датчик калибровки находится далеко от центра сопла, возможно есть и другие причины, они пока нами не выявлены. Решение было на программном уровне в добавлении коэффициентов погрешности плоскостей x и y. Данное значение достаточно установить один раз и в будущем при калибровке коэффициент будет учитываться;

- столкнулись с проблемами выхода калибровки за приделы стола, для этого были адаптированы программные энд стопы выхода печати за область стола( на текущей момент в UBL калибровки такой проблемы нету).

Включение/отключение этой функции производится по специальному G-коду. Если эта функция включена, после каждой автокалибровки (отправка команды «G29») все параметры рабочей поверхности будут автоматически сохраняться в энергонезависимую память и в дальнейшем использоваться перед каждой печатью (исключает необходимость запуска автокалибровки перед каждой печатью). Полный сброс осуществляется при условии очистки энергонезависимой памяти (либо при отключении этой функции по специальному G-коду). :

1. «G29» Сохранение калибровки на ЕЕПРОМ происходит автоматически после выполнения команды ;

2. «М700» используется для управления сохранением калибровки на энергонезависимую память EEPROM ;

3. «М700 R» — обнулить/сбросить текущую калибровку в памяти и калибровку в EEPROM;

4. «М700 O» — вывести в консоль текущие параметры калибровки;

5. «М700 P» — вывести в консоль сохраненные на EEPROM параметры калибровки;

6. «М215» — информация о текущих коэффициентах (Установка значения «М215 Х 0.0 Y 0.0» либо по одной оси (либо только М215 Х0.0 либо М215 Y0.0));

7. «М215 S» — сохранить в ЕЕПРОМ текущие данные в оперативной памяти;

8. «М215 L» — загрузить коэффициенты из ЕЕПРОМ;

9. «М215 R» — сбросить коэффициенты в ЕЕПРОМ до 0.0;

10. «M215 D» — загрузить заводские настройки коэффициентов (индивидуально для каждой модели).

Также команды М500, М501 и т. д. работают для этого коэффициента точно так же, как и на все другие параметры.

Сниппет из файла configuration _ store . cpp . Предназначение кода – сохранение, вывод в консоль и сброс уникальных для принтера настроек, хранящихся на энергонезависимой памяти EEPROM (светодиоды, автоматическая калибровка стола).



#ifdef LED_ENABLE

CONFIG_ECHO_START;

SERIAL_ECHOLNPGM('LEDs in Printing mode:');

SERIAL_ECHOPAIR('Red ', LED_mode [PRINTING] [RED]);

SERIAL_ECHOPAIR(' Green ', LED_mode [PRINTING] [GREEN]);

SERIAL_ECHOPAIR(' Blue ', LED_mode [PRINTING] [BLUE]);

SERIAL_EOL;

CONFIG_ECHO_START;

SERIAL_ECHOLNPGM('LEDs in Waiting mode:');

SERIAL_ECHOPAIR('Red ', LED_mode [WAITING] [RED]);

SERIAL_ECHOPAIR(' Green ', LED_mode [WAITING] [GREEN]);

SERIAL_ECHOPAIR(' Blue ', LED_mode [WAITING] [BLUE]);

SERIAL_EOL;

CONFIG_ECHO_START;

SERIAL_ECHOLNPGM ('LEDs in Heating mode are set according to the nozzle temperature');

SERIAL_ECHOLNPGM ('M580 [M] RXXX GXXX BXXX //M is for mode (W - Watinig, P - Prining). All parameters should be from 0 to 100 and integers.');

SERIAL_EOL;

#endif

SERIAL_ECHOPAIR ('Z coefficient is ', coefficient_z);

}

void save_coefficient_to_EEPROM (float coeff) {

int address = 445;

EEPROM_UPDATE_VAR(address, coeff);

}

float loadcoefficient () {

int address = 445;

float coeff;

EEPROM_READ_VAR(address, coeff);

return coeff;

}

void resetcoefficient () {

int address = 445;

float zeroo = 0.0;

EEPROM_UPDATE_VAR(address, zeroo);

}

float loaddefaultcoefficient () {

coefficient_z = Z_COEFFICIENT;

return coefficient_z;

}

#ifdef LED_ENABLE

void save_LED_eeprom () { //сохраняем данные о светодиодах на еепром.

int address = 444; //IMPORTARNT!!! V27 of EEPROM!!!

for (int i = 0; i <= 2; i++)

{

for (int ii = 0; ii <= 2; ii++)

{

EEPROM_WRITE_VAR(address, LED_mode [i] [ii]); // 0 - heating, 1 - printing, 2 - waiting, 0 - red, 1 - green, 2 - blue

}

}

}

void load_LED_eeprom () {

int address = 444; //IMPORTARNT!!! V27 of EEPROM!!!

for (int i = 0; i <= 2; i++)

{

for (int ii = 0; ii <= 2; ii++)

{

EEPROM_READ_VAR(address, LED_mode [i] [ii]); // 0 - heating, 1 - printing, 2 - waiting, 0 - red, 1 - green, 2 - blue

if (LED_mode [i] [ii] < 0)

{

LED_mode [i] [ii] = 0;

}

}

}

}

void LED_eeprom_update () {

int address = 444; //IMPORTARNT!!! V27 of EEPROM!!!

for (int i = 0; i <= 2; i++)

{

for (int ii = 0; ii <= 2; ii++)

{

EEPROM_UPDATE_VAR(address, LED_mode [i] [ii]); // 0 - heating, 1 - printing, 2 - waiting, 0 - red, 1 - green, 2 - blue

}

}

}

#endif

#ifdef CALIB_TO_EEPROM

void save_calibration_EEPROM (float abl_array[][ABL_GRID_POINTS_X]) { //Следи за адресом, здесь адрес может варьироваться

int address = 460;

for (int i=0; i < ABL_GRID_POINTS_X; i++)

{

for (int ii=0; ii < ABL_GRID_POINTS_X; ii++)

{

EEPROM_WRITE_VAR (address, abl_array[i][ii]);

}

}

SERIAL_ECHOLNPGM('Calibration values have been saved on EEPROM');

SERIAL_EOL;

}

void load_calibration_EEPROM (float abl_array[][ABL_GRID_POINTS_X]) { //Следи за адресом, здесь адрес может варьироваться

int address = 460;

for (int i=0; i < ABL_GRID_POINTS_X; i++)

{

for (int ii=0; ii < ABL_GRID_POINTS_X; ii++)

{

EEPROM_READ_VAR (address, abl_array[i][ii]);

if (abl_array[i] [ii] < -5.0 || abl_array[i][ii] > 5.0)

{

abl_array[i] [ii] = 0.1;

}

}

}

SERIAL_ECHOLNPGM('Saved calibration values have been loaded from EEPROM');

SERIAL_EOL;

}

void reset_calibration_EEPROM (float abl_array[][ABL_GRID_POINTS_X]) {

int address = 460;

float number = 0.10;

for (int i=0; i < ABL_GRID_POINTS_X; i++)

{

for (int ii=0; ii < ABL_GRID_POINTS_X; ii++)

{

EEPROM_UPDATE_VAR (address, number);

}

}

planner.abl_enabled = false;

SERIAL_ECHOLNPGM('Calibration EEPROM has been reset');

SERIAL_EOL;

}

void print_EEPROM_calibration () {

int address = 460;

float abl_array[ABL_GRID_POINTS_X][ABL_GRID_POINTS_X] = {{-1}};

for (int i=0; i < ABL_GRID_POINTS_X; i++)

{

for (int ii=0; ii < ABL_GRID_POINTS_X; ii++)

{

EEPROM_READ_VAR (address, abl_array[i][ii]);

SERIAL_ECHO(abl_array[i][ii]);

SERIAL_ECHOPGM(' ');

}

SERIAL_EOL;

}

SERIAL_ECHOLNPGM('Saved calibration values have been loaded from EEPROM');

SERIAL_EOL;

}

#endif // !DISABLE_M503

#endif //!CALIB_TO_EEPROM

Сниппет из файла marlin _ main . cpp . Различные функции и структуры в этом файле выполняют разные функции, в том числе вывод в консоль данных об уникальных конфигурациях 3D машины, применение коэффициента компенсации геометрических особенностей принтера, обработка данных автоматической калибровки рабочей поверхности принтера (в т. ч. Восстановление, загрузка из энергонезависимой памяти и т. д.), отключение программных эндстопов для оптимизации алгоритма автокалибровки рабочей поверхности.

#ifdef CALIB_TO_EEPROM

inline void gcode_M700() {

//G-код для обработки автоматического сохранения

//автокалибровки в энергонезависимую память

if (code_seen('R')) { reset_calibration_EEPROM (bed_level_grid); reset_bed_level();}

if (code_seen('S')) save_calibration_EEPROM (bed_level_grid);

if (code_seen('L')) { my_gcode_G29 (); }

if (code_seen('P')) print_EEPROM_calibration ();

if (code_seen('O')) output_current_calibration ();

if (code_seen('B')) report_current_position ();

}

#ifdef LED_ENABLE

inline void gcode_M580 () { //вывод в консоль и прием настроек светодиодной ленты

char bad_command1 [] = 'Wrong commad. Type M580 [M] Rxxx Gxxx Bxxx for M=mode, R,G,B = Red, Green, Blue. For example, to change the Printing mode LED color type: M580 P R50 G9 B100.';

char bad_command2 [] = 'Or you may change just one or two colors by typing for example: M580 P G9. The numbers should be integers from 0 to 100.';

int temp_LED_status = 0;

char LED_mode_printing [] = 'Printing';

char LED_mode_waiting [] = 'Waiting';

char *pLED_temp_mode = NULL;

int buff_red, buff_green, buff_blue = 0;

SERIAL_ECHO_START;

if (code_seen('.')) {SERIAL_ECHO(bad_command1); SERIAL_EOL; SERIAL_ECHO(bad_command2); SERIAL_EOL; return ;}

if (code_seen('W') || code_seen('P')) {

if (code_seen('W')) temp_LED_status = WAITING;

if (code_seen('P')) temp_LED_status = PRINTING;

} else {SERIAL_ECHO(bad_command1); SERIAL_EOL; SERIAL_ECHO(bad_command2); SERIAL_EOL; return ;}

switch (temp_LED_status) {

case WAITING:

pLED_temp_mode = LED_mode_waiting;

break;

case PRINTING:

pLED_temp_mode = LED_mode_printing;

break;

}

if (code_seen ('R') || code_seen ('G') || code_seen ('B')) {

if (code_seen ('R')) {

buff_red = code_value_int ();

if (buff_red < 0 || buff_red > 100)

{

SERIAL_ECHO(bad_command1);

SERIAL_EOL;

SERIAL_ECHO(bad_command2);

SERIAL_EOL;

return ;

}

}

if (code_seen ('G')) {

buff_green = code_value_int ();

if (buff_green < 0 || buff_green > 100)

{

SERIAL_ECHO(bad_command1);

SERIAL_EOL;

SERIAL_ECHO(bad_command2);

SERIAL_EOL;

return ;

}

}

if (code_seen ('B')) {

buff_blue = code_value_int ();

if (buff_blue < 0 || buff_blue > 100)

{

SERIAL_ECHO(bad_command1);

SERIAL_EOL;

SERIAL_ECHO(bad_command2);

SERIAL_EOL;

return ;

}

}

} else {SERIAL_ECHO(bad_command1); SERIAL_EOL; SERIAL_ECHO(bad_command2); SERIAL_EOL; return ;}

if (code_seen ('R')) LED_mode [temp_LED_status] [RED] = buff_red;

if (code_seen ('G')) LED_mode [temp_LED_status] [GREEN] = buff_green;

if (code_seen ('B')) LED_mode [temp_LED_status] [BLUE] = buff_blue;

SERIAL_ECHO('Colors of LEDs in the mode ');

SERIAL_ECHO(*pLED_temp_mode);

SERIAL_ECHO(' were changed. Now they are: Red ');

SERIAL_ECHO(LED_mode [temp_LED_status] [RED]);

SERIAL_ECHO(' Green ');

SERIAL_ECHO(LED_mode [temp_LED_status] [GREEN]);

SERIAL_ECHO(' Blue ');

SERIAL_ECHO(LED_mode [temp_LED_status] [BLUE]);

SERIAL_EOL;

}

#endif //LED_ENABLE

inline void gcode_M215 () { //работа с коэффициентом компенсации геометрических //особенностей принтера

if (code_seen('Z')) {

coefficient_z = code_value_float();

SERIAL_ECHO_START;

SERIAL_ECHOLNPAIR ('Z coefficient has been changed to ', coefficient_z);

} else

#ifdef EEPROM_SETTINGS

if (code_seen('S')) {

save_coefficient_to_EEPROM (coefficient_z);

SERIAL_ECHO_START;

SERIAL_ECHOLNPAIR ('Z coefficient has been written to EEPROM ', coefficient_z);

}

else if (code_seen('L')) {

coefficient_z = loadcoefficient ();

SERIAL_ECHO_START;

SERIAL_ECHOLNPAIR ('Z coefficient has been read from EEPROM ', coefficient_z);

}

else if (code_seen('R')) {

resetcoefficient ();

coefficient_z = loadcoefficient ();

SERIAL_ECHO_START;

SERIAL_ECHOLNPAIR ('Z coefficient is ', coefficient_z);

}

else if (code_seen('D')) {

coefficient_z = loaddefaultcoefficient ();

SERIAL_ECHO_START;

SERIAL_ECHOLNPAIR ('Z coefficient is ', coefficient_z);

SERIAL_ECHOLN ('Use M215 S or M500 to save it to EEPROM');

} else

#endif

{

SERIAL_ECHO_START;

SERIAL_ECHOLNPAIR ('Current Z coefficient is ', coefficient_z);

}

}

#ifdef LED_ENABLE //инициализация светодиодов при пуске принтера

pinMode(REDPIN, OUTPUT);

pinMode(GREENPIN, OUTPUT);

pinMode(BLUEPIN, OUTPUT);

#ifdef EEPROM_SETTINGS

load_LED_eeprom ();

#endif

LED_status = WAITING;

change_LED_status ();

#endif

void handle_status_leds(void) { //выбор режима работы светодиодов, таймер включения

//float max_temp = 0.0;

if (millis() > next_status_led_update_ms) {

next_status_led_update_ms += LCD_UPDATE_INTERVAL+100; // Update every 0.5s

change_LED_status ();

bool isheating = isHeatingFlag ();

if (isheating)

{

LED_status = HEATING;

return ;

}

if ((planner.movesplanned()) && ((thermalManager.current_temperature [0] + 3) > thermalManager.target_temperature [0]) && ((thermalManager.current_temperature [0] - 3) < thermalManager.target_temperature [0]))

{

LED_status = PRINTING;

if (mytimer_should_turnoff == false) {mytimer_should_turnoff = true;}

return ;

}

else { LED_status = WAITING; if (mytimer_should_turnoff == false) {mytimer_should_turnoff = true;} }

}

}

#endif

Спустя время Marlin обновил систему калибровки с некоторыми совпадениями наших доработок, неизвестно совпадение ли это)

Всем спасибо за внимание, команда ООО 'Робокинетика'!

Патент программы для ЭВМ №2018611221

Подпишитесь на автора

Подпишитесь на автора, если вам нравятся его публикации. Тогда вы будете получать уведомления о его новых статьях.

Отписаться от уведомлений вы всегда сможете в профиле автора.

3
Комментарии к статье