DSP_无通信接口系统辨识

前言

由于本人接触的项目,DSP板没有留通信接口给PC端,因此要对系统做辨识,获取数据的唯一渠道就是直接把DSP内存里的数据通过CCS拷贝出来。本文重点讨论在DSP内存有限的情况下,高效地完成系统辨识的方法。

在做这部分工作前,需要学习两个前置知识,即

DSP_CCS7实现变量的导出与MatLAB读取_江湖上都叫我秋博的博客-CSDN博客

DSP_定义一个大的全局数组_探索之路_江湖上都叫我秋博的博客-CSDN博客

这两部分内容是必须要懂的,不然后续的内容,容易卡壳。

正文

低频大数据问题

假设系统采样率为5kHz,要辨识0.1Hz处系统特性,需要存储5wx2 = 10w个点(5w输入序列,5w输出序列)。前面文章DSP_定义一个大的全局数组_探索之路_江湖上都叫我秋博的博客-CSDN博客中已经探讨了,28377D最多存2.4w左右个点,显然是不够的。因此我们选择在低频做降采样率处理,用1kHz的采样率,0.1Hz需要1wx2=2w个点,刚好合适。 而更高的频率比如1Hz,我们则继续用5kHz的采样率。

频率点简化及高频数据合并

对于频段0.1~1000Hz常规的系统辨识一般来200个频率点都不过分, 那难到我们要去点CCS点200次,存200次数据? 显然这样不够高效,因此对于高频部分,我们把多个频率点的数据都合并存到大小为1w的数组中(输入序列一个、输出序列一个)。另外,经过实验,只有能被采样率整除的频率点,它的数据点数才是整数,该频率点下的辨识更加准确。因此经过层层筛选, 200个频率被我筛到39个频率点。  基于上述的两个简化思路。 用MatLAB设计了分配策略。代码如下:

data_allocation.m

clear all;
close all;
clc;
 
%  频率         采样率   点数    周期数
FreqArray = [
    0.1,        1000,   10000,  2;
    0.125,      1000,   8000,   2;
    0.16,       1000,   6250,   2;
    0.2,        1000,   5000,   2;
    0.25,       1000,   4000,   2;
    0.3125,     1000,   3200,   2;
    0.4,        1000,   2500,   2;
    0.5,        1000,   2000,   2;
    0.625,      1000,   1600,   4;
    0.8,        1000,   1250,   4;
    
    1,          5000,   5000,   4;
    1.25,       5000,   4000,   4;
    1.5625,     5000,   3200,   4;
    2,          5000,   2500,   4;
    2.5,        5000,   2000,   4;
    3.125,      5000,   1600,   6;
    4,          5000,   1250,   6;
    5,          5000,   1000,   6;
    6.25,       5000,   800,    6;
    7.8125,     5000,   640,    6;

    
	10,         5000,   500,    10;
    12.5,       5000,   400,    10;
    15.625,     5000,   320,    10;
    20,         5000,   250,    10;
    25,         5000,   200,    10;
    31.25,      5000,   160,    10;
    40,         5000,   125,    10;
    50,         5000,   100,    10;
    62.5,       5000,   80,     10;
    78.125,     5000,   64,     10;
    
	100,        5000,   50,     20;
    125,        5000,   40,     20;
    156.25,     5000,   32,     20;
    200,        5000,   25,     20;
    250,        5000,   20,     20;
    312.5,      5000,   16,     20;
    500,      	5000,   10,     40;
    625,        5000,   8,      40;
    1000,       5000,   5,      40;
       
    ];

FreqNum = length(FreqArray(:,1));


% 数据校验
for i=1 : 1 : FreqNum
    if (FreqArray(i, 2) / FreqArray(i, 1)) ~= FreqArray(i, 3)
        fprintf('%f is wrong!\r\n',FreqArray(i, 1));
    else
        fprintf('%f is ok!\r\n',FreqArray(i, 1));
    end
end

%-------------------------------------------------------------------------------------
% 频响数据的排列分配
% 数组总长度
DSP_Array_Length = 10000;

Current_Length = 0;
AllocationResult = zeros(FreqNum,4); 
% 第一列:频率        第二列:频响数据序号
% 第三列:起始位置    第四列:截至位置
DataIndex = 1;
for i=1 : 1 : FreqNum
    if (Current_Length +  FreqArray(i, 3)) <= DSP_Array_Length
        StartPosition	= Current_Length + 1;        
        Current_Length	= Current_Length +  FreqArray(i, 3);
        StopPosition	= Current_Length;
        
        AllocationResult(i,1)   = FreqArray(i, 1);
        AllocationResult(i,2)   = DataIndex;
        AllocationResult(i,3)   = StartPosition;
        AllocationResult(i,4)   = StopPosition;
        
    elseif FreqArray(i, 3) <= DSP_Array_Length
        DataIndex = DataIndex + 1;
        StartPosition  = 1;
        Current_Length = FreqArray(i, 3);
        StopPosition = Current_Length;
        
        AllocationResult(i,1)   = FreqArray(i, 1);
        AllocationResult(i,2)   = DataIndex;
        AllocationResult(i,3)   = StartPosition;
        AllocationResult(i,4)   = StopPosition;
                
    else
        fprintf('频率点:%f的数据点数超过了DSP的数组总长度 \r\n',FreqArray(i, 1));
    end
