You'll need to tun the pump at some number of intermediate PWM values and measure its output at each one. The more intermediate values you measure, the more precise your control can be. Then you build a table of flow-rates vs. PWM level in flow-rate order, something like:
struct {
float flow; // measured flow rate
float pwm; // pwm value that gave that rate
} FlowTable[FLOWTESTS] = {
// flow PWM
{ 0., 0. },
{ 218., 256. },
{ 480., 512. },
{ 732., 768. },
{ 885., 1023. }
}
For a particular flow-rate, step through the table until you find a flow in the table that is >= to the flow you want (if it's ==, just use that PWM and you're done.)
We'll interpolate between the two table values that span the desired flow-rate. The idea is, if your desired flow is say, 17% (0.17) of the way between those two flows, you want a PWM value that's about 17% of the way between the two PWM values.
Let's say you want a flow of 600 (in whatever units your measurements are in - cc/minute, for example. Index 3 in the table (remember, our arrays are 0-based) has the first measured flow greater than 600, the desired flow, so we know the required PWM will be between 512 and 768. To find it, find the desired flow as a fraction of the interval [480, 732]:
frac = (600-480)/(732-480) = 120 / 252 = 0.476
,
or letting 'i' be the index of the first table entry whose flow exceeds the desired flow:
frac = (flow_des-FlowTable[i-1].flow) / (FlowTable[i].flow-FlowTable[i-1].flow);
. We need the PWM that is 47.6% of the interval [512, 768]:
pwm_req = 512 + ((768-512) * 0.476)) = 634
or
' pwm_req = FlowTable[i-1].pwm + ((FlowTable[i].pwm-FlowTable[i-1].pwm) * frac);`