メインプログラム: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.
**
** ###################################################################
*/

TOP BACK NEXT