Photon, MOSFET & Pump

Hey Particlers :wave:t3:

Long time listener, first time caller! :fist:t3::stuck_out_tongue_closed_eyes: thanks for keeping this informative forum and helpline alive!

I’ve been trying to get a water pump connected up my Photon via a MOSFET. Unfortunately, I’m fairly new to EE & cpp, so do excuse all my silly questions.

I have the following MOSFET (https://rover.ebay.com/rover/0/0/0?mpre=https%3A%2F%2Fwww.ebay.co.uk%2Fulk%2Fitm%2F372004306992) which is connected up to a desktop power supply for the moment and connected to a 12v Pump.

Now my test code is fairly simple, with a MOSFET util class and a simple ino runner using the the photon’s D0 pin:

#ifndef Mosfet_h
#define Mosfet_h
class Mosfet
{
    public:
        Mosfet(String name, int trigger_pin);
        void turnOn();
        void turnOff();
        bool status();
    private:
        int _trigger_pin;
        String _name;
        bool _status = false;
};
#endif
/*
Mosfet.cpp - Utility class for controlling a mosfet
Created by LAEG April 2019
*/
#include "application.h"
#include "Mosfet.h"

Mosfet::Mosfet(String name, int trigger_pin)
{
    _trigger_pin = trigger_pin;
    Serial.println("setup mosfet assign trigger pin");
    pinMode(_trigger_pin, OUTPUT);
    Serial.println("setup mosfet write low");
    digitalWrite(_trigger_pin, LOW); // set mosfet to off straight away by writing low
    Serial.println("setup mosfet off");
}

void Mosfet::turnOn()
{
    Serial.println("turnOn");
    digitalWrite(_trigger_pin, HIGH);
    _status = true;

}

void Mosfet::turnOff()
{
    Serial.println("turnOff");
    digitalWrite(_trigger_pin, LOW);
    _status = false;
}

bool Mosfet::status()
{
    return _status;
}
/*
 * Project MosfetTest
 * Description: Testing triggering a MOSFET
 * Author: LAEG
 * Date: April 2019
 */
#include "Particle.h"
#include "Mosfet.h"

Mosfet mosfet("test", D0);

// setup() runs once, when the device is first turned on.
void setup()
{
    Serial.begin(9600);
    Serial.println("setup");
}
// loop() runs over and over again, as quickly as it can execute.
void loop() 
{
    Serial.println("loop");
    mosfet.turnOn();
    Serial.printlnf("status: %s", mosfet.status());
    delay(6000);
    mosfet.turnOff();
    Serial.printlnf("status: %s", mosfet.status());
    delay(5000);
}

Now if I connect it all up and let the code run, I can see the LED come on the MOSFET but the pump doesn’t.

However, if I wait for it to cycle through again until it’s on and essentially tap the D0 pin thats connected to the MOSFET after a few taps it gets the motor going and I can sit the pin back in the breadboard and business as usual.

Can anyone help understand why I effectively have to pulse start it initially and then it runs fine after the first set of taps against D0? Am I doing something wrong either in my code or my wiring? Do I just need to switch to analogue and use PWM? Was I wrong in thinking I could use the MOSFET as just a straigh HIGH/LOW switch?

Wiring:
Pump + -> MOSFET OUT +
Pump - -> MOSFET OUT -
DPU -> MOSFET VIN +
DPU - -> MOSFET VIN -
D0 -> MOSFET TRIG/PWM
GND -> MOSFET GND

I’m open to any critique about my code, setup or for even buying cheap goods from eBay without a data sheet :stuck_out_tongue_closed_eyes:

Thanks in advance!

Cheers,
L

Are all your grounds tied together? I’m looking at the traces on your MOSFET boards and I can’t really tell the switch configuration (low-side, high-side, or some kind of push-pull configuration). It seems like the board ties together the uC ground and In- but not Out-. If all your grounds are not tied together it could cause some strange behaviour like you describe.

1 Like

Hey Tim,

Thanks for replying and apologises for my ignorant questions!

Do you mean tying the ground of the pump to the the board ground too?
I’ve previously tried the board/mosfet control ground to the DPU ground and didn’t find any change. Am I right I’m assuming that the pump ground will go to the DPU ground anyway, so by grounding the board ground to it that would accomplish what you’re asking?

@laexample, the board connects the motor power GND to the CPU GND so that’s not the issue. Breadboards can be finicky so you may need to move your jumper.

If you disconnect the jumper from D0 and connect it to Vusb (Vin) does the motor turn on immediately?

1 Like

Hey Paul,

Definitely a long time listener of yours :joy:! Honour to have you on my thread :green_heart:

So my first connection to VIN via my breadboard (and also subsequently directly to the VIN pin) it still needed these “misfires” in order to start up.

I’ve also tried switching it so I’m doing analogueWrites straight into 255 but no difference. So being the annoying lazy developer I am, I modified my MOSFET class to simulate these misfires and it works like a charm… strange, huh!

/*
Mosfet.cpp - Utility class for controlling a mosfet
Created by LAEG April 2019
*/
#include "application.h"
#include "Mosfet.h"

Mosfet::Mosfet(String name, int trigger_pin)
{
    _trigger_pin = trigger_pin;
    Serial.println("setup mosfet assign trigger pin");
    pinMode(_trigger_pin, OUTPUT);
    Serial.println("setup mosfet write low");
    // digitalWrite(_trigger_pin, LOW); // set mosfet to off straight away by writing low
    analogWrite(_trigger_pin, 0);
    Serial.println("setup mosfet off");
}

void Mosfet::turnOn()
{
    Serial.println("turnOn");
    analogWrite(_trigger_pin, 255);
    analogWrite(_trigger_pin, 0);
    analogWrite(_trigger_pin, 255);
    analogWrite(_trigger_pin, 0);
    analogWrite(_trigger_pin, 255);
    // digitalWrite(_trigger_pin, HIGH);
    _status = true;

}

void Mosfet::turnOff()
{
    Serial.println("turnOff");
    // digitalWrite(_trigger_pin, LOW);
    analogWrite(_trigger_pin, 0);
    _status = false;
}

bool Mosfet::status()
{
    return _status;
}

Although I don’t know why I need to send 3. So let’s take it down to two - no luck, back to 3 it’s dead again… weird. Pulse VIN or D0 with the pin and it’s back online. Switch back to D0 via breadboard, runs normally, take the pin out and put it back in - goes into the weird state.

When I see the code execute the turn on block, my DPU is stuck at a constant ~4.4v & ~0.48A however this is usual of it starting and then dropping down to somewhere around 12v & ~.29A after the pump is running.

Am I doing something out of the ordinary / just being a complete EE n00b?

Cheers for everyone’s help and suggestions so far!

Luke

If you are not comfortable on either side (software and hardware) it may be best to focus on one side and keep the other to the bare minimum with least potential of failure there.

In your case I’d focus on the HW side and postpone getting tangled up in creating CPP classes.

Try with a minimal sketch like this

void setup() {
  pinMode(D7, OUTPUT);
  pinMode(D0, INPUT_PULLUP);
}

void loop() {
  static int prevState = -1;
  int currState = digitalRead(D0);
  if (currState == prevState) return; // only act on change
  prevState = currState;
  delay(100);                         // poor man's debounce

  digitalWrite(D7, !currState);
}

Connect your trigger pin to D7 (visual feedback about the expected state) and provide the desired state via D0 (inverted) pulling to GND.

Then you can focus on the HW side without any distraction.
Once you have that sorted, you can focus on the SW side.


Just a side note: pinMode() is not safe to be called in a constructor.
You should move most of your constructor code into a Mosefet::begin() function and call that from setup().

1 Like

I agree that this should be the first step, but then connect it to 3V3 pin, since that is what his I/O pin D0 is going to output at a high level.

1 Like

Thanks @ScruffR :slight_smile: I’ll stop with the fanboy thank yous, but I’m sure you can guess what I would have said.

Just to double check I’ve understood what you’re saying: connect D0 to the trigger/D7, while also connecting D0 to GND?

D7 -> TRIG
D7 -> D0
D0 -> GND

Cheers,

P.s. thank you for the advice on the begin method too! Any reading I can do to understand why it’s not safe?

1 Like

Not quite. D7 and D0 are not connected physically but only via program logic.
When you pull D0 to GND then D7 should go HIGH, the on-board LED on and your motor should start spinning. Once you let D0 go back to its PULLUP state D7 LED should go out and the motor stop.

While you were following the community discussions you may have heard about the non-deterministic order of execution of global/static object constructors (across independent modules).
Since functions like pinMode() require some system objects to be fully instantiated before it's safe to use them, using it in any constructor that may be executed before that may lead to an SOS panic reset.

1 Like

@ScruffR Thanks for the great explanation.

So I gave your code and wiring a try, LED comes on both the board and the MOSFET, but as per usual the motor just makes a little whirring sound.

However, something happened when I tried moving the board and it kicked in again. So reset the Photon and then it was back to dead with high A (~.48A) & low v’s (~4.5v). I then decided what happened if I tried the “misfire pulsing” on the D0 ground and hey presto it kicked back in.

Super strange.

So I decided to take it back to bare bones and remove the Photon, put the GND to the VIN - and TRIG to the VIN +… still needs a couple of taps before it gets underway. Does this signal dodgy hardware?

Thanks for everyone’s help so far! Cheers

I’d assume the motor runs fine connected directly to your desktop power supply? If it won’t start correctly without the Photon (connecting the SIG pin on the MOSFET board to ground), it’s entirely possible that the board simply can’t handle the current it’s “rated” for. When you source parts from Ebay/Chinese vendors, it’s very unfortunately common for them to advertise completely exaggerated specs!

You may have tried this already, but the Tinker app is a great way to check your circuit because you can control PWM on the motor pin through the phone app.

Also, if you post pictures of your wiring, it can help people give better advice :wink: