二轮平衡小车1:舵机与电机的基本控制

这篇具有很好参考价值的文章主要介绍了二轮平衡小车1:舵机与电机的基本控制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

今日开始使用STM32F103 C8T6尝试做一个二轮平衡小车,从电机舵机控制开始,小车也是在三个小时的自主设计下框架结构与引脚安排都做好了。

本文主要贴代码,之前的文章都有原理,代码中相应初始化驱动部分也有注释~~

文章提供源码,解释以及工程下载,测试效果视频。

目录

电机与舵机控制基础原理:

初始化TIM1为通用定时器:

初始化定时器TIM2为PWM输出控制电机:

TB6612电机正反转控制引脚的初始化:

编写函数封装电机控制:

初始化定时器TIM4为舵机控制:

如此以后我们将这些动作加入主函数

测试效果:

测试工程下载:


电机与舵机控制基础原理:

原理方面其余文章都有讲到:

使用模块分别为:TB6612带稳压模块、MG996R舵机、JGB-520电机 。

STM32 F103C8T6学习笔记5:定时器输出不同占空比PWM驱动舵机旋转角度_NULL指向我的博客-CSDN博客

【MSP432电机驱动学习—上篇】TB6612带稳压电机驱动模块、MG310电机、霍尔编码器_tb6612fng电机驱动模块_NULL指向我的博客-CSDN博客

初始化TIM1为通用定时器:

这里我选择了TIM1为通用定时器,因为它与定时器TIM2、3、4不同,

1、它是高级定时器,拥有带死区控制,但我们不需要,

2、它的部分初始化内容也与TIM2、3、4不同,因此这里初始化一下TIM1,巩固一下,

3、它占用的引脚有俩个是串口1的PA9\PA10,为了使得串口1能正常使用,因此不使用TIM1的通道,来控制舵机电机了

直接贴代码,这里初始化TIM1为通用定时器,都是周期1ms:

void TIM1_init(void)
{
	  // 定时器初始化结构体定义
	  TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;   
    // 定时器中断向量配置
    NVIC_InitTypeDef NVIC_InitStructure;    
	
    // 使能定时器1时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);    
    // 定时器时钟分频系数设置为72-1
    TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1;    
    // 定时器重载值设置为1000-1,即定时器溢出时间为1ms
    TIM_TimeBaseStructure.TIM_Period = 1000 - 1;    
    // 定时器计数模式设置为向上计数
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;    
    // 定时器时钟分频因子设置为1
    TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1;  
	  //高级计数器需要,不需要用到的直接给0就好
	  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
  
    // 应用定时器初始化配置
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);    
    // 清除定时器中断标志位
    TIM_ClearFlag(TIM1, TIM_FLAG_Update);   
    // 使能定时器中断
    TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);    

    // 中断优先级设置为最低
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;
   
    // 中断子优先级设置为最低
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;    
    // 使能中断
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
    // 应用中断配置
    NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;
    NVIC_Init(&NVIC_InitStructure);
    // 启动定时器1
    TIM_Cmd(TIM1, ENABLE);
}

 中断服务函数:

//通用定时器 定时器1 中断服务函数
void TIM1_UP_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM1, TIM_IT_Update) == SET)
	{	
//		if(++t==1000)		
//		{
//			T++;t=0;
//			printf("%d\r\n",T);
//		}
		TIM_ClearITPendingBit(TIM1, TIM_IT_Update);//清出中断寄存器标志位,用于退出中断
	}
}

初始化定时器TIM2为PWM输出控制电机:

TIM2_init();              //定时器2初始化为电机PWM (频率 18K HZ,重载值 1000)

void TIM2_init(void)
{
  TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义初始化参数结构体
	TIM_OCInitTypeDef TIM_OCInitStructure;//结构体变量需要赋值
	GPIO_InitTypeDef GPIO_Initstructure;  //引脚结构体
	
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//开启TIM2的时钟
	TIM_InternalClockConfig(TIM2);//开启定时器2的时钟源作为内部时钟源
	
	TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim,这里是不分频
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//TIM向上计数模式
	TIM_TimeBaseInitStructure.TIM_Period=1000- 1;       //ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler=4 - 1;      //PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;;//定时器的倍率,如果定时1秒,参数是1,那就是1+1=2倍
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
	
	//	TIM_ClearFlag(TIM2,TIM_FLAG_Update);//中断清除
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开启中断
	
	TIM_OCStructInit(&TIM_OCInitStructure);//结构体赋初始值的函数
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//输出比较模式
 
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;//输出比较的极性
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//输出比较的使能
 
	TIM_OCInitStructure.TIM_Pulse =0;//设置CCR的
 
	TIM_OC1Init(TIM2,&TIM_OCInitStructure);//初始化TIM2_CH1
	TIM_OC1PreloadConfig(TIM2, TIM_OCPreload_Enable);//使能预装载寄存器
	
	TIM_OC2Init(TIM2,&TIM_OCInitStructure);//初始化TIM2_CH2
	TIM_OC2PreloadConfig(TIM2, TIM_OCPreload_Enable);//使能预装载寄存器
	
	//	用结构体初始化输出比较单元,不同函数不同的GPIO(A0)
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	//这里的注释部分是展示开启定时器相应通道管脚的重映射
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启AFIO的时钟
	//GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2,ENABLE);//部分重映射
	//GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//关闭调试端口的复用
	
	
	GPIO_Initstructure.GPIO_Mode= GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_Initstructure.GPIO_Pin= GPIO_Pin_0;
	GPIO_Initstructure.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_Initstructure);
	
	GPIO_Initstructure.GPIO_Mode= GPIO_Mode_AF_PP;//复用推挽输出
	GPIO_Initstructure.GPIO_Pin= GPIO_Pin_1;
	GPIO_Initstructure.GPIO_Speed= GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_Initstructure);
	
	//	GPIO_SetBits(GPIOA,GPIO_Pin_0);
	TIM_Cmd(TIM2,ENABLE);

	
}


//void PWM_SetCompare1(uint16_t Compare1)
//{
//	TIM_SetCompare1(TIM2,Compare1);//TIM2通道1,改变比较值CCRx,达到不同的占空比效果
//}

TB6612电机正反转控制引脚的初始化:

控制速度的PWM在上面已经初始化了,现在还需要初始化启用几个类似于点灯的,可以输出1和0逻辑的几个引脚,用于控制电机正反转:

//电机正反转控制引脚初始化:
void TB6612_init(void)
{
	//初始化BIN2 (PB9) 和 BIN1 (PB10)
	
		/*定义一个GPIO_InitTypeDef类型的结构体*/
		GPIO_InitTypeDef GPIO_InitStructure0;	
		/*开启LED相关的GPIO外设时钟*/
		RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB,ENABLE);
		/*选择要控制的GPIO引脚*/
		GPIO_InitStructure0.GPIO_Pin = GPIO_Pin_9;	
		/*设置引脚模式为通用推挽输出*/
		GPIO_InitStructure0.GPIO_Mode = GPIO_Mode_Out_PP;   
		/*设置引脚速率为50MHz */   
		GPIO_InitStructure0.GPIO_Speed = GPIO_Speed_50MHz; 
		/*调用库函数,初始化GPIO*/
		GPIO_Init(GPIOB, &GPIO_InitStructure0);		
		
		/*开启LED相关的GPIO外设时钟*/
		RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB,ENABLE);
		/*选择要控制的GPIO引脚*/
		GPIO_InitStructure0.GPIO_Pin = GPIO_Pin_10;	
		/*设置引脚模式为通用推挽输出*/
		GPIO_InitStructure0.GPIO_Mode = GPIO_Mode_Out_PP;   
		/*设置引脚速率为50MHz */   
		GPIO_InitStructure0.GPIO_Speed = GPIO_Speed_50MHz; 
		/*调用库函数,初始化GPIO*/
		GPIO_Init(GPIOB, &GPIO_InitStructure0);			
		
		
	//初始化AIN2 (PA8) 和 AIN1 (PA11)		
		/*开启LED相关的GPIO外设时钟*/
		RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA,ENABLE);	
		/*选择要控制的GPIO引脚*/
		GPIO_InitStructure0.GPIO_Pin = GPIO_Pin_8;	
		/*设置引脚模式为通用推挽输出*/
		GPIO_InitStructure0.GPIO_Mode = GPIO_Mode_Out_PP;   
		/*设置引脚速率为50MHz */   
		GPIO_InitStructure0.GPIO_Speed = GPIO_Speed_50MHz; 
		/*调用库函数,初始化GPIO*/
		GPIO_Init(GPIOA, &GPIO_InitStructure0);			
		
		/*开启LED相关的GPIO外设时钟*/
		RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA,ENABLE);	
		/*选择要控制的GPIO引脚*/
		GPIO_InitStructure0.GPIO_Pin = GPIO_Pin_4;	
		/*设置引脚模式为通用推挽输出*/
		GPIO_InitStructure0.GPIO_Mode = GPIO_Mode_Out_PP;   
		/*设置引脚速率为50MHz */   
		GPIO_InitStructure0.GPIO_Speed = GPIO_Speed_50MHz; 
		/*调用库函数,初始化GPIO*/
		GPIO_Init(GPIOA, &GPIO_InitStructure0);			
		
		//初始化完先都置0,不转
		GPIO_ResetBits(GPIOA,GPIO_Pin_8);  //AIN1
		GPIO_ResetBits(GPIOA,GPIO_Pin_4); //AIN2
		GPIO_ResetBits(GPIOB,GPIO_Pin_10); //BIN1 
		GPIO_ResetBits(GPIOB,GPIO_Pin_9);	 //BIN2	 
} 

