(2014.8.6 作成)
STM32のように高機能なマイコンの場合タイマーをひとつ消費して定期的にRun関数を呼び出す方法と、メインのループで毎回呼ぶ2通りの方法で使用することが出来ます。
タイマーを使用してRun関数をひたすら呼び続けます。メイン関数で思い処理をしてもタイマー割り込みで定期的にRun関数が呼ばれるので、この方式がよいと思います。1[us]単位で割り込みを行うと他の処理が追いつかないので、10~15[us]間隔ぐらいで割り込みを行うのがよいと思います。
/* Copyright (c) 2014 DenshiKousakuSenka This software is released under the MIT License. http://opensource.org/licenses/mit-license.php */ #include "math.h" #include "DKS_Timer_Discovery_F3.h" #include "DKS_GPIO_Discovery_F3.h" #include "DKS_EasyDriver.h" #include "DKS_Wait_Discovery_F3.h" #include "stm32f30x_misc.h" extern "C" { DKS::Timer *tim; DKS::Stepper::StepperControl *sc; void TimerConfig(const uint16_t &t); int main(void) { tim=new DKS::Timer(1e-6); //引数なしだと1msでカウントアップ tim->start(); DKS::DigitalOut pinDir(GPIOD, GPIO_Pin_8); DKS::DigitalOut pinStep(GPIOD, GPIO_Pin_10); DKS::DigitalOut pinMS1(GPIOD, GPIO_Pin_12); DKS::DigitalOut pinMS2(GPIOD, GPIO_Pin_14); DKS::Stepper::EasyDriver motor(tim, &pinDir, &pinStep, 1.8f*M_PI/180.0f, &pinMS1, &pinMS2); DKS::Stepper::IStepperMotor **motors = new DKS::Stepper::IStepperMotor*[1]; motors[0] = &motor; sc = new DKS::Stepper::StepperControl(motors, 1); TimerConfig(15); //15us単位で割り込み DKS::Wait w(TIM6); w.wait_ms(3000); //3秒待ち sc->SetSpeed(0, 10.0f, 10.0f); //10[rad/s]で回転 w.wait_ms(3000); //3秒待ち sc->SetSpeed(0, 20.0f, 10.0f); //20[rad/s]で回転 w.wait_ms(3000); //3秒待ち sc->SetSpeed(0, 0.0f, 10.0f); //停止 w.wait_ms(3000); //3秒待ち sc->SetRelativeAngle(0, -6.0f*M_PI, 20.0f, 50.0f); //逆方向に2周回す while(1); //停止して無限ループ } void TimerConfig(const uint16_t &t) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; NVIC_Init(&NVIC_InitStructure); TIM_DeInit(TIM2); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_ClockDivision = 0; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Prescaler = 72 -1; //1us TIM_TimeBaseStructure.TIM_Period = t - 1; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); TIM_Cmd(TIM2, ENABLE); } void TIM2_IRQHandler() { TIM_ClearITPendingBit(TIM2, TIM_IT_Update); if (sc) sc->Run(); } }
無限ループ内でRun関数を呼び出し続けます。ループ内でビジーウエイトや思い処理を実行するとモーターの動作が期待しないもになると思います。できればタイマー使用をお奨めします。
/* Copyright (c) 2014 DenshiKousakuSenka This software is released under the MIT License. http://opensource.org/licenses/mit-license.php */ #include "math.h" #include "DKS_Timer_Discovery_F3.h" #include "DKS_GPIO_Discovery_F3.h" #include "DKS_EasyDriver.h" extern "C" { DKS::Timer *tim; DKS::Stepper::StepperControl *sc; //台形駆動 // 最大20[rad/s]で3周往復を繰り返す void TestRelativeAngle(void) { float angle = M_PI*2*3; const float maxVelocity = 20.0f; const float acceleration = 30.0f; sc->SetRelativeAngle(0, angle, maxVelocity, acceleration, acceleration, false); while(1) { sc->Run(); if (sc->IsError()) { while (1); } if (!sc->IsMoving(0)) { angle *= -1.0f; sc->SetRelativeAngle(0, angle, maxVelocity, acceleration, acceleration, false); } } } //加速、減速 // 5秒単位で 停止 → 5[rad/s] → 15[rad/s] → 停止を行う void TestSpeed(void) { const float acceleration=10.0f; const float speedList[] = {0,5,15,0}; uint8_t stage=0; const uint8_t n=sizeof(speedList)/sizeof(float); sc->SetSpeed(0, speedList[0], acceleration); while(1) { if ( stage != (uint8_t)(tim->readCounter()/5000000)) { stage++; if (stage>=n) break; sc->SetSpeed(0, speedList[stage], acceleration); } sc->Run(); } } int main(void) { tim=new DKS::Timer(1e-6); tim->start(); DKS::DigitalOut pinDir(GPIOD, GPIO_Pin_8); DKS::DigitalOut pinStep(GPIOD, GPIO_Pin_10); DKS::DigitalOut pinMS1(GPIOD, GPIO_Pin_12); DKS::DigitalOut pinMS2(GPIOD, GPIO_Pin_14); DKS::Stepper::EasyDriver motor(tim, &pinDir, &pinStep, 1.8f*M_PI/180.0f, &pinMS1, &pinMS2); DKS::Stepper::IStepperMotor **motors = new DKS::Stepper::IStepperMotor*[1]; motors[0] = &motor; sc = new DKS::Stepper::StepperControl(motors, 1); TestSpeed(); // TestRelativeAngle(); } }