PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Hall Motor auslesen



Sinnloserknopf
28.08.2017, 20:06
Moin Moin,
Ich habe einen Scooter und möchte mit einem Arduino fest stellen ob der Motor sich Dreht wenn ja drehrichtung und Umdrehung/m messen.


Der Motor hat 3 Hall Sensoren die ich auf 3 D. Eingänge gelegt habe.



Ich schon einiges gelesen & auch verstanden wie man das Messen kann. Vorallem wie man die Drehrichtung feststellen kann.


Aber wie ich das Programieren soll ist für mich ein rätzel^^ hat das von euch schonmal jemand gemacht und könnte mir evtl eine kleine Demo zur verfügung stellen?


Lg

Klebwax
29.08.2017, 02:43
Mal ein paar Gedanken vorneweg. Um die Drehzahl zu bestimmen, benötigt man ein Signal, daß mit der Drehung wechselt. So einen einfachen Encoder. Dann muß man "nur noch" die Zeit zwischen zwei gleichen Flanken bestimmen und kann daraus die Drehzahl bestimmen. Dazu reicht das Signal von einem Hallsensor aus. Man kann da z.b. die Capture-HW des µC verwenden und damit die Zeit zwischen zwei Low-High (bzw zwei High-Low) Flanken bestimmen.

Um die Drehrichtung zu bestimmen, braucht man noch ein zweites Signal, daß in der Phase zum ersten verschoben ist. Diese muß nicht 90° sein, da tun es auch die typisch 60° der Hallsensoren eines BLDCs. Wichtig ist nur, daß sich die Phasenbeziehung zwischen den beiden Signalen während einer Umdrehung nicht ändert. Stichwort ist da Inkrementalgeber (https://de.wikipedia.org/wiki/Inkrementalgeber#Signalauswertung). Am Ende braucht man von den drei Hallsensorsignalen nur zwei um Drehzahl und Richtung zu bestimmen.

Wie man das jetzt praktisch realisiert, hängt von den Umständen ab. Da ist zum ersten der Drehzahlbereich, den man erfassen will. Dann kommt der Aufbau des Motors dazu: wieviele Polpaare hat er. Daraus kann man dann die höchstmögliche Frequenz des Hall-Signals bestimmen. Dann kommt der µC. Wie schnell ist er? Kann ich Hallsignale in einem schnellen Timerinterrupt sampeln und daraus dann sowohl Drehzahl als auch Drehrichtung bestimmen? Hier mal etwas zur Drehrichtungserkennung (http://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29), die Drehzahlbestimmung läßt sich da noch einbauen. Wenn die Frequenz des Hallsignals hoch und der Prozessor langsam ist, muß ich z.B. die Capture-HW zu Hilfe nehmen. Manche µC haben auch einen Quadratur-Encoder in HW, den könnte ich auch benutzen.

Das ist leider keine fertige Lösung für dein Problem, sollte aber mögliche Lösungswege aufzeigen.

MfG Klebwax

Sinnloserknopf
04.09.2017, 20:09
Danke für deine ausführliche Antwort.
Ich habe jetzt einiges versucht und komme langsam an meine Zweifel ob mein UNO schnell genug für mein vorhaben ist.

Der Motor bringt maximal 800 U/min. Je Umdrehung kommen pro Hall Sensor 30 Impulse. Sind also 400 Impulse pro Sekunde pro Sensor. Schafft der Uno das noch?

shedepe
04.09.2017, 20:26
Überleg dir mal mit welchem Takt der Uno läuft. Dann hast du ein Gefühl für die Zeiten bzw. Taktraten

Sisor
04.09.2017, 22:15
Wie lang sind die Impulse? Ohne 3 Hardware-Interrupts wirds evtl. schwierig, die Impulse sicher zu detektieren (der UNO hat 2 Hardware-Interrupts (https://www.arduino.cc/en/Reference/AttachInterrupt)). Ohne Hardware-Interrupts müssen die 3 Digital-Inputs schneller abgetastet werden, als die Impulse lang sind.
Was soll der Arduino mit den Drehzahl-Daten machen?

Sinnloserknopf
04.09.2017, 22:28
Hei,
2 Sensoren reichen mir eigendlich. Ich brauch die Drehrichtung und die ungefähre Geschwindigkeit.

Gruß

Sisor
04.09.2017, 23:00
Hab noch mal nachgedacht: Ein Hardware-Interrupt reicht aus. Und 2 Sensoren.
Wenn Flanke an Sensor1 (per Hardware-Interrupt detektiert), wird Zustand an Sensor2 gemessen: Wenn High: Drehrichtung A, wenn Low: Drehrichtung -A.
Anzahl Impulse / Zeiteinheit ist Drehgeschwindigkeit.
So schafft der UNO das locker. Das Programmieren ist auch nicht schwer.
Vorausgesetzt das Signal der Sensoren sieht so aus (https://i.stack.imgur.com/tXBod.png).

Klebwax
05.09.2017, 02:55
Hab noch mal nachgedacht: Ein Hardware-Interrupt reicht aus. Und 2 Sensoren.
Wenn Flanke an Sensor1 (per Hardware-Interrupt detektiert), wird Zustand an Sensor2 gemessen: Wenn High: Drehrichtung A, wenn Low: Drehrichtung -A.
Anzahl Impulse / Zeiteinheit ist Drehgeschwindigkeit.[/URL].

Wenn man den Input Capture des Prozessors nutzen und dieser einen Interrupt hat, bekommt man auch die Drehzahl recht präzise gemessen. Weiß jetzt nicht, ob der UNO das hat.

MfG Klebwax

Sinnloserknopf
05.09.2017, 17:31
Moin Moin,
ich habe mal folgende Lib probiert: RotaryEncoder.h

(http://www.mathertel.de/Arduino/RotaryEncoderLibrary.aspx)
#include <RotaryEncoder.h>

// Setup a RoraryEncoder for pins A2 and A3:
RotaryEncoder encoder(A2, A3);

void setup()
{
Serial.begin(9600);
Serial.println("SimplePollRotator example for the RotaryEncoder library.");

// You may have to modify the next 2 lines if using other pins than A2 and A3
PCICR |= (1 << PCIE1); // This enables Pin Change Interrupt 1 that covers the Analog input pins or Port C.
PCMSK1 |= (1 << PCINT10) | (1 << PCINT11); // This enables the interrupt for pin 2 and 3 of Port C.
} // setup()



// The Interrupt Service Routine for Pin Change Interrupt 1
// This routine will only be called on any signal change on A2 and A3: exactly where we need to check.
ISR(PCINT1_vect) {
encoder.tick(); // just call tick() to check the state.
}


long position = -999;
void loop()
{
static int pos = 0;

int newPos = encoder.getPosition();
if (pos != newPos) {

if(newPos < position){
Serial.print("Vor");
}else{
Serial.print("Zurueck");
}
position = newPos;

Serial.println();
pos = newPos;

if (newPos == 66)
delay(6600);
} // if
} // loop ()

// The End


Damit kann ich schon mal zuverlässig Vor und Zurück erkennen. Der Uno ist also schnell genug hab es nur scheiße programmiert....

werde es weiter versuchen :)

Sisor
05.09.2017, 23:44
Moin Moin,
ich habe mal folgende Lib probiert: RotaryEncoder.h (http://www.mathertel.de/Arduino/RotaryEncoderLibrary.aspx)

Damit kann ich schon mal zuverlässig Vor und Zurück erkennen. Der Uno ist also schnell genug hab es nur scheiße programmiert....

werde es weiter versuchen :)
Hi, in dein Code hat noch Schwächen:
- Ein Motor kann auch stehen
- Überflüssige Variable: Position
- Die Zeilen 'if (newPos == 66) delay(6600);' sind sinnlos
- Test 'if(newPos < position) ...': Die Variable newPos läuft irgendwann über. Dann ist einmal newPos kleiner als pos -> Test liefert einmalig falsche Richtung.
Vorschlag:

#include <RotaryEncoder.h>

// Setup a RoraryEncoder for pins A2 and A3:
RotaryEncoder encoder(A2, A3);

enum {zurueck =-1, still, vor}; // Motorrichtung
sign(int x) { return (x>0)-(x<0); } // Vorzeichen einer Zahl : -1, 0, +1

void setup() {
Serial.begin(9600);
Serial.println("SimplePollRotator example for the RotaryEncoder library.");

// Interrupt für Encoder festlegen
PCICR |= (1 << PCIE1);
PCMSK1 |= (1 << PCINT10) | (1 << PCINT11);
}

// Interrupt Service Routine für Pin Change Interrupt 1
ISR(PCINT1_vect) { encoder.tick(); }

void loop() {
static int pos = 0;
int newPos = encoder.getPosition();
int richtung = sign(newPos - pos);

switch(richtung) {
case zurueck:
Serial.println("Zurueck!"); break;
case still:
Serial.println("Still!"); break;
case vor:
Serial.println("Vor!"); break;
}
Serial.println();

pos = newPos;
}
}

Sinnloserknopf
06.09.2017, 17:39
chic, danke :)

Sinnloserknopf
09.09.2017, 14:53
So,
ich bins mal wieder.


Ich wollte mich nochmal bei Sisor bedanken.

Er hat mich bei meinem Projekt kräftig weitergebracht.

Hier sein Meisterwerk:

Zum Code (https://create.arduino.cc/editor/Sisor/520cb0d0-bd11-4046-a68f-d5a0f6c5ff30/preview)



vielen Dank dafür!