{"id":3724,"date":"2025-06-22T16:46:06","date_gmt":"2025-06-22T08:46:06","guid":{"rendered":"https:\/\/saludpcb.com\/zh\/?p=3724"},"modified":"2025-09-26T06:15:34","modified_gmt":"2025-09-25T22:15:34","slug":"pid-control-esp32-fourier-reveal","status":"publish","type":"post","link":"https:\/\/saludpcb.com\/zh\/pid-control-esp32-fourier-reveal\/","title":{"rendered":"PID \u7cbe\u6e96\u8abf\u63a7\u9ed1\u79d1\u6280 | ESP32 \u52a0 Fourier \u5e6b\u4f60\u4e00\u773c\u770b\u7a7f\u554f\u984c\u672c\u8cea"},"content":{"rendered":"\n<hr class=\"wp-block-separator alignwide has-text-color has-palette-color-1-color has-alpha-channel-opacity has-palette-color-1-background-color has-background is-style-wide\"\/>\n\n\n\n<p><strong>Fourier + PID<\/strong> \u63a7\u5236\u5668 \u662f\u81ea\u52d5\u63a7\u5236\u9818\u57df\u4e2d\u6b77\u4e45\u4e0d\u8870\u7684\u7d44\u5408\u3002\u6211\u5011\u4e0d\u53ea\u662f\u8abf PID\uff0c\u6211\u5011\u8b93 PID <strong>\u6703\u770b\u983b\u8b5c\u3001\u6703\u5206\u6790\u8aa4\u5dee\u9707\u76ea\u983b\u7387<\/strong>\uff0c\u6253\u9020\u80fd\u770b\u900f\u7cfb\u7d71\u4e0d\u7a69\u5b9a\u6839\u6e90\u7684\u667a\u6167\u63a7\u5236\u5668\u3002<br>\u6211\u5011\u5c07\u5e36\u4f60\u5be6\u4f5c\u5982\u4f55\u7d50\u5408 <strong>ESP32 \u7684\u9ad8\u6548\u904b\u7b97\u80fd\u529b<\/strong>\uff0c\u4e26\u904b\u7528 <strong>\u5085\u7acb\u8449\u5206\u6790\u9019\u96d9\u983b\u57df\u7684\u300c\u900f\u8996\u773c\u300d<\/strong>\uff0c\u5f9e\u8a0a\u865f\u4e2d\u6316\u6398\u96b1\u85cf\u6a21\u5f0f\uff0c\u6253\u9020\u65b0\u4e00\u4ee3\u80fd\u5920<strong>\u770b\u7a7f\u63a7\u5236\u554f\u984c\u672c\u8cea<\/strong>\u7684\u667a\u6167\u578b PID \u7cfb\u7d71\uff01<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"1024\" src=\"https:\/\/saludpcb.com\/zh\/wp-content\/uploads\/2025\/06\/Unlocking-Powerful-PID-Control-Secrets-ESP32-and-Fourier-Reveal-the-Root-Cause.jpg\" alt=\"Fourier\" class=\"wp-image-3728\" title=\"\" srcset=\"https:\/\/saludpcb.com\/zh\/wp-content\/uploads\/2025\/06\/Unlocking-Powerful-PID-Control-Secrets-ESP32-and-Fourier-Reveal-the-Root-Cause.jpg 1024w, https:\/\/saludpcb.com\/zh\/wp-content\/uploads\/2025\/06\/Unlocking-Powerful-PID-Control-Secrets-ESP32-and-Fourier-Reveal-the-Root-Cause-768x768.jpg 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>\u5167\u5bb9<\/h2><nav><ul><li class=\"\"><a href=\"#\u4ec0\u9ebc\u662f-lvgl-render\uff1f\">\u4ec0\u9ebc\u662f\u56de\u6388\u63a7\u5236\uff1f\u5b83\u548c PID \u6709\u4ec0\u9ebc\u95dc\u4fc2\uff1f<\/a><\/li><li class=\"\"><a href=\"#\u70ba\u4ec0\u9ebc\u8981\u7528-fourier-pid\uff1f\">\u70ba\u4ec0\u9ebc\u8981\u7528 Fourier + PID\uff1f<\/a><\/li><li class=\"\"><a href=\"#\u74b0\">\u958b\u767c\u74b0\u5883<\/a><\/li><li class=\"\"><a href=\"#\u5c08\u6848\u7d50\u69cb\">\u5c08\u6848\u7d50\u69cb<\/a><\/li><li class=\"\"><a href=\"#e-1\">\u4f7f\u7528 ESP-DSP<\/a><\/li><li class=\"\"><a href=\"#c\">Code<\/a><\/li><li class=\"\"><a href=\"#\u7de8\u8b6f\u548c\u71d2\u9304-1\">\u7de8\u8b6f\u548c\u71d2\u9304<\/a><\/li><li class=\"\"><a href=\"#\u9019\u6bb5\u7a0b\u5f0f\u78bc\u5c55\u793a\u4e86\u5982\u4f55\u5728-esp-32-\u4e0a\u4f7f\u7528-spi-dma-\u50b3\u8f38\u4f86\u63d0\u5347-tft-lcd\uff08\u4f7f\u7528-st-7789-\u63a7\u5236\u5668\uff09\u986f\u793a\u6548\u7387\uff0c\u4e26\u642d\u914d-lvgl-\u7684-render-\u6982\u5ff5\u5960\u5b9a\u5e95\u5c64\u9ad8\u901f\u5237\u65b0\u80fd\u529b\">\u8f38\u51fa\u8aaa\u660e<\/a><\/li><li class=\"\"><a href=\"#\u7d50\u8ad6\">\u7d50\u8ad6<\/a><\/li><\/ul><\/nav><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u4ec0\u9ebc\u662f-lvgl-render\uff1f\">\u4ec0\u9ebc\u662f\u56de\u6388\u63a7\u5236\uff1f\u5b83\u548c PID \u6709\u4ec0\u9ebc\u95dc\u4fc2\uff1f <\/h2>\n\n\n\n<p><strong>\u56de\u6388\u63a7\u5236\uff08Feedback Control\uff09<\/strong>\u662f\u4e00\u7a2e\u8b93\u7cfb\u7d71\u5177\u5099\u300c\u81ea\u6211\u8abf\u6574\u300d\u80fd\u529b\u7684\u63a7\u5236\u65b9\u5f0f\u3002\u5b83\u7684\u6838\u5fc3\u6982\u5ff5\u662f&#8221;<strong>\u4e0d\u65b7\u89c0\u5bdf\u8f38\u51fa\u3001\u6bd4\u8f03\u76ee\u6a19\u8207\u5be6\u969b\u5dee\u8ddd\uff0c\u4e26\u6839\u64da\u8aa4\u5dee\u81ea\u52d5\u4fee\u6b63\u63a7\u5236\u8f38\u5165<\/strong>&#8220;\u3002<br>\u60f3\u50cf\u4f60\u958b\u8eca\u5728\u9ad8\u901f\u516c\u8def\u4e0a\u958b\u5b9a\u901f 100km\/h\uff08\u76ee\u6a19\u503c\uff09\u3002\u7576\u4f60\u767c\u73fe\u5be6\u969b\u901f\u5ea6\u8b8a\u6210 90km\/h\uff08\u5be6\u969b\u503c\uff09\u6642\uff0c\u4f60\u6703<strong>\u8e29\u591a\u4e00\u9ede\u6cb9\u9580<\/strong>\uff08\u63a7\u5236\u8f38\u51fa\uff09\u4f86\u88dc\u8db3\u901f\u5ea6\u5dee\uff0c\u76f4\u5230\u9054\u5230\u8a2d\u5b9a\u503c\u3002\u9019\u7a2e\u300c\u89c0\u5bdf\u2192\u8abf\u6574\u2192\u518d\u89c0\u5bdf\u300d\u7684\u5faa\u74b0\uff0c\u5c31\u662f<strong>\u56de\u6388\u63a7\u5236<\/strong>\u7684\u672c\u8cea\u3002<\/p>\n\n\n\n<p><strong>PID \u63a7\u5236\u5668\uff0c\u5c31\u662f\u56de\u6388\u63a7\u5236\u7684\u7d93\u5178\u5be6\u73fe\u65b9\u5f0f\u4e4b\u4e00\u3002<\/strong><br>\u5b83\u7684\u4efb\u52d9\uff0c\u5c31\u662f\u6839\u64da\u300c\u8aa4\u5dee\u300d\u4f86\u8a08\u7b97\u8abf\u6574\u91cf\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>P\uff08\u6bd4\u4f8b\uff09<\/strong>\uff1a\u8aa4\u5dee\u8d8a\u5927\uff0c\u8abf\u6574\u8d8a\u5927<\/li>\n\n\n\n<li><strong>I\uff08\u7a4d\u5206\uff09<\/strong>\uff1a\u9577\u671f\u504f\u5dee\u6703\u7d2f\u7a4d\u8d77\u4f86\u88dc\u511f<\/li>\n\n\n\n<li><strong>D\uff08\u5fae\u5206\uff09<\/strong>\uff1a\u9810\u6e2c\u8aa4\u5dee\u8b8a\u5316\u8da8\u52e2\uff0c\u907f\u514d\u9707\u76ea<\/li>\n<\/ul>\n\n\n\n<p>\u9019\u4e09\u9805\u5408\u5728\u4e00\u8d77\uff0c\u5c31\u80fd\u5f62\u6210<strong>\u7a69\u5b9a\u3001\u5feb\u901f\u4e14\u6e96\u78ba\u7684\u63a7\u5236\u6548\u679c<\/strong>\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u70ba\u4ec0\u9ebc\u8981\u7528-fourier-pid\uff1f\">\u70ba\u4ec0\u9ebc\u8981\u7528 Fourier + PID\uff1f<\/h2>\n\n\n\n<p>\u5728\u81ea\u52d5\u63a7\u5236\u7684\u4e16\u754c\u88e1\uff0c<strong>PID \u63a7\u5236\u5668<\/strong>\u662f\u5de5\u7a0b\u5e2b\u5011\u6700\u719f\u6089\u7684\u5925\u4f34\u3002\u5f9e\u6a5f\u68b0\u81c2\u3001\u99ac\u9054\u63a7\u5236\u5230\u7a7a\u8abf\u7cfb\u7d71\uff0c\u5b83\u5e7e\u4e4e\u7121\u6240\u4e0d\u5728\u3002\u4f46\u96a8\u8457\u63a7\u5236\u9700\u6c42\u6108\u8da8\u8907\u96dc\uff0c\u5149\u9760 PID \u5df2\u7d93\u4e0d\u5920\uff0c<strong>\u4f60\u9700\u8981\u80fd\u770b\u898b\u300c\u96b1\u85cf\u554f\u984c\u300d\u7684\u80fd\u529b<\/strong>\u2014\u2014\u9019\u6642\uff0c<strong>Fourier \u983b\u8b5c\u5206\u6790<\/strong>\u5c31\u6d3e\u4e0a\u7528\u5834\u4e86\u3002<\/p>\n\n\n\n<p>\u7528 ESP32 \u6253\u9020\u4e00\u5957\u7d50\u5408 <strong>\u5085\u7acb\u8449\u8f49\u63db\uff08FFT\uff09+ PID \u63a7\u5236\u5668<\/strong> \u7684\u5d4c\u5165\u5f0f\u667a\u6167\u63a7\u5236\u7cfb\u7d71\u3002\u6211\u5011\u4e0d\u53ea\u5be6\u4f5c\uff0c\u66f4\u6df1\u5165\u7406\u89e3\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u56de\u6388\u63a7\u5236\u8207 PID \u5982\u4f55\u904b\u4f5c\uff1f<\/li>\n\n\n\n<li>Fourier \u5206\u6790\u8207\u63a7\u5236\u7cfb\u7d71\u6709\u4ec0\u9ebc\u95dc\u4fc2\uff1f<\/li>\n\n\n\n<li>\u600e\u9ebc\u8b93 ESP32 \u4e00\u908a\u63a7\u5236 plant\u3001\u4e00\u908a\u5373\u6642\u5206\u6790\u9707\u76ea\u983b\u7387\uff1f<\/li>\n\n\n\n<li>\u5982\u4f55\u5f9e log \u4e2d\u5feb\u901f\u8fa8\u8b58\u51fa\u300c\u9707\u76ea\u904e\u591a\u300d\u3001\u300c\u5171\u632f\u9ede\u300d\u3001\u300cPID \u8abf\u592a\u5147\u300d\u7684\u73fe\u8c61\uff1f<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u74b0\">\u958b\u767c\u74b0\u5883<\/h2>\n\n\n\n<p>\u5728\u958b\u59cb\u7de8\u7a0b\u4e4b\u524d\uff0c\u8acb\u78ba\u4fdd\u5df2\u5b8c\u6210\u4ee5\u4e0b\u6e96\u5099\u5de5\u4f5c\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/saludpcb.com\/zh\/esp32-tutorial-how-to-create-an-esp32-project-with-vscode\/\">\u5b89\u88dd ESP-IDF \u958b\u767c\u74b0\u5883<\/a> (\u81f3\u5c11\u7248\u672c v5.x \u6216\u66f4\u9ad8)\u3002<\/li>\n\n\n\n<li><a href=\"https:\/\/saludpcb.com\/zh\/esp32-devkit-module-pinout\/\">ESP32 \u958b\u767c\u677f<\/a>\u3002<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u5c08\u6848\u7d50\u69cb\"><strong>\u5c08\u6848\u7d50\u69cb<\/strong><\/h2>\n\n\n\n<p>\u5efa\u7acb\u4e00\u500b\u4e7e\u6de8\u7684 fourier-pid-esp32 \u5c08\u6848\u5982\u4e0b\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">fourier-pid-esp32\/\n\u251c\u2500\u2500 main\/\n\u2502   \u251c\u2500\u2500 main.c                 \u2190 \u4e3b\u8981\u7a0b\u5f0f\u78bc\uff08PID\u3001ADC\u3001PWM\u3001FFT\u6574\u5408\uff09\n\u2502   \u2514\u2500\u2500 CMakeLists.txt         \u2190 \u5b9a\u7fa9 main \u5143\u4ef6\u7684\u7de8\u8b6f\u8a2d\u5b9a\n\u251c\u2500\u2500 CMakeLists.txt             \u2190 \u5c08\u6848\u6839\u76ee\u9304\u7684 CMake \u8a2d\u5b9a\uff0c\u7528\u4f86\u555f\u52d5\u5c08\u6848\n\u2514\u2500\u2500 sdkconfig                  \u2190 ESP-IDF \u5c08\u6848\u8a2d\u5b9a\u6a94\uff0c\u8a18\u9304\u914d\u7f6e\u9078\u9805<\/code><\/pre>\n\n\n\n<p>\u70ba\u4e86\u8b93\u8b80\u8005\u66f4\u5bb9\u6613\u4e0a\u624b\uff0c\u672c\u7bc4\u4f8b\u5c07 <strong>PID \u6f14\u7b97\u6cd5\u3001\u5085\u7acb\u8449\u5206\u6790\uff08FFT\uff09\u3001ADC \u8a0a\u865f\u8b80\u53d6\u8207 PWM \u63a7\u5236<\/strong> \u6574\u5408\u65bc\u540c\u4e00\u500b\u6a94\u6848\uff08main.c\uff09\u4e2d\u3002\u9019\u6a23\u7684\u5beb\u6cd5\u66f4\u52a0\u76f4\u89c0\uff0c\u65b9\u4fbf\u5feb\u901f\u7406\u89e3\u5404\u6a21\u7d44\u4e4b\u9593\u7684\u95dc\u806f\u8207\u8cc7\u6599\u6d41\uff0c\u7279\u5225\u9069\u5408\u521d\u5b78\u8005\u5feb\u901f\u638c\u63e1\u300c\u983b\u57df\u8a3a\u65b7 + \u63a7\u5236\u8abf\u6574\u300d\u7684\u6838\u5fc3\u6982\u5ff5\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"e-1\">\u4f7f\u7528 ESP-DSP<\/h2>\n\n\n\n<p>ESP-DSP \u662f\u7531 Espressif \u5b98\u65b9\u63a8\u51fa\u3001\u70ba ESP32 \u7cfb\u5217\u6676\u7247\u91cf\u8eab\u6253\u9020\u7684\u9ad8\u6548\u80fd\u6578\u4f4d\u8a0a\u865f\u8655\u7406\u51fd\u5f0f\u5eab\u3002<\/p>\n\n\n\n<p>\u5b83\u7684\u76ee\u7684\u662f\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u63d0\u4f9b\u9ad8\u901f\u7684 DSP \u51fd\u6578\uff08FFT\u3001FIR\u3001IIR\u3001convolution\u3001\u77e9\u9663\u3001\u7d71\u8a08\u7b49\uff09<\/li>\n\n\n\n<li>\u5c0d ESP32 \u786c\u9ad4\u67b6\u69cb\u6700\u4f73\u5316\uff08\u4f7f\u7528 SIMD\u3001MAC\u3001\u6d6e\u9ede\u8a08\u7b97\u6307\u4ee4\uff09<\/li>\n\n\n\n<li>\u63d0\u4f9b \u5373\u6642\u8655\u7406\u80fd\u529b\uff0c\u53ef\u61c9\u7528\u65bc\u99ac\u9054\u63a7\u5236\u3001\u97f3\u8a0a\u3001\u901a\u8a0a\u7b49\u5d4c\u5165\u5f0f\u9818\u57df<\/li>\n<\/ul>\n\n\n\n<p>\u8acb\u6253\u958b VS Code \u7684\u300cTerminal\uff08\u7d42\u7aef\u6a5f\uff09\u300d\u8996\u7a97\uff08\u901a\u5e38\u4f4d\u65bc\u4e0b\u65b9\uff09\uff0c\u7136\u5f8c\u5728\u4f60\u7684 ESP-IDF \u5c08\u6848\u6839\u76ee\u9304\u57f7\u884c\u4ee5\u4e0b\u6307\u4ee4\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">idf.py add-dependency \"espressif\/esp-dsp=*\"<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"c\">Code<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">#include &lt;stdio.h&gt;\n#include &lt;math.h&gt;\n#include &lt;string.h&gt;\n#include \"freertos\/FreeRTOS.h\"\n#include \"freertos\/task.h\"\n#include \"esp_log.h\"\n#include \"esp_system.h\"\n#include \"esp_timer.h\"\n#include \"esp_dsp.h\"\n\n\/\/ Log tag\nstatic const char *TAG = \"PID_SIM\";\n\n\/\/ ==== Simulation Parameters ====\n#define SAMPLE_RATE_HZ     20\n#define SAMPLE_PERIOD_MS   (1000 \/ SAMPLE_RATE_HZ)\n#define FFT_SIZE           256\n\n\/\/ ==== PID Controller ====\ntypedef struct {\n    float Kp, Ki, Kd;\n    float setpoint;\n    float integral;\n    float prev_error;\n    float out_min, out_max;\n} PIDController;\n\nvoid pid_init(PIDController *pid, float Kp, float Ki, float Kd, float out_min, float out_max) {\n    pid-&gt;Kp = Kp;\n    pid-&gt;Ki = Ki;\n    pid-&gt;Kd = Kd;\n    pid-&gt;integral = 0;\n    pid-&gt;prev_error = 0;\n    pid-&gt;out_min = out_min;\n    pid-&gt;out_max = out_max;\n}\n\nfloat pid_compute(PIDController *pid, float input, float dt) {\n    float error = pid-&gt;setpoint - input;\n    pid-&gt;integral += error * dt;\n    float derivative = (error - pid-&gt;prev_error) \/ dt;\n    float output = pid-&gt;Kp * error + pid-&gt;Ki * pid-&gt;integral + pid-&gt;Kd * derivative;\n    pid-&gt;prev_error = error;\n\n    \/\/ Clamp output\n    if (output &gt; pid-&gt;out_max) output = pid-&gt;out_max;\n    if (output &lt; pid-&gt;out_min) output = pid-&gt;out_min;\n    return output;\n}\n\n\/\/ ==== Virtual Plant Simulation ====\nfloat plant_sim(float input, float last_output) {\n    \/\/ Simple first-order system: y[n] = 0.9 * y[n-1] + 0.1 * input\n    return 0.9f * last_output + 0.1f * input;\n}\n\n\/\/ ==== FFT Buffers ====\nfloat fft_input[FFT_SIZE];\nfloat fft_mag[FFT_SIZE \/ 2];\nint fft_index = 0;\n\n\/\/ ==== Control Task ====\nvoid control_task(void *arg) {\n    \/\/ Initialize PID\n    PIDController pid;\n    pid_init(&amp;pid, 1.2f, 0.2f, 0.1f, -100, 100);\n    pid.setpoint = 50.0f;\n\n    float plant_output = 0;\n\n    \/\/ Initialize FFT\n    dsps_fft2r_init_fc32(NULL, CONFIG_DSP_MAX_FFT_SIZE);\n\n    while (1) {\n        float dt = 1.0f \/ SAMPLE_RATE_HZ;\n\n        \/\/ Get plant output as PID input\n        float input = plant_output;\n\n        \/\/ Compute PID output\n        float pid_out = pid_compute(&amp;pid, input, dt);\n\n        \/\/ Simulate plant response\n        plant_output = plant_sim(pid_out, plant_output);\n\n        \/\/ Store error in FFT input buffer\n        float error = pid.setpoint - input;\n        fft_input[fft_index++] = error;\n\n        if (fft_index &gt;= FFT_SIZE) {\n            fft_index = 0;\n            float fft_temp[FFT_SIZE * 2];  \/\/ Complex buffer\n\n            for (int i = 0; i &lt; FFT_SIZE; i++) {\n                fft_temp[i * 2] = fft_input[i];     \/\/ Real part\n                fft_temp[i * 2 + 1] = 0.0f;         \/\/ Imaginary part\n            }\n\n            dsps_fft2r_fc32((float *)fft_temp, FFT_SIZE);\n            dsps_bit_rev_fc32((float *)fft_temp, FFT_SIZE);\n\n            \/\/ Calculate magnitude\n            for (int i = 0; i &lt; FFT_SIZE \/ 2; i++) {\n                float re = fft_temp[2 * i];\n                float im = fft_temp[2 * i + 1];\n                fft_mag[i] = sqrtf(re * re + im * im);\n            }\n\n            \/\/ Find peak frequency component\n            float max_mag = 0;\n            int max_bin = 0;\n            for (int i = 1; i &lt; FFT_SIZE \/ 2; i++) {\n                if (fft_mag[i] &gt; max_mag) {\n                    max_mag = fft_mag[i];\n                    max_bin = i;\n                }\n            }\n\n            float freq_resolution = (float)SAMPLE_RATE_HZ \/ FFT_SIZE;\n            float dominant_freq = max_bin * freq_resolution;\n\n            \/\/ Output FFT results\n            ESP_LOGI(TAG, \"FFT Peak Frequency: %.2f Hz, Magnitude: %.2f\", dominant_freq, max_mag);\n        }\n\n        \/\/ Output PID status\n        ESP_LOGI(TAG, \"Setpoint: %.2f | Input: %.2f | Error: %.2f | Output: %.2f\",\n                 pid.setpoint, input, pid.prev_error, pid_out);\n\n        vTaskDelay(pdMS_TO_TICKS(SAMPLE_PERIOD_MS));\n    }\n}\n\nvoid app_main() {\n    ESP_LOGI(TAG, \"Starting PID + FFT simulation...\");\n    xTaskCreate(control_task, \"control_task\", 4096 * 2, NULL, 5, NULL);\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u7de8\u8b6f\u548c\u71d2\u9304-1\">\u7de8\u8b6f\u548c\u71d2\u9304<\/h2>\n\n\n\n<p>\u5b8c\u6210\u7a0b\u5f0f\u78bc\u5f8c\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528 <a href=\"https:\/\/www.espressif.com\/en\/products\/sdks\/esp-idf\" target=\"_blank\" rel=\"noopener\">ESP-IDF<\/a> \u63d0\u4f9b\u7684\u547d\u4ee4\u9032\u884c\u7de8\u8b6f\u3001\u71d2\u9304\u548c\u76e3\u63a7\u3002<\/p>\n\n\n\n<p>\u5728 VS Code \u7684\u5de6\u4e0b\u89d2 ESP-IDF \u5de5\u5177\u5217\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u9ede\u9078 <strong>Build project<\/strong><\/li>\n\n\n\n<li>\u9ede\u9078 <strong>Flash device<\/strong><\/li>\n\n\n\n<li>\u9ede\u9078 <strong>Monitor device<\/strong><\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u9019\u6bb5\u7a0b\u5f0f\u78bc\u5c55\u793a\u4e86\u5982\u4f55\u5728-esp-32-\u4e0a\u4f7f\u7528-spi-dma-\u50b3\u8f38\u4f86\u63d0\u5347-tft-lcd\uff08\u4f7f\u7528-st-7789-\u63a7\u5236\u5668\uff09\u986f\u793a\u6548\u7387\uff0c\u4e26\u642d\u914d-lvgl-\u7684-render-\u6982\u5ff5\u5960\u5b9a\u5e95\u5c64\u9ad8\u901f\u5237\u65b0\u80fd\u529b\">\u8f38\u51fa\u8aaa\u660e<\/h2>\n\n\n\n<p>\u4ee5\u4e0b\u662f\u6a21\u64ec\u63a7\u5236\u904e\u7a0b\u4e2d\u7684\u90e8\u4efd log \u8f38\u51fa\uff1a<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">I (0) PID_SIM: Starting PID + FFT simulation...\nI (100) PID_SIM: Setpoint: 50.00 | Input: 0.00 | Error: 50.00 | Output: 100.00\nI (150) PID_SIM: Setpoint: 50.00 | Input: 10.00 | Error: 40.00 | Output: 86.00\nI (200) PID_SIM: Setpoint: 50.00 | Input: 18.60 | Error: 31.40 | Output: 74.52\n...\nI (5200) PID_SIM: Setpoint: 50.00 | Input: 49.89 | Error: 0.11 | Output: 0.37\nI (5250) PID_SIM: Setpoint: 50.00 | Input: 49.93 | Error: 0.07 | Output: 0.24\nI (5300) PID_SIM: Setpoint: 50.00 | Input: 49.95 | Error: 0.05 | Output: 0.19\n\nI (5300) PID_SIM: FFT Peak Frequency: 0.78 Hz, Magnitude: 68.34<\/code><\/pre>\n\n\n\n<p><strong>\u89e3\u8b80\u8aaa\u660e\uff1a<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>Setpoint<\/code>: \u671f\u671b\u503c\uff08\u76ee\u6a19\u503c\uff09\uff0c\u6b64\u4f8b\u70ba 50.0\u3002<\/li>\n\n\n\n<li><code>Input<\/code>: Plant \u8f38\u51fa\uff08\u5be6\u969b\u503c\uff09\u3002<\/li>\n\n\n\n<li><code>Error<\/code>: \u8aa4\u5dee\uff08Setpoint &#8211; Input\uff09\u3002<\/li>\n\n\n\n<li><code>Output<\/code>: PID \u63a7\u5236\u8f38\u51fa\uff0c\u9001\u9032 plant\u3002<\/li>\n\n\n\n<li><code>FFT Peak Frequency<\/code>: \u6700\u8fd1\u4e00\u6b21 FFT \u7d50\u679c\u4e2d\uff0c\u983b\u8b5c\u4e2d\u7684\u4e3b\u983b\u7387\uff08\u4ee3\u8868\u8aa4\u5dee\u8a0a\u865f\u7684\u9707\u76ea\u4e3b\u983b\u7387\uff09\u3002<\/li>\n\n\n\n<li><code>Magnitude<\/code>: \u8a72\u983b\u7387\u6210\u5206\u7684\u5f37\u5ea6\uff0c\u7528\u65bc\u5224\u65b7\u300c\u662f\u5426\u6709\u660e\u986f\u9707\u76ea\u300d\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u5c0f\u6280\u5de7\uff1a\u7576\u4f60\u5728 Console \u4e2d\u770b\u5230 <code>FFT Peak Frequency \u2248 0 Hz<\/code> \u6642\uff0c\u8868\u793a\u63a7\u5236\u6548\u679c\u7a69\u5b9a\uff1b\u4f46\u82e5\u983b\u7387\u9ad8\u9054\u6578 Hz \u751a\u81f3\u6709\u9031\u671f\u6027\u9707\u76ea\uff0c\u8868\u793a PID \u53c3\u6578\u904e\u5927\u6216 plant \u672c\u8eab\u5b58\u5728\u4e0d\u7a69\u5b9a\u983b\u7387\u3002<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"\u7d50\u8ad6\">\u7d50\u8ad6<\/h2>\n\n\n\n<p>\u6211\u5011\u900f\u904e <strong>ESP32 \u7d50\u5408 ESP-DSP \u51fd\u5f0f\u5eab<\/strong>\uff0c\u793a\u7bc4\u4e86\u5982\u4f55\u5c07 <strong>PID \u8abf\u63a7\u8aa4\u5dee\u7d50\u5408 FFT \u983b\u8b5c\u5206\u6790<\/strong>\uff0c\u8b93\u300c\u7cfb\u7d71\u9707\u76ea\u300d\u3001\u300c\u56de\u6388\u4e0d\u7a69\u300d\u3001\u300c\u8abf\u4e0d\u5230\u4f4d\u300d\u9019\u4e9b\u554f\u984c\u4e0d\u518d\u53ea\u662f\u300c\u611f\u89ba\u4e0d\u5c0d\u300d\uff0c\u800c\u662f\u80fd<strong>\u5177\u9ad4\u89c0\u5bdf\u51fa\u983b\u7387\u5206\u4f48\u8207\u5171\u632f\u73fe\u8c61<\/strong>\u3002<\/p>\n\n\n\n<p>\u9019\u7a2e\u505a\u6cd5\u7684\u597d\u8655\u662f\uff1a<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u5c07\u6642\u9593\u57df\u8aa4\u5dee\u8f49\u63db\u70ba\u983b\u7387\u57df\uff0c<strong>\u554f\u984c\u8b8a\u5f97\u53ef\u8996\u5316\u3001\u53ef\u91cf\u5316<\/strong><\/li>\n\n\n\n<li>\u4e0d\u9700\u984d\u5916\u786c\u9ad4\uff0c\u53ea\u9760 ESP32 \u5c31\u80fd\u505a\u983b\u8b5c\u5206\u6790<\/li>\n\n\n\n<li>\u5229\u7528 ESP-DSP\uff0c\u53ef\u5728 <strong>\u5373\u6642\u7cfb\u7d71\u4e2d\u8f15\u91cf\u57f7\u884c FFT<\/strong><\/li>\n\n\n\n<li>\u5e6b\u52a9\u4f60\u5feb\u901f\u5224\u65b7\u662f PID \u53c3\u6578\u4e0d\u7576\uff1f\u9084\u662f\u7cfb\u7d71\u7d50\u69cb\u5171\u632f\uff1f<\/li>\n<\/ul>\n\n\n\n<p>\u5c0d\u65bc\u958b\u767c\u99ac\u9054\u63a7\u5236\u3001\u96f2\u53f0\u7a69\u5b9a\u5668\u3001\u81ea\u5e73\u8861\u6a5f\u5668\u4eba\u6216\u5176\u4ed6\u9589\u8ff4\u8def\u7cfb\u7d71\u7684\u958b\u767c\u8005\u4f86\u8aaa\uff0c\u9019\u6a23\u7684\u983b\u8b5c\u8a3a\u65b7\u65b9\u6cd5\uff0c\u5c31\u50cf\u662f\u52a0\u4e86\u4e00\u96d9\u300c\u983b\u7387\u57df\u7684\u773c\u775b\u300d\uff0c\u8b93\u4f60\u4e0d\u518d\u76f2\u8abf\u53c3\u6578\uff0c\u800c\u662f<strong>\u770b\u898b\u554f\u984c\u672c\u8cea\uff0c\u7cbe\u6e96\u4fee\u6b63<\/strong>\u3002<\/p>\n\n\n\n<hr class=\"wp-block-separator alignwide has-text-color has-palette-color-1-color has-alpha-channel-opacity has-palette-color-1-background-color has-background is-style-wide\"\/>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Fourier + PID \u63a7\u5236\u5668 \u662f\u81ea\u52d5\u63a7\u5236\u9818\u57df\u4e2d\u6b77\u4e45\u4e0d\u8870\u7684\u7d44\u5408\u3002\u6211\u5011\u4e0d\u53ea\u662f\u8abf PID\uff0c\u6211\u5011\u8b93 PID \u6703\u770b [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3728,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2,53,83],"tags":[27,21,44,9,11],"class_list":["post-3724","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-module","category-esp32","category-featured","tag-c","tag-ide","tag-programming-language","tag-python","tag-tutorial"],"blocksy_meta":[],"_links":{"self":[{"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/posts\/3724","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/comments?post=3724"}],"version-history":[{"count":15,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/posts\/3724\/revisions"}],"predecessor-version":[{"id":3742,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/posts\/3724\/revisions\/3742"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/media\/3728"}],"wp:attachment":[{"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/media?parent=3724"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/categories?post=3724"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/saludpcb.com\/zh\/wp-json\/wp\/v2\/tags?post=3724"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}