XController Spindle Direction Pin Reassignment

I have an XController driving an XCarve 750.

The 0-5V spindle speed pin is routed to an IOT relay for controlling the spindle, and the PWM pin is routed to a JTech Photonics laser controller. This works fine.

However, I wanted direct router speed control, so I bought a VHipe SuperPID AC motor controller.

The SuperPID will take either a PWM or 0-5V speed control signal, so no worries there. However, it also wants a +5V SPINDLE ENABLE signal.

The ugly hack to get that working would be to connect the MIST COOLANT output to the SuperPID SPINDLE ENABLE, and then add the mist coolant on/off gcode to any spindle control lines via the postprocessor. That will work, but it’s a terrible, terrible idea because it’s non-obvious from the code how to actually turn the spindle on or off.

So what I want looks like a custom GRBL build that assigns the SPINDLE DIRECTION to the mist coolant pin.

Looking in the GRBL code, I see this:

// By default on a 328p(Uno), Grbl combines the variable spindle PWM and the enable into one pin to help
// preserve I/O pins. For certain setups, these may need to be separate pins. This configure option uses
// the spindle direction pin(D13) as a separate spindle enable pin along with spindle speed PWM on pin D11.
// NOTE: This configure option only works with VARIABLE_SPINDLE enabled and a 328p processor (Uno).
// NOTE: Without a direction pin, M4 will not have a pin output to indicate a difference with M3. 
// NOTE: BEWARE! The Arduino bootloader toggles the D13 pin when it powers up. If you flash Grbl with
// a programmer (you can use a spare Arduino as "Arduino as ISP". Search the web on how to wire this.),
// this D13 LED toggling should go away. We haven't tested this though. Please report how it goes!
// #define USE_SPINDLE_DIR_AS_ENABLE_PIN // Default disabled. Uncomment to enable.

OK, so if I define this, D13 will become the enable pin, with the caveat that it will flash high during bootup, potentially starting the spindle. If I ensure to always power cycle the XController with the SuperPID turned off, this won’t be a problem. I can live with that.

It isn’t clear to me though if the XController has D13 wired to anything.

So if I turn off M7 by commenting out the define:

// Enables a second coolant control pin via the mist coolant g-code command M7 on the Arduino Uno
// analog pin 4. Only use this option if you require a second coolant control pin.
// NOTE: The M8 flood coolant control pin on analog pin 3 will still be functional regardless.
 #define ENABLE_M7 // Disabled by default. Uncomment to enable.

That should free up analogue pin 4.

This bit of code in spindle_control.c

void spindle_init()
{
  #ifdef VARIABLE_SPINDLE

    // Configure variable spindle PWM and enable pin, if requried. On the Uno, PWM and enable are
    // combined unless configured otherwise.
    SPINDLE_PWM_DDR |= (1<<SPINDLE_PWM_BIT); // Configure as PWM output pin.
    SPINDLE_TCCRA_REGISTER = SPINDLE_TCCRA_INIT_MASK; // Configure PWM output compare timer
    SPINDLE_TCCRB_REGISTER = SPINDLE_TCCRB_INIT_MASK;
    #ifdef USE_SPINDLE_DIR_AS_ENABLE_PIN
      SPINDLE_ENABLE_DDR |= (1<<SPINDLE_ENABLE_BIT); // Configure as output pin.
    #else
      SPINDLE_DIRECTION_DDR |= (1<<SPINDLE_DIRECTION_BIT); // Configure as output pin.
    #endif

    pwm_gradient = SPINDLE_PWM_RANGE/(settings.rpm_max-settings.rpm_min);

  #else

    // Configure no variable spindle and only enable pin.
    SPINDLE_ENABLE_DDR |= (1<<SPINDLE_ENABLE_BIT); // Configure as output pin.
    SPINDLE_DIRECTION_DDR |= (1<<SPINDLE_DIRECTION_BIT); // Configure as output pin.

  #endif

  spindle_stop();
}

specifically, the line

SPINDLE_DIRECTION_DDR |= (1<<SPINDLE_DIRECTION_BIT); // Configure as output pin.

sets the output pin

cpu_map.h has the following:

// Define spindle enable and spindle direction output pins.
  #define SPINDLE_ENABLE_DDR    DDRB
  #define SPINDLE_ENABLE_PORT   PORTB
  // Z Limit pin and spindle PWM/enable pin swapped to access hardware PWM on Pin 11.
  #ifdef VARIABLE_SPINDLE
    #ifdef USE_SPINDLE_DIR_AS_ENABLE_PIN
      // If enabled, spindle direction pin now used as spindle enable, while PWM remains on D11.
      #define SPINDLE_ENABLE_BIT    5  // Uno Digital Pin 13 (NOTE: D13 can't be pulled-high input due to LED.)
    #else
      #define SPINDLE_ENABLE_BIT    3  // Uno Digital Pin 11
    #endif
  #else
    #define SPINDLE_ENABLE_BIT    4  // Uno Digital Pin 12
  #endif
  #ifndef USE_SPINDLE_DIR_AS_ENABLE_PIN
    #define SPINDLE_DIRECTION_DDR   DDRB
    #define SPINDLE_DIRECTION_PORT  PORTB
    #define SPINDLE_DIRECTION_BIT   5  // Uno Digital Pin 13 (NOTE: D13 can't be pulled-high input due to LED.)
  #endif

  // Define flood and mist coolant enable output pins.
  #define COOLANT_FLOOD_DDR   DDRC
  #define COOLANT_FLOOD_PORT  PORTC
  #define COOLANT_FLOOD_BIT   3  // Uno Analog Pin 3
  #define COOLANT_MIST_DDR   DDRC
  #define COOLANT_MIST_PORT  PORTC
  #define COOLANT_MIST_BIT   4  // Uno Analog Pin 4

So I feel like taking the DDR, port and bit for mist cooling and assigning it to spindle direction should work?

Like this:

#define SPINDLE_DIRECTION_DDR   DDRC // using mist coolant DDR for SuperPID
    #define SPINDLE_DIRECTION_PORT  PORTC // using mist coolant port for SuperPID
    #define SPINDLE_DIRECTION_BIT   4  // Uno Analog port 4 - was D13

The two big unknowns are:

  1. Does the XController use D13 for anything?
  2. Does the code that sets a digital output high also work for an analog output?

Is there anyone around who understands how the XController is physically wired? Or docs published somewhere?

Digging deeper… I don’t see any code that assigns a variable voltage to the supposed 0-5V analog output on the XController - and the port itself is labelled 0-10V.

Is that just an enable switch with no actual variable voltage?

Did you ever arrive at an answer here? I’m in basically the exact same situation, trying to figure out if spindle speed is actually controllable to light up a Super-PID.