Pages: [1]   Go Down
Author Topic: Measure Rotational Speed of a Stirling Engine  (Read 2487 times)
0 Members and 1 Guest are viewing this topic.
Switzerland
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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
« Last Edit: February 07, 2013, 02:00:11 am by saduino » Logged

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

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

Rob Tillaart

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

Switzerland
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi robtillaart

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

Offline Offline
Faraday Member
**
Karma: 62
Posts: 3080
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Switzerland
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

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

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

Rob Tillaart

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

Switzerland
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

it's my brothers work and I have to measure the rotation speed smiley-wink, 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.
Logged

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

cool! (or must I say hot ! smiley-wink

you can also trigger on the horizontal movement of the cylinder!
Logged

Rob Tillaart

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

Switzerland
Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is the result:



the maximum rotation speed was about 1474 rpm.
« Last Edit: February 08, 2013, 10:36:46 am by saduino » Logged

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

A nice piece of "stirluino" !
Logged

Rob Tillaart

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

Pages: [1]   Go Up
Jump to: