This commit is contained in:
2026-05-06 19:51:30 +07:00
commit 3958b0edcf
2704 changed files with 410390 additions and 0 deletions
@@ -0,0 +1,21 @@
# ESP-DSP Examples
This directory contains a range of examples for ESP-DSP library.
These examples are intended to demonstrate part of ESP-DSP functionality (e.g. initialization, execution) and to provide code that you can copy and adapt into your own projects.
See the [README.md](../README.md) file in the upper level directory for more information about ESP-DSP.
# Example Layout
The examples are grouped into subdirectories by category. Each category directory contains one or more example projects:
* [Dot Product Calculation](./dotprod/README.md) Example
* [Basic Math Operations](./basic_math/README.md) Example
* [FFT](./fft/README.md) Example
* [Matrix](./matrix/README.md) Example
* [FFT Window](./fft_window/README.md) Example
* [IIR Filter](./iir/README.md) Example
* [Kalman Filter](./kalman/README.md) Example
* [FIR Filter](.fir/README.md) Example
* [2D Convolution](./conv2d//README.md) Example
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(basic_math)
@@ -0,0 +1,75 @@
# Basic Math Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use basic math functions from esp-dsp library. Example does the following steps:
1. Initialize the library
2. Initialize input signals with 1024 samples
3. Apply window to input signal by standard C loop.
4. Calculate FFT for 1024 complex samples and show the result
5. Show results on the plots
6. Apply window to input signal by basic math functions dsps_mul_f32 and dsps_mulc_f32.
7. Calculate FFT for 1024 complex samples
8. Show results on the plots
## How to use example
### Hardware required
This example does not require any special hardware, and can be run on any common development board.
### Configure the project
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
### Build and flash
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example output
Here is an typical example console output.
```bash
I (132) main: *** Start Example. ***
I (132) main: *** Multiply tone signal with Hann window by standard C loop. ***
I (152) view: Data min[432] = -173.749878, Data max[205] = 23.849705
________________________________________________________________
0 | |
1 | |
2 | |
3 || |
4 | | |
5 || | |
6 ||| || |
7 ||||| |||| |
8||||||||||||||| |||||| |
9 |||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (162) view: Plot: Length=512, min=-120.000000, max=40.000000
I (162) main: *** Multiply tone signal with Hann window by esp-dsp basic math functions. ***
I (162) view: Data min[432] = -173.749878, Data max[205] = 23.849705
________________________________________________________________
0 | |
1 | |
2 | |
3 || |
4 | | |
5 || | |
6 ||| || |
7 ||||| |||| |
8||||||||||||||| |||||| |
9 |||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (172) view: Plot: Length=512, min=-120.000000, max=40.000000
I (172) main: *** End Example. ***
```
@@ -0,0 +1 @@
idf_component_register(SRCS "dsps_math_main.c")
@@ -0,0 +1,94 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "soc/gpio_struct.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "soc/uart_struct.h"
#include <math.h>
#include "esp_dsp.h"
static const char *TAG = "main";
// This example shows how to use FFT from esp-dsp library
#define N_SAMPLES 1024
int N = N_SAMPLES;
// Input test array
__attribute__((aligned(16)))
float x1[N_SAMPLES];
// Window coefficients
__attribute__((aligned(16)))
float wind[N_SAMPLES];
// working complex array
__attribute__((aligned(16)))
float y_cf[N_SAMPLES * 2];
// Pointers to result arrays
float *y1_cf = &y_cf[0];
static void process_and_show(float *data, int length)
{
dsps_fft2r_fc32(data, length);
// Bit reverse
dsps_bit_rev_fc32(data, length);
// Convert one complex vector to two complex vectors
dsps_cplx2reC_fc32(data, length);
for (int i = 0 ; i < length / 2 ; i++) {
data[i] = 10 * log10f((data[i * 2 + 0] * data[i * 2 + 0] + data[i * 2 + 1] * data[i * 2 + 1]) / N);
}
// Show power spectrum in 64x10 window from -100 to 0 dB from 0..N/4 samples
dsps_view(data, length / 2, 64, 10, -120, 40, '|');
}
void app_main()
{
esp_err_t ret;
ESP_LOGI(TAG, "*** Start Example. ***");
ret = dsps_fft2r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
return;
}
// Generate Hann window
dsps_wind_hann_f32(wind, N);
ESP_LOGI(TAG, "*** Multiply tone signal with Hann window by standard C loop. ***");
// Generate input signal
dsps_tone_gen_f32(x1, N, 1., 0.2, 0);
// Convert two input vectors to one complex vector
for (int i = 0 ; i < N ; i++) {
y_cf[i * 2 + 0] = x1[i] * wind[i];
y_cf[i * 2 + 1] = 0;
}
process_and_show(y_cf, N);
ESP_LOGI(TAG, "*** Multiply tone signal with Hann window by esp-dsp basic math functions. ***");
// Convert two input vectors to one complex vector with basic functions
dsps_mul_f32(x1, wind, y_cf, N, 1, 1, 2); // Multiply input array with window and store as real part
dsps_mulc_f32(&y_cf[1], &y_cf[1], N, 0, 2, 2); // Clear imaginary part of the complex signal
process_and_show(y_cf, N);
ESP_LOGI(TAG, "*** End Example. ***");
}
@@ -0,0 +1,3 @@
dependencies:
espressif/esp-dsp:
version: '*'
@@ -0,0 +1 @@
CONFIG_PARTITION_TABLE_OFFSET=0x9000
@@ -0,0 +1,6 @@
# The following five lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(conv2d)
@@ -0,0 +1,57 @@
# 2D convolution Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use 2D convolution dspi_conv_f32 from esp-dsp library. Example does the following steps:
1. Initialize the input arrays
2. Calculate 2D convolution of two images
The example reproduce the Matlab code:
```
A = ones(8);
B = ones(4);
Csame = conv2(A,B, "same")
```
## How to use example
### Hardware required
This example does not require any special hardware, and can be run on any common development board.
### Configure the project
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
### Build and flash
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example output
Here is an typical example console output.
```
I (305) main: Start Example.
I (305) main: 2D Convolution result.
[ 0 .. 8, 0]: 9, 12, 12, 12, 12, 12, 9, 6,
[ 0 .. 8, 1]: 12, 16, 16, 16, 16, 16, 12, 8,
[ 0 .. 8, 2]: 12, 16, 16, 16, 16, 16, 12, 8,
[ 0 .. 8, 3]: 12, 16, 16, 16, 16, 16, 12, 8,
[ 0 .. 8, 4]: 12, 16, 16, 16, 16, 16, 12, 8,
[ 0 .. 8, 5]: 12, 16, 16, 16, 16, 16, 12, 8,
[ 0 .. 8, 6]: 9, 12, 12, 12, 12, 12, 9, 6,
[ 0 .. 8, 7]: 6, 8, 8, 8, 8, 8, 6, 4,
```
@@ -0,0 +1,2 @@
idf_component_register(SRCS "conv2d_main.c"
INCLUDE_DIRS ".")
@@ -0,0 +1,55 @@
#include <stdio.h>
#include <malloc.h>
#include "esp_dsp.h"
#include "dsp_tests.h"
static const char *TAG = "main";
void app_main(void)
{
ESP_LOGI(TAG, "Start Example.");
int max_N = 100;
float *data1 = (float *)memalign(16, max_N * sizeof(float));
float *data2 = (float *)memalign(16, max_N * sizeof(float));
float *data3 = (float *)memalign(16, max_N * sizeof(float));
image2d_t image1 = {data1, 1, 1, 8, 8, 8, 8}; // Image 8x8
image2d_t image2 = {data2, 1, 1, 4, 4, 4, 4}; // Image 4x4
image2d_t image3 = {data3, 1, 1, 10, 10, 0, 0}; // Image 10x10
for (int i = 0 ; i < max_N ; i++) {
data1[i] = 0;
data2[i] = 0;
data3[i] = 0;
}
for (int y = 0 ; y < image1.stride_y / image1.step_y ; y++) {
for (int x = 0 ; x < image1.stride_x / image1.step_x ; x++) {
data1[y * image1.stride_x * image1.step_y + x * image1.step_x] = 1;
}
}
for (int y = 0 ; y < image2.stride_y / image2.step_y ; y++) {
for (int x = 0 ; x < image2.stride_x / image2.step_x ; x++) {
data2[y * image2.stride_x * image2.step_y + x * image2.step_x] = 1;
}
}
dspi_conv_f32(&image1, &image2, &image3);
ESP_LOGI(TAG, "2D Convolution result.");
for (int y = 0 ; y < image3.size_y; y++) {
printf("[%2i .. %2i, %2i]: ", 0, image3.size_x, y);
for (int x = 0 ; x < image3.size_x; x++) {
printf("%2.0f, ", data3[y * image3.stride_x * image3.step_y + x * image3.step_x]);
}
printf("\n");
}
free(data1);
free(data2);
free(data3);
}
@@ -0,0 +1,3 @@
dependencies:
espressif/esp-dsp:
version: '*'
@@ -0,0 +1,4 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) 5.4.0 Project Minimal Configuration
#
CONFIG_PARTITION_TABLE_OFFSET=0x9000
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(dotprod)
@@ -0,0 +1,42 @@
# Dot Product Calculation Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use dotprod dsps_dotprod_f32 from esp-dsp library. Example does the following steps:
1. Initialize the input arrays
2. Calculate dot product of two arrays
3. Compare results and calculate execution time in cycles.
## How to use example
### Hardware required
This example does not require any special hardware, and can be run on any common development board.
### Configure the project
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
### Build and flash
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example output
Here is an typical example console output.
```
I (55) main: Start Example.
I (55) main: The sum of 101 elements from 0..100 = 5050.000000
I (55) main: Operation for 101 samples took 1381 cycles
I (65) main: End Example.
```
@@ -0,0 +1 @@
idf_component_register(SRCS "dsps_dotproduct_main.c")
@@ -0,0 +1,63 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "soc/gpio_struct.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "soc/uart_struct.h"
#include "esp_dsp.h"
static const char *TAG = "main";
// This example shows how to use dsps_dotprod_f32 and dsps_dotprode_f32 functions
#define N_SAMPLES 256
int N = N_SAMPLES;
__attribute__((aligned(16)))
float input1[N_SAMPLES];
__attribute__((aligned(16)))
float input2[N_SAMPLES];
void app_main()
{
esp_err_t ret;
ESP_LOGI(TAG, "Start Example.");
// The example will calculate n!
//Initialize an input arrays
for (int i = 0 ; i < N ; i++) {
input1[i] = 1;
input2[i] = i;
}
float result1 = 0;
unsigned int start_b = dsp_get_cpu_cycle_count();
ret = dsps_dotprod_f32(input1, input2, &result1, 101);
unsigned int end_b = dsp_get_cpu_cycle_count();
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Operation error = %i", ret);
}
ESP_LOGI(TAG, "The sum of 101 elements from 0..100 = %f", result1);
ESP_LOGI(TAG, "Operation for 101 samples take %i cycles", end_b - start_b);
ESP_LOGI(TAG, "End Example.");
}
@@ -0,0 +1,3 @@
dependencies:
espressif/esp-dsp:
version: '*'
@@ -0,0 +1 @@
CONFIG_PARTITION_TABLE_OFFSET=0x9000
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(fft2r)
@@ -0,0 +1,91 @@
# FFT Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use FFT functionality from esp-dsp library. Example does the following steps:
1. Initialize the library
2. Initialize input signals with 1024 samples: one 0 dB, second with -20 dB
3. Combine two signals as one complex input signal and apply window to input signals paar.
4. Calculate FFT for 1024 complex samples
5. Apply bit reverse operation for output complex vector
6. Split one complex FFT output spectrum to two real signal spectrums
7. Show results on the plots
8. Show execution time of FFT
## How to use example
### Hardware required
This example does not require any special hardware, and can be run on any common development board.
### Configure the project
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
### Build and flash
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example output
Here is an typical example console output.
```
I (59) main: Start Example.
W (89) main: Signal x1
I (89) view: Data min[495] = -162.760925, Data max[164] = 23.938747
________________________________________________________________
0 |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | | |
7 | | |
8 || || |
9|||||||||||||||||| ||||||||||||||||||||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (159) view: Plot: Length=512, min=-60.000000, max=40.000000
W (169) main: Signal x2
I (169) view: Data min[502] = -164.545135, Data max[205] = 3.857752
________________________________________________________________
0 |
1 |
2 |
3 | |
4 | |
5 | |
6 | |
7 || |
8 | | |
9|||||||||||||||||||||||| ||||||||||||||||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (249) view: Plot: Length=512, min=-60.000000, max=40.000000
W (249) main: Signals x1 and x2 on one plot
I (259) view: Data min[505] = -159.215271, Data max[164] = 23.938747
________________________________________________________________
0 |
1 | |
2 | |
3 | | |
4 | | |
5 | | |
6 | | | |
7 | | || |
8 || || | | |
9|||||||||||||||||| | ||||||||||||||||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (339) view: Plot: Length=512, min=-60.000000, max=40.000000
I (339) main: FFT for 1024 complex points take 140472 cycles
I (349) main: End Example.
```
@@ -0,0 +1 @@
idf_component_register(SRCS "dsps_fft_main.c")
@@ -0,0 +1,104 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "soc/gpio_struct.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "soc/uart_struct.h"
#include <math.h>
#include "esp_dsp.h"
static const char *TAG = "main";
// This example shows how to use FFT from esp-dsp library
#define N_SAMPLES 1024
int N = N_SAMPLES;
// Input test array
__attribute__((aligned(16)))
float x1[N_SAMPLES];
__attribute__((aligned(16)))
float x2[N_SAMPLES];
// Window coefficients
__attribute__((aligned(16)))
float wind[N_SAMPLES];
// working complex array
__attribute__((aligned(16)))
float y_cf[N_SAMPLES * 2];
// Pointers to result arrays
float *y1_cf = &y_cf[0];
float *y2_cf = &y_cf[N_SAMPLES];
// Sum of y1 and y2
__attribute__((aligned(16)))
float sum_y[N_SAMPLES / 2];
void app_main()
{
esp_err_t ret;
ESP_LOGI(TAG, "Start Example.");
ret = dsps_fft2r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
return;
}
// Generate hann window
dsps_wind_hann_f32(wind, N);
// Generate input signal for x1 A=1 , F=0.1
dsps_tone_gen_f32(x1, N, 1.0, 0.16, 0);
// Generate input signal for x2 A=0.1,F=0.2
dsps_tone_gen_f32(x2, N, 0.1, 0.2, 0);
// Convert two input vectors to one complex vector
for (int i = 0 ; i < N ; i++) {
y_cf[i * 2 + 0] = x1[i] * wind[i];
y_cf[i * 2 + 1] = x2[i] * wind[i];
}
// FFT
unsigned int start_b = dsp_get_cpu_cycle_count();
dsps_fft2r_fc32(y_cf, N);
unsigned int end_b = dsp_get_cpu_cycle_count();
// Bit reverse
dsps_bit_rev_fc32(y_cf, N);
// Convert one complex vector to two complex vectors
dsps_cplx2reC_fc32(y_cf, N);
for (int i = 0 ; i < N / 2 ; i++) {
y1_cf[i] = 10 * log10f((y1_cf[i * 2 + 0] * y1_cf[i * 2 + 0] + y1_cf[i * 2 + 1] * y1_cf[i * 2 + 1]) / N);
y2_cf[i] = 10 * log10f((y2_cf[i * 2 + 0] * y2_cf[i * 2 + 0] + y2_cf[i * 2 + 1] * y2_cf[i * 2 + 1]) / N);
// Simple way to show two power spectrums as one plot
sum_y[i] = fmax(y1_cf[i], y2_cf[i]);
}
// Show power spectrum in 64x10 window from -100 to 0 dB from 0..N/4 samples
ESP_LOGW(TAG, "Signal x1");
dsps_view(y1_cf, N / 2, 64, 10, -60, 40, '|');
ESP_LOGW(TAG, "Signal x2");
dsps_view(y2_cf, N / 2, 64, 10, -60, 40, '|');
ESP_LOGW(TAG, "Signals x1 and x2 on one plot");
dsps_view(sum_y, N / 2, 64, 10, -60, 40, '|');
ESP_LOGI(TAG, "FFT for %i complex points take %i cycles", N, end_b - start_b);
ESP_LOGI(TAG, "End Example.");
}
@@ -0,0 +1,3 @@
dependencies:
espressif/esp-dsp:
version: '*'
@@ -0,0 +1 @@
CONFIG_PARTITION_TABLE_OFFSET=0x9000
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(fft4real)
@@ -0,0 +1,91 @@
# FFT 4 Real Input Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use FFT functionality from esp-dsp library. Example does the following steps:
1. Initialize the library
2. Initialize input signals with 1024 samples: one 0 dB, second with -20 dB
3. Calculate FFT Radix-2 for 1024 complex samples
4. Calculate FFT Radix-4 for 1024 complex samples
5. Apply bit reverse operation for output complex vectors
6. Show results on the plots
7. Show execution time of FFTs
## How to use example
### Hardware required
This example does not require any special hardware, and can be run on any common development board.
### Configure the project
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
### Build and flash
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example output
Here is an typical example console output.
```
I (344) main: Start Example.
W (424) main: Signal x1
I (424) view: Data min[673] = -103.113297, Data max[328] = 20.490950
________________________________________________________________
0 |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | | |
8 | | |
9||||||||||||||||||| |||||||||||||||||||||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (494) view: Plot: Length=1024, min=-60.000000, max=40.000000
W (504) main: Signal x2
I (504) view: Data min[582] = -103.113297, Data max[328] = 20.490950
________________________________________________________________
0 |
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | | |
8 | | |
9||||||||||||||||||| |||||||||||||||||||||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (584) view: Plot: Length=1024, min=-60.000000, max=40.000000
W (593) main: Difference between signals x1 and x2 on one plot
I (594) view: Data min[0] = 0.000000, Data max[392] = 0.313019
________________________________________________________________
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8----------------------------------------------------------------|
9 |
0123456789012345678901234567890123456789012345678901234567890123
I (674) view: Plot: Length=1024, min=0.000000, max=40.000000
I (674) main: FFT Radix 2 for 1024 complex points take 168652 cycles
I (684) main: FFT Radix 4 for 1024 complex points take 104665 cycles
I (694) main: End Example.
```
@@ -0,0 +1 @@
idf_component_register(SRCS "dsps_fft4real_main.c")
@@ -0,0 +1,115 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "soc/gpio_struct.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "soc/uart_struct.h"
#include <math.h>
#include "esp_dsp.h"
static const char *TAG = "main";
// This example shows how to use FFT from esp-dsp library
#define N_SAMPLES 2048 // Amount of real input samples
int N = N_SAMPLES;
// Input test array
__attribute__((aligned(16)))
float x1[N_SAMPLES];
__attribute__((aligned(16)))
float x2[N_SAMPLES];
// Window coefficients
__attribute__((aligned(16)))
float wind[N_SAMPLES];
// Pointers to result arrays
float *y1_cf = &x1[0];
float *y2_cf = &x2[0];
// diff of y1 and y2
__attribute__((aligned(16)))
float diff_y[N_SAMPLES / 2];
void app_main()
{
esp_err_t ret;
ESP_LOGI(TAG, "Start Example.");
ret = dsps_fft2r_init_fc32(NULL, N >> 1);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Not possible to initialize FFT2R. Error = %i", ret);
return;
}
ret = dsps_fft4r_init_fc32(NULL, N >> 1);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Not possible to initialize FFT4R. Error = %i", ret);
return;
}
// Generate hann window
dsps_wind_hann_f32(wind, N);
// Generate input signal for x1 A=1 , F=0.1
dsps_tone_gen_f32(x1, N, 1.0, 0.16, 0);
// Convert two input vectors to one complex vector
for (int i = 0 ; i < N ; i++) {
x1[i] = x1[i] * wind[i];
x2[i] = x1[i];
}
// FFT Radix-2
unsigned int start_r2 = dsp_get_cpu_cycle_count();
dsps_fft2r_fc32(x1, N >> 1);
// Bit reverse
dsps_bit_rev2r_fc32(x1, N >> 1);
// Convert one complex vector with length N/2 to one real spectrum vector with length N/2
dsps_cplx2real_fc32(x1, N >> 1);
unsigned int end_r2 = dsp_get_cpu_cycle_count();
// FFT Radix-4
unsigned int start_r4 = dsp_get_cpu_cycle_count();
dsps_fft4r_fc32(x2, N >> 1);
// Bit reverse
dsps_bit_rev4r_fc32(x2, N >> 1);
// Convert one complex vector with length N/2 to one real spectrum vector with length N/2
dsps_cplx2real_fc32(x2, N >> 1);
unsigned int end_r4 = dsp_get_cpu_cycle_count();
for (int i = 0 ; i < N / 2 ; i++) {
x1[i] = 10 * log10f((x1[i * 2 + 0] * x1[i * 2 + 0] + x1[i * 2 + 1] * x1[i * 2 + 1] + 0.0000001) / N);
x2[i] = 10 * log10f((x2[i * 2 + 0] * x2[i * 2 + 0] + x2[i * 2 + 1] * x2[i * 2 + 1] + 0.0000001) / N);
// Simple way to show two power spectrums as one plot
diff_y[i] = fabs(x1[i] - x2[i]);
}
// Show power spectrum in 64x10 window from -100 to 0 dB from 0..N/4 samples
ESP_LOGW(TAG, "Signal x1");
dsps_view(x1, N / 2, 64, 10, -60, 40, '|');
ESP_LOGW(TAG, "Signal x2");
dsps_view(x2, N / 2, 64, 10, -60, 40, '|');
ESP_LOGW(TAG, "Difference between signals x1 and x2 on one plot");
dsps_view(diff_y, N / 2, 64, 10, 0, 40, '-');
ESP_LOGI(TAG, "FFT Radix 2 for %i complex points take %i cycles", N / 2, end_r2 - start_r2);
ESP_LOGI(TAG, "FFT Radix 4 for %i complex points take %i cycles", N / 2, end_r4 - start_r4);
ESP_LOGI(TAG, "End Example.");
}
@@ -0,0 +1,3 @@
dependencies:
espressif/esp-dsp:
version: '*'
@@ -0,0 +1,9 @@
[mapping:dsp]
archive: libdsp.a
entries:
* (noflash)
[mapping:esp-dsp]
archive: libesp-dsp.a
entries:
* (noflash)
@@ -0,0 +1 @@
CONFIG_PARTITION_TABLE_OFFSET=0x9000
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(fft_window)
@@ -0,0 +1,134 @@
# FFT Window Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use Window and FFT functionality from esp-dsp library. Example does the following steps:
1. Initialize the library
2. Initialize input signals with 1024 samples
3. Apply window to input signal.
4. Calculate FFT for 1024 complex samples
5. Apply bit reverse operation for output complex vector
6. Split one complex FFT output spectrum to two real signal spectrums
7. Show results on the plots
## How to use example
### Hardware required
This example does not require any special hardware, and can be run on any common development board.
### Configure the project
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
### Build and flash
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example output
Here is an typical example console output.
```
I (128) main: Start Example.
W (128) main: Hann Window
I (128) view: Data min[256] = -inf, Data max[1] = 24.086628
________________________________________________________________
0| |
1| |
2| |
3| |
4| |
5 | |
6 | |
7 ||||| |
8 ||||||||||||||| |
9 ||||||||||||||||||||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (138) view: Plot: Length=512, min=-120.000000, max=40.000000
W (138) main: Blackman Window
I (148) view: Data min[355] = -165.295654, Data max[1] = 24.083012
________________________________________________________________
0| |
1| |
2| |
3| |
4| |
5| |
6 | |
7 ||| |
8 ||||||||| |
9 |||||||||||||||||||||||||||||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (158) view: Plot: Length=512, min=-120.000000, max=40.000000
W (158) main: Blackman-Harris Window
I (168) view: Data min[128] = -inf, Data max[1] = 23.874702
________________________________________________________________
0| |
1| |
2| |
3| |
4| |
5| |
6| |
7|| |
8| |||| |
9 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (178) view: Plot: Length=512, min=-120.000000, max=40.000000
W (178) main: Blackman-Nuttall Window
I (188) view: Data min[128] = -inf, Data max[1] = 23.890663
________________________________________________________________
0| |
1| |
2| |
3| |
4| |
5| |
6| |
7 || |
8 |||| | |
9 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (198) view: Plot: Length=512, min=-120.000000, max=40.000000
W (198) main: Nuttall Window
I (208) view: Data min[203] = -175.147400, Data max[1] = 23.858671
________________________________________________________________
0| |
1| |
2| |
3| |
4| |
5| |
6| |
7|| |
8 ||| |
9 ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (218) view: Plot: Length=512, min=-120.000000, max=40.000000
W (218) main: Flat-Top Window
I (228) view: Data min[256] = -inf, Data max[1] = 22.490753
________________________________________________________________
0| |
1| |
2| |
3| |
4| |
5| |
6| |
7 || |
8 ||||| |
9 |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
0123456789012345678901234567890123456789012345678901234567890123
I (238) view: Plot: Length=512, min=-120.000000, max=40.000000
I (238) main: End Example.
```
@@ -0,0 +1 @@
idf_component_register(SRCS "dsps_window_main.c")
@@ -0,0 +1,138 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "soc/gpio_struct.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "soc/uart_struct.h"
#include <math.h>
#include "esp_dsp.h"
static const char *TAG = "main";
// This example shows how to use FFT from esp-dsp library
#define N_SAMPLES 1024
int N = N_SAMPLES;
// Input test array
__attribute__((aligned(16)))
float x1[N_SAMPLES];
// Window coefficients
__attribute__((aligned(16)))
float wind[N_SAMPLES];
// working complex array
__attribute__((aligned(16)))
float y_cf[N_SAMPLES * 2];
// Pointers to result arrays
__attribute__((aligned(16)))
float *y1_cf = &y_cf[0];
void process_and_show(float *data, int length)
{
dsps_fft2r_fc32(data, length);
// Bit reverse
dsps_bit_rev_fc32(data, length);
// Convert one complex vector to two complex vectors
dsps_cplx2reC_fc32(data, length);
for (int i = 0 ; i < length / 2 ; i++) {
data[i] = 10 * log10f((data[i * 2 + 0] * data[i * 2 + 0] + data[i * 2 + 1] * data[i * 2 + 1]) / N);
}
// Show power spectrum in 64x10 window from -100 to 0 dB from 0..N/4 samples
dsps_view(data, length / 2, 64, 10, -120, 40, '|');
}
void app_main()
{
esp_err_t ret;
ESP_LOGI(TAG, "Start Example.");
ret = dsps_fft2r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
return;
}
ESP_LOGW(TAG, "Hann Window");
// Generate Hann window
dsps_wind_hann_f32(wind, N);
// Convert two input vectors to one complex vector
for (int i = 0 ; i < N ; i++) {
y_cf[i * 2 + 0] = wind[i];
y_cf[i * 2 + 1] = 0;
}
process_and_show(y_cf, N);
ESP_LOGW(TAG, "Blackman Window");
// Generate Blackman window
dsps_wind_blackman_f32(wind, N);
// Convert two input vectors to one complex vector
for (int i = 0 ; i < N ; i++) {
y_cf[i * 2 + 0] = wind[i];
y_cf[i * 2 + 1] = 0;
}
process_and_show(y_cf, N);
ESP_LOGW(TAG, "Blackman-Harris Window");
// Generate Blackman-Harris window
dsps_wind_blackman_harris_f32(wind, N);
// Convert two input vectors to one complex vector
for (int i = 0 ; i < N ; i++) {
y_cf[i * 2 + 0] = wind[i];
y_cf[i * 2 + 1] = 0;
}
process_and_show(y_cf, N);
ESP_LOGW(TAG, "Blackman-Nuttall Window");
// Generate Blackman-Nuttall window
dsps_wind_blackman_nuttall_f32(wind, N);
// Convert two input vectors to one complex vector
for (int i = 0 ; i < N ; i++) {
y_cf[i * 2 + 0] = wind[i];
y_cf[i * 2 + 1] = 0;
}
process_and_show(y_cf, N);
ESP_LOGW(TAG, "Nuttall Window");
// Generate Nuttall window
dsps_wind_nuttall_f32(wind, N);
// Convert two input vectors to one complex vector
for (int i = 0 ; i < N ; i++) {
y_cf[i * 2 + 0] = wind[i];
y_cf[i * 2 + 1] = 0;
}
process_and_show(y_cf, N);
ESP_LOGW(TAG, "Flat-Top Window");
// Generate Flat-Top window
dsps_wind_flat_top_f32(wind, N);
// Convert two input vectors to one complex vector
for (int i = 0 ; i < N ; i++) {
y_cf[i * 2 + 0] = wind[i];
y_cf[i * 2 + 1] = 0;
}
process_and_show(y_cf, N);
ESP_LOGI(TAG, "End Example.");
}
@@ -0,0 +1,3 @@
dependencies:
espressif/esp-dsp:
version: '*'
@@ -0,0 +1 @@
CONFIG_PARTITION_TABLE_OFFSET=0x9000
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(fir)
@@ -0,0 +1,87 @@
# FIR Filter Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use FIR filter functionality from esp-dsp library. Example does the following steps:
1. Initialize the FFT library
2. Initialize input signal
* 1st Sine wave (f = 0.2Fs)
* 2nd Sine wave (f = 0.4Fs)
* Combine the waves
3. Show input signal
* Calculate windows coefficients
* Apply the windowing to the input signal
* Do the FFT
* Show the frequency response on a plot
* Calculate execution performance
4. Show filtered signal
* Initialize the FIR filter library
* Calculate Windowed-Sinc coefficients of FIR filter
* Apply the FIR filter to the input signal
* Do the FFT
* Show the frequency response on a plot
* Calculate execution performance
## How to use the example
### Hardware required
This example does not require any special hardware, and can be run on any common development board.
### Configure the project
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
### Build and flash
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example output
Here is a typical example of console output.
```
I (340) main: Start Example.
I (400) view: Data min[388] = -108.419342, Data max[205] = 30.267143
________________________________________________________________
0 | | |
1 | || |
2 || || |
3 || || |
4 || || |
5 || ||| |
6 || || | | |
7|||||||||||||||||||||||| |||||||||||||||||||||| ||||||||||||
8 |
9 |
0123456789012345678901234567890123456789012345678901234567890123
I (470) view: Plot: Length=512, min=-120.000000, max=40.000000
I (490) view: Data min[254] = -114.853371, Data max[205] = 27.247583
________________________________________________________________
0 | |
1 | |
2 | |
3 | | |
4 | | |
5 | | |
6 | ||| ||| |
7||||||||||||||||||||||||||||||||||||||||||||||| | ||||| |
8 |||||
9 |
0123456789012345678901234567890123456789012345678901234567890123
I (560) view: Plot: Length=256, min=-120.000000, max=40.000000
I (560) main: FIR for 1024 samples and decimation 2 takes 763647 cycles
I (570) main: End Example.
```
@@ -0,0 +1 @@
idf_component_register(SRCS "dsps_fir_main.c")
@@ -0,0 +1,167 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "soc/gpio_struct.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "soc/uart_struct.h"
#include <math.h>
#include <malloc.h>
#include "esp_dsp.h"
static const char *TAG = "main";
// This example shows how to use FIR filters from esp-dsp library
#define FIR_COEFFS_LEN 64 // Number of FIR filter coefficients
#define DECIMATION 2 // Decimation ratio of the FIR filter
#define N_SAMPLES 1024 // Input samples
#define FIR_DELAY (FIR_COEFFS_LEN / DECIMATION) // Amount of samples not being considered for the FFT
#define FIR_BUFF_OUT_LEN (N_SAMPLES + FIR_DELAY) // Total length of samples
// Function shows the result of the FIR filter
void show_FFT(float *input_signal, const unsigned int fft_len)
{
dsps_fft2r_fc32(input_signal, fft_len >> 1);
dsps_bit_rev2r_fc32(input_signal, fft_len >> 1);
dsps_cplx2real_fc32(input_signal, fft_len >> 1);
// Correction factor for the FFT spectrum
const float correction_factor = fft_len * 3;
// Calculating power of spectrum in dB
for (int i = 0 ; i < fft_len / 2 ; i++) {
input_signal[i] = 10 * log10f((input_signal[i * 2 + 0] * input_signal[i * 2 + 0] + input_signal[i * 2 + 1] * input_signal[i * 2 + 1] + 0.0000001) / correction_factor);
}
// Display power spectrum
dsps_view(input_signal, fft_len / 2, 64, 10, -120, 40, '|');
}
// Generate Windowed-Sinc filter coefficients
void generate_FIR_coefficients(float *fir_coeffs, const unsigned int fir_len, const float ft)
{
// Even or odd length of the FIR filter
const bool is_odd = (fir_len % 2) ? (true) : (false);
const float fir_order = (float)(fir_len - 1);
// Window coefficients
float *fir_window = (float *)malloc(fir_len * sizeof(float));
dsps_wind_blackman_f32(fir_window, fir_len);
for (int i = 0; i < fir_len; i++) {
if ((i == fir_order / 2) && (is_odd)) {
fir_coeffs[i] = 2 * ft;
} else {
fir_coeffs[i] = sinf((2 * M_PI * ft * (i - fir_order / 2))) / (M_PI * (i - fir_order / 2));
}
fir_coeffs[i] *= fir_window[i];
}
free(fir_window);
}
static __attribute__((aligned(16))) float tone_combined[FIR_BUFF_OUT_LEN];
static __attribute__((aligned(16))) float fir_coeffs[FIR_COEFFS_LEN];
static __attribute__((aligned(16))) float delay_line[FIR_COEFFS_LEN];
void app_main()
{
const int32_t fir_len = FIR_COEFFS_LEN;
const float fir_ft = 0.5 / DECIMATION; // Transition frequency of the FIR filter
const int32_t N = N_SAMPLES; // Number of input samples
const int32_t fir_decim = DECIMATION; // FIR filter decimation
const int32_t N_buff = FIR_BUFF_OUT_LEN; // Total length of samples with ignored
fir_f32_t fir1;
esp_err_t ret;
// Ignoring the first set of samples, due to the delay line of the FIR filter
const int fir_out_offset = ((FIR_DELAY / 2) - 1);
ESP_LOGI(TAG, "Start Example.");
// If a user doesn't care about buffer allocation, the default
// initialization could be used as shown here:
ret = dsps_fft2r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
return;
}
ret = dsps_fft4r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
return;
}
// Generate input signal as 2 sine waves
float *tone_1 = (float *)malloc(N_buff * sizeof(float));
float *tone_2 = (float *)malloc(N_buff * sizeof(float));
dsps_tone_gen_f32(tone_1, N_buff, 5, 0.2, 0);
dsps_tone_gen_f32(tone_2, N_buff, 5, 0.4, 0);
// Generate windowing coefficients
float *window = (float *)malloc(N * sizeof(float));
dsps_wind_blackman_harris_f32(window, N);
// Add the two waves together
for (int i = 0 ; i < N_buff ; i++) {
tone_combined[i] = tone_1[i] + tone_2[i];
}
free(tone_1);
free(tone_2);
// Apply the windowing
for (int i = 0 ; i < N ; i++) {
window[i] *= tone_combined[i];
}
// Show FFT spectrum
show_FFT(window, N);
// Calculate coefficients for the FIR filter
generate_FIR_coefficients(fir_coeffs, fir_len, fir_ft);
ESP_LOGI(TAG, "\n");
// Filter the input signal with FIR filter
float *fir_out = (float *)malloc( N_buff * sizeof(float));
dsps_fird_init_f32(&fir1, fir_coeffs, delay_line, fir_len, fir_decim);
uint32_t start_b = dsp_get_cpu_cycle_count();
dsps_fird_f32(&fir1, tone_combined, fir_out, N_buff / fir_decim);
uint32_t end_b = dsp_get_cpu_cycle_count();
// Generate windowing coefficients and apply the windowing
dsps_wind_blackman_harris_f32(window, (N / fir_decim));
for (int i = 0 ; i < N / fir_decim ; i++) {
window[i] *= fir_out[fir_out_offset + i];
}
// Show FFT spectrum, ignoring first samples from the delay line
show_FFT(window, N / fir_decim);
ESP_LOGI(TAG, "FIR for %"PRId32" samples and decimation %"PRId32" takes %"PRId32" cycles", N, fir_decim, (int32_t)(end_b - start_b));
ESP_LOGI(TAG, "End Example.");
free(fir_out);
free(window);
}
@@ -0,0 +1,3 @@
dependencies:
espressif/esp-dsp:
version: '*'
@@ -0,0 +1 @@
CONFIG_PARTITION_TABLE_OFFSET=0x9000
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(iir)
@@ -0,0 +1,107 @@
# IIR Filter Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use IIR filters functionality from esp-dsp library. Example does the following steps:
1. Initialize the library
2. Initialize input signal
3. Show LPF filter with Q factor 1
* Calculate iir filter coefficients
* Filter the input test signal (delta function)
* Shows impulse response on the plot
* Shows frequency response on the plot
* Calculate execution performance
4. The same for LPF filter with Q factor 10
## How to use example
### Hardware required
This example does not require any special hardware, and can be run on any common development board.
### Configure the project
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
### Build and flash
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example output
Here is an typical example console output.
```
I (58) main: Start Example.
I (58) main: Impulse response of IIR filter with F=0.100000, qFactor=1.000000
I (68) view: Data min[8] = -0.060052, Data max[2] = 0.333517
________________________________________________________________
0 |
1 |
2 - |
3- - |
4 -------------------------------------------------------------|
5 |
6 |
7 |
8 |
9 |
0123456789012345678901234567890123456789012345678901234567890123
I (138) view: Plot: Length=128, min=-1.000000, max=1.000000
I (148) view: Data min[511] = -149.983795, Data max[0] = 0.000000
________________________________________________________________
0 |
1 |
2----------------- |
3 ---------- |
4 ------------- |
5 ---------- |
6 ------- |
7 --- |
8 -- |
9 --|
0123456789012345678901234567890123456789012345678901234567890123
I (228) view: Plot: Length=512, min=-100.000000, max=0.000000
I (228) main: IIR for 1024 samples take 20276 cycles
I (238) main: Impulse response of IIR filter with F=0.100000, qFactor=10.000000
I (248) view: Data min[7] = -0.453739, Data max[2] = 0.526114
________________________________________________________________
0 |
1 |
2 - - |
3- - - - --- --- - - |
4- - - - - ---- -------------------------------------|
5 -- -- -- -- |
6 |
7 |
8 |
9 |
0123456789012345678901234567890123456789012345678901234567890123
I (318) view: Plot: Length=128, min=-1.000000, max=1.000000
I (328) view: Data min[511] = -149.480377, Data max[0] = 0.000000
________________________________________________________________
0 -- |
1 -- - |
2---------- ----- |
3 -------- |
4 ------------ |
5 ---------- |
6 ------- |
7 --- |
8 -- |
9 --|
0123456789012345678901234567890123456789012345678901234567890123
I (408) view: Plot: Length=512, min=-100.000000, max=0.000000
I (408) main: IIR for 1024 samples take 17456 cycles
I (418) main: End Example.
```
@@ -0,0 +1 @@
idf_component_register(SRCS "dsps_iir_main.c")
@@ -0,0 +1,111 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "driver/spi_master.h"
#include "soc/gpio_struct.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "soc/uart_struct.h"
#include <math.h>
#include "esp_dsp.h"
static const char *TAG = "main";
// This example shows how to use iir filters from esp-dsp library
#define N_SAMPLES 1024
int N = N_SAMPLES;
// Input test array
__attribute__((aligned(16)))
float d[N_SAMPLES];
// output array
__attribute__((aligned(16)))
float y[N_SAMPLES];
__attribute__((aligned(16)))
float y_cf[N_SAMPLES * 2];
// Function shows result of IIR filter
void ShowIIRfilter(float freq, float qFactor)
{
esp_err_t ret = ESP_OK;
float coeffs_lpf[5];
float w_lpf[5] = {0, 0};
// Calculate iir filter coefficients
ret = dsps_biquad_gen_lpf_f32(coeffs_lpf, freq, qFactor);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Operation error = %i", ret);
return;
}
// Process input signal
unsigned int start_b = dsp_get_cpu_cycle_count();
ret = dsps_biquad_f32(d, y, N, coeffs_lpf, w_lpf);
unsigned int end_b = dsp_get_cpu_cycle_count();
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Operation error = %i", ret);
return;
}
// Show result as a plot
ESP_LOGI(TAG, "Impulse response of IIR filter with F=%f, qFactor=%f", freq, qFactor);
dsps_view(y, 128, 64, 10, -1, 1, '-');
// Show result as frequency response on the plot
for (int i = 0 ; i < N ; i++) {
y_cf[i * 2 + 0] = y[i];
y_cf[i * 2 + 1] = 0;
}
// We making FFT transform
dsps_fft2r_fc32_ansi(y_cf, N);
// Bit reverse
dsps_bit_rev_fc32_ansi(y_cf, N);
// Calculating power of spectrum in dB
for (int i = 0 ; i < N / 2 ; i++) {
y_cf[i] = 10 * log10f((y_cf[i * 2 + 0] * y_cf[i * 2 + 0] + y_cf[i * 2 + 1] * y_cf[i * 2 + 1]) / N);
}
// Show power spectrum in 64x10 window from -100 to 0 dB from 0..N/2 samples
dsps_view(y_cf, N / 2, 64, 10, -100, 0, '-');
ESP_LOGI(TAG, "IIR for %i samples take %i cycles", N, end_b - start_b);
}
void app_main()
{
esp_err_t ret;
ESP_LOGI(TAG, "Start Example.");
// If user don't care about buffer allocation, the default
// initialization could be used as shown here:
ret = dsps_fft2r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "Not possible to initialize FFT. Error = %i", ret);
return;
}
// Initialize input signal
// Generate d function as input signal
dsps_d_gen_f32(d, N, 0);
// Show filter with Q factor 1
ShowIIRfilter(0.1, 1);
// Show filter with Q factor 10
ShowIIRfilter(0.1, 10);
ESP_LOGI(TAG, "End Example.");
}
@@ -0,0 +1,3 @@
dependencies:
espressif/esp-dsp:
version: '*'
@@ -0,0 +1 @@
CONFIG_PARTITION_TABLE_OFFSET=0x9000
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ekf13states)
@@ -0,0 +1,149 @@
# Extended Kalman Filter
This example emulate system with IMU sensors and show how to use Extended Kalman Filter (EKF), with 13 values states vector,
to estimate gyroscope errors and calculate system attitude.
Also, this example show how to use esp-dsp library to operate with matrices and vectors.
In real system, the emulated sensors values should be replace by the real sensors values.
Then, in real system, a calibration phase should be implemented and after the calibration
phase the state vector X and covariance matrix P should be saved and restored next time, when
filter called. It will save time for initial phase.
## How to use example
### Hardware required
This example does not require any special hardware, and can be run on any common development board.
### Configure the project
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
### Build and flash
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example Output
```
I (380) spi_flash: detected chip: gd
I (383) spi_flash: flash io: dio
W (387) spi_flash: Detected size(4096k) larger than the size in the binary image header(2048k). Using the size in the binary image header.
I (404) cpu_start: Starting scheduler on PRO CPU.
I (0) cpu_start: Starting scheduler on APP CPU.
I (413) main: Start Example.
Gyro error: 0.1 0.2 0.3
Calibration phase started:
Loop 1000 from 48000, State data : 0.998361 0.0152476 0.0211183 0.0509682 0.00463435 0.00919946 0.01352 0.998156 0.00619182 -0.000683098 -0.00117112 0.0063196 -0.000952147
Loop 2000 from 48000, State data : 0.941757 0.0877462 0.170681 0.276156 0.016951 0.0334337 0.0498731 0.998804 0.0162317 -0.00225174 0.00389746 0.0110905 -0.000489083
Loop 3000 from 48000, State data : 0.372216 0.24247 0.488788 0.750832 0.0323164 0.0642265 0.0962768 0.997295 0.0269348 -0.00481966 0.00605674 0.00779719 0.00494921
Loop 4000 from 48000, State data : 0.944725 0.0951798 0.165878 0.266308 0.0470155 0.0946294 0.141251 0.998213 0.0337875 -0.00704064 0.00422252 0.0124181 0.00485692
Loop 5000 from 48000, State data : 0.944287 0.102183 0.168344 0.263706 0.0597481 0.12037 0.179946 0.997498 0.0378795 -0.00841348 0.0053515 0.0104612 0.00666854
Loop 6000 from 48000, State data : 0.379137 0.258284 0.476853 0.74977 0.0697741 0.140876 0.210702 0.995523 0.0410914 -0.00911293 0.00510267 0.00764586 0.00913832
Loop 7000 from 48000, State data : 0.947048 0.112494 0.165382 0.251187 0.0773002 0.156661 0.233985 0.996358 0.0425222 -0.00994576 0.00353348 0.00969652 0.00849919
Loop 8000 from 48000, State data : 0.945556 0.120624 0.169212 0.250481 0.082995 0.16838 0.251493 0.995914 0.0433827 -0.0102827 0.0039165 0.00846988 0.00913964
Loop 9000 from 48000, State data : 0.381034 0.276875 0.4647 0.749805 0.0871785 0.177046 0.264439 0.995073 0.0441243 -0.0103565 0.00391002 0.0071649 0.00997719
Loop 10000 from 48000, State data : 0.946592 0.132375 0.168307 0.241068 0.0902326 0.183443 0.273873 0.995445 0.0443655 -0.0106197 0.00326065 0.00799655 0.00960479
Loop 11000 from 48000, State data : 0.944297 0.140946 0.172816 0.242015 0.0924658 0.188118 0.280807 0.995187 0.0445766 -0.0106806 0.00346742 0.00749049 0.00979064
Loop 12000 from 48000, State data : 0.378334 0.295555 0.452859 0.751285 0.0941005 0.191525 0.285886 0.994796 0.0447763 -0.0106511 0.0034986 0.00695604 0.0100697
Loop 13000 from 48000, State data : 0.944329 0.1532 0.172826 0.234315 0.0953075 0.194011 0.289567 0.994899 0.0448155 -0.0107384 0.00323858 0.00728781 0.00989103
Loop 14000 from 48000, State data : 0.941572 0.16194 0.177533 0.236008 0.0961574 0.195842 0.292257 0.994735 0.0448801 -0.0107422 0.00334282 0.0070798 0.00993131
Loop 15000 from 48000, State data : 0.373427 0.314041 0.441061 0.753256 0.0967899 0.197167 0.294234 0.994523 0.0449438 -0.0107112 0.00335898 0.00685221 0.0100213
Loop 16000 from 48000, State data : 0.941028 0.174338 0.177916 0.228952 0.0972752 0.198121 0.295664 0.994518 0.0449512 -0.0107403 0.0032445 0.00697761 0.00993463
Loop 17000 from 48000, State data : 0.937959 0.183145 0.18262 0.230959 0.0975883 0.198844 0.296697 0.994396 0.0449757 -0.0107339 0.0032963 0.00688409 0.00992845
Loop 18000 from 48000, State data : 0.3675 0.33233 0.429142 0.755207 0.0978324 0.199358 0.297465 0.994256 0.0450002 -0.0107104 0.00330113 0.00677742 0.00995297
Loop 19000 from 48000, State data : 0.937014 0.195546 0.183166 0.224089 0.0980371 0.199716 0.298023 0.994211 0.0450036 -0.0107164 0.00324275 0.00681997 0.00990755
Loop 20000 from 48000, State data : 0.933698 0.204372 0.187784 0.226223 0.0981422 0.200008 0.29842 0.994114 0.0450155 -0.0107065 0.00327025 0.00677405 0.00988484
Loop 21000 from 48000, State data : 0.361055 0.350426 0.417036 0.756916 0.0982358 0.200208 0.29872 0.99401 0.0450272 -0.0106858 0.00326787 0.00671759 0.0098834
Loop 22000 from 48000, State data : 0.932425 0.216717 0.188413 0.219358 0.0983318 0.200334 0.298938 0.993947 0.0450303 -0.0106798 0.00323017 0.00672916 0.00985372
Loop 23000 from 48000, State data : 0.928888 0.225543 0.19291 0.221546 0.0983561 0.200458 0.299082 0.993866 0.0450371 -0.0106664 0.00324701 0.00670354 0.00982584
Loop 24000 from 48000, State data : 0.354297 0.36833 0.404722 0.758292 0.0983915 0.200535 0.299203 0.993773 0.045044 -0.0106443 0.00324109 0.00666712 0.00981608
Loop 25000 from 48000, State data : 0.927316 0.237803 0.19359 0.214612 0.0984453 0.200572 0.299291 0.993709 0.0450468 -0.0106303 0.00321085 0.00666748 0.00979369
Loop 26000 from 48000, State data : 0.92357 0.246618 0.197954 0.216824 0.0984385 0.200632 0.299342 0.993629 0.0450514 -0.0106123 0.00322403 0.00665109 0.00976504
Loop 27000 from 48000, State data : 0.347305 0.386034 0.392194 0.759303 0.0984521 0.200663 0.299393 0.993546 0.0450564 -0.0105864 0.00321847 0.00662376 0.00975319
Loop 28000 from 48000, State data : 0.92171 0.258777 0.198672 0.209796 0.0984898 0.200666 0.299433 0.993475 0.045059 -0.0105663 0.00319366 0.00662077 0.00973562
Loop 29000 from 48000, State data : 0.917761 0.267574 0.202895 0.212019 0.0984714 0.2007 0.299446 0.9934 0.0450631 -0.0105437 0.00320563 0.0066091 0.00970881
Loop 30000 from 48000, State data : 0.340113 0.403531 0.379459 0.759933 0.0984762 0.200711 0.299466 0.993322 0.0450673 -0.0105132 0.00320031 0.00658594 0.00969804
Loop 31000 from 48000, State data : 0.915619 0.279623 0.203648 0.204891 0.0985076 0.2007 0.299484 0.993253 0.0450696 -0.0104878 0.00317637 0.00658294 0.00968329
Loop 32000 from 48000, State data : 0.91147 0.288396 0.207727 0.207121 0.0984838 0.200725 0.299481 0.99318 0.0450732 -0.0104599 0.00318786 0.00657435 0.00965871
Loop 33000 from 48000, State data : 0.332734 0.420812 0.366519 0.760177 0.0984844 0.20073 0.299492 0.993105 0.045077 -0.0104242 0.00318322 0.00655352 0.00964965
Loop 34000 from 48000, State data : 0.909049 0.300327 0.208511 0.199891 0.0985129 0.200714 0.299506 0.993034 0.0450794 -0.0103941 0.0031609 0.00655179 0.00963774
Loop 35000 from 48000, State data : 0.904704 0.309072 0.212442 0.202124 0.0984875 0.200736 0.299498 0.992959 0.0450829 -0.0103612 0.0031732 0.00654506 0.00961709
Loop 36000 from 48000, State data : 0.325179 0.437867 0.353384 0.760034 0.098487 0.200738 0.299504 0.992885 0.0450865 -0.0103208 0.00317079 0.00652607 0.00961171
Loop 37000 from 48000, State data : 0.325177 0.437848 0.353377 0.760049 0.0989011 0.200534 0.299617 0.992838 0.0450912 -0.0103039 0.00319877 0.00652725 0.00959415
Loop 38000 from 48000, State data : 0.325194 0.437821 0.353363 0.760064 0.099202 0.200388 0.299726 0.992838 0.0450926 -0.0102998 0.00320422 0.00652895 0.00959084
Loop 39000 from 48000, State data : 0.325211 0.437798 0.353354 0.760074 0.0994169 0.200278 0.299826 0.992816 0.045093 -0.0102979 0.00320263 0.0065278 0.00959847
Loop 40000 from 48000, State data : 0.325222 0.437784 0.353346 0.760081 0.0995754 0.200199 0.299886 0.992816 0.0450925 -0.0102967 0.00320118 0.00652683 0.00960376
Loop 41000 from 48000, State data : 0.325231 0.437773 0.353342 0.760085 0.0996929 0.200142 0.299945 0.992816 0.0450925 -0.0102966 0.00320043 0.00652627 0.00960631
Loop 42000 from 48000, State data : 0.325238 0.437769 0.353336 0.760087 0.0997802 0.200119 0.299978 0.992816 0.0450913 -0.0102965 0.00320007 0.0065261 0.00960773
Loop 43000 from 48000, State data : 0.32524 0.437762 0.353331 0.760093 0.099842 0.200089 0.299979 0.992816 0.0450913 -0.0102961 0.00320001 0.00652608 0.00960857
Loop 44000 from 48000, State data : 0.325241 0.43776 0.353327 0.760095 0.099883 0.200059 0.299979 0.992816 0.045089 -0.0102953 0.00319975 0.00652622 0.00960868
Loop 45000 from 48000, State data : 0.325243 0.437759 0.353325 0.760096 0.0999138 0.200045 0.299979 0.992816 0.0450878 -0.0102956 0.0031996 0.00652593 0.00960985
Loop 46000 from 48000, State data : 0.325245 0.437756 0.353324 0.760097 0.0999355 0.200042 0.299979 0.992816 0.0450878 -0.0102959 0.00319972 0.0065261 0.00960944
Loop 47000 from 48000, State data : 0.325246 0.437757 0.353322 0.760098 0.0999504 0.200039 0.299979 0.992816 0.0450878 -0.0102959 0.00319952 0.00652634 0.00960984
Calibration phase finished.
Regular calculation started:
Loop 1000 from 48000, State data : 0.9996 6.68374e-06 -7.71055e-05 0.028269 0.0999599 0.199742 0.298758 0.992397 0.0506049 -0.00981295 0.00516875 0.00517689 0.0102406
Loop 2000 from 48000, State data : 0.95186 0.0747648 0.154942 0.253704 0.0997667 0.199899 0.298983 0.992397 0.0504132 -0.0098162 0.00510809 0.00522702 0.0102249
Loop 3000 from 48000, State data : 0.395338 0.237819 0.486861 0.741698 0.0994409 0.200091 0.299095 0.992397 0.0502891 -0.00981838 0.00506923 0.00525921 0.0102147
Loop 4000 from 48000, State data : 0.952465 0.0877289 0.155254 0.247002 0.0992076 0.200299 0.299271 0.992397 0.0502054 -0.00981973 0.00504271 0.00528111 0.0102076
Loop 5000 from 48000, State data : 0.950016 0.096521 0.160702 0.249654 0.0990023 0.200426 0.299306 0.992397 0.05013 -0.00982108 0.00501929 0.00530046 0.0102013
Loop 6000 from 48000, State data : 0.389808 0.256786 0.476033 0.745321 0.0988748 0.200476 0.299331 0.992397 0.050078 -0.00982208 0.0050032 0.00531378 0.0101971
Loop 7000 from 48000, State data : 0.950306 0.109383 0.161046 0.242937 0.0987883 0.200581 0.299444 0.992397 0.0500379 -0.00982289 0.0049906 0.00532416 0.0101938
Loop 8000 from 48000, State data : 0.947646 0.118155 0.166392 0.2456 0.0986931 0.200633 0.299434 0.992397 0.0499987 -0.00982366 0.00497852 0.00533416 0.0101903
Loop 9000 from 48000, State data : 0.383995 0.275557 0.464951 0.748623 0.0986473 0.200627 0.299425 0.992397 0.0499702 -0.00982415 0.00496994 0.00534126 0.0101879
Loop 10000 from 48000, State data : 0.94764 0.130939 0.166769 0.238794 0.0986203 0.200694 0.299509 0.992397 0.0499475 -0.00982454 0.004963 0.00534698 0.0101861
Loop 11000 from 48000, State data : 0.944771 0.139703 0.171999 0.241471 0.0985699 0.200714 0.299481 0.992397 0.0499252 -0.00982467 0.00495605 0.00535274 0.0101844
Loop 12000 from 48000, State data : 0.377949 0.294161 0.453622 0.751566 0.0985571 0.200685 0.299459 0.992397 0.0499092 -0.00982467 0.00495124 0.0053567 0.0101832
Loop 13000 from 48000, State data : 0.944475 0.152413 0.172408 0.234549 0.0985539 0.200736 0.299532 0.992397 0.0498962 -0.00982467 0.00494735 0.0053599 0.0101823
Loop 14000 from 48000, State data : 0.941398 0.16117 0.177516 0.237239 0.0985215 0.200743 0.299498 0.992397 0.0498826 -0.00982467 0.0049434 0.00536316 0.0101813
Loop 15000 from 48000, State data : 0.371694 0.312599 0.442052 0.754132 0.0985222 0.200704 0.299474 0.992397 0.049874 -0.00982467 0.00494084 0.0053653 0.0101808
Loop 16000 from 48000, State data : 0.940819 0.173801 0.177954 0.230187 0.0985277 0.20075 0.299544 0.992397 0.0498671 -0.00982467 0.00493887 0.00536698 0.0101804
Loop 17000 from 48000, State data : 0.937532 0.182552 0.182939 0.232897 0.0985023 0.200752 0.299507 0.992397 0.0498602 -0.00982467 0.0049367 0.0053688 0.0101799
Loop 18000 from 48000, State data : 0.365235 0.33087 0.43025 0.756316 0.0985084 0.200708 0.299482 0.992397 0.0498562 -0.00982467 0.00493555 0.0053698 0.0101796
Loop 19000 from 48000, State data : 0.936669 0.195102 0.183407 0.225717 0.0985175 0.200754 0.299549 0.992397 0.0498532 -0.00982467 0.00493474 0.00537051 0.0101794
Loop 20000 from 48000, State data : 0.933178 0.203841 0.188264 0.22844 0.0984953 0.200754 0.299511 0.992397 0.0498502 -0.00982467 0.00493366 0.00537141 0.010179
Loop 21000 from 48000, State data : 0.35858 0.348967 0.41822 0.758113 0.0985034 0.200709 0.299484 0.992397 0.0498495 -0.00982467 0.00493334 0.00537172 0.0101788
Loop 22000 from 48000, State data : 0.93203 0.216304 0.188763 0.221136 0.0985129 0.200755 0.299549 0.992397 0.0498497 -0.00982467 0.00493327 0.00537182 0.0101787
Loop 23000 from 48000, State data : 0.928336 0.225027 0.193488 0.22387 0.0984918 0.200754 0.29951 0.992397 0.0498497 -0.00982467 0.00493298 0.00537209 0.0101787
Loop 24000 from 48000, State data : 0.351735 0.366882 0.405969 0.759519 0.0985006 0.200707 0.299482 0.992397 0.0498508 -0.00982467 0.00493324 0.00537189 0.0101787
Loop 25000 from 48000, State data : 0.926905 0.237397 0.194017 0.216443 0.0985107 0.200755 0.299545 0.992397 0.0498526 -0.00982467 0.00493366 0.00537159 0.0101787
Loop 26000 from 48000, State data : 0.92301 0.246099 0.198608 0.219185 0.0984902 0.200753 0.299511 0.992397 0.0498537 -0.00982467 0.00493391 0.00537146 0.0101787
Loop 27000 from 48000, State data : 0.344708 0.384605 0.393502 0.760534 0.0984992 0.200706 0.299488 0.992397 0.0498556 -0.00982467 0.00493459 0.00537092 0.0101787
Loop 28000 from 48000, State data : 0.921297 0.258369 0.199166 0.211636 0.0985091 0.200757 0.299555 0.992397 0.0498579 -0.00982467 0.00493535 0.00537033 0.0101787
Loop 29000 from 48000, State data : 0.917204 0.267048 0.203621 0.214385 0.0984891 0.200754 0.29952 0.992397 0.0498601 -0.00982467 0.00493597 0.0053698 0.0101787
Loop 30000 from 48000, State data : 0.337501 0.402129 0.380825 0.761156 0.0984981 0.200706 0.299491 0.992397 0.0498626 -0.00982467 0.00493691 0.00536903 0.0101787
Loop 31000 from 48000, State data : 0.915208 0.279212 0.204208 0.206723 0.0985072 0.200758 0.299553 0.992397 0.0498654 -0.00982467 0.00493789 0.00536824 0.0101787
Loop 32000 from 48000, State data : 0.910918 0.287861 0.208526 0.209479 0.0984873 0.200754 0.299515 0.992397 0.0498676 -0.00982467 0.00493879 0.00536752 0.0101787
Loop 33000 from 48000, State data : 0.330116 0.419445 0.367945 0.761385 0.0984966 0.200704 0.299489 0.992397 0.0498701 -0.00982467 0.00493986 0.00536667 0.0101787
Loop 34000 from 48000, State data : 0.908641 0.299912 0.209141 0.201703 0.0985056 0.200757 0.299551 0.992397 0.0498728 -0.00982467 0.00494093 0.00536582 0.0101787
Loop 35000 from 48000, State data : 0.904158 0.308528 0.213318 0.204462 0.0984862 0.200752 0.299518 0.992397 0.0498751 -0.00982467 0.00494188 0.00536507 0.0101787
Loop 36000 from 48000, State data : 0.322561 0.436541 0.354869 0.761219 0.0984953 0.200702 0.299495 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Loop 37000 from 48000, State data : 0.322549 0.436508 0.354868 0.761243 0.0989076 0.200506 0.299634 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Loop 38000 from 48000, State data : 0.322568 0.436485 0.354851 0.761257 0.099208 0.200371 0.299726 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Loop 39000 from 48000, State data : 0.322581 0.436466 0.354841 0.761267 0.0994207 0.200267 0.299799 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Loop 40000 from 48000, State data : 0.322592 0.436454 0.354831 0.761274 0.099581 0.200208 0.299849 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Loop 41000 from 48000, State data : 0.322601 0.436443 0.354826 0.761278 0.099701 0.20015 0.299901 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Loop 42000 from 48000, State data : 0.322606 0.436435 0.35482 0.761283 0.0997844 0.200101 0.299931 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Loop 43000 from 48000, State data : 0.322611 0.436429 0.35482 0.761285 0.0998457 0.200072 0.299961 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Loop 44000 from 48000, State data : 0.322615 0.436425 0.354818 0.761286 0.0998883 0.200057 0.29999 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Loop 45000 from 48000, State data : 0.322617 0.436423 0.354816 0.761287 0.099912 0.200042 0.300002 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Loop 46000 from 48000, State data : 0.322617 0.436421 0.354815 0.761289 0.0999343 0.20003 0.300002 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Loop 47000 from 48000, State data : 0.322618 0.436421 0.354814 0.761289 0.0999444 0.20003 0.300002 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Final State data : 0.322618 0.436421 0.354814 0.761289 0.0999518 0.20003 0.300002 0.992397 0.0498778 -0.00982467 0.00494296 0.00536423 0.0101787
Estimated error : 0.0999518 0.20003 0.300002
Difference between real and estimated errors : 4.81904e-05 -2.99811e-05 -2.17557e-06
Expected Euler angels (degree) : -29.8215 64.9692 150.241
Calculated Euler angels (degree) : -35.1525 63.3067 156.167
```
@@ -0,0 +1 @@
idf_component_register(SRCS "ekf_imu13states_main.cpp")
@@ -0,0 +1,196 @@
// Copyright 2020-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dsp_platform.h"
#include "esp_log.h"
#include "esp_dsp.h"
#include "ekf_imu13states.h"
static const char *TAG = "main";
extern "C" void app_main();
// This example reproduce system with gyroscope, accelerometer, and magnetometer
// True gyroscope values will be transformed and applied to the rotation and reference measurements.
void app_main()
{
ekf_imu13states *ekf13 = new ekf_imu13states();
ekf13->Init();
ESP_LOGI(TAG, "Start Example.");
// Set up some initial values to emulate and calculate system values
int total_N = 3000;
// Pi value
float pi = std::atan(1) * 4;
// gyroscope bias error
float gyro_err_data[] = {0.1, 0.2, 0.3}; // static constant error
dspm::Mat gyro_err(gyro_err_data, 3, 1);
// Measurement noise covariance values for diagonal covariance matrix.
// For the real system these values could be adjusted!
// These values depends on how noisy the measurement.
//
float R[10];
for (size_t i = 0; i < 10; i++) {
R[i] = 0.01;
}
// Reference vectors
float accel0_data[] = {0, 0, 1};
// In real system magnetometer vector will have different value and direction
// The EKF will calculate them. This value is used as initial state.
float magn0_data[] = {1, 0, 0};
dspm::Mat accel0(accel0_data, 3, 1);
dspm::Mat magn0(magn0_data, 3, 1);
float dt = 0.01;
dspm::Mat gyro_data(3, 1);
int count = 0;
// Initial rotation matrix
dspm::Mat Rm = dspm::Mat::eye(3);
dspm::Mat Re = dspm::Mat::eye(3);
gyro_err *= 1;
std::cout << "Gyro error: " << gyro_err.t() << std::endl;
std::cout << "Calibration phase started: " << std::endl;
for (size_t n = 1; n < total_N * 16; n++) {
if ((n % 1000) == 0) {
std::cout << "Loop " << n << " from " << total_N * 16;
std::cout << ", State data : " << ekf13->X.t();
}
//
// This part of the loop related to the system emulation
//
// Generate gyro values for system emulation
gyro_data *= 0; // reset gyro value
if ((n >= (total_N / 2)) && (n < total_N * 12)) {
gyro_data(0, 0) = 1 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
gyro_data(1, 0) = 2 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
gyro_data(2, 0) = 3 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
count++;
}
dspm::Mat gyro_sample = gyro_data + gyro_err;
gyro_data *= dt;
// Calculate rotation for the last time interval
Re = ekf::eul2rotm(gyro_data.data);
// Ally rotation to the system rotation matrix
Rm = Rm * Re;
// Convert rotation matrix to the system attitude quaternion
dspm::Mat attitude = ekf::rotm2quat(Rm);
// We have to rotate accel and magn to the opposite direction
dspm::Mat accel_data = Rm.t() * accel0;
dspm::Mat magn_data = Rm.t() * magn0;
dspm::Mat accel_norm = accel_data / accel_data.norm();
dspm::Mat magn_norm = magn_data / magn_data.norm();
//
// This part of the loop related to the real system
// Here gyro_sample values must be replaced by measured gyroscope values
// and accel_norm and magn_norm should be real measured accel and magn values
// The dt in this case should be real time difference in seconds between samples
// Fill the input control values with measured gyro values
float input_u[] = {gyro_sample(0, 0), gyro_sample(1, 0), gyro_sample(2, 0)};
// Process input values to new state
ekf13->Process(input_u, dt);
dspm::Mat q_norm(ekf13->X.data, 4, 1);
q_norm /= q_norm.norm();
// Correct state and calculate gyro and magnetometer values.
// Here accel_norm and magn_norm should be real measured accel and magn values
ekf13->UpdateRefMeasurementMagn(accel_norm.data, magn_norm.data, R);
}
std::cout << "Calibration phase finished." << std::endl << std::endl;
std::cout << "Regular calculation started:" << std::endl;
// Reset rotation nmatrix
Rm = dspm::Mat::eye(3);
Re = dspm::Mat::eye(3);
count = 0;
// Set initial state
ekf13->X(0, 0) = 1;
ekf13->X(0, 1) = 0;
ekf13->X(0, 2) = 0;
ekf13->X(0, 3) = 0;
for (size_t n = 1; n < total_N * 16; n++) {
if ((n % 1000) == 0) {
std::cout << "Loop " << n << " from " << total_N * 16;
std::cout << ", State data : " << ekf13->X.t();
}
//
// This part of the loop related to the system emulation
//
// Generate gyro values for system emulation
gyro_data *= 0; // reset gyro value
if ((n >= (total_N / 2)) && (n < total_N * 12)) {
gyro_data(0, 0) = 1 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
gyro_data(1, 0) = 2 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
gyro_data(2, 0) = 3 / pi * std::cos(-pi / 2 + pi / 2 * count * 2 / (total_N / 10));
count++;
}
dspm::Mat gyro_sample = gyro_data + gyro_err;
gyro_data *= dt;
// Calculate rotation for the last time interval
Re = ekf::eul2rotm(gyro_data.data);
// Ally rotation to the system rotation matrix
Rm = Rm * Re;
// Convert rotation matrix to the system attitude quaternion
dspm::Mat attitude = ekf::rotm2quat(Rm);
// We have to rotate accel and magn to the opposite direction
dspm::Mat accel_data = Rm.t() * accel0;
dspm::Mat magn_data = Rm.t() * magn0;
dspm::Mat accel_norm = accel_data / accel_data.norm();
dspm::Mat magn_norm = magn_data / magn_data.norm();
//
// This part of the loop related to the real system
// Here gyro_sample values must be replaced by measured gyroscope values
// and accel_norm and magn_norm should be real measured accel and magn values
// The dt in this case should be real time difference in seconds between samples
// Fill the input control values with measured gyro values
float input_u[] = {gyro_sample(0, 0), gyro_sample(1, 0), gyro_sample(2, 0)};
// Process input values to new state
ekf13->Process(input_u, dt);
dspm::Mat q_norm(ekf13->X.data, 4, 1);
q_norm /= q_norm.norm();
// Correct state and calculate gyro and magnetometer values.
// Here accel_norm and magn_norm should be real measured accel and magn values
ekf13->UpdateRefMeasurement(accel_norm.data, magn_norm.data, R);
}
std::cout << "Final State data : " << ekf13->X.t();
dspm::Mat estimated_error(&ekf13->X.data[4], 3, 1);
std::cout << "Estimated error : " << estimated_error.t();
std::cout << "Difference between real and estimated errors : " << (gyro_err - estimated_error).t() << std::endl;
std::cout << "Expected Euler angels (degree) : " << (180 / pi * ekf::quat2eul(ekf::rotm2quat(Rm).data)).t();
std::cout << "Calculated Euler angels (degree) : " << (180 / pi * ekf::quat2eul(ekf13->X.data)).t() << std::endl;
}
@@ -0,0 +1,3 @@
dependencies:
espressif/esp-dsp:
version: '*'
@@ -0,0 +1,22 @@
#
# DSP Library
#
# CONFIG_DSP_ANSI is not set
CONFIG_DSP_OPTIMIZED=y
# CONFIG_DSP_MAX_FFT_SIZE_512 is not set
# CONFIG_DSP_MAX_FFT_SIZE_1024 is not set
# CONFIG_DSP_MAX_FFT_SIZE_2048 is not set
CONFIG_DSP_MAX_FFT_SIZE_4096=y
# CONFIG_DSP_MAX_FFT_SIZE_8192 is not set
# CONFIG_DSP_MAX_FFT_SIZE_16384 is not set
# CONFIG_DSP_MAX_FFT_SIZE_32768 is not set
CONFIG_DSP_MAX_FFT_SIZE=4096
# end of DSP Library
#
# ESP System Settings
#
CONFIG_PARTITION_TABLE_OFFSET=0x9000
CONFIG_ESP_INT_WDT=n
CONFIG_ESP_TASK_WDT=n
# end of ESP System Settings
@@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's
# CMakeLists in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(matrix)
@@ -0,0 +1,54 @@
# Matrix Operations Example
(See the README.md file in the upper level 'examples' directory for more information about examples.)
This example demonstrates how to use Mat class functionality from esp-dsp library. Example does the following steps:
1. Initialize a matrix A and matrix x
2. Calculate matrix b: b = A*x
3. Find roots x1_: A*x1_ = b, with different methods
4. Print result
## How to use example
### Hardware required
This example does not require any special hardware, and can be run on any common development board.
### Configure the project
Under Component Config ---> DSP Library ---> DSP Optimization, it's possible to choose either the optimized or ANSI implementation, to compare them.
### Build and flash
Build the project and flash it to the board, then run monitor tool to view serial output (replace PORT with serial port name):
```
idf.py -p PORT flash monitor
```
(To exit the serial monitor, type ``Ctrl-]``.)
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
## Example output
Here is an typical example console output.
```
I (215) main: Start Example.
I (215) main: Original vector x:
0
1
2
I (215) main: Solve result:
0
1
2
I (215) main: Roots result:
0
1
2
I (215) main: End Example.
```
@@ -0,0 +1 @@
idf_component_register(SRCS "dspm_matrix_main.cpp")
@@ -0,0 +1,62 @@
// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dsp_platform.h"
#include "esp_log.h"
#include "esp_dsp.h"
static const char *TAG = "main";
// This example shows how to use Mat class from esp-dsp library.
//
// First we create matrix A and x, and then calculating matrix b as result
// A*x = b
// Then we can find x as roots of matrices X and b
//
extern "C" void app_main();
void app_main()
{
ESP_LOGI(TAG, "Start Example.");
int M = 3;
int N = 3;
dspm::Mat A(M, N);
dspm::Mat x(N, 1);
for (int m = 0 ; m < M ; m++) {
for (int n = 0 ; n < N ; n++) {
A(m, n) = N * m + n;
}
x(m, 0) = m;
}
A(0, 0) = 10;
A(0, 1) = 11;
dspm::Mat b = A * x;
// Gaussian method
dspm::Mat x1_ = dspm::Mat::solve(A, b);
// Non Gaussian method
dspm::Mat x2_ = dspm::Mat::roots(A, b);
ESP_LOGI(TAG, "Original vector x:");
std::cout << x;
ESP_LOGI(TAG, "Solve result:");
std::cout << x1_;
ESP_LOGI(TAG, "Roots result:");
std::cout << x2_;
ESP_LOGI(TAG, "End Example.");
}
@@ -0,0 +1,3 @@
dependencies:
espressif/esp-dsp:
version: '*'
@@ -0,0 +1 @@
CONFIG_PARTITION_TABLE_OFFSET=0x9000