Verwendung von BLDC-Hall-Sensoren als Positionsgeber – Teil 3
Verwendung eines Teensy-3.5-Mikrocontrollers zur Berechnung von Position, Richtung und Entfernung
Die folgenden Informationen sollen bei der Interpretation des logischen Ausgangs des Hall-Sensors zum Bestimmen von Position, Richtung und Geschwindigkeit helfen. Obwohl der Ausgang für die Motorkommutierung verwendet werden kann, wird dieser Aspekt des Betriebs bürstenloser DC-Motoren (BLDC-Motoren) hier nicht erläutert.
Lesen Sie Teil 1 und Teil 2 dieser Blogreihe, um dieses Projekt bis hierhin zu verfolgen.
Übersicht
Wenn die drei Ausgänge des Hall-Effekt-Sensors in einem BLDC in einen Mikrocontroller eingespeist werden, können die Signale wie ein dreikanaliger Drehgeber verarbeitet werden. Die Daten können angezeigt oder verwendet werden, um eine Impulszahl, die Drehrichtung sowie die durchschnittlichen Umdrehungen pro Minute (U/min) zu ermitteln. Die U/min werden gemittelt, um einen glatten Verlauf der angezeigten Werte zu erhalten.
Das Entwicklungsboard PJRC Teensy 3.5
Das Entwicklungsboard PJRC Teensy 3.5 von SparkFun (1568-1464-ND) verfügt über mehr als genügend digitale Interrupts für die drei Signaleingänge vom Hall-Sensor. Außerdem verfügt sie über eingelötete Steckleisten. Die Teensy 3.5 verfügt dank einer ausreichenden Anzahl an zusätzlichen I/O-Kanälen über genügend Leistung, um viele weitere Aufgaben auszuführen. Des Weiteren kann sie unter Verwendung der integrierten SD-Karte zur Datenprotokollierung verwendet werden.
Abbildung 1: Das Evaluierungsboard Teensy 3.5 von SparkFun Electronics. (Bildquelle: SparkFun Electronics)
Verbinden von Sensorausgang und PJRC Teensy 3.5
Nehmen Sie eine Steckplatine (438-1045-ND oder vergleichbar) zur Hand und positionieren Sie die Teensy 3.5 so, dass der USB-Anschluss nach rechts zeigt und die oberen Steckleistenpins in die erste Lochreihe der Steckplatine oberhalb der Unterteilung eingesetzt werden (Abbildung 2). So können die Sensorausgänge an die I/Os der Teensy angeschlossen werden.
Abbildung 2: Diese Abbildung zeigt die Steckplatine mit dem Entwicklungsboard Teensy 3.5 und Verbindungen über Drahtbrücken. (Bildquelle: DigiKey)
Verwenden Sie für alle Verbindungen auf der Steckplatine stabile Drahtbrücken (BKWK-3-ND). Verbinden Sie die positive Leitung (+) einer Stromversorgung (5 V, 1 A) mit der oberen oder unteren positiven Stromschiene der Steckplatine. Verbinden Sie anschließend die negative Leitung (-) der Stromversorgung mit der oberen oder unteren negativen Stromschiene. Verbinden Sie den positiven (rot) und den negativen (schwarz) Draht des Hall-Sensor-Steckverbinders mit der positiven bzw. der negativen Stromschiene der Steckplatine. Verbinden Sie dann die drei Sensordrähte des Steckverbinders an den Pins 2, 3 und 4 in beliebiger Reihenfolge mit der Teensy 3.5.
Der Sensorausgang ist Aktiv-Low. Das bedeutet, dass der Ausgang im ausgelösten Zustand mit der negativen Stromschiene verbunden ist. Im nicht ausgelösten Zustand muss der Sensorausgang auf die positive Stromschiene „hochgezogen“ werden, um zwei definierte Logikzustände zu erhalten. Platzieren Sie drei Widerstände (4 bis 8 kΩ) auf der Steckplatine, die als Pull-up-Widerstände für den Sensorausgang dienen (Abbildung 2).
Verbinden Sie die Teensy 3.5 über ein Kabel vom Typ Micro-USB-B-zu-Standard-USB-A mit einem Computer.
Software
Die Teensy 3.5 ist zu Programmierzwecken mit der integrierten Arduino-Entwicklungsumgebung (IDE) kompatibel. Die IDE und das Teensyduino-Add-on sind online erhältlich. Befolgen Sie das unter https://www.pjrc.com/teensy/td_download.html beschriebene Installationsverfahren, um fortzufahren.
Im folgenden Beispiel für einen Programmiercode kommen drei Hardware-Interrupts zum Einsatz, um jegliche Änderung (ansteigende und abfallende Kanten) der Hall-Sensor-Ausgänge zu überwachen. Bei einem Interrupt werden die verstrichene Zeit der Teensy 3.5 sowie zwei der drei Eingangspins gelesen. Die Sensorwerte werden verglichen, um die Drehrichtung zu bestimmen. Anschließend werden weitere Berechnungen durchgeführt, um die Impulszahl und die durchschnittlichen U/min zu ermitteln. Die zwischen Interrupts liegende Zeit wird berechnet, indem die aktuelle Zeit mit der gespeicherten Zeit vom vorherigen Interrupt verglichen wird.
Für den Seriendruck stehen in der „void loop“ des Programmcodes vier Werte zur Verfügung. Zum Deaktivieren bzw. Aktivieren der Seriendruckfunktion müssen Sie einzelne Codezeilen kommentieren bzw. auskommentieren. Laden Sie anschließend den Code auf die Teensy herunter und starten Sie den seriellen Monitor, um die Live-Daten anzuzeigen. Drehen Sie den BLDC-Motor, um am Druckmonitor zu beobachten, wie sich die Werte ändern.
Hinweis: Serielle Druckfunktionen verlangsamen den Mikrocontroller. Die I/O-Interrupts verursachen ein Stocken und Springen der angezeigten Werte, da – gemäß Definition – der serielle Druckprozess jedesmal unterbrochen wird, wenn sich der Status eines Eingangspins ändert. Stellen Sie bei Nichtverwendung der Anzeigefunktion sicher, dass alle seriellen Druckfunktionen im Code auskommentiert sind.
Kopieren/* BLDC Hall Sensor read and calculation program for Teensy 3.5 in the Arduino IDE (Ver.1). DigiKey*/
/***************************** Variables *********************************/
#define CW 1 // Assign a value to represent clock wise rotation
#define CCW -1 // Assign a value to represent counter-clock wise rotation
bool HSU_Val = digitalRead(2); // Set the U sensor value as boolean and read initial state
bool HSV_Val = digitalRead(3); // Set the V sensor value as boolean and read initial state
bool HSW_Val = digitalRead(4); // Set the W sensor value as boolean and read initial state
int direct = 1; // Integer variable to store BLDC rotation direction
int pulseCount; // Integer variable to store the pulse count
float startTime; // Float variable to store the start time of the current interrupt
float prevTime; // Float variable to store the start time of the previous interrupt
float pulseTimeW; // Float variable to store the elapsed time between interrupts for hall sensor W
float pulseTimeU; // Float variable to store the elapsed time between interrupts for hall sensor U
float pulseTimeV; // Float variable to store the elapsed time between interrupts for hall sensor V
float AvPulseTime; // Float variable to store the average elapsed time between all interrupts
float PPM; // Float variable to store calculated pulses per minute
float RPM; // Float variable to store calculated revolutions per minute
/***************************** Setup *********************************/
void setup()
{
// Set digital pins 2, 3 and 4 as inputs
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(4, INPUT);
// Set digital pins 2, 3 and 4 as interrupts that trigger on rising and falling edge changes. Call a function (i.e. HallSensorU) on change
attachInterrupt(digitalPinToInterrupt(2), HallSensorU, CHANGE);
attachInterrupt(digitalPinToInterrupt(3), HallSensorV, CHANGE);
attachInterrupt(digitalPinToInterrupt(4), HallSensorW, CHANGE);
// Initialize the print monitor and set baud rate to 9600
Serial.begin(9600);
}
/*************************** Main Loop ******************************/
void loop()
{
if ((millis() - prevTime) > 600) RPM = 0; // Zero out RPM variable if wheel is stopped
//Serial.print(HSU_Val); Serial.print(HSV_Val); Serial.println(HSW_Val); // Display Hall Sensor Values
//Serial.println(direct); // Display direction of rotation
//Serial.println(pulseCount); // Display the pulse count
Serial.println(RPM); // Display revolutions per minute
}
/************************ Interrupt Functions ***************************/
void HallSensorW()
{
startTime = millis(); // Set startTime to current microcontroller elapsed time value
HSW_Val = digitalRead(4); // Read the current W hall sensor value
HSV_Val = digitalRead(3); // Read the current V (or U) hall sensor value
direct = (HSW_Val == HSV_Val) ? CW : CCW; // Determine rotation direction (ternary if statement)
pulseCount = pulseCount + (1 * direct); // Add 1 to the pulse count
pulseTimeW = startTime - prevTime; // Calculate the current time between pulses
AvPulseTime = ((pulseTimeW + pulseTimeU + pulseTimeV)/3); // Calculate the average time time between pulses
PPM = (1000 / AvPulseTime) * 60; // Calculate the pulses per min (1000 millis in 1 second)
RPM = PPM / 90; // Calculate revs per minute based on 90 pulses per rev
prevTime = startTime; // Remember the start time for the next interrupt
}
void HallSensorV()
{
startTime = millis();
HSV_Val = digitalRead(3);
HSU_Val = digitalRead(2); // Read the current U (or W) hall sensor value
direct = (HSV_Val == HSU_Val) ? CW : CCW;
pulseCount = pulseCount + (1 * direct);
pulseTimeV = startTime - prevTime;
AvPulseTime = ((pulseTimeW + pulseTimeU + pulseTimeV)/3);
PPM = (1000 / AvPulseTime) * 60;
RPM = PPM / 90;
prevTime = startTime;
}
void HallSensorU()
{
startTime = millis();
HSU_Val = digitalRead(2);
HSW_Val = digitalRead(4); // Read the current W (or V) hall sensor value
direct = (HSU_Val == HSW_Val) ? CW : CCW;
pulseCount = pulseCount + (1 * direct);
pulseTimeU = startTime - prevTime;
AvPulseTime = ((pulseTimeW + pulseTimeU + pulseTimeV)/3);
PPM = (1000 / AvPulseTime) * 60;
RPM = PPM / 90;
prevTime = startTime;
}
Hinweis: Programmierer könnten versuchen, repetitiven Interrupt-Funktionscode in eine zusätzliche Funktion auszulagern, um das Programm zu vereinfachen. Das kann dazu führen, dass die zusätzliche Funktion unterbrochen wird und Werte zwischen den Berechnungen geändert werden, was wiederum Datenfehler zur Folge hat. Wie im Zusammenhang mit dem Verbinden des Boards und dem Code bereits erwähnt, hat die Reihenfolge des Sensoreingangs lediglich Auswirkungen auf die Ermittlung der Drehrichtung. Kommentieren Sie die mit der Variable „direct“ verbundene Zeile für den Seriendruck aus, um den Wert im Anzeigemonitor anzuzeigen. Vergewissern Sie sich, dass dieser Wert je nach Drehrichtung des Rads immer 1 bzw. -1 ist. Vertauschen Sie bei Abweichungen in der entsprechenden Interrupt-Funktion im ternären Code „CW“ und „CCW“, um den Ausgang zu korrigieren.
Zusammenfassung
Die BLDC-Hall-Sensoren sind jetzt als dreikanaliger Drehgeber mit geringer Auflösung konfiguriert, der exakte Daten für die Navigation und die Positionsmessung des Rads liefern kann, ohne ihre primäre Motorsteuerungsfunktion zu beeinträchtigen. Manche BLDC-Controller verwenden zur Ermittlung der Spulen- und Magnetposition ausschließlich die rückwirkende EMK, wodurch die Hall-Sensor-Ausgänge einzig und allein für die Navigation und die Positionsmessung zur Verfügung stehen. In beiden Fällen bieten die Sensoren dem Benutzer mehr als lediglich eine Motorsteuerung.
Zusätzliche Ressourcen:
Arduino IDE: http://www.arduino.cc/en/Main/Software
Teensyduino: https://www.pjrc.com/teensy/td_145/TeensyduinoInstall.exe
Have questions or comments? Continue the conversation on TechForum, Digi-Key's online community and technical resource.
Visit TechForum




