Pilotare motori Brushless con i microcontrollori RENESAS

Lo sviluppo di periferiche sempre più specifiche e complete a bordo dei microcontrollori  ha permesso l’integrazione sempre più spinta dei circuiti di controllo e la conseguente riduzione di spazio e potenza dissipata. Nell’articolo si illustrerà un caso tangibile di questa integrazione: il pilotaggio di un motore con la tecnica della modulazione della larghezza dell’impulso (pwm).

Il micro H8/3687 di Renesas è dotato di un PWM a 14-bit che sarà utilizzato per generare la forma d’onda necessaria a far ruotare un tipico motore brushless. La figura 1 mostra la configurazione circuitale che sarà impiegata per il pilotaggio.

Figura 1: configurazione circuitale che consente di utilizzare il chip H8/300H per pilotare un motore brushless.

Figura 1: configurazione circuitale che consente di utilizzare il chip H8/300H per pilotare un motore brushless.

E’ utilizzato l’interrupt esterno (IRQ1) per avviare il motore e variarne la velocità; in questo modo la latenza nella risposta del chip alla richiesta di variazione di velocità del motore sarà la minima possibile. Il  transistor for nirà al motore la corrente sufficiente al movimento, tramite opportuna modulazione della base ad opera dell’uscita del PWM. Le operazioni descritte permetteranno di effettuare una rotazione con un segnale di uscita il cui duty-cycle è impostabile al 50%, al 75% ed al 100%. Questo, ovviamente, è solo un esempio applicativo. Con la tecnica del PWM si potranno ottenere tutte le velocità del motore comprese tra 0 e la massima velocità prevista. La figura 2 riporta lo schema a blocchi dell’applicazione oggetto di quest’articolo.

Figura 2: schema a blocchi utilizzato per il controllo di un BLDC tramite un processore Renesas

Figura 2: schema a blocchi utilizzato per il controllo di un BLDC tramite un processore Renesas

Descrizione delle  funzioni

Per l’applicazione descritta sarà utilizzato il modello di motore brushless Mabuchi FA-130, di cui si riporta un’immagine in figura 3.

Figura 3: immagine del motore Mabuchi FA-130.

Figura 3: immagine del motore Mabuchi FA-130.

Le caratteristiche tecniche di questo motore sono riassunte nella tabella 1.

TABELLA 1

TABELLA 1: caratteristiche tecniche del motore

In figura 4 si riporta una schema a blocchi dettagliato, che consentirà di comprendere al meglio il funzionamento  della periferica PWM. Tutto il sistema utilizza il master clock (Φ = 16MHz) per la sincronizzazione delle operazioni.

Figura 4: schema a blocchi della periferica PWM.

Figura 4: schema a blocchi della periferica PWM.

Tale clock deve essere opportunamente condizionato, tramite il blocco indicato con Prescale S(PSS), per ottenere il giusto clock. Si può scegliere tra due differenti valori: Φ/2 o Φ/4. I registri PWM data L e U (PWDRU e PWDRL) sono utilizzati per gestire il funzionamento del PWM che è a 14-bit. PWDRU contiene i  6 bit più significativi, mentre l’altro gli otto bit meno significativi. Ogni volta che tali registri vengono scritti, il loro valore è automaticamente utilizzato dal modulo PWM waveform generation per generare la corrispondente forma d’onda quadra con il duty-cycle desiderato. Le operazioni di scrittura di tali registri devono sempre essere eseguite a partire dal PWDRL e poi PWDRU. Il registro PWM control (PWCR) è costituito da 8 bit e serve per selezionare il clock di ingresso. Poiché l’applicazione descritta richiede anche l’uso dell’interrupt esterno 1, allora sarà necessario far riferimento al registro Port mode (PMR1), che serve per selezionare la funzione di ciascun pin della porta 1. Per effettuare tale operazione è necessario impostare ad 1 il bit 5 di tale registro. Inoltre, poiché il  pin del PWM si trova sempre sulla porta 1, bisogna impostarlo come uscita (bit 2 del registro PMR1).

Descrizione delle  operazioni

Il fatto che il motore in esame è di tipo DC oltre che un brushless, comporta che esso possa essere pilotato in continua (tensione tipica 1.5V). In questa condizione esso produrrà una velocità fissa che è anche la massima; secondo i dati in tabella 1 tale valore corrisponde a 5900 giri/minuto (con un carico tipico). Per variare dinamicamente la sua velocità è necessario pilotare la base del transistor che for nisce la corrente con un onda quadra il  cui duty-cycle è variabile. Il duty-cycle (definito come il tempo che l’onda rimane al valore alto rapportato al periodo totale) è direttamente proporzionale alla velocità del motore. Quindi se si vuole impostare una velocità di 5900/2 = 2950 giri/minuto sarà sufficiente generare un onda quadra con dutycycle 50%. Portandolo al 75% si otterrà, ovviamente, una velocità di 4425 giri/minuto. Infine, la massima velocità sarà ottenuta in corrispondenza di un duty-cycle pari al 100%, ossia una continua.

