メインプログラム:RC_RX.c
プロセッサーエキスパート(PE)で設定した結果、下図の様なソースファイルが生成されます。初期設定は全て完了していますのでMAIN関数の含まれているRC_RX.cのみを記述します。
【プログラムの概要】
今回は陸上走行ラジコンですが、3軸制御となりますのでヘリコプターと同様の制御方法が出来るようにしました。
まずは送信機側のスティックですが、下図のように左のスティック前後がエレベーターで前進・後進を制御します。左右はラダーで進行方向を左右に制御します。
右スティックの前後は今回使用しませんがヘリコプターではピッチ制御で機体の上下を制御します。最後に左右はエルロンで左右に平行移動します。
下図に走行制御パターンを示します。Bが前後直進で左右もモーターは同じ速度で回転します。Aのように左に旋回する場合、右のモーターは変化せず、左のモーターの回転数が下がるように制御します。Eはエレベーターが中点の時に左右のモーターが正転と逆転で信地旋回をします。そしてDはエルロンの制御で横方向モーターを制御します。
/** ###################################################################
** Filename : RC_RX.C
** Project : RC_RX
** Processor : MC9S08SH8CPJ
** Version : Driver 01.11
** Compiler : CodeWarrior HCS08 C Compiler
** Date/Time : 2009/11/22, 14:50
** Abstract :
** Main module.
** This module contains user's application code.
** Settings :
** Contents :
** No public methods
**
** ###################################################################*/
/* MODULE RC_RX */
/* Including needed modules to compile this module/procedure */
#include "Cpu.h"
#include "Events.h"
#include "AS1.h"
#include "PWM1.h"
#include "PWM2.h"
#include "PWM3.h"
#include "PWM4.h"
#include "FC1.h"
#include "Bits2.h"
/* Include shared modules, which are used for whole project */
#include "PE_Types.h"
#include "PE_Error.h"
#include "PE_Const.h"
#include "IO_Map.h"
/* User includes (#include below this line is not maintained by Processor Expert) */
/****************************************************
* *
* Filename : RC_RX.c *
* Version : 01.00 *
* Compiler : CodeWarrior HCS08 C Compiler *
* Date/Time : 2011/12/25, 0:00 *
* Debug : 2012/01/01, 17:30 *
* *
* 電動アンプ付ラジコン受信機制御プログラム *
* *
* Copyright : n.Tanaka *
* *
****************************************************/
/***** 宣言部 *****/
#define L1 PTAD_PTAD0 // 左側モーター前進
#define L2 PTCD_PTCD0 // 左側モーター後進
#define R1 PTBD_PTBD5 // 右側モーター前進
#define R2 PTCD_PTCD1 // 右側モーター後進
word L_AIL; // 左エルロンモーターPWM制御値レジスタ
word R_AIL; // 右エルロンモーターPWM制御値レジスタ
word L_ELV; // 左モーターPWM制御値レジスタ
word R_ELV; // 右モーターPWM制御値レジスタ
word L_RAD; // 左モーター用ラダー制御差分値レジスタ
word R_RAD; // 右モーター用ラダー制御差分値レジスタ
word L_WORK; // 左モーター用PWM制御値レジスタ
word R_WORK; // 右モーター用PWM制御値レジスタ
byte CUSTOMCODE; // カスタムコード
byte CH1_H,CH1_L; // CH1受信データ(10bit)
byte CH2_H,CH2_L; // CH2受信データ(10bit)
byte CH3_H,CH3_L; // CH3受信データ(10bit)
byte CH4_H,CH4_L; // CH4受信データ(10bit)
byte SW_DATA; // 10スイッチ受信データ
byte TEMP; // テンポラリーレジスタ
word CH1,CH2; // PWM制御データ(16bit)
word CH3,CH4; // PWM制御データ(16bit)
word FAIL_CH1; // CH1 fail safe mode data
word FAIL_CH2; // CH2 fail safe mode data
word FAIL_CH3; // CH3 fail safe mode data
word FAIL_CH4; // CH4 fail safe mode data
byte FAIL_SW; // SW fail safe mode data
byte ERR_COUNTER; // 受信エラーカウンター
/***** プロトタイプ宣言 *****/
void AILERON(void);
void L_ROTATION(void);
void R_ROTATION(void);
void FORWORD(void);
void REVERSE(void);
void FAIL_SAFE(void);
void RECEIVE(void);
/*************
* メイン関数 *
*************/
void main(void)
{
/* Write your local variable definition here */
/*** Processor Expert internal initialization. DON'T REMOVE THIS CODE!!! ***/
PE_low_level_init();
/*** End of Processor Expert internal initialization. ***/
/* Write your code here */
/* For example: for(;;) { } */
/***********
* 初期設定 *
***********/
/***** TRIM設定 *****/
ICSTRM = 0xA2; // 内臓基準クロックのトリム設定
ICSSC_FTRIM = 1; // 内臓基準クロックのファイントリム設定
/***** ポート設定 *****/
PTADD_PTADD0 = 1; // PWM出力端子を出力に設定
PTBDD_PTBDD5 = 1;
PTCDD_PTCDD0 = 1;
PTCDD_PTCDD1 = 1;
/***** モジュロタイマ設定 *****/
MTIMSC_TSTP = 1; // タイマ停止(周期は3mS)
/***** フェイルセーフ用制御データ設定 *****/
送信機からの電波が受信できない時は以下のデータを出力して安全に静止する。
FAIL_CH1 = 512;
FAIL_CH2 = 512;
FAIL_CH3 = 512;
FAIL_CH4 = 512;
FAIL_SW = 0;
/***** 制御データ初期値設定 *****/
CUSTOMCODE = 0x78;
CH1_H = 2;
CH1_L = 0;
CH2_H = 2;
CH2_L = 0;
CH3_H = 2;
CH3_L = 0;
CH4_H = 2;
CH4_L = 0;
L1 = 1;
R1 = 1;
L2 = 1;
R2 = 1;
/***************
* メインループ *
***************/
for(;;)
{
RECEIVE(); // 制御データ受信
/***** エルロン制御 *****/
中点データを512とし、±10以内は中点として不感帯を設ける。
/* エルロン左 */
if (CH1 > 522)
{
R_AIL = CH1 - 512; // REV側PWM
L_AIL = 0; // FOR側High固定
}
/* エルロン右 */
else if (CH1 < 502)
{
L_AIL = 512 - CH1; // FOR側PWM
R_AIL = 0; // REV側High固定
}
/* ニュートラル */
else
{
L_AIL = 0;
R_AIL = 0;
}
/***** ラダー制御 *****/
不感帯は±5。
/* ラダー左 */
if (CH3 > 517)
{
L_RAD = CH3 - 512; // 左モーター用ラダー差分値
R_RAD = 0;
}
/* ラダー右 */
else if (CH3 < 507)
{
L_RAD = 0;
R_RAD = 512 - CH3; // 右モーター用ラダー差分値
}
/* ニュートラル */
else
{
L_RAD = 0;
R_RAD = 0;
}
/***** エレベータ制御 *****/
不感帯は±30.
/* 後進 */
if (CH2 > 542)
{
REVERSE(); // 後進切り替え
if (CH2 >= 1023) CH2 = 1023; // 後進最大値制限
L_ELV = CH2 - 512; // 左モーター後進制御値
R_ELV = CH2 - 512; // 右モーター後進制御値
}
/* 前進 */
else if (CH2 < 482)
{
FORWORD(); // 前進切替
if (CH2 >= 1023) CH2 = 1023; // 前進最大値制限
L_ELV = 512 - CH2; // 左モーター前進制御値
R_ELV = 512 - CH2; // 右モーター前進制御値
}
/* ニュートラル */
else
{
L_ELV = 0; // エレベータ制御ニュートラル
R_ELV = 0;
if (L_RAD > 0) L_ROTATION(); // 左信地旋回
else if (R_RAD > 0) R_ROTATION(); // 右信地旋回
}
/***** エレベータ・ラダー合成 *****/
/* ラダー制御値制限 */
if (L_ELV != 0 && L_ELV < L_RAD) L_RAD = L_ELV;
if (R_ELV != 0 && R_ELV < R_RAD) R_RAD = R_ELV;
コントロールを楽にするため、旋回はラダーの制御値を1/2にする。
/* 左エレベーター制御値+左ラダー制御値 */
if (L_ELV != 0) L_WORK = L_ELV - (L_RAD / 2);
/* 左信地旋回 */
else if (L_RAD > 50) L_WORK = L_RAD;
/* 右エレベーター制御値+右ラダー制御値 */
if (R_ELV != 0) R_WORK = R_ELV - (R_RAD / 2);
/* 右信地旋回 */
else if (R_RAD > 50) R_WORK = R_RAD;
/* PWM DATA OUT */
TPM1C0V = L_WORK; // 左モーターPWM制御値出力
TPM1C1V = R_WORK; // 右モーターPWM制御値出力
TPM2C0V = R_AIL; // 右エルロンモーターPWM制御値出力
TPM2C1V = L_AIL; // 左エルロンモーターPWM制御値出力
} //End of main loop!
/*** Don't write any code pass this line, or it will be deleted during code generation. ***/
/*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
for(;;){}
/*** Processor Expert end of main routine. DON'T WRITE CODE BELOW!!! ***/
} /*** End of main routine. DO NOT MODIFY THIS TEXT!!! ***/
/***** 関数群 *****/
/*********************
* 左信地旋回切替関数 *
*********************/
void L_ROTATION(void)
{
TPM1C0V = 0; // Clear PWM data
TPM1C1V = 0;
Cpu_Delay100US(1); // Wait 100uS
SOPT2 = 2; // PWM output poart set
L1 = 1;
R1 = 1;
L2 = 1;
R2 = 1;
R_RAD = L_RAD;
}
/*********************
* 右信地旋回切替関数 *
*********************/
void R_ROTATION(void)
{
TPM1C0V = 0;
TPM1C1V = 0;
Cpu_Delay100US(1);
SOPT2 = 1;
L1 = 1;
R1 = 1;
L2 = 1;
R2 = 1;
L_RAD = R_RAD;
}
/***************
* 前進切替関数 *
***************/
void FORWORD(void)
{
TPM1C0V = 0;
TPM1C1V = 0;
Cpu_Delay100US(1);
SOPT2 = 0;
L1 = 1;
R1 = 1;
L2 = 1;
R2 = 1;
}
/***************
* 後進切替関数 *
***************/
void REVERSE(void)
{
TPM1C0V = 0;
TPM1C1V = 0;
Cpu_Delay100US(1);
SOPT2 = 3;
L1 = 1;
R1 = 1;
L2 = 1;
R2 = 1;
}
/*********************
* Fail safe mode関数 *
*********************/
void FAIL_SAFE(void)
{
CH1 = FAIL_CH1;
CH2 = FAIL_CH2;
CH3 = FAIL_CH3;
CH4 = FAIL_CH4;
SW_DATA = FAIL_SW;
}
/**************
* Receive関数 *
**************/
void RECEIVE(void)
{
/***** 受信処理 *****/
ERR_COUNTER = 0;
MTIMSC_TRST = 1; // モジュロタイマリセット
MTIMSC_TSTP = 0; // モジュロタイマ開始
/***** 受信待ち処理 *****/
while(!SCIS1_RDRF) // 受信待ち
{
if (MTIMSC_TOF) // タイムアウトしたらエラーカウンタ+1
{
ERR_COUNTER++;
MTIMSC_TRST =1;
}
if (ERR_COUNTER > 10) break; // 30mS経過したら抜ける
}
/***** 受信完了 *****/
TEMP = SCID; // 受信データ格納
if(TEMP == CUSTOMCODE) // 受信データがカスタムコードと一致
{
/***** CH1_H *****/
MTIMSC_TRST = 1;
while(!SCIS1_RDRF | MTIMSC_TOF); // 受信待ちとタイマ待ち(3mS)
if(MTIMSC_TOF == 0) CH1_H = SCID; // 3mS未経過でデータを受信!データ更新
else ERR_COUNTER++; // 3mS経過したのでエラーカウンタ+1
/***** CH1_L *****/
MTIMSC_TRST = 1;
while(!SCIS1_RDRF | MTIMSC_TOF);
if(MTIMSC_TOF == 0) CH1_L = SCID;
else ERR_COUNTER++;
/***** CH2_H *****/
MTIMSC_TRST = 1;
while(!SCIS1_RDRF | MTIMSC_TOF);
if(MTIMSC_TOF == 0) CH2_H = SCID;
else ERR_COUNTER++;
/***** CH2_L *****/
MTIMSC_TRST = 1;
while(!SCIS1_RDRF | MTIMSC_TOF);
if(MTIMSC_TOF == 0) CH2_L = SCID;
else ERR_COUNTER++;
/***** CH3_H *****/
MTIMSC_TRST = 1;
while(!SCIS1_RDRF | MTIMSC_TOF);
if(MTIMSC_TOF == 0) CH3_H = SCID;
else ERR_COUNTER++;
/***** CH3_L *****/
MTIMSC_TRST = 1;
while(!SCIS1_RDRF | MTIMSC_TOF);
if(MTIMSC_TOF == 0) CH3_L = SCID;
else ERR_COUNTER++;
/***** CH4_H *****/
MTIMSC_TRST = 1;
while(!SCIS1_RDRF | MTIMSC_TOF);
if(MTIMSC_TOF == 0) CH4_H = SCID;
else ERR_COUNTER++;
/***** CH4_L *****/
MTIMSC_TRST = 1;
while(!SCIS1_RDRF | MTIMSC_TOF);
if(MTIMSC_TOF == 0) CH4_L = SCID;
else ERR_COUNTER++;
/***** SW_DATA *****/
MTIMSC_TRST = 1;
while(!SCIS1_RDRF | MTIMSC_TOF);
if(MTIMSC_TOF == 0) SW_DATA = SCID;
else ERR_COUNTER++;
}
else ERR_COUNTER++; // カスタムコード不一致→エラーカウンタ+1
/***** 10bit化 *****/
if (ERR_COUNTER < 5)
{
CH1 = (CH1_H * 256 + CH1_L);
CH2 = (CH2_H * 256 + CH2_L);
CH3 = (CH3_H * 256 + CH3_L);
CH4 = (CH4_H * 256 + CH4_L);
}
else FAIL_SAFE();
}
/* END RC_RX */
/*
** ###################################################################
**
** This file was created by Processor Expert 3.06 [04.26]
** for the Freescale HCS08 series of microcontrollers.
**
** ###################################################################
*/