Triggering a relay off multiple analog readings/automotive water injection

I am trying to make an affordable water/methanol injection controller for me and a few friends(and whoever else wants to copy the design). For those that do not know what this is or understand, have a good read here: http://en.wikipedia.org/wiki/Water_injection_(engines) I have used several systems manufactured kits but mostly homebrew through out the years and have had very good success especially with turbocharged with ability to increase boost pressure and high compression engines equipped with knock sensor control or mechanical/electrical means to advance ignition timing and leaning of fuel mixtures. I have seen MPG and HP increases ranging from small to big, and lower EGT's depending on engine configuration and the ability to tune.

Most of out goals are to avoid using expensive premium gas(and controllers!) while achieving better economy and the extra power and reliability is nice too. I'm trying to start simple but would like to add more features as I develop the controller. Turbo cars are easy to setup a simple system, all is needed is a pressure switch set the desires psi/bar wired to a relay to run the pump. Non turbo/naturally aspirated engine get more complex when going mechanical activation. First you need a throttle switch to give minimum throttle activation, which can be a pain to install safely and reliably, next, wired in series you need a vacuum switch so the spray is activated when engine is under load(vacuum low, MAP high). Some cars use mass air flow signals which can make things a bit easier on NA cars to setup. An expensive but sort of necessary module needed is the RPM switch like the ones sold by MSD and others to prevent spraying during an engine off or stall condition, especially if no throttle switch is used. The RPM switch also prevents what I call "driveway missfire", I have had a few people complain and experienced myself when the throttle is blip-ed when climping a steep grade at low speed/rpm, causing a spray event and a chugging missfire. A temp switch is also a good Idea to conserve water when it is not needed on cold engine and to prevent it from delaying warm up times(it really pulls heat out of the engine).

All these parts can total over $100usd or more just to turn on a system, not including the rest of it(pump, nozzle, solenoid, tank, line/fittings, ect). Buying a pre-made controller will run you $200-$300 for bottom of the line. So I would like to tap the existing engine sensors to save money and ease installation. I'm using a $10 nano clone, it seems sufficient, please let me know if you think otherwise. TPS, MAP/MAF and ECT(coolant temp) are 0-5v signals on the vehicles I'm working with, I can easily tap off the ecu inside the car. From what I read the analog read pins do not use enough current to alter the signals to the ecu. RPM can be somewhat difficult for the arduino to read from what I've read and giving the varying types of ignition systems and there tach signals, I think I'll just start with powering the controller off the fuel pump circuit to ensure the engine is running when active, will have to just add a few seconds of delay before the loop begins to avoid spraying during the "prime" when ignition is first turned on and manifold vacuum is at 0.

So here's where I need help, while I have a great deal of knowledge and experience in automotive electronics, engine performance, and water injection, I am entering a steep learning curve of programming. Just like spanish, I can read C and kinda tell whats going on and whats gonna happen most of the time, but if I tried to read or speak it, I would sound like a fool as of now. But I'm learning it, and I find it very interesting, so here goes some pseudo code first:

Initialize the three analog sensor input pins: ECT, TPS, MAP, Initialize outputs of the "coolant temp ready" LED and Motor relay delay 2-3 seconds or more

Loop would look at ECT and if value was equal to or greater than the specified min temp, than the "ECT ready" led will illuminate to tell the driver the engine temp is high enough to begin using spray and the code will continue onto the next sensor.

If TPS value higher than X value, then MAP or MAF value is looked at and if greater than specified min, pump pin goes high.

I would like to also add a serial print to each analog read so I can view data on the serial monitor and then adjust code a little less blindly. Eventually I would like to add RPM, LCD display. I'm sure many more features can be added, but I have found complexity like fuel injected quantity % matching is optimal but most of the benefits on stock-ish engines can be realized with simply on/off of the pump at the right time. But for now the only thing I have done successfully with this thing is make a crazy high power rgb seizure inducing light blinker thing, other than copying someone elses code. This may seem simple to some that can program, but I really would like to at least know where to start as to what the best way to structure this code would be, thanks in advance.

RPM can be somewhat difficult for the arduino to read from what I've read

That depends on what mechanism is used to determine engine RPM. Adding hall-effect sensors and magnets to an existing engine can be problematic.

