Driving Comp Air Engine with Solenoids and Arduino

I made a post a few months ago asking for assistance regarding this topic. I now have more research under my belt and feel like you guys will be able to guide me better.

I want to fire 8 solenoids at different rates. The solenoids will be firing in pairs of 2 (2 will be getting the same signal to fire at same time and same length).

These solenoids can be driven off of many voltages, but I am probably looking at 12v or 120v.

My timing device will be to use a rotary encoder. I want to count the crank shaft gear with the encoder and tell my arduino board that every time the encoder counts "14" (made up number) teeth fire solenoids 1 and 2, and everytime it counts another "14" teeth to fire 3 and 4... This would be oscillating back and forth and would be variable to the speed of the engine.

My questions... Which arduino? I think the UNO is find since it has 14 in/outs What devices are premade for this function? I assume I will have to use relays, or can I use this? http://www.sparkfun.com/commerce/product_info.php?products_id=9526

How do I write code for this? It seems fairly simple, but I have little programming knowledge besides basic web page construction.

Thanks, Austin

Hopefully you can help me come to a conclusion on some of these questions.

The speed of the shaft encoder will be dictated upon the size of the gear ration between the crankshaft and my encoder. It is also dictated on the RPMS of the engine.

It will see no more than 3000 rpm. The timing needs to be decently accurate, allowing the solenoids to fire every time the pistons are just past TDC (top dead center). The solenoids can run off of a variety of voltages, 12, 24, 120.... its power requirement is 40w.

How would the solenoids be run without a relay? More specifically how would you "drive" the solenoids using only the 5v output of the arduino?


Is the 16Mhz Clock Speed the maximum process rate?

so if I have a device that counts teeth 24 times a revolution spinning at 9000 rpm (gear ratio) that would be

150 revolutions/sec x 24 teeth in one revolution =3600 tooth senses a second?

Is this too high for the arduino and or the mega?

thanks for you help so far

the rest of the code will be seeing 8 outputs per revolution (for each solenoid).

Regarding the TDC detection, that is essentially what I am attempting to do. As far as I know, car computers use a hall sensor on the flywheel. Google agrees. So, the car companies are also counting the gears to dictate when the pistons are at the top of the stroke. Hence the rotary encoder.

If you have a different idea on how to clock when the pistons are at the top of the stroke, I'm all ears.

Thanks again for the quick responses

I am confused with your question. The link you posted agrees with what I stated previously.

100% I need some device to track when the pistons are TDC.... I.E replicating what car manufactures use, and instead of a hall device, using a mechanical shaft encoder.

hmm. Okay, I'm maybe missing something.

this is an engine, with four sets of pistons. These pistons drive a crankshaft. given that we know the firing sequence, the speed is determined solely by the rate at which you repeat that firing sequence- the interval timing between the pistons doesn't change, even if the engine RPM does, does it? And even if it does, isn't it directly proportional? In that case, is sensing the rotation position even necessary?

I know I must be spacing out something very basic here..

RPM can be calculated from shaft position, but shaft position can NOT be calculated from RPM. All the automotive systems I've seen use only a once-per-revolution signal because POSITION is crucial and everything else can be calculated from that.

I now follow what your saying. Unless I started the engine at the same point every time, "14" teeth will be at a different point every time...

If you have one spot on the crankshaft that is marked where the pistons are at the top, this device will send signal once a stroke.

Like you said, doesn't matter what device, it just has to dictate once per rev...

One thing that concerns me though, is with a "once per rev" device, now comes an issue of timing how long the valves are open. With the shaft encoder, you could say to keep the valve open for 4 more clicks, and no matter how fast the engine was rotating, it would be timed perfectly... With a once per rev sensor, you would have to use some sort of time calculation based upon the rpms. Do you know of an easier way? It would be way over my head to come up with a formula based upon exponential time to program

You can calculate RPM by measuring the time between pulses. And you can calculate position (in fractions of a degree if necessary) by dividing the period (the time between TDC) by 360. Once you know where TDC is, and you know the RPM (or actually the time between TDC), then it is almost trivial to calculate (and adjust) the position and period of any solenoid opening.

Yes I guess your correct. I was over thinking it. Thank you for your help so far again. I'm going to spend some time tonight researching writing some code assuming I'm using two sensors at 8 outputs. Would it be ok to PM you if I have any questions, or should I just keep coming back to this thread?

Heh, well I guess I should have worded that a little better.. but the idea I was driving at seems to be correct- if you know the position at least at one point (ala a single hall sensor), and know the rate of revolution, then you can calculate the timing rather than sense it. Again, I'm oversimplifying I know..

Quite interested in this thread.. some interesting problems posed and want to see how this works out. If nothing else, a nice primer in engine theory and practice..

I'm hoping this is an automotive or transportation engine.. compressed gas though dangerous has a great energy density and would be pretty practical (if noisy) short-range commuter vehicle engine. Seen a few prototypes on the web that use a compressed air engine in car prototypes....

As I'm getting closer to finishing this project, I have come across the need to buy hardware now.

Should I buy one Mega, or two Uno's?

The uno's would each control 4 solenoids, using a split hall effect signal.

I don't know if this is effective to allow enough space to handle all of the processes...

I plan on adding an LCD board to display the rpms as well as some temperature and pressure sensors

I figured with all those inputs it would be easier on a MEGA because I have more than enough input/outputs. I was also under the assumption is has a newer chip than the uno.

If I split two uno's again it would allow me to split the tasks. If thats even needed. :-/

Also Richard,

When I was researching the circuit for the solenoid, I noticed that the guide on the arduino site specifies that it is only for DC solenoids. I plan on using AC. Is this just a change of the transistor? I also noticed that your schematic includes a capacitor which the arduino one does not. Please explain. Thanks alot!

Ok. I already have my solenoids on order, just have to decide whether I want AC or DC. What was your opinion regarding the MEGA or UNO?

Thanks once again for the advice. I think you are correct with how to split the two boards.

FYI: The speed/power is dictated by the flow of air which is controlled by a mechanical valve.

I have ordered from a company on backorder. I did not have to specify at the time what current I wanted.

The starting is solved just like a car engine for now. Just a quick spin from a slow turning electric motor. I have other intentions once I get all the other pieces of the puzzle complete :wink:

So, I think I have found a way to keep it to just one Uno.

Let me know if there are any issues with this setup:

Uno LCD with Backpack (2 pins) Hall Effect Sensor Wingshield Screwshield Thermocouple With Thermocouple breakout Board Push Button Switch

My hopes are to run the 8 solenoids by reading the hall effect sensor, but at the same time use the LCD to display RPM and Temperature. The button would be used to change preset solenoid timings.

Can one UNO handle all that? Thanks

Man, what a challenge this is turning out to be :o

Once again, I appreciate your help thus far

If anyone is interested, I expanded this thread into the software forum for the code design.


Much help is needed and appreciated!


You can calculate RPM by measuring the time between pulses. And you can calculate position (in fractions of a degree if necessary) by dividing the period (the time between TDC) by 360. Once you know where TDC is, and you know the RPM (or actually the time between TDC), then it is almost trivial to calculate (and adjust) the position and period of any solenoid opening.

I’m actually a bit confused with the position calculation. If you divide a time like 20 seconds by 360, 20/360, you get a decimal that is irrelevant to its position. Please explain.
Here is my current code to better illustrate.

 #include <LiquidCrystal.h>
 LiquidCrystal lcd(7,8,9,10,11,12)
 volatile unsigned int eventcount; 
 unsigned int degree; // Angle of rotation out of 360
 unsigned int rpm;
 unsigned long timeold;
 int So17Pin = 3 // Solenoids 1 and 7 assigned to Pin 3
 int So35Pin = 4 // Solenoids 3 and 5 assigned to Pin 4
 int So28Pin = 5 // Solenoids 2 and 8 assigned to Pin 5
 int So46Pin = 6 // Solenoids 4 and 6 assigned to Pin 6
 void setup()
   pinMode (So17Pin, OUTPUT);
   pinMode (So35Pin, OUTPUT);
   pinMode (So28Pin, OUTPUT);
   pinMode (So46Pin, OUTPUT);
   attachInterrupt(0, rpm_count, RISING);
   eventcount = 0;
   degree = 0;
   rpm = 0;
   timeold = 0;
  void rpm_count()
   //Updated Count
 void loop()
   if (eventcount >= 1) { 
     degree = (millis() - timeold) / 360;
     rpm = (millis() - timeold) / eventcount; 
     rpm = 1000/rpm;
     rpm = rpm*60; 
     timeold = millis();
     eventcount = 0;
   // Open for 80% Stroke Intake (1 and 7) Exhaust (4 and 6)
   if (degree <= 143.2) || (degree >= 1) {
     digitalWrite(So17, HIGH);
     digitalWrite(So46, HIGH);
else { 
  digitalWrite(So17, LOW);
  digitalWrite(So46, LOW);

  // Open for 80% Stroke Intake (3 and 5) Exhaust (2 and 8)
  if (degree <= 324.2) || (degree >= 181) {
     digitalWrite(So35, HIGH);
     digitalWrite(So28, HIGH);
else { 
  digitalWrite(So35, LOW);
  digitalWrite(So28, LOW);

If you divide a time like 20 seconds by 360

20 secs is 20,000 milliseconds. 20,000/360 is about 56ms. If you want to wait for the shaft to be half way around, you wait 10,000 ms.

If you have an interrupt attached to the TDC event, you can have it remember (1) the time at which TDC was seen and (2) the elapsed time for the most recent rotation. Then at any time you can take the current time, subtract (1) and divide into (2) to see where the shaft is most likely at.

This would work okay up to about 100 RPM. After that you'd have to harness the hardware timers directly.