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.
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
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).
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)
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.
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);
}
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?
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?
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.