ThrustMeter

Arduino Basierter Schub/Motor Messstand.

Ermöglicht Messung und Logging der folgenden Parameter:

  • Gasstellung
  • Spannung
  • Strom
  • Leistung
  • Schub
  • Drehzahl
  • Temperatur
  • Vibration

Status: In Arbeit

Fotos:

Code:

/*****************************************************************************
  *                                                                           
  *  Copyright (c) 2013 www.der-frickler.net                   
  *                                                                           
  *                                                                           
  *  This library is free software; you can redistribute it and/or modify it  
  *  under the terms of the GNU Lesser General Public License as published    
  *  by the Free Software Foundation; either version 2 of the License, or     
  *  (at your option) any later version.                                      
  *                                                                           
  *  This software is distributed in the hope that it will be useful, but     
  *  WITHOUT ANY WARRANTY; without even the implied warranty of               
  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU        
  *  Lesser General Public License for more details.                          
  *                                                                           
  *  You should have received a copy of the GNU Lesser General Public         
  *  License along with this library; if not, write to the Free Software      
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA  
  *                                                                           
  *****************************************************************************
  *                                                                           
  *  Arduino Thrustmeter to measure 
  *  Throttle, Volts, Amperes, Thrust, RPM, Temp and Vibration of 
  *  Motor / Propeller Combinations.
  *                                                                           
  *                                                                           
  *****************************************************************************/

#include <LiquidCrystal.h>
#include <Servo.h> 
#include "Wire.h"
#include "I2Cdev.h"
#include "BMA150.h"
#include <Hx711.h>

#define thrustPinDOUT 11
#define thrustPinSCK 12
#define currentPin A2
#define voltagePin A3
#define throttlePin 3
#define rpmPin 2

//#define CALIB_THROTTLE
//#define CALIB_VOLT_AMPERE
//#define CALIB_THRUST

// define some values used by the panel and buttons
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5
int key, lastKey     = 5;
int adc_key_in  = 0;

// How often do we do print?
long time = 0; // 
int timeBetweenPrinting = 500; // We want a print every 500 ms;

// LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// scale Stuff
Hx711 scale(thrustPinDOUT, thrustPinSCK);

// Throtle Stuff
Servo throttleOut;
int throttleMS = 0; 

// ACC stuff
BMA150 accel;
int16_t ax, ay, az, acc, accAverage;
int16_t axOffset, ayOffset, azOffset;
int tempRead;
float temp;

// Voltage Stuff 
float voltsA = 0.0; // Volts
int analogVoltsA = 0; // analog reading volts
float voltsB = 14.0; // Volts
int analogVoltsB = 990; // analog reading volts
float analogVoltsAverage = 0;
int analogVoltsValue;
float volts;

// Current Stuff 
float currentA = 0.0; // Ampere
int analogCurrentA = 510; // analog reading current
float currentB = 7.01; // Ampere
int analogCurrentB = 650; // analog reading current
int analogCurrentValue;
float analogCurrentAverage = 0;
float amperes;

// Watts
float watts;

// Thrust Stuff 
long scaleOffset = 0;
float scaleScale = (1992.f/4)-35.0;
//float thrustA = 0.0; // Grams
//int analogThrustA = 170; // analog reading thrust
//float thrustB = 1000.0; // Grams
//int analogThrustB = 812; // analog reading thrust
//int analogThrustValue;
//float analogThrustAverage = 0;
float thrust;

// RPM
volatile long rpmStart;
volatile long rpm;
float rpmAverage;
int propBlades = 2;

void setup()
{

  // Init Throttle Servo
  throttleOut.attach(throttlePin);
  throttleOut.writeMicroseconds(throttleMS+1000);

  // init Serial
  Serial.begin(115200);
  Serial.println();
  Serial.println("Motorteststand - der-Frickler.net");
  Serial.println();
  
  // Init LCD 
  lcd.begin(16, 2);
  lcd.setCursor(0,0);
  lcd.print(" Motorteststand");
  lcd.setCursor(0,1);
  lcd.print("der-Frickler.net");

  // Init RPM
  attachInterrupt(0, measureRPM, RISING);
  
  // init Scale
  scale.setScale(scaleScale);

  // Init ACC / Temp
  Wire.begin();
  accel.initialize();
  // Serial.println(accel.testConnection() ? "BMA150 connection successful" : "BMA150 connection failed");
  accel.setRange(2); // +- 8g
  accel.setBandwidth(2); // 100Hz
  // calc ACC Offsets
  for (int i=0; i <= 20; i++){
    accel.getAcceleration(&ax, &ay, &az);
    axOffset += ax;
    ayOffset += ay;
    azOffset += az;
  }
  axOffset /= 20;
  ayOffset /= 20;
  azOffset /= 20;


  delay(1000);
  lcd.clear();
  
  writeHeader();

}

