サンプルプログラム(F3Discovery)

(2014.8.6 作成)

 STM32のように高機能なマイコンの場合タイマーをひとつ消費して定期的にRun関数を呼び出す方法と、メインのループで毎回呼ぶ2通りの方法で使用することが出来ます。

STM32F3Discovery (タイマー割り込み式)

 タイマーを使用して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();
}

}

STM32F3Discovery(ループ式)

 無限ループ内で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();

}

}

動作ビデオ