Se hace la lectura correspondiente a las hojas de fabricante de los elementos involucrados directamente en el proyecto. En este caso, se menciona los elementos dados:
Por último, se hace la lectura pertinente a modo de introducción del borrador de la propuesta de Trabajo Final de Graduación Licenciatura del estudiante César Quesada Zamora. Aquí se estudian los temas y conceptos más importantes relacionados con este trabajo, como lo son las definiciones de Control por Impedancia y Control Directo por Torque.
Esta semana se busca conocer de mejor manera el Microcontrolador, STM32F407VG-Discovery y la FPGA, iCE40-HX8K. Para este primero se busca hacer un taller en el que pone a prueba el uso de librerías llamadas libopencm3 y libopencm3-plus que permiten utilizar algunas extensiones para microcontroladores STM32. Por otro lado, para la FPGA se busca hacer un tutorial de LED mini blink para entender el funcionamiento de generar un binario, crear su archivo de restricciones y cargarlo a la FPGA.
Para el microcontrolador algunas anotaciones pertinentes fueron:
Se tuvo que instalar apt install gcc-arm-none-eabi para los makes de los ejemplos del stm32 de las librerías libopncm3
Se usa el ejemplo del /stm32/f4/stm32f4discovery
Instalar opencd sudo apt install openocd.
Se cambia en el make de cmcacm\_example.flash el OOCD_INTERFACE=stlink-v2-1 a OOCD_INTERFACE=stlink. También se hace la instalación de estas sudo apt-get install stlink-tools.
Se instala minicom con sudo apt-get install minicom. En la configuración de programa para la opción A, se agrega el directorio /dev/ttyACM0 que corresponde al dispositivo en cuestión.
En este caso, se intentó hacer el ejemplo en la casa, sin embargo no funcionó correctamente. De esta forma se intentará hacer en el laboratorio propiamente.
Para la FPGA algunas anotaciones pertinentes fueron:
sudo apt-get install yosys arachne-pnr fpga-icestorm.yosys -p "synth_ice40 -blif miniblik.blif" miniblink.v.arachne-pnr -d 8k -p restriction.pcf miniblink.blif -o miniblink.txticepack miniblink.txt miniblink.bin Finalmente se plantean las metas a cumplir para las proximas semanas. Una vez puesto a prueba los ejemplos de funcionamiento para el STM32 y la FPGA, se estudian ya varias referencias que pretenden generar una propuesta a la implementación de la Funcion de Control Directo de Torque (DTC).
Esta semana se estudian directamente las fuentes necesarias para la implementación correcta de Función de Control Directo de Torque (DTC) y Control por Impedancia. Es bien sabido que uno de los componentes más comunes en cualquier máquina industrial o residencial es el motor eléctrico. Por ello, se han desarrollado varias estrategias de control de alto rendimiento para motores de corriente alterna (CA); dos de los métodos de control son: control orientado al campo (FOC) y el control directo del par (DTC).
El objetivo principal del DTC es estimar valores instantáneos de par y flujo magnético, basándose en la corriente y el voltaje del motor. Los vectores de par y flujo se controlan de forma directa e independiente, seleccionando el vector de voltaje del inversor adecuado que mantenga los errores de par y flujo dentro de los límites del comparador de histéresis.
Para estimar los valores de par y flujo del motor, se obtienen las señales instantáneas de corriente (ia, ib) y voltaje del bus de corriente continua (Vcd) del motor de inducción de corriente alterna (ACIM). Estas señales analógicas se convierten en valores digitales mediante un convertidor analógico a digital (ADC). Las señales de corriente y voltaje, así como el estado actual del vector del inversor de fuente de voltaje (VSI) (Sa, Sb, Sc), se transforman de un sistema de referencia trifásico a uno bifásico (α, β). [2]
Para poder reorientar el vector de flujo φs, primero es necesario determinar su posición. Para ello, la trayectoria circular del vector de flujo se divide en seis sectores simétricos. La posición de este ayudará luego a determinar el vector de pulso de voltaje (Sn) para el vector del inversor de fuente de voltaje (VSI).
Por otro lado, los valores estimados de flujo magnético y par electromagnético se comparan con sus respectivos valores de referencia. A partir de esta comparación, se obtienen los errores de flujo (eφ) y de par (eT), los cuales se envían a controladores por histéresis. El controlador de histéresis utilizado para el flujo es de dos niveles, mientras que el del par es de tres niveles. Estas configuraciones de los errores permiten mantener dentro de rangos aceptables los valores discretos que escogen vector de pulso de voltaje. [2]
Las variables digitalizadas del flujo (φ), el par (τ) y el sector en el que se encuentra el flujo del estator determinan qué vector de tensión debe aplicarse, según la tabla de conmutación del inversor. De esta manera, la tabla de selección genera las señales de control (Sa, Sb, Sc) que activan los interruptores de potencia del inversor, permitiendo generar seis vectores activos posibles. Incrementando el vector de flujo φs con (v2, v3 o v4), decrementándolo con (v1, v5 o v6) y dos vectores nulos constantes con (v0 y v7). [2]
Para la implementación del Control de Impedancia es necesario la implementación un controlador de Torque. El Control por Impedancia se rige por la siguiente ecuación:
Para el DTC el flujo magnético de referencia y el torque de referencia son señales medidas externas. Estas señales se utilizan para calcular el error a través del flujo magnético y el torque calculados internamente por la FPGA. Por otro lado, se usan las corrientes del rotor i y i, el bus de tensión V del VSI también como mediciones externas y una reutilización del valor de las tensiones Sa-b-c. Para las salidas, serían valores binarios Sa-b-c de la tabla de vectores de conmutación. Las entradas se verían de la siguiente forma, aunque quedaría de definir el tamaño de las variables, pines según como los envía el STM32:
module Direct_torque_control (
input wire CLK,
input wire Reset, # para manejar maquina de estados
input wire Vcd,
# input wire Va, Vb,
input wire Ia, Ib,
input wire tau_Torque_ref,
input wire phi_Flujomag_ref,
output reg Sa_o, Sb_o, Sc_o
);
Para el Control por Impedancia las entradas son la constante de amortiguamiento (D), constante de rigidez (K), posición , velocidad angular , posición deseada , torque y como salida una referencia de torque .
module Impedance_control (
input wire CLK,
input wire Reset,
input wire K_riguidez,
input wire D_amortiguamiento,
input wire angular_position,
input wire angular_velocity,
input wire tau_Torque,
input wire angular_position_ref,
output reg tau_Torque_ref
);
Conversación con el estudiante de maestría Cesar sobre la propuesta de entradas. Se otorga el visto bueno aunque con algunas dudas que se deben aclarar con el profesor Federico acerca del manejo correcto de pines de la FPGA, además de como lee el opencoroco los datos y se envían del STM32. Se muestra a continuación los diagramas de conexión entre la FPGA y el STM32.
//Numero del estado ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
parameter Estado_inicial = 4'b0000; //|
parameter E_current_voltage_signals = 4'b0001; //|
parameter E_flux_components = 4'b0010; //|
parameter E_flux_magnitude = 4'b0011; //|
parameter E_electromag_torque: = 4'b0100; //|
parameter E_flux_space_sector = 4'b0101; //|
parameter E_hysteresis_controller = 4'b0110; //|
parameter E_table_vector_selector = 4'b0111; //|
parameter Estado_salida = 4'b1000; //|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
E_hysteresis_controller: begin
// Controlador de Flujo Magnetico
if (Phi_s => i_Phi_ref ) begin // Se necesita un decremento.
table_Phi = 0;
end else begin // Se necesita un incremento.
table_Phi = 1;
end
// Controlador de Torque
if (T_e =< i_Tau_ref) begin // Se necesita un decremento.
table_Tau = 1;
end else if (T_e == i_Tau_ref) begin // No cambio.
table_Tau = 0;
end else if (T_e => i_Tau_ref) begin // Se necesita un incremento.
table_Tau = -1;
end
e_siguiente = E_table_vector_selector;
end
module Direct_torque_control (
input wire ice_CLK,
inout wire DATA0, // pin L1
inout wire DATA1, // pin J3
inout wire DATA2, // pin L2
inout wire DATA3, // pin K3
inout wire DATA4, // pin J4
inout wire DATA5, // pin L3
inout wire DATA6, // pin L4
inout wire DATA7, // pin K4
input wire CTRL0, // STM32 w/r = 1, w/r = 0.
input wire CTRL1, // STM32 data w/ry to w/r = 1, not = 0.
input wire CTRL2, // FPGA w/r = 1, w/r = 0.
output reg CTRL3, // FPGA data w/ry to w/r = 1, not = 0. // pin SPI2_SCK
input wire CTRL4, // negeative number pin SPI2_MISO
// Selector de variables externas
input wire SEL0,
input wire SEL1,
input wire SEL2,
input wire SEL3 // pin SPI2_CS
);
Esto principalmente pensando que se va a trabajar en punto fijo con 16 bits, así las variables de selección (\verb|SEL|) permiten escoger valores de la parte entera y decimal de las variables de entrada. También las variables (\verb|CTRL|) permiten escoger los diferentes funcionamientos de lectura y escritura entre ambos dispositivos.
//Control de pines para la salida
assign DATA0 = (CTRL3&CTRL1) ? data_out[0] : 1'bz;
assign DATA1 = (CTRL3&CTRL1) ? data_out[1] : 1'bz;
assign DATA2 = (CTRL3&CTRL1) ? data_out[2] : 1'bz;
assign DATA3 = (CTRL3&CTRL1) ? data_out[3] : 1'bz;
assign DATA4 = (CTRL3&CTRL1) ? data_out[4] : 1'bz;
assign DATA5 = (CTRL3&CTRL1) ? data_out[5] : 1'bz;
assign DATA6 = (CTRL3&CTRL1) ? data_out[6] : 1'bz;
assign DATA7 = (CTRL3&CTRL1) ? data_out[7] : 1'bz;
CTRL3 es indicador de cuando hay datos listos de salida o estamos en el estado de salida. CTRL1 es una bandera ``ready'' que habilita el STM32 en el momento justo que quiere leer o escribir datos. Así CTRL3&CTRL1 es una lógica que permite al FPGA escribir en las líneas de datos cuando CTRL3 = CTRL1 = 1, de otra forma la deja en alta impedancia.


