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