5iMX宗旨:分享遥控模型兴趣爱好

5iMX.com 我爱模型 玩家论坛 ——专业遥控模型和无人机玩家论坛(玩模型就上我爱模型,创始于2003年)
楼主: n44303
打印 上一主题 下一主题

DIY个飞翼用的陀螺仪混控器

[复制链接]
21
 楼主| 发表于 2012-7-28 00:15 | 只看该作者
最近家里来了好多亲戚,不多的时间就更少了。

AVR16有一个16位定时器,如果用它来做输出计数器的话混控器的输出精度可以达到1uS。不过输入捕捉就没了,要用外部中断才行。好在飞翼的控制比较简单,只需要2路输入。

看来用AVR16做这个有些奢侈了:em15:

欢迎继续阅读楼主其他信息

22
发表于 2012-7-28 07:31 | 只看该作者
原帖由 n44303 于 2012-7-26 14:51 发表
遥控器的混控是纯手动控制,并且没办法在混控输出通道中用一个陀螺仪控制一个飞翼通道,如果强行要用的话需要在每个轴上使用2个陀螺仪。
就是说要用陀螺仪控制一个2舵机的飞翼的X、Y轴,需要安装4个陀螺仪,并且要求 ...
大约明白LZ的意思了:就是在不动摇杆的时候,保持副翼和升降方向的稳定?
买一个现成的混控器就可以了,淘宝20元左右。
23
发表于 2012-7-28 10:16 | 只看该作者
好可爱啊!!:loveliness:
24
 楼主| 发表于 2012-7-29 12:27 | 只看该作者
原帖由 铜河 于 2012-7-28 07:31 发表
大约明白LZ的意思了:就是在不动摇杆的时候,保持副翼和升降方向的稳定?
买一个现成的混控器就可以了,淘宝20元左右。


用现成的混控一来速度慢、滞后严重,二来少了DIY的乐趣了。再说我那些单片机反正闲着也是闲着,还可以巩固一下单片机的知识。

好处多多啊。:em15: :em15:
25
 楼主| 发表于 2012-7-29 13:02 | 只看该作者

用M16或者M32实现2通道输出

用16位计数器的比较匹配输出功能实现2通道输出控制。

输出频率先定为100Hz,也就是10mS的周期,比普通的50Hz快一倍,但也没有333Hz那么快。飞翼还是没有那个必要的:em15:

就2个通道的输出,就没有必要用数组了

int   ch_in_01,                    //存储ch1的输入值,来自接收器
        ch_in_02,                 //存储ch2的输入值,来自接收器
        ch_out_01,         //存储ch1的输出值,直接作为舵机信号线的驱动信号
        ch_out_02,         //存储ch2的输出值,直接作为舵机信号线的驱动信号
        out_f = 100;         //设置驱动信号输出频率,单位Hz;今后可以方便的修改为50Hz或者333Hz

//TIMER1 initialize - prescale:8
// WGM: 14) PWM fast, TOP=ICRn
// desired value: 10000uSec
// actual value: 10000.000uSec (0.0%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0x00; //setup
TCNT1L = 0x00;
  OCR1A = ch_out_01;
  OCR1B = ch_out_02;
  ICR1  = out_f*100*2;//16M晶振;8分频;实际TOP数值为20000;TOP值可以用“out_f”进行修改;
TCCR1A|= (1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);        //OC1A/B 比较匹配时输出低电平;WGM13:WGM10配置TC1为快速PWM、TOP值=ICR1;
TCCR1B|= (1<<WGM13)|(1<<WGM12)|(1<<CS11);        //时钟8分频,每2个时钟=1uS;
}
26
发表于 2012-7-31 17:04 | 只看该作者

DDD

DDD
27
发表于 2012-7-31 17:18 | 只看该作者
NICE:em15:
28
 楼主| 发表于 2012-7-31 23:49 | 只看该作者
昨晚把输入检测写好了,现在手机上网,明天贴上来。

可以贴上了:

//ICC-AVR application builder : 2012/7/27 17:49:05
// Target : M16
// Crystal: 16.000Mhz

#include <iom16v.h>
#include <macros.h>


int out_f = 100,
//设置输出频率,单位Hz

ch_in_01,
   
//存储ch1的输入值

ch_in_02,
//存储ch2的输入值

ch_out_01,
//存储ch1的输出值

ch_out_02,
//存储ch2的输出值

int0_rising,

int0_falling,

int1_rising,

int1_falling;


char int0_ovf_count,

int1_ovf_count;
  //这里记录上升沿后timer1的溢出次数


void port_init(void)
{
PORTA = 0x0F;
DDRA  = 0xF0;
//PORTA最高4位为输出端口
PORTB = 0xFF;
DDRB  = 0x00;
PORTC = 0xFF;
DDRC  = 0x00;
PORTD = 0xFF;
DDRD  = 0x30;
}

