Start Das Forum Die Technikecke RC-Technik und Elektrik Eigenbau RPM Tester Brushless Motoren
Willkommen, Gast
Benutzername: Passwort: Angemeldet bleiben:
  • Seite:
  • 1
  • 2

THEMA: Eigenbau RPM Tester Brushless Motoren

Eigenbau RPM Tester Brushless Motoren 16 Feb 2025 11:24 #11

  • Kay_01
  • ( Administrator )
  • OFFLINE
  • Administrator
  • Beiträge: 1720
  • Dank erhalten: 1668
Moin Lex,

das sieht doch irgendwie schon ganz fertig aus. :1st:

Bezüglich der Formel ist mir ein Punkt ins Auge gefallen, der mir beim Bau er Zeiterfassung ebenfalls über den Weg gekommen ist. Der Befehl >delay()< hält das Programm für eine gewisse Zeit an und lässt es nach Ablauf der Zeit wieder laufen.

Besser ist die Variante mit dem Befehl >millis()< in Verbindung mit einer Bedingung >if(){}< . Millis ist die Zeit in ms, die der Prozessor/Controller seit dem Einschalten läuft. Wenn Du diesen Wert in eine Variable steckst (als Anfang einer Verzögerung) und diesen Wer um die gewünschten Verzögerung erhöhst, dann kann die if-Schleife auslösen, wenn der Wert erreicht ist. Der Vorteil ist, dass das Programm permanent läuft und damit auch keine anderen Zetimessungen verzerrt werde.

Viele Grüße, Kay
Der Administrator hat öffentliche Schreibrechte deaktiviert.

Eigenbau RPM Tester Brushless Motoren 16 Feb 2025 12:25 #12

  • Lex Verkuijl
  • ( Supermoderator )
  • OFFLINE
  • Moderator
  • Beiträge: 4874
  • Dank erhalten: 3149
Hi Kay,

Im Grunde hast du recht, eine Warteschleiffe mit 'Millis()' nutze ich öfters. Aber hier funktioniert das ein bischen anders. Die RPM erfassung geht über Interrupt. Währed der 100ms 'Pausezeit' laufen diese interrups weiter, aber das Programm wartet. Dan passiert nur diese Erfassung. Darum auch die Interupt ein- und auf schaltung. Damit gibt es keine unerwartete Unterbrechungen und wird die Drehzahl sauber erfast.

Mittlerweile habe ich die Fehler erkant und rausgenommen. Alles functioniert jetzt wie erdacht, ein Video stelle ich in Kürtze ein.
Gruss, Lex
Der Administrator hat öffentliche Schreibrechte deaktiviert.

Eigenbau RPM Tester Brushless Motoren 16 Feb 2025 15:49 #13

  • Lex Verkuijl
  • ( Supermoderator )
  • OFFLINE
  • Moderator
  • Beiträge: 4874
  • Dank erhalten: 3149
Funktioniert:



Hier ein Video der Funktionen. Anzahl der Polen und ob der interne ESC benutzt wird für die Messung, oder man kan mit wzei Drähte egal welcher Brushless Motor anschliessen zur messung.

VIDEO

Angehängt hier ist der uns Allen bekanner blaue TFL 3000KV Outrunner der am TFL-Mini geliefert wirdt.

Letzter Schritt ist noch eine Messung zur Kontrolle mit einen optischen Drehzahlmesser vor zu nehmen. An Hand davon kan noch eine Korrektur eingebaut werden wenn die Daten zufiel abweichen. Für jetzt ist das Project aber erfolgreich abgeschlossen. :dance:
Gruss, Lex
Der Administrator hat öffentliche Schreibrechte deaktiviert.
Folgende Benutzer bedankten sich: Klemens, Kay_01, Hasse.69, Floh, OldGun

Eigenbau RPM Tester Brushless Motoren 17 Feb 2025 17:05 #14

  • OldGun
  • ( Benutzer )
  • OFFLINE
  • Class AU Stock Racer
  • Beiträge: 393
  • Dank erhalten: 496
Hallo Lex,

bei meinen Messungen mit dem SkyRC Analyzer kam ich auf etwas andere Werte bei dem TFL F450B Motor.

Die Drehzahlangabe bei deinem Messgerät müsste um ca 100 rpm höher sein.

7,6 Volt mal 3092 KV = 23.499 rpm.

Bei meinen Messungen ergab auch die Amperezahl einen höheren Wert als bei Dir.
2 Amps vs 0,98 Amps bei Dir.

p.s.
Allerdings sind im Video auch höhere Zahlen zu sehen, also mal 23.450 rpm und 1,79 Amps.
Da dürften die Abweichungen nicht so groß ausfallen.
Der Administrator hat öffentliche Schreibrechte deaktiviert.

Eigenbau RPM Tester Brushless Motoren 19 Feb 2025 17:26 #15

  • Lex Verkuijl
  • ( Supermoderator )
  • OFFLINE
  • Moderator
  • Beiträge: 4874
  • Dank erhalten: 3149
Zuerst, ich habe nicht die Illusion das mein DIY-Gerät genauso gut funktioniert wie ein € 100 oder mehr gekauftes Messgerät. Eine Kalibration met optischen Drehzahlmesser steht auch noch in Planung.

Der angezeigte Werte von Volt zeigen nicht alles. 7,6 V kan 7,60 V sein, aber auch 7,69 V. Intern wirdt aber schon mit den wirklichen Wert gerechnet. Auch de RPM Sensor selber ist nicht 100% Sauber, da 'Rüttelt' es schon manchmal. Wie gesagt, Kalibration volgt.

Auch der AMP-Sensor ist wackelich. Darum ist ein Complementary Filter eingesetzt um den Wert einigermassen stabil anzeigen zu können, damit läugt die Nazeige aber hinter den actuellen wert her. Ist ja auch für die KV erfassung nich benötigd, aber nützlich als Vergleichswert bei Timing- oder andere Justierungen am ESC. Im SkyRc ist ein anderer ESC verbaut als bei mir, da kann auch der Unterschied her kommen. Die Amp-Angabe stimmt mit ein dazu angeklemmter Multimeter in Amp-Wiedergabe..


Für die Interessierten hier der komplette Arduino Code:
/*  brushless RPM meter
Readout: Volt, Amp, RPM, KV
 
Setup: instellen aantal polen
       instellen interne meting via ESC of extern via draden
 
Tijdens meting knop drukken is weer naar setup
Knop draaien is gas
*/
 
#include <LiquidCrystal_I2C.h>
#include <Servo.h>
 
LiquidCrystal_I2C lcd(0x27,16,2);  // set the LCD address to 0x27 for a 16 chars and 2 line display
 
Servo ESC; // servo object voor ESC
 
// define custom charaters
byte Gas0[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x04};
byte Gas1[8] = {0x00,0x00,0x00,0x00,0x00,0x0F,0x1F};
byte Gas2[8] = {0x00,0x00,0x00,0x00,0x0F,0x0F,0x1F};
byte Gas3[8] = {0x00,0x00,0x00,0x07,0x0F,0x0F,0x1F};
byte Gas4[8] = {0x00,0x00,0x07,0x07,0x0F,0x0F,0x1F};
byte Gas5[8] = {0x00,0x03,0x07,0x07,0x0F,0x0F,0x1F};
byte Gas6[8] = {0x03,0x03,0x07,0x07,0x0F,0x0F,0x1F};
 
String Pole;
String Volt;
String Amp;
String KV;
String RPM;
String KVad;
String RPMad;
 
const int ESCpin=10;     // ESC out signaal
const int PinS1=4;       // encoder signaal
const int PinS2=3;       // encoder signaal (VAST INTERRUPT)
const int PinRPM=2;      // RPM sensor signaal (VAST INTERRUPT)
const int PinSW=5;       // drukschakelaar encoder
const int BeepPin=8;     // plus beeper
const int RelaisPin1=A0; // relaicoil 1 plus
const int RelaisPin2=A1; // relaiscoil 2 plus
const int AmpPin=A2;     // AMP sensor signaal
const int VoltPin=A3;    // Volt read pin (midden weestandbrug)
//        A4             // I2C pin SDA (VAST) 
//        A5             // I2C pin SCL (VAST)
 
int P=6;
double V;
double V_oud;
double A;
double A_oud;
int Kv;
int G;
int RpmLengte;
int KvLengte;
int ESCval=1000;
 
volatile int Teller;
volatile long Rpm;
volatile long RPMcount;
 
bool RPMinput;
bool Relais1;
bool Relais2;
 
unsigned long LaatsteDraai=0;
 
void setup() {
 
  lcd.init();                 // initialize the lcd 
  lcd.backlight();            // backlight aan
  Serial.begin(115200);
 
  pinMode(PinS2, INPUT);
  attachInterrupt(digitalPinToInterrupt(PinS2), EncoderDraai, LOW);
  pinMode(PinRPM, INPUT);
  attachInterrupt(digitalPinToInterrupt(PinRPM), InterruptFired, CHANGE);
 
  lcd.createChar(0, Gas0);    // charakters gas instellen
  lcd.createChar(1, Gas1);
  lcd.createChar(2, Gas2);
  lcd.createChar(3, Gas3);
  lcd.createChar(4, Gas4);
  lcd.createChar(5, Gas5);
  lcd.createChar(6, Gas6);
 
  pinMode(PinS1, INPUT);
  pinMode(PinSW, INPUT_PULLUP);
  pinMode(BeepPin, OUTPUT);
  pinMode(RelaisPin1, OUTPUT);
  pinMode(RelaisPin2, OUTPUT);
  pinMode(AmpPin, INPUT);
  pinMode(VoltPin, INPUT);
 
  ESC.writeMicroseconds(ESCval);
  ESC.attach(ESCpin);
 
  V_oud=analogRead(VoltPin); // init oud voltage
  Beep();                    // aan signaal
  manual_input_setup();      // manual setup draaien
}
 
void loop() {
 
// -------- drukken switch -----------
  if (!digitalRead(PinSW)) {      // als gedrukt
    Beep();                       // signaal
    ESC.writeMicroseconds(1000);  // ESC uit
    while (!digitalRead(PinSW)) { // wachten op loslaten
    delay(10);
    }  
  manual_input_setup();           // manual setup draaien
  }
 
// Volt
  V=analogRead(VoltPin); // volt lezen 
  V=(V*0.3)+(V_oud*0.7); // comp filter
  V_oud=V;               // reset oud
  V=map(V, 0, 666, 0, 11200); // map naar voltage
  V/=1000;               // werkelijke voltage
  if(V<0) V=0.0;         // min uitsluiten
  Volt=String(V,1);      // Volt waarde naar string
  if(Volt.length()<4) {  // als string te kort
    Volt=" "+Volt;       // spatie toevoegen
    lcd.setCursor(4,0);  // cursor plaatsen
    lcd.print(" ");      // oud char met spatie overschrijven
  }
  lcd.setCursor(4,0);    // cursor plaatsen
  lcd.print(Volt);       // string printen
 
// Amp
  A=((analogRead(AmpPin)-526.0)/100.0); // lees ampere
  if(A<0) A=0,0;         // min uitsluiten
  if(G==0) {             // bij gas nul, versneld naar nul
    A=0;                 // amp nul
    A_oud=0;             // amp oud nul
  }
  A=(A*0.1)+(A_oud*0.9); // comp filter
  A_oud=A;               // reset oud
  A*=2.84;               // omzetten meetwaarde naar amp                      
  Amp=String(A,2);       // Amp waarde naar string
  lcd.setCursor(11,0);   // cursor plaatsen
  lcd.print(Amp);        // string printen
 
// RPM
  ReadRpm();             // lees rpm
  RPM=String(Rpm);       // naar string
  RpmLengte=RPM.length();// lengte string
  RPMad="";              // opvul bepalen
  if(RpmLengte==1) {RPMad="    ";// opvul 4 spaties
  } else 
  if(RpmLengte==2) {RPMad="   "; // opvul 3 spaties
  } else
  if(RpmLengte==3) {RPMad="  ";  // opvul 2 spaties
  } else
  if(RpmLengte==4) {RPMad=" ";   // opvul 1 spatie
  }
  RPM=RPMad+RPM;         // string samenstellen
  lcd.setCursor(10,1);   // cursor plaatsen
  lcd.print("     ");    // wissen
  lcd.setCursor(10,1);   // cursor plaatsen
  lcd.print(RPM);        // string printen
 
// KV
  Kv=Rpm/V;              // kv berekenen
  KV=String(Kv);         // naar string
  KvLengte=KV.length();  // lengte string
  if(KvLengte==1) {KVad="   ";// opvul 3 spaties
  } else 
  if(KvLengte==2) {KVad="  "; // opvul 2 spaties
  } else 
  if(KvLengte==3) {KVad=" ";  // opvul 1 spaties
  } else KVad="";             // opvul 0 spaties
  KV=KVad+KV;            // string samenstellen
  lcd.setCursor(3,1);    // cursor plaatsen
  lcd.print("    ");
  lcd.setCursor(3,1);    // cursor plaatsen
  lcd.print(KV);         // string printen
 
// Gas 
  G=G+Teller;            // gas bepalen
  Teller=0;              // teller reset
  G=constrain(G, 0, 7);  // gas begrenzen
  lcd.setCursor(0,1);    // cursor plaatsen
  if(G==0) lcd.write(0); // bepalen teken graph bar
  if(G==1) lcd.print("_");
  if(G==2) lcd.write(1);
  if(G==3) lcd.write(2);
  if(G==4) lcd.write(3);
  if(G==5) lcd.write(4);
  if(G==6) lcd.write(5);
  if(G==7) lcd.write(6);
  ESCval=1000+(G*145);   // puls esc bepalen
  ESC.writeMicroseconds(ESCval); // puls schrijven
 
delay(100);              // delay voor rustigere uitlees
 
}  // >>>>>>>>>>>>>>> END LOOP <<<<<<<<<<<<<<<<<<
 
  // >>>>>>>>>>>>>> RUBROUTINES <<<<<<<<<<<<<<<<
 
void EncoderDraai(){            // bij bewegen encoder
  if (millis()-LaatsteDraai>5){ // als minimaal 5ms verstreken
    Beep();                     // beep
    if (digitalRead(PinS1)){    // als draairichting CW
      Teller--;                 // teller bijwerken           
      } else                    // als draairichting CCW
      {
      Teller++;                 // teller bijwerken
      }
    LaatsteDraai=millis();      // tijd reset
  }
}
 
void manual_input_setup() {
  // initialiseren
  lcd.clear();        
  lcd.setCursor(8,0);
  lcd.print("P");
  lcd.setCursor(2,1);
  lcd.print("Pole nr setup");
  // instellen aantal polen
  while(digitalRead(PinSW)) { // terwijl knop niet gedrukt instellen waarde
    P=P+Teller*2;             // pool waarde veranderen
    Teller=0;                 // teller reset
    P=constrain(P, 2, 30);    // polen begrenzen
    Pole=String(P);           // Pole waarde naar string
    if(Pole.length()<2) {     // als string te kort
      Pole=" "+Pole;          // spatie toevoegen
      lcd.setCursor(5,0);     // cursor plaatsen
      lcd.print(" ");         // oud char met spatie overschrijven
    }
  lcd.setCursor(5,0);         // cursor plaatsen
  lcd.print(Pole);            // string printen
  }
  Beep();
  while(digitalRead(PinSW)==LOW) {} // wacht knop loslaten
  // initialiseren
  lcd.clear();
  lcd.setCursor(0,0);
  // ingestelde waarde weergeven
  if(RPMinput){                // extern geschakeld
      lcd.print(" EXTERN CONNECT "); 
    } else {                   // bij intern geschakeld
      lcd.print("   INTERN ESC   ");
      }
  lcd.setCursor(3,1);
  lcd.print("Input setup");
  while(digitalRead(PinSW)) { // terwijl kop niet gedrukt
    if(Teller!=0) {           // bij draaien
    Teller=0;                 // reset teller
    RPMinput=!RPMinput;       // wissel input
    lcd.setCursor(0,0);
    if(RPMinput){             // betreffende input weergeven
      lcd.print(" EXTERN CONNECT ");
      digitalWrite(RelaisPin1, HIGH);
      delay(5);
      digitalWrite(RelaisPin1, LOW);
    } else {
      lcd.print("   INTERN ESC   ");
      digitalWrite(RelaisPin2, HIGH);
      delay(5);
      digitalWrite(RelaisPin2, LOW);
      }
    }
  }
  Beep();
  while(digitalRead(PinSW)==LOW) {} // wacht knop loslaten 
  // initialiseer vast display
  lcd.setCursor(0,0);
  lcd.print("  P     V      A");
  lcd.setCursor(0,1);
  lcd.write(0);
  lcd.print("G     KV      R");
  lcd.setCursor(0,0);  // cursor plaatsen
  Pole=String(P);
  lcd.print(Pole);     // string printen
  G=0; // reset gas op nul
  // terug naar loop
}
 
void Beep() {          // beep laten klinken
  digitalWrite(BeepPin, HIGH);
  delay(5);
  digitalWrite(BeepPin, LOW);
}
 
void InterruptFired()  // interrupt voor rpm read, teller verhogen
{ RPMcount++; }
 
void ReadRpm() {       // rpm read, bereken
  noInterrupts();      // interrupts uit 
  RPMcount=0;          // set variable in critical section
  interrupts();        // interrupts aan
  delay(200);          // wachttijd waarbij stabiel RPM gemeten kan worden
  noInterrupts();      // interrupts weer uit, meetwaarde constant
  Rpm=RPMcount*60/P*5; // bereken RPM     (Hz x 60 x 2) / number of poles = no-load RPM
  interrupts();        // interrupt aan     
 }
Gruss, Lex
Der Administrator hat öffentliche Schreibrechte deaktiviert.
Folgende Benutzer bedankten sich: Klemens, Hasse.69, OldGun

Eigenbau RPM Tester Brushless Motoren 19 Feb 2025 18:02 #16

  • OldGun
  • ( Benutzer )
  • OFFLINE
  • Class AU Stock Racer
  • Beiträge: 393
  • Dank erhalten: 496
Hi Lex,

also ich finde dein Gerät schon klasse !
Ich wollte da nicht kritisieren.

Für den Preis welcher ein SkyRC Analyzer kostet, erwarte ich aber schon das die Werte von dem Gerät stimmen.

Wenn ich sehe was dein Gerät anzeigt, dann frage ich mich ob die Anschaffung von dem SkyRC Analyzer überhaupt lohnt.

Fest steht, das was Du da bauen kannst, dazu bin ich nicht fähig.
(Zu oft in Physik in der Schule gefehlt :-) )
Der Administrator hat öffentliche Schreibrechte deaktiviert.
Folgende Benutzer bedankten sich: Lex Verkuijl

Eigenbau RPM Tester Brushless Motoren 20 Feb 2025 18:15 #17

  • Lex Verkuijl
  • ( Supermoderator )
  • OFFLINE
  • Moderator
  • Beiträge: 4874
  • Dank erhalten: 3149
Also ... ein Test mit optischen Drehzahlmesser ist gelaufen. Das Resultat hat mich schon überrascht: Der Arduino mit Hobbywing RPM Sensor ergibt so gut wie genau gleiche Werte wie der optische Drehwahlmesser! Und dann meine ich 99,5 % genau, damit kann ich leben!

Die Stabilisierungsfilter für die Volt und Amp Angaben habe ich auch noch was getweeked. Volt ist jetzt stabiler, und auf 99% genau. Amp bleibt etwas wackelich, der € 0,56 China-Sensor kann mann wahrscheinlich auch nichts besseres zutrauen. Für Vergleichswerte ist die Angabe aber sicher gut brauchbar.

Damit ist das RPM-Mess-Project dan wirklich zu ende. Nicht nur ist das Gerät doch ziehmlich genau, eine ganze Menge billiger, aber hat auch Spass gemacht zu bauen!
Gruss, Lex
Der Administrator hat öffentliche Schreibrechte deaktiviert.
Folgende Benutzer bedankten sich: Klemens, Kay_01, Hasse.69, Floh, OldGun
  • Seite:
  • 1
  • 2
Powered by Kunena Forum