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勉強会の準備も必要だが。。)