だんだんバイク弄りたいのか、PIC弄りたいのか分からん様になってきた。
PIC12版は、後はもうセッティングとかガワの話になっちゃうので、初心に戻りUSB対応しようと思う。

USBのホスト機能はPIC24Fで散々やってみたが、5V500mA、2.5Wというハンパ無い大電力が必要で、解決するにはレギュレータじゃなくて、DC/DCコンバータが必要という結論。
これだとなかなかサイズが小さくならないので後回しにする。
まだその段階ではない。
PIC24はなかなかパワフルで機能も多くて面白かったけどね。

USB対応のPICはいろいろあるのだが、サイズを小さくしたいので、PIC18F15K50を考えてみようと思う。
20ピンのUSB対応PICはこれ一択。
まずはここから検討してみたい。

なぜそんなに小さくしたいのか。
それはSDRだから。
場所がないのよ。ホンマ。

PIC12Fも、もうワンサイズ小さくならんかな〜と思って考えてみる。
iPhone 006

むりかな〜
iPhone 007

むりやな〜。どう考えても。
レギュレータを小さくすればイケるかな。
パズルを解いてるみたいやね。

だけど基板発注したらたぶん余裕なんで、一回発注してみようかいな。
今回は熱問題もまったくないので、実際このサイズでも余裕やろうね。


PIC18F15K50のプロジェクトを開始する前に、、MPLAB X IDEを入れてみた。
Windows/Max/Linux対応ってことで、やっぱりJavaベースなんだろうなと思っていたら、やはり NetBEANS でしたとさ。
Eclipseに慣れてきたのに、いまさらNBはなぁ、、、まぁ嫌いじゃないけど。
でもやっぱり昔のIDEが軽くて使いやすいので、結局開発環境は MPLAB 8 に戻ってきましたとさ。


PIC12Fは一旦終わりでリファクタリングフェーズ。
作業前のものとしてソース公開しときます。
サイズはボチボチやろか。
もっと色々とやりたかった気もするが、もう少しメモリがあるCPUでやる事とします。

結構細かい実機あわせ的なパラメータがあるけど、まぁこんなものでしょう。
気になる部分があるのできっとまだ修正は入ります。
とソースを眺めていたら、、、
あ、、、不具合発見・・・
時々オープニング動作が行われないのは、
これが原因か!
アホか俺は。
後日修正しておきます。
今後はなんとかアクセルオンとオフの切り替えを感知して制御を変えたいと思っています。

→以下のソースは重たいのでCDIと合わせて軽く作り直してます

[コードを表示する]
#include <htc>
#include <string>
#define _XTAL_FREQ 8000000 // 8MHz
#define LED GP1
#define MC1 GP4
#define MC2 GP5
#define MODE GP3

#define TRUE 1
#define FALSE 0

#define TIMEOUT_COUNT 7    // この回数タイムアウトしたらエンジン停止

#define INSENSITIVE_RANGE 6 // 不感症領域
#define WIDE_RANGE_RATIO 3  // 特別な不感症領域の倍率
#define BRAKE_TIME 120    // ブレーキを掛ける時間(x 22us)
#define DRIVE_TIME 1    // 立ち上がりの最小時間(x 22us)
#define MT_STOP_TIME 90    // TA8428Kは切り替えにSTOP時間100us必要


#define FULL_CLOSE_TARGET(x) (gPotTable[x][0])
#define FULL_OPEN_TARGET(x) (gPotTable[x][10])

__CONFIG(
  FOSC_INTOSCIO &amp;  // 発振機 内臓利用
  WDTE_OFF &amp;    // ウォッチドッグ 無効
  PWRTE_ON &amp;    // パワーアップタイマー 有効
  BOREN_ON &amp;    // ブラウンアウト検出 有効
  MCLRE_OFF &amp;    // ~MCLR 無効
  CP_OFF &amp;      // コードプロテクション 無効
  IESO_OFF &amp;    // IEスイッチオーバー 無効
  FCMEN_OFF      // フェイルセーフクロック 無効
  );

// ポテンションメータテーブル
const unsigned int gPotTable[2][11] = {
//0    1    2    3    4    5    6    7    8    9   10(Krpm)
190, 190, 190, 190, 190, 190, 274, 357, 446, 500, 500,
190, 190, 170, 170, 175, 220, 290, 380, 470, 500, 500
};


// Engine state
typedef enum{
  EG_STARTED,    // EG_STARTED
  EG_INIT_OPEN1,  // 電源オン時の最初の全開動作
  EG_INIT_CLOSE,  // その次の全閉
  EG_INIT_OPEN2,  // その次の全開
  EG_INITIALIZED,  // 全開のままエンジン起動待ち
}EG_STATE;

// Moter state
/*
IN1 IN2 OUTA OUTB  
H   H   L    L  BRAKE
L   H   L    H  逆転
H   L   H    L  正転
L   L   OFF     (ハイインピーダンス)  ストップ
*/
typedef enum{
  MT_BRAKE,
  MT_OPEN,
  MT_CLOSE,
  MT_STOP
}MT_STATE;

MT_STATE mt_state[3] = {MT_STOP};

#define MTBrake() {MC1=1;MC2=1;}
#define MTOpen()  {MC1=0;MC2=1;}
#define MTClose() {MC1=1;MC2=0;}
#define MTStop()  {MC1=0;MC2=0;}

EG_STATE gEGState = EG_STARTED;
unsigned int gRPM = 0;
unsigned int gPot = 0;

int MoterHead(unsigned int pot, unsigned int rpm, unsigned char mode);

/** -----------------------------------------------------------------
          1|VDD    PIC12F683    VSS|8
  MTR_O&lt;- 2|GP5(MC2)        GP0/AN0|7 &lt;-Potension meter Analog IN
  MTR_C&lt;- 3|GP4(MC1)        GP1/AN1|6 -&gt;LED
  MODE -&gt; 4|GP3/~MCLR  GP2/AN2/CCP1|5 &lt;-PULSE
------------------------------------------------------------------ */

/** -----------------------------------------------------------------
 void main(void)
 メイン関数
------------------------------------------------------------------ */
void main(void)
{
  OPTION_REG = 0b10000010;  // PUしない
  WPU        = 0b00000000;  // PUしない
  OSCCON     = 0b01110000;  // 8MHz
  TRISIO     = 0b00001101;  // IN: GP0/GP2/GP3/ OUT:GP1/GP4/GP5
  ANSEL      = 0b01010001;  // AN0選択、Tad(Fosc/16)=2.0us
  CMCON0     = 0x7;      // コンパレータ無効
  ADCON0     = 0b10000001;  // 右詰、VDD、AN0利用

  gEGState = EG_INIT_OPEN1;

  MTStop();  // モータ初期値
  // スタートアップデモ
  {
    int ii;
    for( ii = 0; ii &lt; 10; ii++ ) {
      __delay_ms(100);
      LED = !LED;
    }
  }
  LED = 0;

  // Input capture初期化(*1)
  CCP1CON = 0;  // 一度リセットする必要がある
  CCP1CON      = 0b00000110;  // every 4th rising edge
  CCP1IF = 0;  // 設定後は必ずIFをリセット

  // タイマー初期化
  T1CON     = 0b00110100;    // T1CKPS 1:8
  TMR1IF = 0;
  TMR1L=0;
  TMR1H=0;
  
  // 割り込み初期化
  GIE = 1;
  PEIE = 1;
  TMR1IE = 1;    // Timer1 intterupt on
  TMR1ON = 1;    // Timer1 start
  CCP1IE = 1;    // Capture interrupt on

  // メインループ
  while(1) {
    LED = MODE;    // モード表示
    GO_DONE = 1;    // 変換開始
    while(GO_DONE);  // 変換待ち Tad*11=22us
    gPot = (ADRESH * 256 + ADRESL)+1;  // Analog input

    if(MoterHead(gPot, gRPM, MODE)) {
      __delay_us(MT_STOP_TIME);
    }  
  }
}

