Go Down

Topic: Measure Rotational Speed of a Stirling Engine (Read 2638 times) previous topic - next topic

saduino

Feb 05, 2013, 10:48 am Last Edit: Feb 07, 2013, 08:00 am by saduino Reason: 1
Hi

I try to measure the rotational speed of my own build Stirling engine. And I want to display the actual speed on a 4 x 7 segment display.
So I thought it's the best way doing this like an encoder. So I build a paper circle, with one half black and the other half white. Then I use a photo resistor for the detection. Now that I don't miss any crossover (black / white) I use the comparator and their interrupt. I give on the positive comparator pin PD7 a reverence voltage with a potentiometer, this is lower than the voltage I get over the white section with the photo resistor an higher than over the black section. Every time when the photo resistor comes from black to white the counter should increase 1 in the interrupt.

But now my Problem: This isn't very accurate, because sometimes the counter increases 2 or more on the black-white crossover. I think this is because the analog signal isn't very accurate in the crossover section so the analog value swing a little bit.

Do you have any idea, how I can solve that problem?

My code:
Code: [Select]

#define F_CPU 16000000L
#define ARDUINO 101

#include <avr/interrupt.h>
#include <avr/io.h>
#include "stdint.h"
#include <math.h>
// Arduino Library
#include "Arduino.h"
// additional header files

// prototype functions
uint8_t displayValue(int Value);

// button pin
#define buttonPin       13
// photo resistor analog pin
#define photoAnalogPin  A0
// display pins high
#define NumberHIGH      4
uint8_t pinHIGH[NumberHIGH] = {12,11,10,9};
// display pins low
#define NumberLOW       7
uint8_t pinLOW[NumberLOW] = {17,3,5,16,8,4,2};
// numbers
uint8_t Numbers[10] = {0b11111100,
                      0b01100000,
                      0b11011010,
                      0b11110010,
                      0b01100110,
                      0b10110110,
                      0b10111110,
                      0b11100000,
                      0b11111110,
                      0b11110110};
// special characters
uint8_t Minus = 0b00000010;

//
int sensorValue = 0;
float rotationSpeed = 0;

// button state
bool buttonState = false;
bool lastButtonState = false;

// measurement state
bool measurementState = false;
bool sensorState = false;

// sensor
int stateCounter = 0;

// time
long double startTime = 0;
long double recentTime = 0;
long double stopTime = 0;


// interrupt
ISR(ANALOG_COMP_vect)
{
   if (measurementState)
       stateCounter++;
}


int main(void)
{
   // initialize
   init();
   
   // serial output
   Serial.begin(9600);
   
   // set pins for 7 segment display
   for (int i=0; i<NumberHIGH; i++)
       pinMode(pinHIGH[i],OUTPUT);
   for (int i=0; i<NumberHIGH; i++)
       digitalWrite(pinHIGH[i],LOW);
   for (int i=0; i<NumberLOW; i++)
       pinMode(pinLOW[i],OUTPUT);
   for (int i=0; i<NumberLOW; i++)
       digitalWrite(pinLOW[i],HIGH);
   pinMode(buttonPin,INPUT);
   
   // enable interrupt
   sei();
   
   // initialize comparator
   pinMode(6,INPUT);
   pinMode(7,INPUT);
   digitalWrite(6,LOW);
   digitalWrite(7,LOW);
   
   // initialize interrupt
   ACSR =
   (0<<ACD)   |   //analog comparator: enabled
   (0<<ACBG)  |   //analog comp bandgap select: AIN0 is positive input
   (1<<ACIE)  |   //analog comp interrupt: enabled
   (0<<ACIC)  |   //analog comp input capture: disabled
   (1<<ACIS1) | (0<<ACIS0);   //analog comp interrupt mode: rising
   
   DIDR1 = (0<<AIN1D) | (0<<AIN0D);

   
   // start program
   while(1)
   {
       // display value on 4 x 7 segment display
       displayValue((int)rotationSpeed);
       
       /*
       Serial.print("Sensor: ");
       Serial.println(analogRead(A0));
       Serial.print("Poti: ");
       Serial.println(analogRead(A5));
       delay(500);
       */
       
       // get button state
       buttonState = digitalRead(buttonPin);
       // start/stop measurement
       if (buttonState != lastButtonState)
       {
           if (buttonState) // stop measurement
           {
               Serial.println("on");
               if (measurementState)
               {
                   measurementState = false;
                   Serial.println("measurement Stop");
                   stopTime = millis();
               }
               else // start measurement
               {
                   stateCounter = 0;
                   rotationSpeed = 0;
                   measurementState = true;
                   Serial.println("measurement Start");
                   startTime = millis();
               }                    
           }
           else
           {
               Serial.println("off");
           }
       }
       lastButtonState = buttonState;
       
       if (measurementState)
       {
           if (stateCounter >= 100)
           {
               int lastStateCounter = stateCounter;
               stateCounter = 0;
               
               stopTime = millis();
               // get time
               float time = (float)(stopTime-startTime)/(float)1000;
               Serial.print("Time (seconds): ");
               Serial.println(time);
               // get numer of rotations
               float numberRotation = lastStateCounter;
               Serial.print("Number of rotations: ");
               Serial.println(numberRotation);
               // calculate rotation speed
               rotationSpeed = (float)numberRotation/(float)time;
               Serial.print("Rotational speed: ");
               Serial.print(rotationSpeed);
               Serial.println(" 1/s");
               
               startTime = millis();
           }
       }
   }
return 0;
}



// display the value on the 4 x 7 segment display
uint8_t displayValue(int Value)
{
   // reset led
   for (int i=0; i<4; i++)
       digitalWrite(pinHIGH[i],LOW);
   for (int i=0; i<7; i++)
       digitalWrite(pinLOW[i],HIGH);
   
   // set led
   for (int a=0; a<4; a++)
   {
       // split value
       int aValue = (Value % (int)pow(10,(a+1))) / pow(10,a);
       // don't display zeros
       if (a > 0 && aValue == 0 && Value < (int)pow(10,(a+1)))
           break;
       
       // display
       // led on
       digitalWrite(pinHIGH[a],HIGH);
       for (int i=0; i<7; i++)
       {
           digitalWrite(pinLOW[i],!(Numbers[aValue] << i & 0x80));
       }
       delay(1);
       // led off
       digitalWrite(pinHIGH[a],LOW);
       for (int i=0; i<7; i++)
           digitalWrite(pinLOW[i],HIGH);
       
       Value -= aValue;
   }
   
   return 0;
}


Thanks.

Sam

robtillaart

don't use an analog sensor but a digital one and connect it to the attach interrupt.

Often used constructs are a small magnet and a hall sensor. if you search for "hall sensor arduino " you will get enough hits...
Rob Tillaart

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

saduino

Hi robtillaart

thank you, I'll buy a hall sensor and try it with this.

michinyon

I don't think you need an encoder,   as you don't need to estimate the rotational position of the shaft,  or fractions of a revolution.

It would be easier, I would think,  to just use a hall effect sensor and count the whole revolutions.

saduino


I don't think you need an encoder,   as you don't need to estimate the rotational position of the shaft,  or fractions of a revolution.

It would be easier, I would think,  to just use a hall effect sensor and count the whole revolutions.


yes, that's exactly what I will do...

robtillaart

Can you tell more about how you build the Stirling engine?
pictures?
youtube?
Rob Tillaart

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

saduino

it's my brothers work http://www.youtube.com/watch?v=RrHCN-AQ6i4 and I have to measure the rotation speed ;), as accurate as possible.
The first tests with the hall effect sensor seems to be good, I will post soon a youtube video with the result.

robtillaart

cool! (or must I say hot ! ;)

you can also trigger on the horizontal movement of the cylinder!
Rob Tillaart

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

saduino

#8
Feb 08, 2013, 04:32 pm Last Edit: Feb 08, 2013, 04:36 pm by saduino Reason: 1
Here is the result:

http://www.youtube.com/watch?feature=player_embedded&v=aSU9DES79V4

the maximum rotation speed was about 1474 rpm.

robtillaart

Rob Tillaart

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

Go Up