void writeHeader() {
    // write CSV Header
  Serial.print("Throttle(%);");
  Serial.print("Voltage(V);");
  Serial.print("Current(A);");
  Serial.print("Watts(W);");
  Serial.print("Thrust(g);");
  Serial.print("RPM(krpm);");
  Serial.print("TEMP(°C);");
  Serial.print("ACC;");
  Serial.print("Efficiency(g/W);");
  Serial.println();
}
  

void loop()
{
  // read Button
  key = read_LCD_buttons();

  // save old Keystate
  if (key != btnNONE) {
    lastKey = key;
  }
  
  if (key == btnRIGHT) {
    Serial.println();
    Serial.println();
    Serial.println();
    writeHeader();
  }

  // check for maunal inc./dec./reset
  if (key == btnUP) {
    throttleMS += 1;
  } 
  else if (key == btnDOWN) {
    throttleMS -= 1;
  } 
  else if (key == btnSELECT) {
    throttleMS = 0;
  } 

  // check for automatic inc./dec.
  if (lastKey == btnRIGHT) {
    throttleMS += 1; 
  } 
  else if (lastKey == btnLEFT) {
    throttleMS -= 1; 
  }
  
//  if (throttleMS < 1000) {
//    Serial.println();
//    Serial.println();
//    Serial.println();
//    writeHeader();
//  }

  // limit Throttle
  throttleMS = constrain(throttleMS, 0, 1000);

  // Start Measuring

  // get volts
  analogVoltsValue = analogRead(voltagePin);
  analogVoltsAverage = 0.5*analogVoltsAverage + 0.5*analogVoltsValue;

  // get current
  int curAvCount = 10; // sample current several times
  analogCurrentValue = 0;
  for (int i=0; i < curAvCount; i++){
    analogCurrentValue += analogRead(currentPin);  
    //Serial.println(analogCurrentValue);
  }
  analogCurrentValue = analogCurrentValue/curAvCount;
  //Serial.println(analogCurrentValue);
  //Serial.println();
  analogCurrentAverage = 0.5*analogCurrentAverage + 0.5*analogCurrentValue;
  
//  // get thrust
//  analogThrustValue = analogRead(thrustPin);
//  analogThrustAverage = 0.5*analogThrustAverage + 0.5*analogThrustValue;

  // get ACC and Temp
  accel.getAcceleration(&ax, &ay, &az);
  ax -= axOffset;
  ay -= ayOffset;
  az -= azOffset;
  acc = max(abs(ax), abs(ay));
  acc = max(acc, abs(az));
  accAverage = 0.8*accAverage + 0.2*acc;
  tempRead = accel.getTemperature();
  temp = 0.8*temp + 0.2*((tempRead * 0.5) - 30.0);

  // get RPM
  rpmAverage = 0.8*rpmAverage + 0.2*rpm;


  // set throttle
  throttleOut.writeMicroseconds(throttleMS+1000);

#ifdef CALIB_VOLT_AMPERE
  lcd.clear();

  lcd.setCursor(0,0);
  lcd.print(analogVoltsAverage);
  lcd.setCursor(8,0);
  lcd.print(analogToVolts(analogVoltsAverage),1);
  lcd.print("V"); 

  lcd.setCursor(0,1);
  lcd.print(analogCurrentAverage);
  lcd.setCursor(8,1);
  lcd.print(analogToAmperes(analogCurrentAverage),1);
  lcd.print("A"); 

  delay(250);  
#endif
#ifdef CALIB_THRUST

  //thrust = analogToThrust(analogThrustAverage);
  thrust = scale.getGram();
  
  lcd.clear();
  lcd.setCursor(0,0);
//  lcd.print(analogVoltsAverage);
//  lcd.setCursor(8,0);
  lcd.print(thrust,1);
  lcd.print(" Gram"); 


  delay(250);  
#endif
#if  !defined (CALIB_VOLT_AMPERE)  && !defined (CALIB_THRUST) 


  // Is it time to print? 
  if(millis() > time + timeBetweenPrinting) {
    // print throttle
    lcd.setCursor(0,0);
    if (throttleMS < 1000) lcd.print(" ");
    if (throttleMS < 100) lcd.print(" ");
    lcd.print(throttleMS/10); 
    lcd.print("% "); 

    // print Temp
//      if (temp < 10) lcd.print(" ");
//      lcd.print(temp,1); 
//      lcd.print("C "); 
    
    // Print Thrust
    //thrust = analogToThrust(analogThrustAverage);
    thrust = scale.getGram();
    //thrust = analogToThrust(analogThrustValue);
    if (thrust < 0) thrust = 0;
    //if (thrust < 1000) lcd.print(" ");
    if (thrust < 100) lcd.print(" ");
    if (thrust < 10) lcd.print(" ");
    lcd.print(thrust,1); 
    lcd.print("g "); 

    // Print RPM
    //if (rpm < 1000) lcd.print(" ");
    if (rpm < 100) lcd.print(" ");
    if (rpm < 10) lcd.print(" ");
    lcd.print(rpm,1); 
    lcd.print("R "); 

    // Print ACC
//    if (accAverage < 10) lcd.print(" ");
//    lcd.print(accAverage,1); 
//    lcd.print("G "); 

    // 2nd Line
    lcd.setCursor(0,1);

    // print voltage
    volts = analogToVolts(analogVoltsAverage);
    if (volts < 10) lcd.print(" ");
    lcd.print(volts,1); 
    lcd.print("V"); 

    // print current
    amperes = analogToAmperes(analogCurrentValue);
    if (amperes < 0 ) amperes = 0.0;
    if (amperes < 10) lcd.print(" ");
    lcd.print(amperes,1); 
    lcd.print("A"); 

    // Print Wat
    watts = volts * amperes;
    if (watts < 100) lcd.print(" ");
    if (watts < 10) lcd.print(" ");
    lcd.print(watts,1); 
    lcd.print("W"); 


if (throttleMS > 0) {

    // write Values to Serial as CSV
    Serial.print(throttleMS/10);
    Serial.print(";");
    Serial.print(volts);
    Serial.print(";");
    Serial.print(amperes);
    Serial.print(";");
    Serial.print(watts);
    Serial.print(";");
    Serial.print(thrust);
    Serial.print(";");
    Serial.print(rpm/1000);
    Serial.print(";");
    Serial.print(temp);
    Serial.print(";");
    Serial.print(accAverage);
    Serial.print(";");
    Serial.print(thrust/watts);
    Serial.print(";");
    Serial.println();
}

    time = millis();
  }

  delay(50); 

#endif

}