编写函数封装电机控制:

//设置轮子速度,方向
//PWMA PWMB分别设置 左PWMA 右PWMB 电机 
void set_wheels(uint16_t PWMA,uint16_t PWMB,uint16_t DIRA,uint16_t DIRB)
{
	TIM_SetCompare1(TIM2,PWMB);//TIM2通道1,改变比较值CCRx,达到不同的占空比效果
	TIM_SetCompare2(TIM2,PWMA);//TIM2通道1,改变比较值CCRx,达到不同的占空比效果
	if(DIRA==0)  //反转
	{
		GPIO_SetBits(GPIOA,GPIO_Pin_8);  //AIN1
		GPIO_ResetBits(GPIOA,GPIO_Pin_4);//AIN2
	}
	else if(DIRA==1)  //正转
	{
		GPIO_SetBits(GPIOA,GPIO_Pin_4);  //AIN1
		GPIO_ResetBits(GPIOA,GPIO_Pin_8);//AIN2		
	}
	
	if(DIRB==0)  //反转
	{
	  GPIO_SetBits(GPIOB,GPIO_Pin_10); //BIN1 
		GPIO_ResetBits(GPIOB,GPIO_Pin_9);//BIN2	 
	}
	else if(DIRB==1)  //正转
	{
	  GPIO_SetBits(GPIOB,GPIO_Pin_9);   //BIN1 
		GPIO_ResetBits(GPIOB,GPIO_Pin_10);//BIN2	 		
	}
}

初始化定时器TIM4为舵机控制:

void TIM4_init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;	
	
//   //开时钟	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);	
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   
	
//  //PWM输出管脚配置 
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);	
	
	TIM_TimeBaseStructure.TIM_Period = 3000; 
	TIM_TimeBaseStructure.TIM_Prescaler =71; 
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; 
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); 	
	
//	//PWM模式配置
	TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High;
	TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;
	
	TIM_OC3Init(TIM4,&TIM_OCInitStructure); 
	TIM_OC3PreloadConfig(TIM4,TIM_OCPreload_Enable); 
	
	TIM_Cmd(TIM4,ENABLE); 	
	
//TIM_SetCompare3(TIM4,psc);	   //设置舵机占空比,控制舵机转动	
}
//	TIM_SetCompare3(TIM4,350); // 0度
//	TIM_SetCompare3(TIM4,2600);  //180度
//	TIM_SetCompare3(TIM4,1475);  //90度	

如此以后我们将这些动作加入主函数



uint16_t T,t;

int main(void)
{	
	init_ALL();     //初始化所有函数
	TIM_SetCompare3(TIM4,350); // 0度
	delay_ms(5000);
	set_wheels(555,555,1,1);
	delay_ms(1000);
	set_wheels(0,0,0,0);
	delay_ms(1000);
	set_wheels(555,555,0,0);
	delay_ms(1000);
	set_wheels(0,0,0,0);
	
  while(1)
	{	

	}
}


//初始化所有函数:
void init_ALL(void)
{
	SysTick_Init(72);         //初始化滴答计时器
	Usart1_Init(115200);      //串口1初始化
//	i2c_GPIO_Config();	      //IIC初始化
//	Usart2_Init(115200);      //串口2初始化
//	Usart3_Init(115200);      //串口3初始化
//	OLED_Init();              //初始化OLED屏幕
//	OLED_Clear();             //清空屏幕数据
//	RTC_init();               //初始化RTC实时时钟
	TIM1_init();              //定时器1初始化为通用定时器 (周期1ms)
	TIM2_init();              //定时器2初始化为电机PWM (频率 18K HZ,重载值 1000)
	TIM4_init();              //定时器4初始化为舵机PWM (频率333 hz ,重载值3000)
	TB6612_init();  	        //电机正反转控制引脚初始化:
	
	printf("HELLO");            //开机测试 串口1

//	TIM_SetCompare3(TIM4,350); // 0度
//	TIM_SetCompare3(TIM4,2600);  //180度
//	TIM_SetCompare3(TIM4,1475);  //90度	
}

测试效果:

今日就做到这吧,明日在接着做下面的东西......

二轮平衡小车:舵机与电机的基本控制与编码器信号捕获

测试工程下载:

https://download.csdn.net/download/qq_64257614/88286409?spm=1001.2014.3001.5503文章来源地址https://www.toymoban.com/news/detail-689455.html