If the engine already has a mechanism to report RPM (via CAN bus?), reading that isn't hard. If the engine already has magnets and hall-effect sensors, tapping that signal and triggering an interrupt is not difficult. Determining RPM from time between interrupts or by counting interrupts within a given time frame are two alternatives. Counting interrupts leads to a more stable reading, but determining that the engine has stopped can take a while. Determining RPM based on time between signals has pros and cons, too.

So here's where I need help, while I have a great deal of knowledge and experience in automotive electronics, engine performance, and water injection, I am entering a steep learning curve of programming. Just like spanish, I can read C and kinda tell whats going on and whats gonna happen most of the time, but if I tried to read or speak it, I would sound like a fool as of now.

This is NOT the project to experiment with, unless you are water-injecting a lawn mower that is past its prime.

delay 2-3 seconds or more

No. No delay()s. Read, understand, and embrace the blink without delay example/methodology before you even think about getting started.

The only place delay() MIGHT be used is in setup().

And, really, you need to determine how long the engine should be running before injection is enabled, so that you can state your requirement in concrete terms. "2 to 3 seconds or maybe longer" is not translatable into code.

Loop would look at ECT

Using terms that match what the computer can actually do makes going from pseudo code to real code much easier. The Arduino can't look at anything - no eyes. It can READ temperature sensors. (Just a nit, but I'm nit-picky).

than the specified min temp

Specified how? Details are important. Read from SD card? Hard-coded? Read by ping sensor aimed at someone waving semaphore flags?

and the code will continue onto the next sensor.

No. If the temperature is high enough, the LED will be lit, a flag will be set, and there will be more code to execute in the if block. Else, the LED will be turned off and the flag cleared.

Hand-waving has no place in pseudo code. Again, the better you align the pseudo code to the way real code is written, the clearer your requirements are and the easier it is to convert to real code.

If TPS value higher than X value, then MAP or MAF value is looked at and if greater than specified min, pump pin goes high.

Again, you need to define how these values will be specified. Unless you mean set, in which case you should use that term.

Something about when the pump should be turned off would be useful.

I would like to also add a serial print to each analog read

You could add a Serial.print() AFTER each line of code that performed an analogRead(). You shouldn't add Serial.print() to the analogRead() function. Really, you shouldn't.

But for now the only thing I have done successfully with this thing is make a crazy high power rgb seizure inducing light blinker thing

Deliberately?

This may seem simple to some that can program

Relatively, yes. And I strongly encourage you to wait until it seems simple to you, too, before you undertake this project. Or, post in gigs and collaboration, asking for help.

To get the best results from WI you really ought to be controlling it via a mapped injector. That's not what you're describing here, though. If all you want is to prevent it from turning on when manifold depression exceeds a threshold, when engine RPM is below a threshold, when coolant temp is below a threshold then you could feasibly achieve all of that using plain old analog electrics.

Coolant temp sensor becomes aftermarket adjustable electric fan switch. Manifold absolute pressure sensor becomes a vacuum switch. Engine running signal becomes power supply taken from fuel pump circuit. Engine rpm measurement becomes aftermarket shift light configured to operate at the threshold rpm. You just need to route the pump supply through all these various switches before you feed it to the water reservoir pressure switch, so the pump only comes on when all these parameters are within your limits.

PaulS: That depends on what mechanism is used to determine engine RPM. Adding hall-effect sensors and magnets to an existing engine can be problematic. If the engine already has a mechanism to report RPM (via CAN bus?), reading that isn't hard. If the engine already has magnets and hall-effect sensors, tapping that signal and triggering an interrupt is not difficult. Determining RPM from time between interrupts or by counting interrupts within a given time frame are two alternatives. Counting interrupts leads to a more stable reading, but determining that the engine has stopped can take a while. Determining RPM based on time between signals has pros and cons, too.

Like I said not too concerned with rpm right now, its not a big deal to not have it and I'm trying to learn the basics before I move onto some more advanced code, interrupts and such. Detection of RPM and the other sensors via CAN bus would be nice, but the vehicle I am working on at the moment is OBD1 and has ALDL, and some vehicles I deal with have no form of communication. I can get a tach signal from just about any vehicle, whether it be from the ignition coil or fuel injector, but they differ from a 12-5v square wave to drive coil on plug to 12v pulse with a huge back spike from and older coil distributor system or actual fuel injector.

PaulS: This is NOT the project to experiment with, unless you are water-injecting a lawn mower that is past its prime.

I don't see your logic on this, I am powering the controller off the fuel pump circuit, the ecu only turns on the pump during prime and when rpm is detected, there is no chance of spray when engine is not running other than the 2 second prime when ignition is first turned on. It can spray all day long with engine running and it would just waste water and make the engine run rough at idle.

