Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

Dir gefällt die Seite?
Gib mir n Bier aus!

modellbau:avr:thrustmeter

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();
}

Ich garantiere bei meinen Bauberichten und Teilelisten keine Vollständigkeit etc...es wird aus den Teilen gebastelt die gerade herumliegen.
Bitte keine Anfragen zum Bau/Fräsen von Frames, Teilen oder sonstigen Aufträgen. Ich betreibe die Seite rein als Hobby und nutze die zur Verfügung stehende Zeit gerne für meine eigenen Projekte.
Bei einigen Projekten werde ich zu gegebener Zeit die Pläne veröffentlichen - aber auch hier lasse ich mich ungern hetzten ;-)

No waranties for completeness of any contructions, part lists etc.. I build from party i have just lying around in my workshop.
Please, No requests to buy frames, builds, etc.. I run this page in my spare-time and as hobby only. Want to keep my free time to work on my own projects - sorry
I will release the plans for some build at some point in time, but again, please don't ask for unreleased plans, i don't want to get rushed ;-)

modellbau/avr/thrustmeter.txt · Zuletzt geändert: 2017/04/18 von hermenj