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:
#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