|
本帖最后由 xuwh008 于 2013-12-6 22:41 编辑
用上了mz-24,尽管爽,但无法继续操我的mcpx。以前用T8FG的时候为了玩mcpx按照C2PO的帖子DIY了一个DSM2高频头,现在换了遥控后本以为直接插遥控上就能用,结果发现有些问题,要么就是对频失败,要么就是飞起来十字盘跑偏。于是花了几天时间分析原因,经过不懈的努力,对C2PO的程序作了稍微的修改。终于成功搞定了MZ-24上能用的DSM2高频头。
元件清单:
Arduino pro mini 3.3v 8Mhz 板一个
ASM1117 3.3V 稳压芯片
一个发光二极管
两个开关
一个470欧姆电阻和一个560uf的电容
一个DX4E或者DX5E高频头
以及一些线头和一小块洞洞板。
这个就是DX5E高频头,用DX4E的也可以。
下面是电路图:
一下几张是C2PO的图片,借鉴一下,大家也可以根据这个图片看管脚的对应。
MZ-24上需要做如下设置:
BASE->TX CTL里面要选择PPM16;
BASE->out.Swap需要修改对外的通道顺序
BASE->EPA要相应的减少副翼,升降和螺距的行程量
BASE->Reverse里面保持原样
FUNCTION->trainner里面选择DSC-S,也就是玩模拟器的设置方法
这是我做出来的东东,找不到合适的盒子,感觉特丑,等以后找到外壳再搬家。
用法:
先接通mcpx电源,等电源灯闪烁。然后按住高频头的BIND开关通电,蓝灯会开始闪。蓝灯闪说明在开始对频,如果正常的话大约几秒后就能对上频。
如果高频头没有接收到PPM信号会蓝灯慢闪。
下面是程序代码:
//dsm2_mz_24.pde
#include "WProgram.h"
#include <avr/interrupt.h>
typedef enum {
NULL_ST = -1, NOT_SYNCHED, ACQUIRING, READY, FAILSAFE
} State_t;
#define PRESCALE 0x42
#define TICKS_PER_uS 1
#define MAX_CHANNELS 8
#define MIN_IN_PULSE (750 * TICKS_PER_uS)
#define MAX_IN_PULSE (2250 * TICKS_PER_uS)
#define SYNC_GAP_LEN (5000 * TICKS_PER_uS)
#define VALID_FRAMES 10
#define BIND_TIME 10000
#define BINDinterval 50
#define ERRORinterval 250
#define DSM2_CHANNELS 6
// "Pro mini" pinout
#define BINDING_PIN 2
#define BINDING_LED 5
#define FLASH_LED 10
#define PPM_PIN 8
static int Pulses[MAX_CHANNELS + 1];
static int Failsafe[MAX_CHANNELS + 1];
static byte ChannelNum;
static byte ChannelCnt;
static State_t State;
static byte stateCount;
volatile long ICR1Cn;
static byte DSM2_Header[2];
static byte DSM2_Channel[DSM2_CHANNELS*2] = {0x00,0xAA,0x05,0xFF,0x09,0xFF,0x0D,0xFF,0x13,0x54,0x14,0xAA};
static byte DSM2_Sent = 0;
static byte ChanIndex[] = {3,1,2,4,5,6,7,8}; //PPM to DSM2 Channel Mapping Table
static byte PPMwaitCount;
static int pulse;
long previousMillis = 0;
long ERRORpreviousMillis = 0;
long interval = 500;
byte DisFlash = LOW;
int LEDbrightness = 100;
int LEDfadeAmount = 5;
/* ---------- ---------- ---------- Sync ---------- ---------- ---------- */
static void processSync() {
if(State == READY) {
if( ChannelNum != ChannelCnt)
{
State = FAILSAFE;
}
}
else {
if(State == NOT_SYNCHED) {
State = ACQUIRING;
stateCount = 0;
} else {
if( State == ACQUIRING) {
if(++stateCount > VALID_FRAMES) {
State = READY;
ChannelCnt = ChannelNum;
}
} else
if( State == FAILSAFE) {
if(ChannelNum == ChannelCnt)
{
State = READY;
}
}
}
}
ChannelNum = 0;
}
/* ---------- ---------- ---------- Interrupt Handerling---------- ---------- ---------- */
ISR(TIMER1_OVF_vect) {
if(State == READY) {
State = FAILSAFE;
ChannelNum = 0;
}
}
ISR(TIMER1_CAPT_vect) {
ICR1Cn = ICR1;
TCNT1 = 0X00;
if(ICR1Cn >= SYNC_GAP_LEN)
{
processSync();
}
else
if(ChannelNum < MAX_CHANNELS) {
if((ICR1Cn >= MIN_IN_PULSE) && (ICR1Cn <= MAX_IN_PULSE))
Pulses[++ChannelNum] = ICR1Cn / TICKS_PER_uS;
else
if(State == READY) {
State = FAILSAFE;
ChannelNum = 0;
}
}
}
/* ---------- ---------- ---------- PPM Class ---------- ---------- ---------- */
class PPM_Decode {
public:
PPM_Decode() { // Constructor
}
void begin() {
pinMode(8, INPUT);
ChannelNum = 0;
State = NOT_SYNCHED;
TIMSK1 = 0x21;
TCCR1A = 0x00;
TCCR1B = PRESCALE;
for(byte ch = 1; ch <= MAX_CHANNELS; ch++) {
Failsafe[ch] = Pulses[ch] = 1500;
}
Failsafe[3] = Pulses[3] = 1100;
}
void stop() {
State = NOT_SYNCHED;
TIMSK1 = 0x00;
TCCR1A = 0x00;
TCCR1B = 0x00;
}
State_t getState() {
return State;
}
byte getChannelCnt() {
return ChannelCnt;
}
void setFailsafe(byte ch, int value) {
if((ch > 0) && (ch <= MAX_CHANNELS))
Failsafe[ch] = value;
}
void setFailsafe() {
if(State == READY)
for(byte ch = 1; ch <= MAX_CHANNELS; ch++)
Failsafe[ch] = Pulses[ch];
}
int getChannelData(uint8_t channel) {
int result = 0;
if(channel <= MAX_CHANNELS) {
if((State == FAILSAFE) && (Failsafe[channel] > 0 ))
result = Failsafe[channel];
else
if((State == READY) || (State == FAILSAFE)) {
cli();
result = Pulses[channel];
sei();
}
}
return result;
}
};
PPM_Decode Receiver = PPM_Decode();
void setup() {
Serial.begin(125000);
pinMode(BINDING_PIN, INPUT);
digitalWrite(BINDING_PIN, HIGH);
pinMode(BINDING_LED, OUTPUT);
digitalWrite(PPM_PIN, HIGH);
DSM2_Header[0] = 0;
DSM2_Header[1] = 0;
if(digitalRead(BINDING_PIN) == LOW) {
digitalWrite(BINDING_LED, HIGH);
BindDSM2();
}
digitalWrite(BINDING_LED,LOW);
Receiver.begin();
PPMwaitCount = 30;
while(Receiver.getState() != READY && PPMwaitCount-- > 0)
delay(100);
}
void loop() {
if(Receiver.getState() == READY || Receiver.getState() == FAILSAFE) {
if(ChannelNum == 0 || ChannelNum == ChannelCnt) {
if(DSM2_Sent == 0) {
for (byte i=0; i<DSM2_CHANNELS; i++) {
pulse = Receiver.getChannelData(ChanIndex) - 980;
pulse = constrain(pulse, 0, 0x3FF);
DSM2_Channel[i*2] = (byte)(i<<2) | highByte(pulse);
DSM2_Channel[i*2+1] = lowByte(pulse);
}
sendDSM2();
DSM2_Sent = 1;
} else {
if(Receiver.getState() == FAILSAFE) {
delay(20);
DSM2_Sent = 0;
}
}
} else {
if(ChannelNum == 1)
DSM2_Sent = 0;
}
}
if (State == READY){
digitalWrite(BINDING_LED,HIGH);
}else{
unsigned long currentMillis = millis();
if(currentMillis - ERRORpreviousMillis >= ERRORinterval)
{
ERRORpreviousMillis = millis();
if(DisFlash == LOW)
{
digitalWrite(BINDING_LED,LOW); // PPM TX LED
DisFlash = HIGH;
}
else
{
digitalWrite(BINDING_LED,HIGH); // PPM TX LED
DisFlash = LOW;
}
}
}
}
void sendDSM2() {
Serial.write(DSM2_Header, 2);
Serial.write(DSM2_Channel, DSM2_CHANNELS*2);
}
void BindDSM2(){
delay (250);
DSM2_Header[0] = 0x80;
unsigned long currentMillis = BIND_TIME + millis();
while(currentMillis > millis()){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > BINDinterval)
{
previousMillis = currentMillis;
if (DisFlash == LOW)
{
digitalWrite(BINDING_LED,LOW);
DisFlash = HIGH;
}
else
{
digitalWrite(BINDING_LED,HIGH);
DisFlash = LOW;
}
}
sendDSM2();
delay(20);
}
DSM2_Header[0] = 0;
digitalWrite(BINDING_LED, LOW);
}
|
评分
-
查看全部评分
欢迎继续阅读楼主其他信息
|