Working ZenXY configuration for FluidNC Pen/Laser Controller

Control Board: FluidNC Pen/Laser Controller, TMC2130

http://wiki.fluidnc.com/en/hardware/official/FluidNC_Pen_Laser_CNC_Controller_SPI

All credit to bdring and mitch from FluidNC for their patience and expertise in dealing with my interminable questions.

I hope to write up a more comprehensive how-to at some point. Until then, a couple brief notes below:

Help With Switch Problems | Wiki.js is a good point to get started with testing. CoreXY won’t allow you to single-axis home, so use $H instead of $HX.

It’s worth it to start out using fluidterm to connect over usb. I ran into some issues configuring and running over wifi and you can’t see all of the errors in the gui.

If you’re having issues/errors uploading files, try running install-fs.bat in the main folder. This will clean out the partition (and overwrite any existing files), but fixed all my upload problems. Unclear if this is a software or hardware problem.

If you have movement, but it’s backwards in one axis, switch your motors around (unplug motor A and plug it into motor B and vice versa).

When you finally get movement, you’ll need to measure how much the head actually moves and adjust the steps_per_mm under X and Y accordingly.

Config below:

board: FluidNC Pen/Laser 2130
name: TMC2130 ZenXY
meta:
stepping:
  engine: RMT
  idle_ms: 255
  pulse_us: 2
  dir_delay_us: 1
  disable_delay_us: 0
  segments: 6

axes:
  shared_stepper_disable_pin: gpio.13
  shared_stepper_reset_pin: NO_PIN
  x:
    steps_per_mm: 200.37
    max_rate_mm_per_min: 5000.000
    acceleration_mm_per_sec2: 25.000
    max_travel_mm: 440.000
    soft_limits: true
    homing:
      cycle: 2
      allow_single_axis: true
      positive_direction: false
      mpos_mm: 0.000
      feed_mm_per_min: 100.000
      seek_mm_per_min: 2000.000
      settle_ms: 500
      seek_scaler: 1.100
      feed_scaler: 1.100

    motor0:
      limit_neg_pin: gpio.39
      limit_pos_pin: NO_PIN
      limit_all_pin: NO_PIN
      hard_limits: false
      pulloff_mm: 1.000
      tmc_2130:
        step_pin: gpio.14
        direction_pin: gpio.12
        disable_pin: NO_PIN
        r_sense_ohms: 0.110
        run_amps: 0.250
        hold_amps: 0.250
        microsteps: 32
        toff_disable: 0
        toff_stealthchop: 5
        use_enable: false
        cs_pin: gpio.16
        spi_index: -1
        run_mode: StealthChop
        homing_mode: StealthChop
        stallguard: 0
        stallguard_debug: false
        toff_coolstep: 3

    motor1:
      limit_neg_pin: NO_PIN
      limit_pos_pin: NO_PIN
      limit_all_pin: NO_PIN
      hard_limits: false
      pulloff_mm: 1.000
      null_motor:

  y:
    steps_per_mm: 200.37
    max_rate_mm_per_min: 5000.000
    acceleration_mm_per_sec2: 25.000
    max_travel_mm: 880.000
    soft_limits: true
    homing:
      cycle: 1
      allow_single_axis: true
      positive_direction: false
      mpos_mm: 0.000
      feed_mm_per_min: 100.000
      seek_mm_per_min: 2000.000
      settle_ms: 500
      seek_scaler: 1.100
      feed_scaler: 1.100

    motor0:
      limit_neg_pin: gpio.36
      limit_pos_pin: NO_PIN
      limit_all_pin: NO_PIN
      hard_limits: false
      pulloff_mm: 1.000
      tmc_2130:
        step_pin: gpio.25
        direction_pin: gpio.26
        disable_pin: NO_PIN
        r_sense_ohms: 0.110
        run_amps: 0.250
        hold_amps: 0.250
        microsteps: 32
        toff_disable: 0
        toff_stealthchop: 5
        use_enable: false
        cs_pin: gpio.17
        spi_index: -1
        run_mode: StealthChop
        homing_mode: StealthChop
        stallguard: 0
        stallguard_debug: false
        toff_coolstep: 3

    motor1:
      limit_neg_pin: NO_PIN
      limit_pos_pin: NO_PIN
      limit_all_pin: NO_PIN
      hard_limits: false
      pulloff_mm: 1.000
      null_motor:

  z:
    steps_per_mm: 80.000
    max_rate_mm_per_min: 1000.000
    acceleration_mm_per_sec2: 25.000
    max_travel_mm: 1000.000
    soft_limits: false
    homing:
      cycle: 0
      allow_single_axis: true
      positive_direction: true
      mpos_mm: 0.000
      feed_mm_per_min: 50.000
      seek_mm_per_min: 200.000
      settle_ms: 250
      seek_scaler: 1.100
      feed_scaler: 1.100

    motor0:
      limit_neg_pin: NO_PIN
      limit_pos_pin: NO_PIN
      limit_all_pin: NO_PIN
      hard_limits: false
      pulloff_mm: 1.000
      null_motor:

    motor1:
      limit_neg_pin: NO_PIN
      limit_pos_pin: NO_PIN
      limit_all_pin: NO_PIN
      hard_limits: false
      pulloff_mm: 1.000
      null_motor:

