Go Down

Topic: Arduino Pro and Anemometer (Reading Pulse Times) (Read 3 times) previous topic - next topic

PaulS

Quote
Since my signals are close to squares, could I send them through the digital pins (2,3). How would I handle the interrupt if now I have two different signals that I will need to compare?

The answer to the first question is yes. But, I wouldn't. I'd use 4 and 5. Or use 2 and 3, but attach interrupt handlers to the two pins (they are the external interrupt pins). Each ISR would fire on the RISING edge or the FALLING edge. In each ISR, record when the interrupt occured. In loop, look at the relative times.

DynamiK

Quote
Are you sure your wind vane uses a reed switch? Don't think I've ever seen one of those, unless it uses several switches to indicate wind sectors.

Yes, it does implement reed switches. Two in fact (one associated with the three cup system and one for the wind vein). You can find speed relative to one switch and seeing how fast the switch turns on and off. To find direction you have to measure the shift between the two pulses.

Quote
The answer to the first question is yes. But, I wouldn't. I'd use 4 and 5. Or use 2 and 3, but attach interrupt handlers to the two pins (they are the external interrupt pins). Each ISR would fire on the RISING edge or the FALLING edge. In each ISR, record when the interrupt occured. In loop, look at the relative times.


I guess I am just confused on how the data will be stored. If I attach my pins to 2 and 3 using and use 2 attathinterrupts instead of two

Quote

attachInterrupt(0, arduino_anemometer, RISING);
attachInterrupt(1, arduino_anemometer, RISING);


in my loop function if digital pin 2 triggers on the rising and digital pin 3 rises while pin 2 is high, will the data I have for stored while using Pin 2 be erased?

for example...


Quote

   //Calculating Speed Duration
SpeedDuration = (millis() - SpeedTimePrevious);
SpeedTimePrevious = millis();


if (SpeedTimePrevious  >  DirectionTimePrevious)
{
DirectionDuration = (millis() - DirectionTimePrevious);
DirectionTimePrevious = millis();
DirectionTimePeriod = (DirectionTimePrevious - DirectionTimePrevious1);
}

// Calculates Frequency between DIRECTION signals
DirectionTimePrevious1 = DirectionTimePrevious;
Frequency = 1/DirectionTimePeriod;

// Calculates time difference between SPEED and DIRECTION signals
if (DirectionTimePrevious != 0 )   // Ensures that Direction must occur second
{
TimeDifference = (SpeedTimePrevious - DirectionTimePrevious);
}


I would only want my SpeedDuration to trigger only when pin 2 rises. Does that mean I have to create a new subroutine outside of loop to account for this? Will this data be erased when pin 3 triggers with an interrupt? Can I compare the Time Difference in the loop if they are being handled in the interrupt subroutine?


DynamiK

So I tried doing a simple loop.

My signal is low and for some reason count is incrementing, because the values being printed out for SpeedDuration and SpeedTimePrevious are nonzero.

Quote
setup()
{
attachInterrupt(0, arduino_anemometer, RISING);
attachInterrupt(1, arduino_direction, RISING);
}

void loop()
{

if (count = 1)
{
   //Calculating Speed Duration
SpeedDuration = (millis() - SpeedTimePrevious);
SpeedTimePrevious = millis();
Serial.print("Speed: ");
Serial.println(SpeedDuration, DEC);
Serial.println(SpeedTimePrevious, DEC);
delay(1000);

}

Serial.print("Speed2: ");
Serial.println(DirectionTimePrevious, DEC);
delay(1000);

count=0;
directioncount=0;
}

void arduino_anemometer()
{
count++
}

void arduino_direction()
{
directioncount++
}

PaulS

Code: [Select]
if (count = 1)
This is an assignment statement, not an equality test.

You would not want to test for equality, anyway. You want to do something when count > 0, not any specific value greater than 0.

Are count and directionCount volatile?

In order to get good timing data, the time the interrupt occured needs to be recorded in the ISRs. Finally, while didling with the time and count values, you really should disable interrupts, so you are not interrupted during the computations. Re-enable them when done.

And last, but not necessarily least, GET RID OF THE delay()s. You probably want to only calculate and output speed and direction once every few seconds, but don't use delay to make that happen.

DynamiK

So this is the data that I am getting now. (code is posted below)
Quote








Count: 0
Speed: 0
DirectionCount: 0
Speed Time: 0
Direction Time: 0
Time Difference: 0
DirectionTimePeriod: 0
Speed: 4294967295
Direction: 4294967295
Time: 2861


Count: 3
Speed: 820
DirectionCount: 3
Speed2: 11790
Speed Time: 11632
Direction Time: 11790
Time Difference: 158
DirectionTimePeriod: 820
Speed: 1312478
Direction: 69
Time: 12382


Count: 2
Speed: 821
DirectionCount: 3
Speed2: 14252
Speed Time: 14094
Direction Time: 14252
Time Difference: 158
DirectionTimePeriod: 821
Speed: 1310880
Direction: 69
Time: 14843