PaulS: No. No delay()s. Read, understand, and embrace the blink without delay example/methodology before you even think about getting started. The only place delay() MIGHT be used is in setup(). And, really, you need to determine how long the engine should be running before injection is enabled, so that you can state your requirement in concrete terms. "2 to 3 seconds or maybe longer" is not translatable into code.

I understand the delay function thanks to the hello world sketch, but was wandering how to use it properly in setup() so during the fuel pump prime it would not make it into loop and fire the pump due to lack of manifold vacuum. "2-3 seconds" was an example of a value I would change based on what I found works best, not something I was looking for the arduino to figure out for me, I use a time delay relay to do this on N/A cars and wanted to eliminate the use of $10-$20 part with a simple piece of code.

PaulS: Using terms that match what the computer can actually do makes going from pseudo code to real code much easier. The Arduino can't look at anything - no eyes. It can READ temperature sensors. (Just a nit, but I'm nit-picky).

Ok, I will try to correct my computer code grammer that I am strugling to learn for nit pickers like you.

PaulS: Specified how? Details are important. Read from SD card? Hard-coded? Read by ping sensor aimed at someone waving semaphore flags?

I thought it was quite obvious that I meant read the analog voltage of the the sensor, very funny.

PaulS: No. If the temperature is high enough, the LED will be lit, a flag will be set, and there will be more code to execute in the if block. Else, the LED will be turned off and the flag cleared. Hand-waving has no place in pseudo code. Again, the better you align the pseudo code to the way real code is written, the clearer your requirements are and the easier it is to convert to real code.

I obviously don't know much about code yet, my impression was that pseudo code was just to get the basic idea of what you want to computer to do. However it is written, I would be nice to know if the engine has reached its warm and ready state. Again I'm not sure the best way to implement this in code.

PaulS:

If TPS value higher than X value, then MAP or MAF value is looked at and if greater than specified min, pump pin goes high.

Again, you need to define how these values will be specified. Unless you mean set, in which case you should use that term.Something about when the pump should be turned off would be useful.

These will be values I will manually change in the code, for example, the coolant temp reaches 2.5v its ready, then when the TPS reaches %50 or 2.5v, it is ready, then when the map reaches 500milibar (2.5v)it is ready and the pump pin goes high, if any one of these go below the value I specify in the code(512 for analog read?) then the pump pin goes low.

PaulS: You could add a Serial.print() AFTER each line of code that performed an analogRead(). You shouldn't add Serial.print() to the analogRead() function. Really, you shouldn't.

I would just like it to print so I can see what values are beeing read by the arduino so I can make faster decisions on how to change the code to get the controller to activate under the right conditions.

PaulS: Deliberately?

It was a joke, I made my neice an rgb project for her school project with three knobs to change the pwm/color, it called for low power leds and electronic diming, I souped it up with an arduino and a 10w rgb led. I loaded a modified blink sketch to demonstrate to a couple of friends what the arduino was and could do.

PeterH: To get the best results from WI you really ought to be controlling it via a mapped injector. That's not what you're describing here, though. If all you want is to prevent it from turning on when manifold depression exceeds a threshold, when engine RPM is below a threshold, when coolant temp is below a threshold then you could feasibly achieve all of that using plain old analog electrics.

Coolant temp sensor becomes aftermarket adjustable electric fan switch. Manifold absolute pressure sensor becomes a vacuum switch. Engine running signal becomes power supply taken from fuel pump circuit. Engine rpm measurement becomes aftermarket shift light configured to operate at the threshold rpm. You just need to route the pump supply through all these various switches before you feed it to the water reservoir pressure switch, so the pump only comes on when all these parameters are within your limits.

You are correct and one day I would like to build to the mapped injector controller. But for know all those analog parts you describe add up, you cant beat a $10 nano.

jmil2271: But for know all those analog parts you describe add up, you cant beat a $10 nano.

Bear in mind that you're probably going to need to buy all that stuff anyway, and wire it up and provide filters and voltage regulation and so on in addition to the microcontroller. The microcontroller isn't really adding much value considering that it's no harder, and probably easier, and probably cheaper and more reliable, to do the whole thing in hardware.

Bear in mind that you're probably going to need to buy all that stuff anyway, and wire it up and provide filters and voltage regulation and so on in addition to the microcontroller. The microcontroller isn't really adding much value considering that it's no harder, and probably easier, and probably cheaper and more reliable, to do the whole thing in hardware.

