Why are my fans always spinning?

So had an issue earlier about reading rpm from fans with the 33Iot board. That was solved. The rpm readin works fine now. I am using a N-FET to turn on or off fans, which also works.

But the thing I noticed is that when fans are off... they still spin... low rpm, even arduino doesnt read any rpm from them but they are on, probably running on very low power. I am confused in a way that even if I unplug the GND wire, they still on. So somehow its getting gnd from the signal wire?? (insert confused image here) The signal wire is connected to the 3v3 with a 10k resistor and to the pin D2 (and D3 for the second fan). I am confused probably by my lack of understanding of what is happening.

Here is a small schematic of my circuit:

The GND from the 12v battery is shared with the arduino.
So in a nutshell, Telling the FET to turn on, works... fan spins at 1300 rpm... When I turn off fans... they "turn off" even no reading of rpm is read by the board... but the fans are still spinning (much lower rpm).. what am i missing?

If I unplug the usb powering the board, I still see the green light on it dimming or flashing... not sure where its getting power from... 12v still connected on fan.

Here is my code. Dont think this issue is related but before someone asks :slight_smile: Its not perfect but it works.

#include <WiFiNINA.h>
#include "thingProperties.h"
#include "DHT.h"
#define DHTTYPE DHT22   // DHT 22  (AM2302)

#define dataPin 5 // Defines pin number to which the sensor is connected
#define relayPin 4
DHT dht(dataPin, DHTTYPE); 

int NbTopsFan1; int NbTopsFan2; int Calc1; int Calc2;

int hallsensor1 = 3; 
int hallsensor2 = 2; 

typedef struct{
//Defines the structure for multiple fans and their dividers 
char fantype;
unsigned int fandiv; }fanspec;

fanspec fanspace[3]={{0,1},{1,2},{2,8}}; char fan = 2;

String location = "Enclosure";
char ssid[] = SECRET_SSID;                // your network SSID (name)
char pass[] = SECRET_PASS;                // your network password (use for WPA, or use as key for WEP)

int status = WL_IDLE_STATUS;             // the Wi-Fi radio's status
int ledState = LOW;                       //ledState used to set the LED
unsigned long previousMillisInfo = 0;     //will store last time Wi-Fi information was updated
unsigned long previousMillisLED = 0;      // will store the last time LED was updated
const int intervalInfo = 5000;            // interval at which to update the board information

void rpm1 ()
{ NbTopsFan1++;}

void rpm2 ()
{ NbTopsFan2++;}

void setup() {
  pinMode(hallsensor1, INPUT);
  pinMode(hallsensor2, INPUT);
  pinMode(relayPin, OUTPUT);
  digitalWrite(relayPin, LOW);
  attachInterrupt(digitalPinToInterrupt(3), rpm1, RISING); 
  attachInterrupt(digitalPinToInterrupt(2), rpm2, RISING); 
  // attempt to connect to Wi-Fi network:
  while (status != WL_CONNECTED) {
    Serial.print("Attempting to connect to network: ");
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(ssid, pass);
    // wait 10 seconds for connection:
    Serial.println("You're connected to the network");

void loop() {
    NbTopsFan1 = 0;
    NbTopsFan2 = 0;
    Calc1 = ((NbTopsFan1 * 60)/fanspace[fan].fandiv);
    Calc2 = ((NbTopsFan2 * 60)/fanspace[fan].fandiv);
    rpmfan1 = Calc1; rpmfan1 = rpmfan1 + " RPM";
    rpmfan2 = Calc2; rpmfan2 = rpmfan2 + " RPM";
    curhum = dht.readHumidity();
    curtemp= dht.readTemperature();
    unsigned long currentMillisLED = millis();
    int intervalLED = WiFi.RSSI() * -10;
    if (currentMillisLED - previousMillisLED >= intervalLED) {
      previousMillisLED = currentMillisLED;
      if (ledState == LOW) {
          ledState = HIGH;
      } else {
          ledState = LOW;
      digitalWrite(LED_BUILTIN, ledState);
    Serial.println("Network Information:");
    IPAddress ip = WiFi.localIP();
    Serial.print("IP Address: ");
    varIP = String(ip[0]) + String(".") + String(ip[1]) + String(".") + String(ip[2]) + String(".") + String(ip[3])  ; 
    Serial.print("SSID: ");
    long rssi = WiFi.RSSI();
    Serial.print("Signal strength (RSSI): ");
    Serial.print(rssi); varRSSI = rssi; varRSSI = varRSSI + "dbm";
    Serial.print("Humidity: ");
    Serial.print("Temp: ");
    if (curtemp > 40){
      digitalWrite(relayPin, HIGH);
      fanRelay = true;
      Serial.println("Fans are ON");
      Serial.print("Fan 1: "); Serial.print(Calc1, DEC); Serial.println(" RPM");
      Serial.print("Fan 2: "); Serial.print(Calc2, DEC); Serial.println(" RPM");
      digitalWrite(relayPin, LOW);
      fanRelay = false;
      Serial.println("Fans are OFF");
      Serial.print("Fan 1: "); Serial.print(Calc1, DEC); Serial.println(" RPM");
      Serial.print("Fan 2: "); Serial.print(Calc2, DEC); Serial.println(" RPM");
    delay(2000); //Delay 2 sec.

Why are you connecting the GNDs of the fans to the GATE of the N channel MOSSFET ?

Well to my understanding... thats to turn them on? They do need ground to work

You need a MOSFET that can be controlled by 3.3V


LarryD's correct. But to add something to help you understand; The MosFet has a built in diode. It is this diode that allowed you to "turn on" the fans, but it will not allow you to turn them off.

I am using FQP30N06L (TO-220).. arent these able to handle 3.3?

So since im using the 33 IOT powered through USB... I could enable 5v by bridging the pads correct?
Would that make it work?

Yes but change to LarryD's first connection diagram.

I wish I was good enough to read it properly... what would I need to change exactly? add a 150R resistor from gate pin to the D4 pin? My 5v is not connected anywhere

No problem.

You will have to go to the MosFet spec to identify the Gate, Source and Draing.

  1. Connect your fan grounds to the battery - (aka common, ground)

Now I have to ask, what signal are the fans expecting? 5V, 12V ??
or just connect them to common?

Sure? Does it even compile? Where are "rpmfan1" and "rpmfan2" declared?

Fans are 12V. They have a + (connected to battery), a gnd (connected to drain) and a signal wire (used to read my rpm). I thought "turning on the GND" from the mosfet was the ideal option.

It does. They are in thingsproperties.h

Ah, got it. Apologies!

So i have bridged the 5v. Tested it on my current setup (no rpm monitoring) and it only turns fans ON and off based on temp... and that worked properly now.

Now on my other board I am testing with the rpm reading... they turn on fine, and seem to turn off but like I said, they keep spinning at a lower rpm. They are getting power somehow.

I have unplugged the GND wire of the fans from the drain of the mosfet... behold.. they are still spinning. Only the positive connected to 12v battery and the signal wire (like in my diagram, connected to D2 and D3 (2 fans) and that line is also connected to 3v3 with a 10k resistor. I also tried to the 5v (since now its on) and still same behavior. So how is it getting GND from the signal wire? if I unplug the signal, fan stop.

So the GND is not coming from the mosfet but from signal? That where lies my confusion :slight_smile:

Use a High side switch:

Ok if i understand correctly mosfets (think i read that somewhere)... n channel are used for negative/gnd signal and p channel are used for using positive? or can i just use the 12v pos on the n channel instead of gnd?

The P channel MOSFET shown in post 16 is used as a positive switch to your load.

You must ensure the V(gs) maximum rating of the MOSFET is not exceeded.

If there is a possibility it will, use a circuit similar to this:

Your supply voltage must match that of your load.

Thanks for your inputs LarryD. I am having a hard time understanding this schematic. Mind you I am a noob in all this, tinkering for fun and learn at same time.

Is it possible to make it simpler for me (until i understand schematics better lol). All I want to do is turn on the fan when it reaches a certain temp and turn it off when its under that target temp. That part seems to work fine when I am not checking for RPM. When I do check for RPM and the fans are off, it gets GND from the signal wire for some reason as the fans are still spinning, much slower but spinning. When I dont have the wires to check for RPM, this does not happen.

The power issue doesnt seem to be from Me using a N Channel Mosfet to turn on the GND when needed. I bridged the 5v on 33 iot to enable 5v and on my board without any rpm checks, fan turn on and off properly (and completely). So the mosfet does close and open fine.

On my board with the rpm check (schematic in original post), even if I unplug the gnd wires of the fan from the drain, they still spin (only pos connected to battery and signal connected to D2 with a 10k from 3v3). Also if I unplug the usb to the nano, it stays on. So the signal wire is causing me issues I think or I am not wired properly.

On my breadboard where I am doing tests with the rpm checks.. If i do not plug in the signal wire... fan starts and stops properly.

Mind you checking RPM is a nice to have and not necessary for my project... just the best way to confirm if my fans are spinning when checking remotely. But I am at a point I want to understand why its not working and fan keep spinning.

Yes the signal wire can cause this problem you are exercising.
There can be backfeededing thru the Arduino internal protection diodes on the RPM inputs on the Arduino.

If you insist on using RPM monitoring, to prevent this you must switch the positive (+) to the motor, not the negative.

This is about as basic as it gets, what part is confusing, we’ll explain.