Arduino based flow bench (i know there are some but never completed)

hello i intent to make an injector flow bench using arduino and a screen but i need help with code i have a partial code from git hub but i think it needs quite some work looks to have not been updated in years :frowning:

or if needs be a complete new set up i need to run 6 injectors at varying rpm simulations at different duty cycles ideal controlled by the screen (RGB LCD Shield Kit w/ 16x2 Character Display - Only 2 pins used! [NEGATIVE DISPLAY] : ID 714 : $24.95 : Adafruit Industries, Unique & fun DIY electronics and kits)

any help would be amazing

You might start by explaining what you mean by "an injector flow bench" and what part the Arduino is expected to play.

It is also much easier if you post code here so people don't have to go to another website. If the program is too long (but I hope not) you can add the .ino file as an attachment.

...R

this is the said code, and the injector flow bench basically i need to be able to change duty cycle of 6 injectors and run them at different opening times (ms scale) at a simulated rpm

//THIS DOESNT EXACTLY WORK YET. DONT EXPECT TO UPLOAD IT AND HAVE IT RUN.
//ARUINO FUEL INJECTOR CLEANER/TESTER

//NEED A SAFETY STOP INPUT WITTEN IN - NOT DONE YET
//VOLTAGE DISPLAY INPUT?

// inj_mode is 1 for 360 degrees and 2 for 720 degree mode
//EQUATION 60000000/RPM)*inj_mode =revolution_time
//revolution_time - min_inj_off_time = avail_on_time
// rev_time / injqty = inj_seq_gap - to time sequencing

unsigned int injqty = 8; //WILL EVENTUALLY BE MENU ADJUSTABLE TO SET # OF INJECTORS, 1-8

unsigned int inj_mode = 2; // 1 for 360 mode or 2 for 720
unsigned int RPM = 1000; //NOT PROGRAMMED YET - WILL BE MENU DRIEN AND WILL CALCULATE INJECTOR OFF TIME AND AVAILABLE ON TIME
unsigned int req_on_time = 1000UL; //requested on time

unsigned int min_inj_off_time = 1000UL; //TO BE ALCULATED AND MENU DRIVEN - in microseconds

unsigned int on_time = 1000UL;

unsigned long rev_time = (long) ((60000000/RPM)*inj_mode); //time in microsec per revolution * injector mode - 360' or 720'
unsigned long avail_on_time = (long) rev_time - min_inj_off_time;
unsigned long inj_seq_gap = (long) rev_time/injqty; //working?
unsigned long off_time = (long) avail_on_time - on_time;

const byte FUEL_PUMP = 4000; //millis pump on time - resets when injectors are pulsed and holds up injectors to prime.
//TO BE ON FOR 4 SECONDS BEFORE, DURING, AND 4 SECONDS AFTER RUN CYCLE - NOT PROGRAMMED YET

const byte INJ1_PIN = 5;
const byte INJ2_PIN = 6;
const byte INJ3_PIN = 7;
const byte INJ4_PIN = 8;
const byte INJ5_PIN = 9;
const byte INJ6_PIN = 10;
const byte INJ7_PIN = 11;
const byte INJ8_PIN = 12;
//SKIPPED PIN 13 BECAUSE OF ITS BOOT/WRITE BEHAVIORS

//1 MILLSECOND = 1000 MICROSECONDS - WILL EVENTUALLY BE MENU DRVEN - IDIVIDUAL OR BATCHTIME?
unsigned long INJ1_ON = on_time; //microseconds on
unsigned long INJ2_ON = on_time;
unsigned long INJ3_ON = on_time; //microseconds on
unsigned long INJ4_ON = on_time;
unsigned long INJ5_ON = on_time; //microseconds on
unsigned long INJ6_ON = on_time;
unsigned long INJ7_ON = on_time; //microseconds on
unsigned long INJ8_ON = on_time;

//MINIMUM OFF TIME? OFF TIME AS MICROSECONSDS OR DUTY CYCE?
unsigned long INJ1_OFF = off_time; //microseconds off - WILL BE MENU DRIVEN AND CALC'D FROM RPM
unsigned long INJ2_OFF = off_time;
unsigned long INJ3_OFF = off_time;
unsigned long INJ4_OFF = off_time;
unsigned long INJ5_OFF = off_time;
unsigned long INJ6_OFF = off_time;
unsigned long INJ7_OFF = off_time;
unsigned long INJ8_OFF = off_time;