end
%-------------------------------------------------------------------------------------


%--------------------------------------------------------------------------------------
% DSP代码生成
para_path = 'AutoGeneratedCode.txt';
fp      = fopen(para_path, 'w');
fprintf(fp,'**请把下面的代码拷贝到dsp工程项目的sys_identify_init函数中**\n');


Current_Length = 0;
DataIndex = 1;
for i=1 : 1 : FreqNum
    if (Current_Length +  FreqArray(i, 3)) <= DSP_Array_Length
        StartPosition	= Current_Length + 1;        
        Current_Length	= Current_Length +  FreqArray(i, 3);
        StopPosition	= Current_Length;
        
        AllocationResult(i,1)   = FreqArray(i, 1);
        AllocationResult(i,2)   = DataIndex;
        AllocationResult(i,3)   = StartPosition;
        AllocationResult(i,4)   = StopPosition;
        fprintf(fp,'    FreqPoints[%d].freq              = %f;\n', i-1, FreqArray(i, 1));
        fprintf(fp,'    FreqPoints[%d].sampling_rate     = %d;\n', i-1, FreqArray(i, 2));
        fprintf(fp,'    FreqPoints[%d].data_number       = %d;\n', i-1, FreqArray(i, 3));
        fprintf(fp,'    FreqPoints[%d].data_index        = %d;\n', i-1, DataIndex);
        fprintf(fp,'    FreqPoints[%d].start_position    = %d;\n', i-1, StartPosition - 1);
        fprintf(fp,'    FreqPoints[%d].stop_position     = %d;\n', i-1, StopPosition - 1);
        fprintf(fp,'    FreqPoints[%d].period_number     = %d;\n', i-1, FreqArray(i, 4));
        fprintf(fp,'    FreqPoints[%d].freq_div_addr     = &iFreq%dHz;\n\n',i-1,FreqArray(i, 2));
    elseif FreqArray(i, 3) <= DSP_Array_Length
        DataIndex = DataIndex + 1;
        StartPosition  = 1;
        Current_Length = FreqArray(i, 3);
        StopPosition = Current_Length;
        
        AllocationResult(i,1)   = FreqArray(i, 1);
        AllocationResult(i,2)   = DataIndex;
        AllocationResult(i,3)   = StartPosition;
        AllocationResult(i,4)   = StopPosition;
        fprintf(fp,'    FreqPoints[%d].freq              = %f;\n', i-1, FreqArray(i, 1));
        fprintf(fp,'    FreqPoints[%d].sampling_rate     = %d;\n', i-1, FreqArray(i, 2));
        fprintf(fp,'    FreqPoints[%d].data_number       = %d;\n', i-1, FreqArray(i, 3));
        fprintf(fp,'    FreqPoints[%d].data_index        = %d;\n', i-1, DataIndex);
        fprintf(fp,'    FreqPoints[%d].start_position    = %d;\n', i-1, StartPosition - 1);
        fprintf(fp,'    FreqPoints[%d].stop_position     = %d;\n', i-1, StopPosition - 1);
        fprintf(fp,'    FreqPoints[%d].period_number     = %d;\n', i-1, FreqArray(i, 4));
        fprintf(fp,'    FreqPoints[%d].freq_div_addr     = &iFreq%dHz;\n\n',i-1,FreqArray(i, 2));         
    else
        fprintf('频率点:%f的数据点数超过了DSP的数组总长度 \r\n',FreqArray(i, 1));
    end
end
    
fclose(fp);
open(para_path);

根据代码运行结果,系统实现一次完整的辨识,只需要拷贝8次结果。 相比于200次拷贝优化程度已经较高了。 另外,代码中还包含了dsp部分代码的生成,这部分代码可以拷贝到dsp的项目当中,这对开发人员(我)是福音啊。

DSP相关代码

要完成系统辨识,dsp这边的代码肯定是必不可少的。

1、针对不同的采样率,我们需要用定时器(CPU Timer)进行分频实现。 

2、针对每个频率点需要用到信息,拷贝序列的安排,拷贝上述.m文件生成的代码即可完成初始化

3、具体的整体实现流程也并不复杂,详情看代码就行了,自行体会。

main.c

/*
 * main.c
 *
 *  Created on: 2022年12月8日
 *      Author: YFR-HQN
 */


#include <main.h>



int16   iFreqCnt    = 0;
int16   iFreq1Hz    = 0;
int16   iFreq2Hz    = 0;
int16   iFreq20Hz   = 0;
int16   iFreq40Hz   = 0;
int16   iFreq50Hz   = 0;
int16   iFreq100Hz  = 0;
int16   iFreq200Hz  = 0;
int16   iFreq250Hz  = 0;
int16   iFreq500Hz  = 0;
int16   iFreq1000Hz = 0;
int16   iFreq2000Hz = 0;
int16   iFreq2500Hz = 0;
int16   iFreq5000Hz = 0;


void main(void)
{
    default_init();
    interrupt_init();
    CpuTimer0Regs.TCR.bit.TSS   = 0;          // 使能CPUTimer0
    runtime_init();

    sys_identify_init();
    sys_idenfify();

}

void default_init(void){
    InitSysCtrl();
    DINT;
    InitPieCtrl();
    InitGpio();
    IER     = 0x0000;
    IFR     = 0x0000;
    InitPieVectTable();

    #ifdef _STANDALONE
        #ifdef _FLASH
            IPCBootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH);
        #else
            IPCBootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_RAM);
        #endif
    #endif

    InitCpuTimers();        //  Initialize CPU Timers


}

void interrupt_init(void){


    // CPU Timer0
    ConfigCpuTimer(&CpuTimer0, 200, 1000000/SYS_BASIC_FREQUENCY);
    CpuTimer0Regs.TCR.bit.TIE   = 1;        //  1: The CPU-Timer interrupt is enabled

    // TIMER0 INT1.7 [Page102: Table 3-2.PIE Channel Mapping]
    EALLOW;
    PieVectTable.TIMER0_INT = &CpuTimer0ISR;  //  Specify the interrupt service routine
    EDIS;

    IER |= M_INT1;                          //  Enable CPU Level interrupt
    PieCtrlRegs.PIEIER1.bit.INTx7   = 1;    //  Enable PIE Level interrupt






    PieCtrlRegs.PIECTRL.bit.ENPIE = 1;
    EINT;  // 使能全局中断
    ERTM;  // 使能实时仿真中断

}




//  Generate frequency division signal
interrupt void CpuTimer0ISR(void){

    DivideFreq();

    PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}




void DivideFreq(void){

    if(iFreqCnt >= CNT1HZ){
        iFreq1Hz    = 1;
        iFreqCnt    = 0;
    }else{
        iFreq1Hz    = 0;
    }

    if((iFreqCnt%CNT2HZ)==0){
        iFreq2Hz    = 1;
    }else{
        iFreq2Hz    = 0;
    }

    if((iFreqCnt%CNT20HZ)==0){
        iFreq20Hz    = 1;
    }else{
        iFreq20Hz    = 0;
    }

    if((iFreqCnt%CNT40HZ)==0){
        iFreq40Hz    = 1;
    }else{
        iFreq40Hz    = 0;
    }


    if((iFreqCnt%CNT50HZ)==0){
        iFreq50Hz    = 1;
    }else{
        iFreq50Hz    = 0;
    }

    if((iFreqCnt%CNT100HZ)==0){
        iFreq100Hz    = 1;
    }else{
        iFreq100Hz    = 0;
    }

    if((iFreqCnt%CNT200HZ)==0){
        iFreq200Hz    = 1;
    }else{
        iFreq200Hz    = 0;
    }

    if((iFreqCnt%CNT250HZ)==0){
        iFreq250Hz    = 1;
    }else{
        iFreq250Hz    = 0;
    }

    if((iFreqCnt%CNT500HZ)==0){
        iFreq500Hz    = 1;
    }else{
        iFreq500Hz    = 0;
    }

    if((iFreqCnt%CNT1000HZ)==0){
        iFreq1000Hz    = 1;
    }else{
        iFreq1000Hz    = 0;
    }

/*
    if((iFreqCnt%CNT2000HZ)==0){
        iFreq2000Hz    = 1;
    }else{
        iFreq2000Hz    = 0;
    }
*/
    if((iFreqCnt%CNT2500HZ)==0){
        iFreq2500Hz    = 1;
    }else{
        iFreq2500Hz    = 0;
    }

    if((iFreqCnt%CNT5000HZ)==0){
        iFreq5000Hz    = 1;
    }else{
        iFreq5000Hz    = 0;
    }


    iFreqCnt++;

}

main.h

/*
 * main.h
 *
 *  Created on: 2022年12月8日
 *      Author: YFR-HQN
 */

#ifndef PROGRAM_MAIN_H_
#define PROGRAM_MAIN_H_

#include <F28x_Project.h>
#include <F2837xD_Ipc_drivers.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include <runtime.h>
#include <sys_identify.h>
#include <control.h>

void default_init(void);
void interrupt_init(void);
interrupt void CpuTimer0ISR(void);
void DivideFreq(void);


#define SYS_BASIC_FREQUENCY 5000
extern  int16   iFreqCnt;
extern  int16   iFreq1Hz;
extern  int16   iFreq2Hz;
extern  int16   iFreq20Hz;
extern  int16   iFreq40Hz;
extern  int16   iFreq50Hz;
extern  int16   iFreq100Hz;
extern  int16   iFreq200Hz;
extern  int16   iFreq250Hz;
extern  int16   iFreq500Hz;
extern  int16   iFreq1000Hz;
extern  int16   iFreq2500Hz;
extern  int16   iFreq5000Hz;

#define CNT1HZ      5000
#define CNT2HZ      2500
#define CNT20HZ     250
#define CNT40HZ     125
#define CNT50HZ     100
#define CNT100HZ    50
#define CNT200HZ    25
#define CNT250HZ    20
#define CNT500HZ    10
#define CNT1000HZ   5
#define CNT2500HZ   2
#define CNT5000HZ   1

#endif /* PROGRAM_MAIN_H_ */

sys_identify.c

/*
 * sys_identify.c
 *
 *  Created on: 2023年2月6日
 *      Author: YFR-HQN
 */


#include <main.h>

float sys_identify_in[10000];
float sys_identify_out[10000];

// float sys_identify_in = 0.0;
int   FreqPonitNum = 39;
struct FreqPoint FreqPoints[39];

void sys_idenfify(void){

    int i = 0;
    int j = 0;
    int k = 0;
    float t = 0.0;
    float delta_t = 0;
    float pi = 3.141592653589793;

    // 频率点
    for(i = 0; i < FreqPonitNum; i++){
        delta_t = __divf32(1,(float)FreqPoints[i].sampling_rate);

        // 测试周期
        for(j = 0; j < FreqPoints[i].period_number; j++){
            t = 0.0;
            for(k = 0;k < FreqPoints[i].data_number;k++){

                while(*FreqPoints[i].freq_div_addr != 1);
                *FreqPoints[i].freq_div_addr = 0;

                // sys_identify_in = __sin(2 * pi * FreqPoints[i].freq * t);
                if(j == (FreqPoints[i].period_number-1)){
                    sys_identify_in[FreqPoints[i].start_position + k]  = __sin(2 * pi * FreqPoints[i].freq * t);
                    sys_identify_out[FreqPoints[i].start_position + k] = 10 * __sin(2 * pi * FreqPoints[i].freq * t + pi/3.0);
                }

                t = t + delta_t;

            }
        }

        if((FreqPoints[i].start_position + k - 1)!=FreqPoints[i].stop_position){
            asm ("      ESTOP0");   // 数据分配错误
        }

        if(i == (FreqPonitNum-1)){
            asm ("      ESTOP0");   // 断点,保存数据
        }else if(FreqPoints[i+1].data_index != FreqPoints[i].data_index){
            asm ("      ESTOP0");   // 断点,保存数据
        }

    }
}

void sys_identify_init(void){
    FreqPoints[0].freq              = 0.100000;
    FreqPoints[0].sampling_rate     = 1000;
    FreqPoints[0].data_number       = 10000;
    FreqPoints[0].data_index        = 1;
    FreqPoints[0].start_position    = 0;
    FreqPoints[0].stop_position     = 9999;
    FreqPoints[0].period_number     = 2;
    FreqPoints[0].freq_div_addr     = &iFreq1000Hz;

    FreqPoints[1].freq              = 0.125000;
    FreqPoints[1].sampling_rate     = 1000;
    FreqPoints[1].data_number       = 8000;
    FreqPoints[1].data_index        = 2;
    FreqPoints[1].start_position    = 0;
    FreqPoints[1].stop_position     = 7999;
    FreqPoints[1].period_number     = 2;
    FreqPoints[1].freq_div_addr     = &iFreq1000Hz;

    FreqPoints[2].freq              = 0.160000;
    FreqPoints[2].sampling_rate     = 1000;
    FreqPoints[2].data_number       = 6250;
    FreqPoints[2].data_index        = 3;
    FreqPoints[2].start_position    = 0;
    FreqPoints[2].stop_position     = 6249;
    FreqPoints[2].period_number     = 2;
    FreqPoints[2].freq_div_addr     = &iFreq1000Hz;

    FreqPoints[3].freq              = 0.200000;
    FreqPoints[3].sampling_rate     = 1000;
    FreqPoints[3].data_number       = 5000;
    FreqPoints[3].data_index        = 4;
    FreqPoints[3].start_position    = 0;
    FreqPoints[3].stop_position     = 4999;
    FreqPoints[3].period_number     = 2;
    FreqPoints[3].freq_div_addr     = &iFreq1000Hz;

    FreqPoints[4].freq              = 0.250000;
    FreqPoints[4].sampling_rate     = 1000;
    FreqPoints[4].data_number       = 4000;
    FreqPoints[4].data_index        = 4;
    FreqPoints[4].start_position    = 5000;
    FreqPoints[4].stop_position     = 8999;
    FreqPoints[4].period_number     = 2;
    FreqPoints[4].freq_div_addr     = &iFreq1000Hz;

    FreqPoints[5].freq              = 0.312500;
    FreqPoints[5].sampling_rate     = 1000;
    FreqPoints[5].data_number       = 3200;
    FreqPoints[5].data_index        = 5;
    FreqPoints[5].start_position    = 0;
    FreqPoints[5].stop_position     = 3199;
    FreqPoints[5].period_number     = 2;
    FreqPoints[5].freq_div_addr     = &iFreq1000Hz;

    FreqPoints[6].freq              = 0.400000;
    FreqPoints[6].sampling_rate     = 1000;
    FreqPoints[6].data_number       = 2500;
    FreqPoints[6].data_index        = 5;
    FreqPoints[6].start_position    = 3200;
    FreqPoints[6].stop_position     = 5699;
    FreqPoints[6].period_number     = 2;
    FreqPoints[6].freq_div_addr     = &iFreq1000Hz;

    FreqPoints[7].freq              = 0.500000;
    FreqPoints[7].sampling_rate     = 1000;
    FreqPoints[7].data_number       = 2000;
    FreqPoints[7].data_index        = 5;
    FreqPoints[7].start_position    = 5700;
    FreqPoints[7].stop_position     = 7699;
    FreqPoints[7].period_number     = 2;
    FreqPoints[7].freq_div_addr     = &iFreq1000Hz;

    FreqPoints[8].freq              = 0.625000;
    FreqPoints[8].sampling_rate     = 1000;
    FreqPoints[8].data_number       = 1600;
    FreqPoints[8].data_index        = 5;
    FreqPoints[8].start_position    = 7700;
    FreqPoints[8].stop_position     = 9299;
    FreqPoints[8].period_number     = 4;
    FreqPoints[8].freq_div_addr     = &iFreq1000Hz;

    FreqPoints[9].freq              = 0.800000;
    FreqPoints[9].sampling_rate     = 1000;
    FreqPoints[9].data_number       = 1250;
    FreqPoints[9].data_index        = 6;
    FreqPoints[9].start_position    = 0;
    FreqPoints[9].stop_position     = 1249;
    FreqPoints[9].period_number     = 4;
    FreqPoints[9].freq_div_addr     = &iFreq1000Hz;

    FreqPoints[10].freq              = 1.000000;
    FreqPoints[10].sampling_rate     = 5000;
    FreqPoints[10].data_number       = 5000;
    FreqPoints[10].data_index        = 6;
    FreqPoints[10].start_position    = 1250;
    FreqPoints[10].stop_position     = 6249;
    FreqPoints[10].period_number     = 4;
    FreqPoints[10].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[11].freq              = 1.250000;
    FreqPoints[11].sampling_rate     = 5000;
    FreqPoints[11].data_number       = 4000;
    FreqPoints[11].data_index        = 7;
    FreqPoints[11].start_position    = 0;
    FreqPoints[11].stop_position     = 3999;
    FreqPoints[11].period_number     = 4;
    FreqPoints[11].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[12].freq              = 1.562500;
    FreqPoints[12].sampling_rate     = 5000;
    FreqPoints[12].data_number       = 3200;
    FreqPoints[12].data_index        = 7;
    FreqPoints[12].start_position    = 4000;
    FreqPoints[12].stop_position     = 7199;
    FreqPoints[12].period_number     = 4;
    FreqPoints[12].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[13].freq              = 2.000000;
    FreqPoints[13].sampling_rate     = 5000;
    FreqPoints[13].data_number       = 2500;
    FreqPoints[13].data_index        = 7;
    FreqPoints[13].start_position    = 7200;
    FreqPoints[13].stop_position     = 9699;
    FreqPoints[13].period_number     = 4;
    FreqPoints[13].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[14].freq              = 2.500000;
    FreqPoints[14].sampling_rate     = 5000;
    FreqPoints[14].data_number       = 2000;
    FreqPoints[14].data_index        = 8;
    FreqPoints[14].start_position    = 0;
    FreqPoints[14].stop_position     = 1999;
    FreqPoints[14].period_number     = 4;
    FreqPoints[14].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[15].freq              = 3.125000;
    FreqPoints[15].sampling_rate     = 5000;
    FreqPoints[15].data_number       = 1600;
    FreqPoints[15].data_index        = 8;
    FreqPoints[15].start_position    = 2000;
    FreqPoints[15].stop_position     = 3599;
    FreqPoints[15].period_number     = 6;
    FreqPoints[15].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[16].freq              = 4.000000;
    FreqPoints[16].sampling_rate     = 5000;
    FreqPoints[16].data_number       = 1250;
    FreqPoints[16].data_index        = 8;
    FreqPoints[16].start_position    = 3600;
    FreqPoints[16].stop_position     = 4849;
    FreqPoints[16].period_number     = 6;
    FreqPoints[16].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[17].freq              = 5.000000;
    FreqPoints[17].sampling_rate     = 5000;
    FreqPoints[17].data_number       = 1000;
    FreqPoints[17].data_index        = 8;
    FreqPoints[17].start_position    = 4850;
    FreqPoints[17].stop_position     = 5849;
    FreqPoints[17].period_number     = 6;
    FreqPoints[17].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[18].freq              = 6.250000;
    FreqPoints[18].sampling_rate     = 5000;
    FreqPoints[18].data_number       = 800;
    FreqPoints[18].data_index        = 8;
    FreqPoints[18].start_position    = 5850;
    FreqPoints[18].stop_position     = 6649;
    FreqPoints[18].period_number     = 6;
    FreqPoints[18].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[19].freq              = 7.812500;
    FreqPoints[19].sampling_rate     = 5000;
    FreqPoints[19].data_number       = 640;
    FreqPoints[19].data_index        = 8;
    FreqPoints[19].start_position    = 6650;
    FreqPoints[19].stop_position     = 7289;
    FreqPoints[19].period_number     = 6;
    FreqPoints[19].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[20].freq              = 10.000000;
    FreqPoints[20].sampling_rate     = 5000;
    FreqPoints[20].data_number       = 500;
    FreqPoints[20].data_index        = 8;
    FreqPoints[20].start_position    = 7290;
    FreqPoints[20].stop_position     = 7789;
    FreqPoints[20].period_number     = 10;
    FreqPoints[20].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[21].freq              = 12.500000;
    FreqPoints[21].sampling_rate     = 5000;
    FreqPoints[21].data_number       = 400;
    FreqPoints[21].data_index        = 8;
    FreqPoints[21].start_position    = 7790;
    FreqPoints[21].stop_position     = 8189;
    FreqPoints[21].period_number     = 10;
    FreqPoints[21].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[22].freq              = 15.625000;
    FreqPoints[22].sampling_rate     = 5000;
    FreqPoints[22].data_number       = 320;
    FreqPoints[22].data_index        = 8;
    FreqPoints[22].start_position    = 8190;
    FreqPoints[22].stop_position     = 8509;
    FreqPoints[22].period_number     = 10;
    FreqPoints[22].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[23].freq              = 20.000000;
    FreqPoints[23].sampling_rate     = 5000;
    FreqPoints[23].data_number       = 250;
    FreqPoints[23].data_index        = 8;
    FreqPoints[23].start_position    = 8510;
    FreqPoints[23].stop_position     = 8759;
    FreqPoints[23].period_number     = 10;
    FreqPoints[23].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[24].freq              = 25.000000;
    FreqPoints[24].sampling_rate     = 5000;
    FreqPoints[24].data_number       = 200;
    FreqPoints[24].data_index        = 8;
    FreqPoints[24].start_position    = 8760;
    FreqPoints[24].stop_position     = 8959;
    FreqPoints[24].period_number     = 10;
    FreqPoints[24].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[25].freq              = 31.250000;
    FreqPoints[25].sampling_rate     = 5000;
    FreqPoints[25].data_number       = 160;
    FreqPoints[25].data_index        = 8;
    FreqPoints[25].start_position    = 8960;
    FreqPoints[25].stop_position     = 9119;
    FreqPoints[25].period_number     = 10;
    FreqPoints[25].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[26].freq              = 40.000000;
    FreqPoints[26].sampling_rate     = 5000;
    FreqPoints[26].data_number       = 125;
    FreqPoints[26].data_index        = 8;
    FreqPoints[26].start_position    = 9120;
    FreqPoints[26].stop_position     = 9244;
    FreqPoints[26].period_number     = 10;
    FreqPoints[26].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[27].freq              = 50.000000;
    FreqPoints[27].sampling_rate     = 5000;
    FreqPoints[27].data_number       = 100;
    FreqPoints[27].data_index        = 8;
    FreqPoints[27].start_position    = 9245;
    FreqPoints[27].stop_position     = 9344;
    FreqPoints[27].period_number     = 10;
    FreqPoints[27].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[28].freq              = 62.500000;
    FreqPoints[28].sampling_rate     = 5000;
    FreqPoints[28].data_number       = 80;
    FreqPoints[28].data_index        = 8;
    FreqPoints[28].start_position    = 9345;
    FreqPoints[28].stop_position     = 9424;
    FreqPoints[28].period_number     = 10;
    FreqPoints[28].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[29].freq              = 78.125000;
    FreqPoints[29].sampling_rate     = 5000;
    FreqPoints[29].data_number       = 64;
    FreqPoints[29].data_index        = 8;
    FreqPoints[29].start_position    = 9425;
    FreqPoints[29].stop_position     = 9488;
    FreqPoints[29].period_number     = 10;
    FreqPoints[29].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[30].freq              = 100.000000;
    FreqPoints[30].sampling_rate     = 5000;
    FreqPoints[30].data_number       = 50;
    FreqPoints[30].data_index        = 8;
    FreqPoints[30].start_position    = 9489;
    FreqPoints[30].stop_position     = 9538;
    FreqPoints[30].period_number     = 20;
    FreqPoints[30].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[31].freq              = 125.000000;
    FreqPoints[31].sampling_rate     = 5000;
    FreqPoints[31].data_number       = 40;
    FreqPoints[31].data_index        = 8;
    FreqPoints[31].start_position    = 9539;
    FreqPoints[31].stop_position     = 9578;
    FreqPoints[31].period_number     = 20;
    FreqPoints[31].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[32].freq              = 156.250000;
    FreqPoints[32].sampling_rate     = 5000;
    FreqPoints[32].data_number       = 32;
    FreqPoints[32].data_index        = 8;
    FreqPoints[32].start_position    = 9579;
    FreqPoints[32].stop_position     = 9610;
    FreqPoints[32].period_number     = 20;
    FreqPoints[32].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[33].freq              = 200.000000;
    FreqPoints[33].sampling_rate     = 5000;
    FreqPoints[33].data_number       = 25;
    FreqPoints[33].data_index        = 8;
    FreqPoints[33].start_position    = 9611;
    FreqPoints[33].stop_position     = 9635;
    FreqPoints[33].period_number     = 20;
    FreqPoints[33].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[34].freq              = 250.000000;
    FreqPoints[34].sampling_rate     = 5000;
    FreqPoints[34].data_number       = 20;
    FreqPoints[34].data_index        = 8;
    FreqPoints[34].start_position    = 9636;
    FreqPoints[34].stop_position     = 9655;
    FreqPoints[34].period_number     = 20;
    FreqPoints[34].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[35].freq              = 312.500000;
    FreqPoints[35].sampling_rate     = 5000;
    FreqPoints[35].data_number       = 16;
    FreqPoints[35].data_index        = 8;
    FreqPoints[35].start_position    = 9656;
    FreqPoints[35].stop_position     = 9671;
    FreqPoints[35].period_number     = 20;
    FreqPoints[35].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[36].freq              = 500.000000;
    FreqPoints[36].sampling_rate     = 5000;
    FreqPoints[36].data_number       = 10;
    FreqPoints[36].data_index        = 8;
    FreqPoints[36].start_position    = 9672;
    FreqPoints[36].stop_position     = 9681;
    FreqPoints[36].period_number     = 40;
    FreqPoints[36].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[37].freq              = 625.000000;
    FreqPoints[37].sampling_rate     = 5000;
    FreqPoints[37].data_number       = 8;
    FreqPoints[37].data_index        = 8;
    FreqPoints[37].start_position    = 9682;
    FreqPoints[37].stop_position     = 9689;
    FreqPoints[37].period_number     = 40;
    FreqPoints[37].freq_div_addr     = &iFreq5000Hz;

    FreqPoints[38].freq              = 1000.000000;
    FreqPoints[38].sampling_rate     = 5000;
    FreqPoints[38].data_number       = 5;
    FreqPoints[38].data_index        = 8;
    FreqPoints[38].start_position    = 9690;
    FreqPoints[38].stop_position     = 9694;
    FreqPoints[38].period_number     = 40;
    FreqPoints[38].freq_div_addr     = &iFreq5000Hz;
}


sys_identify.h

/*
 * sys_identify.h
 *
 *  Created on: 2023年2月6日
 *      Author: YFR-HQN
 */

#ifndef PROGRAM_SYSIDENTIFY_SYS_IDENTIFY_H_
#define PROGRAM_SYSIDENTIFY_SYS_IDENTIFY_H_

extern float sys_identify_out[10000];
extern float sys_identify_in[10000];
extern int   FreqPonitNum;
extern struct FreqPoint FreqPoints[39];

struct FreqPoint{
    float   freq;
    int     sampling_rate;
    int     data_number;
    int     data_index;
    int     start_position;
    int     stop_position;
    int     period_number;
    int16 * freq_div_addr;
};


void sys_identify_init(void);
void sys_idenfify(void);

#endif /* PROGRAM_SYSIDENTIFY_SYS_IDENTIFY_H_ */

注意:代码运行起来后,会在下面这部分代码进入自动进入中断

        if(i == (FreqPonitNum-1)){
            asm ("      ESTOP0");   // 断点,保存数据
        }else if(FreqPoints[i+1].data_index != FreqPoints[i].data_index){
            asm ("      ESTOP0");   // 断点,保存数据
        }

这时候,我们需要把分别把sys_identify_in数组和sys_identify_out数组导出来。 

Tips: 在存数据的时候,把FreqPoints[i].data_index放到变量观察栏,根据这个变量判断当前的序列号是多少。  比如FreqPoints[i].data_index=1,那么就把sys_identify_in数组存为“../DspData/in1.dat",把sys_identify_out存为“../DspData/out1.dat",以此类推,..., FreqPoints[i].data_index=8时,sys_identify_in数组存为“../DspData/in8.dat",sys_identify_out存为“../DspData/Out8.dat"。 在不停的存储数据时,除了修改文件名以外,还需要注意start_address那里需要不停的切换sys_identify_in/sys_identify_out。 看看下面截图。

 

 8组输入输出序列存完后,如下所示:

MatLAB数据解析,系统辨识

得到了数据之后,就需要把上述的8组输入输出序列进行解析,得到其频域上的特性。具体的代码如下:

clear all; close all; clc;


FreqArray = [
    0.1,        1000,   10000,  2;
    0.125,      1000,   8000,   2;
    0.16,       1000,   6250,   2;
    0.2,        1000,   5000,   2;
    0.25,       1000,   4000,   2;
    0.3125,     1000,   3200,   2;
    0.4,        1000,   2500,   2;
    0.5,        1000,   2000,   2;
    0.625,      1000,   1600,   4;
    0.8,        1000,   1250,   4;
    
    1,          5000,   5000,   4;
    1.25,       5000,   4000,   4;
    1.5625,     5000,   3200,   4;
    2,          5000,   2500,   4;
    2.5,        5000,   2000,   4;
    3.125,      5000,   1600,   6;
    4,          5000,   1250,   6;
    5,          5000,   1000,   6;
    6.25,       5000,   800,    6;
    7.8125,     5000,   640,    6;

    
	10,         5000,   500,    10;
    12.5,       5000,   400,    10;
    15.625,     5000,   320,    10;
    20,         5000,   250,    10;
    25,         5000,   200,    10;
    31.25,      5000,   160,    10;
    40,         5000,   125,    10;
    50,         5000,   100,    10;
    62.5,       5000,   80,     10;
    78.125,     5000,   64,     10;
    
	100,        5000,   50,     20;
    125,        5000,   40,     20;
    156.25,     5000,   32,     20;
    200,        5000,   25,     20;
    250,        5000,   20,     20;
    312.5,      5000,   16,     20;
    500,      	5000,   10,     40;
    625,        5000,   8,      40;
    1000,       5000,   5,      40;
       
    ];

FreqNum = length(FreqArray(:,1));

for i=1 : 1 : FreqNum
    if (FreqArray(i, 2) / FreqArray(i, 1)) ~= FreqArray(i, 3)
        %fprintf('%f is wrong!\r\n',FreqArray(i, 1));
    else
        %fprintf('%f is ok!\r\n',FreqArray(i, 1));
    end
end

% 数组总长度
DSP_Array_Length = 10000;

Current_Length = 0;
AllocationResult = zeros(FreqNum,4); 
% 第一列表示频率 % 第二列表示频响数据序号
% 第三列起始位置 % 第四列截至位置
DataIndex = 1;
for i=1 : 1 : FreqNum
    if (Current_Length +  FreqArray(i, 3)) <= DSP_Array_Length
        StartPosition	= Current_Length + 1;        
        Current_Length	= Current_Length +  FreqArray(i, 3);
        StopPosition	= Current_Length;
        
        AllocationResult(i,1)   = FreqArray(i, 1);
        AllocationResult(i,2)   = DataIndex;
        AllocationResult(i,3)   = StartPosition;
        AllocationResult(i,4)   = StopPosition;
        
    elseif FreqArray(i, 3) <= DSP_Array_Length
        DataIndex = DataIndex + 1;
        StartPosition  = 1;
        Current_Length = FreqArray(i, 3);
        StopPosition = Current_Length;
        
        AllocationResult(i,1)   = FreqArray(i, 1);
        AllocationResult(i,2)   = DataIndex;
        AllocationResult(i,3)   = StartPosition;
        AllocationResult(i,4)   = StopPosition;
                
    else
        fprintf('频率点:%f的数据点数超过了DSP的数组总长度 \r\n',FreqArray(i, 1));
    end
end



%-----------------------------------------------------------------------------------
%-----------------------------------------------------------------------------------
% 注意文件头的字节个数
%-----------------------------------------------------------------------------------
%-----------------------------------------------------------------------------------
fid = fopen('DspData/in1.dat');
fseek(fid, 21,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y1 = x{1};
fclose(fid);

fid = fopen('DspData/in2.dat');
fseek(fid, 21,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y2 = x{1};
fclose(fid);

fid = fopen('DspData/in3.dat');
fseek(fid, 21,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y3 = x{1};
fclose(fid);

fid = fopen('DspData/in4.dat');
fseek(fid, 21,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y4 = x{1};
fclose(fid);

fid = fopen('DspData/in5.dat');
fseek(fid, 21,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y5 = x{1};
fclose(fid);

fid = fopen('DspData/in6.dat');
fseek(fid, 21,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y6 = x{1};
fclose(fid);

fid = fopen('DspData/in7.dat');
fseek(fid, 21,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y7 = x{1};
fclose(fid);

fid = fopen('DspData/in8.dat');
fseek(fid, 21,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y8 = x{1};
fclose(fid);

y1 = y1';y2 = y2';y3=y3';y4=y4';y5=y5';y6=y6';y7=y7';y8=y8';

sys_identify_in = [y1;y2;y3;y4;y5;y6;y7;y8];


%-----------------------------------------------------------------------------------
%-----------------------------------------------------------------------------------
% 注意文件头的字节个数
%-----------------------------------------------------------------------------------
%-----------------------------------------------------------------------------------
fid = fopen('DspData/out1.dat');
fseek(fid, 23,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y1 = x{1};
fclose(fid);

fid = fopen('DspData/out2.dat');
fseek(fid, 23,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y2 = x{1};
fclose(fid);

fid = fopen('DspData/out3.dat');
fseek(fid, 23,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y3 = x{1};
fclose(fid);

fid = fopen('DspData/out4.dat');
fseek(fid, 23,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y4 = x{1};
fclose(fid);

fid = fopen('DspData/out5.dat');
fseek(fid, 23,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y5 = x{1};
fclose(fid);

fid = fopen('DspData/out6.dat');
fseek(fid, 23,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y6 = x{1};
fclose(fid);

fid = fopen('DspData/out7.dat');
fseek(fid, 23,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y7 = x{1};
fclose(fid);

fid = fopen('DspData/out8.dat');
fseek(fid, 23,-1);  % 去文件头, 21字节,如 1651 1 80000006 0 100
x = textscan(fid, '%f'); 
y8 = x{1};
fclose(fid);

y1 = y1';y2 = y2';y3=y3';y4=y4';y5=y5';y6=y6';y7=y7';y8=y8';

sys_identify_out = [y1;y2;y3;y4;y5;y6;y7;y8];



FrequencyArray	= zeros(FreqNum,1);
MagnitudeArray	= zeros(FreqNum,1);
PhaseArray      = zeros(FreqNum,1);
for i = 1:1:FreqNum
    In_Signal = sys_identify_in(AllocationResult(i,2), AllocationResult(i,3):1:AllocationResult(i,4));
    Out_Signal = sys_identify_out(AllocationResult(i,2), AllocationResult(i,3):1:AllocationResult(i,4));
    
    InFFT	= fft(In_Signal);
    OutFFT	= fft(Out_Signal);
    
    FrequencyArray(i)   = AllocationResult(i,1);
	MagnitudeArray(i)	= abs(OutFFT(2)/InFFT(2));          % 第一个信号为直流分量 第二个信号为主分量
	PhaseArray(i)       = angle(OutFFT(2)/InFFT(2))/pi*180; % 角度处理为角度制
    
end
obj     = [FrequencyArray, MagnitudeArray, PhaseArray];
save(['MatlabData/','obj','.mat'],'obj');

ObjNum        = 2;
ObjPath       = {'MatlabData/obj.mat','MatlabData/obj1.mat'};
ObjLegend     = {'test','test1'};
ObjTitle      = '频域特性';    
comparison(ObjNum,ObjPath,ObjLegend,ObjTitle);

运行结果如下:

 可以翻一下,前面我们DSP代码中的测试代码就是输出是输入的10倍(20dB)相位相差pi/3(60°)。第一次测试有问题的原因数据解析的问题。

到此为止,DSP无通信接口系统辨识就结束了。 相关代码我会上传备份一手。

DSP无通信接口高效频域辨识-嵌入式文档类资源-CSDN文库

下面给一个直观的辨识视频,舒服

高速电机FOC iq→iq 电流环被控对象辨识

感谢您的阅读,欢迎留言讨论、收藏、点赞、分享。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江湖上都叫我秋博

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值