Skip to content

04.01 Desarrollo del firmware

David Redondo edited this page Jun 3, 2024 · 9 revisions

# Desarrollo del firmware

Herramientas utilizadas

Análisis estático: Cppcheck

Cppcheck es una herramienta de análisis estático de código C/C++ que se utiliza para detectar errores y problemas potenciales en el código. Realiza un escaneo exhaustivo del código para identificar posibles problemas como fugas de memoria, uso incorrecto de punteros, variables no inicializadas y otros errores comunes de programación. La integración de Cppcheck en el flujo de trabajo de desarrollo ayuda a identificar y corregir estos problemas en una etapa temprana del proceso de desarrollo, lo que contribuye a mejorar la calidad y fiabilidad del firmware.

Documentación del código: Doxygen

Doxygen es una herramienta de generación de documentación que se utiliza para crear documentación automática a partir del mismo código. Permite documentar el código usando comentarios especiales incrustados en el código mismo, utilizando una sintaxis sencilla y clara. Doxygen procesa estos comentarios para generar documentación en varios formatos, incluyendo HTML (como una pequeña web), y PDF (para una documentación más tradicional). Esta documentación incluye detalles sobre la estructura del código, la descripción de las funciones y variables, así como relaciones y dependencias entre diferentes partes del código. La generación automática de documentación con Doxygen facilita la comprensión y el mantenimiento del código, y proporciona una referencia útil para futuros desarrolladores.

Plataforma de desarrollo

Para el desarrollo del firmware, se emplea STM32CubeIDE de STMicroelectronics, una plataforma de desarrollo integrado (IDE) basada en Eclipse y diseñada específicamente para trabajar con microcontroladores STM32. CubeIDE proporciona un entorno de desarrollo completo que incluye un editor de código, un compilador, un depurador y otras herramientas útiles para la programación de microcontroladores STM32. Además, integra STM32CubeMX, que facilita la configuración de periféricos y la generación de código inicial mediante una interfaz gráfica intuitiva.

El uso de CubeIDE simplifica el proceso de desarrollo de firmware para microcontroladores STM32, ofreciendo características como autocompletado de código, resaltado de sintaxis, depuración paso a paso y visualización de variables en tiempo real.

Lenguaje de programación

El lenguaje de programación seleccionado para desarrollar el firmware de este proyecto es C. Esta elección se basa en varias consideraciones relacionadas con la naturaleza de la aplicación embebida en un microcontrolador STM32.

En primer lugar, el lenguaje C es ampliamente compatible y soportado por la mayoría de los microcontroladores, incluidos los STM32. La vasta cantidad de recursos, bibliotecas y herramientas disponibles para el desarrollo en C facilita la implementación de funcionalidades complejas y la integración con el hardware específico del microcontrolador.

Además, el lenguaje C es altamente eficiente en términos de uso de recursos de memoria y velocidad de ejecución, lo cual es crucial en aplicaciones embebidas donde se deben cumplir estrictas restricciones de recursos.

Se reconoce que usar C++ podría tener beneficios en la legibilidad y la modularidad por tratarse de un lenguaje orientado a objetos. Sin embargo, las ventajas de usar C son demasiadas como para considerar escribir el código en C++.

Estilo de programación

Para mantener un código claro y coherente, se seguirán las siguientes convenciones de nomenclatura y estilo de programación:

  1. Convenciones generales:

    • Se usará el inglés como idioma a la hora de programar para facilitar el entendimiento.
  2. Convenciones de nomenclatura para variables/estructuras/enumeraciones:

    • Se utilizará camelCase para los nombres de variables y la declaración de estructuras/enumeraciones.

    • Se utilizará PascalCase para la definición de estructuras/enumeraciones.

    • Se emplearán nombres descriptivos que indiquen claramente el propósito de la variable.

    • Se agregarán extensiones _left y _right a las variables que representen componentes del inversor izquierdo y derecho, respectivamente.

    • Se evitará añadir más extensiones con guión bajo.

    • Las constantes se nombrarán en MAYÚSCULAS.

    Ejemplo:

    • Para el offset y el slope del ADC:

      #define CURRENT_SLOPE  117.57704f  /**< [A/V] ((4.7+10)/10) * (1 / (12.5 mV / A)) */
      #define CURRENT_OFFSET 1.70068027211f /**< [V] (10/(4.7+10))* 2.5 V */
    • Para la referencia de par:

      torqueRef_left
      torqueRef_right
    • Para la definición y declaración de la estructura Encoder:

      typedef struct {} Encoder; // Encoder struct definition
      Encoder encoder_left; // Declaration of encoder_left
  3. Convenciones de nomenclatura para funciones:

    • Se utilizará snake_case para los nombres de funciones.

    • Se emplearán nombres descriptivos que indiquen claramente el propósito de la función, incluso si parecen demasiado largos.

    • El nombre de todas las funciones debe empezar por un verbo.

    Ejemplo:

    • initialize_inverter()

    • limit_torque_to_prevent_overspeed()

    • handle_direction()

  4. Convenciones de nomenclatura para archivos:

    • Los pares de archivos .c/.h desarrollados se nombrarán en MAYÚSCULAS, facilitando su distinción de los archivos generados automáticamente.

    Ejemplo:

    • MEASUREMENTS.c/.h $\rightarrow$ Desarrollado

    • adc.c/.h $\rightarrow$ Generado automáticamente

  5. Convenciones para abreviaturas:

    • Se utilizarán abreviaciones comunes solo cuando sean ampliamente entendidas dentro del contexto del proyecto.

    • Se evitarán abreviaciones ambiguas o poco claras.

    Ejemplo:

    • ADC (Convertidor Analógico-Digital)

    • FSM (Máquina de Estados Finitos)

    • LUT (Tabla de Búsqueda)

  6. Comentarios:

    • Cada archivo y función debe ir precedido por un comentario estilo Doxygen que explique claramente su propósito.

    Ejemplo:

    max width=

                    
    /**
    * @brief Computes d-q currents from current measurements and electrical angle.
    *
    * This function computes the d-q currents from phase currents (ABC), theta_e, and stores
    * the results in the provided pointers.
    *
    * @param[in] ia Phase A current in A.
    * @param[in] ib Phase B current in A.
    * @param[in] ic Phase C current in A.
    * @param[in] sinTheta_e Electrical angle sine (-1..1)
    * @param[in] cosTheta_e Electrical angle cosine (-1..1)
    * @param[out] idMeas Pointer to store the d-axis current.
    * @param[out] iqMeas Pointer to store the q-axis current.
    */
    void get_idiq(float ia, float ib, float ic, float sinTheta_e, float cosTheta_e, float *idMeas, float *iqMeas);