Measuring Wake velocity & Rotational Velocity for a VAWT

Hi Arduino Gurus!

I've recently inherited a code to measure the performance of a model (3 straight bladed) Vertical Axis Wind Turbine which I have been trying to expand and build upon (with varying success).

Original set up included an Adafruit BMP280 to measure the Temperature and barometric pressure of the test section prior to any incoming flow, a MPXV5004DP to measure incoming flow velocity, and an OPB704 Reflectance object sensor to measure the rotational velocity of the turbine.

I have since incorporated another diffpx (MPXV5004DP) sensor to connect to a second pitot tube in order to measure the wakeflow velocity. The issue I've been having is that I can't successfully set up the wakeflow pitot to take more than one measurement per turbine rotation. I really need to do this since Vwakeflow changes depending where in the rotation the turbine is in.

Rotational velocity (omega) is set up on a 'while' loop where while it registers the turbine spinning, it will measure and serial print: data line number, omega, time taken for rotation, Front velocity (m/s), Back (wakeflow) Velocity (m/s).

Different attempts to fix so far:

  • set wakeflow velocity (back pitot) to take measurements every 5 milliseconds, either by:
    --outside 'while' statement (lots of dead data before running the wind tunnel and difficult to determine when the turbine makes one rotation).
    -- inside 'while' statement (to get rid of dead data but only prints one Vback measurement per rotation)
  • set up a matrix to take x Vback data points per rotation
    -- number of data points required at low rotational velocities is not the same at high rotational velocities

Goal is to measure wakeflow (Velb) every five milliseconds (arbitrary time stamp) and then when turbine is registered as spinning, measure omega, time taken for the rotation, then incoming flow (VelF) once per rotation

Current code is below, any suggestions or guidance would be really appreciated:

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP280.h>

#define BMP_SCK 13
#define BMP_MISO 12
#define BMP_MOSI 11 
#define BMP_CS 10

Adafruit_BMP280 bmp(BMP_CS); // hardware SPI
// ******* End temp & barometric pressure setup *******

volatile byte FLAG;

unsigned int data;  

float omega, time, temp, baro, rho, velocity_front, velocity_back, Vout1,Vout2, diffPx1, diffPx2;

int ledPin = 7;           //   Status LED

long currenttime = 0.0;

long currenttime_data = 0;

long prevtime = 0;      

unsigned long interval = 5;  //interval between diff px 2 readings (wake velocity)

unsigned long previousMillis = 0; //millis() returns an unsigned long

float prevomega = 0; 

const float TPi = 6.283185307L;

  
void setup()
{
   Serial.begin(115200);   // Initiates serial monitor (communication between board and computer)
   
   attachInterrupt(digitalPinToInterrupt(2), angVel, FALLING);     
 

Activate temp and baro sensor: *******
  Serial.println(F("BMP280 test"));
  if (!bmp.begin()) {  
  Serial.println(F("Could not find a valid BMP280 sensor, check wiring!"));
  while (1);
                  }
// ******* End activation of temp and baro sensor *******
  
   temp = bmp.readTemperature()+273.15; // Temperature output in Kelvin

   baro = bmp.readPressure(); // Barometric pressure in Pa

   rho = baro/(287*temp); // Calculated density

   data = 0; // Counts every revolution (to ensure no output data is missing)

   FLAG = false;
   
   time = 0;

   pinMode(ledPin, OUTPUT);

 
  Serial.print(F("Temperature (*C)= ")); Serial.print("\t"); 
  Serial.println(bmp.readTemperature());
  Serial.print(F("Temperature (K)= ")); Serial.print("\t"); 
  Serial.println(temp);
  Serial.print(F("Barometric Pressure (Pa) = ")); Serial.print("\t"); 
  Serial.println(bmp.readPressure());
  Serial.print(F("Density (kg/m^3)= ")); Serial.print("\t");
  Serial.println(rho,4);


  Serial.print( "Data" ) ; Serial.print("\t");
  Serial.print( "Omega" ) ; Serial.print("\t");
  Serial.print( "time" ); Serial.print("\t");
  Serial.print( "VelF" ) ; Serial.print("\t");     //Incoming flow velocity    
  Serial.print( "VelB" ) ; Serial.print("\t"); Serial.print("\n");    //wakeflow velocity

  
}