Diagramma di flusso del controllo di velocità

Nell’applicazione descritta si implementa una semplice macchina a stati, in cui la pressione dell’unico ingresso IRQ1 con sentirà di modificare la velocità del motore (figura 5). Gli stati posso essere così riassunti:

1- Motore fermo (condizione iniziale).
2- Accelerazione. Motore in movimento con velocità al 50% (prima pressione di IRQ1).
3- Accelerazione. Motore in movimento con velocità al 75% (seconda pressione di IRQ1).
4- Accelerazione. Motore in movimento con velocità al 100% (terza pressione di IRQ1).
5- Decelerazione. Motore in movimento con velocità al 75% (quarta pressione di IRQ1).
6- Decelerazione. Motore in movimento con velocità al 50% (quinta pressione di IRQ1).
7- Decelerazione. Ritorno alla condizione iniziale (motore fermo).

 

Figura 8: la velocità di un motore brushless DC si può variare agento sulla quantità media di corrente che si fa scorrere nel transistor che pilota il motore. Tale modulazione è possibile con la periferica PWM.

Figura 5: la velocità di un motore brushless DC si può variare agento sulla quantità media di corrente che si fa scorrere nel transistor che pilota il motore. Tale modulazione è possibile con la periferica PWM.

Descrizione del firmware

L’intero firmware per la realizzazione dei compiti descritti è costituito da due soli moduli:

1 - Main, in cui sono impostate le varibili globali, configurato il  PWM e abilitato l’interrupt IRQ1. Il relativo  diagramma di flusso è riportato in figura 10.

Figura 10: diagramma di flusso del modulo main.

Figura 10: diagramma di flusso del modulo main.

2 - IRQ1 Handler, in cui si gestiscono le variazioni di velocità del motore, tramite la modifica dei registri PWDRL e PWDRU. Il relativo diagramma di flusso è riportato in figura 11. Il codice completo, scritto in C, è riportato nel listato 1. La funzione irq1int gestisce gli stati del microcontrollore tramite la variabile locale next-mode. Tale variabile può assumere valori da 0 a 5 che corrispondono agli stati riportati nel diagramma di flusso in figura 9.

Figura 9: la pressione di un pulsante esterno agisce sull’interrupt IRQ1 e provoca la variazione della macchina a stati implementata, per modificare la velocità del motore a step di 25% rispetto alla massima velocità di rotazione.

Figura 9: la pressione di un pulsante esterno agisce sull’interrupt IRQ1 e provoca la variazione della macchina a stati implementata, per modificare la velocità del motore a step di 25% rispetto alla massima velocità di rotazione.

Impostando a 0 entrambi i registri PWM data il motore resta fermo, poiché il valore della tensione di uscita sarà sempre zero e quindi il transistor rimarrà interdetto, impedendo il passaggio di corrente nel motore. Quando si passa nello stato 1 oppure 5 (valore della variabile nextmode) si genera una velocità al 50%. Per sapere quali valori scrivere nei registri PWM data per ottenere una qualsiasi velocità, bisogna considerare che i  bit a disposizione sono 14 e quindi il massimo valore (corrispondente alla massima velocità di rotazione) che si potrà inserire è 214 - 1 = 16383, quindi 0x3FFF. Alla luce di quando detto, se si indica con x il numero da scrivere nel registro PWM data e con v la velocità desiderata (in percentuale rispetto alla massima velocità), si avrà:

x = 16384  v

Convertendo  il valore x in esadecimale e prendendo le relative cifre a coppie di due si otterrà il valore da scrivere nei registri. Ad esempio, se si volesse una velocità al 75% si dovrebbe scrivere:

x = 16384 x 0.75 = 12288 = 0x3000

e quindi:

PWDRL1 = 0x00
PWDRU1 = 0x30

1. /************************************************/
2. #include <machine.h>
3. struct BIT {
4. unsigned char b7:1; /* bit7 */
5. unsigned char b6:1; /* bit6 */
6. unsigned char b5:1; /* bit5 */
7. unsigned char b4:1; /* bit4 */
8. unsigned char b3:1; /* bit3 */
9. unsigned char b2:1; /* bit2 */
10. unsigned char b1:1; /* bit1 */
11. unsigned char b0:1; /* bit0 */
12. };
13. #define PWCR1 *(volatile unsigned char *)0xFFD0
/* PWM Control Register */
14. #define PWDRU1 *(volatile unsigned char *)0xFFD1
/* PWM Data Register U */
15. #define PWDRL1 *(volatile unsigned char *)0xFFD2
/* PWM Data Register L */
16. #define PMR9_BIT *(struct BIT *)0xFFEC) /* Port
Mode Register 9 */
17. #define PWM1 PMR9_BIT.b0 /* P90/PWM1 pin function
switches */
18. #define IEGR1_BIT (*(struct BIT *)0xFFF2) /* Interrupt
Edge Select Register 1 */
19. #define IEG1 IEGR1_BIT.b1 /* IEG1 Edge Select */
20. #define IENR1_BIT (*(struct BIT *)0xFFF3) /* Interrupt
Enable Register 1 */
21. #define IEN1 IENR1_BIT.b1 /* IEN1 Interrupt Enable
*/
22. #define IRR1_BIT (*(struct BIT *)0xFFF6) /* Interrupt
Request Register 1*/
23. #define IRRI1 IRR1_BIT.b1 /* IRRI1 Interrupt Request
Register */
24. #define PMRB_BIT (*(struct BIT *)0xFFEE) /* Port
mode register B */
25. #define IRQ1 PMRB_BIT.b3 /* PB3/AN3/IRQ1 pin
function switch */
26. #pragma interrupt (irq1int)
27. /**************************************************/
28. /* Function define */
29. /**************************************************/
30. extern void INIT( void ); /* SP Set */
31. void main( void );
32. void irq1int( void );
33. /**************************************************/
34. /* RAM define */
35. /**************************************************/
36. unsigned int nextmode; /* Motor mode counter */
37. /**************************************************/
38. /* Vector Address */
39. /**************************************************/
40. #pragma section V1 /* VECTOR SECTION SET */
41. void (*const VEC_TBL1[])(void) = { /* 0x00 - 0x0f */
42. INIT /* 00 Reset */
43. };
44. #pragma section V2 /* VECTOR SECTION SET */
45. void (*const VEC_TBL2[])(void) = {
46. irq1int /* 0A IRQ1 Interrupt */
47. };
48. #pragma section /* P */
49. /***********************************************/
50. /* Main Program */
51. /************************************************/
52. void main( void ){
53. unsigned char pwmu_data,pwml_data;
54. unsigned char tmp;
55. set_imask_ccr(1);/* Interrupt Disable */
56. PWDRL1 = 0x00; /* Set PWM Output Pulse Data Higher */
57. PWDRU1 = 0x00; /* Set PWM Output Pulse Data Lower */
58. PWM1 = 1; /* Pin function Select PWM1 */
59. PWCR1 = 0xFC; /* Initialize PWM Input Clock */
60. IEG1 = 1; /* Rising edge of IRQ1 */
61. IRRI1 = 0; /* Initialize IRRI1 */
62. IEN1 = 1; /* IRQ1 Interrupt Request Enable */
63. IRQ1 = 1; /* Pin function Select IRQ1 */
64. nextmode = 0; /* Motor mode counter Clear */
65. set_imask_ccr(0); /* Interrupt Disable */
66. while(1);
67. }
68. /**************************************************/
69. /* IRQ1 Interrupt */
70. /**************************************************/
71. void irq1int( void ){
72. unsigned char tmp;
73. IRRI1 = 0; /* Clear IRRI0 */
74. if(nextmode < 5) /* Motor Mode count over 5? */
75. nextmode++; /* Next mode */
76. else
77. nextmode = 0; /* Mode Clear */
78. switch(nextmode){ /* What Motor Mode? */
79. case 0:
80. PWDRL1 = 0x00; /* Set PWDRU1,PWDRL1 */
81. PWDRU1 = 0x00; /* DC Motor Stop */
82. break;
83. case 1:
84. PWDRL1 = 0x00; /* Set PWDRU1,PWDRL1 */
85. PWDRU1 = 0x20; /* DC Motor 50% Power revolution */
86. break;
87. case 5:
88. PWDRL1 = 0x00; /* Set PWDRU1,PWDRL1 */
89. PWDRU1 = 0x20; /* DC Motor 50% Power revolution */
90. break;
91. case 2:
92. PWDRL1 = 0x00; /* Set PWDRU1,PWDRL1 */
93. PWDRU1 = 0x30; /* DC Motor 75% Power revolution */
94. break;
95. case 4:
96. PWDRL1 = 0x00; /* Set PWDRU1,PWDRL1 */
97. PWDRU1 = 0x30; /* DC Motor 75% Power revolution */
98. break;
99. case 3:
100. PWDRL1 = 0xFF; /* Set PWDRU1,PWDRL1 */
101. PWDRU1 = 0x3F; /* DC Motor Full Power revolution */
102. break;
103. }
104. }
Listato 1

Conclusioni

Quello proposto è solo un esempio didattico di utilizzo del PWM per il controllo di motori brushless. L’applicazione nel caso pratico potrebbe risultare più complessa e completa, ma ciò che si è cercato di fornire al lettore è il principio di funzionamento e di utilizzo di questo semplice, ma al tempo stesso efficace strumento per il controllo di motori e non solo.

 

Una risposta

  1. Giovanni Carrera Giovanni Carrera 29 gennaio 2018

Scrivi un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *