当前位置:   article > 正文

STM32单片机智能小车一PWM方式实现小车调速和转向_stm32小车遥控调速

stm32小车遥控调速

目录

1. 电机模块开发

2. 让小车动起来

3. 串口控制小车方向

4. 如何进行小车PWM调速

5. PWM方式实现小车转向


1. 电机模块开发

L9110s概述

接通VCC,GND 模块电源指示灯亮, 以下资料来源官方,具体根据实际调试

IA1输入高电平,IA1输入低电平,【OA1 OB1】电机正转;

IA1输入低电平,IA1输入高电平,【OA1 OB1】电机反转;

IA2输入高电平,IA2输入低电平,【OA2 OB2】电机正转;

IA2输入低电平,IA2输入高电平,【OA2 OB2】电机反转;

接线参考:

B-1A -- PA0

B-1B -- PB1

A-1A -- PA1

A-1B -- PB10 

2. 让小车动起来

代码实现:

motor.c

  1. #include "motor.h"
  2. void goForward(void)
  3. {
  4. // 左轮
  5. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
  6. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
  7. // 右轮
  8. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
  9. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
  10. }
  11. void goBack(void)
  12. {
  13. // 左轮
  14. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
  15. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
  16. // 右轮
  17. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
  18. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_SET);
  19. }
  20. void goLeft(void)
  21. {
  22. // 左轮
  23. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_RESET);
  24. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
  25. // 右轮
  26. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_SET);
  27. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
  28. }
  29. void goRight(void)
  30. {
  31. // 左轮
  32. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
  33. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
  34. // 右轮
  35. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
  36. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
  37. }
  38. void stop(void)
  39. {
  40. // 左轮
  41. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);
  42. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
  43. // 右轮
  44. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_0, GPIO_PIN_RESET);
  45. HAL_GPIO_WritePin(GPIOB, GPIO_PIN_1, GPIO_PIN_RESET);
  46. }

motor.h

  1. #ifndef __MOTOR_H__
  2. #define __MOTOR_H__
  3. #include "main.h"
  4. void goForward(void);
  5. void goBack(void);
  6. void goLeft(void);
  7. void goRight(void);
  8. void stop(void);
  9. #endif

main.c

  1. #include "motor.h"
  2. //main函数的while循环部分:
  3. while (1)
  4. {
  5. goForward();
  6. HAL_Delay(1000);
  7. goBack();
  8. HAL_Delay(1000);
  9. goLeft();
  10. HAL_Delay(1000);
  11. goRight();
  12. HAL_Delay(1000);
  13. stop();
  14. HAL_Delay(1000);
  15. }

3. 串口控制小车方向

  • 串口分文件编程进行代码整合——通过现象来改代码
  • 接入蓝牙模块,通过蓝牙控制小车
  • 添加点动控制,如果APP支持按下一直发数据,松开就停止发数据(蓝牙调试助手的自定义按键不 能实现),就能实现前进按键按下后小车一直往前走的功能

代码实现:

