视觉巡线小车——STM32+OpenMV(一)

目录

前言

一、CubeMX配置

1、系统及时钟配置

2、配置GPIO

3、定时器配置

4、生成MDK工程

二、Keil编辑代码

1.初始化代码

2.电机控制代码

3、电机测速代码

4、控制示例

总结



前言

利用STM32CubeMX新建减速电机驱动工程,并且通过减速电机自带的霍尔编码器采集速度。

重点:

1、配置定时器生成PWM------控制TB6612输出;

2、配置定时器产生10ms中断------电机控制周期;

3、配置定时器为正交编码模式------采集电机转速;

4、配置GPIO------控制电机方向


一、CubeMX配置

1、系统及时钟配置

2、配置GPIO

3、定时器配置

配置定时器TIM1生成PWM:

PSC = 0;

ARR = 7199;

由于系统时钟为72M,所以PWM频率为:10kHz。

占空比为:D=Pulse/ARR * 100%。

配置定时器TIM2产生10ms中断:

PSC = 72-1;

ARR = 10000-1;

同时 需要开启定时器中断,中断优先级自己设置。

配置定时器TIM3、TIM4为正交编码模式:

定时器TIM3和TIM4操作一样,如果有需要可以自行开启定时器更新中断。

4、生成MDK工程

其中工程名字和路径都不能有中文,必须用标准C的标识符命名。

二、Keil编辑代码

1.初始化代码

通过CubeMX配置生成的工程还需要加入一些初始化代码:

cpp 复制代码
HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL);
     
 HAL_TIM_Base_Start_IT(&htim2); 
 
 HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
 HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4);
 __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,0);
 __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_4,0);

2.电机控制代码

这里主要采用TB6612来驱动减速电机:

motor.h文件代码如下

cpp 复制代码
#ifndef  _MOTOR_H_
#define  _MOTOR_H_	 

#include "stm32f1xx_hal.h"
#include "tim.h"


/*******直流减速电机机械参数*********/
#define ENCODE_X 500 //编码器线数
#define JIANSUBI 30		//减速比
#define BEIPIN 4			//倍频
#define SAMPLE_TIME 0.01  //采样时间10ms
#define C (ENCODE_X*JIANSUBI*BEIPIN*SAMPLE_TIME)

#define PI 3.1415
#define R  6.5   //车轮直径cm 

#define BIN2(n)  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_13 , (GPIO_PinState)n)
#define BIN1(n)  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_12 , (GPIO_PinState)n)
#define AIN2(n)  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_15 , (GPIO_PinState)n)
#define AIN1(n)  HAL_GPIO_WritePin(GPIOB,GPIO_PIN_14 , (GPIO_PinState)n)

typedef struct
{
    float speed;
    int S;
    int Target_Speed;
    int out;
}MOTOR_t;    
extern MOTOR_t motorA,motorB;

#define LIMIT(x,min,max) (x)=(((x)<=(min))?(min):(((x)>=(max))?(max):(x)))  //限幅定义
int abs(int p);
void Load(int motorA,int motorB);


#endif

其中电机以及轮子的参数自己修改。

motor.c文件代码如下

cpp 复制代码
#include "motor.h"

MOTOR_t motorA = {0},motorB = {0};

int abs(int p)
{
	int q;
	q=p>0?p:(-p);
	return q;
}

void Load(int motorA,int motorB)
{
    LIMIT(motorA,-7199,7199);
    LIMIT(motorB,-7199,7199);  
	if(motorA>0)	
		AIN1(1),AIN2(0);//正转
	else 				
		AIN1(0),AIN2(1);//正转

	__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_1, abs(motorA)); 
	
	if(motorB>0)	
		BIN1(1),BIN2(0);
	else 		
		BIN1(0),BIN2(1);
	__HAL_TIM_SetCompare(&htim1, TIM_CHANNEL_4,  abs(motorB)); 

}

3、电机测速代码

cpp 复制代码
float get_speed_motorA()
{

    short Encoder_TIM = 0;
    float Speed = 0.0;
    Encoder_TIM = (short)__HAL_TIM_GetCounter(&htim3);       //获取编码器定时器中的计数值
    __HAL_TIM_SetCounter(&htim3, 0);

    if(htim3.Instance->CR1 & 0X10) //判断计数器的计数方向,逻辑1则是减计数
    {
        Encoder_TIM = -65536 + Encoder_TIM;
    }
//    Encoder_TIM = Encoder_TIM+Encoder3_Overflow_Count*65536;
    Speed = (float)Encoder_TIM / (C) * PI * R;
    return Speed;
}

float get_speed_motorB()
{
    short Encoder_TIM = 0;
    float Speed = 0.0;
    Encoder_TIM = (short)__HAL_TIM_GetCounter(&htim4);       //获取编码器定时器中的计数值
    __HAL_TIM_SetCounter(&htim4, 0);

    if(htim4.Instance->CR1 & 0X10) //判断计数器的计数方向,逻辑1则是减计数
    {
        Encoder_TIM = -65536 + Encoder_TIM;
    }
//    Encoder_TIM = Encoder_TIM+Encoder3_Overflow_Count*65536;
    Speed = -(float)Encoder_TIM / (C) * PI * R;
    return Speed;
}

在定时器中断里, 每10毫秒对定时器TIM3和TIM4的计数值进行处理,得到电机速度,方便后续进行速度闭环控制。

4、控制示例

cpp 复制代码
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM1_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  MX_TIM4_Init();
  /* USER CODE BEGIN 2 */
    HAL_TIM_Encoder_Start(&htim3, TIM_CHANNEL_ALL);
    HAL_TIM_Encoder_Start(&htim4, TIM_CHANNEL_ALL);
  
    HAL_TIM_Base_Start_IT(&htim2);
    
    HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
    HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_4);
    __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_1,0);
    __HAL_TIM_SetCompare(&htim1,TIM_CHANNEL_4,0);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
            motorA.out = 20;
            motorB.out = -20;
  }
  /* USER CODE END 3 */
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{   
/*******电机控制周期,每十秒对电机控制一次*********/
    if(htim->Instance == TIM2 )
    {
            motorA.speed = get_speed_motorA();
            motorB.speed = get_speed_motorB(); 
            motorA.S += motorA.speed;
            motorB.S += motorB.speed;

        Load(motorA.out, motorB.out);
    }

}

总结

通过本文,就可以对减速电机进行简单的控制,以及速度的采集了。

同时可以自行加入OLED等显示屏,显示所采集的速度,也可以通过配置串口进行打印观察。

相关推荐
国科安芯3 小时前
航天器多路并联大功率电源系统设计与ASP4644均流特性分析
单片机·嵌入式硬件·fpga开发·安全性测试
茯苓gao5 小时前
嵌入式开发笔记:CANopen相关移位运算与通信协议术语详解
网络·嵌入式硬件·学习·信息与通信
梁朝辉7 小时前
STM32H750VBT6中ADCINP与INN什么区别
stm32·单片机·嵌入式硬件
省四收割者8 小时前
一文详解信号完整性(1)
python·嵌入式硬件·数学建模·信息与通信·信号处理·智能硬件
崇山峻岭之间9 小时前
单片机无感FOC驱动之ADC
单片机·嵌入式硬件
Ligocious10 小时前
1.点亮一颗小小的LED
单片机·嵌入式硬件
KaifuZeng13 小时前
通信与接口协议面试八、CAN通信
单片机·嵌入式硬件·面试·通信与接口协议
智源单片机设计15 小时前
基于单片机的直流电机双闭环调速系统设计
单片机·嵌入式硬件
kebidaixu15 小时前
两轮车换电 BMS 的模拟前端中颖 SH367306 AFE 芯片详解
stm32
kebidaixu16 小时前
两轮车换电 BMS 的模拟前端中颖 SH367306 AFE 芯片调试实录:四个关键问题与解决方案
stm32