For some reason my direction is always 69 +/- 1 no matter the direction the wind vein points.

I'm calculating speed and direction value using
Quote

Speedvalue = (1492*3600000/SpeedDuration); 
---where 1492 is some arbitrary distance and 3600000 is to convert to hours from miliseconds
Directionvalue = 360*TimeDifference/DirectionTimePeriod;
---I decided to divide by the period of my direction signal rather than multiply by the frequency, because I would end up getting zero because of the scaling.



I'm checking the math using the tables and they match up to be 69-ish. I guess this leads to the idea that I'm not reading the rising pulses correctly. Any thoughts?

Here is my code for now:
Quote

//////////////////////////////////////////////////////////
//    Declaration of Variables   //
//////////////////////////////////////////////////////////
           
int analogSpeed = 0;             //Speed bus connected to analog pin 0
int analogDirection = 1;          //Direction bus connected to analog pin 1
unsigned long Speedvalue =  0;
unsigned long Directionvalue = 0;

// Variables for time
unsigned long SpeedDuration;
unsigned long DirectionDuration;
unsigned long SpeedTimePrevious;
unsigned long DirectionTimePrevious;
unsigned long DirectionTimePrevious1;
unsigned long DirectionTimePeriod;
unsigned long TimeDifference;
unsigned long Frequency;

// Variables for counting
volatile byte count;
volatile byte directioncount;

void setup()
{
//pinMode (analogSpeed, INPUT);
//pinMode (analogDirection, INPUT);
Serial.begin(2400);          // Setup serial with baud rate
attachInterrupt(0, arduino_anemometer, RISING);
attachInterrupt(1, arduino_direction, RISING);

count = 0;
directioncount=0;
SpeedDuration = 0;
DirectionDuration = 0;
SpeedTimePrevious = 0;
DirectionTimePrevious = 0;
DirectionTimePrevious1 = 0;

TimeDifference = 0;
}

void loop()
{
///////////////////////////////////////////////////////////////////////////////////////////
// It takes about 100 microseconds to read an analog input    //
// Max reading rate is 10,000 times a second          //
/////////////////////////////////////////////e////////////////////////////////////////////

//DO I WANT DIGITAL OR ANALOG READ?!

Speedvalue = digitalRead(analogSpeed);       // Read the input pin at 0
Directionvalue = digitalRead(analogDirection);    // Read the input pin at 1

Serial.print("Count: ");
Serial.println(count, DEC);

if (count >= 1)
{
   //Calculating Speed Duration
SpeedDuration = (millis() - SpeedTimePrevious);
SpeedTimePrevious = millis();
count = 0;

}

Serial.print("Speed: ");
Serial.println(SpeedDuration, DEC);
Serial.println(SpeedTimePrevious, DEC);


Serial.print("DirectionCount: ");
Serial.println(directioncount, DEC);

if ((SpeedTimePrevious  >  DirectionTimePrevious)  && (directioncount >= 1))
{
DirectionDuration = (millis() - DirectionTimePrevious);
DirectionTimePrevious = millis();
DirectionTimePeriod = (DirectionTimePrevious - DirectionTimePrevious1);
directioncount = 0;

Serial.print("Speed2: ");
Serial.println(DirectionTimePrevious, DEC);


// Calculates Frequency between DIRECTION signals
DirectionTimePrevious1 = DirectionTimePrevious;
Frequency = 1/DirectionTimePeriod;
}

// Calculates time difference between SPEED and DIRECTION signals
if (DirectionTimePrevious != 0 )   // Ensures that Direction must occur second
{
TimeDifference = (DirectionTimePrevious - SpeedTimePrevious);
}
Serial.print("Speed Time: ");
Serial.println(SpeedTimePrevious, DEC);
Serial.print("Direction Time: ");
Serial.println(DirectionTimePrevious, DEC);
Serial.print("Time Difference: ");
Serial.println(TimeDifference, DEC);
Serial.print("DirectionTimePeriod: ");
Serial.println(DirectionTimePeriod, DEC);


//////////////////////////////////
//   VALUES   //
/////////////////////////////////
Speedvalue = (1492*3600000/SpeedDuration);      // Finds speed of cup rotation in
Directionvalue = 360*TimeDifference/DirectionTimePeriod; //Finds Angle of Wind Vein

/////////////////////////////////////////////////////////////////////////////
//   Printing SPEED, DIRECTION, TIME   //
/////////////////////////////////////////////////////////////////////////////
Serial.print("Speed: ");
Serial.println(Speedvalue, DEC);
Serial.print("Direction: ");
Serial.println(Directionvalue, DEC);
Serial.print("Time: ");
Serial.println(millis());



}

void arduino_anemometer()
{
count++;
}

void arduino_direction()
{
directioncount++;
}


Go Up