PIC初心者用掲示板

★★ 質問する前に下記をチェック ★★
(PICに関する疑問は必ず解決するはず)
←←←「電子工作の実験室」へ
←←←← 

■最新ツリー一覧

□このツリー付近のツリー一覧

★新規ツリー作成

◆ 9977. 16F84AでモータPWM制御方法 [kazu22006/03/21 12:40
    ┗ 9978. Re: 16F84AでモータPWM制御方法 [松本2006/03/21 13:27
        ┗ 10043. Re: 16F84AでモータPWM制御方法 [kazu22006/03/29 00:37
            ┗ 10044. Re: 16F84AでモータPWM制御方法 [記事一覧でツリーを上に上げない2006/03/29 01:22
                ┗ 10045. Re: 16F84AでモータPWM制御方法 [kazu22006/03/29 01:46
                    ┗ 10046. Re: 16F84AでモータPWM制御方法 [R2006/03/29 02:03
                    ┗ 10047. 投稿者削除 [ ] 2006/03/29 09:19
            ┗ 10048. Re: 16F84AでモータPWM制御方法 [松本2006/03/29 09:30


9977. 16F84AでモータPWM制御方法 [kazu22006/03/21 12:40
16F84Aで2個のモータを独立にPWM制御する方法を考えてます。
しかし、duty99%(2.39V)とduty98%(1.89V)の間に大きな実効
電圧ステップが発生してしまいます。実効電圧2.3V、2.2V、2.0Vあ
たりの制御を実現したいのですが、解決方法をアドバイス頂けると
助かります。

duty V(実効電圧)
100 2.34
99 2.39
98 1.89
97 1.84
90 1.68
80 1.56
70 1.46
60 1.36

/**
* PWMテスト
*
* PIC 16F84A
* 発信器 10MHz
* 言語 MikroC v2.1
* Device Flags: _CP_OFF _PWRTE_ON _WDT_OFF _HS_OSC
*
* モータ mabuchi FA-130RA(1.5V-3.0V)
* モータドライバIC 東芝TA7291P
* http://www.semicon.toshiba.co.jp/td/ja/Linear_ICs/Motor_Driver_ICs/20060307_TA7291SG_datasheet.pdf
* PortB 0,1:モータ右
* PortB 6,7:モータ左
* 電源:電池4本(実測5.4V)
*/

/**
* my_PWM_RB0()  機能:RB0の出力を0%-100%で制御する
*
* duty:範囲 0-100
* 500ループで約1秒
*/
void my_PWM_RB0(unsigned short int duty) {
  unsigned short int period = 100; //PWM分解能
  unsigned short int t_count;

  PORTB.F0 = 1; //ON
    for(t_count = 0; t_count < period; t_count++){
    if(t_count > duty) {
      PORTB.F0 = 0; //OFF
    }
    delay_us(10);
  }
}

void my_PWM_RB6(unsigned short int duty) {
  unsigned short int period = 100; //PWM分解能
  unsigned short int t_count;

  PORTB.F6 = 1; //ON
    for(t_count = 0; t_count < period; t_count++){
    if(t_count > duty) {
      PORTB.F6 = 0; //OFF
    }
    delay_us(10);
  }
}

void main() {
  unsigned int i;
  unsigned int pause = 1000; //待機時間1秒

  //ポートの初期化
  PORTB = 0b00000000;
  //入出力の設定 1:input 0:output
  TRISB = 0b00000000; //PORTB 8ヶ全て出力に設定

  do {
    for(i = 0; i < 1000; i++) { //約2秒継続
      my_PWM_RB0(90); //90%右前進
      my_PWM_RB6(90); //90%左前進
    }

    PORTB = 0b00000000; //停止
    Vdelay_ms(pause); //待機
  } while(1);
}

9978. Re: 16F84AでモータPWM制御方法 [松本2006/03/21 13:27
duty=99の時PORTBがoffにならないからでないかい?

10043. Re: 16F84AでモータPWM制御方法 [kazu22006/03/29 00:37
 
> duty=99の時PORTBがoffにならないからでないかい?
アドバイスありがとうございます。

アドバイスを元に色々検討してみました。しかし、目的の2.0V近辺の
細かい制御を実現する事が出来ませんでした。

if(t_count > duty) { → if(t_count > duty -1) {
に変更する事で、duty=99とduty=98の間に大きな電圧差はなくなり
ました。
しかし、大きな電圧さはduty=100とduty=99の間に移動しただけで
2.0V近辺の細かい制御を実現する事が出来ませんでした。


PORTBをoffにしている時間10μ秒が長過ぎるのが影響しているのでは
と考え、off時間を1μ秒にして見ましたが問題は解決しませんでした。

duty V(実効電圧)
100 2.29
99 1.73
98 1.70
97 1.68
90 1.58


次に delay_us(10); の行を削除してみましたが、これも目的を実現
する結果とはなりませんでした。

  PORTB.F0 = 1; //ON
  for(t_count = 0; t_count < period; t_count++){
    if(t_count > duty - 1) {
      PORTB.F0 = 0; //OFF
    }
  }

duty V(実効電圧)
100 2.12
99 1.63
98 1.60
97 1.52
90 1.39

実効電圧2.3V、2.2V、2.0Vあたりの制御を実現する方法をアドバイス
頂けると助かります。よろしくお願いします。

10044. Re: 16F84AでモータPWM制御方法 [記事一覧でツリーを上に上げない2006/03/29 01:22
>実効電圧2.3V、2.2V、2.0Vあたりの制御を実現する方法をアドバイス
>頂けると助かります。よろしくお願いします。
PICで直接PWMをする以上、2.0=0%, 2.3V=100%のような範囲分けは無理でしょう。
PICの外部に回路を置けば、方法はいくらでもありそう。

10045. Re: 16F84AでモータPWM制御方法 [kazu22006/03/29 01:46
 
> > 実効電圧2.3V、2.2V、2.0Vあたりの制御を実現する方法をアドバイス
> > 頂けると助かります。よろしくお願いします。
> PICで直接PWMをする以上、2.0=0%, 2.3V=100%のような範囲分けは無理でしょう。
> PICの外部に回路を置けば、方法はいくらでもありそう。

早急なお返事ありがとうございます。
0.0V=0%, 2.3V=100%, 2.2V=95%, 2.1V=90%の制御を希望してますが、
これなら可能な方法がありますでしょうか?

10046. Re: 16F84AでモータPWM制御方法 [R2006/03/29 02:03
質問の回答とは違いますが・・・
2つのモータをmy_PWM_RB0/my_PWM_RB6と別々に制御しているので90%とかにはなりませんよ。
90%と指定したら約半分の45%となります。
0〜100%の制御をしたければ2つのPWMを同時に処理してください。

10047. 投稿者削除 [ ] 2006/03/29 09:19

10048. Re: 16F84AでモータPWM制御方法 [松本2006/03/29 09:30
既にかかれてますが、片方ずつ制御しているので、一方を制御している時他方はOFFになるので、PWMとしては0〜50%にしかなってません。
なので、両方同時に制御したほうが良いです。
たとえば以下のようにしてみたらどうです?

void my_PWM(u8 right_duty, u8 left_duty) {
  u8 period = 100; //PWM分解能
  u8 t_count;

  PORTB.F0 = 1; // right ON
  PORTB.F6 = 1; // left_on
  for(t_count = 0; t_count < period; t_count++){
   if(t_count == right_duty) PORTB.F0 = 0; // right off
   if(t_count == left_duty ) PORTB.F6 = 0; // left off
   delay_us(10);
  }
}