Generación de señal PWM multifase en TMS320F28027

Érase una vez en una lejana galaxia lejana Escribí un breve artículo sobre el controlador Piccolo especializado de Texas Instruments, que está diseñado para controlar convertidores de potencia y unidades eléctricas. Estos controladores son herramientas de desarrollo muy poderosas en muchas tareas y quería escribir algo más sobre ellos ... simple y útil.


Recientemente, me intrigó desarrollar un controlador para el control del motor y, en consecuencia, se formó un tema para el artículo: hoy hablaré sobre el proceso de formación de un PWM trifásico para el control del motor, así como explicaré las diferencias beneficiosas entre TMS320F28 y otros controladores como STM32F334, STM32G484, XMC4200 y otros.


Como soporte, usaré el controlador en desarrollo, por desgracia, no puedo hablar sobre la parte de hierro en detalle. Sin embargo, si digo que el controlador se basa en el paquete TMS320F28027 + DRV8353RSRGZT, entonces puede ver los datos del controlador y ver el concepto general de circuitos + hay una depuración en esta piedra y el diseño de referencia está abierto.


Controlador BLDC


En principio, en el mismo tipo de circuito es posible controlar motores BLDC que "consumen" niveles de voltaje y trifásicos ordinarios, que ya desean una salida sinusoidal. Mostraré ambas opciones, como El camino hacia el seno reside en la formación de niveles de voltaje.


Oscilograma número 1


Un poco sobre hierro


La parte de potencia del controlador ideológicamente consiste en 3 convertidores de medio puente, probablemente todos los chastotniks y controladores para controlar los motores BLDC en todos los helicópteros están hechos de manera similar:


Puente trifásico


Una diferencia: no tengo un rectificador de entrada, porque El controlador está alimentado inicialmente por un voltaje constante. La fuente de alimentación en mi caso es un conjunto de baterías de iones de litio en forma de celdas 18650. El controlador DRV8353RSRGZT usado puede controlar solo 3 medios puentes de potencia, también en la versión usada de la piedra también hay amplificadores operacionales incorporados para trabajar con derivaciones como sensores de corriente, incorporados dc / dc, que puede digerir hasta 70 ... 80V y todo esto está configurado de manera muy flexible a través de SPI. Por ejemplo, es muy conveniente poder ajustar la corriente de pulso máxima del control del transistor.


También en esta serie hay controladores con un conjunto diferente de funciones, por ejemplo, hay con control analógico, no SPI o sin CC / CC incorporado y sin amplificador operacional. Por el precio no son muy diferentes y tomé el más "audaz" como probablemente ya entendiste. Todo esto se ve muy hermoso, pero me acerqué frívolamente al diseño del enlace del controlador y obtuve 2 problemas importantes. De hecho, solo hay un problema: este es un fuerte sobrecalentamiento:


Cámara termográfica


Pero este problema fue causado por 2 razones. En realidad, la esencia del problema es el sobrecalentamiento del propio controlador. En el termograma, el controlador se carga con una corriente de 5A (para él está casi inactivo) y nada más que el controlador y el MK se calientan un poco. Los transistores ni siquiera son visibles, tienen una temperatura de PCB, a 5 A hay pocas pérdidas de calor.


  • Error no 1
    Un amigo mío me pidió que, sinceramente, hubiera pensado en esto como un último recurso: dc / dc está integrado en el controlador, que recibe una entrada de 15 ... 50V y proporciona 3.3V para alimentar el MK, la lógica, los comparadores y los amplificadores operacionales. Parece que mis proyectos tienen microcircuitos LM5008 y LM5017 en forma de microcircuitos separados y reduje tranquilamente 60V a 3.3V sin un calentamiento notable a una corriente de 100-150 mA, pero todo resultó ser más complicado: la eficiencia general del convertidor resultó ser de aproximadamente 65-70% a una corriente 300 mA! El hecho es que el convertidor en sí puede dar 3.3V, pero la eficiencia será escasa, es óptimo configurar el voltaje de salida 10-12-15V. Cuando la salida era de 12V 100 mA, mi controlador dejó de calentarse prácticamente y la eficiencia alcanzó un agradable 88%. La solución al problema es bajar la entrada de 15 ... 50V a 12V con el dc / dc incorporado, y luego bajarlo de 12V a 3.3V con un dc / dc externo ya barato.


  • Error no 2
    El segundo error es más obvio y lo primero que pequé en él como pude. El hecho es que para los chips en el paquete QFN, el calor principal se elimina a través del "vientre", por lo general se asienta en el GND y, a través de varias vías, se aferra al suelo y todo el calor va allí con calma. Inicialmente, no tomé en cuenta la escasa eficiencia de la CC / CC incorporada con una gran diferencia de voltaje, por lo que no me molestó que la caída térmica ("vientre") se aferrara a un polígono GND continuo en la capa interna, en la capa externa no tenía cobre debajo del vientre como un polígono GND Como resultado, resultó que ~ 0.5 W de calor se libera en el chip, y se disipa en la capa interna de la placa, es decir, la eficiencia es muy pobre. La solución al problema es que necesita hacer un terreno de prueba de tierra en la capa externa (capa inferior) y no hacer esto:

Placa de circuito


Como resultado, en la segunda revisión del hierro, se corrigieron estos errores: se agregó un convertidor de CC / CC externo de 12-3.3V y el polígono GND se rellenó adicionalmente en la capa inferior y se colocó la almohadilla de chip en él + se conservó el polígono de tierra sólido interno. Después de tales mejoras, la temperatura en funcionamiento continuo disminuyó de +82 a +43 o C:


Termograma


Como puede ver, debido a la reducción de las pérdidas, la temperatura ha disminuido significativamente en las mismas condiciones, así como el calor ahora se distribuye de manera más uniforme en el área del tablero y no sobrecalienta ni el controlador ni el microcontrolador. En principio, todo era hierro, no pasó nada más interesante y funcionó de manera estable. Como resultado, pueden recomendar el uso del controlador DRV8353 .


Implementación de un cambio de fase de hardware de 120 o


Una característica de la red trifásica es que la corriente en las fases no es síncrona, sino que se desplaza 120 o en relación con la vecina. ¿Qué es este cambio de fase de 120 o en general? En términos simples, este es un cambio del punto de inicio de la generación en 1/3 del período. Desde el punto de vista matemático, el período de señal es , lo que significa que la segunda señal debe moverse 2π / 3, y la tercera 4π / 3. Desde un punto de vista electrónico, el período se establece por el período de cuenta regresiva de nuestro temporizador. Por ejemplo, cuando se registra a 60 MHz, queremos obtener un PWM con una frecuencia de 50 kHz, lo que significa que el temporizador será de 0 a 1200 (60 000 000 Hz / 50 000 Hz = 1200). Ahora, para obtener 3 fases con un desplazamiento de 120 o, no necesitamos tocar la primera fase, agregar +400 al valor actual para la segunda fase, agregar +800 a la fase actual.


Si usamos microcontroladores en el núcleo de la corteza, entonces podemos implementar el cambio ya sea escribiendo una fórmula matemática o usando la sincronización de eventos. Siempre fue sorprendente para mí por qué ST, NXP y otros no solo registraron dónde se escribiría el valor del cambio. Afortunadamente, TI hizo esto en su TMS320F28xxx, para configurar el cambio, ¡solo escriba un registro! No voy a decirte por qué la solución de software no es óptima, solo diré que considera las fórmulas MK no muy rápidamente. El pro con sincronización de eventos ya es más adecuado y en stm haría exactamente eso, pero esta opción no permite cambiar el valor de fase sobre la marcha, es decir, para algún puente de fase desplazada nuevamente solo queda la versión del software. ¿Es la ventaja de la capacidad de controlar el hardware de fase? Depende de usted decidir, mi tarea es decirle que es posible. Para mí, esta es una ventaja obvia cuando hablamos de controlar un variador eléctrico o inversores de voltaje con una salida trifásica.


Ahora configuremos la generación de señales PWM en forma de 3 pares complementarios con tiempo muerto y cambio de fase. Hasta ahora sin un seno. Usaré los siguientes pares: EPWM1A + EPWM1B, EPWM2A + EPWM2B y EPWM4A + EPWM4B. Estas son las señales que van del microcontrolador al controlador.


  • Paso 1
    Es necesario configurar el multiplexor GPIO con la ayuda del registro GPAMUX para trabajar con PWM y apagar los pull-ups de la salida a la fuente de alimentación, de modo que en el momento del encendido no haya log.1 en todas las patas y las teclas no se abran. La protección actual ciertamente ahorrará, pero es mejor no hacerlo. También vale la pena recordar que para acceder a los registros de configuración, debe obtenerlo con el comando EALLOW y luego volver a activar la protección de sobrescritura con el comando EDIS .

void InitGPIOforPWM (void) { EALLOW; GpioCtrlRegs.GPAPUD.bit.GPIO0 = 1; // Disable pull-up on GPIO0 (EPWM1A) GpioCtrlRegs.GPAPUD.bit.GPIO1 = 1; // Disable pull-up on GPIO1 (EPWM1B) GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 1; // Configure GPIO0 as EPWM1A GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 1; // Configure GPIO1 as EPWM1B GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1; // Disable pull-up on GPIO2 (EPWM2A) GpioCtrlRegs.GPAPUD.bit.GPIO3 = 1; // Disable pull-up on GPIO3 (EPWM2B) GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1; // Configure GPIO2 as EPWM2A GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1; // Configure GPIO3 as EPWM2B GpioCtrlRegs.GPAPUD.bit.GPIO6 = 1; // Disable pull-up on GPIO6 (EPWM4A) GpioCtrlRegs.GPAPUD.bit.GPIO7 = 1; // Disable pull-up on GPIO7 (EPWM4B) GpioCtrlRegs.GPAMUX1.bit.GPIO6 = 1; // Configure GPIO6 as EPWM4A GpioCtrlRegs.GPAMUX1.bit.GPIO7 = 1; // Configure GPIO7 as EPWM4B EDIS; } 

  • Paso 2
    Configure la generación de señal PWM. Es necesario obtener una frecuencia de 50 kHz y un desplazamiento de fase de 120 o . En este caso, utilizo el PWM habitual, porque en este controlador también hay HRPWM, es importante recordar esto. El módulo PWM está sincronizado a la frecuencia central, es decir, 60 MHz, mostré cómo configurar la frecuencia PLL en el primer artículo sobre TMS320, no lo repetiré, pero al final del artículo habrá un archivo con el código y será posible mirar allí.

  void InitPWM (void) { // EPWM Module 1 config EPwm1Regs.TBPRD = 600; // Set priod EPwm1Regs.TBPHS.half.TBPHS = 0; // Set phase EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Symmetrical mode EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Master enable EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // Sync down-stream module EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; EPwm1Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; EPwm1Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; // enable dead-time module EPwm1Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; // Active Hi complementary EPwm1Regs.DBFED = 20; // dead-time on 20 tick EPwm1Regs.DBRED = 20; // dead-time off 20 tick // EPWM Module 2 config EPwm2Regs.TBPRD = 600; EPwm2Regs.TBPHS.half.TBPHS = 400; // Set phase = 400/1200 * 360 = 120 deg EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; EPwm2Regs.TBCTL.bit.PHSEN = TB_ENABLE; // Slave enable EPwm2Regs.TBCTL.bit.PHSDIR = TB_DOWN; // Count DOWN on sync (=120 deg) EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // sync flow-through EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; EPwm2Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; EPwm2Regs.AQCTLA.bit.CAU = AQ_SET; EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR; EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; EPwm2Regs.DBFED = 20; EPwm2Regs.DBRED = 20; // EPWM Module 4 config EPwm4Regs.TBPRD = 600; EPwm4Regs.TBPHS.half.TBPHS = 400; EPwm4Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; EPwm4Regs.TBCTL.bit.PHSEN = TB_ENABLE; EPwm4Regs.TBCTL.bit.PHSDIR = TB_UP; EPwm4Regs.TBCTL.bit.PRDLD = TB_SHADOW; EPwm4Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN; EPwm4Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm4Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW; EPwm4Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; EPwm4Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO; EPwm4Regs.AQCTLA.bit.CAU = AQ_SET; EPwm4Regs.AQCTLA.bit.CAD = AQ_CLEAR; EPwm4Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE; EPwm4Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC; EPwm4Regs.DBFED = 20; EPwm4Regs.DBRED = 20; } 

Ahora, un poco más de detalle ... en el registro TBPRD , escriba el período, o mejor dicho, "período / 2", porque el temporizador se cuenta en ambas direcciones, resulta que el período 600 corresponde a la frecuencia de la señal PWM de salida de 50 kHz en el modo de par complementario. En el registro TBPHS escribimos el valor de fase por el cual necesitamos cambiar, en este caso 400 de 600, que corresponde a 2π / 3. Vale la pena señalar que no estamos moviendo la primera fase, por lo que para él el turno es 0, para la segunda fase el turno es 400, respectivamente, pero para la tercera fase parecería lógico escribir 800, pero 800 de 600 de alguna manera en realidad no ... por lo tanto, escriben el cambio no en relación con la primera fase, sino en relación con la anterior, es decir, la segunda. Como resultado, obtenemos que en la tercera fase escribimos 400 y esto corresponde a 2π / 3 entre las fases 2 y 3, y dado que la segunda ya está desplazada, entonces entre las fases 1 y 3 habrá "2π / 3 + 2π / 3 = 4π / 3 "y desde el punto de vista de la electrónica, todo parece lógico.


Para que las fases comprendan quién se está moviendo en relación con quién, se necesita un jefe, por lo que EPWM1 ​​se establece utilizando el bit PHSEN en modo maestro y EPWM2 y EPWM4, respectivamente, como esclavos. Usando los bits SYNCOSEL , también se establece el "punto" de sincronización , es decir, desde dónde leer el cambio. EPWM1 ​​está sincronizado con el inicio del temporizador, es decir, con período cero, y EPWM2 y EPWM4 ya están sincronizados con respecto al borde de la señal del canal anterior: el canal anterior para EPWM2 es EPWM1, y para EPWM4 es EPWM2.


Ahora queda activar pares complementarios y establecer la duración del tiempo muerto. Usando los bits POLSEL , establecemos un PWM no inverso, es decir, al alcanzar el valor establecido del comparador (referencia), se genera un registro en la salida. 1. En OUT_MODE establecemos la generación de tiempo muerto tanto en el borde como en la caída de la señal. En consecuencia, en los registros DBFED y DBRED escriben la duración del tiempo muerto en ticks.


  • Paso 3
    Ahora queda por escribir el valor del factor de trabajo en el registro CMPA correspondiente a cada canal y puede observar el resultado.

  EPwm1Regs.CMPA.half.CMPA = 300; // duty for output EPWM1A EPwm2Regs.CMPA.half.CMPA = 300; // duty for output EPWM2A EPwm4Regs.CMPA.half.CMPA = 300; // duty for output EPWM4A 

PWM trifásico


Voila! Las sondas de osciloscopio están conectadas a la salida del controlador. El canal amarillo es nuestro EPWM1, es decir, el maestro. El canal azul es EPWM2 y se desplaza 2π / 3 (o 400 muestras) en relación con el canal amarillo, y el canal verde se desplaza otras 400 muestras. Así obtenemos 3 fases, donde cada fase se desplaza por 120 o .


Ahora transfiramos las sondas de osciloscopio desde la salida del puente de alimentación a las señales de control que salen del microcontrolador y verifiquemos el tiempo muerto dentro del par complementario:


Oscilograma número 2


Como puede ver, el tiempo muerto establecido corresponde al real. La duración de una muestra es 1 / 60,000,000 Hz = 16.6 ns y obtenemos 20 muestras, lo que equivale al tiempo muerto 20.6 16 ns = 332 ns, * que es aproximadamente lo que se observa en el oscilograma.


En realidad, donde esto puede ser útil, en la forma en que está ahora. La opción más obvia son los convertidores de CC / CC multifásicos, para aquellos interesados ​​en googlear el convertidor de CC / CC intercalado . Esta es una solución técnica extremadamente interesante que puede reducir significativamente el tamaño de las inductancias de potencia, reducir la capacitancia de salida de los condensadores y también aumentar la eficiencia. En un TMS320F28027 simple, puede implementar un convertidor de 4 fases y todo esto se implementará de manera muy simple en el código y solo en el hardware.


Generamos una tensión alterna trifásica.


En muchos problemas, no será suficiente obtener valores discretos de 0 o VCC en la salida; se necesita una onda sinusoidal. Tengo un artículo que habla sobre la formación de un voltaje alterno monofásico y el método "tabular" se usa allí, es decir, los valores para la onda sinusoidal se calcularon inicialmente. En principio, esto también se puede hacer para una fase trifásica, pero quiero mostrar una opción alternativa, a saber, el cálculo del valor del derecho en tiempo real o sobre la marcha.


Hay una característica La frecuencia PWM en este caso también es de 50 kHz y el cambio de fase se establece entre los períodos de esta señal. En consecuencia, cuando modulamos una sinusoide con una frecuencia de 50 Hz, el cambio de fase del hardware se "perderá", todavía estará presente entre los PWM, pero no dentro de la sinusoide, por lo que deberá realizarse un software. La trigonometría es algo pesado para TMS320F28027, pero no está muy ocupado conmigo, así que déjelo contar. Si tiene una tarea que requiere muchos cálculos, entonces necesita un controlador con TMU y FPU, por ejemplo, TMS320F280049, que puede convertir las matemáticas mucho más rápido.


Para cargar los valores de servicio en el PWM, necesitamos un temporizador, cuyo período establecerá la frecuencia de muestreo. Necesito un período de 20 ms (1 / 50Hz = 20 ms) y tomaré el número de pasos en una sinusoide, digamos 20, como resultado, se debe generar una interrupción con una frecuencia de 0.02 s / 20 = 0.001 ms = 1 kHz y en esta interrupción escribiré el valor en el PWM . Para simplificar, tomaré un temporizador CPU0 normal y lo configuraré:


 void InitTimer0ForGenerator (void) { EALLOW; PieVectTable.TINT0 = &cpu_timer0_isr; EDIS; InitCpuTimers(); ConfigCpuTimer(&CpuTimer0, 60, 1000); CpuTimer0Regs.TCR.bit.TIE = 1; CpuTimer0Regs.TCR.bit.TSS = 0; IER |= M_INT1; PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // Enable TINT0 in the PIE: Group 1 interrupt 7 EINT; // Enable Global interrupt INTM ERTM; // Enable Global real-time interrupt DBGM } __interrupt void cpu_timer0_isr (void) { CpuTimer0.InterruptCount++; /* *   -  . ... */ PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge this interrupt to receive more interrupts from group 1 } 

Las funciones InitCpuTimers y ConfigCpuTimer son estándar, todos los ajustes están en ellas, solo necesitamos transferir la frecuencia central (60 MHz) y el período de conteo en microsegundos (1000 μs = 1 ms), que es equivalente a 1 kHz, y lo necesitábamos. Entonces, ¿dónde en la función de configuración habilitamos las interrupciones y pasamos la dirección del controlador de nuestra interrupción, donde todo sucederá?


Ahora es necesario "inventar" la fórmula sinusoidal de nuevo, para esto necesita conocimiento de trigonometría escolar y eso es todo. Y entonces ... tenemos una función y = sin (x) tracemos esta función:


y = sin (x)


Como puede ver en el gráfico, la amplitud de y varía de -1 a 1, pero queremos de 0 a 1, porque con una amplitud mínima tenemos 0V, y con un máximo (equivalente a 1) tenemos + VCC. Para "dibujar" -1 ... + 1 necesitamos nutrición bipolar, pero no lo es. Necesita cambiar el gráfico en una dirección positiva. Si lo levantamos, pasará de 0 a +2, y solo podremos subir a +1. ¡Entonces necesitas dividir por 2 y solo algo! Comencemos simplemente dividiendo y trazando para y = (sin (x) / 2):


y = (sin (x) / 2)


Si! Ahora el gráfico tiene un rango de -0.5 a +0.5, es decir, la amplitud es 1. Ya es mejor, pero aún no hemos eliminado los valores negativos, así que simplemente cambiemos el gráfico a 0.5, para esto solo necesitamos agregar este valor al resultado y obtener la fórmula y = 0.5 + (sin (x) / 2) y trace el gráfico para esta función:


y = 0.5 + (sin (x) / 2)


Ahora todo se ha vuelto absolutamente perfecto: la sinusoide tiene una amplitud de 0 a 1, los valores negativos están ausentes. La fórmula y = 0.5 + (sin (x) / 2) describe la primera fase, ahora es necesario agregar un cambio de fase para obtener las fases 2 y 3. Para hacer esto, reste 2π / 3 y 4π / 3 de x, respectivamente, y obtenga las fórmulas para el resto fases y = 0.5 + (sin (x-2π / 3) / 2) e y = 0.5 + (sin (x-4π / 3) / 2). Construimos 3 gráficos y vemos si parece la verdad:


3 fases


No esta mal! La imagen es similar a lo que generalmente se pinta en los libros de texto de ingeniería eléctrica cuando hablan de una red trifásica o motores asíncronos. Por cierto, 2.0943 es 2π / 3, y 4.1866 es 4π / 3, respectivamente, solo los conté de inmediato y aparecen en mi código. Total tenemos 3 ecuaciones:


  • Fase A - y = 0.5 + (sin (x) / 2)
  • Fase B - y = 0.5 + (sin (x-2π / 3) / 2)
  • Fase C - y = 0.5 + (sin (x-4π / 3) / 2)

Por parte de las matemáticas, todo parece ser simple y claro, pero ahora debe adaptarse a las realidades de los microcontroladores. Nuestra onda sinusoidal no es analógica, pero tiene "pasos", es decir, es discreta, porque en mi caso solo podemos establecer voltaje o 0V o + 15V (VCC). Anteriormente, escribí que tendría 20 pasos, por lo que durante 1 período tendré 20 cálculos.


Primero, decidamos qué sustituir por x . El período de nuestra sinusoide es , lo que significa que el paso de muestreo será 2π / 20 . En consecuencia, la sinusoide constará de 20 puntos, como si estuviéramos construyendo un gráfico sobre los puntos, y aproximándolos entre ellos. Como resultado, el valor en el primer paso será sin (2π * (1/20), en el segundo paso sin (2π * (2/20)), en el tercer paso * sin (2π (3/20)) y así sucesivamente, cuando Si llega a 20/20 , esto significará el final del período y será necesario comenzar a contar nuevamente. Según los datos recibidos, corrijamos las fórmulas:


  • Fase A - y = 0.5 + (sin (2π * (n / N)) / 2)
  • Fase B - y = 0.5 + (sin (2π * (n / N) -2π / 3) / 2)
  • Fase C - y = 0.5 + (sin (2π * (n / N) -4π / 3) / 2)

Ahora, ahora consideramos el valor del seno en cada punto específico del gráfico. En consecuencia, n es el paso actual, N es el paso total (20). Después de estas fórmulas, obtenemos un valor de 0 a 1, pero en realidad no estamos operando con una amplitud abstracta. La amplitud en nuestro caso depende del ciclo de trabajo, porque el deber varía de 0 a 600 (de la configuración PWM), luego 0 es 0 y 1 es equivalente a 600. En base a esto, volvamos a calcularlo en una fórmula real para obtener el valor que se cargará en el registro CMPA PWM :


  • Fase A - deber1 = A (0.5 + (sin (2π (n / N)) / 2))
  • Fase B - deber2 = A (0.5 + (sin (2π (n / N) -2π / 3) / 2))
  • Fase C - deber 4 = A (0.5 + (sin (2π (n / N) -4π / 3) / 2))

En consecuencia, A es el valor máximo de la amplitud, es decir, 600, n es el paso actual, N es el número total de pasos (20). Los valores de duty1, duty2, duty4 son los valores reales convertidos del factor de deber, que se carga en el CMPA. Ahora escribamos el código para el controlador de interrupciones actualizado y declaremos todas las variables necesarias:


 float activeStep = 0.0; float amplitude = 600.0; float allStep = 20.0; const float pi = 3.1415; // π const float piTwo = 6.2831; // 2π const float phaseShifted120deg = 2.0943; // 2π/3 const float phaseShifted240deg = 4.1866; // 4π/3 __interrupt void cpu_timer0_isr (void) { if (activeStep >= allStep) {activeStep = 0;} activeStep++; EPwm1Regs.CMPA.half.CMPA = ((uint16_t)(amplitude * (0.5 + (sinf(piTwo * (activeStep / allStep)) / 2)))); EPwm2Regs.CMPA.half.CMPA = ((uint16_t)(amplitude * (0.5 + (sinf(piTwo * (activeStep / allStep) - phaseShifted120deg) / 2)))); EPwm4Regs.CMPA.half.CMPA = ((uint16_t)(amplitude * (0.5 + (sinf(piTwo * (activeStep / allStep) - phaseShifted240deg) / 2)))); PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; // Acknowledge this interrupt to receive more interrupts from group 1 } 

El código, como puede ver, es el más simple, si comprende lo que se requería hacer y las matemáticas simples en el problema a resolver. Cada vez que se llama a la interrupción, incrementamos la variable activeStep , que contiene el número de paso, cambia de 0 a 20 y luego se restablece. Resulta que en un período realizamos 20 pasos y 20 cálculos para cada fase. Para no contar 2π / 3 y 4π / 3 en la fórmula todo el tiempo, los conté de inmediato para usarlos como constantes.


Los cálculos resultaron mínimos, para este MK no es absolutamente nada. Si lo desea, el número de puntos se puede aumentar significativamente, por ejemplo, hasta 200. Todo depende de la tarea. El cambio de la frecuencia PWM se produce al cambiar la frecuencia de la llamada de interrupción y el número de pasos. También puede cambiar la amplitud variable y cambiar el voltaje en la salida del convertidor de potencia.


Después de descargar el código al microcontrolador, obtendrá la imagen correspondiente:


Oscilograma número 1


Si estira el gráfico a lo largo de Y , es mejor ver los defectos de la señal. Esto es una consecuencia del pequeño número de pasos de muestreo; se aplica una regla condicional: cuantos más puntos, más bella es la señal.


Oscilograma número 3


Conclusión


Hoy hablé sobre el proceso de formación de cambio de fase en sistemas multifásicos, en principio, no hay nada complicado, especialmente cuando se usa TMS320F28. El resto depende de los algoritmos, en principio, en Internet, hay muchos artículos donde el control de masticación y los motores sin escobillas, y asíncronos y todo tipo de otros, solo puede cambiar la lógica.


Espero que este material sea útil y no particularmente aburrido de leer. Como siempre, se adjunta la fuente:


Archivo con el proyecto para Code Composer Studio

Source: https://habr.com/ru/post/457548/


All Articles