2018년 8월 4일 토요일

말로하는 3D 프린터 - 3편 (CuraEngine 으로 command line 에서 직접 슬라이싱 하기)

alexa 로 3D 프린터에게 명령을 내릴 수 있게 되었긴 한데, 단순히 autohome 을 한다던가 Move Z 를 하는 작업은 G28 이나 G1 Z10 과 같은 simple 한 gcode 만 던져 주면 그만이었는데 Printing 을 하는 것은 이런것과 달리 좀 더 복잡하고 머리를 써야 했다.

일단 프린팅을 하려면 STL 파일에서 slicing 을 해서 gcode 를 만들어야 한다. 이건 CURA 같은 슬라이싱 툴로 가능한데 말로하다보니 Application 을 손으로 만지는게 아니라 command line 에서 자동으로 (스크립트) 돌릴 수 있어야 했기에 새로운 공부가 필요했다.

이걸 하기 위해서는 CuraEngine 을 알아야 한다. 집에 Windows PC 가 없어서 Ubuntu 에서 작업을 하긴 했는데 Windows 에서도 같은 환경일 것 같다. 어쨌든 작업 내용을 적어보면, 일단, cura 를 다운로드 해야 한다. github 에서 소스를 다운로드 받아서 Compile 해서 사용할 수 도 있지만 ..
https://github.com/Ultimaker/Cura
굳이 그렇게 까지 할 필요까지야...

그냥 간편하게 설치 파일을 다운로드 한다. 
https://ultimaker.com/en/products/ultimaker-cura-software/list
Ubuntu 의 경우는 Linux 32bit 혹은 64bit 를 받으면 되는데, 어느 것을 다운로드 받던지 확장자가 AppImage 라는 파일을 받게 된다. 이것을 다운로드 하고 실행 가능 하게 해 줘야 cura 가 실행이 된다. 이런 식으로 말이다.

$ chmod a+x Cura-3.4.1.AppImage

이렇게 하고 마우스로 더블클릭을 하거나 터미널에서 실행해 주면 cura 가 실행이 된다.
그런데... 이렇게 하면 cura 를 키보드 마우스로만 동작시킬 수 있으니 내가 원하는 작업을 할 수 없다.
그런데 CuraEngine 은 또 어디에 있길래 꼴랑 Cura-3.4.1.AppImage 파일 하나만 있는 것인가.
AppImage 라는 것이 어떻게 동작하는지 살펴 봤더니 실행을 함과 동시에 /tmp/xxx 에 AppImage 를 mount 해서 동작을 하는 것이다. 흠..

$ mount |grep -i cura
/home/gouache/Desktop/Cura-3.4.1.AppImage on /tmp/.mount_KYZzSm type fuse.Cura-3.4.1.AppImage (ro,nosuid,nodev,relatime,user_id=1000,group_id=1000)

일단 난 /tmp/xxx 를 통째로 복사해 왔다.

$ cp -R /tmp/.mount_KYZzSm ~/cura-3.4.1
$ cd ~/cura-3.4.1
$ tree -d -L 4
.
└── usr
    └── bin
        ├── lib
        │   └── python3.5
        ├── plugins
        │   └── plugins
        ├── qml
        │   └── UM
        ├── qt
        │   ├── plugins
        │   └── qml
        └── resources
            ├── definitions
            ├── extruders
            ├── firmware
            ├── i18n
            ├── images
            ├── materials
            ├── meshes
            ├── qml
            ├── quality
            ├── setting_visibility
            ├── shaders
            ├── themes
            └── variants

여기에서  bin 디렉토리를 보면 CuraEngine 이 있음을 알 수 있다
그런데 이건 어떻게 사용하는 거지? 그래서 구글링을 해 보니 github 에 간단한 설명이 되어 있는 것을 찾을 수 있었다.
https://github.com/Ultimaker/CuraEngine

Running

Other than running CuraEngine from a frontend, such as Ultimaker/Cura, one can run CuraEngine from the command line. For that one needs a settings JSON file, which can be found in the Ultimaker/Cura repository. Note that the structure of the json files has changed since 2.1. In the corresponding branch of the Cura repository you can find how the json files used to be structured.
An example run for an UM2 machine looks as follows:
  • Navigate to the CuraEngine directory and execute the following
./build/CuraEngine slice -v -j ../Cura/resources/definitions/dual_extrusion_printer.def.json -o "output/test.gcode" -e1 -s infill_line_distance=0 -e0 -l "/model_1.stl" -e1 -l "fully_filled_model.stl" 
Run CuraEngine help for a general description of how to use the CuraEngine tool.
Set the environment variable CURA_ENGINE_SEARCH_PATH to the appropriate paths, delimited by a colon e.g.
CURA_ENGINE_SEARCH_PATH=/path/to/Cura/resources/definitions:/user/defined/path
보자보자 그러니까 커맨드 라인에서 이렇게 하면 된단 말이지?
$ CuraEngine slice -v -j <settings.json> -s <settingkey>=<value> -l <model.stl> -o <output.gcode>

model.stl 이나 output.gcode 는 직관적으로 이해 하겠는데 ..settings.json 은 뭐지?

대충 cura 화면에서 프린터 machine 설정이나 출력 Profile 설정 같은 것일 거라는 예상은 되는데 이것이 무엇인지 설명을 도통 찾을수가 없없다.
그래서 PC 에 있는 모든 파일을 뒤져봤다.
~/.config/cura/3.4
~/.local/share/cura/3.4
~/cura-3.4.1/usr/bin/resources

그랬더니 이렇게 3군데 디렉토리에서 json 비스무리한 설정 파일을 찾을 수 있었다.
뭐.. 찾긴 찾았는데... so what? 그래서 어쩌란 말인가. 어쩔 수 없이 하나씩 열어보면서 공부를 해야만 했다.

일단 구조상 cura 설치 후 최초 프린터 등록할 때 나오는 프린터 목록은 Cura/usr/bin/resources/definitions 에 있는 듯 하고, 이걸 실행해서 내가 변경하는 Cura 설정값들은 ~/.config 나 ~/.local 에 저장 되는 듯 하다.

그럼 익숙한 CR-10S 로 한번 추적해 볼까?
gouache@gouache-laptop:~/cura-3.4.1/usr/bin/resources/definitions$ ls creality_cr10*
creality_cr10.def.json  creality_cr10s4.def.json  creality_cr10s5.def.json

3가지 json 파일이 있는데 이중에서 내가 사용하는 cr10s5.def.json 을 살펴 보면 아래와 같다.
{
    "name": "Cartesio",
    "version": 2,
    "inherits": "fdmprinter",
    "metadata": {
        "visible": true,
        "author": "Scheepers",
        "manufacturer": "MaukCC",
        "file_formats": "text/x-gcode",

        "has_machine_quality": true,
        "has_materials": true,
        "has_machine_materials": true,
        "has_variant_materials": true,
        "has_variants": true,

        "variants_name": "Tool",
        "preferred_variant_name": "0.8 mm",
        "preferred_material": "generic_pla",
        "preferred_quality_type": "normal",

        "machine_extruder_trains":
        {
            "0": "cartesio_extruder_0",
            "1": "cartesio_extruder_1",
            "2": "cartesio_extruder_2",
            "3": "cartesio_extruder_3"
        },
        "platform": "cartesio_platform.stl",
        "platform_offset": [ -220, -5, 150],
        "first_start_actions": ["MachineSettingsAction"],
        "supported_actions": ["MachineSettingsAction"]
    },

    "overrides": {
        "machine_extruder_count": { "default_value": 2 },
        "material_diameter": { "default_value": 1.75 },
        "machine_heated_bed": { "default_value": true },
        "machine_center_is_zero": { "default_value": false },
        "gantry_height": { "default_value": 35 },
        "machine_height": { "default_value": 400 },
        "machine_depth": { "default_value": 270 },
        "machine_width": { "default_value": 430 },
        "machine_gcode_flavor": { "default_value": "RepRap (Marlin/Sprinter)" },
        "material_print_temp_wait": { "default_value": false },
        "material_bed_temp_wait": { "default_value": false },
        "prime_tower_enable": { "default_value": false },
        "prime_tower_wall_thickness": { "resolve": 0.7 },
        "prime_tower_size": { "value": 24.0 },
        "prime_tower_position_x": { "value": 125 },
        "prime_tower_position_y": { "value": 70 },
        "prime_blob_enable": { "default_value": false },
        "machine_max_feedrate_z": { "default_value": 20 },
        "machine_disallowed_areas": { "default_value": [
            [[215, 135], [-215, 135], [-215, 75], [215, 75]]
        ]},
        "machine_start_gcode": {
            "default_value": "\nM92 E159 ;2288 for V5 extruder\n\nM140 S{material_bed_temperature_layer_0}\nM104 T1 S120\nM104 T2 S120\nM104 T3 S120\n\nG21\nG90\nM42 S255 P13 ;chamber lights\nM42 S255 P12 ;fume extraction\nM204 S300 ;default acceleration\nM205 X10 ;default jerk\n\nM117 Homing Y ......\nG28 Y\nM117 Homing X ......\nG28 X\nM117 Homing Z ......\nG28 Z F100\nG1 Z10 F600\nG1 X70 Y20 F9000;go to wipe point\n\nM190 S{material_bed_temperature_layer_0}\n\nM117 Heating for 50 sec.\nG4 S20\nM117 Heating for 30 sec.\nG4 S20\nM117 Heating for 10 sec.\nM300 S1200 P1000\nG4 S9\n\nM117 purging nozzle....\nT0\nG92 E0;set E\nG1 E10 F100\nG92 E0\nG1 E-1 F600\n\nM117 wiping nozzle....\nG1 X1 Y24 F3000\nG1 X70 F9000\nG1 Z10 F900\n\nM104 T1 S21\nM104 T2 S21\nM104 T3 S21\n\nM117 Printing .....\n"
        },
        "machine_end_gcode": {
            "default_value": "; -- END GCODE --\nM117 cooling down....\nM106 S255\nM140 S5\nM104 T0 S5\nM104 T1 S5\nM104 T2 S5\nM104 T3 S5\n\nG91\nG1 Z1 F900\nG90\n\nG1 X20.0 Y260.0 F6000\nG4 S7\nM84\nG4 S90\nM107\nM42 P12 S0\nM42 P13 S0\nM84\nT0\nM117 Finished.\n; -- end of GCODE --"
        },
        "layer_height": { "maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" },
        "layer_height_0": { "maximum_value": "(0.8 * min(extruderValues('machine_nozzle_size')))" },
        "retraction_extra_prime_amount": { "minimum_value_warning": "-2.0" },
        "optimize_wall_printing_order": { "default_value": true },
        "material_initial_print_temperature": {"maximum_value_warning": "material_print_temperature + 15" },
        "machine_nozzle_heat_up_speed": {"default_value": 20},
        "machine_nozzle_cool_down_speed": {"default_value": 20},
        "machine_min_cool_heat_time_window": {"default_value": 5}
    }
}