unsigned long mcs1; //time from micros()
unsigned long mcs1Last; //last time the inj changed state
unsigned long mcs2; //time from micros()
unsigned long mcs2Last; //last time the inj changed state
unsigned long mcs3; //time from micros()
unsigned long mcs3Last; //last time the inj changed state
unsigned long mcs4; //time from micros()
unsigned long mcs4Last; //last time the inj changed state
unsigned long mcs5; //time from micros()
unsigned long mcs5Last; //last time the inj changed state
unsigned long mcs6; //time from micros()
unsigned long mcs6Last; //last time the inj changed state
unsigned long mcs7; //time from micros()
unsigned long mcs7Last; //last time the inj changed state
unsigned long mcs8; //time from micros()
unsigned long mcs8Last; //last time the inj changed state
boolean inj1State; //current inj1 state
boolean inj2State; //current inj2 state
boolean inj3State; //current inj3 state
boolean inj4State; //current inj4 state
boolean inj5State; //current inj5 state
boolean inj6State; //current inj6 state
boolean inj7State; //current inj7 state
boolean inj8State; //current inj8 state

void setup(void) {

//Serial.begin(9600);

pinMode (INJ1_PIN, OUTPUT);
pinMode (INJ2_PIN, OUTPUT);
pinMode (INJ3_PIN, OUTPUT);
pinMode (INJ4_PIN, OUTPUT);
pinMode (INJ5_PIN, OUTPUT);
pinMode (INJ6_PIN, OUTPUT);
pinMode (INJ7_PIN, OUTPUT);
pinMode (INJ8_PIN, OUTPUT);
pinMode (FUEL_PUMP, OUTPUT); //NOT PROGRAMMED YET
}

void loop(void){

//Serial.print ("on time");
//Serial.print ("");
//Serial.print (on_time);

//Serial.print ("off time");
//Serial.print ("");
//Serial.print (off_time);

//delay (1000);

mcs1 = micros();
mcs2 = micros();
mcs3 = micros();
mcs4 = micros();
mcs5 = micros();
mcs6 = micros();
mcs7 = micros();
mcs8 = micros();
pulseINJ1();
pulseINJ2();
pulseINJ3();
pulseINJ4();
pulseINJ5();
pulseINJ6();
pulseINJ7();
pulseINJ8();

//NEEDS SEQUENTIAL TIME CALCULATED FROM # OF INJECTORS. INITIAL DELAY OR DELAY EACH CYCLE?
//NEEDS COUNTERS ADDED TO EACH/LAST? INJECTOR TO KEEP TRACK OF RUN

}

void pulseINJ1(void)
{
if (( injqty > 0) && (mcs1 - mcs1Last > (inj1State ? INJ1_ON : INJ1_OFF))) {
digitalWrite(INJ1_PIN, inj1State = !inj1State);
mcs1Last = mcs1;
}
}

void pulseINJ2(void)
{
if (( injqty > 1) && (mcs2 - mcs2Last > (inj2State ? INJ2_ON : INJ2_OFF))) {
digitalWrite(INJ2_PIN, inj2State = !inj2State);
mcs2Last = mcs2;
}
}

void pulseINJ3(void)
{
if (( injqty > 2) && (mcs3 - mcs3Last > (inj3State ? INJ3_ON : INJ3_OFF))) {
digitalWrite(INJ3_PIN, inj3State = !inj3State);
mcs3Last = mcs3;
}
}

void pulseINJ4(void)
{
if (( injqty > 3) && (mcs4 - mcs4Last > (inj4State ? INJ4_ON : INJ4_OFF))) {
digitalWrite(INJ4_PIN, inj4State = !inj4State);
mcs4Last = mcs4;
}
}

void pulseINJ5(void)
{
if (( injqty > 4) && (mcs5 - mcs5Last > (inj5State ? INJ5_ON : INJ5_OFF))) {
digitalWrite(INJ5_PIN, inj5State = !inj5State);
mcs5Last = mcs5;
}
}

