chakokuのブログ(rev4)

テック・コミック・DTM・・・ごくまれにチャリ

ST Micro社のサンプルコードを参考にSTEVAL-DRONE01のPWM制御部を改良ー>少なくとも浮上はした

HALを使わず周辺I/Oの制御もフルスクラッチで作ってきたSTEVAL-DRONE01だったが最終的に浮上すらしないという状況に陥った。ST Micro社が提供しているDroneサンプルコードを使って動かすとかなり危険に浮上して飛んだ。だから、、基板のGNDが不安定とかではなく制御の問題であると分かった。
サンプルコードを読み解いたが、特別な設定は行っておらず、GPIOもPWMもごく素直な実装であった。ただ違っていたのは、PWMのパラメータであり、サンプルコードでは、PWMの動作周波数は1MHzでカウンタは2000が設定されていた。だから、PWMの周期は500Hzで動作する仕様であった。この実装がモータ出力に関係するかもしれないと思い、俺ライブラリも、同じ設定を入れた(これはではもっと低い周波数で動かしていた)。結果、DRONEは浮上した。深夜あまりにうるさいので、出力は最大まで上げていないけど、浮上する程度にはモータが回せている。なぜ、PWM周波数を上げるとモータのパワーが上がるのかが全く分かっていないけど、、ハードウエアとしては飛ぶことが分かったので、ソフト実装にまた取り組める。
かなり汚い絵ですが、浮上テストしている動画は以下。
youtu.be
PWMのduty:30%ぐらいでほぼ飛びそうなぐらいのパワーです。これ以上出力を上げると深夜でうるさいし、制御不能によりひっくり返りそうなので、これぐらいにしておきます。

どれだけ参考になるか分からんが、、16MHzのクロックに対してプリスケーラで1/16によりPWMの動作周波数を1MHzに落として、カウンタを2000で動かす実装例(Rustで書いています)

  //--------------------------------
  // set Timer4 (TIM4) CH2
  //--------------------------------

  // enable Counter (CE) AND ARPE
  addr = (TIM4_BASE + TIM_CR1_OFFSET) as *mut u32;  // 0
  set_mode = 0x1 << TIM_CEN_BIT;               // UE_BIT = 0
  set_mode |= 0x1 << TIM_ARPE_BIT;            // UE_BIT = 7
  unsafe { 
	let current = core::ptr::read_volatile(addr) ;
        let val = current | set_mode;
	core::ptr::write_volatile(addr, val) ;
  }

  // Set  Prescalar ()
  addr = (TIM4_BASE + TIM_PSC_OFFSET) as *mut u32;  // 0x28
  let div = 16 - 1;  // divied to 16MHz -> 1MHz by prescalar
  unsafe { 
	let current = core::ptr::read_volatile(addr) ;
        let val =  div;  
	core::ptr::write_volatile(addr, val) ;
  }

  // Set ARR ()
  addr = (TIM4_BASE + TIM_ARR_OFFSET) as *mut u32;  // 0x2c
  let auto_reload = ARR_MAX;               //  set value of AUTO-RELOAD to 2000
  unsafe { 
	let current = core::ptr::read_volatile(addr) ;
        let val:u32 = auto_reload;
	core::ptr::write_volatile(addr, val) ;
  }

  // Set  CCR
  addr = (TIM4_BASE + TIM_CCR1_OFFSET) as *mut u32;  //  0x34
  let cc_val = 0;        // duty 0%
  unsafe { 
	let current = core::ptr::read_volatile(addr) ;
        let val = cc_val;
	core::ptr::write_volatile(addr, val) ;
  }

  // set PWM MODE1 
  addr = (TIM4_BASE + TIM_CCMR1_OFFSET) as *mut u32;  // 0
  set_mode = 0b110 << TIM_OC1M_BIT_FLD;              // OCM1_BIT_FIELD = 4
  set_mode |= 1 << TIM_OC1PE_BIT;                    // TIM_OC1PE = 3
  mask = !(0b111 << TIM_OC1M_BIT_FLD | 1 << TIM_OC1PE_BIT);
  unsafe { 
	let current = core::ptr::read_volatile(addr) ;
        let mut val = current & mask;
        val |= set_mode;
	core::ptr::write_volatile(addr, val) ;
  }

  // enable PWM
  addr = (TIM4_BASE + TIM_CCER_OFFSET) as *mut u32;  // 0x20
  set_mode = 1 << TIM_CC1E_BIT;                    // TIM_CC1E_BIT = 0
  //set_mode = 3;
  unsafe { 
	let current = core::ptr::read_volatile(addr) ;
        let val = current | set_mode;
	core::ptr::write_volatile(addr, val) ;
  }

なぜPWMの周波数を上げるとモータの出力が上がるのか??まったく理解できないので、オシロで波形確認したり、参考文献を読んで調べる予定です。パワーが落ちない理由がまったく分からず、晴れやかな気持ちには到底なれないけど、、飛ぶことは分かったので制御プログラムの開発を続けられる。(IoT勉強会の準備も必要だが。。)