kinematics:
  CoreXY:

spi:
  miso_pin: gpio.19
  mosi_pin: gpio.23
  sck_pin: gpio.18

sdcard:
  cs_pin: gpio.5
  card_detect_pin: NO_PIN

control:
  safety_door_pin: NO_PIN
  reset_pin: NO_PIN
  feed_hold_pin: NO_PIN
  cycle_start_pin: NO_PIN
  macro0_pin: NO_PIN
  macro1_pin: NO_PIN
  macro2_pin: NO_PIN
  macro3_pin: NO_PIN

coolant:
  flood_pin: NO_PIN
  mist_pin: NO_PIN
  delay_ms: 0

probe:
  pin: NO_PIN
  check_mode_start: true

macros:
  startup_line0:
  startup_line1:
  macro0:
  macro1:
  macro2:
  macro3:

start:
  must_home: true
  deactivate_parking: false
  check_limits: false

user_outputs:
  analog0_pin: NO_PIN
  analog1_pin: NO_PIN
  analog2_pin: NO_PIN
  analog3_pin: NO_PIN
  analog0_hz: 5000
  analog1_hz: 5000
  analog2_hz: 5000
  analog3_hz: 5000
  digital0_pin: NO_PIN
  digital1_pin: NO_PIN
  digital2_pin: NO_PIN
  digital3_pin: NO_PIN

arc_tolerance_mm: 0.002
junction_deviation_mm: 0.010
verbose_errors: true
report_inches: false
enable_parking_override_control: false
use_line_numbers: false
planner_blocks: 16
NoSpindle:
3 Likes

Anyone has a new board from dring, copy this config to a .yaml file and upload in the web ui?

I finally got my pen/laser fluid NC board wired up tonight and figured I’d try. Powered up, connected the wifi for the web interface and loaded the config file. I “set” it to the right config but couldn’t get too far. Ran a out of time tonight but looking forward to getting it up and running. Thanks!

1 Like

Ignore that last comment. I couldn’t sleep so went to messing with it more. I have movement and homing. I have some issues with it loosing connection at times and not sure why but I’m also somewhat “temporarily mounted” to the table. I need to do a few things to have it mounted closer to a finished system and test more. But I’m stoked that it’s currently moving!

1 Like

I have the pen/laser board from Dring, but that is the first part of my build. I just received it a couple days ago and it’s still in the box, lol. If you get yours working well, can you post build information, lessons learned, and pics?

Hi Phil. You may find it easier to build the mechanical portion of the table first before you dive into the the fluidNC aspect. I found troubleshooting much easier when I could tell it to move X 200mm and then physically watch it move (or not move).

My table isn’t finished yet (and probably won’t be for a while unfortunately). I was hoping to write up a bit of a beginners “guide” of sorts, but life seems to have other plans for me at the moment. Happy to (try to) answer any questions in the meantime.

One point to note: the above config will only work if you have the 2130 pen/laser board, the 2209 board needs an entirely different configuration.

1 Like

Any luck getting this working?

I’m new to all this and spent all night last night trying to get things working correctly with the TMC2209 board and FluidNC with the rig temporarily clamped down to my kitchen table. I can get it to move but not correctly. It doesn’t seem to be as simple as flipping one/both of the stepper connections as I think I’ve tried every combination possible and none of them solve the issue.

From my limited knowledge, the config file seems appropriately configured with corexy kinematics, TMC2209 UART pins set, home Y before X, home in the negative direction, but when I try to move using the FluidNC WebUI, I only get slight diagonal (not 45°) moves in two directions regardless of the direction chosen and homing refuses to go to the correct corner (-X+Y instead of -X-Y).

I’ll have to post my config file in the morning but I’ve been scouring google, youtube, forums, and read every page of the FluidNC wiki to help me diagnose the issue without much luck. I really like the yaml configuration and simplicity of FluidNC, but it’s so new that there isn’t a ton of info out there for it especially when it comes to CoreXY

Diagonal is really strange. 45 probably means you don’t have it set to corexy. If it was 90, but the wrong cardinal direction, then that would be a stepper that needed to be reversed, or your steppers would need to be swapped.

Another direction, like 22.5 means that the two steppers are moving a different distance. So maybe the steps per mm is wrong on one motor? Or maybe the microstepping is wrong on one motor?

In corexy, a 45 degree move is going to only rotate one motor. You could try manually sending a move like G0 X10 Y10 and make sure only one motor moves. Then try G0 X0 Y0 to reset and G0 X-10 Y10 to move the other motor. They should move the same distance.

If you can’t get it, post a video somewhere, post it in a new topic along with soms pictures of your build and we can probably work it out with you.

1 Like

Thanks for the response.

I did read similar that 45° is a sign that only one motor is moving, but as I said it’s more of a gentle slope up and down from the X axis. Both are configured at 100 steps/mm as I’m using the V1 hardware kit with the NEMA17 steppers, 16 microsteps, and 16t GT2 pulleys and this is what I calculated to be appropriate, though I did notice that the carriage thinks it’s moving much further than it really is so there is definitely work to be done there.

Probably won’t be able to work on it again until Wednesday, but I’ll try out these commands and see what happens and start a new topic in the troubleshooting section if I’m still stuck.

Transforms and coordinate frames are hard. I have some experience with them, so we could probably make a better guess if we had some good measurements of how far it’s actually going in each direction.

Accidentally getting one 20T pulley put in your order would do it too.

Are you basing your config file off of mine (in the first post)?

That could be part of the issue, the config for 2209s should be based off the example config on the wiki FluidNC - TMC2209_corexy config.

That aside, I found it useful to get some of my config troubleshooting done before connecting the motors to the motion platform.

I should give this a shot. My table is still running a very old config.

1 Like

Me too. Mine is 2130s and running grbl_esp32.

I’m working through it. I am not seeing default config for our older boards. I think I can piece one together.

I started with the ESP32_GRBL ZenXY config and ran it through Bart’s converter on his github to get the baseline yaml config. From there, I pieced the rest together using the TMC2209 example on the FluidNC wiki and lots of googling.

I also found some free time this morning to play around with it. Running the commands suggested by Jeff produced some really erratic movements. Sometimes the commands would work correctly, sometimes nothing would move, and sometimes the carriage would move in a completely random direction. Seeing this, I decided to swap out the ESP32 for a different one with a fresh FluidNC install, uploaded my same config.yaml, and everything started working correctly! I still need to swap motor wiring around as the X and Y axes are flipped (+X moves +Y and vice versa) but this is some solid progress! I can post the config here once I get it a bit more dialed-in in case future people want to work from an example.

Ryan, not sure if you’ve seen this but Bart has a tool to convert grbl_ESP32 configs to FluidNC configs:

Is there an easy way convert from Grbl_ESP32?

Yes, create a new issue at the Grbl_ESP32 repo. Select the translate template and follow the instructions. Behind the scenes, a magic robot will create a config file based on your machine definition file.