// read the buttons
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);      // read the value from the sensor
  // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
  // we add approx 50 to those values and check to see if we are close
  if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
  // For V1.1 us this threshold
  if (adc_key_in < 50)   return btnRIGHT; 
  if (adc_key_in < 250)  return btnUP;
  if (adc_key_in < 450)  return btnDOWN;
  if (adc_key_in < 650)  return btnLEFT;
  if (adc_key_in < 850)  return btnSELECT; 

  // For V1.0 comment the other threshold and use the one below:
  /*
 if (adc_key_in < 50)   return btnRIGHT; 
   if (adc_key_in < 195)  return btnUP;
   if (adc_key_in < 380)  return btnDOWN;
   if (adc_key_in < 555)  return btnLEFT;
   if (adc_key_in < 790)  return btnSELECT;  
   */
  return btnNONE;  // when all others fail, return this...
}


float mapfloat(float x, float in_min, float in_max, float out_min, float out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}


float analogToVolts(float analogval){
  float load = mapfloat(analogval, analogVoltsA, analogVoltsB, voltsA, voltsB);
  return load;
}

float analogToAmperes(float analogval){
  float load = mapfloat(analogval, analogCurrentA, analogCurrentB, currentA, currentB);
  return load;
}

//float analogToThrust(float analogval){
//  float load = mapfloat(analogval, analogThrustA, analogThrustB, thrustA, thrustB);
//  return load;
//}

void measureRPM() {
  rpm = 60000000 / ((micros() - rpmStart) * propBlades);
  rpmStart = micros();
}