//TIMER1 initialize - prescale:8
// WGM: 14) PWM fast, TOP=ICRn
// desired value: 10000uSec
// actual value: 10000.000uSec (0.0%)
void timer1_init(void)
{
TCCR1B = 0x00;
  //stop
TCNT1H = 0x00;
  //setup
TCNT1L = 0x00;
  OCR1A = ch_out_01;
  OCR1B = ch_out_02;
  ICR1  = out_f*100*2;
   

//16M晶振;8分频;实际TOP数值为20000;TOP值可以用“out_f”进行修改;
TCCR1A|= (1<<COM1A1)|(1<<COM1B1)|(1<<WGM11);
//OC1A/B 比较匹配时输出低电平;WGM13:WGM10配置TC1为快速PWM、TOP值=ICR1;
TCCR1B|= (1<<WGM13)|(1<<WGM12)|(1<<CS11);
//时钟8分频,每2个时钟=1uS;
}

#pragma interrupt_handler timer1_ovf_isr:iv_TIM1_OVF
void timer1_ovf_isr(void)
{
//TIMER1 has overflowed
TCNT1H = 0x00 /*INVALID SETTING*/; //reload counter high value
TCNT1L = 0x00 /*INVALID SETTING*/; //reload counter low value
int0_ovf_count++;
int1_ovf_count++;

ch_out_01 = (unsigned long)ch_in_01/100*75+(ch_in_02>>1);
//更新ch1的输出值

ch_out_02 = (unsigned long)ch_in_01/100*75-(ch_in_02>>1);
//更新ch2的输出值
}

#pragma interrupt_handler int0_isr:iv_INT0
void int0_isr(void)
{//external interupt on INT0  PD2

if(PIND & 0x04)//如果PD2为高电平,证明是上升沿触发

{

int0_rising = TCNT1;

int0_ovf_count = 0;

}

else

{

int0_falling = TCNT1;
//读取当前寄存器数值

ch_in_01 =(unsigned long)int0_ovf_count*ICR1+(unsigned long)int0_falling-(unsigned long)int0_rising;

}
}

#pragma interrupt_handler int1_isr:iv_INT1
void int1_isr(void)
{//external interupt on INT1 PD3

if(PIND & 0x08)//如果PD3为高电平,证明是上升沿触发

{

int1_rising = TCNT1;

int1_ovf_count = 0;

}

else

{

int1_falling = TCNT1;
//读取当前寄存器数值

ch_in_02 =(unsigned long)int1_ovf_count*ICR1+(unsigned long)int1_falling-(unsigned long)int1_rising;

}
}


//call this routine to initialize all peripherals
void init_devices(void)
{
//stop errant interrupts until set up
CLI(); //disable all interrupts
port_init();
timer1_init();
TIMSK |= 1<<TOIE1;   
  
//开timer1溢出中断

  GICR |= (1<<INT1)|(1<<INT0);
//开启外部中断int1,int0
MCUCR |= (1<<ISC10)|(1<<ISC00);
  
//设置int1,int0电平变化触发中断
SEI(); //re-enable interrupts
//all peripherals are now initialized
}








void main(void)
{
init_devices();
while(1)
{
;
}

}

[ 本帖最后由 n44303 于 2012-8-1 23:43 编辑 ]
29
发表于 2012-8-4 10:35 | 只看该作者
不错,程序都出来了。不知调通没?
看了上面程序,感觉有个地方可小小改进一下,现提出探讨:
TC1在TOP值为ICR1的快速PWM模式下,当计数器计到ICR1+1后,会自动清0,在溢出中断中可以省去清0的语句,省去两个时钟周期的中断时长。
30
发表于 2012-8-4 21:11 | 只看该作者
顶了
31
 楼主| 发表于 2012-8-4 21:49 | 只看该作者
原帖由 铜河 于 2012-8-4 10:35 发表
不错,程序都出来了。不知调通没?
看了上面程序,感觉有个地方可小小改进一下,现提出探讨:
TC1在TOP值为ICR1的快速PWM模式下,当计数器计到ICR1+1后,会自动清0,在溢出中断中可以省去清0的语句,省去两个时钟周 ...

接受
调通很容易,问题是混控程序还没有搞好,有什么好的建议么?
32
 楼主| 发表于 2012-8-10 12:19 | 只看该作者

混控没时间搞,确有了意外的收获

:em15:

没耐心拖到中间看,呵呵。

33
 楼主| 发表于 2012-8-15 02:01 | 只看该作者
没人关注啊
34
发表于 2012-8-15 04:20 | 只看该作者
这个其实有简单的办法。随便找个 MCPX, GCP 的主板上面带了三维陀螺仪。
还是数字的。芯片是 xmega 的,比 mega 还要好。然后就是编程就行了。
你这个读 gyro PPM 的输出频率太慢了,比较难做。
35
发表于 2012-8-16 10:21 | 只看该作者
看中LZ的手提。。是苹果的吧。。
36
 楼主| 发表于 2012-8-16 12:52 | 只看该作者
原帖由 buknwbg 于 2012-8-16 10:21 发表
看中LZ的手提。。是苹果的吧。。

Apple MBP
37
发表于 2012-8-17 12:05 | 只看该作者
:em26:
38
发表于 2012-8-22 13:04 | 只看该作者
39
发表于 2012-8-22 13:39 | 只看该作者
占楼看更新,真是幸福的人:em15:
40
 楼主| 发表于 2012-10-11 11:21 | 只看该作者
您需要登录后才可以回帖 登录 | 我要加入

本版积分规则

关闭

【站内推荐】上一条 /1 下一条

快速回复 返回顶部 返回列表