usart.c

  1. #include "usart.h"
  2. #include "string.h"
  3. #include "stdio.h"
  4. #include "motor.h"
  5. //串口接收缓存(1字节)
  6. uint8_t buf=0;
  7. //定义最大接收字节数 200,可根据需求调整
  8. #define UART1_REC_LEN 200
  9. // 接收缓冲, 串口接收到的数据放在这个数组里,最大UART1_REC_LEN个字节
  10. uint8_t UART1_RX_Buffer[UART1_REC_LEN];
  11. // 接收状态
  12. // bit15, 接收完成标志
  13. // bit14, 接收到0x0d
  14. // bit13~0, 接收到的有效字节数目
  15. uint16_t UART1_RX_STA=0;
  16. #define SIZE 12
  17. char buffer[SIZE];
  18. // 接收完成回调函数,收到一个数据后,在这里处理
  19. void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
  20. {
  21. // 判断中断是由哪个串口触发的
  22. if(huart->Instance == USART1)
  23. {
  24. // 判断接收是否完成(UART1_RX_STA bit15 位是否为1)
  25. if((UART1_RX_STA & 0x8000) == 0)
  26. {
  27. // 如果已经收到了 0x0d (回车),
  28. if(UART1_RX_STA & 0x4000)
  29. {
  30. // 则接着判断是否收到 0x0a (换行)
  31. if(buf == 0x0a)
  32. {
  33. // 如果 0x0a 和 0x0d 都收到,则将 bit15 位置为1
  34. UART1_RX_STA |= 0x8000;
  35. // 灯控指令
  36. if(!strcmp(UART1_RX_Buffer, "M1"))
  37. goForward();
  38. else if(!strcmp(UART1_RX_Buffer, "M2"))
  39. goBack();
  40. else if(!strcmp(UART1_RX_Buffer, "M3"))
  41. goLeft();
  42. else if(!strcmp(UART1_RX_Buffer, "M4"))
  43. goRight();
  44. else
  45. stop();
  46. memset(UART1_RX_Buffer, 0, UART1_REC_LEN);
  47. UART1_RX_STA = 0;
  48. }
  49. else
  50. // 否则认为接收错误,重新开始
  51. UART1_RX_STA = 0;
  52. }
  53. else // 如果没有收到了 0x0d (回车)
  54. {
  55. //则先判断收到的这个字符是否是 0x0d (回车)
  56. if(buf == 0x0d)
  57. {
  58. // 是的话则将 bit14 位置为1
  59. UART1_RX_STA |= 0x4000;
  60. }
  61. else
  62. {
  63. // 否则将接收到的数据保存在缓存数组里
  64. UART1_RX_Buffer[UART1_RX_STA & 0X3FFF] = buf;
  65. UART1_RX_STA++;
  66. // 如果接收数据大于UART1_REC_LEN(200字节),则重新开始接收
  67. if(UART1_RX_STA > UART1_REC_LEN - 1)
  68. UART1_RX_STA = 0;
  69. }
  70. }
  71. }
  72. // 重新开启中断
  73. HAL_UART_Receive_IT(&huart1, &buf, 1);
  74. }
  75. }
  76. int fputc(int ch, FILE *f)
  77. {
  78. unsigned char temp[1]={ch};
  79. HAL_UART_Transmit(&huart1,temp,1,0xffff);
  80. return ch;
  81. }

4. 如何进行小车PWM调速

原理

全速前进是LeftCon1A = 0; LeftCon1B = 1;

完全停止是LeftCon1A = 0;LeftCon1B = 0;

那么单位时间内,比如20ms, 有15ms是全速前进,5ms是完全停止, 速度就会比5ms全速前进,15ms完全停止获得的功率多,相应的速度更快!

开发:借用PWM的舵机控制代码

将控制车轮的4个 GPIO 口配置修改如下,否则小车动不起来。

原因:L9110每个控制口需要一高一低才可以动起来,如果PWM有效电平为高电平,则另一个 GPIO口则需要输出低电平才可以驱动轮子。

代码实现:

main.c

  1. // main函数里
  2. HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_1);
  3. HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);
  4. while (1)
  5. {
  6. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 8);
  7. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 8);
  8. HAL_Delay(1000);
  9. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 10);
  10. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 10);
  11. HAL_Delay(1000);
  12. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1, 15);
  13. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2, 15);
  14. HAL_Delay(1000);
  15. }

5. PWM方式实现小车转向

右转原理:

左轮速度大于右轮

左转原理:

右轮速度大于左轮

左右轮各自调速代码实现:

  1. // main函数里
  2. while (1)
  3. {
  4. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,8);
  5. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,15);
  6. HAL_Delay(1000);
  7. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_1,15);
  8. __HAL_TIM_SetCompare(&htim2, TIM_CHANNEL_2,8);
  9. HAL_Delay(1000);
  10. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/470744
推荐阅读
相关标签
  

闽ICP备14008679号