Wind speed calculations based on sensors inout become unstable over long usage

Hi

I am using an Arduino R3 to process voltages from a wind speed anemometer and wind direction vane. I am then using an Ethernet Shield to send the data via UDP to a computer where the data is used for further processing.

The sketch works fine when I first turn the Arduino on and the wind data appears to be inline with reality.

I leave the anemometer and Arduino in a working state and then after a period of time when I return to it I am experiencing sporadic jumps in the data with a repeated high wind speed output of 76mph which is definitely not in line with what is going on. Unfortunately I do not know exactly how long it is before the data is getting muddled.

I have had some concerns about the heat that the Ethernet shield generates and I know that this has been spoken about on other threads.... Could this possibly be responsible for the calculation output?

I've been racking my brain with it and can't see why it would be outputting sporadic numbers after a period of time and not when it is first turned on??? :o :confused:

My code is as follows.... The wind direction part of the code works fine so please ignore that (Also please excuse the messy bits).

#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h> // UDP library from: bjoern@cs.stanford.edu 12/30/2008

byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 177);
IPAddress subnet(255, 255,0,0);
IPAddress gateway(192, 168, 1, 2);
IPAddress dnServer(192, 168, 1, 1);
IPAddress remote(192, 168, 1, 178);
int portremote(6000);

unsigned int localPort = 8888;

int windSpeed; //WindSpeed VAR
String windSpeedString;
String windDirectionString;

int pin = 2; // wind speed in pin number
float windSpeedCon = 2.453; //1.492; old constant //Constant for MPH/Revolution
int windDirection = 0;
int direction1;
int direction2;

volatile unsigned long previous; // time stamps
volatile unsigned long current;

char ReplyBuffer[3];
char ReplyBuffer2[4];

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {

pinMode(pin, INPUT);
current = millis(); // prime the time stamp
attachInterrupt(digitalPinToInterrupt(pin), anemometerISR, RISING); // on a rising edge call the ISR to update the timestamps stored

// start the Ethernet and UDP:
Ethernet.begin(mac,ip,dnServer,gateway,subnet); //
Udp.begin(localPort);

}

void loop() {

// Wind speed calculation

windSpeed = windSpeedCon * 500 / (current - previous);
windSpeedString = String(windSpeed, DEC);

windDirectionString = String(windDirection, DEC);
windDirectionString.toCharArray(ReplyBuffer2, 4);

direction1 = analogRead(0);
direction2 = analogRead(1);

// Wind direction calculation - Based on ADC Value, assign and display direction.

if ( (direction1 >= 530) && (direction1 < 703) && (direction2 >= 320 ) && (direction2 < 346 )) { //NORTH
windDirection = 45;
}
else if ( (direction1 >= 703) && (direction1 < 729) && (direction2 >= 329 ) && (direction2 < 353 )) { //NORTH NORTH EAST
windDirection = 67.5;
}
else if ( (direction1 >= 729) && (direction1 < 806 ) && (direction2 >= 353 ) && (direction2 < 411 )) { //NORTH EAST
windDirection = 90;
}
else if ( (direction1 >= 806) && (direction1 < 838) && (direction2 >= 411 ) && (direction2 < 519 )) { //EAST NORTH EAST
windDirection = 112.5;
}
else if ((direction1 >= 838) && (direction1 < 948) && (direction2 >= 519 ) && (direction2 < 725 )) { //EAST
windDirection = 135;
}
else if ((direction1 >= 902) && (direction1 < 948) && (direction2 >= 725 ) && (direction2 < 826 ) ) { //EAST SOUTH EAST
windDirection = 157.5;
}
else if ((direction1 >= 813) && (direction1 < 902) && (direction2 >=826 ) && (direction2 < 915 )) { //SOUTH EAST
windDirection = 180;
}
else if ((direction1 >= 706) && (direction1 < 813) && (direction2 >= 915 ) && (direction2 < 958)) { //SOUTH SOUTH EAST
windDirection = 202.5;
}
else if ((direction1 >= 579) && (direction1 < 706) && (direction2 >= 953 ) && (direction2 < 965 )) { //SOUTH
windDirection = 225;
}
else if ((direction1 >= 479) && (direction1 < 579) && (direction2 >= 908 ) && (direction2 < 953 )) { //SOUTH SOUTH WEST
windDirection = 247.5;
}
else if ((direction1 >= 397) && (direction1 < 479) && (direction2 >=813 ) && (direction2 < 908 )) { //SOUTH WEST
windDirection = 270;
}
else if ((direction1 >= 352) && (direction1 < 397) && (direction2 >= 686 ) && (direction2 < 813)) { //WEST SOUTH WEST
windDirection = 292.5;
}
else if ((direction1 >= 352) && (direction1 < 361) && (direction2 >= 582 ) && (direction2 < 686)) { //WEST
windDirection = 0;
}
else if ((direction1 >= 361) && (direction1 < 415) && (direction2 >= 469 ) && (direction2 < 582 )) { //WEST NORTH WEST
windDirection = 22.5;
}
else if ((direction1 >= 415) && (direction1 < 502) && (direction2 >= 392 ) && (direction2 < 469 )) { //NORTH WEST
windDirection = 315;
}
else if ((direction1 >= 502) && (direction1 < 619) && (direction2 >= 354 ) && (direction2 < 392 )) { //NORTH NORTH WEST
windDirection = 237.5;
}

////////////////////////////////////////////////////////////////////

if (millis() % 3000 == 0 ){ // Send the data via UDP every 3 seconds

Udp.beginPacket(remote, portremote);
Udp.write("WD");
Udp.write(ReplyBuffer2);
Udp.write("WS");
Udp.write(ReplyBuffer);
Udp.write("E");
Udp.endPacket() ;

}

}

void anemometerISR(){ // Anemometer interupt sub routine

previous = current;

current = millis();

}

I would stop using Strings and use dtostrf() to convert float to char[] instead.


windSpeed = windSpeedCon  * 500 / (current - previous);

Both current & previous are ISR variables bigger than a byte size so you should protect there reading by disabling/enabling interrupts around them. A better way might be to just count pulses in the ISR and in loop divide pulses by time since last read to get speed.
What happens if there is no wind and current/previous are the same values (divide by zero)


if (millis() % 3000 == 0 ){                            // Send the data via UDP every 3 seconds

Might not be every 3 seconds if millis() is not an exact multiple of 3000 when you hit this statement.


    Udp.write("WS");
    Udp.write(ReplyBuffer);

Nowhere in the code you posted do you update ReplyBuffer so assuming this is the Wind Speed value it will never change.

Thank you very much for your reply... I will have a look at the points you have raised and see how it goes.

With regards to the last point, that bit of code accidentally got deleted when I was "tidying it up" before posting it on here. :-/

Thanks again Riva.