Motor shield to drive solenoid-type PUMP

Hardware:

  1. L293P-based, Arduino Motor Shield (Rev3)
  2. Arduino Due
  3. Solenoid-drive (pulse, metering) pump
    Task at Hand:
    I would like to drive a 12vdc solenoid pump at various pulse rates to control the metered flow of a liquid. Each pulse delivers about 0.25 ml of liquid. The solenoid within the pump has a return spring, meaning that there is no need for an inverted-current pulse to return it to its resting position.
    I would like to program the Arduino with a variable pulse rate (from about 1 pulse in 3 seconds, to about 2 pulse per second (ie., 0.3 Hz to 2 Hz). To be sure that the solenoid can move to the full length of its stroke, I would like to be able to set the pulse width.
    Would anyone have a suggestion for the best Library to use, and which functions to call upon?

What do you base the need for a library on? What will it be required to do? Seems like rather simple, direct, programming project.
You want to set the pulse width, which is just a matter of defining the number of milliseconds for the pin to be set high( or low, depending on the circuit).
How do you intend to set the pulse rate? How often will it change? Set in code or some external control? potentiometer, push buttons, etc?
Determine the current needed to operate the solenoid and build a MOSFET circuit to drive it, including a diode across the solenoid to dampen the pulse created when the solenoid is turned off.

1 Like

Hi, Paul, thanks for the fast reply!
I already own the Arduino Motor Shield, and thought I could make use of that rather than bread-boarding a FET or a bipolar power-transistor. I have made use of the Motor Shield a few years ago ( for testing some automotive servos) but have never tried using it as a solenoid driver.
PM

I doubt very much if any motor shield will make your solenoid work the way you want, but test it!

1 Like

Doesn't need a library. Connect your solenoid between CHA+ of the L293 and GND

const int DIR = 12;
const int SOLENOID = 3;

void setup()
{
  pinMode(DIR, OUTPUT);
  pinMode (SOLENOID, OUTPUT);
  
  // Turn solenoid off
  digitalWrite(DIR, HIGH);
  digitalWrite(SOLENOID, LOW);
}

void loop()
{
	// On for 500ms
	digitalWrite(SOLENOID, HIGH);
	delay(500);
	
	// Off for 2000ms
	digitalWrite(SOLENOID, LOW);
	delay(2000);
}  

That should turn it on and off continuously. You might need to change DIR to LOW instead of high to get this to work (not tested).

1 Like

How much current does the solenoid require? What is the minimum pulse width? Post a link to the pump's datasheet or the web page where you bought it.

According to the data sheet it draws between 0.5 and 1.5 Amps. That is likely to be a time-weighted average, according to the pulsing rate. The in-rush current is likely to be higher than that of course because the coil resistance (un-energized) is ~3 Ohms...making the inrush current ~4 Ampere
I am guessing that the pulse width is not critical; it just needs to be long enough to prevent bouncing or chattering. I am guessing about 100ms (about 10% of the highest pulse frequency).

Excellent! Thanks, I will gave that a try ASAP, and get back to you about the results!

The L293D's max continuous current rating is 600mA, you could parallel 2 channels if needed.

This simple Nano sketch might do what you want, (untested, I don't have your hardware).

unsigned long timer,
              pulseWidth = 100, // 100ms
              pulseInterval = 3333, // 0.3Hz, 500 = 2Hz
              elapsed;
const byte outPin = 13;


void setup()
{
  //Serial.begin(9600);
  pinMode( outPin, OUTPUT);
  elapsed = millis();
}

void loop()
{
  elapsed = millis() - timer;
  if(elapsed > pulseInterval)
  {
    timer += pulseInterval;
  }
  digitalWrite(outPin, elapsed < pulseWidth);  
} // end loop

The sketch you suggested does work! Thanks!
But...
Would you please suggest how this sketch be modified so that the output of both CH_A and CH_B are paralleled (as suggested by JCA34F, my solenoid probably might be drawing an excessive load (even if one applies time-weighted averaging)

You could parallel them in hardware by connecting both L293D inputs to the same Arduino outPin.

1 Like

This is the best option since it avoids accidental current "shoot-through". You don't want to source current through A, while B is sinking or you'll have a nice little fire on your hands if that persists long enough. Best case is you'll get weird, unexpected arduino resets from power glitching.

The problem is that with the motor shield, the pin configurations are already set so you can't bridge the outputs, so try this.

// On for 500ms
digitalWrite(SOLENOID, HIGH);
digitalWrite(11, HIGH);
delay(500);
	
// Off for 2000ms
digitalWrite(SOLENOID, LOW);
digitalWrite(11, LOW);
delay(2000);

This will turn pins 3 & 11 on/off in pretty close timing. Also you need to set pin 11 for Output.

Personally, I'd use a higher-rated driver, but I guess you can try this.

1 Like

So this is what I have done...doubled-up on the DIR and SOLENOID commands (one for each channel). I have yet to try this in practice.
There are extra lines as I am working toward displaying the pumping rate (fluid is a fuel), as a power rate, and to also incorporate a potentiometer to easily change the fuelling rate.
M

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// for use with the R3 Arduino Motor Shield (with L293P IC)
//  Connect your solenoid between CHA+ of the L293 output, and GND
// LIQUID CRYSTAL SETUP
LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27


// MOTOR SHIELD SETUP
const int DIRA = 12;
const int DIRB = 13;
const int SOLENOIDA = 3;
const int SOLENOIDB = 11;
float PULSERATE = 100; //pulses per minute or per 60000ms
float OFFTIME = (0.95*60000/PULSERATE);
float ONTIME = (0.05*60000/PULSERATE);
float LHV = (34.3*PULSERATE*28/100); //BTU PER HOUR AT GIVEN PULSERATE

float j = (PULSERATE/100);
void setup()
{
  lcd.init();  //initialize the lcd
  lcd.backlight();  //open the backlight
  lcd.setCursor(0, 0); // set the cursor to column 3, line 0
  lcd.print("Pwr= ");
  lcd.print(LHV);
  lcd.print("BTU/HR");  // Print a message to the LCD
  lcd.setCursor(0,1);
  lcd.print("PULSE=");
  lcd.print("potatot");
  lcd.print("/min");

  pinMode(DIRA, OUTPUT);
  pinMode(DIRB, OUTPUT);
  pinMode (SOLENOIDA, OUTPUT);
   pinMode (SOLENOIDB, OUTPUT);
  // Turn solenoid off
  digitalWrite(DIRA, HIGH);
  digitalWrite(DIRB, HIGH);
  digitalWrite(SOLENOIDA, LOW);
  digitalWrite(SOLENOIDB, LOW);
}

void loop()
{
	// On for ONTIME (ms)
	digitalWrite(SOLENOIDA, HIGH);
  digitalWrite(SOLENOIDB, HIGH);
	delay(ONTIME);
		// Off for OFFTIME (ms)
	digitalWrite(SOLENOIDA, LOW);
  digitalWrite(SOLENOIDB, LOW);
	delay(OFFTIME);
}
  


(courtesy Arduino Motor Shield Rev3 — Arduino Official Store)

Since this shield exposes all the pins with female headers, couldn't you physically jumper 3 to 11, leave 11 as an INPUT as far as the Uno is concerned, and then the pin 3 Arduino output would drive the motor shield's pin 11 input?

1 Like

Hmm. I think you have "lost me" on this. Is my suggested code not acceptable-- will it cause some sort of timing issues?

Wouldn't it be simpler to use a MOSFET like IRLB8721 and a couple of resistors instead of an obsolete motor drive that cannot handle the current you need?

Or a modern MOSFET motor driver (about $7), IF you are able to solder the connecting wires / pins.

https://www.pololu.com/product/4036

https://www.adafruit.com/product/3190

1 Like

This would be the right tool for the job.

Well, while the OP doesn't need to reverse the solenoid current, a single channel motor driver would be closer to "plug'n play" than MOSFET, resistors, diode,etc.