当前位置:   article > 正文

蓝牙控制三轴机械臂_蓝牙模块控制步进电机

蓝牙模块控制步进电机

    前言,emm,确实,已经在视觉控制部分卡了很久了 ,查了很多资料,目前,对于专业做机器臂的企业用的大多是用的路径规划,它涉及到了人工智能方向,但在本科生阶段,大多用的是一种叫运动学逆解的思路,它用到的是解三角函数的方式,这是对于低自由度的,对于高自由度的还会用到现代控制理论的知识,,只能说,创作之路略微小小小小的困难. 

准备物品:

STM32F407VET6 、STM32F103C8T6、HC05蓝牙模块,两块HC06模块 三块步进电机驱动器, 一台三轴机械臂

  

  1. 主体思路:想做的是一个三轴机械臂,能实现蓝牙控制和视觉抓取(目前只完成蓝牙控制)  用手机连接一块HC06蓝牙,当收到手机的指令后,在单片机(c8t6和vet6的控制下,完成简单的三轴运动)。                                                     

     5步骤:  

    1.STM32407ZGT6 

      这里的VET6主要担任了两个任务,一个是接收手机的数据,并发送给c8t6,另一个就是控制三个步进电机,步进电机只要控制,而控制步进电机需要一个驱动器,在驱动器的作用下,我们只要对其输入脉冲电机就能够旋转,输入高低电平,电机便能正转和反转, 具体如下: 

    1. /* USER CODE BEGIN Header */
    2. /**
    3. ******************************************************************************
    4. * @file : main.c
    5. * @brief : Main program body
    6. ******************************************************************************
    7. * @attention
    8. *
    9. * Copyright (c) 2022 STMicroelectronics.
    10. * All rights reserved.
    11. *
    12. * This software is licensed under terms that can be found in the LICENSE file
    13. * in the root directory of this software component.
    14. * If no LICENSE file comes with this software, it is provided AS-IS.
    15. *
    16. ******************************************************************************
    17. */
    18. /* USER CODE END Header */
    19. /* Includes ------------------------------------------------------------------*/
    20. #include "main.h"
    21. #include "i2c.h"
    22. #include "tim.h"
    23. #include "usart.h"
    24. #include "gpio.h"
    25. /* Private includes ----------------------------------------------------------*/
    26. /* USER CODE BEGIN Includes */
    27. /* USER CODE END Includes */
    28. /* Private typedef -----------------------------------------------------------*/
    29. /* USER CODE BEGIN PTD */
    30. /* USER CODE END PTD */
    31. /* Private define ------------------------------------------------------------*/
    32. /* USER CODE BEGIN PD */
    33. /* USER CODE END PD */
    34. /* Private macro -------------------------------------------------------------*/
    35. /* USER CODE BEGIN PM */
    36. /* USER CODE END PM */
    37. /* Private variables ---------------------------------------------------------*/
    38. /* USER CODE BEGIN PV */
    39. /* USER CODE END PV */
    40. /* Private function prototypes -----------------------------------------------*/
    41. void SystemClock_Config(void);
    42. /* USER CODE BEGIN PFP */
    43. #define USART_REC_LEN 200
    44. uint8_t Res ,S; //数据存放的地方
    45. uint8_t USART2_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.(一般给200,接收数据量大就增加)
    46. uint16_t USART2_RX_STA; //接收状态标记
    47. /* USER CODE END PFP */
    48. /* Private user code ---------------------------------------------------------*/
    49. /* USER CODE BEGIN 0 */
    50. uint8_t send_str0[]="8";
    51. uint8_t send_str1[]="9";
    52. /* USER CODE END 0 */
    53. /**
    54. * @brief The application entry point.
    55. * @retval int
    56. */
    57. int main(void)
    58. {
    59. /* USER CODE BEGIN 1 */
    60. /* USER CODE END 1 */
    61. /* MCU Configuration--------------------------------------------------------*/
    62. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    63. HAL_Init();
    64. /* USER CODE BEGIN Init */
    65. /* USER CODE END Init */
    66. /* Configure the system clock */
    67. SystemClock_Config();
    68. /* USER CODE BEGIN SysInit */
    69. /* USER CODE END SysInit */
    70. /* Initialize all configured peripherals */
    71. MX_GPIO_Init();
    72. MX_I2C1_Init();
    73. MX_TIM1_Init();
    74. MX_USART1_UART_Init();
    75. MX_USART2_UART_Init();
    76. /* USER CODE BEGIN 2 */
    77. HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
    78. HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_2);
    79. HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_3);
    80. HAL_UART_Receive_IT(&huart2, &Res, 1);
    81. HAL_UART_Transmit_IT(&huart1, &Res, 1);
    82. /* USER CODE END 2 */
    83. /* Infinite loop */
    84. /* USER CODE BEGIN WHILE */
    85. while (1)
    86. {
    87. HAL_Delay(100);
    88. USART2_RX_BUF[0]=S;
    89. /* USER CODE END WHILE */
    90. /* USER CODE BEGIN 3 */
    91. //if(USART1_RX_STA & 0x8000)// 1000 0000 0000 0000 0000 判断是否接受到
    92. //{
    93. //
    94. // while(huart1.gState != HAL_UART_STATE_READY){};
    95. if( USART2_RX_BUF[0]== '1') // 当收到字符'1'的时候 机械臂向上运动
    96. {__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,100); //定时器1通道1输出一段脉冲
    97. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,0);//屏蔽定时器1通道2
    98. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);//屏蔽定时器1通道3
    99. HAL_Delay(1);
    100. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_RESET); //F407引脚 输出 低电平 使其向上运动
    101. }
    102. if(USART2_RX_BUF[0]== '2') // 当收到字符'2' 的时候 机械臂向下运动
    103. {__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,100);//定时器1通道1输出一段脉冲
    104. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,0);//屏蔽定时器1通道2
    105. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0); //屏蔽定时器1通道3
    106. HAL_Delay(1);
    107. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_4,GPIO_PIN_SET); //F407引脚 输出 高电平 使其向下运动
    108. }
    109. if(USART2_RX_BUF[0]== '3') // 当收到字符'3' 的时候 机械臂向左运动
    110. {
    111. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,100);//定时器1通道2输出一段脉冲
    112. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,0);//屏蔽定时器1通道1
    113. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);//屏蔽定时器1通道3
    114. HAL_Delay(1);
    115. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_RESET);//F407引脚 输出 低电平 使其向左运动
    116. }
    117. if(USART2_RX_BUF[0]== '4') // 当收到字符'4'的时候 机械臂向右运动
    118. {
    119. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,100);//定时器1通道2输出一段脉冲
    120. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,0);//屏蔽定时器1通道1
    121. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);//屏蔽定时器1通道3
    122. HAL_Delay(1);
    123. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_5,GPIO_PIN_SET);//F407引脚 输出 高电平 使其向右运动
    124. }
    125. if(USART2_RX_BUF[0]== '5') // 当收到字符'5'的时候 机械臂向前运动
    126. {
    127. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,100);//定时器1 通道3输出一段脉冲
    128. HAL_Delay(1);
    129. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_RESET);//F407引脚 输出 低电平 使其向前运动
    130. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,0); //屏蔽定时器1通道1
    131. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,0); //屏蔽定时器1通道2
    132. }
    133. if(USART2_RX_BUF[0]== '6') // 当收到字符'6'的时候 机械臂向后运动
    134. {
    135. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,100);//定时器1 通道3 输出一段脉冲
    136. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,0);//屏蔽定时器1通道2
    137. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,0);//屏蔽定时器1通道1
    138. HAL_Delay(1);
    139. HAL_GPIO_WritePin(GPIOA,GPIO_PIN_6,GPIO_PIN_SET);//F407引脚 输出 高电平 使其向后运动
    140. }
    141. if(USART2_RX_BUF[0]== 'A') // 当收到字符'6'的时候 机械臂停止
    142. {
    143. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);//定时器1 通道3 输出一段脉冲
    144. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,0);//屏蔽定时器1通道2
    145. __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,0);//屏蔽定时器1通道1
    146. HAL_Delay(1);
    147. }
    148. USART2_RX_STA=0;
    149. }
    150. HAL_Delay(10);
    151. }
    152. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    153. {
    154. /* 判断是哪个串口触发的中断 */
    155. if(huart ->Instance == USART2)
    156. {
    157. S=Res;
    158. HAL_UART_Transmit(&huart1,&S,1,1000);
    159. //等待下一次接收中断
    160. HAL_UART_Receive_IT(huart,&Res,1);
    161. }
    162. }
    163. /* USER CODE END 3 */
    164. /**
    165. * @brief System Clock Configuration
    166. * @retval None
    167. */
    168. void SystemClock_Config(void)
    169. {
    170. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    171. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    172. /** Configure the main internal regulator output voltage
    173. */
    174. __HAL_RCC_PWR_CLK_ENABLE();
    175. __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
    176. /** Initializes the RCC Oscillators according to the specified parameters
    177. * in the RCC_OscInitTypeDef structure.
    178. */
    179. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
    180. RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    181. RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
    182. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
    183. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    184. {
    185. Error_Handler();
    186. }
    187. /** Initializes the CPU, AHB and APB buses clocks
    188. */
    189. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    190. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    191. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
    192. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    193. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
    194. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    195. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
    196. {
    197. Error_Handler();
    198. }
    199. }
    200. /* USER CODE BEGIN 4 */
    201. /* USER CODE END 4 */
    202. /**
    203. * @brief This function is executed in case of error occurrence.
    204. * @retval None
    205. */
    206. void Error_Handler(void)
    207. {
    208. /* USER CODE BEGIN Error_Handler_Debug */
    209. /* User can add his own implementation to report the HAL error return state */
    210. __disable_irq();
    211. while (1)
    212. {
    213. }
    214. /* USER CODE END Error_Handler_Debug */
    215. }
    216. #ifdef USE_FULL_ASSERT
    217. /**
    218. * @brief Reports the name of the source file and the source line number
    219. * where the assert_param error has occurred.
    220. * @param file: pointer to the source file name
    221. * @param line: assert_param error line source number
    222. * @retval None
    223. */
    224. void assert_failed(uint8_t *file, uint32_t line)
    225. {
    226. /* USER CODE BEGIN 6 */
    227. /* User can add his own implementation to report the file name and line number,
    228. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    229. /* USER CODE END 6 */
    230. }
    231. #endif /* USE_FULL_ASSERT */

      这是main.c里面的文件,思路很简单,就是,用 串口2接收来自手机的信号 具体是'1'  '2 '  '3'  '4' '5'  '6'  '7'  '8' 注意,这里传输的字符, 同时用串口1把这个数据发送给另一块单片机c8t6(为什么还要用一块单片机呢  ,因为抓取的爪子距离 zgt6 太远了,,所以干脆直接在那附近加一块单片机单独控制,)收到1.2 3 时根据不同情况输出一段pwm,控制器机械臂运动  

  2.  这是cubemx 的引脚图,也是相当明朗,用到了,定时器1的三个通道.还有两个串口 ,IIC是用来显示坐标的 但视觉部分还未加载,所以 ,目前没有用的   ,,同时用三个角PE9 到PE13输出高低电平,因为机械臂的电机时步进电机,输出高低时会控制正反转,当然了,控制步进电机还需要 步进电机驱动器 

    1. /* USER CODE BEGIN Header */
    2. /**
    3. ******************************************************************************
    4. * @file : main.c
    5. * @brief : Main program body
    6. ******************************************************************************
    7. * @attention
    8. *
    9. * Copyright (c) 2023 STMicroelectronics.
    10. * All rights reserved.
    11. *
    12. * This software is licensed under terms that can be found in the LICENSE file
    13. * in the root directory of this software component.
    14. * If no LICENSE file comes with this software, it is provided AS-IS.
    15. *
    16. ******************************************************************************
    17. */
    18. /* USER CODE END Header */
    19. /* Includes ------------------------------------------------------------------*/
    20. #include "main.h"
    21. #include "tim.h"
    22. #include "usart.h"
    23. #include "gpio.h"
    24. /* Private includes ----------------------------------------------------------*/
    25. /* USER CODE BEGIN Includes */
    26. /* USER CODE END Includes */
    27. /* Private typedef -----------------------------------------------------------*/
    28. /* USER CODE BEGIN PTD */
    29. /* USER CODE END PTD */
    30. /* Private define ------------------------------------------------------------*/
    31. /* USER CODE BEGIN PD */
    32. /* USER CODE END PD */
    33. /* Private macro -------------------------------------------------------------*/
    34. /* USER CODE BEGIN PM */
    35. /* USER CODE END PM */
    36. /* Private variables ---------------------------------------------------------*/
    37. /* USER CODE BEGIN PV */
    38. /* USER CODE END PV */
    39. /* Private function prototypes -----------------------------------------------*/
    40. void SystemClock_Config(void);
    41. /* USER CODE BEGIN PFP */
    42. #define USART_REC_LEN 200
    43. uint8_t Res; //数据存放的地方
    44. uint8_t USART1_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.(一般给200,接收数据量大就增加)
    45. uint16_t USART1_RX_STA; //接收状态标记
    46. /* USER CODE END PFP */
    47. /* USER CODE END PFP */
    48. /* Private user code ---------------------------------------------------------*/
    49. /* USER CODE BEGIN 0 */
    50. /* USER CODE END 0 */
    51. /**
    52. * @brief The application entry point.
    53. * @retval int
    54. */
    55. int main(void)
    56. {
    57. /* USER CODE BEGIN 1 */
    58. /* USER CODE END 1 */
    59. /* MCU Configuration--------------------------------------------------------*/
    60. /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
    61. HAL_Init();
    62. /* USER CODE BEGIN Init */
    63. /* USER CODE END Init */
    64. /* Configure the system clock */
    65. SystemClock_Config();
    66. /* USER CODE BEGIN SysInit */
    67. /* USER CODE END SysInit */
    68. /* Initialize all configured peripherals */
    69. MX_GPIO_Init();
    70. MX_TIM3_Init();
    71. MX_USART1_UART_Init();
    72. HAL_TIM_PWM_Start(&htim3,TIM_CHANNEL_1);
    73. HAL_UART_Receive_IT(&huart1, &Res, 1);
    74. /* USER CODE BEGIN 2 */
    75. /* USER CODE END 2 */
    76. /* Infinite loop */
    77. /* USER CODE BEGIN WHILE */
    78. while (1)
    79. {
    80. /* USER CODE END WHILE */
    81. if(USART1_RX_STA & 0x8000)// 1000 0000 0000 0000 0000 判断是否接受到
    82. {
    83. while(huart1.gState != HAL_UART_STATE_READY){};
    84. if( USART1_RX_BUF[0]== '8') // 当收到字符'1'的时候 机械臂向上运动
    85. {__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,500); //定时器1通道1输出一段脉冲
    86. HAL_Delay(1);
    87. }
    88. if( USART1_RX_BUF[0]== '9')
    89. {__HAL_TIM_SET_COMPARE(&htim3,TIM_CHANNEL_1,0);
    90. HAL_Delay(1);
    91. }
    92. // if(USART1_RX_BUF[0]== '7')
    93. // {
    94. // __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,0);
    95. // HAL_Delay(10);
    96. // }
    97. // if(USART1_RX_BUF[0]== '8')
    98. // { __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,0);
    99. // __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_2,0);
    100. // __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_3,0);
    101. //
    102. // }
    103. //
    104. // else
    105. // {
    106. // __HAL_TIM_SET_COMPARE(&htim2,TIM_CHANNEL_1,25);
    107. // }
    108. USART1_RX_STA=0;
    109. }
    110. HAL_Delay(10);
    111. /* USER CODE BEGIN 3 */
    112. }
    113. /* USER CODE END 3 */
    114. }
    115. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
    116. {
    117. /* 判断是哪个串口触发的中断 */
    118. if(huart ->Instance == USART1)
    119. {
    120. if((USART1_RX_STA&0x8000)==0)//接收未完成
    121. {
    122. //读取接收到的数据
    123. if(Res==0x0D)
    124. {
    125. USART1_RX_STA|=0x8000;//读取到数据 标志位置1
    126. HAL_UART_Receive_IT(&huart1, &Res, 1);//接收的数据存到Res
    127. }
    128. else
    129. {
    130. USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res;// Res的数据
    131. USART1_RX_STA++;
    132. if(USART1_RX_STA>(USART_REC_LEN-1))
    133. USART1_RX_STA=0;
    134. }
    135. }
    136. //等待下一次接收中断
    137. HAL_UART_Receive_IT(huart,&Res,1);
    138. }
    139. }
    140. /**
    141. * @brief System Clock Configuration
    142. * @retval None
    143. */
    144. void SystemClock_Config(void)
    145. {
    146. RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    147. RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
    148. /** Initializes the RCC Oscillators according to the specified parameters
    149. * in the RCC_OscInitTypeDef structure.
    150. */
    151. RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    152. RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    153. RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
    154. RCC_OscInitStruct.HSIState = RCC_HSI_ON;
    155. RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    156. RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    157. RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    158. if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
    159. {
    160. Error_Handler();
    161. }
    162. /** Initializes the CPU, AHB and APB buses clocks
    163. */
    164. RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
    165. |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
    166. RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    167. RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    168. RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    169. RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    170. if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
    171. {
    172. Error_Handler();
    173. }
    174. }
    175. /* USER CODE BEGIN 4 */
    176. /* USER CODE END 4 */
    177. /**
    178. * @brief This function is executed in case of error occurrence.
    179. * @retval None
    180. */
    181. void Error_Handler(void)
    182. {
    183. /* USER CODE BEGIN Error_Handler_Debug */
    184. /* User can add his own implementation to report the HAL error return state */
    185. __disable_irq();
    186. while (1)
    187. {
    188. }
    189. /* USER CODE END Error_Handler_Debug */
    190. }
    191. #ifdef USE_FULL_ASSERT
    192. /**
    193. * @brief Reports the name of the source file and the source line number
    194. * where the assert_param error has occurred.
    195. * @param file: pointer to the source file name
    196. * @param line: assert_param error line source number
    197. * @retval None
    198. */
    199. void assert_failed(uint8_t *file, uint32_t line)
    200. {
    201. /* USER CODE BEGIN 6 */
    202. /* User can add his own implementation to report the file name and line number,
    203. ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    204. /* USER CODE END 6 */
    205. }
    206. #endif /* USE_FULL_ASSERT */

     这里是c8t6的代码,就是用来控制爪子的抓取的,收到8抓取,9松开抓子 

  3.   

     c8t6的cubemx配置很简单,就是打开了串口和一个定时器,其它的引脚暂时没用, 

  4. 最后 就是   

 这是手机蓝牙端,按up发送'1',dowm发送'2'  送开时发送A  当然也可以自己

 最后是视频效果

                   

蓝牙机械臂

总体代码链接:

链接:https://pan.baidu.com/s/124qH9PBN6jMnlYq1KngEoA?pwd=7777 
提取码:7777 
--来自百度网盘超级会员V3的分享

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/405241
推荐阅读
相关标签
  

闽ICP备14008679号