Así se activa el vector del inversor de fuente de voltaje (VSI) (Sa~, Sb~, Sc~).
Esta semana se iba a probar la conexión física entre las tarjetas con el demo del STM32. Sin embargo, al intentar sintetizar el código para generar el .blif, ocurrieron varios errores, entre ellos uno muy importante que las generación de Latches o DLatches.
Los Latches aparecen cuando una variable de un registro se modifica dentro una condición case, if o \always(*) pero no se especifica que otro valor toma en otro caso. La síntesis de lógica secuencial a estructural (hardware/compuertas) tiene que adivinar que valor toma en el otro caso que no se especifica o cuando no se esta trabajando con la variable, lo que cual hace que se cree una compuerta no deseada llamada \verb|DLatch|.
Se trabaja con los siguientes comandos de depuración de Yosys para detectar cuáles variables estaban generando estos Latches en la generación del .blif.
Para poder ver el numero de compuertas
yosys -p ``read\_verilog Direct\_torque\_control.v; proc; stat''
yosys -p ``read\_verilog Direct\_torque\_control.v; proc; show Direct\_torque\_control''
//Control de pines para la salida
assign DATA0 = (CTRL3&CTRL1) ? data_out[0] : 1'bz;
Que son los que generan los TBUF.
SB_IO #(
.PIN_TYPE(6'b101001), // Configuracion para bidireccional simple
.PULLUP(1'b0)
) io_data0 (
.PACKAGE_PIN(DATA0), // Pin fisico
.D_OUT_0(data_out_0), // Salida desde FPGA
.D_IN_0(data_in_0), // Entrada hacia FPGA
.OUTPUT_ENABLE(oe_0) // Habilita la salida
);
Yosys y Arachne-pnr sí reconocen a \verb|SB_IO| y saben qué hacer con él, porque están diseñados para sintetizar para iCE40.
Se debe también escoger el paquete que contenga los pines correcto asociados a la placa el cual sería bg121.
arachne-pnr -d 8k -P bg121 -p restrictions.pcf Direct\_torque\_control.blif -o Direct\_torque\_control.txt
Esta semana también trabaja la optimización del código ya que el diseño inicial no cabe en la FPGA. Se descubre que el tamaño de los registros, la gran cantidad de condicionales if, else y cases generan muchas LC`s que se traducen como ``logic cells''. De forma que la síntesis estaba generando 31523 y la FPGA solo tiene disponibles 7824, o sea un 400% mas de las que podría usar.
Las optimizaciones que se hacen son: reducir el tamaño de los registros de 64 bits a 16 bits a excepción del registro de operación que es uno especial para almacenar resultados y no perder presición, se pasar a usar punto fijo de Q16.16 a punto fijo de Q8.8, se reduce drásticamente los condicionales if,else y las operaciones de comparación == con variables de muchos bits, entre otras elementos más
Se logra la optimización del código y se sintetiza de manera correcta.
Surge un último problema. Para realizar la síntesis de manera correcta se necesita un archivo de restricciones que indica un mapeo entre los pines de la FPGA y las entradas y salidas del código. Existen varios ``paquetes'' de pines que traen un mapeo especifico para algunos modelos de la FPGA. El paquete con el que se trabaja en la maestría se llama \texttt{bg121} y fue con el que se generó el archivo de restricciones, así, a la hora de flashearlo se nota que el juego de LEDs implementado para verificar la funcionalidad no funciona. Tras un cierto análisis se decide volver a correr el ejemplo de miniblink.v que había funcionado de manera correcta, esto permite detectar que el paquete que usa este modelo de FPGA se llama \textbf{ct256} el cual tiene asociado otro mapeo de pines y funciona de forma correcta. Se decide correr el ejemplo del miniblink.v pero con el mapeo de \texttt{bg121} para verificar el funcionamiento y el resultado es que no funciona con este paquete el ejemplo. Esto impacta de manera negativa en las pruebas físicas entre ambos dispositivos.
Se hace el reporte del problema al profesor encargado. Se comenta esto también con el estudiante de maestría encargado, y corrobora que los paquetes de pines del diseño original y los que usa mi FPGA actual son distintos y por tanto habría que trasladar todos los pines de un paquete al otro. Se inicia a trabajar en el reporte final escrito/ resumen ejecutivo.
A continuación se muestran algunos de los resultados obtenidos en el desarrollo del DTC y su
funcionamiento con algunos casos de prueba en el verilog:

Señales de onda que muestran la lectura y almacenamiento de los datos enviados a la
FPGA. [E_lectura]

Señales de onda que muestran el resultado de todas las variables necesarias para
implementar el DTC. [E_resultados]

Señales de onda que muestran la implementación y cálculo del algoritmo de raíz cuadrada. [E_sqr_root]

Señales de onda que muestran el envío de señales hacía el STM32. [E_salida]
Primeramente se puede observar como en los estados de entrada E_lectura y salida E_salida se utilizan las señales de CTRLx y SELx para leer los valores y enviarlos por medio de la señal data_bus_in que representa los pines de entrada y salida de DATAx.
La interpretación de estos valores, como se mencionó anteriormente es pasar la representación hexadecimal a decimal y dividir por o 256. Esto dará los resultados correctos. Por ejemplo en E_resultados las señal Phi_s = 00E2, esto en decimal es 226 que al dividir por o 256 da como resultado 0.882812 y así con todos los valores de resultados de ecuaciones.
libopencm3-plus-examples/examples/stm32/f4/stm32f4discovery/DTC\_demo
Los pasos para descargar la librería y ponerla a funcionar son:
git clone git@gitlab.com:arcoslab/libopencm3-plus-examples.git
cd libopencm3-plus-examples
git submodule init
git submodule update
//Para inicializarla
cd libopencm3
make -j`nproc`
cd ..
cd libopencm3-plus
make -j`nproc`
cd ..
El código en el STM32 para compilarlo usar el comando make -jnproc y para flashearlo make V=1 flash.

Los valores que se imprimen como "Valor Hexadecimal" son los valores que se deberían de estar enviando directamente al FPGA. Esto como forma para verificar que la traducción de decimal a hexadecimal con punto flotante Q8.8 se está haciendo de manera correcta. Esto recordando que los pines de datos son solo 8, haciendo que las palabras se tengan que dividir por la mitad en parte entera y decimal.