<p>From the <a href="https://github.com/MarlinFirmware/Marlin/" rel="nofollow noreferrer">sources of Marlin</a> 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.</p>

<p>Starting in <a href="https://github.com/MarlinFirmware/Marlin/blob/ed86550061ab94f10dd1d310c994bd74db582740/Marlin/Marlin_main.cpp" rel="nofollow noreferrer">Marlin_main.cpp</a> and searching for <code>106</code> (or <code>106</code> on the Marlin GitHub website) will lead you to the sources of the execution of the <code>M106</code> command. Below a snippet of <code>M106</code> and <code>M107</code> is shown. The reason for <code>M107</code> to be there becomes clear later.</p>

<pre>
#if FAN_COUNT &gt; 0

  /**
   * M106: Set Fan Speed
   *
   *  S&lt;int&gt;   Speed between 0-255
   *  P&lt;index&gt; Fan index, if more than one fan
   *
   * With EXTRA_FAN_SPEED enabled:
   *
   *  T&lt;int&gt;   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 &lt; FAN_COUNT) {
      #if ENABLED(EXTRA_FAN_SPEED)
        const int16_t t = parser.intval('T');
        if (t &gt; 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 &lt; FAN_COUNT) fanSpeeds[p] = 0;
  }

#endif // FAN_COUNT &gt; 0
</pre>

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

<p>Continuing the search by finding how <code>FAN_COUNT</code> is set (using the search on GitHub for the Marlin repository) leads to file <a href="https://github.com/MarlinFirmware/Marlin/blob/ed86550061ab94f10dd1d310c994bd74db582740/Marlin/Conditionals_post.h" rel="nofollow noreferrer">Conditionals_post.h</a>. An interesting part is:</p>

<pre>
/**
 * 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
</pre>

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

<p>Let's now search for <code>HAS_FANx</code>; in the same file you will find:</p>

<pre>
// 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)
</pre>

<p>Now we are getting into clear water! This codes hints to <code>FAN1_PIN</code> and <code>FAN2_PIN</code>. If you look into you pin layout file, e.g. <a href="https://github.com/MarlinFirmware/Marlin/blob/1.1.x/Marlin/pins_RAMPS.h" rel="nofollow noreferrer">pins_RAMPS.h</a> you see that that are the pin constants that need to be defined, actually <code>FAN1_PIN</code> is e.g. set if you choose an "EFF" configuration (Hotend, Fan0, Fan1), e.g. <code>#define FAN1_PIN  RAMPS_D8_PIN</code>.</p>

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

<p>E.g. pin 4 is not a used pin number (and an analog output pin). Don't forget that the pin you choose cannot directly run a fan, it should be used to schedule a MOSFET.</p>

<p>Note that a dual external fan header <a href="http://www.geeetech.com/wiki/index.php/Reprap_Ramps1.4_RRD_Fan_Extender" rel="nofollow noreferrer">"Reprap Ramps1.4 RRD Fan Extender"</a> exists, this describes using the D6 and D11 pins. Further investigation led to a 3D.SE posting using this fan header: <a href="https://3dprinting.stackexchange.com/q/5220/5740">"How to configure Marlin to enable auto-fans with dual extruder"</a>.</p>

CC BY-SA 4.0
2018-08-03T18:57:25.883Z
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
CC BY-SA 4.0
2018-08-03T19:01:52.713Z
@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
CC BY-SA 4.0
2018-08-02T21:19:06.627Z
2019-01-16T12:57:48.403Z
2019-01-16T12:57:48.403Z
0scar
<p>I am using RAMPS 1.4 with Marlin. With Marlin, you can control a large number of fans with the <code>M106 P&lt;fan index&gt;</code> 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.</p>

CC BY-SA 4.0
2018-08-02T16:37:10.620Z
Have you looked at https://reprap.org/wiki/File:Arduinomegapololushieldschematic.png?
OyaMist
CC BY-SA 4.0
2018-08-02T21:23:06.700Z
You can control up to 3 fans with `M106 P<fan index>`, see my answer below.
0scar
<marlin><ramps-1.4><octoprint><print-fan>
Controlling more fans with RAMPS board
vega
# Controlling more fans with RAMPS board

(Asked by: username_0 on 2018-08-02)

I am using RAMPS 1.4 with Marlin. With Marlin, you can control a large number of fans with the `M106 P` 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.

**Tags:** marlin, ramps-1.4, octoprint, print-fan
> **Comments:**
> **username_1**: Have you looked at https://reprap.org/wiki/File:Arduinomegapololushieldschematic.png?  
> **username_2**: You can control up to 3 fans with `M106 P<fan index>`, see my answer below.  

---

## 1 answers

### Answer by username_2 on 2018-08-02. Score: 4 | Accepted answer

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   Speed between 0-255
   *  P Fan index, if more than one fan
   *
   * With EXTRA_FAN_SPEED enabled:
   *
   *  T   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  .
E.g. pin 4 is not a used pin number (and an analog output pin). 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".

> **Comments:**
> **username_0**: 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).  
> **username_2**: @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!  

---

