草庐IT

基于STM32F1的舵机控制

搞机佬 2024-06-17 原文

一、SG90舵机介绍

SG90是有三个版本的,90度版、180度版和360度版,前两个只是舵机旋转角度的范围不一样,可以在这个范围内任意的控制舵机所转的角度,而360版本的是一直旋转的,我们不能控制它旋转的角度,只能控制它旋转的速度,这里我们在买的时候就要注意一点,根据自己的需求选取不同的版本,以免买错。这里我们介绍180度版本的。三个控制原理基本相同。

单片机系统实现对舵机输出转角的控制,必须首先完成两个任务:首先是产生基本的PWM周期信号,本设计是产生20ms的周期信号;其次是脉宽的调整,即单片机模拟PWM信号的输出,并且调整占空比。

脉冲的高电平部分一般为0.5ms~2.5ms范围内的角度控制脉冲部分,所以是利用一个占空比来控制舵机转动的角度。PWM占空比是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比。占空比 = t / T 相关参数如下:

t = 0.5ms——————-舵机会转动 0 °

t = 1.0ms——————-舵机会转动 45°

t = 1.5ms——————-舵机会转动 90°

t = 2.0ms——————-舵机会转动 135°

t = 2.5ms——————-舵机会转动180°

当你需要转动135°时,他的占空比就是2.0ms/20ms=10%,所以 TIMx 捕获比较寄存器值就为200-200*10% = 180。

二、与单片机的连接:

SG90分别有三根线。棕色,红色,橙色

棕色接地(GND)

红色接电源(+5V)

橙色接输出PWM信号的引脚

三、PWM

因为舵机的控制主要用到的就是定时器的pwm功能,所以我们先聊一聊pwm

PWM的输出其实就是对外输出脉宽可调(即占空比调节)的方波信号,信号频率是由自动重装寄存器 ARR 的值决定,占空比由比较寄存器CCR的值决定。

  当TIMx_CR1寄存器中的 DIR 位为低时执行递增计数,计数器CNT从0计数到自动重载值(TIMx_ARR 寄存器的内容),然后重新从 0 开始数并生成计数器上溢事件。

 以PWM 模式 1 为例。只要TIMx_CNT < TIMx_CCRx, PWM 参考信号OCxREF 便为有高电平,否则为无效的低电平。如果 TIMx_CCRx 中的比较值大于自动重载值(TIMx_ARR 中),则 OCxREF 保持为“ 1”。果比较值为 0, 则 OCxREF 保持为“ 0”。

  我们控制舵机主要是产生一个以20ms为周期的pwm信号,然后通过改变pwm的占空比就可以控制舵机的转角。

四、程序设计

主函数如下:

int main() 

{

u8 i;

SysTick_Init(72);

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);  //中断优先级分组 分2组

LED_Init();

Sg90_Init();

USART1_Init();

while(1)

   {

   i++;

// TIM_SetCompare2(TIM3, 195);  // 0度    t = 0.5ms           修改TIMx_CCRx的值控制占空比

// delay_ms(1000);

// TIM_SetCompare2(TIM3, 190);  //45度   t = 1.0ms——————-舵机会转动 45°  占空比就应该为1ms/20ms = 5%,所以TIM_SetCompare1的 TIMx 捕获比较 1 寄存器值就为200-200*5% = 190

// delay_ms(1000);

// TIM_SetCompare2(TIM3, 185);  //90度      t = 1.5ms

// delay_ms(1000);

// TIM_SetCompare2(TIM3, 180);  //135度        t = 2.0ms

// delay_ms(1000);

// TIM_SetCompare2(TIM3, 175);  //180度         t = 2.5ms

// delay_ms(1000);

// Sg90_Return(0);

// delay_ms(1000);

//    Sg90_Return(45);

// delay_ms(1000);

//    Sg90_Return(90);

// delay_ms(1000);

//    Sg90_Return(135);

// delay_ms(1000);

//    Sg90_Return(180);

// delay_ms(1000);

   

   if(i%20==0)

   {

   led1=!led1;

   }

   delay_ms(10);

   

   }

}

在主函数中我们控制舵机以此转过45、90、135、180度,这里之所以会注销掉这些,是因为我在工程文件中增添了通过串口控制舵机的功能,我们可以直接在串口中向单片机发送控制数据,舵机就会转过相应的角度。

  先看看sg90.c文件:

void Sg90_Init()

{

TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;

TIM_OCInitTypeDef TIM_OCInitStructure;     //输出比较结构体

GPIO_InitTypeDef GPIO_InitStructure; 

/* 开启时钟 */

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//初始化GPIOB端口使能

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//开启定时器3的时钟

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

/*  配置GPIO的模式和IO口 */

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7;                   // 选择你要设置的IO口

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;          //选择输出模式(复用推挽输出)

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_Init(GPIOC,&GPIO_InitStructure);

GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);  //设置管脚复用映射(部分重映射)