Ummm.... not to sound rude at all, but no, It won't, and that is exactly what I am trying to move away from, get rid of three more expensive, less reliable, harder to install mechanical/electrical switches in favor of sensor already in use. The nano accepts up to 20v for a power supply, if the raw system voltage is not clean enough a cheap 5v regulator and cap will do or just power it off of the ecu's 5v bus, it has plenty of room for my estimated max power draw of 100ma for the micro and ssr.

It will directly read the sensors which are just a thermistor, a potentiometer, pressure transducer, all operate on a 0-5v scale. An SSR is another $10 but I could even pull a transistor and relay out of the junk pile and use them too. Yes I could do this with opamps and such, but the whole point of the micro is to make changes to code with a computer through a usb port and make quick prototype changes without breaking out the soldering iron. Not really sure why this thread was moved to project guidance from programming questions, I do not need help with the project hardware, I have been building and using the mechanical and pre-made electronics for years, I need help with the programming, C mostly.

Maybe I should have asked how I should structure a program that has three potentiometers hooked to analog inputs 1, 2 and 3. I want an LED to light on digital pin 3 when all pot pins read 2.5v or higher, all must be 2.5v or higher to allow digital pin 3 to go high. I also would like to serial print their current state, and possibly one day when analog input pin 1 is equal to or greater than 2.5v to set digital pin 4 high and keep it there until analog input 1 is less than 2.5v. Does this make more sense? I am going to try to find a similar sketch online and try to modify it and post it here to see what you guys think.

jmil2271:
Maybe I should have asked how I should structure a program that has three potentiometers hooked to analog inputs 1, 2 and 3. I want an LED to light on digital pin 3 when all pot pins read 2.5v or higher, all must be 2.5v or higher to allow digital pin 3 to go high. I also would like to serial print their current state, and possibly one day when analog input pin 1 is equal to or greater than 2.5v to set digital pin 4 high and keep it there until analog input 1 is less than 2.5v. Does this make more sense? I am going to try to find a similar sketch online and try to modify it and post it here to see what you guys think.

From the description, it sounds like a simple program I would write it like this. Note, I’m doing this free hand, just to give you an idea of what the program would look like, and in practice I would probably simplify the if’s to turn on/off the leds:

// Pins used
const int pin_thermistor = A0;
const int pin_potentiometer = A1;
const int pin_pressure = A2;
const int pin_main_led = 3;
const int pin_pot_led = 4;

// Initialize things
void setup (void)
{
  // Setup serial monitor via USB/FTDI, 9600 baud
  Serial.begin (9600);

  // Initialize input pins
  pinMode (pin_thermistor, INPUT);
  pinMode (pin_potentiometer, INPUT);
  pinMode (pin_pressure, INPUT);

  // Initialize LED
  pinMode (pin_main_led, OUTPUT);
  digitalWrite (pin_main_led, LOW);

  pinMode (pin_pot_led, OUTPUT);
  digitalWrite (pin_pot_led, LOW);
}

// Main loop
void loop (void)
{
  // analogRead returns 0..1023 for 0..5v, so to check for at least 511 for 2.5v
  int thermistor = analogRead (pin_thermistor);
  int potentiometer = analogRead (pin_potentiometer);
  int pressure = analogRead (pin_pressure);

  // If all 3 inputs are at least 2.5v, turn on the main led
  if ((thermistor >= 511) && (potentiometer >= 511) && (pressure >= 511))
    {
      digitalWrite (pin_main_led, HIGH);
    }
  else
    {
      digitalWrite (pin_main_led, LOW);
    }

  // if the potentiometer is >= 2.5v, turn on the secondary led
  if (potentiometer >= 511)
    {
      digitalWrite (pin_pot_led, HIGH);
    }
  else
    {
      digitalWrite (pin_pod_led, LOW);
    }

  // Now write all 3 values to the serial monitor
  Serial.print ("Thermistor = ");
  Serial.print (thermistor);
  Serial.print (", Potentiometer = ");
  Serial.print (potentiometer);
  Serial.print (", Pressure = ");
  Serial.println (pressure);

  // delay for a second before the next reading
  // this might not be needed in the real app, but it can slow things down
  // so you can read the USB more.
  delay (1000);
}

Thank you so much michael, thats exactly what I was looking for, I'll play with it and make the necessary changes, but I think you nailed it.

I'm glad it was helpful.