到了这里,关于二轮平衡小车1:舵机与电机的基本控制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 舵机控制(STM32F103C8T6)

            本文是以 STM32F103C8T6 作为主控芯片,通过PB6端口输出PWM,实现控制180°舵机。 (一)概述         舵机是一种位置伺服驱动器器,是一种带有输出轴的小装置。当我们向伺服器发送一个控制信号时,输出轴就可以转到特定的位置。只在控制信号持续不变,伺服机构就

    2023年04月09日
    浏览(53)
  • 毕业设计——基于STM32的智能家具系统(语音识别控制、步进电机、舵机)

    智能家具系统分为两个不同版本系列: ①系列一:手机app远程控制、远程检测温湿度显示在app,(云平台)!!!!                   https://blog.csdn.net/m0_59113542/article/details/123737710 ②系列二:语音识别控制-------本文章 硬件采购链接: 步进电机及相关驱动 ULN2003步进电机驱动

    2024年02月05日
    浏览(69)
  • STM32循迹小车系列教程(一)—— 使用PWM控制电机

    本章节主要讲解直流减速电机控制原理,电机驱动电路,以及如何使用PWM控制直流减速电机 1.软件准备:STM32CubeMx、Keil5_ MDK 2.硬件准备:STM32F103C8T6核心板、TB6612电机驱动模块/L298N电机驱动、18650锂电池3节/3S航模电池、杜邦线若干         图2-1为 市场上 常用 的 直流减速 电

    2024年02月05日
    浏览(50)
  • STM32F103RCT6驱动SG90舵机-完成正反转角度控制

    SG90是一种微型舵机,也被称为伺服电机。它是一种小型、低成本的直流电机,通常用于模型和机器人控制等应用中。SG90舵机可以通过电子信号来控制其精确的位置和速度。它具有体积小、重量轻、响应快等特点,因此在各种小型机械设备上得到了广泛应用。 SG90舵机通常用于

    2024年02月03日
    浏览(62)
  • 用正点原子STM32F103ZET6精英板控制舵机转动实验保姆教程

    正点原子精英板一块 Jlink4线SWD下载线一根 精英板usb供电/下载线一根(负责给开发板供电) SG90舵机一个(三线:其中红线接5V电压,棕线接GED,橙黄色为信号线接开发板PB5引脚,舵机所给为3pin杜邦线母头,可用单根杜邦线(一头子一头母)将舵机线飞开接到精英板上)。 以

    2023年04月15日
    浏览(57)
  • STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

    作者:公子易平 时间:2023/6/6 前段时间做一个智能小车的相关项目时,发现很少有人能够将STM32的PWM控制讲清楚,故而书此文,希望对后来的学习者有所帮助。 STM32F103C8T6最小系统板 直流TT电机 电机驱动芯片(TB6612) 杜邦线若干 接线情况: TB6612引脚说明: STM32主控芯片与TB6612接

    2024年02月15日
    浏览(45)
  • stm32F103单片机pwm控制伺服驱动器进而控制步进电机

    1.需要一台步进电机,私服驱动器,stm32单片机;先按照说明文档,连接好硬件相关线路,对应好sign+,sign-,puls+,puls-线路,其中sign只是个io口拉高拉低操作,puls是pwm波形输出口,虽然有两根线,但只是需要控制一个IO口输出波形即可; 采用主从模式,TIM1为主定时器,tim3未从定

    2024年02月04日
    浏览(50)
  • 基于STM32F103控制舵机 仿真 简单二轴机器人逆运动学(20220615完成 正在处理三轴)

    本项目基于 正点原子精英(stm32f103zet6) 控制小舵机 模拟 二轴机器人逆运动学控制。 目录 概述: 1. 我的问题总结 2.stm32控制部分 与机械部分 2.1 对于二轴机器人设计 2.2 stm32 输出 pwm 2.3 舵机控制 3.正运动学 3.1 D-H建模下对姿态的描述 4.逆运动学 4.1 几何解法 4.2 代数解法 4.3 多重

    2023年04月20日
    浏览(61)
  • stm32f103使用DM542控制42相步进电机的原理和可行性分析

    步进电机是一种能够实现准确位置控制的电机,通常应用于需要高精度定位的场合,例如3D打印机、机器人和自动化系统等。而STM32F103是一种高性能、低功耗的微控制器,它拥有广泛的外设,适合用于控制各种电机。本文将介绍使用STM32F103控制DM542驱动器驱动42相步进电机的原

    2024年02月15日
    浏览(41)
  • STM32F103C8T6实现CAN通讯与直流编码电机转速闭环控制

    本次实验目的是通过CAN发送目标转速与转向信息,接收方在接到CAN数据流后开始对直流编码电机进行转速闭环控制。我会尽量说清每个函数,注释每一句代码,希望能对大家有所帮助。 CAN通讯基于STM32自带CAN通讯模块,配合库函数使用十分方便。关于CAN通讯可以参考站内大佬

    2023年04月08日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包