TIM_TimeBaseInitStructure.TIM_Period=199;    //自动装载值      定时器定时时间计算公式

TIM_TimeBaseInitStructure.TIM_Prescaler=7199; //分频系数      ((per)*(psc+1))/Tclk

TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//时钟分频

TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //计数模式(向上计数模式)

TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);

TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;

TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low; //设置输出极性(底)

TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; // 比较输出使能

TIM_OC2Init(TIM3,&TIM_OCInitStructure);   //输出比较通道2初始化

TIM_Cmd(TIM3,ENABLE); //开启定时器

TIM_OC2PreloadConfig(TIM3,TIM_OCPreload_Enable); //使能TIM3在CCR2上的预装载寄存器

TIM_ARRPreloadConfig(TIM3,ENABLE); //使能TIM3在ARR上的预装载寄存器允许位

}

void Sg90_Return(u8 angle)

{

u8 per;

if(angle==45)

{

per=190;

TIM_SetCompare2(TIM3, per);

}

else if(angle==90)

{

per=185;

TIM_SetCompare2(TIM3, per);

}

else if(angle==135)

{

per=180;

TIM_SetCompare2(TIM3, per);

}

else if(angle==180)

{

per=175;

TIM_SetCompare2(TIM3, per);

}

else

{

per=195;

TIM_SetCompare2(TIM3, per);

}

}

程序比较简单,就一个定时器初始化和直接输入角度的控制函数,(第二个是函数是我自己写的,比较烂,有能力的可以完善完善一起学习)主要思想还是通过TIM_SetCompare2()设置CCR的数值。

在看看如何通过串口控制:

void USART1_IRQHandler(void)     //中断服务函数

      { 

  

  u8 r;

u16 num;

static char pwm[4];

    static int i=0;

if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)  //检查串口1的接收中断是否发生

{

r=USART_ReceiveData(USART1);      //返回 USART1 最近接收到的数据

if(r!='g'&&r!='m')

{

pwm[i]=r;

i++;

}

else

{

i=0;

num=(atoi(pwm));

TIM_SetCompare2(TIM3, num);

}

USART_SendData(USART1,r);         //通过外设 USART1 发送单个数据

while (USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);   //检查 USART1的 发送完成标志位 设置与否

}

USART_ClearFlag(USART1,USART_FLAG_TC);

       }

这里主要就是数据转化的问题,通过atoi()函数将字符串转化为整数然后再用于控制舵机。串口传输数据的时候要特别注意不同数据格式之间的转化。

 

有关基于STM32F1的舵机控制的更多相关文章

  1. Ruby Readline 在向上箭头上使控制台崩溃 - 2

    当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby​​安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少

  2. ruby-on-rails - 带 Spring 锁的 Rails 4 控制台 - 2

    我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.

  3. ruby-on-rails - openshift 上的 rails 控制台 - 2

    我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

  4. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  5. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  6. STM32读取串口传感器数据(颗粒物传感器,主动上传) - 2

    文章目录1.开发板选择*用到的资源2.串口通信(个人理解)3.代码分析(注释比较详细)1.主函数2.串口1配置3.串口2配置以及中断函数4.注意问题5.源码链接1.开发板选择我用的是STM32F103RCT6的板子,不过代码大概在F103系列的板子上都可以运行,我试过在野火103的霸道板上也可以,主要看一下串口对应的引脚一不一样就行了,不一样的就更改一下。*用到的资源keil5软件这里用到了两个串口资源,采集数据一个,串口通信一个,板子对应引脚如下:串口1,TX:PA9,RX:PA10串口2,TX:PA2,RX:PA32.串口通信(个人理解)我就从串口采集传感器数据这个过程说一下我自己的理解,

  7. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  8. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  9. ruby-on-rails - 在 Rails 控制台中使用 asset_path - 2

    在我的Character模型中,我添加了:字符.rbbefore_savedoself.profile_picture_url=asset_path('icon.png')end但是,对于数据库中已存在的所有角色,它们的profile_picture_url为nil。因此,我想进入控制台并遍历所有这些并进行设置。在我试过的控制台中:Character.find_eachdo|c|c.profile_picture_url=asset_path('icon.png')end但这给出了错误:NoMethodError:undefinedmethod`asset_path'formain:O

  10. ruby-on-rails - 带有 Pry 的 Rails 控制台 - 2

    当我进入Rails控制台时,我已将pry设置为加载代替irb。我找不到该页面或不记得如何将其恢复为默认行为,因为它似乎干扰了我的Rubymine调试器。有什么建议吗? 最佳答案 我刚发现问题,pry-railsgem。忘记了它的目的是让“railsconsole”打开pry。 关于ruby-on-rails-带有Pry的Rails控制台,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/question

随机推荐