/** -----------------------------------------------------------------
  void MoterHead(unsigned int pot, unsigned int rpm)
  モータ制御
  @param pot ポテンションメータ(1〜1,024)
  @param rpm 回転数(0〜9,999)
  @oaram mode 0 or 1
  @return 100usの待ち時間が必要な場合TRUE
------------------------------------------------------------------ */
int MoterHead(unsigned int pot, unsigned int rpm, unsigned char mode)
{
  unsigned int target;
  static char brake_count = 0;
  static char open_count = 0;
  static char close_count = 0;
  int iRange = INSENSITIVE_RANGE;

  
  if(rpm &gt;=500) {
    gEGState = EG_STARTED;
  }
  if( rpm &lt; 2000 ) {
    iRange = INSENSITIVE_RANGE * WIDE_RANGE_RATIO;
  }  
  if( rpm &gt; 10000 ) {
    rpm = 9999;
  }


  // --------------------------------------------------------------
  // モード別のターゲット設定とモード遷移
  // --------------------------------------------------------------
  switch(gEGState) {
  case EG_STARTED: {
    unsigned int index;

    // ターゲット算出 (*2)
    index = rpm / 1000;
    if(gPotTable[mode][index+1] &gt;= gPotTable[mode][index]) {
      target = gPotTable[mode][index]
        + ((((gPotTable[mode][index+1] - gPotTable[mode][index])
        * ((rpm%1000)/100)))/10);
    } else {
      target = gPotTable[mode][index]
        - ((((gPotTable[mode][index] - gPotTable[mode][index+1])
        * ((rpm%1000)/100)))/10);
    }       
    break;
  }  

  // 電源オン時の最初の全開動作
  case EG_INIT_OPEN1: {

    target = FULL_OPEN_TARGET(mode);
    if( pot &gt;= FULL_OPEN_TARGET(mode) ) {
      gEGState = EG_INIT_CLOSE;
    }  
    break;
  }  
  
  // その次の全閉
  case EG_INIT_CLOSE: {

    target = FULL_CLOSE_TARGET(mode);
    if( pot &lt;= FULL_CLOSE_TARGET(mode) ) {
      gEGState = EG_INIT_OPEN2;
    }  
    break;
  }  
  
  // その次の全開
  case EG_INIT_OPEN2: {

    target = FULL_OPEN_TARGET(mode);
    if( pot &gt;= FULL_OPEN_TARGET(mode) ) {
      gEGState = EG_INITIALIZED;
    }  
    break;
  }
  
  // 全開のままエンジン起動待ち
  case EG_INITIALIZED: {

    target = FULL_OPEN_TARGET(mode);
    iRange = INSENSITIVE_RANGE * WIDE_RANGE_RATIO;
    // パルスが入ればEG_STATEDへ遷移
    if( rpm &gt; 0 ) {
      gEGState = EG_STARTED;  
    }  
    break;
  }  

  default:
    break;
  }
  
  // --------------------------------------------------------------
  // ポテンションメータと比較して制御
  // --------------------------------------------------------------
  if((MT_OPEN == mt_state[0] &amp;&amp; MT_OPEN == mt_state[1]
        &amp;&amp; MT_OPEN == mt_state[2]) ||
    (MT_CLOSE == mt_state[1] &amp;&amp; MT_CLOSE == mt_state[1]
        &amp;&amp; MT_CLOSE == mt_state[2])) {
    iRange /= 2;
  }
  
  if(target &gt; pot+iRange) {
    mt_state[0] = MT_OPEN;
  } else if(target &lt; pot-iRange) {
    mt_state[0] = MT_CLOSE;
  } else {
    mt_state[0] = MT_STOP;
  }


  // --------------------------------------------------------------
  // BRAKE制御  
  // --------------------------------------------------------------
  if(MT_STOP == mt_state[0] &amp;&amp; MT_STOP == mt_state[1]
      &amp;&amp; (MT_OPEN == mt_state[2] || MT_CLOSE == mt_state[2])) {
    brake_count = BRAKE_TIME;
  } else if(MT_OPEN == mt_state[0] &amp;&amp; MT_STOP == mt_state[1]) {
    open_count = DRIVE_TIME;
  } else if(MT_CLOSE == mt_state[0] &amp;&amp; MT_STOP == mt_state[1]) {
    close_count = DRIVE_TIME;
  }

  if(open_count &gt;0) {
    open_count--;
    mt_state[0] = MT_OPEN;
  } else if(close_count &gt;0) {
    close_count--;
    mt_state[0] = MT_CLOSE;
  } else if(brake_count &gt; 0) {
    brake_count--;
    mt_state[0] = MT_BRAKE;
  }
  // --------------------------------------------------------------
  // モータ出力
  switch( mt_state[0] ) {
    case MT_BRAKE: MTBrake();   break;
    case MT_OPEN:  MTOpen();    break;
    case MT_CLOSE: MTClose();   break;
    case MT_STOP:  MTStop();    break;
    default:       MTStop();    break;
  }
  mt_state[2] = mt_state[1];
  mt_state[1] = mt_state[0];

#ifdef __DEBUG
  switch( mt_state[0] ) {
    case MT_BRAKE: LED=1;   break;
    case MT_OPEN:  LED=0;    break;
    case MT_CLOSE: LED=0;   break;
    case MT_STOP:  LED=0;    break;
    default:       LED=0;    break;
  }
#endif
  
  if(mt_state[0] == MT_STOP &amp;&amp; mt_state[1] != MT_STOP) {
    return 1;
  }  
  return 0;
  
}  

/** -----------------------------------------------------------------
  void interrupt ISR(void)
  割り込み制御関数
  Timer1、Captureを処理する
------------------------------------------------------------------ */

void interrupt ISR(void)
{
  static int timeout_count = 0;
  // Input capture 
  if(CCP1IF) {
    // タイマーリセット
    TMR1H=0;
    TMR1L=0;
    
    gRPM = 60000000UL/(unsigned long)((CCPR1H*256)+CCPR1L);

    CCP1IF = 0;
  }  

  // Timer1 タイムアウト→エンジン停止と判断
  if(TMR1IF) {
    gRPM = 0;
    if(TIMEOUT_COUNT &lt; timeout_count++) {
      if(EG_STARTED == gEGState) {
        gEGState = EG_INIT_OPEN1;
      }
      timeout_count = 0;
    }  
    TMR1IF = 0;
  }
}


回路図も思い出せるうちに書いておこう。
大体こんな感じ。
無題
あ、GP3のプルアップ忘れてる・・・。
色々締まりませんな。

PIC18F15K50のデータシートとにらめっこ中です。