Was wondering how to incorporate a sensor output that I’ve calculated from the code into an equation for CdA?
This is the full code that I’ve used without the CdA equation:
//Routine for calculating the velocity from
//a pitot tube and MPXV7002DP pressure differential sensor
float V_0 = 5.0; // supply voltage to the pressure sensor
float rho = 1.225; // density of air
// parameters for averaging and offset
int offset = 0;
int offset_size = 10;
int veloc_mean_size = 20;
int zero_span = 2;
// Configuration constants:
const byte RevSensePin = 2;
const float WheelRadiusInMeters = 0.3;
const unsigned long DisplayIntervalMillis = 1000; // Update once per second
const unsigned long MaxRevTimeMicros = 2000000UL; // >2 seconds per revolution counts as 0 RPM
// Variables used in the ISR and in the main code must be 'volatile'
volatile unsigned long RevSenseTimeMicros = 0; // Time that the rising edge was sensed
volatile unsigned long RevTimeMicros = 0; // Microseconds between consecutive pulses
// Useful constants:
const unsigned long SixtySecondsInMicros = 60000000UL;
const float WheelCircumferenceInMeters = TWO_PI * WheelRadiusInMeters;
void setup() {
Serial.begin(9600);
for (int ii=0;ii<offset_size;ii++){
offset += analogRead(A0)-(1023/2);
}
offset /= offset_size;
pinMode(RevSensePin, INPUT);
attachInterrupt(digitalPinToInterrupt(RevSensePin), RevSenseISR, RISING);
}
void RevSenseISR()
{
static unsigned long revSensePreviousMicros = 0; // 'static' to retain value between calls
RevSenseTimeMicros = micros();
RevTimeMicros = RevSenseTimeMicros - revSensePreviousMicros; // Time for last revolution
revSensePreviousMicros = RevSenseTimeMicros;
}
void loop()
{
static unsigned previousRPM;
// Only update the display once per DisplayIntervalMillis
unsigned long currentMillis = millis();
static unsigned long previousMillis = 0;
if (currentMillis - previousMillis >= DisplayIntervalMillis)
{
previousMillis += DisplayIntervalMillis;
// With interrupts disabled, make local copies of volatile variables
// This is so the ISR can't change them while we read them
noInterrupts();
unsigned long revSenseTimeMicros = RevSenseTimeMicros; // Time that the last rising edge was sensed
unsigned long revTimeMicros = RevTimeMicros; // Microseconds between consecutive pulses
interrupts();
// Calculate RPM
unsigned newRPM;
if (micros() - revSenseTimeMicros > MaxRevTimeMicros)
newRPM = 0; // Going so slow we're essentially stopped
else
newRPM = SixtySecondsInMicros / revTimeMicros;
// No need to update the display unless the RPM value has changed
if (newRPM != previousRPM)
{
previousRPM = newRPM;
displayRPM(newRPM);
}
}
float adc_avg = 0; float veloc = 0.0;
// average a few ADC readings for stability
for (int ii=0;ii<veloc_mean_size;ii++){
adc_avg+= analogRead(A0)-offset;
}
adc_avg/=veloc_mean_size;
// make sure if the ADC reads below 512, then we equate it to a negative velocity
if (adc_avg>512-zero_span and adc_avg<512+zero_span){
} else{
if (adc_avg<512){
veloc = -sqrt((-10000.0*((adc_avg/1023.0)-0.5))/rho);
} else{
veloc = sqrt((10000.0*((adc_avg/1023.0)-0.5))/rho); // wind speed value
}
}
Serial.println(veloc); // print velocity
delay(2000); // delay for stability
}
void displayRPM(unsigned RPM)
{
float metersPerMinute = RPM * WheelCircumferenceInMeters;
Serial.print("RPM = "); //print the word "RPM".
Serial.print(RPM); // print the rpm value.
Serial.print("\t\t Linear Speed = ");
Serial.print(metersPerMinute/60); //print the linear velocity value.
Serial.println(" m/s");
}
I’m trying to get the output which is 'veloc' in the code into the equation as sensorValue2, also the output that measures ‘RPM’ and changes it to (metersPerMinute/60); as sensorValue1 into the equation.
The code I’ve attempted to use is below, however when I’ve put that into the above code it doesn’t seem to work? Can anyone guide me on how to put the serial outputs (veloc) and (metersPerMinute/60) into the equation for another serial.print value?
This is what it's meant to look like sorry, sensorvalue1 (veloc in the first code) being squared.
Yes the first code works fine displaying the wind speed from serial.print = veloc, in m/s and the rpm&linear speed being displayed using Hall effect sensor with serial.print(metersPerMinute/60).
Just don't know how to incorporate the outputs from the first code into the equation I need for CdA?
can you provide values for veloc and metersPerMinute to see what the value of output is?
I've tried adding what you said into the void loop() and the veloc seems to be working with the sensor however it says (metersPerMinute/60) is not defined in the loop scope, looking at the first code the metersPerMinute/60 is in the 'void displayRPM' how will I add and define the (metersPerMinute/60) into the loop?
The values for the outputs are constantly changing with the different wind speeds (pitot tube) and how many times I'm spinning my bike wheel (hall effect w/ magnet) but the values are usually around 10m/s for wind speed and 3-4m/s for the bike wheel.
metersPerMinute/60 is in the 'void displayRPM' how will I add and define the (metersPerMinute/60) into the loop?
you could define metersPerMinute globally as you many other variables. I little benefit defining it only within displayRPM() when its value is needed elsewhere
gcjr:
you could define metersPerMinute globally as you many other variables. I little benefit defining it only within displayRPM() when its value is needed elsewhere
I've manage to come up with this code, it seems to be working with the pitot tube and (veloc) but when I just use the RPM it gives you me a CdA value of inf, seems to not be working for the RPM side of things but fine for the veloc? Any ideas?
jremington:
Post ALL the code, so we can see what the real problem is.
Most people would incorporate the code for the CdA equation into the code that measures the sensor value.
Here's the full code
//Routine for calculating the velocity from
//a pitot tube and MPXV7002DP pressure differential sensor
float V_0 = 5.0; // supply voltage to the pressure sensor
float rho = 1.225; // density of air
float Wtotal = 250.0000;
float WRR = 7.0000;
float WKE = 28.0000;
float v2 = 8.0000;
float v = 3.0000;
float output = 0.0000;
// parameters for averaging and offset
int offset = 0;
int offset_size = 10;
int veloc_mean_size = 20;
int zero_span = 2;
// Configuration constants:
const byte RevSensePin = 2;
const float WheelRadiusInMeters = 0.3;
const unsigned long DisplayIntervalMillis = 1000; // Update once per second
const unsigned long MaxRevTimeMicros = 2000000UL; // >2 seconds per revolution counts as 0 RPM
// Variables used in the ISR and in the main code must be 'volatile'
volatile unsigned long RevSenseTimeMicros = 0; // Time that the rising edge was sensed
volatile unsigned long RevTimeMicros = 0; // Microseconds between consecutive pulses
// Useful constants:
const unsigned long SixtySecondsInMicros = 60000000UL;
const float WheelCircumferenceInMeters = TWO_PI * WheelRadiusInMeters;
void setup() {
Serial.begin(9600);
for (int ii=0;ii<offset_size;ii++){
offset += analogRead(A0)-(1023/2);
}
offset /= offset_size;
pinMode(RevSensePin, INPUT);
attachInterrupt(digitalPinToInterrupt(RevSensePin), RevSenseISR, RISING);
}
void RevSenseISR()
{
static unsigned long revSensePreviousMicros = 0; // 'static' to retain value between calls
RevSenseTimeMicros = micros();
RevTimeMicros = RevSenseTimeMicros - revSensePreviousMicros; // Time for last revolution
revSensePreviousMicros = RevSenseTimeMicros;
}
void loop()
{
static unsigned previousRPM;
// Only update the display once per DisplayIntervalMillis
unsigned long currentMillis = millis();
static unsigned long previousMillis = 0;
if (currentMillis - previousMillis >= DisplayIntervalMillis)
{
previousMillis += DisplayIntervalMillis;
// With interrupts disabled, make local copies of volatile variables
// This is so the ISR can't change them while we read them
noInterrupts();
unsigned long revSenseTimeMicros = RevSenseTimeMicros; // Time that the last rising edge was sensed
unsigned long revTimeMicros = RevTimeMicros; // Microseconds between consecutive pulses
interrupts();
// Calculate RPM
unsigned newRPM;
if (micros() - revSenseTimeMicros > MaxRevTimeMicros)
newRPM = 0; // Going so slow we're essentially stopped
else
newRPM = SixtySecondsInMicros / revTimeMicros;
// No need to update the display unless the RPM value has changed
if (newRPM != previousRPM)
{
previousRPM = newRPM;
displayRPM(newRPM);
}
}
float adc_avg = 0; float veloc = 0.0;
// average a few ADC readings for stability
for (int ii=0;ii<veloc_mean_size;ii++){
adc_avg+= analogRead(A0)-offset;
}
adc_avg/=veloc_mean_size;
// make sure if the ADC reads below 512, then we equate it to a negative velocity
if (adc_avg>512-zero_span and adc_avg<512+zero_span){
} else{
if (adc_avg<512){
veloc = -sqrt((-10000.0*((adc_avg/1023.0)-0.5))/rho);
} else{
veloc = sqrt((10000.0*((adc_avg/1023.0)-0.5))/rho);
}
}
Serial.println(veloc); // print velocity
delay(2000); // delay for stability
float sensorValue = veloc;
output = ((Wtotal-WRR+WKE)/(rho*(sensorValue*sensorValue)*v));
Serial.print("CdA = ");
Serial.println(output);
delay(1000);
}
void displayRPM(unsigned RPM)
{
float metersPerMinute = RPM * WheelCircumferenceInMeters;
Serial.print("RPM = "); //print the word "RPM".
Serial.print(RPM); // print the rpm value.
Serial.print("\t\t Linear Speed = ");
Serial.print(metersPerMinute/60); //print the linear velocity value.
Serial.println(" m/s");
}
I've managed to get apply the sensor value from 'veloc' into the equation and it's giving me proper values for CdA. However I need the ''v'' in the equation to be the output from this part float metersPerMinute = RPM * WheelCircumferenceInMeters; just keeps giving me values of inf for CdA
Can someone PLEASE tell me how to get rid of the void displayRPM in order for all of the values and commands to be in the same scope ''void loop ()'', this code would work if I could do that however nothing seems to be working constantly saying sensorValue1 is not defined since it's in the previous scope.
//Routine for calculating the velocity from
//a pitot tube and MPXV7002DP pressure differential sensor
float V_0 = 5.0; // supply voltage to the pressure sensor
float rho = 1.225; // density of air
float Wtotal = 250.0000;
float WRR = 7.0000;
float WKE = 28.0000;
float v2 = 8.0000;
float v = 3.0000;
float output = 0.0000;
// parameters for averaging and offset
int offset = 0;
int offset_size = 10;
int veloc_mean_size = 20;
int zero_span = 2;
// Configuration constants:
const byte RevSensePin = 2;
const float WheelRadiusInMeters = 0.3;
const unsigned long DisplayIntervalMillis = 1000; // Update once per second
const unsigned long MaxRevTimeMicros = 2000000UL; // >2 seconds per revolution counts as 0 RPM
// Variables used in the ISR and in the main code must be 'volatile'
volatile unsigned long RevSenseTimeMicros = 0; // Time that the rising edge was sensed
volatile unsigned long RevTimeMicros = 0; // Microseconds between consecutive pulses
// Useful constants:
const unsigned long SixtySecondsInMicros = 60000000UL;
const float WheelCircumferenceInMeters = TWO_PI * WheelRadiusInMeters;
void setup() {
Serial.begin(9600);
for (int ii=0;ii<offset_size;ii++){
offset += analogRead(A0)-(1023/2);
}
offset /= offset_size;
pinMode(RevSensePin, INPUT);
attachInterrupt(digitalPinToInterrupt(RevSensePin), RevSenseISR, RISING);
}
void RevSenseISR()
{
static unsigned long revSensePreviousMicros = 0; // 'static' to retain value between calls
RevSenseTimeMicros = micros();
RevTimeMicros = RevSenseTimeMicros - revSensePreviousMicros; // Time for last revolution
revSensePreviousMicros = RevSenseTimeMicros;
}
void loop()
{
static unsigned previousRPM;
// Only update the display once per DisplayIntervalMillis
unsigned long currentMillis = millis();
static unsigned long previousMillis = 0;
if (currentMillis - previousMillis >= DisplayIntervalMillis)
{
previousMillis += DisplayIntervalMillis;
// With interrupts disabled, make local copies of volatile variables
// This is so the ISR can't change them while we read them
noInterrupts();
unsigned long revSenseTimeMicros = RevSenseTimeMicros; // Time that the last rising edge was sensed
unsigned long revTimeMicros = RevTimeMicros; // Microseconds between consecutive pulses
interrupts();
// Calculate RPM
unsigned newRPM;
if (micros() - revSenseTimeMicros > MaxRevTimeMicros)
newRPM = 0; // Going so slow we're essentially stopped
else
newRPM = SixtySecondsInMicros / revTimeMicros;
// No need to update the display unless the RPM value has changed
if (newRPM != previousRPM)
{
previousRPM = newRPM;
displayRPM(newRPM);
}
}
float adc_avg = 0; float veloc = 0.0;
// average a few ADC readings for stability
for (int ii=0;ii<veloc_mean_size;ii++){
adc_avg+= analogRead(A0)-offset;
}
adc_avg/=veloc_mean_size;
// make sure if the ADC reads below 512, then we equate it to a negative velocity
if (adc_avg>512-zero_span and adc_avg<512+zero_span){
} else{
if (adc_avg<512){
veloc = -sqrt((-10000.0*((adc_avg/1023.0)-0.5))/rho);
} else{
veloc = sqrt((10000.0*((adc_avg/1023.0)-0.5))/rho);
}
}
float sensorValue1 = veloc;
}
void displayRPM(unsigned RPM)
{
float metersPerMinute = RPM * WheelCircumferenceInMeters;
Serial.print("RPM = "); //print the word "RPM".
Serial.print(RPM); // print the rpm value.
Serial.print("\t\t Linear Speed = ");
Serial.print(metersPerMinute/60); //print the linear velocity value.
Serial.println(" m/s");
float sensorValue = (metersPerMinute/60);
float output = ((Wtotal-WRR+WKE)/(rho*(sensorValue1*sensorValue1)*sensorValue));
Serial.print("CdA = ");
Serial.println(output);
delay(1000);
gcjr:
you declared sensorValue1 in loop() but use it in displayRPM(). you can declare globally at the top of your file along with other variables
float sensorValue1 = veloc;
}
void displayRPM(unsigned RPM)
{
can you give me an example? sorry i'm new to arduino only been using for like 2 weeks. I've just declared the veloc as float veloc = 0.0000 at top but that doesn't seem right.
RICKV123:
can you give me an example? sorry i'm new to arduino only been using for like 2 weeks. I've just declared the veloc as float veloc = 0.0000 at top but that doesn't seem right.
Here's the latest code i've put in, so close to getting it all working just can't that last bit. Appreciate all the help though.
//Routine for calculating the velocity from
//a pitot tube and MPXV7002DP pressure differential sensor
float V_0 = 5.0; // supply voltage to the pressure sensor
float rho = 1.225; // density of air
float Wtotal = 250.0000;
float WRR = 7.0000;
float WKE = 28.0000;
float v2 = 8.0000;
float v = 3.0000;
float output = 0.0000;
float veloc = 0.0000;
// parameters for averaging and offset
int offset = 0;
int offset_size = 10;
int veloc_mean_size = 20;
int zero_span = 2;
// Configuration constants:
const byte RevSensePin = 2;
const float WheelRadiusInMeters = 0.3;
const unsigned long DisplayIntervalMillis = 1000; // Update once per second
const unsigned long MaxRevTimeMicros = 2000000UL; // >2 seconds per revolution counts as 0 RPM
// Variables used in the ISR and in the main code must be 'volatile'
volatile unsigned long RevSenseTimeMicros = 0; // Time that the rising edge was sensed
volatile unsigned long RevTimeMicros = 0; // Microseconds between consecutive pulses
// Useful constants:
const unsigned long SixtySecondsInMicros = 60000000UL;
const float WheelCircumferenceInMeters = TWO_PI * WheelRadiusInMeters;
void setup() {
Serial.begin(9600);
for (int ii=0;ii<offset_size;ii++){
offset += analogRead(A0)-(1023/2);
}
offset /= offset_size;
pinMode(RevSensePin, INPUT);
attachInterrupt(digitalPinToInterrupt(RevSensePin), RevSenseISR, RISING);
}
void RevSenseISR()
{
static unsigned long revSensePreviousMicros = 0; // 'static' to retain value between calls
RevSenseTimeMicros = micros();
RevTimeMicros = RevSenseTimeMicros - revSensePreviousMicros; // Time for last revolution
revSensePreviousMicros = RevSenseTimeMicros;
}
void loop()
{
static unsigned previousRPM;
// Only update the display once per DisplayIntervalMillis
unsigned long currentMillis = millis();
static unsigned long previousMillis = 0;
if (currentMillis - previousMillis >= DisplayIntervalMillis)
{
previousMillis += DisplayIntervalMillis;
// With interrupts disabled, make local copies of volatile variables
// This is so the ISR can't change them while we read them
noInterrupts();
unsigned long revSenseTimeMicros = RevSenseTimeMicros; // Time that the last rising edge was sensed
unsigned long revTimeMicros = RevTimeMicros; // Microseconds between consecutive pulses
interrupts();
// Calculate RPM
unsigned newRPM;
if (micros() - revSenseTimeMicros > MaxRevTimeMicros)
newRPM = 0; // Going so slow we're essentially stopped
else
newRPM = SixtySecondsInMicros / revTimeMicros;
// No need to update the display unless the RPM value has changed
if (newRPM != previousRPM)
{
previousRPM = newRPM;
displayRPM(newRPM);
}
}
float adc_avg = 0; float veloc = 0.0;
// average a few ADC readings for stability
for (int ii=0;ii<veloc_mean_size;ii++){
adc_avg+= analogRead(A0)-offset;
}
adc_avg/=veloc_mean_size;
// make sure if the ADC reads below 512, then we equate it to a negative velocity
if (adc_avg>512-zero_span and adc_avg<512+zero_span){
} else{
if (adc_avg<512){
veloc = -sqrt((-10000.0*((adc_avg/1023.0)-0.5))/rho);
} else{
veloc = sqrt((10000.0*((adc_avg/1023.0)-0.5))/rho);
}
}
Serial.println(veloc); // print velocity
delay(2000); // delay for stability
}
void displayRPM(unsigned RPM)
{
float metersPerMinute = RPM * WheelCircumferenceInMeters;
float sensorValue1 = veloc;
Serial.print("RPM = "); //print the word "RPM".
Serial.print(RPM); // print the rpm value.
Serial.print("\t\t Linear Speed = ");
Serial.print(metersPerMinute/60); //print the linear velocity value.
Serial.println(" m/s");
float sensorValue = (metersPerMinute/60);
float output = ((Wtotal-WRR+WKE)/(rho*(sensorValue1*sensorValue1)*sensorValue));
Serial.print("CdA = ");
Serial.println(output);
delay(1000);
}
RICKV123:
I've just declared the veloc as float veloc = 0.0000 at top but that doesn't seem right.
normally when variables are defined, they are not defined with an initial value (e.g. float veloc;). presumably, variables initialized with an initial value (e.g. int offset = 0) may save some code in setup().
constant values (e.g. float rho = 1.225) should not be a variable. when C first came out #define (e.g. #define Rho 1.225) were used to specify constants which were often embedded in the logic at compile time. Good practice today is to define them as const (e.g. const float Rho = 1.225) which is not a variable allocated from RAM but simply a symbolic constant handled like #define but with type checking.
and it is common practice to Capitalize constant and not Capitalize variables.
It's still giving me a value of CdA = inf.
it's hard to say without seeing values. suggest you print each value in your equation using sprintf may make it esier
I'm honestly not sure tbh, heads a bit scrambled feel like it should be working with that code but just keeps giving me the veloc as 0 it seems and making the whole output equation 'inf'
if (adc_avg<=512-zero_span or adc_avg>=512+zero_span){
if (adc_avg<512){
veloc = -sqrt((-10000.0*((adc_avg/1023.0)-0.5))/rho);
} else{
veloc = sqrt((10000.0*((adc_avg/1023.0)-0.5))/rho);
}