Yeah I have been messing with it. It did not seem to convert mine very well. I had to make some edits and it still is not homing right. I have only had a few short attempts but it all seems to do the right thing but like you said, sometimes it just doesn’t work. I swapped esp32 chips even.

name: TMC2209 Pen Laser
board: unknown

kinematics:
  CoreXY:

stepping:
  engine: RMT
  idle_ms: 250
  dir_delay_us: 0
  pulse_us: 3
  disable_delay_us: 0

axes:
  x:
    steps_per_mm: 100.000
    max_rate_mm_per_min: 8000.000
    acceleration_mm_per_sec2: 300.000
    max_travel_mm: 692.000
    soft_limits: false
    homing:
      cycle: 2
      mpos_mm: 0.000
      positive_direction: false
      settle_ms: 250.000
      seek_mm_per_min: 1000.000
      feed_mm_per_min: 500.000
      seek_scaler: 1.100
      feed_scaler: 5.000
    motor0:
      limit_all_pin: gpio.33
      hard_limits: false
      tmc_2209:
        direction_pin: gpio.26
        step_pin: gpio.12
        r_sense_ohms: 0.110
        addr: 0
        run_amps: 0.250
        hold_amps: 0.125
        microsteps: 16
        stallguard: 16
        stallguard_debug: false
        run_mode: StealthChop
        homing_mode: StealthChop
        use_enable: false
        uart:
          txd_pin: gpio.22
          rxd_pin: gpio.21
          baud: 115200
          mode: 8N1
    motor1:
      null_motor:
  y:
    steps_per_mm: 100.000
    max_rate_mm_per_min: 8000.000
    acceleration_mm_per_sec2: 300.000
    max_travel_mm: 1306.000
    soft_limits: false
    homing:
      cycle: 1
      mpos_mm: 0.000
      positive_direction: false
      settle_ms: 250.000
      seek_mm_per_min: 1000.000
      feed_mm_per_min: 500.000
      seek_scaler: 1.100
      feed_scaler: 5.000
    motor0:
      limit_all_pin: gpio.32
      hard_limits: false
      tmc_2209:
        direction_pin: gpio.25
        step_pin: gpio.14
        r_sense_ohms: 0.110
        addr: 1
        run_amps: 0.250
        hold_amps: 0.125
        microsteps: 16
        stallguard: 16
        stallguard_debug: false
        run_mode: StealthChop
        homing_mode: StealthChop
        use_enable: false
    motor1:
      null_motor:
  z:
    steps_per_mm: 100.000
    max_rate_mm_per_min: 1000.000
    acceleration_mm_per_sec2: 200.000
    max_travel_mm: 300.000
    soft_limits: false
    motor0:
      null_motor:
    motor1:
      null_motor:

spi:
  miso_pin: gpio.19
  mosi_pin: gpio.23
  sck_pin: gpio.18

sdcard:
  cs_pin: gpio.5

control:

coolant:
  delay_ms: 1000.000

probe:
  check_mode_start: false

macros:
  startup_line0: 
  startup_line1: 
  macro0: 
  macro1: 
  macro2: 
  macro3: 

start:
  must_home: false
  check_limits: false
  deactivate_parking: true

user_outputs:
arc_tolerance_mm: 0.002
junction_deviation_mm: 0.010
verbose_errors: false
report_inches: false
enable_parking_override_control: true
use_line_numbers: false

Mine will home, and let me move negative. Sometimes it will trip a hard limit, even though they are turned off. Other times once it homes Y it will not move anymore.

I am actually sitting down to look at it again now for a few minutes.

I think I need to get rid of stall guard. It must be tripping something. I did not have it originally, the converter added it.

1 Like

This has to be it. Why is it limit all, I need limit X limit Y. More google.

Mine also had Stallguard enabled after running through the conversion (though I obviously was starting with an example config and not something I’d been using previously). I read in their wiki that it isn’t recommended for CoreXY, but disabling it didn’t seem to make a difference with the erratic behavior in my case.

Also this is off topic, but I noticed that your config shows X=692mm and Y=1306mm. Is this for your table shown in the design docs? This, combined with me thinking my X and Y axes were flipped has me questioning whether I built mine 90° off.

Is this not correct?