Pages: 1 2 3 [4] 5 6 ... 9   Go Down
Author Topic: Driving Comp Air Engine with Solenoids and Arduino  (Read 5088 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Newbie
*
Karma: 0
Posts: 7
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Better yet.  Make a one tooth wheel that transitions at TDC/BDC.  When it's high you are on power stroke cyl1, when it's low you are on exhaust stroke.  
Logged

United States
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Learning
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you for your suggestions  MI_Troll.
As Richard has pointed out, I am using a similar system.
Logged

United States
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Learning
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Richard, I'm having an issue with the code for when to fire the solenoids. At the moment I haven't switched out of degrees. I will when I get the bugs worked out.

Can you look at my software forum post and give me some suggestions?
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1290052524/13#13

thanks
Logged

Ontario
Offline Offline
God Member
*****
Karma: 20
Posts: 835
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
MI_Troll
1) 4 cylinder engine

Funny.  In my mind's eye I was picturing a 2 cylinder double-acting double-expansion configuration.
Logged

United States
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Learning
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Can you post the latest version of the whole code somewhere? I am reluctant to try to piece together what I think it might be from the bits and pieces I am seeing in that thread.

Ya, np.

Code:
volatile byte eventcount; // Assinging the Count Feature
 unsigned int rt; // Rotation Time
 unsigned int degree; // Position of Piston
 unsigned int degree2;
 unsigned int degree3;
 unsigned int degree4;
 unsigned int rpm; // RPM
 unsigned long timeold; // Previous time Hall Sensor Picked up
 const int So17Pin = 3; // Solenoids 1 and 7 assigned to Pin 3
 const int So35Pin = 4; // Solenoids 3 and 5 assigned to Pin 4
 const int So28Pin = 5; // Solenoids 2 and 8 assigned to Pin 5
 const int So46Pin = 6; // Solenoids 4 and 6 assigned to Pin 6
 const int buttonPin = 13; // Button For Switching "Valve Open Time" Percent
 const int button2Pin = 14; // Button For Start Mode Intake 1+7
 const int button3Pin = 15; // Button For Start Mode Intake 3+5
 int buttonPushCounter = 0;   // counter for the number of button presses--- used with button for "Valve Open Time" Percent
 int buttonState = 0;         // current state of the button
 int button2State = 0;        // current state of the button 2
 int button3State = 0;        // current state of  the button 3
 int lastButtonState = 0;     // previous state of the button
 int lastButton2State = 0;     // previous state of the button 2
 int lastButton3State = 0;     // previous state of the button 3

 void setup()
 {
   Serial.begin(9600); // Communicate to Serial Port
   pinMode (So17Pin, OUTPUT); // Solenoid 1+7 as Output
   pinMode (So35Pin, OUTPUT); // Solenoid 3+5 as Output
   pinMode (So28Pin, OUTPUT); // Solenoid 2+8 as Output
   pinMode (So46Pin, OUTPUT); // Solenoid 4+6 as Output
   pinMode(buttonPin, INPUT); // Button for "Valve Open Time" as Input
   pinMode(button2Pin, INPUT); // Button For Start Mode 1+7 Intake
   pinMode(button3Pin, INPUT); // Button For Start Mode 3+5 Intake
   attachInterrupt(0, event_count, RISING); // Interrupt 0 is Pin 2 Hall Effect Sensor
 
 
 }
  void loop()
  {
    if (eventcount >= 1) {
   // Calculate position of piston
     rt = ((micros() - timeold)/ eventcount)/360; // Time Between Each Hall Pulse
     // Time Between Each Hall Pulse Divided by ( 360 Degrees)--- Time for 1 degree of rotation
    
     timeold = micros();
     eventcount = 0;        
       }
    
   //-------------------------------------------------------------------------------------- START MODE
  
    if (rt == 0)  // If Device is not spinning then Enable the Button's 2 and 3. If it is spinning Disable the Button's 2 and 3
    { Serial.println("Device Immobile");
    if (button2State != lastButton2State) // Start Mode Button2 Pressed--- Intake 1 and 7 Exhaust 4 and 6
    {
        if (button2State == HIGH) {
     digitalWrite(So17Pin, HIGH); // Fire Intake 1 and 7
     digitalWrite(So46Pin, HIGH); // Fire Exhaust 4 and  6
     Serial.println("Start In 1+7"); // Display Via Serial "Start In 1+7"
       }
     }
  
    {
    if (button3State != lastButton3State) // Start Mode Button3 Pressed--- Intake 3 and 5 Exhaust 2 and 8
    {
    
    if (button3State == HIGH) {
     digitalWrite(So35Pin, HIGH); // Fire Intake 3 and 5
     digitalWrite(So28Pin, HIGH); // Fire Exhaust 2 and 8
     Serial.println("Start In 3+5"); // Display Via Serial "Start In 1+7"
       }
     }
    }
   //------------------------------------------------------------------------------------ RUN MODE
     {
   }
  // Open for 100% Stroke Intake (1 and 7) Exhaust (4 and 6)
  
  if (degree <= ( rt*179) || (degree >= ( rt*1) ) // If the piston is inbetween 1 to 179 degrees of revolution then...
  { if (degree >= 0.00000000000000001){
     digitalWrite(So17Pin, HIGH); // Fire Solenoid 1 and 7 (Intake)
     digitalWrite(So46Pin, HIGH); // Fire Solenoid 4 and 6 (Exhaust)
     Serial.println("Intake (1,7) Exhaust (4,6) Fired 100%"); // Print Status and Percent of Valve Open
     }
  }
else {
  digitalWrite(So17Pin, LOW); // Don't Fire Solenoid 1 and 7 (Intake)
  digitalWrite(So46Pin, LOW); // Don't Fire Solenoid 4 and 6 (Exhaust)
  }
  // Open for 100% Stroke Intake (3 and 5) Exhaust (2 and 8)
  if (degree <= (rt*359) || (degree >= (rt*181)) ) // If the piston is inbetween 181 to 359 degrees of revolution then...
  { if (degree >= 0.00000000000000001){
     digitalWrite(So35Pin, HIGH); // Fire Solenoid 3 and 5 (Intake)
     digitalWrite(So28Pin, HIGH); // Fire Solenoid 2 and 8 (Exhaust)
     Serial.println("Intake (3,5) Exhaust (2,8) Fired 100%"); // Print Status and Percent of Valve Open
  }
   }
else {
  digitalWrite(So35Pin, LOW); // Don't  Fire Solenoid 3 and 5 (Intake)
   digitalWrite(So28Pin, LOW); // Don't Fire Solenoid 2 and 8 (Exhaust)
}

}

  //------------------------------------------ Button Control--- Allows the Change of How Long Valve Stays Open Per Revolution
  
   if (buttonPushCounter <= 9){
   if (buttonState != lastButtonState) // "Percent of "Valve Open Time" " Button Pressed
   {
    
    if (buttonState == HIGH) {
       buttonPushCounter++; // Update Button Counter
      Serial.print("number of button pushes:  "); // Display Via Serial "number of button pushes: "
      Serial.println(buttonPushCounter, DEC); // Display Via Serial Button Push Count
    }
    else {          
     lastButtonState = buttonState; // Stay at last button state if Button is not Pressed
    }
   }
   else {
     buttonPushCounter = 0; // Resets to 0 if it has been pressed more than 9 times
   }

 //---------------- 90% Valve Open  
  if (buttonPushCounter == 1) // If button is pressed once
  {
    Serial.println("90%");
   // Open for 90% Stroke Intake (1 and 7) Exhaust (4 and 6)
   if (degree <= ( rt*161.1) || (degree >= rt*1) ){
     digitalWrite(So17Pin, HIGH);
     digitalWrite(So46Pin, HIGH);
      Serial.println("Intake (1,7) Exhaust (4,6) Fired 90%");
     }
else {
  digitalWrite(So17Pin, LOW);
  digitalWrite(So46Pin, LOW);
}
  // Open for 90% Stroke Intake (3 and 5) Exhaust (2 and 8)
  if (degree <= (rt*342.1) || (degree >= (rt*181)) ){
     digitalWrite(So35Pin, HIGH);
     digitalWrite(So28Pin, HIGH);
     Serial.println("Intake (3,5) Exhaust (2,8) Fired 90%");
     }
else {
  digitalWrite(So35Pin, LOW);
  digitalWrite(So28Pin, LOW);
}

}

//---------------- 80% Valve Open    
   if (buttonPushCounter == 2) {
     Serial.println("80%");
   // Open for 80% Stroke Intake (1 and 7) Exhaust (4 and 6)
   if (degree <= ( rt*143.2) || (degree >= rt*1) ){
     digitalWrite(So17Pin, HIGH);
     digitalWrite(So46Pin, HIGH);
      Serial.println("Intake (1,7) Exhaust (4,6) Fired 80%");
     }
else {
  digitalWrite(So17Pin, LOW);
  digitalWrite(So46Pin, LOW);
}
  // Open for 80% Stroke Intake (3 and 5) Exhaust (2 and 8)
  if (degree <= (rt*324.2) || (degree >= (rt*181)) ){
     digitalWrite(So35Pin, HIGH);
     digitalWrite(So28Pin, HIGH);
     Serial.println("Intake (3,5) Exhaust (2,8) Fired 80%");
     }
else {
  digitalWrite(So35Pin, LOW);
  digitalWrite(So28Pin, LOW);
}
}
}

  void event_count()
 {
   eventcount++; // Hall Effect Count Updater
 }

If you have been reading in the other thread, I'm having an issue with actually describing to the Arduino when to fire the solenoids.

I know that I want it to fire specified solenoids between rt*1 and rt*179 and other solenoids between rt*181 and rt*359.

I just don't know how to write the "if" statement to handle those simple calculations.

And yes gardner it is a 4 cylinder. Double acting was harder to build atm.
Logged

United States
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Learning
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What on earth is THAT?
You do realize that you are using an 8-bit Reduced Instruction Set MICRO-processor here?  Right?
You don't need that many zeroes even to calculate the national debt (at least not for the next few weeks).  Shocked

Haha, I was getting frustrated when the serial readout on the arduino port wasn't feeding what I wanted. Just typed a bunch of zeros

Quote
Frankly, you code just seems WAY too complex.  You should be able to do this entirely with integers.  I am suspicious of anything requiring decimals.
I agree its overly complex, so Please guide me with how to do this.
As I mentioned before, this is for my senior design for mechanical engineering. The software side was supposed to be quick and easy. Even though I've never taken a programming course, or learned any type of computer engineering, I thought it was going to be a lot easier.
I'm willing to learn though,
I'm not asking you to write it for me, but give me some examples!  smiley-wink


Logged

United States
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Learning
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I don't know how you are calculating the valve open and close times/positions/angles? Are they fixed? Are you going to change them?
Unfortunately, the valve timings need to be adjustable to set increments. If it was always one set value, I would probably bypass the microprocessor all together...

Quote
Anyway, I would create a table of open and close values. I would make each value in integer 1000ths of a rotation (or 10ths of a percent, if you wish). So something that happens right after TDC would have a value of 0001 and something that happens just before TDC would have a value of 0999. Note that this is ~3x better resolution than using "degrees" and keeps all the math in integers.

Here is what I would do in the code, starting with the detection of TDC.
1) Subtract right now from previous TDC to establish rotation period in microseconds.
2) Store this TDC time for use next time around.
3) Multiply your table of open/close times (in 1000ths of a revolution) against the rotation period.
4) Each time one of those calculated times occurs open or close whatever valve.
5) wait for the next TDC
Great! Let me research how to set up tables, and I'll try to put one together. Thanks Richard.

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 1
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Richard said:
"Here is what I would do in the code, starting with the detection of TDC.
1) Subtract right now from previous TDC to establish rotation period in microseconds.
2) Store this TDC time for use next time around.
3) Multiply your table of open/close times (in 1000ths of a revolution) against the rotation period.
4) Each time one of those calculated times occurs open or close whatever valve.
5) wait for the next TDC

I don't know why it should be any more complex than that?

Note that if the valve open/close times are fixed, you could consider just cutting a custom rotor with "teeth" at each open or close point. Then you wouldn't have to worry about extrapolating or calculating times within each resolution."
**************************
I apologize if my input seems out of line..... After 30 years in the computer industry I have come to believe strongly in the KISS principle. It is axiomatic that if the code is ugly and complex it's not ready to play.... that being said, Richard has thumbnailed a simple flow chart to conquer your timing issue.

My suggestion is to focus on the sensor position readings and the timing between pulses rather than reinventing the wheel in the code.

Back in the day we learned to "right" a logic map/flow chart before writing code......

Just sayin'  smiley-wink

Dave

"Middle out programming is the path to insanity......"
mumbled by a Microsoft engineer sleeping under his desk circa 1995
Logged

Seattle, WA USA
Online Online
Brattain Member
*****
Karma: 551
Posts: 46240
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
2) Store this TDC time for use next time around.
This is what I told you you need to do, over in the software thread. But, you weren't listening there, so I doubt you'll listen here, either.
Logged

United States
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Learning
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
This is what I told you you need to do, over in the software thread. But, you weren't listening there, so I doubt you'll listen here, either.
It's not that I wasn't listening, but I think you were forgetting that I have no background in this side of engineering. Me asking a question and you responding with something other than the answer to my question got me confused and frustrated. I appreciate your input thus far and hope that you continue to give me insight. Just remember, I'm a beginner.  smiley-wink
Logged

