Drehzahlmessung von zwei Motoren gleichzeitig

Hallo
Aus welcher Quelle "kommen aufeinmal sehr unrealistische Werte heraus"?

Hi,
die Werte rpm_left und rpm_right sind es die nicht stimmen.

Moin,

Ich messe 3 Lüfterdrehzahlen quasi gleichzeitig und schreibe sie in eine Datenbank.
Ich mache das so, dass ich Drehzahlimpulse eine Minute lang aufaddiere und dann den Wert schreibe.
D.h. mir reicht jede Minute ein Wert.
Mein Sketch funktioniert ohne Interrupts.

Wie oft brauchst du die Drehzalwerte?

Beste Grüße,
Chris

Hallo,
die Drehzahlen brauche ich mindestens sekündlich, wenn nicht sogar öfters....aber löst das mein Problem mit dem GPS-Modul?
Gruß und Danke für die Antwort,
Tobi

Hallo,
ich kenne das GPS Modul nicht , aber was ich so gefunden habe werden die mittels RX,TX seriell verbunden. Pin11 und 12 hast Du doch bereits für die SD Karte verwendet. SoftSeriell hast Du ja noch gar nicht drin. Ich glaube dafür gibt es keine Pin Beschränkungen zu , kannst Du also an andere freie Pins verwenden.

Wenn Du doch die Drehzahl von den Motoren hast , macht es da nicht mehr Sinn die Geschwindigkeit damit zu ermitteln. Was glaubst Du denn wie genau das GPS ist.? ich kann mir nicht vorstellen das da weniger als 3-10m geht.
Heinz

Hi @Rentner
um mit dem GPS-Modul kommunizieren zu können verwende die SoftwareSerial bibliothek, funktioniert alleine auch ganz gut. Aber sobald ich das Modul an den Arduino schließe (auch wenn noch der "alte" Code nur zur Drehzahlmessung läuft) fangen die Werte an zu spinnen.
Sprich: Ich messe die Drehzahlen, alles funktioniert. Ich schließe das GPS-Modul an ohne neuen Code hochzuladen, die Werte fangen an zu spinnen, ich nehme das GPS-Modul wieder weg, die Drehzahlen werden wieder realistisch.
Der Vollständgkeit halber hier trotzdem mein Code zur Drehzahl- und Geschwindigkeitsmessung:

/*
  IR1:          IR2:        SD:         GPS:
  Vcc - 5V      Vcc - 5V    CS - D5     VCC - 5V
  GND - GND     GND - GND   SCK - D13   GND - GND
  AO - D2       AO - D3     MOSI - D11  RX - D6
                            MISO - D12  TX - D7
                            Vcc - 5V
                            GND - GND
*/

#include <SD.h>
#include <SPI.h>
#include <util/atomic.h>
#include <TinyGPSPlus.h>
#include <SoftwareSerial.h>

static const int RXPin = 6, TXPin = 7;
static const uint32_t GPSBaud = 9600;

volatile unsigned long period_left = 0;
volatile unsigned long period_right = 0;

unsigned long p_left = 0;
unsigned long p_right = 0;

unsigned long timer_left = 0;
unsigned long t_left = 0;
volatile unsigned long lasttime_left = 0;

unsigned long timer_right = 0;
unsigned long t_right = 0;
volatile unsigned long lasttime_right = 0;

long rpm_left = 0;
long rpm_right = 0;

unsigned long timer = 0;
unsigned long lasttime = 0;

double speed = 0;

long update_interval = 500;

SoftwareSerial ss(TXPin, RXPin);
TinyGPSPlus gps;

void setup() {
  SD.begin(5);
  ss.begin(GPSBaud);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  attachInterrupt(digitalPinToInterrupt(2), RPM_left, RISING);  //isr akivieren
  attachInterrupt(digitalPinToInterrupt(3), RPM_right, RISING);
}

void loop() {

  timer = micros();

  if (timer - lasttime > update_interval * 1000) {
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { //variablen umladen und wieder schnellstmöglich freigeben
      p_left = period_left;
      p_right = period_right;
      t_left = lasttime_left;
      t_right = lasttime_right;
    }

    lasttime = timer;

    if (micros() - t_left < update_interval * 1000) {  //rpm_left = 0 wenn periodendauer länger als Messinterwall
      rpm_left = 60000000 / p_left;                    //60000000 da mikrosekunden, und umwandlung in Minuten
    }
    else {
      rpm_left = 0;
    }

    if (micros() - t_right < update_interval * 1000) {  //rpm_right = 0 wenn periodendauer länger als Messinterwall
      rpm_right = 60000000 / p_right;
    }
    else {
      rpm_right = 0;
    }

    if (gps.speed.isValid())
    {
      speed = gps.speed.mps();
    }
    else
    {
      speed = -1;
    }

    Print_data();
  }
}
void RPM_left () {
  timer_left = micros();
  period_left = timer_left - lasttime_left;
  lasttime_left = timer_left;
}