내용은 긴데, 여기에서 중요한 것은 굵게 표시한 Inherits 과 Overrides 2개 이다.
CR10-S5 를 위해 모든 설정을 처음부터 다 적어 주지 않고 fdmprinter 라고 하는 대표격 프린터 설정을 상속해서 받아오고, Overrides 항목에서 CR10-S5 만을 위해 변경해야 하는 값들을 적어 준다.
따라서 CuraEngine 에서 이 json 값만 읽어 들이면 CR10-S5 설정으로 슬라이싱을 할 수 있는 것이다.

그런데 이 기본값들을 그냥 사용하지 않고 사용자가 자기 입맛에 맞춰서 Profile 을 변경하고 사용하는 것이니 그 값 또한 적용해 줘야 정확한 슬라이싱을 할 수 있다. 그걸 위한 옵션이 -s 인 것이다.
예제에서 처럼 '-s infill_line_distance=0' 을 주게 되면 infill_line_distance 값이 fdmprinter 도 아니고 cr10s5 도 아닌 내가 -s 로 준 값으로 슬라이싱 되게 된다.

여기서 한번 생각해 봐야 할 것은 -s 를 사용해서 매번 모든 profile 을 적어 줄 것인가? 아니면 json 파일에 직접 적어 주는게 편할 것인가 이다. 그것은 개인의 취향에 맞게 하면 되고 나는 json 파일에 직접 적어 주고 my-def.json 이라는 파일을 만들어 줬다.

자 이제 마지막으로 직접 슬라이싱을 해 보면,
$ usr/bin/CuraEngine slice -v -j my-def.json -l input.stl -o output.gcode

짜잔~ 성공!
그러니까.. 알렉사로 'start printing' 이라고 명령을 내리면,
CuraEngine 으로 slice 하는 스크립트를 실행하게 해 두고, 결과물로 output.gcode 가 나오면 그것을 octoprint 의 REST API 를 사용해서 출력을 하면 되는 것이다.

그럼 다음에는 octoprint REST API 로 출력하는 걸 해 볼까~

댓글 없음: