nuttx-apps/examples/dsptest/test_observer.c
2020-04-03 22:23:23 +01:00

358 lines
9.0 KiB
C

/****************************************************************************
* examples/dsptest/test_observer.c
*
* Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Mateusz Szafoni <raiden00@railab.me>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name NuttX 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include "dsptest.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
/* Dummy angle observer */
struct motor_observer_dummy_s
{
float x;
};
/* Dummy speed observer */
struct motor_sobserver_dummy_s
{
float x;
};
/****************************************************************************
* Private Function Protototypes
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/* Initialize observer data */
static void test_observer_init(void)
{
struct motor_observer_dummy_s ao;
struct motor_sobserver_dummy_s so;
struct motor_observer_s o;
float per = 1e-11;
motor_observer_init(&o, (void *)&ao, (void *)&so, per);
TEST_ASSERT_EQUAL_FLOAT(0.0, o.angle);
TEST_ASSERT_EQUAL_FLOAT(0.0, o.speed);
TEST_ASSERT_EQUAL_FLOAT(per, o.per);
TEST_ASSERT_NOT_NULL(o.ao);
TEST_ASSERT_NOT_NULL(o.so);
}
/* Initialize SMO observer data */
static void test_observer_smo_init(void)
{
struct motor_observer_smo_s ao;
float kslide = 0.99;
float err_max = 0.99;
/* Initialize SMO observer */
motor_observer_smo_init(&ao, kslide, err_max);
/* Test */
TEST_ASSERT_EQUAL_FLOAT(kslide, ao.k_slide);
TEST_ASSERT_EQUAL_FLOAT(err_max, ao.err_max);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.F);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.G);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.emf_lp_filter1);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.emf_lp_filter2);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.emf.a);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.emf.b);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.z.a);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.z.b);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.i_est.a);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.i_est.b);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.v_err.a);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.v_err.b);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.i_err.a);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.i_err.b);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.sign.a);
TEST_ASSERT_EQUAL_FLOAT(0.0, ao.sign.b);
}
/* Feed SMO observer with zeros */
static void test_observer_smo_zeros(void)
{
struct motor_sobserver_dummy_s so;
struct motor_observer_smo_s ao;
struct motor_observer_s o;
struct motor_phy_params_s phy;
ab_frame_t i_ab;
ab_frame_t v_ab;
float k_slide = 1.0;
float err_max = 1.0;
float per = 1e-6;
float angle = 0.0;
int i = 0;
/* Initialize ab frames */
i_ab.a = 0.0f;
i_ab.b = 0.0f;
v_ab.a = 0.0f;
v_ab.b = 0.0f;
/* Initialize motor physical parameters */
phy.p = 8;
phy.res = 0.001;
phy.ind = 10e-6;
/* Initialize SMO angle observer */
motor_observer_smo_init(&ao, k_slide, err_max);
/* Initialize observer */
motor_observer_init(&o, &ao, &so, per);
/* Feed SMO observer with zeros. This should return
* angle equal to observer phase shift (direction * PI)
*/
i_ab.a = 0.0;
i_ab.b = 0.0;
v_ab.a = 0.0;
v_ab.b = 0.0;
for (i = 0; i < 1000000; i += 1)
{
motor_observer_smo(&o, &i_ab, &v_ab, &phy, DIR_CW);
}
angle = motor_observer_angle_get(&o);
/* Test */
TEST_ASSERT_EQUAL_FLOAT(M_PI_F, angle);
for (i = 0; i < 1000000; i += 1)
{
motor_observer_smo(&o, &i_ab, &v_ab, &phy, DIR_CCW);
}
angle = motor_observer_angle_get(&o);
/* Test. NOTE: -M_PI_F normalised = 0.0 */
TEST_ASSERT_FLOAT_WITHIN(5e-6, 0.0, angle);
}
/* Feed SMO in CW direction */
static void test_observer_smo_cw(void)
{
/* TODO */
TEST_FAIL_MESSAGE("not implemented");
}
/* Feed SMO in CCW direction */
static void test_observer_smo_ccw(void)
{
/* TODO */
TEST_FAIL_MESSAGE("not implemented");
}
/* SMO observer in linear region */
static void test_observer_smo_linear(void)
{
/* TODO */
TEST_FAIL_MESSAGE("not implemented");
}
/* SMO observer gain saturation */
static void test_observer_smo_gain_saturate(void)
{
/* TODO */
TEST_FAIL_MESSAGE("not implemented");
}
/* DIV speed observer initialization */
static void test_sobserver_div_init(void)
{
struct motor_sobserver_div_s so;
uint8_t samples = 10;
float filter = 0.1;
float per = 10e-6;
/* Initialize DIV speed observer */
motor_sobserver_div_init(&so, samples, filter, per);
TEST_ASSERT_EQUAL_FLOAT(filter, so.filter);
TEST_ASSERT_EQUAL_FLOAT(1.0 / (samples * per), so.one_by_dt);
TEST_ASSERT_EQUAL_UINT8(samples, so.samples);
}
/* Feed DIV speed observer with zeros */
static void test_sobserver_div_zeros(void)
{
struct motor_sobserver_div_s so;
struct motor_observer_s o;
struct motor_observer_dummy_s ao;
uint8_t samples = 10;
float filter = 0.1;
int i = 0;
float expected_s = 0.0;
float speed = 0.0;
float per = 1e-6;
/* Initialize DIV speed observer */
motor_sobserver_div_init(&so, samples, filter, per);
/* Initialize observer */
motor_observer_init(&o, &ao, &so, per);
/* Feed observer with zeros in CW direction */
expected_s = 0.0;
for (i = 0; i < 1000; i += 1)
{
motor_sobserver_div(&o, 0.0, DIR_CW);
}
speed = motor_observer_speed_get(&o);
/* Test */
TEST_ASSERT_EQUAL_FLOAT(expected_s, speed);
/* Feed observer with zeros in CCW direction */
expected_s = 0.0;
for (i = 0; i < 1000; i += 1)
{
motor_sobserver_div(&o, 0.0, DIR_CCW);
}
speed = motor_observer_speed_get(&o);
/* Test */
TEST_ASSERT_EQUAL_FLOAT(expected_s, speed);
}
/* Feed DIV speed observer in CW direction */
static void test_sobserver_div_cw(void)
{
/* TODO */
TEST_FAIL_MESSAGE("not implemented");
}
/* Feed DIV speed observer in CCW direction */
static void test_sobserver_div_ccw(void)
{
/* TODO */
TEST_FAIL_MESSAGE("not implemented");
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: test_observer
****************************************************************************/
void test_observer(void)
{
UNITY_BEGIN();
TEST_SEPARATOR();
/* Test observer functions */
RUN_TEST(test_observer_init);
/* SMO observer */
RUN_TEST(test_observer_smo_init);
RUN_TEST(test_observer_smo_zeros);
RUN_TEST(test_observer_smo_linear);
RUN_TEST(test_observer_smo_gain_saturate);
RUN_TEST(test_observer_smo_cw);
RUN_TEST(test_observer_smo_ccw);
/* DIV observer */
RUN_TEST(test_sobserver_div_init);
RUN_TEST(test_sobserver_div_zeros);
RUN_TEST(test_sobserver_div_cw);
RUN_TEST(test_sobserver_div_ccw);
UNITY_END();
}