Go Down

### Topic: Compressed Air Engine - Rotary Encoder (Read 10589 times)previous topic - next topic

#### Korman

#15
##### Mar 17, 2011, 08:05 pm
Quote
For example, this is only hypothetical, but if I wanted the valves to fire 16 different times in one revolution, I would have to write 16 different else statements... not including the extra code for how long the valves are open.

Yes, there is. In the end, you might end up with a table driven or algorithmic solution. From the little I know about motor control, you might also modify the angle and duration at which valves open or close depending on the current rpm, pressure, temperature and other parameters. Once you want to do that, the simplistic hard-coded approach with if won't work. But those enhancements can be left for later, once you have the basics working properly.

As I wrote earlier, this project is a very well suited to get into embedded system programming, where you can start out simple and add complexity over time.

If interrupts are confusing you still - which very well might be the case - you can even try to write your first version just using polling the encoder pins with digitalRead() in the loop() function.

Code: [Select]
`void loop() {   static int lastpulsestate = LOW;   static int pulsecount = 0;   // Read pulse pin   int curpulse = digitalRead (pulsepin);   // We process a pulse only once when pulsepin state changed   if (curpulse != lastpulsestate) {       if (curpulse == LOW) {           // Check if the index is present and adjust pulse count           if (digitalRead (indexpin) == LOW) {               // Reset pulse counter               pulsecount = 0;           }           else {               // Increment pulse counter               pulsecount++;           }          // Check if we have a pulse count where we need to so something          switch (pulsecount) {               case 143:                     // Open valve 1                     digitalWrite (valve1pin, HIGH);                     break;               case 156:                     // Close valve 1                     digitalWrite (valve1pin, LOW);                     break;               case 543:                     // Open valve 2                     digitalWrite (valve2pin, HIGH);                     break;               case 556:                     // Close valve 2                     digitalWrite (valve2pin, LOW);                     break;           }       }       lastpulsestate = curpulse;   }}`

The code is as usual untested and all those HIGH and LOW might need to be reversed depending on what kind of signal levels are relevant. If you try that, you need to set up the constant variables and initialise the ports.

Korman

#### Newman180

#16
##### Mar 17, 2011, 08:15 pm
Thank you to both of you. You guys have official given me something physical to work with now.
I hope my encoder gets here before the end of the week so I can try this stuff.

I will attempt to use both of your ideas and write a program. When I am done I will post back here. It could be later tonight, or in the next day or so.

This could be from ignorance, but when looking through the pdf for the encoder, It does not state where the index is triggered.
Will this be obvious when I receive it, or is it a variable index dictating on the last position it started in? The latter would make finding TDC much more annoying.

#### robtillaart

#17
##### Mar 17, 2011, 08:25 pm

Quote
This could be from ignorance, but when looking through the pdf for the encoder, It does not state where the index is triggered.
Will this be obvious when I receive it, or is it a variable index dictating on the last position it started in? The latter would make finding TDC much more annoying.

http://products.cui.com/CUI_AMT103-V_Product_Training_Presentations.pdf?fileID=6203  Sheet 7 shows how it works, but I can't find it either.

http://www.cui.com/Contact/Company - shows email addresses to contact the company.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### Newman180

#18
##### Mar 17, 2011, 08:33 pm

Quote
This could be from ignorance, but when looking through the pdf for the encoder, It does not state where the index is triggered.
Will this be obvious when I receive it, or is it a variable index dictating on the last position it started in? The latter would make finding TDC much more annoying.

http://products.cui.com/CUI_AMT103-V_Product_Training_Presentations.pdf?fileID=6203  Sheet 7 shows how it works, but I can't find it either.

http://www.cui.com/Contact/Company - shows email addresses to contact the company.

I sent them an email. I will post the answer when I receive it.

#### victorf

#19
##### Mar 18, 2011, 02:38 am
You might like to read the Agilent HCTL2032 data sheet. This chip or its single channel cousin the HCTL 2022 might help you out by taking some of the load tracking the pulses off the Arduino. I am using it (2032) to handle a two channel quadrature encoder system. Check it out. It may be of use to you

Vic

Victor Fraenckel
KC2GUI
windswaytoo ATSIGN gmail DOT com

#### Newman180

#20
##### Mar 18, 2011, 02:58 am

You might like to read the Agilent HCTL2032 data sheet. This chip or its single channel cousin the HCTL 2022 might help you out by taking some of the load tracking the pulses off the Arduino. I am using it (2032) to handle a two channel quadrature encoder system. Check it out. It may be of use to you

Vic

Victor Fraenckel
KC2GUI
windswaytoo ATSIGN gmail DOT com

Thanks for the information. I will have to look into it. Any of you guys have an opinion about it?

#### Newman180

#21
##### Mar 18, 2011, 03:03 amLast Edit: Mar 18, 2011, 03:07 am by Newman180 Reason: 1
Let me know what you think. I had some weird errors compiling, something to do with conflicting symbols, but I can look into that later.

Code: [Select]
`//=====================================================================================////////=====================================================================================   #include <LiquidCrystal.h>   #define OPEN HIGH   #define CLOSE LOW   #define V17PIN 9   // Valves 1 and 7   #define V28PIN 10  // Valves 2 and 8   #define V35PIN 11  // Valves 3 and 5   #define V46PIN 12  // Valves 4 and 6   #define timingPIN 15 // Timing Button   #define maintbuttonPIN 16 // Maintenance Button   #define pushstartPIN 17 // Push Start Button   #define PPR 800 //PPR Programmable Setting   void V17(int newState)   { digitalWrite(V17PIN, newState);   }   void V28(int newState)   { digitalWrite(V28PIN, newState);   }   void V35(int newState)   { digitalWrite(V35PIN, newState);   }   void V46(int newState)   { digitalWrite(V46PIN, newState);   }   void timing(int newState)     {  digitalWrite(timingPIN, newState);      }   void pushstart(int newState)  {  digitalWrite(pushstartPIN, newState);   }   void maintbutton(int newState){  digitalWrite(maintbuttonPIN, newState); }     volatile unsigned long PPRcounter = 0;   volatile unsigned long RCounter = 0;  // Rotational Counter- measure RPM   unsigned long start = 0;   unsigned long RPM = 0;                           //----- USED IN TIMING CONTROL- SEE BELOW   unsigned int a;  // First 180 degrees Open     unsigned int a1; // First 180 degrees Close   unsigned int b;  // Second 180 degrees Open   unsigned int b1; // Second 180 degrees Close                          // Used to count button pushes for Timing   int buttonpushcounter = 0;   int buttonstate = 0;   int lastbuttonstate = 0;       int startp; // Used when declaring Start Mode Function     int timing; // Used when declaring Timing Mode Function   int maint; // Used when declaring Maint Mode Function   LiquidCrystal lcd (9,8,7,6,5,4);     //============================================================================================   //------------------------------------------------------------------------INTERRUPTS       void IRQ_TDC() // when TDC Interrupt is rising it resets the PPRcounter every rotation   { PPRcounter = 0; RCounter++;   }   void IRQ_Angle()    // Angle Interrupt   {                         //------------- Setting Timing Values        timing = timingcontrol(); //        timing; // Calling Timing Control Function                         //------------- Controlling Valves if (PPRcounter >= a && PPRcounter<= a1)  V17(OPEN); V46(OPEN); lcd.setCursor(12,1); lcd.print ("++"); // Intake 1 and 7 open as Exhaust 4 and 6 Open else V17(CLOSE); V46(CLOSE); lcd.setCursor(12,1); lcd.print ("  "); if (PPRcounter >=b && PPRcounter<= b1) V35(OPEN); V28(OPEN); lcd.setCursor(14,1); lcd.print ("++"); // Intake 3 and 5 open as Exhaust 2 and 8 Open else V35(CLOSE); V28(CLOSE); lcd.setCursor(14,1); lcd.print ("  "); PPRcounter++;   }//====================================================================================== //--------------------------------------------------------------------------SETUP     void setup()   { Serial.begin(115200); lcd.begin(16,2);        pinMode (V17PIN, OUTPUT); // Valve 1&7 as Output        pinMode (V35PIN, OUTPUT); // Valve 3&5 as Output        pinMode (V28PIN, OUTPUT); // Valve 2&8 as Output        pinMode (V46PIN, OUTPUT); // Valve 4&6 as Output        pinMode (pushstartPIN, INPUT); // Push Start Button Input        pinMode (timingPIN, INPUT); // Timing Button Input        pinMode (maintbuttonPIN, INPUT); // Maint Button Input   // TDC Interrupt connects to pin 2 attachInterrupt(0, IRQ_TDC, RISING); // Angle Interrupt connects to pin 3 attachInterrupt(1, IRQ_Angle, RISING); start = millis();   }//===================================================================================== //------------------------------------------------------------------------LOOP   void loop()   {       //----------------------------------  Button Counter Control- USED FOR TIMING CONTROL       buttonstate = digitalRead(timingPIN);       if ((buttonstate != lastbuttonstate) && (buttonstate == HIGH)){ buttonpushcounter++;} // If the buttonstate is greater than last, and it is high, increase counter       lastbuttonstate = buttonstate;       if( buttonpushcounter > 9) {buttonpushcounter = 0;} // If buttonstate has been pushed more than 9 times, reset to 0             //-----RPM DISPLAY if (millis() - start > 1000) // once per second { start = millis(); RPM = RCounter * 60 + (PPRcounter * 60)/PPR;        lcd.print(RPM, DEC);                Serial.print(RCounter, DEC); Serial.print(", \t"); Serial.println(PPRcounter, DEC); Serial.print(", \t"); Serial.println(RPM, DEC); }        //-------------------START MODE          startp = startmode();          startp; // Calling Start Mode Function        //-------------------Maitenance Mode          maint = maintmode();          maint; // Calling Maint Mode Function   }//===================================================================================================//--------------------------------------------------------------FUNCTIONS //-------------------------------- Timing Control Function int timingcontrol(){  a = 1;  b = 401;  a1 = 400 - 40 * buttonpushcounter; // a1 is upper end of first half of crank angle  if (buttonpushcounter ==0) a1 = a1 -1;  // When buttonpushcounter equals 0, it demands a seperate function to equal 179 rather than 0  b1 = a1 + 400; // b1 is the upper end of the second half of crank angle  lcd.setCursor(12,0);  lcd.print(100-10*buttonpushcounter); // print value of timing  lcd.print("%");} //=================================================================================================== //-------------------------------- Maint Mode Function int maintmode() {    maintbuttonState = digitalRead(maintbuttonPIN);   if (maintbuttonState == HIGH){     cli(); // disable interrupt     PPRCounter = 0; // Prevent any accidently Vavle firing if engine is turned     RCounter = 0;   //     lcd.clear();     lcd.print("Maintenance MODE");     digitalWrite(V28Pin,HIGH); // Open all Exhaust and stay open as long as maintbutton is high     digitalWrite(V46Pin,HIGH);  }        }//=================================================================================================== //----------------------------- Start Mode Function //TO BE WORKED ON `

#### robtillaart

#22
##### Mar 18, 2011, 12:59 pm
First reaction:

too much code in the IRQ, just open the valves, optionally set a global var for state.

next two lines invalid
timing = timingcontrol(); //
timing; // Calling Timing Control Function

The if then else misses {  }  block

A redo to minimize the irq routine
Code: [Select]
`void IRQ_Angle()    // Angle Interrupt{  a = 1;  b = 401;  // a1 is upper end of first half of crank angle  a1 = 400 - 40 * buttonpushcounter;       // When buttonpushcounter equals 0, it demands a seperate function to equal 179 rather than 0  if (buttonpushcounter == 0) a1 = a1 -1;  // b1 is the upper end of the second half of crank angle  b1 = a1 + 400;   //------------- Controlling Valves  if (PPRcounter >= a && PPRcounter<= a1)   {    V17(OPEN);     V46(OPEN);   }  else  {    V17(CLOSE);     V46(CLOSE);   }  if (PPRcounter >= b && PPRcounter<= b1)  {    V35(OPEN);     V28(OPEN);  }  else  {    V35(CLOSE);     V28(CLOSE);   }  PPRcounter++;}`

Change the V17 so it only does a digitalwrite if it has to   (others likewise)
Code: [Select]
`int V17state= 0; void V17(int newState)   {  if (newState != V17state)  {    V17state = newState;     digitalWrite(V17PIN, newState);   }  }`

It makes no sense showing the state values at 2000RPM = 33 RPS as the screen updates far too fast for human eyes!

-------
INvalid code :
//-------------------START MODE
startp = startmode();
startp; // Calling Start Mode Function
//-------------------Maitenance Mode
maint = maintmode();
maint; // Calling Maint Mode Function

should be just

startmode();
maintmode();

-------
in maintmode() you disable interrupts but you do not enable them again. Assume this is done in startmode.

The code for buttonpushcounter should be in the main loop together with the other things to display.

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### Newman180

#23
##### Mar 19, 2011, 03:28 am
Quote

First reaction:

too much code in the IRQ, just open the valves, optionally set a global var for state.

What do you mean set a global variable for state? What would that do?

Quote

next two lines invalid
timing = timingcontrol(); //
timing; // Calling Timing Control Function

For my own curiosity, what makes these invalid?

Quote

The if then else misses {  }  block

Good catch. I don't know how I forgot them :~

Quote

A redo to minimize the irq routine
Code: [Select]
`void IRQ_Angle()    // Angle Interrupt{  a = 1;  b = 401;  // a1 is upper end of first half of crank angle  a1 = 400 - 40 * buttonpushcounter;       // When buttonpushcounter equals 0, it demands a seperate function to equal 179 rather than 0  if (buttonpushcounter == 0) a1 = a1 -1;  // b1 is the upper end of the second half of crank angle  b1 = a1 + 400;   //------------- Controlling Valves  if (PPRcounter >= a && PPRcounter<= a1)   {    V17(OPEN);     V46(OPEN);   }  else  {    V17(CLOSE);     V46(CLOSE);   }  if (PPRcounter >= b && PPRcounter<= b1)  {    V35(OPEN);     V28(OPEN);  }  else  {    V35(CLOSE);     V28(CLOSE);   }  PPRcounter++;}`

If you added the timing function directly into the interrupt, how is that reducing it?

Quote

Change the V17 so it only does a digitalwrite if it has to   (others likewise)
Code: [Select]
`int V17state= 0; void V17(int newState)   {  if (newState != V17state)  {    V17state = newState;     digitalWrite(V17PIN, newState);   }  }`

It makes no sense showing the state values at 2000RPM = 33 RPS as the screen updates far too fast for human eyes!

Explain to me the purpose of this code? I thought I understood it but, I apparently don't.
Regarding the code for the lcd printout of which valves were firing, I guess your right. It was more for novelty.

Quote

INvalid code :
//-------------------START MODE
startp = startmode();
startp; // Calling Start Mode Function
//-------------------Maitenance Mode
maint = maintmode();
maint; // Calling Maint Mode Function

should be just

startmode();
maintmode();

What makes this invalid? I followed a playground post along time ago, but more importantly, I can't get it to compile if I do what you suggest...

Quote

in maintmode() you disable interrupts but you do not enable them again. Assume this is done in startmode.

Yes it will be done in start mode. Definitely don't want the interrupts to ever be enabled when my hands are touching the gears and valves.

#### Newman180

#24
##### Mar 19, 2011, 03:28 am

Here's the updated code as of my remarks and your suggestions
Code: [Select]
`//=====================================================================================////////=====================================================================================   #include <LiquidCrystal.h>   #define OPEN HIGH   #define CLOSE LOW   #define V17PIN 9   // Valves 1 and 7   #define V28PIN 10  // Valves 2 and 8   #define V35PIN 11  // Valves 3 and 5   #define V46PIN 12  // Valves 4 and 6   #define timingPIN 15 // Timing Button   #define maintbuttonPIN 16 // Maintenance Button   #define pushstartPIN 17 // Push Start Button   #define PPR 800 //PPR Programmable Setting      unsigned int V17state = 0;   unsigned int V28state = 0;   unsigned int V35state = 0;   unsigned int V46state = 0;   unsigned int timingstate = 0;   unsigned int pushstartstate = 0;   unsigned int maintbuttonState = 0;      void V17(int newState)   { if (newState != V17state){ V17state = newState; digitalWrite(V17PIN, newState);}   }   void V28(int newState)   { if (newState != V28state){ V28state = newState; digitalWrite(V28PIN, newState);}   }   void V35(int newState)   { if (newState != V35state){ V35state = newState; digitalWrite(V35PIN, newState);}   }   void V46(int newState)   { if (newState != V46state){ V46state = newState; digitalWrite(V46PIN, newState);}   }   void timing(int newState)     { if (newState != timingstate){ timingstate = newState; digitalWrite(timingPIN, newState);}      }   void pushstart(int newState)  { if (newState != pushstartstate){ pushstartstate = newState; digitalWrite(pushstartPIN, newState);}   }   void maintbutton(int newState){ if (newState != maintbuttonState){ maintbuttonState = newState; digitalWrite(maintbuttonPIN, newState);} }       volatile unsigned long PPRcounter = 0;    volatile unsigned long RCounter = 0;  // Rotational Counter- measure RPM   unsigned long start = 0;   unsigned long RPM = 0;                               //----- USED IN TIMING CONTROL- SEE BELOW   unsigned int a;  // First 180 degrees Open      unsigned int a1; // First 180 degrees Close   unsigned int b;  // Second 180 degrees Open   unsigned int b1; // Second 180 degrees Close                           // Used to count button pushes for Timing   int buttonpushcounter = 0;    int buttonstate = 0;    int lastbuttonstate = 0;             int startp; // Used when declaring Start Mode Function     int maint; // Used when declaring Maint Mode Function        LiquidCrystal lcd (9,8,7,6,5,4);      //============================================================================================    //------------------------------------------------------------------------INTERRUPTS       void IRQ_TDC() // when TDC Interrupt is rising it resets the PPRcounter every rotation    { PPRcounter = 0; RCounter++;    }   void IRQ_Angle()    // Angle Interrupt    {        a = 1;        b = 401;                         a1 = 400 - 40 * buttonpushcounter; // a1 is upper end of first half of crank angle                            if (buttonpushcounter == 0) a1 = a1 -1; // When buttonpushcounter equals 0, it demands a seperate function to equal 179 rather than 0                b1 = a1 + 400; // b1 is the upper end of the second half of crank angle        //------------- Controlling Valves        if (PPRcounter >= a && PPRcounter<= a1)         {       V17(OPEN);        V46(OPEN);      }       else       {      V17(CLOSE);       V46(CLOSE);     }      if (PPRcounter >= b && PPRcounter<= b1)      {     V35(OPEN);      V28(OPEN);   }     else     {    V35(CLOSE);     V28(CLOSE);    }    PPRcounter++;   }   //====================================================================================== //--------------------------------------------------------------------------SETUP      void setup()   { Serial.begin(115200); lcd.begin(16,2);        pinMode (V17PIN, OUTPUT); // Valve 1&7 as Output        pinMode (V35PIN, OUTPUT); // Valve 3&5 as Output        pinMode (V28PIN, OUTPUT); // Valve 2&8 as Output        pinMode (V46PIN, OUTPUT); // Valve 4&6 as Output        pinMode (pushstartPIN, INPUT); // Push Start Button Input        pinMode (timingPIN, INPUT); // Timing Button Input        pinMode (maintbuttonPIN, INPUT); // Maint Button Input    // TDC Interrupt connects to pin 2 attachInterrupt(0, IRQ_TDC, RISING); // Angle Interrupt connects to pin 3 attachInterrupt(1, IRQ_Angle, RISING); start = millis();   }//===================================================================================== //------------------------------------------------------------------------LOOP    void loop()   {       //----------------------------------  Button Counter Control- USED FOR TIMING CONTROL       buttonstate = digitalRead(timingPIN);       if ((buttonstate != lastbuttonstate) && (buttonstate == HIGH)){ buttonpushcounter++;} // If the buttonstate is greater than last, and it is high, increase counter       lastbuttonstate = buttonstate;       if( buttonpushcounter > 9) {buttonpushcounter = 0;} // If buttonstate has been pushed more than 9 times, reset to 0              lcd.setCursor(12,0);       lcd.print(100-10*buttonpushcounter); // print value of timing       lcd.print("%");              //-----RPM DISPLAY if (millis() - start > 1000) // once per second { start = millis(); RPM = RCounter * 60 + (PPRcounter * 60)/PPR;         lcd.print(RPM, DEC);                Serial.print(RCounter, DEC); Serial.print(", \t"); Serial.println(PPRcounter, DEC); Serial.print(", \t"); Serial.println(RPM, DEC); }        //-------------------START MODE           //startp = startmode();         // startp; // Calling Start Mode Function        //-------------------Maitenance Mode          maint = maintmode();          maint; // Calling Maint Mode Function   }//===================================================================================================//--------------------------------------------------------------FUNCTIONS //-------------------------------- Maint Mode Function int maintmode() {    maintbuttonState = digitalRead(maintbuttonPIN);   if (maintbuttonState == HIGH){     cli(); // disable interrupt     PPRcounter = 0; // Prevent any accidently Vavle firing if engine is turned     RCounter = 0;   //     lcd.clear();     lcd.print("Maintenance MODE");     digitalWrite(V28PIN,HIGH); // Open all Exhaust and stay open as long as maintbutton is high     digitalWrite(V46PIN,HIGH);  }         }//=================================================================================================== //----------------------------- Start Mode Function //TO BE WORKED ON `

#### robtillaart

#25
##### Mar 19, 2011, 12:59 pm
Quote
What do you mean set a global variable for state? What would that do?

What I meant that instead of displaying the state of the valve in the IRQ (which takes to much time) you can set a global variabele to reflect the state of every valve as I did with the  V17() example. Then the normal loop can do the display but it will be too fast to follow. You might add a LED to reflect the state, might be visible.

Quote

Quote
next two lines invalid
timing = timingcontrol(); //
timing; // Calling Timing Control Function

For my own curiosity, what makes these invalid?

Code: [Select]
` int timingcontrol(){  a = 1;  b = 401;  a1 = 400 - 40 * buttonpushcounter; // a1 is upper end of first half of crank angle  if (buttonpushcounter ==0) a1 = a1 -1;  // When buttonpushcounter equals 0, it demands a seperate function to equal 179 rather than 0  b1 = a1 + 400; // b1 is the upper end of the second half of crank angle  lcd.setCursor(12,0);  lcd.print(100-10*buttonpushcounter); // print value of timing  lcd.print("%");} `

1) timingcontrol() does not return a value although its signature states it should return an int.
2) "timing; // Calling Timing Control Function"  does not call anything,  you use a variable as statement.

Quote
If you added the timing function directly into the interrupt, how is that reducing it?

first - I removed the function call
second - and more important - I only copied the math part, not the calls to LCD.....()
in short I only copied the absolutely necessary code into the IRQ

Quote
int V17state= 0;
void V17(int newState)
{
if (newState != V17state)
{
V17state = newState;
digitalWrite(V17PIN, newState);
}
}
Explain to me the purpose of this code? I thought I understood it but, I apparently don't.

First: there is a global variable to hold the state of the valve.
If a call to V17 is made, the newstate is compared to the state of the valve and if they differ the newstate is remembered and the digitalwrite() to actuate the valve is done.
// as said earlier you could add a LED to the pins simulating the valves

Quote
What makes this invalid? I followed a playground post along time ago, but more importantly, I can't get it to compile if I do what you suggest...

Same pattern/problem as with the call to Timingcontrol() discussed above. Can you provide an URL to the example you mention?

Quote
Definitely don't want the interrupts to ever be enabled when my hands are touching the gears and valves.

You better take off all the power when touching the G&V's, if a switch bounces or there is a loose wire, bad things might happen, you would not be the first (or last one)

Hopes the above makes sense, otherwise let me know.

Will take a look at your latest code later today,

Rob

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### Newman180

#26
##### Mar 19, 2011, 02:08 pmLast Edit: Mar 19, 2011, 02:10 pm by Newman180 Reason: 1
Quote

Quote
next two lines invalid
timing = timingcontrol(); //
timing; // Calling Timing Control Function

For my own curiosity, what makes these invalid?

Code: [Select]
` int timingcontrol(){  a = 1;  b = 401;  a1 = 400 - 40 * buttonpushcounter; // a1 is upper end of first half of crank angle  if (buttonpushcounter ==0) a1 = a1 -1;  // When buttonpushcounter equals 0, it demands a seperate function to equal 179 rather than 0  b1 = a1 + 400; // b1 is the upper end of the second half of crank angle  lcd.setCursor(12,0);  lcd.print(100-10*buttonpushcounter); // print value of timing  lcd.print("%");} `

1) timingcontrol() does not return a value although its signature states it should return an int.
2) "timing; // Calling Timing Control Function"  does not call anything,  you use a variable as statement.

Weird thing is, it seemed to work when testing with my old code, or at least the LCD printout side of it. It would calculate the button presses and display the correct %.

Quote

If you added the timing function directly into the interrupt, how is that reducing it?
first - I removed the function call
second - and more important - I only copied the math part, not the calls to LCD.....()
in short I only copied the absolutely necessary code into the IRQ

understood

Quote

int V17state= 0;
void V17(int newState)
{
if (newState != V17state)
{
V17state = newState;
digitalWrite(V17PIN, newState);
}
}
Explain to me the purpose of this code? I thought I understood it but, I apparently don't.

First: there is a global variable to hold the state of the valve.
If a call to V17 is made, the newstate is compared to the state of the valve and if they differ the newstate is remembered and the digitalwrite() to actuate the valve is done.
// as said earlier you could add a LED to the pins simulating the valves

Understood, so basically it prevents the valve from trying to open if it is already open, and vise versa
I tried the LED idea a while back, but had an issue with the signal becoming grounded, and the mosfets not reacting...Not something I'm worried about right now though. The valves are loud enough I will know which one is which

Quote

What makes this invalid? I followed a playground post along time ago, but more importantly, I can't get it to compile if I do what you suggest...
Same pattern/problem as with the call to Timingcontrol() discussed above. Can you provide an URL to the example you mention?

I cannot find the better of the two guides. It might have been a post in the old forum, but this seems to be close enough http://www.arduino.cc/en/Reference/FunctionDeclaration  Maybe I'm applying it wrong? As state before though, the way I'm calling seems to work. Maint works, Start mode (when I had it) works.

Quote

Definitely don't want the interrupts to ever be enabled when my hands are touching the gears and valves.
You better take off all the power when touching the G&V's, if a switch bounces or there is a loose wire, bad things might happen, you would not be the first (or last one)

Problem is, the valves are normally closed, and I can't spin the engine with all of them closed. I'll attempt to think of an alternative.

Quote

Hopes the above makes sense, otherwise let me know.

Will take a look at your latest code later today,

Rob

Absolutely. Thanks!

#### robtillaart

#27
##### Mar 20, 2011, 01:37 pm

Quote
Weird thing is, it seemed to work when testing with my old code, or at least the LCD printout side of it. It would calculate the button presses and display the correct %.

Yes that part will work,

Code: [Select]
`[color=red]int [/color]timingcontrol(){  a = 1;  b = 401;  a1 = 400 - 40 * buttonpushcounter; // a1 is upper end of first half of crank angle  if (buttonpushcounter ==0) a1 = a1 -1;  // When buttonpushcounter equals 0, it demands a seperate function to equal 179 rather than 0  b1 = a1 + 400; // b1 is the upper end of the second half of crank angle  lcd.setCursor(12,0);  lcd.print(100-10*buttonpushcounter); // print value of timing  lcd.print("%");  [color=red]return 5;[/color]} timingControl() is a function that according to its definition should return an int but it does not. I added the red code to see what is missing. The compiler will not accept this.The call    timing = timingcontrol();   is correct but as timingcontrol does not return a value it makes no sense.The call     timing;   is using a variable as a statement; Afaik it does not do anything, so it is useless. [quote]Problem is, the valves are normally closed, and I can't spin the engine with all of them closed. I'll attempt to think of an alternative.[/quote]You might consider a switch that when set automatically disables the interrupts and set all valves in a closed (or open) position. This switch should imho be in the powersupply of the valves. NOt indirectly through the Arduino.2 cnts,Rob`
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

#### wildbill

#28
##### Mar 20, 2011, 03:08 pm
Interesting project. I'm struggling with understanding your code though, especially the IRQ_Angle routine. What is buttonpushcounter? It appears to be used to calculate the angle the crank has reached, but I thought that your encoder was already giving you that at ~half degree accuracy. Is it a switch that is triggered 10 times a rev? Also, just to help with visualizing it - what is each value? From one of the comments, I'm guessing that 2,4,6 and 8 are exhaust, so I assume that the others are intake. Further to that, what is their cycle of operation as the crank rotates?

The RPM calc doesn't look right, As far as I can see, RCounter counts the total revolutions and the RPM number is being further adjusted by the current fraction of a rev, but there's no consideration of elapsed time. The RPM number will just rise as the program runs.

#### robtillaart

#29
##### Mar 20, 2011, 03:25 pm
Quote
Interesting project. I'm struggling with understanding your code though, especially the IRQ_Angle routine.

The encoder gives a number of pulses per revolution. These must be counted to get the angle the shaft is in, the encoder does not provide this info directly.
See - http://products.cui.com/CUI_AMT103-V_Product_Training_Presentations.pdf?fileID=6203 page 6 for a model of the encoder used.

The X line (or I in the picture) gives one pulse per rotation. So it is used to reset the angle counter to zero.

Quote
What is buttonpushcounter?

It is a button used to set the timing of valves.

(skipped some questions)

Quote

The RPM calc doesn't look right, As far as I can see, RCounter counts the total revolutions and the RPM number is being further adjusted by the current fraction of a rev, but there's no consideration of elapsed time. The RPM number will just rise as the program runs.

You are right, the Rcounter should be reset to 0 after displaying - in loop() -

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Go Up