void RPM_right() {
  timer_right = micros();
  period_right = timer_right - lasttime_right;
  lasttime_right = timer_right;
}

void Print_data() {
  File data = SD.open("RPM.txt", FILE_WRITE);         //Datei öffnen, Schreiben und gleich schließen um Sicherung der Messwerte zu garantieren
  data.print(round(timer / 1000000));
  data.print(";");
  data.print(rpm_left);
  data.print(";");
  data.print(rpm_right);
  data.print(",");
  data.println(speed);
  data.close();
}

Da es sich bei dem Projekt um die Messung für ein RC-Boot handelt kann ich nicht direkt von der Drehzahl der Motoren auf die Geschwindigkeit schließen. Die Messungen dienen dazu, den (noch) fehlenden Zusammenhang zwischen Drehzahlen und Geschwindigkeit zu ermitteln.

Gruß,
Tobi

Klingt nach einem elektrischen Problem. Wenn die Motoren stehen, wenn du D2 /D3 statt mit deinem Impulsgeber zu verbinden mit GND verbindest oder offen lässt, wie wirkt sich das jeweils auf die Drehzahl-Werte aus, wenn das GPS Modul angeschlossen ist?
Die Pulsgeber über ein abgeschirmtes oder verdrilltes Kabel (GND/D2), 5V separat anschließen ...

1 Like

Hi, probiere ich mal aus, muss aber erst noch abgeschirmte Kable besorgen...
Gruß,
Tobi

Telefon-Leitungen, Alufolie, ...
erstmal probieren, ob es daran überhaupt liegt.

1 Like

Hallo,
ok jetzt ist es klarer. Sind die falschen Messwerte instabil und ehr viel zu hoch ? Ich muss nochmals nach den Sensoren für Die Drehzahl fragen. In#1 schreibst Du IR Sensoren. was haben die für Ausgänge.? Eventuell hängt das der Eingang in der Luft. Du hast die Eingänge dazu positiv schaltend festgelegt pinMode(pin , INPUT) . Damit sollte ein externer Pulldown vorhanden sein Damit der Pegel eindeutig LOW ist, oder der Sensor liefert einen ausreichenden LOW Pegel.
Eventuell kannst Du auch noch einen zusätzlichen erternen Pulldown nehmen, damit das niederohmiger wird. (Versuch mal 1K ) Je nach max Frequenz macht eventuell auch ein Kondensator Sinn. Jedenfalls scheint das irgendetwas zu stören.
Heinz

1 Like

Hi

viel zu hoch, vor allem bei niedrigen Drehzahlen (60-180rpm) werden hin und wieder Drehzahlen im Zehntausender-Bereich ausgegeben.

Ich verwende diese Sensoren:
https://www.funduinoshop.com/epages/78096195.sf/secbb16801e34/?ObjectPath=/Shops/78096195/Products/R12-C-6-2
Die haben einen digitalen und einen analogen Ausgang, wobei mir gerade aufgefallen ist dass die Sensoren mit dem analogen Ausgang an dem Arduino angeschlossen sind. Stecke ich auf den digitalen Ausgang um funktioniert nichts mehr (wird der Sensor aktiviert gibt das Programm eine Drehzahl von 50.000.000 aus, ansonsten 0)
....ich begebe mich da mal auf Fehlersuch.
Danke und Gruß

@michael_x: Wenn ich SD-Kartenmodul und die IR-Sensoren an den 5V-Pin des Arduinos schließe und das GPS-Modul an den 3.3VPin klappt das Ganze.
Danke für den Tipp der getrennten Stromversorgungen.
Gruß,
Tobi

Sry, komme etwas spät dazu ... :wink:

Wenn ich den aktuellen Code korrekt interpretiere, wird per ISR regelmäßig mit steigender Flanke die Zeit für eine Umdrehung gemessen. Im Sketch weiterverwendet wird allerdings nur die Zeit aus dem "allerletzten" Interrupt vor dem Auslesen. Soweit korrekt?

D.h. die Genauigkeit der Umdrehungszahl hängt ausschließlich von der Zeitmessung eines Umlaufs ab. Alternativ könnte man einen erheblichen Genauigkeitsgewinn erzielen, wenn man die Anzahl der Umdrehungen über ein deutlich größeres Zeitintervall zählt (entschlackt sogar die ISR) und die Umdrehungszeit dann durch Umdrehungen*60000UL/(Zeitintervall [ms]) in [RPM] errechnet, gerne auch micros() verwenden, wenn es hilft.

Es sei denn es interessiert gar nicht die mittlere Drehzahl über ca. 500 ms (update_interval), sondern tatsächlich genau die letzte Umdrehung zum Ablauf dieser Frist.
[Achtung bitte meinen Post #34 beachten; danach kann ein update_interval = 500 ms frühestens erst ab mindestens 2 Hz = 2 Umdrehungen/s brauchbare Ergebnisse liefern]

Jede Interaktion, die das Timing dieses letzten Interrupts beeinflusst, beeinflusst das RPM-Ergebnis. Durch die o.a. Mittelung sollten kleine zeitliche Verschiebungen "im Rauschen" untergehen.

1 Like

60 bis 180 rpm bedeuten nach Adam Riese 1 bis 3 Umdrehungen pro Sekunde. Das heißt logischerweise, dass eine Messung unterhalb 1 Sekunde nicht genügt, um die Umdrehungszahl zu erfassen. Hier hilft dann nur den Messzeitraum auf über eine Sekunde anzupassen. Letztlich soweit, dass auch der langsamste Vorgang, den man nicht mit "Null" gleichsetzen will, erfasst werden kann.

P.S.: Hier würde es sich vermutlich lohnen, RPM-Werte solange als ungültig zu behandeln, bis reale Umdrehungswerte gemessen wurden.

1 Like

Hallo @ec2021

jawoll, richtig interpretiert

Stimmt, an den Ansatz hatte ich irgendwie gar nicht gedacht....probiere ich mal Umzusetzen. Bei bis zu 60.000U/min kommen auch in einer halben Sekunde ordentlich was an Pulsen rüber. Werde ich mal umsetzen.

Innerhalb der 500ms schwankt die Drehzahl nicht so stark als dass das einen großen Unterschied macht.

ist wahrscheinlich sinnvoll, vor allem da Umdrehungen kleiner als 1000U/min nicht interessieren...hatte zu Testzwecken gerade einen Motor in dieser Range da.

Vielen Dank für deine Rückmeldung, ich mache mich mal an die Umsetzung.

Gruß,
Tobi

Gerne!

Ich bin insgesamt noch nicht sicher, das Ziel, den Aufbau und die Randbedingungen der Aufgabe ausreichend erkannt zu haben, um wirklich zielgerichtet unterstützen zu können. Momentan schält sich folgendes - möglicherweise ganz oder in Teilen unzutreffendes - Bild heraus:

  • Die Anwendung soll/muss auf einem RC-Boot lauffähig sein.
  • Die Drehzahl zweier Motoren soll gemessen werden, um in Verbindung mit GPS einen Zusammenhang zwischen Drehzahl und Geschwindigkeit des Bootes ermitteln zu können.
  • Dabei spielen nur Drehzahlen gleich oder oberhalb von 1000 RPM eine Rolle.

Offene Fragen

  • Wind oder Wasserbewegungen
    • sind entweder ausgeschlossen oder werden vernachlässigt oder
    • werden auf noch nicht bekannte Weise ermittelt und berücksichtigt
  • Wie werden Beschleunigungsphasen (Anfahrt und Abbremsen) in den angestrebten Messungen, die über die Drehzahlmessung hinausgehen, berücksichtigt?
  • Wird zusätzlich zum Geschwindigkeits-/beschleunigungsvektor aus der GPS-Position auch die Ausrichtung des Bootes ermittelt und geplottet? (Wenn das Boot nach Lenkeingriff noch in "alter Richtung" gleitet und die Motorkraft/Schraube schräg, quer oder gar 180° zur momentanen Bewegungsrichtung liegt?

Vielleicht spielt das meiste auch keine Rolle für den Zweck ...

Gruß und viel Erfolg!

Hi, dann kann ich gerne noch etwas drumherum erklären:

genau, wir wollen ein ferngesteuertes Speed-Boot bauen, Geschwindigkeiten von ungefähr 250km/h sind geplant.

genau, damit wollen wir eine Auswahl an Schiffsschrauben testen um die geeignetste herauszufinden

ja, da sich das Boot bei 1000rpm noch nicht für uns im relevanten Geschwindigkeitsbereich bewegt, das passiert erst ab etwa 10.000 bis 60.000rpm.

werden vernachlässigt

spielt keine rolle

spielt vorerst keine Rolle, nur die Geschwindigkeit zählt.

Ich habe deinen Vorschlag aus Post #33 mal umgesetzt, der aktuelle Code ist unten.
Da ich bisher nur eine Markierung auf der Motorwelle habe sind die Drehzahlen ganzzahlige Vielfache von 60RPM. Ich denke sogar dass diese Genauigkeit ausreicht, 60Rpm von 60.000Rpm sind trotzdem nur ein Tausendstel....falls dass nicht reicht mache ich einfach ein paar Markierungen mehr auf die Welle, dass wird schon irgendwie klappen.
Im Code werden die Werte seriell ausgegeben, das ist nur für Testzwecke, im Einsatz werden die Werte dann auf eine SD-Karte geschrieben und nach einer Testfahrt mit Excel oder Matlab ausgewertet.

Hat das GPS-Modul kein Signal oder liefert keine brauchbaren Werte wird die Geschwindigkeit auf -1 gesetzt, dass wird dann im Postprocessing der Daten entsprechend verarbeitet.


/*
  IR1:          IR2:        SD:         GPS:
  Vcc - 5V      Vcc - 5V    CS - D5     VCC - 3.3V
  GND - GND     GND - GND   SCK - D13   GND - GND
  AO - D2       AO - D3     MOSI - D11  RX - D6
                            MISO - D12  TX - D7
                            Vcc - 5V
                            GND - GND
*/

#include <util/atomic.h>
#include <TinyGPSPlus.h>
#include <SoftwareSerial.h>

static const int RXPin = 6, TXPin = 7;
static const uint32_t GPSBaud = 9600;

SoftwareSerial ss(TXPin, RXPin);
TinyGPSPlus gps;

volatile int counter_left = 0;
volatile int counter_right = 0;

int rpm_left = 0;
int rpm_right = 0;

unsigned long timer = 0;
unsigned long lasttime = 0;

double speed = 0;

long update_interval = 500; // in Millisekunden

void setup() {
  Serial.begin(9600);
  ss.begin(GPSBaud);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  attachInterrupt(digitalPinToInterrupt(2), RPM_left, RISING);
  attachInterrupt(digitalPinToInterrupt(3), RPM_right, RISING);
}

void loop() {
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
    timer = micros();
  }

  if (timer - lasttime > update_interval * 1000) {
    rpm_left = 60000 * counter_left / update_interval;
    rpm_right = 60000 * counter_right / update_interval;
    counter_left = 0;
    counter_right = 0;
    lasttime = timer;
    if (gps.speed.isValid())
    {
      speed = gps.speed.mps();
    }
    else
    {
      speed = -1;
    }
    Print_data();
  }
}

void RPM_left () {
  counter_left++;
}

void RPM_right() {
  counter_right++;
}

void Print_data() {
  Serial.print(timer / 1000);
  Serial.print(";");
  Serial.print(rpm_left);
  Serial.print(";");
  Serial.print(rpm_right);
  Serial.print(";");
  Serial.println(speed);
}

Hui, das war jetzt viel Text. Evtl. (höchstwahrscheinlich) findet einer von euch noch Verbesserungen für meinen Code.

Grüße,
Tobi

int ist grundsätzlich der falsche Datentyp. (Verdacht auf Schlamperei :wink: )

rpm z.B. ist nie negativ und mit 60000 beim UNO schon zu groß.

2 Likes

@michael_x
und da fängts schon an :smiley:
stimmt natürlich. Eine unsigned long ist da wohl besser geeignet, oder?
gruß und Danke

Ich habe einfach mal die zugrunde liegende Berechnungsformel in einer Tabellenkalkulation abgebildet, sieht dann so aus:
image

Die Formel unter RPM lautet (60*counterSpalte/$update_int), mit $update_int als feste Zelle, wie z.B. $E$3. Die counter-Werte gehen z.B. von 1 bis 50.

Jetzt kann man mit dem update_int-Wert herumspielen und sich die RPM-Ergebnisse anschauen.
Besonders interessant ist dabei der Wert neben counter = 1. Je länger die Auswertezeit, desto "feiner" die rechnerische Granularität = "Auflösung".

Wenn Ihr die Umdrehungszahlen über einen längeren Zeitraum sammelt und regelmäßig in definierten kürzeren Abständen [Ergänzung: Mit Timestamp!] speichert, könnt Ihr im "Postprocessing" am heimischen Rechner sehr genaue Ergebnisse erzielen. Wenn man (z.B. in einer Tabellenkalkulation) Mittelwerte parallel über unterschiedlich lange Zeitintervalle errechnen lässt, sollte man eigentlich gut erkennen können, wo ein Mittelwert noch zutreffend ist und wo er zu sehr glättet.

Auf jeden Fall den Datentyp für den Zähler sorgfältig festlegen, wenn man keinen Wert auf eine eigene "Überlaufbehandlung" legt :wink: ).

P.S.: Mehr Marken an den Achsen anzubringen, ist natürlich auch ein hilfreiche Sache, um die Auflösung zu verbessern!

1 Like