Pump controller/flow meter for river model, with code

In response to questions about coding and memory elsewhere in the forum ( http://arduino.cc/forum/index.php/topic,78857.0, I've posted functions and code for a pump controller we have developed at Little River Research & Design. In a day or two I'll add more, we've developed a very nice PCB to go with this that holds Arduino, LCD, and components to drive a small pump and use the power sent to the pump to measure flow rates. Description here, followed by code.

(Forum won't let me put all in one post, code in next reply).

Steve Gough www.emriver.com

Em2x digital pump controller (Em2x DPC, “Alix Controller”) software function outline S. Gough Little River Research & Design, www.emriver.com Revised Nov 13, 2011 to add “calibrate” function to menu.

Control input: Optical rotary encoder, quadrature, with push switch. Interface: LCD display, 16 x 2, and maybe a small piezo beeper Power input: Desktop brick switching regulated 12V, 3.5 A capacity. Output: 12 volt PWM to pump.

Basic operation

The flow controller controls flow via 12V PWM to a small pump. We will calibrate flow output from the pump to the PWM value from the Arduino (Duemilanove until stock runs out, then Arduino Pro or UNO). This might have to be done for each unit. The controller displays information about flow on the LCD, and also provides a menu for various functions. An LED on the PCB board provides verification of power input, another LED varies in brightness with duty cycle.


  1. States. There are four states.

a. Startup. On power up (plug-in), controller displays welcome message, sets duty cycle to zero (if this doesn’t happen automatically) and then increases duty cycle to prime the pump and provide a low flow, which verifies to users that things are working, and goes to normal operation: b. Normal, users simply control flow and read values on the LCD.

c. Menu, invoked by a press of the switch, in which users can select from options:

i. Exit menu (for accidental menu enter of change of mind); this should have a 20 second or so default time out to return to normal operation.

ii. Reset flow and time counter with “are you sure?” verification.

iii. Run hydrographs; at least six choices, hydrograph 1,2, etc.

d. Hydrograph run, in which the controller automatically varies flow making a bell-shaped curve of increasing and then decreasing flow to simulate floods. These will last from ~3 minutes to hours. On initiation, flow/time counter is reset, and flow values/totals appear as in normal operation. There are two options for running hydrographs:

i. Program six or so hydrographs into the unit using array values, this is very easy to do. The method and code I used for my (Steve’s) stab at it worked very well.

ii. Allow users to select several hydrograph features from menus. This would require a rather complicated menu/submenu system and we should probably stick to the first option for now. Features would include:

  1. Total hydrograph time.
  2. Flow peak value (e.g. 180 ml/s)
  3. Time to peak.
  4. Time at peak (i.e. how long the flow remains at peak value.

  5. User interface -- flow control and display:

a. Power up and reset are done by unplugging the unit, which resets the Aurduino and LCD.

b. Users can increase or decrease flow by turning encoder knob right or left. Arduino has a robust encoder library for this, and the optical encoder we’re using needs no debouncing.

c. Flow display: rate is displayed on the LCD in ml/sec, and is updated at at least 1Hz.

d. Flow volume and time accumulation: the lower line of the display is used to show accumulated flow in liters/sec; and time in seconds.

e. Sound – small beeper (implemented, along with timer tweaking to enhance volume.)

  1. PWM and flow calibration.

Sketch (what Arduino programs are called) should have a variable tying PWM value from the Arduino to flow values from the pump. We’ll test to determine how PWM values (i.e. “analogWrite”) related to actual flow in ml/s and change this variable to calibrate the units. For most pumps we’ve tested, flow does not start until about 40% duty cycle. Nov, 2011 update: “Calibrate” feature in menu allows users to set the PWM value for “fist flow” or near-zero flow; user adjusts flow until it’s as low as possible but still continuous; then navigates in Menu to “calibrate” and presses knob; this sets PWM lookup values so that PWM value is at 3ml per second and adjusts the entire PWM v. flow curve to match (shifting it right/left, basically, with PWM on the x-axis).

OK, code here.

Mostly written by a professional coder/friend as a favor; he’ll remain anonymous.

Thanks for all your help, forum peeps :slight_smile:

–Arrrggg, keep getting “9500 characters exceeded…” error here so I’m trying the attachment function…

Gough_pump_controler_V4_forum.pde (25.6 KB)

Binary sketch size: 7848 bytes (of a 30720 byte maximum)

There seems to be enough flash free (on a UNO), so you might need PROGMEM to move the tables from RAM to flash... - http://www.arduino.cc/en/Reference/PROGMEM -

Option to consider is to add an SD card as external memory and read the hydroGraph to be used from SDCARD. Then you only need to have one hydroGraph in memory at the same time. It allows you to have dozens of tables on the SDcard. It would also allow you to log to it ...

2 cents..

One small change you could make is to get rid of the ml_per_sec_by_pwm array and calculate it on the fly, which would save 512 bytes of SRAM. This would do it:

int Get_ml_per_sec_by_pwm(uint8_t pwm)
  return 0;
  return Qvals[pwm-pwmCal];

Uncompiled, untested.

Then wherever you use this: ml_per_sec_by_pwm[pwm], replace it with Get_ml_per_sec_by_pwm(pwm). You can also drop init_flow_table, although you would need to keep Qvals somewhere - another candidate for progmem.

Wish I could do that, wildbill, but the pwm v. flow rate curve is way kinky and requires a fourth order polynomial to properly describe it! That's why we're using a lookup table.