Go Down

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

##### Feb 05, 2013, 10:48 amLast 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 functionsuint8_t displayValue(int Value);// button pin#define buttonPin       13// photo resistor analog pin#define photoAnalogPin  A0// display pins high#define NumberHIGH      4uint8_t pinHIGH[NumberHIGH] = {12,11,10,9};// display pins low#define NumberLOW       7uint8_t pinLOW[NumberLOW] = {17,3,5,16,8,4,2};// numbersuint8_t Numbers[10] = {0b11111100,                       0b01100000,                       0b11011010,                       0b11110010,                       0b01100110,                       0b10110110,                       0b10111110,                       0b11100000,                       0b11111110,                       0b11110110};// special charactersuint8_t Minus = 0b00000010;//int sensorValue = 0;float rotationSpeed = 0;// button statebool buttonState = false;bool lastButtonState = false;// measurement statebool measurementState = false;bool sensorState = false;// sensorint stateCounter = 0;// timelong double startTime = 0;long double recentTime = 0;long double stopTime = 0;// interruptISR(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 displayuint8_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

#1
##### Feb 05, 2013, 08:10 pm
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)

#2
##### Feb 05, 2013, 09:59 pm
Hi robtillaart

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

#### michinyon

#3
##### Feb 06, 2013, 07:32 am
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.

#4
##### Feb 06, 2013, 01:41 pm

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

#5
##### Feb 06, 2013, 09:10 pm
Can you tell more about how you build the Stirling engine?
pictures?
Rob Tillaart

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

#6
##### Feb 06, 2013, 10:03 pm
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

#7
##### Feb 06, 2013, 10:08 pm
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)

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

the maximum rotation speed was about 1474 rpm.

#### robtillaart

#9
##### Feb 08, 2013, 06:21 pm
A nice piece of "stirluino" !
Rob Tillaart

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

Go Up