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

Über den Autor

Image of Don Johanneck

Don Johanneck, Technical Content Developer bei DigiKey, arbeitet seit 2014 für das Unternehmen. Seit dem Wechsel in seine aktuelle Position ist er für das Verfassen von Beschreibungen zu Videos und Produkten verantwortlich. Er hat seinen Abschluss als Associate of Applied Science im Bereich Elektronik und automatisierte Systeme vom Northland Community & Technical College im Rahmen des DigiKey-Stipendienprogramms erworben. Er genießt die Modellierung von Funksteuerungen, die Restaurierung von alten Maschinen und das Basteln.

More posts by Don Johanneck
 TechForum

Have questions or comments? Continue the conversation on TechForum, Digi-Key's online community and technical resource.

Visit TechForum