Go Down

### Topic: Driving Comp Air Engine with Solenoids and Arduino (Read 18667 times)previous topic - next topic

#### Newman180

#15
##### Nov 17, 2010, 06:01 am
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

#### Newman180

#16
##### Nov 17, 2010, 06:20 am
Man, what a challenge this is turning out to be

Once again, I appreciate your help thus far

#### Newman180

#17
##### Nov 18, 2010, 06:03 am
If anyone is interested, I expanded this thread into the software forum for the code design.

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1290052524

Much help is needed and appreciated!

Thanks

#### Newman180

#18
##### Nov 18, 2010, 07:35 pm
Quote
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.
Code: [Select]

//-----------------------------------------------
#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()
{
Serial.begin(9600);
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()
{
eventcount++;
//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;
Serial.println(degree,DEC);
Serial.println(rpm,DEC);

}
// 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);
}
//-----------------------------------------------

#### gardner

#19
##### Nov 18, 2010, 07:50 pm
Quote
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.

#### Newman180

#20
##### Nov 18, 2010, 08:01 pm
Thanks gardner, but unfortunately I need this to work much higher than 100 RPM.

#### Newman180

#21
##### Nov 18, 2010, 08:03 pmLast Edit: Nov 18, 2010, 08:03 pm by Newman180 Reason: 1
Quote
My original thoughts were based on using the micros() function.  The period of rotation will be some large number of microseconds, and you can use simple percentage (or degree angles, if you prefer) to calculate how many microseconds beyond TDC to open or close any particular solenoid.

Would you mind showing me an example in code?
I am following you, but can't quite grasp it.

#### Newman180

#22
##### Nov 18, 2010, 08:23 pm
Thank you. I will work on implementing that into the code and post the results.

The speed will not be high initially. 250 to 500 RPM Max.

#### Newman180

#23
##### Nov 18, 2010, 08:40 pm
Quote
If you were making 2000 RPM, you would have 500us (microseconds) for each turn.

Excuse my ignorance, but isn't it 30,000us each revolution?

2000 RPM = 33.33333 RPS

So, theres 1 Revolution for every 1/33.3333 of a second

(1/33.3333)/(1,000,000) = 30,000us

Right?

#### Newman180

#24
##### Nov 18, 2010, 10:50 pm
How does this look?

Code: [Select]
///
///
///
///

//-----------------------------------------------
#include <LiquidCrystal.h>
LiquidCrystal lcd(7,8,9,10,11,12);
volatile unsigned int eventcount;
unsigned int valve; // Time Valve Open
unsigned int rpm;
unsigned int degree;
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
int buttonPin = 13; // Button For Switching %
int buttonPushCounter = 0;   // counter for the number of button presses
int buttonState = 0;         // current state of the button
int lastButtonState = 0;     // previous state of the button

void setup()
{
Serial.begin(9600);
pinMode (So17Pin, OUTPUT);
pinMode (So35Pin, OUTPUT);
pinMode (So28Pin, OUTPUT);
pinMode (So46Pin, OUTPUT);
pinMode(buttonPin, INPUT);
attachInterrupt(0, rpm_count, RISING); // Interrupt 0 is Pin 2 Hall Sensor
eventcount = 0;
valve = 0;
rpm = 0;
timeold = 0;
degree = 0;
}

void rpm_count()
{
eventcount++;
//Updated Count
}

void loop()
{
if (eventcount >= 1) {

rpm = (micros() - timeold) / eventcount;
rpm = 1000000/rpm;
rpm = rpm*60;
timeold = micros();
eventcount = 0;
degree = (60000000/rpm);
degree = degree/360;

Serial.println(degree,DEC);
Serial.println(rpm,DEC);

}

if (buttonState != lastButtonState) {

if (buttonState == HIGH) {

buttonPushCounter++;
Serial.println("on");
Serial.print("number of button pushes:  ");
Serial.println(buttonPushCounter, DEC);
}
else {
Serial.println("off");
}
}
lastButtonState = buttonState;

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

}
}
//-----------------------------------------------

#### Newman180

#25
##### Nov 18, 2010, 10:57 pm
How do I make a formula without multiplying and dividing? Example?

No the important part is not the readout, its controlling the solenoids.

Also, with the hall effect sensor, will I need a pull up or pull down resistor?

#### Newman180

#26
##### Nov 18, 2010, 11:05 pmLast Edit: Nov 18, 2010, 11:06 pm by Newman180 Reason: 1
Unfortunately I don't know how to eliminate/reduce the degree and rpm variables...

Or would a float function work better ?http://www.arduino.cc/en/Reference/Float

My hall effect sensor is

#### Newman180

#27
##### Nov 19, 2010, 12:01 am
Yes I defiantly see the difference with the milliseconds per rotation vs rpm.

Thank you for that source. I have found through a bit of research I should have done before hand that I need a 10K Pull up resistor.

When I search on digikey, radioshack, sparkfun, nothing comes up. Where do I find these or am I searching wrong?

#### Newman180

#28
##### Nov 19, 2010, 12:06 am
Quote
Quote:
Unfortunately I don't know how to eliminate/reduce the ... rpm variables...

Think of speed as milliseconds per rotation.  RPM is simply an artificial convention for humans.

This would work better correct?
Code: [Select]
rpm = (micros() - timeold) / eventcount;
rpm = 1000000/rpm;
rpm = rpm*60;
timeold = micros();
eventcount = 0;
degree = (1000000/(micros() - timeold) / eventcount);
degree = degree/360;

#### triath5147

#29
##### Nov 19, 2010, 12:10 am
It is just a 10k resistor 1/4 watt, 1/2 watt probably doesn't matter either. It is just called a pull up or pull down because of the way it is used to connect the wiring. Pull up resistor is wired to power, pull down it is wired to ground. You should be able to get about 100 10k resistors from anywhere for about \$1 US. I think I even saw them at Walmart once?!

Go Up