打印
[应用相关]

分享一个关于SG90舵机的实验(+串口控制)

[复制链接]
1684|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
新手第一次做实验,如果有写的不对的地方,还希望各位大佬多多指导。
--------第一次做实验,也发现了自己学习过的东西掌握的不是很好,大佬们有啥入门级别的模块也可以推荐一下,分享当然更好了。
-------算是对自己学习的一种记录吧,嘿嘿!

SG90舵机的参数:

使用特权

评论回复
沙发
根特皇宫w|  楼主 | 2022-2-24 17:20 | 只看该作者
对于舵机的控制当然就是利用pwm来控制

1——pwm:高电平时间/总的周期
2——SG90舵机的要求50H的脉冲

使用特权

评论回复
板凳
根特皇宫w|  楼主 | 2022-2-24 17:21 | 只看该作者
对于的占空比就是2.5%--12.5%
3——舵机接线

舵机接线:  
pwm:橙色-PA7
VCC:红色
GND:棕色

使用特权

评论回复
地板
根特皇宫w|  楼主 | 2022-2-24 17:22 | 只看该作者
4——我使用的是stmf103精英版
pwm——定时器3产生pwm,至于pwm的初始化没啥可说的,就是直接套用原子的pwm初始化;
TIM3_PWM_Init(199,7199);  //频率是50Hz  1/50=0.02  周期计算公式为:周期=(arr+1)*(psc+1)/CLK

需求1:利用定时器控制舵机从0--180(尽可能的到达舵机的极限),刚开始想利让一度一度的转,舵机没啥反应;
解决:利用定时器4定时,至于为什么定时4(后面说);
TIM4_Int_Init(79,71); ////80*72/72=80us=0.08ms  //定时时间计算  time=clk/((arr+1)(psc+1))
定时器的初始化也是改了原子定时器3的实验
#include "time.h"
#include "stdio.h"
int i=0,flag=0;
double  maikuan ,date;


void TIM4_Int_Init(u16 arr,u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        NVIC_InitTypeDef NVIC_InitStructure;

        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); //时钟使能
      
        //定时器TIM3初始化
        TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值      
        TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
        TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); //根据指定的参数初始化TIMx的时间基数单位

        TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); //使能指定的TIM3中断,允许更新中断

        //中断优先级NVIC设置
        NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  //TIM3中断
        NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3;  //先占优先级0级
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
        NVIC_Init(&NVIC_InitStructure);  //初始化NVIC寄存器


        TIM_Cmd(TIM4, ENABLE);  //使能TIMx                                         
}


void TIM4_IRQHandler(void)   //TIM4中断
{
      
                if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)  //检查TIM4更新中断发生与否
                {
                        i++;               
                        if(flag==0)
                        {
                                maikuan=i*1.85/9.0;         //  (1.85*i*0.1/180)*200      
                                date=195.0-maikuan;      
                                TIM_SetCompare2(TIM3, date);
                                //printf("%lf\n\n",date);
                        }
                        if(flag==1)
                        {
                                maikuan=i*1.85/9.0;                        
                                date=175.0+maikuan;
                                TIM_SetCompare2(TIM3, date);
                                //printf("%lf\n\n",date);
                              
                        }
                       
                        if(i>250)//理论值计算完的结果是100  但是无法到达最值点
                        //150
                        //175
                        //200
                        //205
                        {
                                i=0;
                                flag=1;
                        }      
                        TIM_ClearITPendingBit(TIM4, TIM_IT_Update  );  //清除TIMx更新中断标志        
               
                }
}

使用特权

评论回复
5
根特皇宫w|  楼主 | 2022-2-24 17:24 | 只看该作者
对于i的确定,我现在也是不太清楚,基本是自己一个一个试出来的。如果有大佬明白了,可以在这里说一下,大家互相学习一下。
对于为什么定时0.08us——定时0.02us效果不好,自己改了一下(还是瞎改的)
目前——这样就可以做到舵机来回转动了;

使用特权

评论回复
6
根特皇宫w|  楼主 | 2022-2-24 17:26 | 只看该作者
需求2:利用串口控制正在转动的舵机;
方案——利用设置优先级
串口1 0  3
定时器4   3  3
但是看不到现象,并不是设置错误,是因为操作定时器4太频繁了,看不出是定时器的效果还是串口指令的作用。

解决:此法我觉得还是有点不太靠谱
在串口发送指令后,关闭定时器4+延时一定的时间+(串口指令执行完)+打开定时器,就可以看到明显的现象。

使用特权

评论回复
7
根特皇宫w|  楼主 | 2022-2-24 17:27 | 只看该作者
最大的难点:

串口——对于串口数据的接受和发送,在论坛也提问了几次,没有找到合适的的办法,很奔溃,新手,太菜。
#include "renji.h"
#include "usart.h"
#include "stdio.h"
#include "led.h"
#include "delay.h"
#include "time.h"