void loop()
{


  time = (currenttime - prevtime) * .001;    
  omega =  TPi / time;                       // Calculates the angular velocity omega

//****** Front Velocity Readings***//
int average = 0;      // takes 10 samples of diff px1 and prints the average
for (int i=0; i < 10; i++) {
average = average + analogRead(A0);
delay(1); // delay for stability
}
  Vout1 = ((average/10));    // Reads output voltage from differential pressure sensor
  diffPx1 = 5*((Vout1 / 1023.0)-0.2); // Rearranged diffPx formula
  velocity_front = sqrt((2*diffPx1*1000)/rho); // Bernoullis equatio - convert kPa to Pa

prevtime = currenttime;
  prevomega = omega;

//*** Back (wakeflow) Velocity Readings***//
unsigned long currentMillis = millis(); // grab current time
if ((unsigned long)(currentMillis-previousMillis) >= interval){       
Vout2 = (analogRead(A1));  // Output voltage form diff px2
previousMillis = millis();
}
  
  diffPx2 = 5*((Vout2 / 1023.0)-0.2); 
velocity_back = sqrt((2*diffPx2*1000)/rho); 
 

  while(FLAG == true) // When interrupt is activated flag goes true causing the while loop to run
 { 
   
  currenttime = millis();

//***Data prints to serial Monitor***//
  Serial.print( data ) ; Serial.print("\t");
  Serial.print( omega ); Serial.print("\t");
  Serial.print( time,4 ); Serial.print("\t");  //,4 = print to 4 decimal places
  Serial.print( velocity_front,3 ); Serial.print("\t");
  Serial.print( velocity_back,3 ); Serial.print("\t"); Serial.print("\n");   

  FLAG = false;
     
 }
    
}

void angVel()                  // Interupt that is triggered on a rising signal 
{
 data++;                      // Adds one to data count each time interupt is triggered
 FLAG = true;                 // Makes flag 'true' to activate the while loop above
 long currenttime = millis();

}
    while(FLAG == true) // When interrupt is activated flag goes true causing the while loop to run
   {
     
    currenttime = millis();

//***Data prints to serial Monitor***//
    Serial.print( data ) ; Serial.print("\t");
    Serial.print( omega ); Serial.print("\t");
    Serial.print( time,4 ); Serial.print("\t");  //,4 = print to 4 decimal places
    Serial.print( velocity_front,3 ); Serial.print("\t");
    Serial.print( velocity_back,3 ); Serial.print("\t"); Serial.print("\n");   
 
    FLAG = false;
       
   }

Why are you using a while statement when the body can only EVER iterate once?

 void angVel()                  // Interupt that is triggered on a rising signal
 {
   data++;                      // Adds one to data count each time interupt is triggered
   FLAG = true;                 // Makes flag 'true' to activate the while loop above
   long currenttime = millis();

 }

Why do you have a local variable that goes out of scope as soon as you assign a value to it?

Why do you have a local variable with the same name as a global variable?

Why is data not volatile?

Please edit your original post to add code tags ("</>" button).

Thanks very much for taking the time out to reply I really appreciate it. Confirming post has been updated with code tags.

PaulS:
Why are you using a while statement when the body can only EVER iterate once?

Why do you have a local variable that goes out of scope as soon as you assign a value to it?

Why do you have a local variable with the same name as a global variable?

Why is data not volatile?

Great questions! Hopefully I can answer them as best I can as code was inherited and a lot of the decisions were made before me.

While statement is in there as a way to control the start and stop of data acquisition. The turbine doesn't start spinning until incoming flow in the wind tunnel reaches approx 4m/s so for anything <4m/s - didn't want dead data filling up the serial monitor to then sort through later. Do you have any recommendations of a different way to start/stop data acquisition suitable to this application?

I'm not sure what the local variable is that goes out of scope as soon as you assign a value to it. Are you able to please expand on that question. Apologies, I am still on my Arduino learners licence.

Local variable same as global variable - is this millis()? If so, I've just realised that. Is there a better way to distingish between the time taken for rotation and the wakeflow velocity acquisition rate/time/interval?

Volitile data - I hadn't thought of or have been exposed to this set up so will look into this further.

Cheers!

I'm not sure what the local variable is that goes out of scope as soon as you assign a value to it.

   long currenttime = millis(); //defines and initializes a local variable

Global variables that are used to communicate between the main program and an interrupt routine must be declared volatile.

volatile long currenttime = 0.0;

Should be "if", not "while":

while(FLAG == true)

Also, unless time can flow backwards in your universe, the output from millis() should be stored in an unsigned long, not a long.

jremington:
Thank you for explaining my mistakes in a way I can understand and grow/learn from them. I really appeciate it and hopefully it can help others who are at my level of experience too!

PaulS:
Cheers for pointing out all of the mistakes in my universe. I will take all of your 'why' questions and your unasigned long suggestion on board.