Go Down

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

Korman

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

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


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



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

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
Vic Fraenckel
KC2GUI
windswaytoo ATSIGN gmail DOT com

Newman180


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 am Last 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

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

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


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

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: [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 pm Last 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?

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



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

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

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