FIRST

第一個測試的日誌
提供了基于BP(Back Propagation)神经网络结合PID(比例-积分-微分)控制策略的Simulink仿真模型。该模型旨在实现对杨艺所著论文《基于S函数的BP神经网络PID控制器及Simulink仿真》中的理论进行实践验证。在Matlab 2016b环境下开发,经过测试,确保能够正常运行,适合学习和研究神经网络在控制系统中的应用。 特点 集成BP神经网络:模型中集成了BP神经网络用于提升PID控制器的性能,使之能更好地适应复杂控制环境。 PID控制优化:利用神经网络的自学习能力,对传统的PID控制算法进行了智能调整,提高控制精度和稳定性。 S函数应用:展示了如何在Simulink中通过S函数嵌入MATLAB代码,实现BP神经网络的定制化逻辑。 兼容性说明:虽然开发于Matlab 2016b,但理论上兼容后续版本,可能会需要调整少量配置以适配不同版本的Matlab。 使用指南 环境要求:确保你的电脑上安装有Matlab 2016b或更高版本。 模型加载: 下载本仓库到本地。 在Matlab中打开.slx文件。 运行仿真: 调整模型参数前,请先熟悉各模块功能和输入输出设置。 运行整个模型,观察控制效果。 参数调整: 用户可以自由调节神经网络的层数、节点数以及PID控制器的参数,探索不同的控制性能。 学习和修改: 通过阅读模型中的注释和查阅相关文献,加深对BP神经网络与PID控制结合的理解。 如需修改S函数内的MATLAB代码,建议有一定的MATLAB编程基础。
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "../include/menu_system.h" /*===================================================================================================================================*/ /* Module Constants */ /*===================================================================================================================================*/ static const U1 u1_s_MENU_first_level_names[(U1)FIRST_LEVEL_MENU_COUNT] = {'A', 'B', 'C'}; static const U1 u1_s_MENU_second_level_names[(U1)FIRST_LEVEL_MENU_COUNT][(U1)SECOND_LEVEL_MENU_COUNT][(U1)DATATHREE] = { {"A1", "A2", "A3"}, {"B1", "B2", "B3"}, {"C1", "C2", "C3"} }; /*===================================================================================================================================*/ /* Global Menu System */ /*===================================================================================================================================*/ ST_MENU_SYSTEM st_g_MENU_system; /*===================================================================================================================================*/ /* Function Name: v_g_MENU_initializeSystem */ /* --------------------------------------------------------------------------------------------------------------------------------- */ /* Description: Initializes the menu system with doubly linked lists */ /* Arguments: void */ /* Return: void */ /*===================================================================================================================================*/ void v_g_MENU_initializeSystem(void) { U1 u1_t_first_index; U1 u1_t_second_index; ST_FIRST_LEVEL_MENU_NODE* stp_t_prev_first; ST_FIRST_LEVEL_MENU_NODE* stp_t_current_first; ST_SECOND_LEVEL_MENU_NODE* stp_t_prev_second[(U1)FIRST_LEVEL_MENU_COUNT]; ST_SECOND_LEVEL_MENU_NODE* stp_t_horizontal_prev[(U1)SECOND_LEVEL_MENU_COUNT]; /* Initialize first level menu nodes */ stp_t_prev_first = (ST_FIRST_LEVEL_MENU_NODE*)NULL; for (u1_t_first_index = (U1)DATAZERO; u1_t_first_index < (U1)FIRST_LEVEL_MENU_COUNT; u1_t_first_index++) { stp_t_current_first = (ST_FIRST_LEVEL_MENU_NODE*)malloc(sizeof(ST_FIRST_LEVEL_MENU_NODE)); if (stp_t_current_first != (ST_FIRST_LEVEL_MENU_NODE*)NULL) { stp_t_current_first->u1_t_menu_id = u1_t_first_index; stp_t_current_first->u1p_t_menu_name = (U1P)&u1_s_MENU_first_level_names[u1_t_first_index]; stp_t_current_first->stp_t_prev = stp_t_prev_first; stp_t_current_first->stp_t_next = (ST_FIRST_LEVEL_MENU_NODE*)NULL; stp_t_current_first->stp_t_second_level_head = NULL; if (stp_t_prev_first != (ST_FIRST_LEVEL_MENU_NODE*)NULL) { stp_t_prev_first->stp_t_next = stp_t_current_first; } else { st_g_MENU_system.stp_t_first_level_head = stp_t_current_first; } stp_t_prev_first = stp_t_current_first; /* Initialize second level menu nodes for this first level */ stp_t_prev_second[u1_t_first_index] = NULL; for (u1_t_second_index = (U1)DATAZERO; u1_t_second_index < SECOND_LEVEL_MENU_COUNT; u1_t_second_index++) { ST_SECOND_LEVEL_MENU_NODE* stp_t_current_second; stp_t_current_second = (ST_SECOND_LEVEL_MENU_NODE*)malloc(sizeof(ST_SECOND_LEVEL_MENU_NODE)); if (stp_t_current_second != NULL) { stp_t_current_second->u1_t_menu_id = u1_t_second_index; stp_t_current_second->u1p_t_menu_name = (U1P)&u1_s_MENU_second_level_names[u1_t_first_index][u1_t_second_index]; stp_t_current_second->stp_t_prev = stp_t_prev_second[u1_t_first_index]; stp_t_current_second->stp_t_next = NULL; stp_t_current_second->stp_t_horizontal_prev = NULL; stp_t_current_second->stp_t_horizontal_next = NULL; stp_t_current_second->stp_t_parent = stp_t_current_first; if (stp_t_prev_second[u1_t_first_index] != NULL) { stp_t_prev_second[u1_t_first_index]->stp_t_next = stp_t_current_second; } else { stp_t_current_first->stp_t_second_level_head = stp_t_current_second; } stp_t_prev_second[u1_t_first_index] = stp_t_current_second; } } /* Make vertical list circular */ if (stp_t_current_first->stp_t_second_level_head != NULL) { stp_t_prev_second[u1_t_first_index]->stp_t_next = stp_t_current_first->stp_t_second_level_head; stp_t_current_first->stp_t_second_level_head->stp_t_prev = stp_t_prev_second[u1_t_first_index]; } } } /* Make first level list circular */ if (st_g_MENU_system.stp_t_first_level_head != (ST_FIRST_LEVEL_MENU_NODE*)NULL) { stp_t_prev_first->stp_t_next = st_g_MENU_system.stp_t_first_level_head; st_g_MENU_system.stp_t_first_level_head->stp_t_prev = stp_t_prev_first; } /* Build horizontal links between second level menus */ for (u1_t_second_index = (U1)DATAZERO; u1_t_second_index < SECOND_LEVEL_MENU_COUNT; u1_t_second_index++) { ST_FIRST_LEVEL_MENU_NODE* stp_t_first_iter; ST_SECOND_LEVEL_MENU_NODE* stp_t_second_iter; stp_t_horizontal_prev[u1_t_second_index] = NULL; stp_t_first_iter = st_g_MENU_system.stp_t_first_level_head; /* Find the second level node at position u1_t_second_index for each first level */ while (stp_t_first_iter != (ST_FIRST_LEVEL_MENU_NODE*)NULL) { stp_t_second_iter = stp_t_first_iter->stp_t_second_level_head; /* Traverse to the correct position in vertical list */ for (u1_t_first_index = (U1)DATAZERO; u1_t_first_index < u1_t_second_index; u1_t_first_index++) { if (stp_t_second_iter != NULL) { stp_t_second_iter = stp_t_second_iter->stp_t_next; } } if (stp_t_second_iter != NULL) { if (stp_t_horizontal_prev[u1_t_second_index] != NULL) { stp_t_horizontal_prev[u1_t_second_index]->stp_t_horizontal_next = stp_t_second_iter; stp_t_second_iter->stp_t_horizontal_prev = stp_t_horizontal_prev[u1_t_second_index]; } stp_t_horizontal_prev[u1_t_second_index] = stp_t_second_iter; } stp_t_first_iter = (stp_t_first_iter->stp_t_next != st_g_MENU_system.stp_t_first_level_head) ? stp_t_first_iter->stp_t_next : (ST_FIRST_LEVEL_MENU_NODE*)NULL; } /* Make horizontal list circular */ if (st_g_MENU_system.stp_t_first_level_head != (ST_FIRST_LEVEL_MENU_NODE*)NULL && stp_t_horizontal_prev[u1_t_second_index] != NULL) { ST_SECOND_LEVEL_MENU_NODE* stp_t_first_horizontal; stp_t_first_horizontal = st_g_MENU_system.stp_t_first_level_head->stp_t_second_level_head; /* Traverse to the correct position */ for (u1_t_first_index = (U1)DATAZERO; u1_t_first_index < u1_t_second_index; u1_t_first_index++) { if (stp_t_first_horizontal != NULL) { stp_t_first_horizontal = stp_t_first_horizontal->stp_t_next; } } if (stp_t_first_horizontal != NULL) { stp_t_horizontal_prev[u1_t_second_index]->stp_t_horizontal_next = stp_t_first_horizontal; stp_t_first_horizontal->stp_t_horizontal_prev = stp_t_horizontal_prev[u1_t_second_index]; } } } /* Set initial state to A2 */ st_g_MENU_system.u1_t_current_state = MENU_STATE_SECOND_LEVEL; st_g_MENU_system.stp_t_current_first_level = st_g_MENU_system.stp_t_first_level_head; /* A */ /* Find A2 in the second level list */ if (st_g_MENU_system.stp_t_current_first_level != (ST_FIRST_LEVEL_MENU_NODE*)NULL && st_g_MENU_system.stp_t_current_first_level->stp_t_second_level_head != NULL) { st_g_MENU_system.stp_t_current_second_level = st_g_MENU_system.stp_t_current_first_level->stp_t_second_level_head->stp_t_next; /* A2 */ } } /*===================================================================================================================================*/ /* Function Name: v_g_MENU_cleanupSystem */ /* --------------------------------------------------------------------------------------------------------------------------------- */ /* Description: Cleans up the menu system and frees memory */ /* Arguments: void */ /* Return: void */ /*===================================================================================================================================*/ void v_g_MENU_cleanupSystem(void) { ST_FIRST_LEVEL_MENU_NODE* stp_t_first_iter; ST_FIRST_LEVEL_MENU_NODE* stp_t_first_temp; ST_SECOND_LEVEL_MENU_NODE* stp_t_second_iter; ST_SECOND_LEVEL_MENU_NODE* stp_t_second_temp; U1 u1_t_first_count; if (st_g_MENU_system.stp_t_first_level_head != NULL) { stp_t_first_iter = st_g_MENU_system.stp_t_first_level_head; u1_t_first_count = (U1)DATAZERO; do { /* Free second level nodes */ if (stp_t_first_iter->stp_t_second_level_head != NULL) { stp_t_second_iter = stp_t_first_iter->stp_t_second_level_head; U1 u1_t_second_count = (U1)DATAZERO; do { stp_t_second_temp = stp_t_second_iter; stp_t_second_iter = stp_t_second_iter->stp_t_next; free(stp_t_second_temp); u1_t_second_count++; } while ((stp_t_second_iter != stp_t_first_iter->stp_t_second_level_head) && (u1_t_second_count < (U1)SECOND_LEVEL_MENU_COUNT)); } stp_t_first_temp = stp_t_first_iter; stp_t_first_iter = stp_t_first_iter->stp_t_next; free(stp_t_first_temp); u1_t_first_count++; } while (stp_t_first_iter != st_g_MENU_system.stp_t_first_level_head && u1_t_first_count < (U1)FIRST_LEVEL_MENU_COUNT); } } /*===================================================================================================================================*/ /* Function Name: u1_g_MENU_getKeyboardInput */ /* --------------------------------------------------------------------------------------------------------------------------------- */ /* Description: Gets keyboard input and converts to key ID */ /* Arguments: void */ /* Return: U1 : Key ID */ /*===================================================================================================================================*/ U1 u1_g_MENU_getKeyboardInput(void) { U1 u1_t_input_buffer[100]; /* Increased buffer size for safety */ U1 u1_t_return_value; S4 s4_t_scanf_result; U1 u1_t_input_length; u1_t_return_value = (U1)KEY_NONE; /* Clear input buffer first */ fflush(stdin); /* Print input prompt */ printf("\nEnter command (W=Up, A=Left, S=Down, D=Right, Q=Quit): "); fflush(stdout); s4_t_scanf_result = scanf("%99s", u1_t_input_buffer); /* Limit input to 99 characters */ if (s4_t_scanf_result == (U1)DATAONE) { /* Get input length for validation */ u1_t_input_length = (U1)strlen((const char*)u1_t_input_buffer); /* Only process single character inputs */ if (u1_t_input_length == (U1)DATAONE) { switch(u1_t_input_buffer[(U1)DATAZERO]) { case 'a': case 'A': u1_t_return_value = KEY_LEFT; break; case 'd': case 'D': u1_t_return_value = KEY_RIGHT; break; case 'w': case 'W': u1_t_return_value = KEY_UP; break; case 's': case 'S': u1_t_return_value = KEY_DOWN; break; case 'q': case 'Q': u1_t_return_value = KEY_QUIT; break; default: u1_t_return_value = KEY_NONE; break; } } else { /* Input too long */ printf("Error: Please enter only one character\n"); u1_t_return_value = KEY_NONE; } } else { /* scanf failed */ printf("Error: Failed to read input\n"); u1_t_return_value = KEY_NONE; } /* Clear any remaining characters in input buffer */ while (getchar() != '\n'); return u1_t_return_value; } /*===================================================================================================================================*/ /* Function Name: v_g_MENU_printCurrentMenu */ /* --------------------------------------------------------------------------------------------------------------------------------- */ /* Description: Prints currently selected menu item */ /* Arguments: void */ /* Return: void */ /*===================================================================================================================================*/ void v_g_MENU_printCurrentMenu(void) { if (st_g_MENU_system.u1_t_current_state == MENU_STATE_FIRST_LEVEL) { if (st_g_MENU_system.stp_t_current_first_level != NULL) { printf("Current Selection: %c\n", *(st_g_MENU_system.stp_t_current_first_level->u1p_t_menu_name)); } } else { if (st_g_MENU_system.stp_t_current_second_level != NULL) { printf("Current Selection: %s\n", st_g_MENU_system.stp_t_current_second_level->u1p_t_menu_name); } } } /*===================================================================================================================================*/ /* Function Name: v_g_MENU_printMenuStatus */ /* --------------------------------------------------------------------------------------------------------------------------------- */ /* Description: Prints complete menu status */ /* Arguments: void */ /* Return: void */ /*===================================================================================================================================*/ void v_g_MENU_printMenuStatus(void) { ST_FIRST_LEVEL_MENU_NODE* stp_t_first_iter; ST_SECOND_LEVEL_MENU_NODE* stp_t_second_iter; U1 u1_t_first_count; printf("\n=== Menu Navigation System ===\n"); printf("Menu State: %s\n", (st_g_MENU_system.u1_t_current_state == MENU_STATE_FIRST_LEVEL) ? "FIRST LEVEL" : "SECOND LEVEL"); printf("First Level: "); stp_t_first_iter = st_g_MENU_system.stp_t_first_level_head; u1_t_first_count = (U1)DATAZERO; if (stp_t_first_iter != NULL) { do { if (stp_t_first_iter == st_g_MENU_system.stp_t_current_first_level && st_g_MENU_system.u1_t_current_state == MENU_STATE_FIRST_LEVEL) { printf("[%c] ", *(stp_t_first_iter->u1p_t_menu_name)); } else { printf(" %c ", *(stp_t_first_iter->u1p_t_menu_name)); } stp_t_first_iter = stp_t_first_iter->stp_t_next; u1_t_first_count++; } while (stp_t_first_iter != st_g_MENU_system.stp_t_first_level_head && u1_t_first_count < (U1)FIRST_LEVEL_MENU_COUNT); } printf("\nSecond Level: "); stp_t_first_iter = st_g_MENU_system.stp_t_first_level_head; u1_t_first_count = (U1)DATAZERO; if (stp_t_first_iter != NULL) { do { stp_t_second_iter = stp_t_first_iter->stp_t_second_level_head; if (stp_t_second_iter != NULL) { U1 u1_t_second_count = (U1)DATAZERO; do { if (stp_t_second_iter == st_g_MENU_system.stp_t_current_second_level && st_g_MENU_system.u1_t_current_state == MENU_STATE_SECOND_LEVEL) { printf("[%s] ", stp_t_second_iter->u1p_t_menu_name); } else { printf(" %s ", stp_t_second_iter->u1p_t_menu_name); } stp_t_second_iter = stp_t_second_iter->stp_t_next; u1_t_second_count++; } while (stp_t_second_iter != stp_t_first_iter->stp_t_second_level_head && u1_t_second_count < SECOND_LEVEL_MENU_COUNT); } if (u1_t_first_count < ((U1)FIRST_LEVEL_MENU_COUNT - (U1)DATAONE)) { printf("| "); } stp_t_first_iter = stp_t_first_iter->stp_t_next; u1_t_first_count++; } while (stp_t_first_iter != st_g_MENU_system.stp_t_first_level_head && u1_t_first_count < (U1)FIRST_LEVEL_MENU_COUNT); } printf("\n"); } /*===================================================================================================================================*/ /* Function Name: v_g_MENU_handleKeyEvent */ /* --------------------------------------------------------------------------------------------------------------------------------- */ /* Description: Handles key event and updates menu position */ /* Arguments: const U1 u1_a_key_id : Key ID */ /* Return: void */ /*===================================================================================================================================*/ void v_g_MENU_handleKeyEvent(const U1 u1_a_key_id) { switch (u1_a_key_id) { case (U1)KEY_LEFT: if ((U1)MENU_STATE_FIRST_LEVEL == st_g_MENU_system.u1_t_current_state) { /* Move left in first level circular list */ if (st_g_MENU_system.stp_t_current_first_level != NULL) { st_g_MENU_system.stp_t_current_first_level = st_g_MENU_system.stp_t_current_first_level->stp_t_prev; } } else { /* Move left in second level horizontal circular list */ if (st_g_MENU_system.stp_t_current_second_level != NULL) { st_g_MENU_system.stp_t_current_second_level = st_g_MENU_system.stp_t_current_second_level->stp_t_horizontal_prev; if (st_g_MENU_system.stp_t_current_second_level != NULL) { st_g_MENU_system.stp_t_current_first_level = st_g_MENU_system.stp_t_current_second_level->stp_t_parent; } } } break; case (U1)KEY_RIGHT: if ((U1)MENU_STATE_FIRST_LEVEL == st_g_MENU_system.u1_t_current_state) { /* Move right in first level circular list */ if (st_g_MENU_system.stp_t_current_first_level != NULL) { st_g_MENU_system.stp_t_current_first_level = st_g_MENU_system.stp_t_current_first_level->stp_t_next; } } else { /* Move right in second level horizontal circular list */ if (st_g_MENU_system.stp_t_current_second_level != NULL) { st_g_MENU_system.stp_t_current_second_level = st_g_MENU_system.stp_t_current_second_level->stp_t_horizontal_next; if (st_g_MENU_system.stp_t_current_second_level != NULL) { st_g_MENU_system.stp_t_current_first_level = st_g_MENU_system.stp_t_current_second_level->stp_t_parent; } } } break; case (U1)KEY_UP: if ((U1)MENU_STATE_FIRST_LEVEL == st_g_MENU_system.u1_t_current_state) { /* Up key does nothing in first level */ } else { /* Check if we're at A1/B1/C1 - if so, jump to first level */ if (st_g_MENU_system.stp_t_current_second_level != NULL && st_g_MENU_system.stp_t_current_second_level->u1_t_menu_id == (U1)DATAZERO) { /* We're at A1/B1/C1, jump to first level */ st_g_MENU_system.u1_t_current_state = MENU_STATE_FIRST_LEVEL; } else { /* Move up in second level vertical circular list */ if (st_g_MENU_system.stp_t_current_second_level != NULL) { st_g_MENU_system.stp_t_current_second_level = st_g_MENU_system.stp_t_current_second_level->stp_t_prev; } } } break; case (U1)KEY_DOWN: if ((U1)MENU_STATE_FIRST_LEVEL == st_g_MENU_system.u1_t_current_state) { /* Special patch: jump to corresponding A1/B1/C1 in second level */ if (st_g_MENU_system.stp_t_current_first_level != NULL && st_g_MENU_system.stp_t_current_first_level->stp_t_second_level_head != NULL) { st_g_MENU_system.stp_t_current_second_level = st_g_MENU_system.stp_t_current_first_level->stp_t_second_level_head; st_g_MENU_system.u1_t_current_state = MENU_STATE_SECOND_LEVEL; } } else { /* Move down in second level vertical circular list */ if (st_g_MENU_system.stp_t_current_second_level != NULL) { st_g_MENU_system.stp_t_current_second_level = st_g_MENU_system.stp_t_current_second_level->stp_t_next; } } break; default: /* No operation for other keys */ break; v_g_MENU_printCurrentMenu(); } } 不修改任何代码,只是加点注释,形如/* English */
10-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值