United States
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Learning
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Should I be using PROGMEM to create and store the tables?
Logged

Ontario
Offline Offline
God Member
*****
Karma: 20
Posts: 835
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Should I be using PROGMEM to create and store the tables

For tables above a few dozen bytes, yes, PROGMEM is the right way to store them. It's a little fussy to access PROGMEM, but not too bad.
Logged

United States
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Learning
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
For tables above a few dozen bytes, yes, PROGMEM is the right way to store them. It's a little fussy to access PROGMEM, but not too bad.

K, Thanks. Yea I haven't found very many examples of storing large tables, so I wasn't completely sure on the method.
Logged

United States
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Learning
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
How many valves do you have 8? 16? each one needs two values one for opening-time and one for closing-time.

Technically 8, but there's 2 on each pin, so the arduino thinks there are only 4.

I was thinking that I was going to make a table with values from 0001 to 0999, but just realized that I was on the wrong thought process.
Logged

United States
Offline Offline
Full Member
***
Karma: 0
Posts: 148
Learning
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Once again, Sorry there hasn't been an update yet. Finals are around the corner, and I have been busy studying.
Hopefully I will be able to post this weekend with new code and probably more questions smiley-wink

Logged

Pages: 1 2 3 [4] 5 6 ... 9   Go Up
Jump to: