Pages: 1 [2] 3   Go Down
Author Topic: Compressed Air Engine - Rotary Encoder  (Read 4080 times)
0 Members and 1 Guest are viewing this topic.
Central Europe
Offline Offline
Edison Member
*
Karma: 6
Posts: 1220
Use the Source, Luke.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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
Logged

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

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.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


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.
Logged

Rob Tillaart

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

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


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.
Logged

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

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
Logged

Vic Fraenckel
KC2GUI
windswaytoo ATSIGN gmail DOT com

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

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?
Logged

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

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:
//=====================================================================================
//
//
//
//=====================================================================================

   #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
 
 
« Last Edit: March 17, 2011, 09:07:37 pm by Newman180 » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
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:
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.

Logged

Rob Tillaart

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

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

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 smiley-confuse


Quote
A redo to minimize the irq routine
Code:
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:
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. smiley-wink

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.

Logged

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


Here's the updated code as of my remarks and your suggestions
Code:
//=====================================================================================
//
//
//
//=====================================================================================

   #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
 

Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?

your code
Code:
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




Logged

Rob Tillaart

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

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

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

For my own curiosity, what makes these invalid?

your code
Code:
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 smiley-wink

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!
« Last Edit: March 19, 2011, 08:10:57 am by Newman180 » Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset



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:
[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




Logged

Rob Tillaart

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

New Jersey
Offline Offline
Faraday Member
**
Karma: 51
Posts: 3438
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 170
Posts: 12487
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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() -

Logged

Rob Tillaart

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

Pages: 1 [2] 3   Go Up
Jump to: