2016年6月20日月曜日

DRV8835でモータ駆動

随分前にスイッチサイエンスで購入したDRV8835基板が出てきたので、モータつないで動かしてみた。

スイッチサイエンス(DRV8835)
https://www.switch-science.com/catalog/1637/

STbee F4miniのTIM8のポートにDRV8835基板を接続し、ハーフマウスで使うMK06-4.5をまわしてみた。
DRV8835のモードピンはデフォルトの0。
適当なプログラムなので、停止状態から動き始めるところで少し可聴音がしたり動きがスムーズでなかったりしたが、普通に動いた。
PWMのDuty50%でも、それなりのスピードが出たので、性能的には問題なさそう。
このDRV8835はピン配置が素直なので、基板レイアウトが楽に出来そうなのがうれしい。
(前に使ったMPC17C724はピン配置が使いにくかった。)




MK06-4.5サイズの小さいモータを使ったのは初めてなので、こんなものかもしれないが、トルクが小さい気がする。
ギアで変速して回したタイヤを指で軽く押さえたら、回転が止まってしまうくらい。
まぁ、ハーフマウスは重さが20gくらいだろうから、大きなトルクはいらないのだけれど。


・プリンタ復活

黒が出なくなったプリンタのプリンタヘッドを取り外して、常温の水を使って洗浄したけど直らなかったのでほぼあきらめていたのだけれど、駄目元で40℃くらいのぬるま湯で洗浄してみた。
すると、まったく出なかった黒がかすれ気味ながらも9割くらい出るようになった。
そこで、プリンタで強力クリーニングを実行してからノズルパターン印刷をしたところ、完全に復活しました!
ぬるま湯を使うことで、プリンタヘッドの中で固まっていたインクが溶けたのだと思う。
壊れたと思ったものを修理できたので、超気持ちいい!





#include 
#include "stm32f4xx.h"


// -------------------------------------------------------
// プロトタイプ宣言
// -------------------------------------------------------
uint8_t get_user_sw(void);
void hw_init(void);
void led_on(void);
void led_off(void);

void tim8_pwm_init(void);
void set_pulse(uint16_t pulse1,uint16_t pulse2,uint16_t pulse3,uint16_t pulse4);


// -------------------------------------------------------
// 割り込み関数
// -------------------------------------------------------
volatile uint16_t time_sec=0;
volatile uint16_t time_msec=0;

void systick_1msec(void)
{
  static uint16_t cnt=0;
  static uint8_t toggle_flag=0;
  
  time_msec++;
  if(++cnt>1000){
    time_msec=0;  cnt=0;  time_sec++;
 toggle_flag = (toggle_flag==0) ? 1 : 0;
 (toggle_flag==0) ? led_on() : led_off();
  }
}

void delay_ms(uint16_t msec){
  uint16_t cnt=0;
  
  cnt = time_msec;
  while(msec){
    if(cnt!=time_msec){
   cnt = time_msec; msec--;
 }
  }
}

// -------------------------------------------------------
// main
// -------------------------------------------------------
int main(void)
{
  uint16_t i=0;

  SystemInit();
  hw_init();
  tim8_pwm_init();

  // systick 設定(1msec,100Hz)
  SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);
  if(SysTick_Config(SystemCoreClock/1000)){
    while(1);                // error
  }
  
  printf("\n");
  printf("tim8 pwm output sample. \n");

  while(1){
#if 1
    // SW処理
    if(get_user_sw() ){       //ボタンを押したら以下を実行
      led_on();     // 点灯
   while(get_user_sw() );  // ボタンを放したら以下を実行
    }else{
      led_off();  // 消灯
    }  // end of if
#endif

    for(i=0;i<50 delay_ms="" for="" i="" set_pulse="">0;i--){
   set_pulse(i*10,1000,0,0);
   delay_ms(100);
 }

  }  // end of while
  
  return 0;
}



uint8_t get_user_sw(void){
  return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0);
}

void led_on(void){
  GPIO_SetBits(GPIOD,GPIO_Pin_2);
}

void led_off(void){
  GPIO_ResetBits(GPIOD,GPIO_Pin_2);
}

// ---------------------------------------------------
//  初期化
// ---------------------------------------------------
void hw_init(void){
  /* structure to initialize GPIO */
  GPIO_InitTypeDef GPIO_InitStructure;

  // --------------------------------------------------
  // LED設定 ここから
  /* supply the clock to AHB1(GPIOD) */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD,ENABLE);
  //GPIO pin configuration
  GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_2;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;
  GPIO_Init(GPIOD,&GPIO_InitStructure);
  // LED設定 ここまで
  // --------------------------------------------------

  // --------------------------------------------------
  // ユーザスイッチ設定 ここから
  //   SW on = 1 , off = 0
  /* supply the clock to AHB1(GPIOA) */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
  //GPIO pin configuration
  GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;
  GPIO_Init(GPIOA,&GPIO_InitStructure);
  // ユーザスイッチ設定 ここまで
  // --------------------------------------------------

  led_off();

}




// センサLEDの焼ききれ防止。パルス幅の上限90%
#define TIM8_SAFTY  1000
void set_pulse(uint16_t pulse1,uint16_t pulse2,uint16_t pulse3,uint16_t pulse4){
  TIM8->CCR1 = (pulse1>TIM8_SAFTY) ? TIM8_SAFTY : pulse1;
  TIM8->CCR2 = (pulse2>TIM8_SAFTY) ? TIM8_SAFTY : pulse2;
  TIM8->CCR3 = (pulse3>TIM8_SAFTY) ? TIM8_SAFTY : pulse3;
  TIM8->CCR4 = (pulse4>TIM8_SAFTY) ? TIM8_SAFTY : pulse4;
//  TIM5->CCR1 = pulse1;
//  TIM5->CCR2 = pulse2;
//  TIM5->CCR3 = pulse3;
//  TIM5->CCR4 = pulse4;
}

#define PWM_PERIOD   1000
void tim8_pwm_init(void){

  // --------------------------------------------------
  // Port C 設定(PC6,7,8,9 PWM 出力) ここから
  
  // GPIOC クロックの有効化
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC,ENABLE);

  // PC6,7,8,9 : 
  GPIO_InitTypeDef GPIO_InitStructure;
  GPIO_StructInit(&GPIO_InitStructure);
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9;
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_High_Speed;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;       // この行がないとPWM出力されない
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOC,&GPIO_InitStructure);
  
  //GPIOCのPIN6,PIN7,PIN8,PIN9をオルタネィテブファンクションのTIM8に割り当て
  GPIO_PinAFConfig(GPIOC , GPIO_PinSource6  , GPIO_AF_TIM8);
  GPIO_PinAFConfig(GPIOC , GPIO_PinSource7  , GPIO_AF_TIM8);
  GPIO_PinAFConfig(GPIOC , GPIO_PinSource8  , GPIO_AF_TIM8);
  GPIO_PinAFConfig(GPIOC , GPIO_PinSource9  , GPIO_AF_TIM8);
  //GPIOCのPIN6,PIN7,PIN8,PIN9をオルタネィテブファンクションのTIM8に割り当て
  // --------------------------------------------------
  

  // --------------------------------------------------
  // TimeBase 設定 ここから
  // TIM8 クロックの有効化
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8, ENABLE);

  //   TIM1 clock = SystemCoreClock / 2 = 168 MHz /2 = 84 MHz
  TIM_TimeBaseInitTypeDef    TIM_TimeBaseStructure;
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
//  TIM_TimeBaseStructure.TIM_Prescaler     = 42;                  // 42 MHz / 42 = 1,000 kHz
  TIM_TimeBaseStructure.TIM_Prescaler     = SystemCoreClock / 1000000; // 1,000 kHz
  TIM_TimeBaseStructure.TIM_Period        = PWM_PERIOD;          // 周期設定
  TIM_TimeBaseStructure.TIM_CounterMode   = TIM_CounterMode_Up;  // カウントアップモード
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;        // インプットキャプチャ用設定(未使用)
  TIM_TimeBaseInit(TIM8,&TIM_TimeBaseStructure);
  // TimeBase 設定 ここまで
  // --------------------------------------------------
  
  
  // --------------------------------------------------
  // アウトプット・キャプチャ設定 ここから
  //PWM1 Modeの設定・チャネル1,2
  TIM_OCInitTypeDef TIM_OCInitStructure;
  TIM_OCStructInit(&TIM_OCInitStructure);
  TIM_OCInitStructure.TIM_OCMode      = TIM_OCMode_PWM1;         // PWM1 モード
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  // タイマ出力を有効
  TIM_OCInitStructure.TIM_Pulse       = 0;                       // Duty 設定
  TIM_OCInitStructure.TIM_OCPolarity  = TIM_OCPolarity_High;     // アクティブ時 出力High
  // ch1
  TIM_OC1Init(TIM8, &TIM_OCInitStructure);
  TIM_OC1PreloadConfig(TIM8, TIM_OCPreload_Enable);             // プリロード
  // ch2
  TIM_OC2Init(TIM8, &TIM_OCInitStructure);
  TIM_OC2PreloadConfig(TIM8, TIM_OCPreload_Enable);             // プリロード
  // ch3
  TIM_OC3Init(TIM8, &TIM_OCInitStructure);
  TIM_OC3PreloadConfig(TIM8, TIM_OCPreload_Enable);             // プリロード
  // ch4
  TIM_OC4Init(TIM8, &TIM_OCInitStructure);
  TIM_OC4PreloadConfig(TIM8, TIM_OCPreload_Enable);             // プリロード
  // アウトプット・キャプチャ設定 ここまで
  // --------------------------------------------------

  TIM_CtrlPWMOutputs(TIM8,ENABLE);    // 高機能タイマ専用
  set_pulse(0,0,0,0);
  TIM_Cmd(TIM8,ENABLE);               // TIM8 有効
}

0 件のコメント:

コメントを投稿