void pulseINJ6(void)
{
if (( injqty > 5) && (mcs6 - mcs6Last > (inj6State ? INJ6_ON : INJ6_OFF))) {
digitalWrite(INJ6_PIN, inj6State = !inj6State);
mcs6Last = mcs6;
}
}

void pulseINJ7(void)
{
if (( injqty > 6) && (mcs7 - mcs7Last > (inj7State ? INJ7_ON : INJ7_OFF))) {
digitalWrite(INJ7_PIN, inj7State = !inj7State);
mcs7Last = mcs7;
}
}

void pulseINJ8(void)
{
if (( injqty > 7) && (mcs8 - mcs8Last > (inj8State ? INJ8_ON : INJ8_OFF))) {
digitalWrite(INJ8_PIN, inj8State = !inj8State);
mcs8Last = mcs8;
}
}

centoproject:
hello i intent to make an injector flow bench using arduino and a screen but i need help with code
[Snip...]
any help would be amazing

I can maybe help a little bit right now but if you can wait until after May 6 then I'll have much more free time. I looked at the sketch you found on GitHub and it's a mess. I think when jrbe wrote that he just wanted a note to remember what he was thinking. In truth the code he wrote will not be able to run 6 injectors at the same time without a lot of problems.

It would be best to start with a new sketch that can be written to operate each injector with its own timing and on-screen display. Believe it or not the hardest part is going to be creating the menu system for controlling everything.

Do you have the plugs for the injectors and have you started on the hardware for mounting the injectors?

centoproject:
this is the said code, and the injector flow bench basically i need to be able to change duty cycle of 6 injectors and run them at different opening times (ms scale) at a simulated rpm

FIRST Please modify your post and use the code button </> so your code looks like this and is easy to copy to a text editor. See How to use the Forum Your code is too long to study quickly without copying to a text editor.

SECOND You have not told us what you mean by "the injector flow bench". It is much easier to offer sensible advice when we know what we are dealing with

...R

Robin2:
SECOND You have not told us what you mean by "the injector flow bench". It is much easier to offer sensible advice when we know what we are dealing with

I know this should be answered by centoproject but...

An injector flow bench allows the mechanic to test automotive fuel injectors on the workbench. The simplest test is a visual confirmation that any amount of fuel is discharged from the injector in a reasonable spray pattern. From there you can get into everything from injector duty cycle, volume of flow, spray pattern, and the size of the fuel droplets. More advanced setups allow for slow motion video capture and review of the spray itself.

mstanley:
I know this should be answered by centoproject but...

Thank you very much for being helpful.

I do think it is important that people asking questions should understand when they have not provided useful information and, personally, I like to leave them to fill their own gaps.

...R

i can confirm what Mstanley said was what i was trying to imply all i want to do is measure volume of fuel coming out of 6 injectors in a given time preferably 60 seconds and compare the flowed liquid from 6 graduated cylinders insuring they flow the same volume of liquid per a given time or pulse width then if posable adjust the frequency (effectively simulating rpm)

i am not amateur to forum etiquette i am a well respected member of a fair few reputable forums all be it mainly automotive so apologies for not posting properly...

//THIS DOESNT EXACTLY WORK YET. DONT EXPECT TO UPLOAD IT AND HAVE IT RUN.
//ARUINO FUEL INJECTOR CLEANER/TESTER

//NEED A SAFETY STOP INPUT WITTEN IN - NOT DONE YET
//VOLTAGE DISPLAY INPUT?

// inj_mode is 1 for 360 degrees and 2 for 720 degree mode
//EQUATION 60000000/RPM)*inj_mode =revolution_time
//revolution_time - min_inj_off_time = avail_on_time
// rev_time / injqty = inj_seq_gap - to time sequencing

unsigned int injqty = 8;   //WILL EVENTUALLY BE MENU ADJUSTABLE TO SET # OF INJECTORS, 1-8

unsigned int inj_mode = 2;   // 1 for 360 mode or 2 for 720
unsigned int RPM = 1000;   //NOT PROGRAMMED YET - WILL BE MENU DRIEN AND WILL CALCULATE INJECTOR OFF TIME AND AVAILABLE ON TIME
unsigned int req_on_time = 1000UL; //requested on time

unsigned int min_inj_off_time = 1000UL; //TO BE ALCULATED AND MENU DRIVEN - in microseconds

unsigned int on_time = 1000UL;

unsigned long rev_time = (long) ((60000000/RPM)*inj_mode); //time in microsec per revolution * injector mode - 360' or 720'
unsigned long avail_on_time = (long) rev_time - min_inj_off_time; 
unsigned long inj_seq_gap = (long) rev_time/injqty;  //working?
unsigned long off_time = (long) avail_on_time - on_time;


const byte FUEL_PUMP = 4000; //millis pump on time - resets when injectors are pulsed and holds up injectors to prime.
//TO BE ON FOR 4 SECONDS BEFORE, DURING, AND 4 SECONDS AFTER RUN CYCLE - NOT PROGRAMMED YET

const byte INJ1_PIN = 5;
const byte INJ2_PIN = 6;
const byte INJ3_PIN = 7;
const byte INJ4_PIN = 8;
const byte INJ5_PIN = 9;
const byte INJ6_PIN = 10;
const byte INJ7_PIN = 11;
const byte INJ8_PIN = 12;
//SKIPPED PIN 13 BECAUSE OF ITS BOOT/WRITE BEHAVIORS

//1 MILLSECOND = 1000 MICROSECONDS - WILL EVENTUALLY BE MENU DRVEN - IDIVIDUAL OR BATCHTIME?
unsigned long INJ1_ON = on_time; //microseconds on
unsigned long INJ2_ON = on_time;
unsigned long INJ3_ON = on_time; //microseconds on
unsigned long INJ4_ON = on_time;
unsigned long INJ5_ON = on_time; //microseconds on
unsigned long INJ6_ON = on_time;
unsigned long INJ7_ON = on_time; //microseconds on
unsigned long INJ8_ON = on_time;

//MINIMUM OFF TIME? OFF TIME AS MICROSECONSDS OR DUTY CYCE?
unsigned long INJ1_OFF = off_time; //microseconds off - WILL BE MENU DRIVEN AND CALC'D FROM RPM
unsigned long INJ2_OFF = off_time;
unsigned long INJ3_OFF = off_time;
unsigned long INJ4_OFF = off_time;
unsigned long INJ5_OFF = off_time;
unsigned long INJ6_OFF = off_time;
unsigned long INJ7_OFF = off_time;
unsigned long INJ8_OFF = off_time;

unsigned long mcs1; //time from micros()
unsigned long mcs1Last; //last time the inj changed state
unsigned long mcs2; //time from micros()
unsigned long mcs2Last; //last time the inj changed state
unsigned long mcs3; //time from micros()
unsigned long mcs3Last; //last time the inj changed state
unsigned long mcs4; //time from micros()
unsigned long mcs4Last; //last time the inj changed state
unsigned long mcs5; //time from micros()
unsigned long mcs5Last; //last time the inj changed state
unsigned long mcs6; //time from micros()
unsigned long mcs6Last; //last time the inj changed state
unsigned long mcs7; //time from micros()
unsigned long mcs7Last; //last time the inj changed state
unsigned long mcs8; //time from micros()
unsigned long mcs8Last; //last time the inj changed state
boolean inj1State; //current inj1 state
boolean inj2State; //current inj2 state
boolean inj3State; //current inj3 state
boolean inj4State; //current inj4 state
boolean inj5State; //current inj5 state
boolean inj6State; //current inj6 state
boolean inj7State; //current inj7 state
boolean inj8State; //current inj8 state

void setup(void) {

  //Serial.begin(9600);

  
    pinMode (INJ1_PIN, OUTPUT);
    pinMode (INJ2_PIN, OUTPUT);
    pinMode (INJ3_PIN, OUTPUT);
    pinMode (INJ4_PIN, OUTPUT);
    pinMode (INJ5_PIN, OUTPUT);
    pinMode (INJ6_PIN, OUTPUT);
    pinMode (INJ7_PIN, OUTPUT);
    pinMode (INJ8_PIN, OUTPUT);
    pinMode (FUEL_PUMP, OUTPUT); //NOT PROGRAMMED YET
}

void loop(void){

  //Serial.print ("on time");
  //Serial.print ("");
  //Serial.print (on_time);


  //Serial.print ("off time");
  //Serial.print ("");
  //Serial.print (off_time);

//delay (1000);
  
    mcs1 = micros();
    mcs2 = micros();
    mcs3 = micros();
    mcs4 = micros();
    mcs5 = micros();
    mcs6 = micros();
    mcs7 = micros();
    mcs8 = micros();
    pulseINJ1();
    pulseINJ2();
    pulseINJ3();
    pulseINJ4();
    pulseINJ5();
    pulseINJ6();
    pulseINJ7();
    pulseINJ8();
    
//NEEDS SEQUENTIAL TIME CALCULATED FROM # OF INJECTORS. INITIAL DELAY OR DELAY EACH CYCLE?
//NEEDS COUNTERS ADDED TO EACH/LAST? INJECTOR TO KEEP TRACK OF RUN

}

void pulseINJ1(void)
{
    if (( injqty > 0) && (mcs1 - mcs1Last > (inj1State ? INJ1_ON : INJ1_OFF))) {
        digitalWrite(INJ1_PIN, inj1State = !inj1State);
        mcs1Last = mcs1;
    }
}

void pulseINJ2(void)
{
    if (( injqty > 1) && (mcs2 - mcs2Last > (inj2State ? INJ2_ON : INJ2_OFF))) {
        digitalWrite(INJ2_PIN, inj2State = !inj2State);
        mcs2Last = mcs2;
    }
}

void pulseINJ3(void)
{
    if (( injqty > 2) && (mcs3 - mcs3Last > (inj3State ? INJ3_ON : INJ3_OFF))) {
        digitalWrite(INJ3_PIN, inj3State = !inj3State);
        mcs3Last = mcs3;
    }
}

void pulseINJ4(void)
{
    if (( injqty > 3) && (mcs4 - mcs4Last > (inj4State ? INJ4_ON : INJ4_OFF))) {
        digitalWrite(INJ4_PIN, inj4State = !inj4State);
        mcs4Last = mcs4;
    }
}

void pulseINJ5(void)
{
    if (( injqty > 4) && (mcs5 - mcs5Last > (inj5State ? INJ5_ON : INJ5_OFF))) {
        digitalWrite(INJ5_PIN, inj5State = !inj5State);
        mcs5Last = mcs5;
    }
}

void pulseINJ6(void)
{
    if (( injqty > 5) && (mcs6 - mcs6Last > (inj6State ? INJ6_ON : INJ6_OFF))) {
        digitalWrite(INJ6_PIN, inj6State = !inj6State);
        mcs6Last = mcs6;
    }
}

void pulseINJ7(void)
{
    if (( injqty > 6) && (mcs7 - mcs7Last > (inj7State ? INJ7_ON : INJ7_OFF))) {
        digitalWrite(INJ7_PIN, inj7State = !inj7State);
        mcs7Last = mcs7;
    }
}

void pulseINJ8(void)
{
    if (( injqty > 7) && (mcs8 - mcs8Last > (inj8State ? INJ8_ON : INJ8_OFF))) {
        digitalWrite(INJ8_PIN, inj8State = !inj8State);
        mcs8Last = mcs8;
    }
}

Jeez - who wrote that? Did he never hear of arrays?

I can't figure what each of the functions pulseINJx() is intended to do?

I don't see any code that reads something to figure out the volume of fuel?
What are you using to measure the small quantities involved?

...R

Robin2:
I can't figure what each of the functions pulseINJx() is intended to do?

Yeah, that's why I said it was a mess. I think the guy just wanted something as a reminder for later on.

As for measuring the volume of the fuel you can actually get very accurate readings using graduated cylinders. It would be cool to measure it electronically but you don't even really need the graduated cylinders. As long as you had 6 glasses of the same diameter you could just compare the levels visually.

So here's a first try at a new sketch. It compiles but of course without having a flow bench I am unable to test it. You can set the timing cycle for each injector individually and then it will run the cycle for 60 seconds.

It's a rough first draft and I make no promises that it will properly control the injectors. So make sure you can quickly unplug the power if you have to. :wink:

InjectorFlowBench.zip (2 KB)

So I'm assuming with a fuel injector test bench you would be worried about volume-metric flow. Do you think you might be able to use something like this? Liquid Flow Meter - Plastic 1/2 NPS Threaded : ID 828 : $9.95 : Adafruit Industries, Unique & fun DIY electronics and kits , a cheaper way would probably be use a get a accurate pressure reading and back calculate the volume-metric flow rate. Sounds like a cool project looking forward to reading about the progress.

thank you everyone i will have a look at your file mstanley when i get to the hotel :slight_smile:

and zbay liquid flow mesurent especially with a low viscosity is very difficult to measure so if i were to measure quantities i mainly rely on either weight or known pressure and regulator most machines use regulator as they can simulate under load i.e. turbocharged applications :slight_smile:

i have ordered the screen this chap has used already so if we can have it work with the screen that would be amazing fully standalone unit

and yes graduated glass cylinders is the best way to measure and compare

centoproject:
i have ordered the screen this chap has used already so if we can have it work with the screen that would be amazing fully standalone unit

That will be just fine. It's already a solved problem. Just be warned that a lot of people who use these LCD's for the first time usually make the mistake of updating the screen too frequently in their sketch. That makes it look like their screen isn't working. Don't panic. :wink:

Would you like some help with the circuit? Or are you comfortable with assembling and testing it yourself?

i would need help with circuit please :slight_smile: where pins go ect I'm quite new to raw arduino i use other chips

OK, that won't be a problem. So at this point I should ask you what your hopes are. There are a couple of options.

The first option is that I just tell you everything during design, assembly, and programming. What this means is that you'll have an Injector Flow Bench when we're done but you won't have learned much.

The second option is that I guide you by giving you explanations and ideas. This means you will learn about designing, building, testing, troubleshooting, programming, and debugging.

I like the second option best but will gladly help you in any way you like. Just let me know what you think so I don't just take over your project.

i like the last option to design is what i do day in day out so I'm competent with that electronics I'm quite literate lets plan something good and complete i will go over gathered parts when I'm home tomorrow and should i fabricate a basic frame ? then we can brain storm where things should be placed ect ?

Goal..

i would like to be able to run injectors through cycles as we have already discussed also maybe acquire data or interface with a computer while remaining a standalone unit that can be adapted to control up to 8 injectors i think that will service everyones needs but for me i just need 6 for now

Adjustments

RPM
Duty cycle
Ms adjustment
eventually the ability to tell us what the ejectors are flowing (start at a given weight of liquid and after a given time scale and quantity of injectors spit out an injector actual flow performance calculated from weight loss from the reference weight before test sequence)

and maybe for it to run through verifying cycles for say cleaning in an ultrasonic tank ?

Sounds like a good plan to me. Fabricating the basic frame should come first. It will help keep all the wires secure so we don't have to fight with them falling out all the time. It will make development a lot easier. Maybe mount the Arduino, too?

Your goals are workable. We'll have the Arduino control everything and the computer can just send commands and data which the Arduino will execute. The computer will be optional.

We'll make the sketch able to handle any number of injectors. That way it can be tested with 100 injectors which gaurantees that 8 will work just fine.

The rest is just details. Once you have the frame and injector drive electronics built we can create a basic sketch to test the Arduino's ability to operate the injectors. After that then we'll add the display, buttons, computer comms, and a method that will let the operator define the cycle at run time.

sounds good to me for the injector drivers to make things simple would solid state relays be a good or bad idea ? can they cope with rapid on and off under in the grand scheme of things low load most seam to be rated at 40 amps ? and can work from as low as 3v signal ? or if you have other ideas let me know

i will be able to machine out manifolds ect and mounting the arduino will be felt with utilising some laser cut acrylic to hold all electrical related things in isolation from liquids obviously

so i will get to work on the basic small frame on the week nights next week and keep updating with pictures ect what is the etiquette for pictures i take it no external hosting ?

also what i figure will be cool to add would be some kind of probe as mentioned earlier but i take it thats as simple as sending signal to the say cob led strip which i already have... milliseconds after the initial injector pulse ?

Actually, no restrictions on where pictures come from.

I like solid state relays but don't get too carried away. I think if you look at the injector specs you may find that the peak current values could be under 1 amp. SSR's are faster than mechanical relays and don't have contact bounce but they still may not be fast enough. There are other options. I'll look around and see if I can find some specs for injectors.

If you want any other hardware like led's then mount it now. We don't have to hook it up to the Arduino right away but it's better to have it when we need it than to try adding it later.