Utilizzare sensori Hall su motori BLDC come encoder di posizione - Parte 3

Utilizzare un microcontroller Teensy 3.5 per calcolare posizione, direzione e distanza

Questo articolo è un contributo all'interpretazione delle uscite logiche dei sensori Hall in relazione alla determinazione della posizione, della direzione e della velocità. Sebbene l'uscita possa servire per la commutazione dei motori BLDC, qui non tratteremo questo aspetto.

Vedere la Parte 1 e la Parte 2 di questo tutorial per i passaggi precedenti di questo progetto.

Panoramica

Quando le tre uscite di un sensore a effetto Hall in un motore BLDC sono collegate a un microcontroller, i segnali possono essere elaborati allo stesso modo di un encoder a tre canali. I dati possono essere visualizzati o utilizzati per determinare il numero di impulsi, la direzione di rotazione e il numero medio di giri/min. Viene calcolato il numero medio di giri/min in modo da creare una progressione graduale nei valori visualizzati.

Scheda di sviluppo PJRC Teensy 3.5

La scheda di sviluppo PJRC Teensy 3.5 di SparkFun (1568-1464-ND) dispone di un numero di interrupt digitali più che sufficiente per gestire i tre ingressi di segnale provenienti dai sensori Hall, ed è fornita con basette presaldate. La scheda Teensy 3.5 è abbastanza potente per eseguire molti compiti aggiuntivi grazie a un gran numero di canali I/O supplementari e può essere utilizzato per la registrazione dati grazie alla scheda SD incorporata.

Figura 1: La scheda di valutazione Teensy 3.5 di SparkFun Electronics. (Immagine per gentile concessione di SparkFun Electronics)

Montaggio sperimentale dell'uscita dei sensori e della scheda PJRC Teensy 3.5

Utilizzando un circuito sperimentale (438-1045-ND o simile), posizionare la scheda Teensy 3.5 con il connettore USB sulla destra, con i pin della basetta inseriti nella prima fila dei fori del circuito sperimentale sopra la partizione (Figura 2). In questo modo, si avrà abbastanza spazio per collegare le uscite dei sensori all'I/O della scheda Teensy.

Figura 2: Circuito sperimentale a cui sono stati collegati la scheda di sviluppo Teensy 3.5 e dei ponticelli. (Immagine per gentile concessione di DigiKey)

Utilizzare fili per ponticelli pieni (BKWK-3-ND) per realizzare tutti i collegamenti al circuito sperimentale. Collegare il conduttore positivo (+) di un alimentatore da 5 V, 1 A al rail di alimentazione positivo superiore o inferiore del circuito sperimentale, quindi collegare il conduttore negativo (-) dell'alimentatore al rail di alimentazione negativo superiore o inferiore. Collegare il conduttore positivo (rosso) e negativo (nero) del connettore dei sensori Hall rispettivamente al rail positivo e negativo del circuito sperimentale, quindi collegare i tre cavi dei sensori del connettore ai pin 2, 3 e 4 della scheda Teensy 3.5 in un ordine qualsiasi.

Le uscite dei sensori sono attive basse, il che significa che, quando attivate, le uscite vengono connesse al rail di alimentazione negativo. Quando un'uscita del sensore non è attivata, dev'essere portata al rail di alimentazione positivo per stabilire due stati logici definiti. Inserire nel circuito sperimentale tre resistori 4 ~°8 kΩ, che verranno utilizzati come pull-up per le uscite dei sensori (Figura 2).

Collegare la scheda Teensy 3.5 a un computer utilizzando un cavo USB micro B - A standard.

Software

La scheda Teensy 3.5 è compatibile con l'ambiente di sviluppo integrato (IDE) Arduino per la programmazione. I componenti aggiuntivi IDE e Teensyduino sono disponibili online. Per continuare, seguire le procedure di installazione al link https://www.pjrc.com/teensy/td_download.html.

Il codice di programmazione di esempio fornito di seguito utilizza tre interrupt hardware per monitorare qualsiasi cambiamento (fronti di salita e di discesa) delle uscite dei sensori Hall. Quando avviene un interrupt, vengono letti il contatore del tempo trascorso della scheda Teensy 3.5 e due dei tre pin di ingresso. I valori dei sensori vengono confrontati per determinare la direzione di rotazione, quindi vengono effettuati altri calcoli per determinare il numero di impulsi e i giri/min medi. Il tempo tra gli interrupt viene calcolato mettendo a confronto il valore di tempo attuale con quello dell'interrupt precedente.

Sulla stampa seriale all'interno del loop vuoto sono disponibili quattro valori. Trasformare eventuali linee di codice in commenti per disattivare le relative funzioni della stampa seriale, quindi scaricare il codice per la scheda Teensy e avviare il monitor seriale per visualizzare i dati in tempo reale. Azionare il motore BLDC per osservare il variare dei valori sul monitor della stampa.

Nota: le funzioni di stampa seriale rallentano il microcontroller. Gli interrupt di I/O causano l'arresto e il salto dei valori visualizzati, in quanto, per definizione, il processo di stampa seriale viene interrotto ogni volta che lo stato di un pin di ingresso cambia. Se non è utilizzata la funzione di visualizzazione, assicurarsi che tutte le funzioni di stampa seriale siano state trasformate in commenti, disattivandole.

Copy/* 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;
}

Nota: i programmatori potrebbero essere tentati di separare il codice funzione interrupt ripetitivo in funzioni aggiuntive per semplificare l'intero programma. Così facendo però le funzioni aggiuntive potrebbero essere interrotte e i cambiamenti dei valori tra un calcolo e l'altro potrebbero generare errori dei dati. Come già visto nei passaggi del montaggio sperimentale della scheda e nel codice, l'ordine dell'ingresso dei sensori influisce solo sulla determinazione della direzione di rotazione. Ripristinare la linea di codice della stampa seriale trasformata in commento collegata alla variabile "direct" per visualizzare il valore sul monitor. Controllare che il valore resti 1 o -1 a seconda della direzione in cui viene fatta girare la ruota. Se il valore si discosta da questi valori, scambiare "CW" e "CCW" all'interno del codice ternario nella funzione di interrupt corrispondente in modo da correggere l'uscita.

Riepilogo

I sensori Hall del motore BLDC ora sono configurati come un encoder a tre canali e a bassa capacità risolutiva in grado di fornire dati precisi per facilitare la navigazione e il rilevamento della posizione della ruota senza limitare la loro funzionalità primaria di controllo motori. Alcuni controller BLDC utilizzano solo la f.c.e.m. per determinare la posizione della bobina e del magnete, lasciando le uscite dei sensori Hall disponibili esclusivamente per il rilevamento della navigazione e della posizione. A ogni modo, i sensori possono fornire funzioni più utili in aggiunta al solo controllo di motori.

Altre risorse:

IDE Arduino: http://www.arduino.cc/en/Main/Software

Teensyduino: https://www.pjrc.com/teensy/td_145/TeensyduinoInstall.exe

Informazioni su questo autore

Image of Don Johanneck

Don Johanneck, Technical Content Developer presso DigiKey, lavora in azienda dal 2014. Di recente promosso alla sua attuale posizione, è responsabile delle descrizioni per i video e dei contenuti di prodotto. Don ha conseguito una laurea tecnico-scientifica in Electronics Technology & Automated Systems presso Northland Community & Technical College attraverso il programma di borse di studio DigiKey. Ama il modellismo radiocomandato, il restauro di auto d'epoca e il bricolage.

More posts by Don Johanneck
 TechForum

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

Visit TechForum