I am using RAMPS 1.4 with Marlin. With Marlin, you can control a large number of fans with the M106 P<fan index> command. I'd like RAMPS to control some additional fans, independent of layer fan. Are there free pins on RAMPS 1.4 to do that? Otherwise, could I setup the RAMPS board to send a command to a separate Arduino? I also have Octoprint if that makes it easier.

up vote 2 down vote accepted

From the sources of Marlin you can find how may fans you can use, even if you're not a coder it should be doable. From there you can find how to set the pins for the fans, provided that there are free unused and exposed (so that you do not have so solder directly to the microprocessor). First find how many fans are possible.

Starting in Marlin_main.cpp and searching for 106 (or 106 on the Marlin GitHub website) will lead you to the sources of the execution of the M106 command. Below a snippet of M106 and M107 is shown. The reason for M107 to be there becomes clear later.

#if FAN_COUNT > 0

  /**
   * M106: Set Fan Speed
   *
   *  S<int>   Speed between 0-255
   *  P<index> Fan index, if more than one fan
   *
   * With EXTRA_FAN_SPEED enabled:
   *
   *  T<int>   Restore/Use/Set Temporary Speed:
   *           1     = Restore previous speed after T2
   *           2     = Use temporary speed set with T3-255
   *           3-255 = Set the speed for use with T2
   */
  inline void gcode_M106() {
    const uint8_t p = parser.byteval('P');
    if (p < FAN_COUNT) {
      #if ENABLED(EXTRA_FAN_SPEED)
        const int16_t t = parser.intval('T');
        if (t > 0) {
          switch (t) {
            case 1:
              fanSpeeds[p] = old_fanSpeeds[p];
              break;
            case 2:
              old_fanSpeeds[p] = fanSpeeds[p];
              fanSpeeds[p] = new_fanSpeeds[p];
              break;
            default:
              new_fanSpeeds[p] = MIN(t, 255);
              break;
          }
          return;
        }
      #endif // EXTRA_FAN_SPEED
      const uint16_t s = parser.ushortval('S', 255);
      fanSpeeds[p] = MIN(s, 255U);
    }
  }

  /**
   * M107: Fan Off
   */
  inline void gcode_M107() {
    const uint16_t p = parser.ushortval('P');
    if (p < FAN_COUNT) fanSpeeds[p] = 0;
  }

#endif // FAN_COUNT > 0

Looking at this code, the first thing (actually the first line, #if FAN_COUNT > 0, already hints to that) that catches your attention is constant FAN_COUNT. Apparently the software knows how much fans are defined! Interesting! How does it know that! This piece of code ends just after handling the M107 command (line #endif // FAN_COUNT > 0), hence it is displayed here.

Continuing the search by finding how FAN_COUNT is set (using the search on GitHub for the Marlin repository) leads to file Conditionals_post.h. An interesting part is:

/**
 * Up to 3 PWM fans
 */
#if HAS_FAN2
  #define FAN_COUNT 3
#elif HAS_FAN1
  #define FAN_COUNT 2
#elif HAS_FAN0
  #define FAN_COUNT 1
#else
  #define FAN_COUNT 0
#endif

So depending on HAS_FANx (where x denotes 0, 1 or 2) you can have multiple fans, up to 3 in total! Cool, learned something in the process. :)

Let's now search for HAS_FANx; in the same file you will find:

// Other fans
#define HAS_FAN0 (PIN_EXISTS(FAN))
#define HAS_FAN1 (PIN_EXISTS(FAN1) && CONTROLLER_FAN_PIN != FAN1_PIN && E0_AUTO_FAN_PIN != FAN1_PIN && E1_AUTO_FAN_PIN != FAN1_PIN && E2_AUTO_FAN_PIN != FAN1_PIN && E3_AUTO_FAN_PIN != FAN1_PIN)
#define HAS_FAN2 (PIN_EXISTS(FAN2) && CONTROLLER_FAN_PIN != FAN2_PIN && E0_AUTO_FAN_PIN != FAN2_PIN && E1_AUTO_FAN_PIN != FAN2_PIN && E2_AUTO_FAN_PIN != FAN2_PIN && E3_AUTO_FAN_PIN != FAN2_PIN)

Now we are getting into clear water! This codes hints to FAN1_PIN and FAN2_PIN. If you look into you pin layout file, e.g. pins_RAMPS.h you see that that are the pin constants that need to be defined, actually FAN1_PIN is e.g. set if you choose an "EFF" configuration (Hotend, Fan0, Fan1), e.g. #define FAN1_PIN RAMPS_D8_PIN.

What is left for you to do is find an unused pin of your micro-controller and set the FAN2_PIN with #define FAN2_PIN <a free pin number>.

E.g. pin 22 is not a used pin number, but cannot find that one exposed. Pins 20 and 21 could be used. Don't forget that the pin you choose cannot directly run a fan, it should be used to schedule a MOSFET.

Note that a dual external fan header "Reprap Ramps1.4 RRD Fan Extender" exists, this describes using the D6 and D11 pins. Further investigation led to a 3D.SE posting using this fan header: "How to configure Marlin to enable auto-fans with dual extruder".

  • Very interesting! Thanks for teaching how to fish! I also see in pins_RAMPS.h that pin 4 is available for filament runout sensor or laser, which I don't use. So I could also use that I guess for a fan (via MOSFET). – vega Aug 3 at 18:57
  • @vega You're welcome, excellent that you used the post to find an unused pin (from here I don't know what your setup looks like and what is used or not), just configure the pin to the #define FAN1_PIN if you are running 2 fans in total and use a MOSFET and you're good to go! – 0scar Aug 3 at 19:01

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.