motor-control-sdk/source/transforms/svgen/svgen.h
Sen Wang 306b984080 am243x/am263x: rtlibs: Add transforms libraries and examples
Fixes: RTLIBS-8

Signed-off-by: Sen Wang <s-wang12@ti.com>
2023-12-15 09:17:20 +05:30

256 lines
7.6 KiB
C

/*
* Copyright (C) 2023 Texas Instruments Incorporated
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _SVGEN_H_
#define _SVGEN_H_
#ifdef __cplusplus
extern "C"
{
#endif
/**
* \addtogroup TRANSFORMS_API_MODULE APIs for motor transformations
* \@{
*
* \file svgen.h
* \brief Contains svpwm generation implementation
*/
#include <stdint.h>
typedef float float32_t;
#define SQRT_THREE_OVER_TWO 0.8660254037844f
#define TWO_OVER_SQRT_THREE 1.15470053837926f
//! \brief Implements a SVM that subtracts common-mode term to achieve SV modulation.
//! \param[in] oneOverDcBUS_invV The inverse dc bus voltage scale factor, used to convert inputs to pu, use 1 if units are already in pu.
//! \param[in] inValpha Input voltage value in alpha-axis, V or pu
//! \param[in] inVbeta Input voltage value in beta-axis, V or pu
//! \param[in] pVa Output pointer to voltage value in a-axis, pu
//! \param[in] pVb Output pointer to voltage value in b-axis, pu
//! \param[in] pVc Output pointer to voltage value in c-axis, pu
//!
static __attribute__((always_inline))
void SVGEN_runCom(const float32_t oneOverDcBus_invV, const float32_t inValpha, const float32_t inVbeta, \
float32_t* pVa, float32_t* pVb, float32_t* pVc)
{
float32_t vmax_pu, vmin_pu, vcom_pu = 0;
float32_t va_pu = inValpha * oneOverDcBus_invV;
float32_t vbeta_pu = inVbeta * oneOverDcBus_invV;
float32_t va_tmp = -0.5f * va_pu;
float32_t vb_tmp = SQRT_THREE_OVER_TWO * vbeta_pu;
//
// -0.5*Valpha + sqrt(3)/2 * Vbeta
//
float32_t vb_pu = va_tmp + vb_tmp;
//
// -0.5*Valpha - sqrt(3)/2 * Vbeta
//
float32_t vc_pu = va_tmp - vb_tmp;
//
// Find Vmax and Vmin
//
if(va_pu > vb_pu)
{
vmax_pu = va_pu;
vmin_pu = vb_pu;
}
else
{
vmax_pu = vb_pu;
vmin_pu = va_pu;
}
if(vc_pu > vmax_pu)
{
vmax_pu = vc_pu;
}
else if(vc_pu < vmin_pu)
{
vmin_pu = vc_pu;
}
//
// Compute Vcom = 0.5*(Vmax+Vmin)
//
vcom_pu = 0.5f * (vmax_pu + vmin_pu);
//
// Subtract common-mode term to achieve SV modulation
//
*pVa = (va_pu - vcom_pu);
*pVb = (vb_pu - vcom_pu);
*pVc = (vc_pu - vcom_pu);
}
//! \brief Implements a DPWM that uses maximum modulation.
//! \param[in] oneOverDcBUS_invV The inverse dc bus voltage scale factor, used to convert inputs to pu, use 1 if units are already in pu.
//! \param[in] inValpha Input voltage value in alpha-axis, V or pu
//! \param[in] inVbeta Input voltage value in beta-axis, V or pu
//! \param[in] pVa Output pointer to voltage value in a-axis, pu
//! \param[in] pVb Output pointer to voltage value in b-axis, pu
//! \param[in] pVc Output pointer to voltage value in c-axis, pu
//!
static __attribute__((always_inline))
void SVGEN_runMax(const float32_t oneOverDcBus_invV, const float32_t inValpha, const float32_t inVbeta, \
float32_t* pVa, float32_t* pVb, float32_t* pVc)
{
float32_t vmax_pu = 0;
float32_t va_pu = inValpha * oneOverDcBus_invV;
float32_t vbeta_pu = inVbeta * oneOverDcBus_invV;
float32_t va_tmp = -0.5f * va_pu;
float32_t vb_tmp = SQRT_THREE_OVER_TWO * vbeta_pu;
//
// -0.5*Valpha + sqrt(3)/2 * Vbeta
//
float32_t vb_pu = va_tmp + vb_tmp;
//
// -0.5*Valpha - sqrt(3)/2 * Vbeta
//
float32_t vc_pu = va_tmp - vb_tmp;
//
// Find Vmax
//
if(va_pu > vb_pu)
{
vmax_pu = va_pu;
}
else
{
vmax_pu = vb_pu;
}
if(vc_pu > vmax_pu)
{
vmax_pu = vc_pu;
}
//
// DPWM maximum modulation
//
*pVa = (va_pu - vmax_pu) + 0.5f;
*pVb = (vb_pu - vmax_pu) + 0.5f;
*pVc = (vc_pu - vmax_pu) + 0.5f;
}
//! \brief Implements a DPWM that uses minimum modulation.
//! \param[in] oneOverDcBUS_invV The inverse dc bus voltage scale factor, used to convert inputs to pu, use 1 if units are already in pu.
//! \param[in] inValpha Input voltage value in alpha-axis, V or pu
//! \param[in] inVbeta Input voltage value in beta-axis, V or pu
//! \param[in] pVa Output pointer to voltage value in a-axis, pu
//! \param[in] pVb Output pointer to voltage value in b-axis, pu
//! \param[in] pVc Output pointer to voltage value in c-axis, pu
//!
static __attribute__((always_inline))
void SVGEN_runMin(const float32_t oneOverDcBus_invV, const float32_t inValpha, const float32_t inVbeta, \
float32_t* pVa, float32_t* pVb, float32_t* pVc)
{
float32_t vmin_pu = 0;
float32_t va_pu = inValpha * oneOverDcBus_invV;
float32_t vbeta_pu = inVbeta * oneOverDcBus_invV;
float32_t va_tmp = -0.5f * va_pu;
float32_t vb_tmp = SQRT_THREE_OVER_TWO * vbeta_pu;
//
// -0.5*Valpha + sqrt(3)/2 * Vbeta
//
float32_t vb_pu = va_tmp + vb_tmp;
//
// -0.5*Valpha - sqrt(3)/2 * Vbeta
//
float32_t vc_pu = va_tmp - vb_tmp;
//
// Find Vmin
//
if(va_pu < vb_pu)
{
vmin_pu = va_pu;
}
else
{
vmin_pu = vb_pu;
}
if(vc_pu < vmin_pu)
{
vmin_pu = vc_pu;
}
//
// DPWM minimum modulation
//
*pVa = (va_pu - vmin_pu) - 0.5f;
*pVb = (vb_pu - vmin_pu) - 0.5f;
*pVc = (vc_pu - vmin_pu) - 0.5f;
}
//! \brief Saturates the SVM variable base on modulation limits
//! \param[in] Umax Maximum modulation limit
//! \param[in] Umin Minimum modulation limit
//! \param[in] pVa pointer to voltage value in a-axis
//! \param[in] pVb pointer to voltage value in b-axis
//! \param[in] pVc pointer to voltage value in c-axis
//!
static __attribute__((always_inline))
void SVGEN_clamp(const float32_t Umax, const float32_t Umin, \
float32_t* pVa, float32_t* pVb, float32_t* pVc)
{
*pVa = (*pVa > Umax) ? Umax : (*pVa < Umin) ? Umin : *pVa;
*pVb = (*pVb > Umax) ? Umax : (*pVb < Umin) ? Umin : *pVb;
*pVc = (*pVc > Umax) ? Umax : (*pVc < Umin) ? Umin : *pVc;
}
/** @} */
#ifdef __cplusplus
}
#endif
#endif // _SVGEN_H_