void angle_ctrl(void)
{
      
        u16 t;  
        u16 len;
        int delay_time;
        double angle,num0,num1,num2;
        double  data,gao,pwm;
        delay_time=500;
        if(USART_RX_STA&0x8000)
                {                                          
                        len=USART_RX_STA&0x3fff;//得到此次接收到的数据长度    0011  1111 1111 1111
                        printf("\r\n您发送的消息为:\r\n\r\n");
                        for(t=0;t<len;t++)
                        {
                                USART_SendData(USART1, USART_RX_BUF[t]);//向串口1发送数据
                                while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);//等待发送结束
                        }//USART_FLAG_TC是发送完成的表示符
                        //TIM_Cmd(TIM4, DISABLE);
                        //delay_ms(delay_time);
                        printf("\n\n\r\r\n\n");
                        num0=USART_RX_BUF[0]-48;
                        num1=USART_RX_BUF[1]-48;
                        num2=USART_RX_BUF[2]-48;
                        printf("\n\n\r\r\n\n");
                        if(num2 <0  &&  num1 <0)
                                angle=num0;
                        else if(num2<0)
                                angle=num0*10+num1;
                        else
                                angle=num0*100+num1*10+num2*1;
                       
                        gao=angle*20.0/180.0;
                        data=195.0-gao;
                        pwm=(200-data)/200.0*100;
                        TIM_SetCompare2(TIM3, data);
                        delay_ms(delay_time);
                        printf("角度值angle=%lf\r\n",angle);      
                        printf("pwm=%.2lf%%\r\n",pwm);      
                        USART_RX_BUF[0]=0;
                        USART_RX_BUF[1]=0;
                        USART_RX_BUF[2]=0;
                        USART_RX_STA=0;//串口的标志位
                        //TIM_Cmd(TIM4, ENABLE);
               
                        }
               
}

使用特权

评论回复
8
根特皇宫w|  楼主 | 2022-2-24 17:28 | 只看该作者
这个串口可以直接发送0--999的数据,至于更多位,类比一下,就可以。



主函数如下:
#include "stm32f10x.h"
#include "time.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "stdio.h"
#include "renji.h"


int main(void)
{
      
      
        int delay_time;
        delay_time = 500;
      
        delay_init();                     //延时函数初始化         
        LED_Init();
        NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
        TIM3_PWM_Init(199,7199);  //频率是50Hz  1/50=0.02  周期计算公式为:周期=(arr+1)*(psc+1)/CLK
        TIM_SetCompare2(TIM3, 195);//200-25    //void TIM3_PWM_Init(u16 period,u16 prescaler)
        delay_ms(delay_time);
        delay_ms(delay_time);
        //TIM4_Int_Init(79,71); ////80*72/72=80us=0.08ms  //定时时间计算  time=clk/((arr+1)(psc+1))
        uart_init(115200);         //串口初始化为115200
      
      
        while(1)     
        {
                angle_ctrl();
        }
}



注:其中的led只是最开始为了检验测试串口指令是否发送成功写的。

使用特权

评论回复
9
根特皇宫w|  楼主 | 2022-2-24 17:29 | 只看该作者

使用特权

评论回复
10
童雨竹| | 2023-9-29 07:09 | 只看该作者

根据这些指标,测试员可以评估电源的性能和可靠性。

使用特权

评论回复
11
万图| | 2023-9-29 08:12 | 只看该作者

设备中的ESD静电阻抗器一般都不易老化损坏

使用特权

评论回复
12
Clyde011| | 2023-9-29 09:15 | 只看该作者

通过将各类分立元器件进行整合和封装,模块电源能够实现以最小的体积来实现功率密度更高的效果。

使用特权

评论回复
13
万图| | 2023-9-29 11:11 | 只看该作者

可对电路进行一个防护效果

使用特权

评论回复
14
Uriah| | 2023-9-29 12:14 | 只看该作者

以保护器件免受ESD的损坏

使用特权

评论回复
15
帛灿灿| | 2023-9-29 14:10 | 只看该作者

不会达到该电压

使用特权

评论回复
16
Bblythe| | 2023-9-29 15:13 | 只看该作者

一端接地,滤去高频

使用特权

评论回复
17
周半梅| | 2023-9-29 17:09 | 只看该作者

但是,由于变压器存在漏感,

使用特权

评论回复
18
万图| | 2023-9-29 18:12 | 只看该作者

在此情况下我们通常会用电阻串联在电路中

使用特权

评论回复
19
周半梅| | 2023-9-29 19:15 | 只看该作者

缩合型灌封硅胶由于固化过程有体积收缩一般不使用在模块电源的灌封中

使用特权

评论回复
20
MessageRing| | 2023-9-30 18:32 | 只看该作者
他们的板子不是有教程吗

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

26

主题

115

帖子

0

粉丝