专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
STM32
在网上买的小车的舵机单位转角只有9度,请问怎样提高精度。
2019-10-16 01:51
发布
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮
站内问答
/
STM32/STM8
16368
2
995
这个代码对应的是zhuanjiao=5~25对应转角0~180度,所以单位转角只有9度,我想知道怎么才能提高精度,可以通过减小定时器周期,比如让定时器周期等于0.01ms,然后zhuanjiao=50~250控制转角吗?这样从原理上是否可行?我自己试验的时候发现舵机瞎转。。。
友情提示:
此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
2条回答
summer_fly
1楼-- · 2019-10-16 03:46
这个程序我记得好像是按一下按键就转一下,然后摆回来。有两个滑动变阻器,一个调速度,一个调角度。
加载中...
summer_fly
2楼-- · 2019-10-16 05:35
我正好手上有写个舵机的程序,贴出来给你参考一下。
我看了一下,你这个程序主要只分了20个档,要增加档位就要把定时器中断时间给减小,但是51单片机定时器中断时间越短就越不准,我建议用delay来写,我就是用的delay的方法。
#include "include.h"
//declare SFR associated with the ADC
sfr ADC_CONTR = 0xC5; //ADC control register
sfr ADC_RES = 0xC6; //ADC high 8-bit result register
sfr ADC_LOW2 = 0xC7; //ADC low 2-bit result register
sfr P1ASF = 0X97; //P1 secondary function control register
//Define ADC operation const for ADC_CONTR
#define ADC_FLAG 0x10 //ADC complete
#define ADC_START 0x08 //ADC start control bit
#define ADC_SPEEDHH 0x00 //89 clocks
#define ADC_SPEEDH 0x20 //179 clocks
#define ADC_SPEEDL 0x40 //356 clocks
#define ADC_SPEEDLL 0x60 //534 clocks
void InitADC(void);
u16 GetADCResult(u8 ch);
sbit PWM0 = P2^0;
bit p_flag = 1;
u8 Speed_Level=1;
u8 wait_count = 0;
u8 ADC_AngleValue = 0;
u8 ADC_PreAngleValue = 0;
u8 ADC_SpeedValue = 0;
u8 ADC_PreSpeedValue = 0;
u8 PWM_Flag = 0;
s16 PWM_PreValue = 0;
u16 PWM_TrueValue = 0;
s16 PWM_Value = 0;
u8 Median_data0[10] = {0};
u8 Median_num0 = 0;
u8 Average0[2] = {0};
u8 Average0_num = 0;
u8 Median_data1[10] = {0};
u8 Median_num1 = 0;
u8 Average1[2] = {0};
u8 Average1_num = 0;
u8 Final_data;
bit start_key, start_trg, start_cont, done_flag = 0, key_flag = 0;
u8 Median(u8 *str, u8 num)
{
u8 i = 0;
u8 j = 0;
u8 Temp = 0;
for(i=0;i<num-1;i++)
{
for(j=i+1;j<num;j++)
{
if(str[i]<str[j])
{
Temp=str[i];
str[i]=str[j];
str[j]=Temp;
}
}
}
return str[num/2];
}
u16 GetADCResult(u8 ch)
{
ADC_CONTR = ADC_SPEEDLL | ch | ADC_START;
_nop_(); //must wait before inquiry
_nop_();
_nop_();
_nop_();
while(!(ADC_CONTR & ADC_FLAG)); //wait complete flag
ADC_CONTR &= ~ADC_FLAG; //closed ADC
return ADC_RES;
}
void InitADC()
{
P1ASF = 0xff; //open 8 channels ADC function
ADC_RES = 0; //clear previous result
ADC_CONTR = ADC_SPEEDLL;
delayms(5);
}
void ADC_Handle(void)
{
Median_data1[Median_num1] = GetADCResult(1);
Median_num1++;
if(Median_num1>9)
{
Median_num1 = 0;
Average1[Average1_num] = Median(Median_data1,10); //ÖDÖμÂË2¨
Average1_num++;
if(Average1_num>1)
{
Average1_num = 0;
ADC_AngleValue = (Average1[0]/2 + Average1[1]/2)/2; //ƽ¾ùÖμ
}
}
Median_data0[Median_num0] = GetADCResult(0);
Median_num0++;
if(Median_num0>9)
{
Median_num0 = 0;
Average0[Average0_num] = Median(Median_data0,10); //ÖDÖμÂË2¨
Average0_num++;
if(Average0_num>1)
{
Average0_num = 0;
ADC_SpeedValue = Average0[0]/2 + Average0[1]/2; //ƽ¾ùÖμ
}
}
if(abs(ADC_PreSpeedValue-ADC_SpeedValue)>16)
{
ADC_PreSpeedValue = ADC_SpeedValue;
}
else
{
ADC_SpeedValue = ADC_PreSpeedValue;
}
Speed_Level = ADC_SpeedValue/32 + 1;
if(abs(ADC_PreAngleValue-ADC_AngleValue)>4)
{
ADC_PreAngleValue = ADC_AngleValue;
}
else
{
ADC_AngleValue = ADC_PreAngleValue;
}
}
void Motor_Handle(u8 speed, u8 angle)
{
u16 i;
if(done_flag==1)
{
if(p_flag==1)
{
PWM_Value += speed;
if(PWM_Value >= angle)
{
PWM_Value = angle;
if(PWM_Value == angle)
{
wait_count++;
if(wait_count>=20)
{
wait_count = 0;
p_flag = 0;
}
}
}
}
else
{
if(speed>4)
{
if(PWM_Value<40)
{
speed = 4;
}
if(speed>2)
{
if(PWM_Value<10)
{
speed = 2;
}
}
}
PWM_Value-=speed;
if(PWM_Value<=0)
{
PWM_Value = 0;
if(PWM_Value == 0)
{
done_flag = 0;
}
}
}
}
PWM_TrueValue = PWM_Value;
PWM0 = 1;
for(i=0; i<=65; i++){}
for(i=0; i<=PWM_TrueValue; i++){}
PWM0 = 0;
}
void main()
{
u16 i;
TIMER_Init();
UART_Init();
InitADC();
while(1)
{
if(vKeyScan()==1)
{
start_key = 1;
start_trg = start_key & (start_key ^ start_cont);
start_cont = start_key;
}
else
{
start_key = 0;
start_trg = 0;
start_cont = 0;
}
if(start_trg && start_cont)
{
key_flag = 1;
}
if(done_flag==0)
{
if(start_trg && start_cont)
{
done_flag = 1;
p_flag = 1;
key_flag = 0;
}
}
else
{
key_flag = 0;
}
ADC_Handle();
if(timer1_count>=21)
{
timer1_count = 0;
Motor_Handle(Speed_Level, ADC_AngleValue);
// UART_SendData(Speed_Level);
// UART_SendData(ADC_AngleValue);
}
}
}
加载中...
一周热门
更多
>
相关问题
STM32F4上I2C(在PROTEUS中模拟)调试不通的问题
6 个回答
芯片供应紧张,准备换个MCU,MM32L系列替换STM32L系列的怎么样?
7 个回答
STM32同时使用两个串口进行数据收发时数据丢包的问题
5 个回答
STM32F103串口通信死机问题
4 个回答
STM32WLE5CC连接SX1268在LoRa模式下能与 SX1278互通吗?
2 个回答
STM32开发板免费用活动
7 个回答
stm32 处理 DHT11占用太多时间,大家程序是怎么设计的
8 个回答
分享一个STM32单片机做的离线编程器代码
9 个回答
相关文章
ST公司第一款无线低功耗单片机模块有效提高物联网设计生产效率
0个评论
如何实现对单片机寄存器的访问
0个评论
通过USB用STM32片内自带Bootloader下载程序及注意事项
0个评论
欲练此功必先自宫之STM32汇编启动,放慢是为了更好的前行
0个评论
×
关闭
采纳回答
向帮助了您的网友说句感谢的话吧!
非常感谢!
确 认
×
关闭
编辑标签
最多设置5个标签!
STM32
保存
关闭
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
关闭
您已邀请
15
人回答
查看邀请
擅长该话题的人
回答过该话题的人
我关注的人
我看了一下,你这个程序主要只分了20个档,要增加档位就要把定时器中断时间给减小,但是51单片机定时器中断时间越短就越不准,我建议用delay来写,我就是用的delay的方法。
#include "include.h"
//declare SFR associated with the ADC
sfr ADC_CONTR = 0xC5; //ADC control register
sfr ADC_RES = 0xC6; //ADC high 8-bit result register
sfr ADC_LOW2 = 0xC7; //ADC low 2-bit result register
sfr P1ASF = 0X97; //P1 secondary function control register
//Define ADC operation const for ADC_CONTR
#define ADC_FLAG 0x10 //ADC complete
#define ADC_START 0x08 //ADC start control bit
#define ADC_SPEEDHH 0x00 //89 clocks
#define ADC_SPEEDH 0x20 //179 clocks
#define ADC_SPEEDL 0x40 //356 clocks
#define ADC_SPEEDLL 0x60 //534 clocks
void InitADC(void);
u16 GetADCResult(u8 ch);
sbit PWM0 = P2^0;
bit p_flag = 1;
u8 Speed_Level=1;
u8 wait_count = 0;
u8 ADC_AngleValue = 0;
u8 ADC_PreAngleValue = 0;
u8 ADC_SpeedValue = 0;
u8 ADC_PreSpeedValue = 0;
u8 PWM_Flag = 0;
s16 PWM_PreValue = 0;
u16 PWM_TrueValue = 0;
s16 PWM_Value = 0;
u8 Median_data0[10] = {0};
u8 Median_num0 = 0;
u8 Average0[2] = {0};
u8 Average0_num = 0;
u8 Median_data1[10] = {0};
u8 Median_num1 = 0;
u8 Average1[2] = {0};
u8 Average1_num = 0;
u8 Final_data;
bit start_key, start_trg, start_cont, done_flag = 0, key_flag = 0;
u8 Median(u8 *str, u8 num)
{
u8 i = 0;
u8 j = 0;
u8 Temp = 0;
for(i=0;i<num-1;i++)
{
for(j=i+1;j<num;j++)
{
if(str[i]<str[j])
{
Temp=str[i];
str[i]=str[j];
str[j]=Temp;
}
}
}
return str[num/2];
}
u16 GetADCResult(u8 ch)
{
ADC_CONTR = ADC_SPEEDLL | ch | ADC_START;
_nop_(); //must wait before inquiry
_nop_();
_nop_();
_nop_();
while(!(ADC_CONTR & ADC_FLAG)); //wait complete flag
ADC_CONTR &= ~ADC_FLAG; //closed ADC
return ADC_RES;
}
void InitADC()
{
P1ASF = 0xff; //open 8 channels ADC function
ADC_RES = 0; //clear previous result
ADC_CONTR = ADC_SPEEDLL;
delayms(5);
}
void ADC_Handle(void)
{
Median_data1[Median_num1] = GetADCResult(1);
Median_num1++;
if(Median_num1>9)
{
Median_num1 = 0;
Average1[Average1_num] = Median(Median_data1,10); //ÖDÖμÂË2¨
Average1_num++;
if(Average1_num>1)
{
Average1_num = 0;
ADC_AngleValue = (Average1[0]/2 + Average1[1]/2)/2; //ƽ¾ùÖμ
}
}
Median_data0[Median_num0] = GetADCResult(0);
Median_num0++;
if(Median_num0>9)
{
Median_num0 = 0;
Average0[Average0_num] = Median(Median_data0,10); //ÖDÖμÂË2¨
Average0_num++;
if(Average0_num>1)
{
Average0_num = 0;
ADC_SpeedValue = Average0[0]/2 + Average0[1]/2; //ƽ¾ùÖμ
}
}
if(abs(ADC_PreSpeedValue-ADC_SpeedValue)>16)
{
ADC_PreSpeedValue = ADC_SpeedValue;
}
else
{
ADC_SpeedValue = ADC_PreSpeedValue;
}
Speed_Level = ADC_SpeedValue/32 + 1;
if(abs(ADC_PreAngleValue-ADC_AngleValue)>4)
{
ADC_PreAngleValue = ADC_AngleValue;
}
else
{
ADC_AngleValue = ADC_PreAngleValue;
}
}
void Motor_Handle(u8 speed, u8 angle)
{
u16 i;
if(done_flag==1)
{
if(p_flag==1)
{
PWM_Value += speed;
if(PWM_Value >= angle)
{
PWM_Value = angle;
if(PWM_Value == angle)
{
wait_count++;
if(wait_count>=20)
{
wait_count = 0;
p_flag = 0;
}
}
}
}
else
{
if(speed>4)
{
if(PWM_Value<40)
{
speed = 4;
}
if(speed>2)
{
if(PWM_Value<10)
{
speed = 2;
}
}
}
PWM_Value-=speed;
if(PWM_Value<=0)
{
PWM_Value = 0;
if(PWM_Value == 0)
{
done_flag = 0;
}
}
}
}
PWM_TrueValue = PWM_Value;
PWM0 = 1;
for(i=0; i<=65; i++){}
for(i=0; i<=PWM_TrueValue; i++){}
PWM0 = 0;
}
void main()
{
u16 i;
TIMER_Init();
UART_Init();
InitADC();
while(1)
{
if(vKeyScan()==1)
{
start_key = 1;
start_trg = start_key & (start_key ^ start_cont);
start_cont = start_key;
}
else
{
start_key = 0;
start_trg = 0;
start_cont = 0;
}
if(start_trg && start_cont)
{
key_flag = 1;
}
if(done_flag==0)
{
if(start_trg && start_cont)
{
done_flag = 1;
p_flag = 1;
key_flag = 0;
}
}
else
{
key_flag = 0;
}
ADC_Handle();
if(timer1_count>=21)
{
timer1_count = 0;
Motor_Handle(Speed_Level, ADC_AngleValue);
// UART_SendData(Speed_Level);
// UART_SendData(ADC_AngleValue);
}
}
}
一周热门 更多>