Without seeing your schematic, I suspect the source of the problem is bounce during the rising signal state change. I also suspect that just adding software debounce would vastly improve, if not eliminate the problem. Care to post a link to your sensor and your interface circuit?
Yes, the averaging could be done in code (there's lots of examples here in the Forum and in the Playground). I should have asked this earlier ... what is the hall sensor used for? (the wind sensor already has various output types (0-5V, 4-20mA, serial 232/485)
What is the relay pin used for?
Could you post a diagram on how you have everything connected?
I think it would be good to make sure the signals and connections are correct prior to averaging the readings.
the hall sensor is measuring RPM of the generator and connect it to the grid via a relay when it comes up over 1500 rpm
and switches it off when the revs are below 1500.
I am pretty sure that everything is connected properly in arduinoen, I measure the correct rpm if I keep the generator on without there is wind blowing on the wings.
the problem is that the wind run up and down rapidly, causing the relay to trip unnecessarily.
so I must find a way to find the average of the revolution.
There are many ways. One way is to slow down the update interval by counting more pulses before calculating the rpm. Could get the equivalent of 10 existing updates averaged just by changing
if (half_revolutions >= 20) {
to
if (half_revolutions >= 200) {
but the rpm update rate will be 10x slower.
If you need the rpm to update to be faster (like it is now) then you would need to add more code that averages or "smooths" multiple rpm values.
brunokc:
I would like to have the average of the last 50-100 measurements.
To measure the average current on a PWM pulsed LED, I used a Modified Moving Average to calculate the average. It has the benefit of faster calculation and less memory, when compared to a standard moving average. You don't need to keep the last 100 measurements. The concept is used quite a bit in the financial world, works great for calculating the average of a PWM like waveform.
Now I've tried it, wind sensor seems to work better now, but the hall sensor show 1000 revs too much and is still very unstable.
Forgot to mention that your code should use micros() instead of millis() because the low timing resolution creates larger and larger jumps in your calculated rpm readings as the input frequency increases. This could be the main reason for the unstable readings you're getting.
dlloyd:
Forgot to mention that your code should use micros() instead of millis() because the low timing resolution creates larger and larger jumps in your calculated rpm readings as the input frequency increases. This could be the main reason for the unstable readings you're getting.
When i change millis() to micros() the rpm show 0.
I've tried to "smooths" RPM, but when the RPM is at 1450-1550 rpm so shows the 205 average. but it is much more stable.
Can you explain to me why it does not show 1,500 rpm?
Here is the code:
#include <LiquidCrystal_I2C.h>
int onRpm = 1500; //Omdr kontaktor tænder ved.
const int numReadings = 50;
int readings[numReadings]; // the readings from the analog input
int readIndex = 0; // the index of the current reading
int total = 0; // the running total
int average = 0; // the average
#define I2C_ADDR 0x3F // <<- Add your address here.
#define Rs_pin 0
#define Rw_pin 1
#define En_pin 2
#define BACKLIGHT_PIN 3
#define D4_pin 4
#define D5_pin 5
#define D6_pin 6
#define D7_pin 7
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);
volatile byte half_revolutions;
unsigned int rpm;
unsigned long timeold;
int windpin = 0;
int relaypin = 9;
int diodePin = 13;
void setup()
{
Serial.begin(115200);
attachInterrupt(0, magnet_detect, RISING);//Initialize the intterrupt pin (Arduino digital pin 2)
half_revolutions = 0;
rpm = 0;
timeold = 0;
pinMode(relaypin, OUTPUT);
digitalWrite(relaypin, LOW);
lcd.begin (20,4); // <<-- our LCD is a 20x4, change for your LCD if needed
// LCD Backlight ON
lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE);
lcd.setBacklight(HIGH);
lcd.clear(); // start with a blank screen
lcd.setCursor(0,0);
lcd.print(" Cs Wind Power");
lcd.setCursor(0,1);
lcd.print("Omdr = ");
lcd.setCursor(0,2);
lcd.print("Vind = ");
lcd.setCursor(0,3);
lcd.print("Relay = ");
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
}
}
void loop()//Measure RPM
{
if (half_revolutions >= 10) {
rpm = 30*1000/(millis() - timeold)*half_revolutions;
timeold = millis();
half_revolutions = 0;
Serial.println(rpm);
}
total = total - readings[readIndex];
readings[readIndex] = rpm;
total = total + readings[readIndex];
readIndex = readIndex + 1;
if (readIndex >= numReadings) {
readIndex = 0;
}
average = total / numReadings;
if (average > 190){
digitalWrite(relaypin, HIGH);
}
else{
digitalWrite(relaypin, LOW);
}
int val = analogRead(windpin);
float outputVolt = val * (5.0 / 1023);
int windSpeed = 6.5 * outputVolt;
int windspeed1 = map(val, 204, 1023, 0, 32);
lcd.setCursor(8,1);
lcd.print(rpm);
lcd.setCursor(14,1);
lcd.print(average);
lcd.print(" ");
lcd.setCursor(8,2);
lcd.print(windspeed1);
lcd.print(" ");
lcd.setCursor(12,2);
lcd.print(outputVolt);
lcd.print("v ");
lcd.setCursor(8,4);
if (digitalRead(relaypin) == 1){
lcd.print("On ");
}
if (digitalRead(relaypin) == 0){
lcd.print("OFF");
}
delay(200);
Serial.println(average);
}
void magnet_detect()//This function is called whenever a magnet/interrupt is detected by the arduino
{
half_revolutions++;
}
I think the signal needs debouncing ... you're probably averaging multiple false readings near 0 and that's throwing off the average. I don't think you need averaging until it's determined how stable the your true readings really are.
You can try this test code ... software debounce is included (stableTime = 1000µs). No averaging is implimented. You can self test with a 100Hz timer by connecting a jumper wire from pin 9 or 10 to pin 2. The reading should be 3000 (half revolutions). Then remove the jumper and connect your singal to pin 2 (INT0) and see what you get for RPM readings.