Go Down

### Topic: Measure Rotational Speed of a Stirling Engine (Read 3438 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"

// 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.print("Poti: ");
delay(500);
*/

// get button state
// 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

#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

Please enter a valid email to subscribe