ステッピングモータの駆動方法

作成者:Colton Parks、最終修正者:BenH[2016年9月1日]

はじめに

この記事は、初心者の方にステッピングモータの仕組みとステッピングモータの駆動方法を理解していただくためのものです。ステッピングモータの制御には幅広いテーマがありますが、この記事はその入門編です。ステッピングモータには、バイポーラ型とユニポーラ型の2種類があります。

バイポーラモータ

image

バイポーラ型ステッピングモータは、4本の電線と2つのコイルで構成されています。回転させるためには、コイルに電流を流す必要があります。それぞれの線は、ハイとローに駆動できなければなりません。ここでは、ステッピングモータを回転させるための電流駆動の方法を説明します。

この仕組みを理解するために、4つのステップしかない単純なステッピングモータを考えてみましょう。最初のステップでは、磁石を最初のコイルに合わせます。次のステップでは、磁石を90度回転させます。最初のコイルに電流を逆流させると、磁極が反転します。向かい合っているコイルが接続されていますが、中央の磁石に対して反対の磁界を発生させます。

もちろん、ほとんどのステッピングモータは4ステップ以上あります。一般的なステッピングモータは、1回転あたり200ステップです。フルステップの動作が確認できれば、ハーフステップの動作は非常にシンプルです。両方のコイルに同時に電流を送れば、分解能が2倍になります。

ステッピングモータドライバは、コイルに流れる電流を変調するマイクロステップを使用することも可能です。一般的なモータコントローラは、フルステップにつき16マイクロステップを実装することができます。電流を調整するチップ(ドライバIC)もありますが、古いチップでは、駆動するステッピングモータに合わせて「調整」する必要があります。さらに、フルステップを256のマイクロステップに分割することで、一般的な200ステップのモータを51,200ステップのモータにすることが可能です!また、マイクロステップによりモータのノイズを低減し、よりスムーズで効率的な運転を可能にします。
image
フルステップ1と2の間のハーフステップ

コイルに流れる電流を制御する方法

巻線に流れる電流を制御する最も一般的な方法は、Hブリッジと呼ばれるものを使用することです。これは4つのトランジスタからなっており、各ワイヤをハイまたはローに引き込むことができます。トランジスタの代わりにMOSFETを使うこともできますが、配線が少し違ってきます。この図は、Hブリッジを通してどちらかの方向に電流を送ることができる方法を示しています。経路上のトランジスタをオンにすればよいのです。

同じ側の2つのトランジスタが同時にオンにならないようにする必要があります。そうなると、電源からアースへの低抵抗パスが形成され、回路をショートさせることになります。また、トランジスタのオンからオフへの移行に時間がかかることがありますので、注意が必要です。コイルに流れる電流を急激に切り替えることは、Hブリッジの詳細がよく分かっていない限りお勧めできません。

image
これでもまだ全体像ではありません。モータが回転すれば、電圧が発生します。トランジスタを保護するために、フライバックダイオードを接続するのが良いでしょう。

これにより、モータが高電圧を発生し、トランジスタやドライバを破壊するのを防ぐことができます。ステッピングモータを駆動する電圧が、MCUが出力する電圧よりも高い場合は、PNPトランジスタを制御するために、もう1つのトランジスタを追加する必要があります。

追加のNPNトランジスタをオンにすると、PNPトランジスタのベース(1番ピン)から電流が流れ出し、オンとなるのです。あとは、すべてのNPNトランジスタのベースに電流制限抵抗が必要です。

これがすべてです!このHブリッジは、片方の巻線に流れる電流を制御することになります。巻線が2つあるので、この回路を2倍にする必要があります。

これで、必要な部品の数がわかるようになりました。デュアルHブリッジを使うだけがステッピングモータの駆動方法ではありません。このデュアルHブリッジを内蔵したステッピングモータドライバを購入することもできます(ドライバには通常MOSFETなどが使用されています)。BOM数を減らしたい(そして時にはより多くの機能を得たい)のであれば、ステッピングモータドライバを検討することをお勧めします。そのチップが何を提供するかは、データシートで確認する必要があります。トランジスタとダイオードを提供するだけのチップもあれば、コイルに流れる電流を完全にコントロールするチップもあります。

マイクロステップ

マイクロステップでは、トランジスタにパルス幅変調信号を送ります。これでモータコイルに流れる電流を簡単にコントロールすることができます。あらかじめ選んでいたPWM値を正弦波ルックアップテーブルに入れます。一般的には、20~40kHzのPWM周波数が選ばれることが多いようです。20kHz以下は人間の耳で聞くことができます。一方、効率を上げ、トランジスタの電力損失を減らすために、周波数は40kHz以下に抑えられています。PWM信号がハイのとき、電流はトランジスタを通過します。PWM信号がローのとき、電流はダイオードを通過します。これはマイクロステップの非常に粗い実装ですが、どのように動作するかの一般的な考えを示しています。MOSFETを使用したモータドライバは、モータ電流の減少、すなわち減衰する速度を制御することができます。ドライバの電流波形は次のようになります。
image

高速減衰期間と低速減衰期間は、駆動するモータに合わせて手動で最適化する必要があります。新しいチップの中には、検知した電流に基づいて減衰期間を自動的に調整するものもありますが、古いチップでは最適化(チューニング)が必要な場合もあります。

トランジスタの基礎知識

トランジスタは、電流を制御する電流制御素子で、ベース、コレクタ、エミッタの3つのピンがあります。(c、b、およびeで表記)

NPNトランジスタ

NPNトランジスタはほとんどMOSFETに取って代わられましたが、トランジスタの方が望ましいと思われるアプリケーションもまだあります。トランジスタは静電気放電(ESD)の影響を受けにくく、使用する電圧も低くて済みます。最大の欠点は、MOSFETほど電流を流せず、効率が悪いことです。IP120に5mAを供給すると、60Vの負荷を5Aまで制御できます(具体的な動作特性はデータシートをお読みください)。

これは典型的な小信号用NPNトランジスタです。ベースからエミッタに小さな電流が流れると、コレクタからエミッタに大きな電流が流れるようになっています。電流ベースのデバイスとして覚えておくことが大切です。

image

ダーリントントランジスタは、2つのトランジスタを1パッケージ化したものです。順方向電圧が2倍になりますが利得は同様に2倍になります。

どんなトランジスタも、ダイオードと従属電流源として考えることができます。

従属電流源に流れる電流は、β(ベータ)にダイオードを流れる電流(ib)を掛けたものです。βはトランジスタの電流増幅率と呼ばれるものです。これは同じ品番であっても、トランジスタによってかなり大きなばらつきがありますので、この値を当てにしないようにしましょう !このモデルは、トランジスタが飽和していない場合にのみ有効です。十分な電流がベースを通過しさらにこれを増やしても、コレクタ・エミッタ間の電流がこれ以上に増えなくなるような場合、飽和と呼びます。(トランジスタをスイッチとして使用する場合、発熱や電力損失を防ぐため、トランジスタは飽和状態かオフのどちらかにしておく必要があります。)

ダイオードは、アノードとカソードで公称0.7Vの電圧降下があります。つまり、ベースからエミッタへの電圧降下は0.7Vです(ダーリントンでは1.4Vとなります)。

image

ダイオードがトランジスタの一部であることから、グランドを制御するようにNPNトランジスタを、電源を制御するようにPNPトランジスタを配置する必要があります。ほぼ等価な2つの回路を考えてみましょう。

最初の回路では、3.3V電源からトランジスタが完全に飽和するほどの電流がベースに流れたとします(トランジスタは負荷電流を制限していません)。image コレクタとエミッタの間に少し電圧降下はありますが、かなり小さいです。負荷に11.8Vの電圧がかかっています。電流制限抵抗にかかる電圧は2.6Vです。これは、抵抗器の大きさを計算するときに重要です。

2番目の回路では、同じ抵抗を使って理論的に同じ電流を制限しています。しかし、トランジスタはベースとエミッタの間でダイオードのような働きをしますので、エミッタはベースより0.7V低くなければなりません。2.6Vはエミッタの取り得る最大値です(2つの抵抗による分圧のため、おそらくもっと低い値になるでしょう)。この時点では、トランジスタは電流を制限しているのではなく、電圧を制限しているのです。それにもかかわらず、トランジスタは余分な電力を熱として放散しています。負荷にかかる電圧はわずか2.6Vです。

PNPトランジスタ

典型的なPNPトランジスタは回路図ではこのようになっています。エミッタからコレクタへ電流を流すために、エミッタからベースへ電流を流す必要がある以外は、NPNトランジスタと同様です。エミッタベース間のダイオードに小さな電流が流れると、エミッタとコレクタにはるかに大きな電流が流れます。

image

トランジスタは、ダイオードと従属電流源と考えることができます。従属電流源からの電流は、 image 。NPNと同じように、ベースからエミッタの間にダイオードが存在します。ダイオードを介して0.7Vの電圧降下があることに変わりはありません。それはちょうど反対側を向いています。

image

回路での使い方は次の通りです。トランジスタをオンにするには,1番ピンを3番ピンより0.7V低くします。 トランジスタをオフにするには,1番ピンをVCCと同じ電圧にする必要があります。これは、オペアンプでPNPトランジスタを制御する場合の注意点です。レールツーレールのオペアンプでないと、PNPトランジスタを完全にシャットダウンすることができないのです。また、より高い電圧を駆動することが難しくなります。12Vの電源を3.3Vで制御しようとしたら、絶対にトランジスタをオフにできません。3.3Vは常に12Vより低いのです。そのため、私は通常、小信号のNPNと組み合わせます。NPNがオフだと、ダイオードに電流が流れず、PNPはオフになります。

image

ディスクリート部品の選び方

ダイオード:ダイオードは用途に応じた定格電流のものを選んでください。オンからオフに切り替えるとき、モータの電流がダイオードを通過する必要があります。過度の発熱を避けるため、順方向電圧の低いダイオードを探すようにしてください。 マイクロステップを実装する予定がある場合は、特にそうです。

トランジスタ:Hブリッジのトランジスタも用途に合った定格電流であることが必要です.コレクタ-エミッタ間飽和電圧の低いものを選ぶと、過度の発熱を避けることができます。また、トランジション周波数が高いほど、トランジスタが活性状態にある時間が短くなるため、有益です。最大電力値は、そのトランジスタがどれだけ電力を消費できるかを示すものです。消費電力が小さいほど、そのトランジスタはスイッチとして有用であることを意味します。

小信号トランジスタ:これはあまり華々しい存在ではありません。検討すべき最大の属性は、コレクタ-エミッタ間耐圧がモータ電源電圧より高いことです。また、トランジション周波数が高いことも重要です。トランジション時間は2つのトランジスタの積み重ねになり全体としてトランジション周波数がかなり低くなります。

抵抗器:抵抗器は選びやすいです。抵抗器には、トランジスタを通過する電流の一部しか流れません。また、NPN用の2つの抵抗器に加わる電圧も最小のレベルです。PNPのベースに接続されている抵抗器だけが注意点です。トランジスタに流れる電流量がわかれば、その電圧は基本的にモータの電源電圧になります。1/4ワット以上の定格電力があれば、ほとんどの用途で十分です。

シナリオの例

ここでは、抵抗器に必要な値の計算方法を、以下の条件設定をシナリオとして説明します。

モータ:

12V、 0.33A

電源:

マイクロコントローラ:

EFM32GG-STK3700。本ボードのロジックレベルは3.3V。各端子は最大20mAまで供給可能。

トランジスタ:

たまたま、TIP120とTIP125のトランジスタを持っているのでHブリッジの駆動に使います。このトランジスタは5Aを駆動することができます。

うわ!両トランジスタともコレクタ-エミッタ間が4Vで飽和しているようだ!これだと、モータを動かすのに4Vしか供給できない。もう少し詳しく調べてみよう。

image

データシートを見て一瞬びくっとしました!私のアプリケーションでは、典型的な飽和電圧は1V以下のようです。大電流になると、飽和電圧は1.2V程度まで上昇します。小信号のNPNは、通常0.2Vの飽和電圧になります。ダーリントントランジスタは、なぜそんなに高いのでしょう?
image

D点について考えてみましょう。もし、1番目のトランジスタが飽和していれば、D点はC点より0.2V低い電圧になります。2番目のトランジスタはダイオードを内蔵していることを忘れないでください。EはDより0.7V小さくないと電流が流れません。全体として、EはCより0.9V低くなります。ダーリントントランジスタが高い飽和電圧を持っているのはこのためです。回路の中の電流の流れを考えるとき、複雑になりすぎないように、単純な真理に頼るのが一番です。

あとは、抵抗とダイオードです。ダイオードは1N4148が手元にありました。このダイオードは、私の用途では定格電流が足りません。しかし、モータをマイクロステップさせるつもりはありませんでした。

電流能力をよく見ると、データシートには順方向電流300mAを扱えると書いてあります。また、1秒間に1Aのサージを扱うことができます。モータに流れる電流は1秒間に1Aを超えないはずです。

image

Hブリッジの抵抗値を計算する

さて、部品の選定がほぼ終わったので、次は抵抗器に注目です。まず始めに、トランジスタに流れる電流を考える必要があります。

負荷電流は0.33Aです。したがってimageです。

PNP抵抗の消費電力は、ibを0.001Aとすると、VI = 12 * 0.001 = 12mWです。どんな大きさの抵抗でも動作します。Digi-keyが提供する面実装抵抗器の最小の電力定格は12.5mWです。

私の使っているトランジスタの動作領域付近の利得は、25°Cで1000近くになります。

したがって、トランジスタのベースには330uAを供給しなければなりません。念のため、1mAを供給します(3倍です。330mAをドライブしているので、あと1mAくらい問題ありません。普通は2倍の電流が無難です)。

必要な電流がわかったので、次は電圧を見てみましょう。

PNPにはダイオードが内蔵されていますので、B点の電圧はVDD(12V)より1.4V低くなり、Vb = 10.6Vとなります。

一番左のNPNが飽和している場合、コレクタ・エミッタ間電圧は0.2Vになります。つまり、Va = 0.2Vとなります。

つまり、抵抗にかかる電圧は10.4Vです。抵抗を通過する電流は1mA必要です。V = I*Rを使うと

R = V/I = 10400 となります。10kの抵抗で十分です。この値は、電流を3倍にしたときに、すでにゲインの許容差を考慮したので、正確である必要はありません。
image

次のトランジスタはもう1つのダーリントントランジスタになります。コレクタ電流は330mAです。このゲインも私の動作点付近では1000程度です。330uAで済むはずですが、許容差を考慮し3倍の1mAにします。

D点の電圧は1.4Vです。C点の私のMCUは3.3Vを供給できます。したがって抵抗にかかる電圧は1.9Vです。V = I*Rを使うと、R = V/I = 1900になります。したがって、2.2kΩの抵抗か1.8kΩの抵抗が使用できます。

image

最後に計算するのは、PNPトランジスタを制御する抵抗器です。コレクタ電流は1mAです。一般的な小信号用トランジスタの利得は100になります。また、低電流ではもっと低くなることもあります。トランジスタのデータシートを再確認してください。このトランジスタに必要な電流は、わずか10uAです。念のため、100uAで計算してみます。Fの電圧は0.7Vです。Eの電圧は再び3.3Vです。したがって抵抗にかかる電圧は2.6Vです。R = V/Iを用いると、R = 26kΩとなります。20kΩから50kΩまでなら何でもよいと思います。私は28kΩの抵抗を使いました。

image

このようにHブリッジを設計します。制御するには、電線に電力を供給する必要があります。

警告:すべてが接続されるまで、モータ供給電圧をVMに接続したり、電圧供給を開始しないでください。ピンの再接続や配線の移動の際には、高圧電源がオフになっていることを確認してください。ICが簡単に壊れてしまいます。前もって注意喚起したので、警告しなかったと言わないでくださいね。

1番ピン、3番ピン、2番ピン、4番ピンの順にオンにして、モータを回転させてください。または、逆の順序(4、2、3、1)で回転させてください。電源・グランド間のショートの発生を確実に防ぐため、状態を切り替えるときはすべてのピンをオフにしてください。

Hブリッジのコード例

フルステップを使用したコード例:

/**************************************************************************//**
 * @file
 * @brief Empty Project
 * @author Energy Micro AS
 * @version 3.20.2
 * @section License
 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
 *******************************************************************************
 *
 * This file is licensed under the Silicon Labs Software License Agreement. See
 * "http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt" 
 * for details. Before using this software for any purpose, you must agree to the
 * terms of that agreement.
 *
 ******************************************************************************/
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_system.h"
#include "em_gpio.h"
volatile uint32_t msTicks;
#define TOTAL_STEPS      4
uint32_t STEPS[TOTAL_STEPS] = {0b1000, 0b0010, 0b0100, 0b0001};             //1,3,2,4
uint16_t STEP = 0;
/* ************* Systick Handler ***************** */
void SysTick_Handler(void) {
    msTicks++;
}
/* ************* Delay function ****************** */
void Delay(uint32_t dlyTicks) {
    uint32_t curTicks = msTicks;
    while((msTicks - curTicks) < dlyTicks);
}
/* ************* Output to H-bridge ************** */
void setStep(void) {
      GPIO->P[3].DOUTCLR = 0xF;                  //Shut off all pins.
      GPIO->P[3].DOUTSET = STEPS[STEP];          //Output the steps
}
/* ************* Main function ******************* */
int main(void)
{
    CHIP_Init();
    CMU->HFRCOCTRL = 0x30; // Set RC clock to 1 MHz
    CMU->HFPERCLKEN0 =(1<<13); //Enable GPIO clock

    if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ;         //Setup SysTick

/* ****************** Setup pushbuttons and H-bridge outputs ****************** */
    GPIO->P[1].MODEH = 0x110;                //Setup RB9 and RB10 as input
    GPIO->P[3].MODEL = 0x5555;               //Setup PD0-PD3 as push pull output. These go directly to the H-bridge
    GPIO->P[3].CTRL = 2;                     //High drivemode
    GPIO->P[3].DOUT = 0x0000;                //They should already be all low.
                                            //H-bridge pins 1,2,3,4 map to pins 3,2,1,0 on port D.
  /* Infinite loop */
  while (1) {
      if(!GPIO_PinInGet(gpioPortB,9)) {                         //If button 0 is pressed
          STEP = (STEP + 1) % TOTAL_STEPS;                      //Increment the step
          setStep();                                            //Output to the H-bridge
      }
      else if(!GPIO_PinInGet(gpioPortB, 10)) {                  //If button 1 is pressed.
          STEP = (STEP + TOTAL_STEPS-1) % TOTAL_STEPS;          //Decrement the step
          setStep();                                            //Output to the H-bridge
      }
      Delay(10);                                                //Short delay to let motor rotate
  }
}

ハーフステップを使用したコード例:

/**************************************************************************//**
     * @file
 * @brief Empty Project
     * @author Energy Micro AS
 * @version 3.20.2
 ******************************************************************************
 * @section License
 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
 *******************************************************************************
 *
 * This file is licensed under the Silicon Labs Software License Agreement. See
 * "http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt" 
 * for details. Before using this software for any purpose, you must agree to the
 * terms of that agreement.
 *
 ******************************************************************************/
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_system.h"
#include "em_gpio.h"
volatile uint32_t msTicks;
#define TOTAL_STEPS      8
uint32_t STEPS[TOTAL_STEPS] = {0b1000, 0b1010, 0b0010, 0b0110, 0b0100, 0b0101, 0b0001, 0b1001};   
//1, 1and3, 3, 3and2, 2, 2and4, 4, 4and1

/* ************* Systick Handler ***************** */
void SysTick_Handler(void) {
    msTicks++;
}
/* ************* Delay function ****************** */
void Delay(uint32_t dlyTicks) {
    uint32_t curTicks = msTicks;
    while((msTicks - curTicks) < dlyTicks);
}
/* ************* Output to H-bridge ************** */
void setStep(uint32_t STEP) {
      GPIO->P[3].DOUTCLR = 0xF;                                  //Shut off all pins.
      GPIO->P[3].DOUTSET = STEPS[(STEP % TOTAL_STEPS)];          //Output the steps
}
/* ************* Main function ******************* */
int main(void)
{
    CHIP_Init();
    CMU->HFRCOCTRL = 0x30; // Set RC clock to 1 MHz
    CMU->HFPERCLKEN0 =(1<<13); //Enable GPIO clock

    if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ;         //Setup millisecond tick counter

    /* ****************** Setup pushbuttons and H-bridge outputs ****************** */
    GPIO->P[1].MODEH = 0x110;                //Setup RB9 and RB10 as input
    GPIO->P[3].MODEL = 0x5555;               //Setup PD0-PD3 as push pull output. These go directly to the H-bridge
    GPIO->P[3].CTRL = 2;                     //High drivemode
    GPIO->P[3].DOUT = 0x0000;                //They should already be all low.
                                            //H-bridge pins 1,2,3,4 map to pins 3,2,1,0 on port D.
int32_t STEP = 0;

  /* Infinite loop */
  while (1) {
      if(!GPIO_PinInGet(gpioPortB,9)) {                         //If button 0 is pressed
          STEP += 1;                                            //Increment the step
          setStep(STEP);                                        //Output to the H-bridge
      }
      else if(!GPIO_PinInGet(gpioPortB, 10)) {                  //If button 1 is pressed.
          STEP -= 1;                                            //Decrement the step
          setStep(STEP);                                        //Output to the H-bridge
      }
      Delay(10);                                                //Short delay to let motor rotate
  }
}

ディスクリート部品を使用しない設計例

まず、どの程度の制御をチップに任せるかを決める必要があります。ステッピングモータドライバは、Hブリッジパッケージのようにシンプルにできます。製品ラインアップは徐々に複雑なものになっているので、アプリケーションに適切な製品を正確に選択できます。 Texas Instrumentsは、さまざまなレベルの制御を備えた幅広いドライバを提供しています。 ステッピングモータのどんなアプリケーションであっても、Texas Instrumentsのチップで対応可能です。また、Allegroもドライバの種類が豊富です。最も多くの機能を内蔵しているドライバはTrinamicのチップです。

STMicroelectronics L293D クアッドハーフブリッジ、各チャンネル600mAを駆動可能。これは、上記の回路図の代用となるものです。どのピンをハイとローに駆動するかを制御する必要があるのは変わりません。Arduinoモータシールドなどのボードは、この種のチップを使用しています。$3.90

TMC SILENTSTEPSTICK – ステップと方向で制御するステッピングモータドライバ。Trinamicは、小型で手頃なパッケージで多くの機能を提供します。本チップは、電流センシングによる256マイクロステップの補間が可能です(チューニング不要)。本製品はTMC2100の評価ボードです。最大1.2Aまで駆動可能です。$7.27

TMC5130-EVAL-KIT – SPI/単線UARTまたはステップと方向で制御するステッピングモータドライバ。このチップは、ステッピングモータドライバのロールスロイスです。評価キットは、お使いのモータに最適な設定を決めるのに便利です。高電圧のVM線にご注意ください。$143.02

チップ自体はTMC5130で6.39ドルです。

Silent Step Stick

TMC2100用のブレークアウトです。3Dプリンタで使用するためにWatterott社が設計したものです。0.11Ωのセンス抵抗が2つあり、最大RMS電流は1.74Aです。ポテンショメータで0から1.7Aまで電流をコントロールできます。

image

購入リンク - Digi-Keyウェブサイト

データシート - TMC2100に役立つ情報が記載されています

ボード情報 - 回路図とボードレイアウトを含みます

Github Trinamicチップデータ - v11を探してください。 これにはチップを理解するために必要なものがすべて含まれています。

ヘッダをはんだ付けする

ヘッダを基板にはんだ付けします。コンフィギュレーション入力の3番ピンを利用する場合は、その隙間を先にはんだ付けしてください(99%の方は気にする必要はありません)。ブレッドボードに取り付けたりソケットを使用する場合は、必ず底面を上にしてください(TOPと書かれています)。これにより、ポテンショメータに簡単にアクセスできるようになります。もし、かなりのモータ電流(0.5アンペア以上)を流す予定なら、露出したビアに熱伝導性のある両面テープで小さなヒートシンクを追加してください。基板上部のビアは、TMC2100の底面およびグランドプレーン(チップのグランドおよび冷却に使用)と熱的、電気的に接続されています。

ピンを接続する

警告:モータ供給電圧をVMに接続しないか、すべてが接続されるまで電圧供給を開始しないでください。ピンを再接続したり、ワイヤを移動したりするときは、必ず高圧電源がオフになっていることを確認してください。ICが簡単に壊れてしまいます。前もって注意喚起したので、警告しなかったと言わないでくださいね。

これはチップの機能設定です。ポテンショメータは、モータに流れる電流を制御します。Diag0、Diag1 はチップからの診断出力です。これについては、TMC2100のデータシートを参照してください。Vrefはポテンショメータの中間ピンの電圧です。AIN_REFピン(モータに流れる電流を計算するのに使用)に接続されています。Trinamicのコンフィギュレーション入力はトライステートです。ピンが接地されているか、VCCに接続されているか、接続されていない(オープン)かを検出できます。 SilentStepStickでは4つのコンフィギュレーションピンを使用できます。

コンフィギュレーション入力1および2: チップのデフォルトの接続は、未接続のままだとCFG1=オープン、CFG2=オープンとなります。後で気が変わるかもしれないので、これらのピンを恒久的に接続しないでください。

image

コンフィギュレーション入力3: このチップのデフォルトの接続はオープンです。コンフィギュレーション入力をコンフィギュレーションピンに接続するには、基板上のはんだギャップを埋める必要があります。1つのsmdジャンパが未接続のままになっています。他の3つはすでに0Ωの抵抗がはんだ付けされています。顕微鏡を使うことを強くお勧めしますが、どのギャップをはんだ付けすればよいかが分かれば、虫眼鏡でも大丈夫です。ギャップに0201抵抗器(0Ω)を付けるという選択もありますが、あまりお勧めしません。


image
このピンは、ヘッダ上で電源を供給していても、N.C.です。

コンフィギュレーション入力6: このチップのデフォルトの接続は、未接続の場合オープンです。モータに静的トルクを与える必要があるアプリケーションを除いては、オープンにしておくことをお勧めします。

image

チョッパーコンフィギュレーションピン:

このボードでは、他にもいくつかの設定ピンをハードワイヤで接続することができます。Watterott氏は残りの3つのピンを設定可能にしておいたようです。

image

ピン0、4および5はハードワイヤで異なる状態にすることが可能です。回路図を見ていただければ、各ピンの位置がわかると思います。また、デフォルトでは、ピン0と4は接地され、ピン5はVCC_IOに接続されていることがわかります。

データシートに記載されているピンの内容は以下のとおりです。

image

image

電流を計算する

CFG3にジャンパを設けなかった場合、ドライバは AIN_REF とセンス抵抗を使用してコイルに流れる電流を調整することになります。本ボードでは、0.11Ωのセンス抵抗を使用しています。Vrefの電圧はコイルに流れる電流に比例することになります。モータを接続する前に電流を設定したい場合は、必ずボードの電源を切ってからモータを接続してください。モータの着脱時にドライバに電源が供給されていると、ドライバを破損する恐れがあります。Vref ピンの電圧を監視してください。電流を下げるには、ネジを反時計回りに回します。電流を調整するもう一つの方法は、モータの性能を確認することです。モータの動作が悪くなるまで電流を下げます。次に、モータが望ましい動作をするようになるまで電流を増やします。

Vref (V) I RMS (A)
2.5 1.74
2.0 1.39
1.5 1.04
1.0 0.70
0.5 0.35

データシートには、1.2ARMS(二乗平均平方根Root Mean Square)がドライバが駆動できる最大値であると書かれていることに留意してください。ヒートシンクへの接続が良好であれば、それ以上の電流を流すことができるかもしれません。

EFM32 Giant Geckoを使用したコード例です。

/**************************************************************************//**
 * @file
 * @brief Empty Project
 * @author Energy Micro AS
 * @version 3.20.2
 ******************************************************************************
 * @section License
 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
 *******************************************************************************
 *
 * This file is licensed under the Silicon Labs Software License Agreement. See
 * "http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt" 
 * for details. Before using this software for any purpose, you must agree to the
 * terms of that agreement.
 *
 ******************************************************************************/
#include "em_device.h"
#include "em_chip.h"
#include "em_gpio.h"
#include "em_cmu.h"
#include "em_timer.h"
#include "em_emu.h"
volatile uint32_t msTicks;
void SysTick_Handler(void) {
    msTicks++;
}
void Delay(uint32_t dlyTicks) {
    uint32_t curTicks = msTicks;
    while((msTicks - curTicks) < dlyTicks);
}
void setDir(bool dir) {
    if(dir) GPIO->P[4].DOUTSET = 1 << 3;
    else GPIO->P[4].DOUTCLR = 1 << 3;
}
bool getPushButton(bool button) {
    return !(GPIO->P[1].DIN & (1 << (button + 9)));
}
/**************************************************************************//**
 * @brief  Main function
 *****************************************************************************/
/* This code isn't optimized for anything. Rather, it was just proof that i could get the motor spinning and test ou the maximum velocities. If you change the step configuration pins, you
could probably get faster speeds out of the driver. */

int main(void)
{
  /* Chip errata */
  CHIP_Init();
  CMU_ClockEnable(cmuClock_GPIO,true);
  CMU_ClockEnable(cmuClock_TIMER3,true);
  TIMER3->CTRL = 1 << 6;                                                       //Run in debug mode
  TIMER3->ROUTE = (1 << 16) | (1 << 2);                                          //Location 1, CC2 output enable
  TIMER3->CC[2].CTRL = (1 << 10) | 2;                                          //On timer overflow, toggle output. Enable compare output.
  if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ;       //Setup system tick handler
  GPIO->P[1].MODEH |= (1 << 4) | (1 << 8);                                       //Enable pushbuttons as inputs (B9, B10)
  GPIO->P[4].MODEL |= 0x4400;                                                    //Enable outputs E2 and E3
  int16_t time_delay = 32767;                                                   //32767 is the largest value for this signed int. If i     increment by one more, it will overflow to -32768. Good.
  /* Infinite loop */
  while (1) {
      if(getPushButton(1)){                                                     //If button one is pressed
          if((time_delay > 0) | (time_delay < -500)) time_delay++;                //Make sure it isn't in the dead zone,     then increment time_delay
      }
      else if(getPushButton(0)) {                                               //If button zero is pressed
          if((time_delay < 0) | (time_delay > 500)) time_delay--;             //Make sure it isn't in the dead zone, then decrement time_delay
      }
      if((time_delay > 32000) | (time_delay < -32000))TIMER3->CMD = 0x2;       //If the time delay is large, i probably wanted to stop the motor entirely.
      else TIMER3->CMD = 0x1;
      if(time_delay < 0) {                                                       //This is not optimized for keeping position absolute. I ignored the direction-to-step transition time here.
          setDir(0);
          TIMER3->TOPB = (time_delay * -1);
      }
      else {
          setDir(1);
          TIMER3->TOPB = time_delay;
      }
  }
}

速度を制御する

モータをステップさせる2つの方法を示しました。タイマを使ってモータをステップさせるのがおすすめです。Hブリッジを使えば、タイマの割り込みの中でモータをステップさせることができます。step/dirドライバを使用する場合、コンペア/キャプチャ ピンをPWMモードに設定することで、ピンを自律的にトグルさせることができます。モータの速度は、時間遅延によって決定されます。また、タイマのオーバーフロー時にコンペアチャンネルを切り替えるか、PWMチャンネルを設定するかを選択することができます。ドライバのデータシートには、タイミング特性に関する情報が記載されています。今回の場合、1MHzのクロックを動作させると、動作の間に20クロック待つ必要があります。私がもともと見落としていた重要な値は、ステップする方向のセットアップ時間でした。このタイミング特性を無視すると、位置を見失う可能性があります。チップはモータが別の場所にあると勘違いしてしまうのです。幸いなことに、Trinamicのデータシートは読みやすいです。

速度は距離÷時間です。ステッピングモータでは、ステップを時間で割ったものです。速度は、1回転あたりの総ステップ数で割ることで計算できます。これにはマイクロステップが含まれます。(総ステップ数=モータステップ数 * マイクロステップ数)

image

1を掛けると、全ステップで1回転します。

image

これをコードに実装する場合、ステップを増加または減少させる期間を求める必要があります。時間の長さを速度の関数として解くと、次のようになります。

image

ここで、Vは1秒あたりの回転数、時間の単位は秒です。秒というのは、マイコンにとっては非常に長い時間です。1秒あたりのクロック数を掛けるのがベストでしょう。

image

変数に関連する数値を無視することで、単位を確認することができます。

image

1秒あたりのクロック数は、周波数とも呼ばれます。

image

タイマがプリスケーラを使用している場合、その同じプリスケーラで分割して使用する必要があります。もし1秒がプリスケール前に1024クロックだったとして、1024でプリスケールすると、ちょうど1クロックが1秒になります。

image

これは、モータが各時間経過後にステップする限り、動作します。タイマをオーバーフローするように設定すると(上のコードでやったように)、これらの方程式はすべて2で割ると動作します(ステップに2つの期間を要するからです。期間を2で割ると元に戻ります)。

プリスケーラは最高速度に大きく依存します。自分の最高速度がわかっていれば、この式を使って、その速度になるためのタイマクロックの最低数を割り出すことができます。最高速度がわからない場合は、試行錯誤してみるとよいでしょう。モータの挙動がおかしくなるまで、時間を短くし続けてください。最高速度に近い負荷がかかると、モータが飛ぶことがあるので注意が必要です。モータの回転数や負荷をいろいろ変えて試してみてください。

image

この実装の最大の問題は、速度が0の場合、無限大の時間を待つ必要があることです。無限大は、マイコンがカウントするには大きすぎます。また、速度が0に近いと、時間遅れが非常に長くなることもあります。これを解決するには、達成可能な最も遅い速度を見つけ、デッドゾーンを作るのがよいでしょう。私のチップでは、トップタイマの値は16ビットの数値です。最長の遅延時間は65,535クロックになります。達成可能な最低速度は、

image

これで完成です!これでプロジェクトに着手できるはずですが、使えるようにするにはもっと工夫が必要です。一定の速度で目標位置を送信するのはとても簡単です。割り込みの中で、目標位置が実際の位置と等しくないかどうかをチェックします。もしそうなら、モータをステップさせます。

速度制御がわかったので、それを使って制御の幅を広げましょう。速度を上下させる機能を実装してみてください。そして、目標位置を設定し、そこに到達するためにランプアップ/ダウンしてみましょう。もし、これが面倒に思えるなら、別の解決方法があります。TMC5130の登場です!

TMC5130を使用した場合の例

Trinamicのステッピングモータドライバ、TMC5130は、すべてを説明するのが難しいほど多くの機能を備えています。まず、このドライバは、step/dir、SPI、または単線UARTで制御することができます。step/dirを使用する場合、チップはTMC2100を模倣し、チップに搭載された素晴らしい機能の一部を失います。SPIまたは単線式UARTを使用すると、速度モードと位置モードにアクセスできます。どちらのモードでも、モータの位置と回転速度が分かります。最大速度と加速度はプログラム可能です。チップに目標位置を与えれば、最大速度まで加速し、その位置に到達する前に減速するように配慮されているのです。

ここでは、ドライバの機能を要約してご紹介します。

SpreadCycle - 自動高速減衰。モータのチューニングは不要

CoolStep - モータが発生する起電力を利用し、コイルに流す電流を最小限に抑える

StealthChop - 低速回転時のモータの動作音がほぼ無音

StallGuard2 - モータの脱調を検知する

DcStep - 高い負荷を考慮し、自動的に速度を下げる

最近のプロジェクトでは、stealthChop、spreadCycle、stallGuard2を使っています。stealthChopとstallGuard2 のためにチップをセットアップする方法について説明します。

まず最初に、チップを基板に搭載する必要がありますが、TMC5130-EVAL-KITなら問題なく始められます。カスタム基板を作成する場合は、この記事では伝えきれないほど多くの情報があるのでデータシートを参照して詳細を確認してください。唯一の特殊性は、ピン29(DRV_ENN_CFG6)がドライバのイネーブルであることです。このピンをHighに接続すると、すべてのモータ出力はフローティングのままになります。このピンをグランドに接続すると,モータ出力が有効になります。また、CLKピンにクロックを供給しない場合は、このピンをグランドに結線する必要があります。私のチップの接続方法は以下の通りです。

ピン 番号 タイプ 接続
TST_MODE 1 DI GND
CLK 2 DI 外部クロックかGND
CSN_CFG3 3 DI (tpu) SPIチップセレクト入力
SCK_CFG2 4 DI (tpu) SPIクロック
SDI_NAI_ CFG1 5 DI (tpu) SPIデータ入力
N.C. 6, 31, 36 未使用端子。将来のバージョンとの互換性のため、GNDに接続してください
SDO_NAO_ CFG0 7 DIO (tpu) SPIデータ出力
REFL_STEP 8 DI フローティング
REFR_DIR 9 DI フローティング
VCC_IO 10 MCUの電源電圧に接続してください
SD_MODE 11 DI (pu) GND
SPI_MODE 12 DI (pu) フローティング
GNDP 13, 48 電源GND。ピン近傍のGNDプレーンに接続してください
DNC. 14, 16, 18,20, 22, 41,43, 45, 47 これらのピンは接続しないでください。高電源電圧に対応するため、コーティング無しでプリント基板のクリープ距離を長くするためのものです。
OB1 15 モータコイルBの出力1
BRB 17 コイルBのセンス抵抗接続ピン。センス抵抗はピン近傍でGNDに接続してください。最良の特性を得るために、GNDに100nFのコンデンサを追加することを推奨します。
OB2 19 モータコイルBの出力2
VS 21, 40 モータ電源電圧。ピン近傍にフィルタリング容量を設け、直近のGNDPピンとショートループ(それぞれGNDプレーンを経由)してください。
ENCN_DCO 23 DIO GND
ENCB_DCEN_ CFG4 24 DI (tpu) GND
ENCA_DCIN_ CFG5 25 DI (tpu) GND
SWN_DIAG0 26 DIO フローティング
SWP_DIAG1 27 DIO フローティング
SWSEL 28 DI (pd) フローティング
DRV_ENN_ CFG6 29 DI GND - トグルスイッチまたはMCUに接続することも可能です。
AIN_IREF 30 AI フローティング
GNDA 32 アナログのGNDです。GNDプレーンに接続してください。
5VOUT 33 内蔵5Vレギュレータの出力。2.2µF以上のセラミックコンデンサを 近傍のGNDAピンに取り付けるとより効果的です。出力はチップのVCCに供給されます。
VCC 34 チップ内のデジタル回路およびチャージポンプの5V電源入力。GND(GNDプレーン)に470nFのコンデンサを装着してください。5VOUTから供給してもかまいません。5VOUTからノイズをデカップリングするために、2.2または 3.3Ωの抵抗を推奨します。外部電源を使用する場合は、VCCが5VOUTまたはVCC_IOの前に、あるいは並列に立ち上がるようにします。5VOUTとVCC_IOは、どちらか後になってもよいです。!
CPO 35 チャージポンプコンデンサ出力
CPI 37 チャージポンプコンデンサ入力端子。22nF 50VのコンデンサでCPOに接続します。
VCP 38 チャージポンプ電圧です。100nFのコンデンサでVSに接続します。
VSA 39 5Vレギュレータのアナログ電源電圧。通常はVSに接続します。100nFのフィルタリングコンデンサを取り付けてください。
OA2 42 モータコイルAの出力2
BRA 44 コイルAのセンス抵抗接続端子です。センス抵抗は端子近傍でGNDに接続してください。GND(GNDプレーン)に100nFのコンデンサを追加することを推奨します。
OA1 46 モータコイルAの出力1
Exposed die pad - 露出ダイパッドをGNDプレーンに接続してください。GNDプレーンへの熱伝達のため、できるだけ多くのビアを設けてください。デジタル回路のGND端子として使用します。

また、リファレンスデザインとしては、データシートの121ページが参考になります。以下は、評価ボードの回路図です。 TMC5130-Eval_v15_01_Schematic.pdf (69.0 KB)

ボトムパッドとグランドプレーンとの熱的接続が良好であることを確認してください。可能であれば、ビアを用いてグランドプレーンに熱を伝達してください。CNCマシンで削り出した2層基板を作る場合は、チップの下に大きなドリル穴を空けておき、そこにはんだを充填してグランドプレーンに接続します。ボトムパッドを熱的に接続しないと、大きな電流を流すことができません。

チップを取り付けたら、チップに設定データを送信する必要があります。私が前回やった時は、あまり効率よくできませんでした。評価キットから送られてきた設定をモニターし、自分のセットアップで真似をし、うまくいかなかったときは、どこが悪いのか、すべてのレジスタを調べなければなりませんでした。結局、SPIバスのクロックラインのショートでした。もしもう一度やるとしたら、5130のデータシートの109ページを参考にします。以下はそのページのコピーです。データシートで各レジスタを参照し、どのような設定が有効かを確認することができます。注:電流の設定を再確認してください。この初期化では、電流を最大値に設定しています。これはチップ下の放熱が非常に大きい評価キットを意識したものです(高電圧でチップを壊したら交換するのが本当に面倒でした)。また、PWMCONFレジスタによっては、設定によって電流が増加する場合があります。このレジスタを設定する際は、モータに流れる電流をモニタするか、チップの温度を確認してください。

25.1 Initialization Examples(初期化例)
SPI datagram example sequence to enable the driver for step and direction operation and initialize the chopper for spreadCycle operation and for stealthChop at <60 RPM:
SPI send: 0xEC000100C5; // CHOPCONF: TOFF=5, HSTRT=4, HEND=1, TBL=2, CHM=0 (spreadCycle)
SPI send: 0x9000061F0A; // IHOLD_IRUN: IHOLD=10, IRUN=31 (max. current), IHOLDDELAY=6
SPI send: 0x910000000A; // TPOWERDOWN=10: Delay before power down in stand still
SPI send: 0x8000000004; // EN_PWM_MODE=1 enables stealthChop (with default PWM_CONF)
SPI send: 0x93000001F4; // TPWM_THRS=500 yields a switching velocity about 35000 = ca. 30RPM
SPI send: 0xF0000401C8; // PWM_CONF: AUTO=1, 2/1024 Fclk, Switch amplitude limit=200, Grad=1
SPI sample sequence to enable and initialize the motion controller and move one rotation (51200 microsteps) using the ramp generator. A read access querying the actual position is also shown.
SPI send: 0xA4000003E8; // A1 = 1 000 First acceleration
SPI send: 0xA50000C350; // V1 = 50 000 Acceleration threshold velocity V1
SPI send: 0xA6000001F4; // AMAX = 500 Acceleration above V1
SPI send: 0xA700030D40; // VMAX = 200 000
SPI send: 0xA8000002BC; // DMAX = 700 Deceleration above V1
SPI send: 0xAA00000578; // D1 = 1400 Deceleration below V1
SPI send: 0xAB0000000A; // VSTOP = 10 Stop velocity (Near to zero)
SPI send: 0xA000000000; // RAMPMODE = 0 (Target position move)
// Ready to move!
SPI send: 0xADFFFF3800; // XTARGET = -51200 (Move one rotation left (200*256 microsteps)
// Now motor 1 starts rotating
SPI send: 0x2100000000; // Query XACTUAL - The next read access delivers XACTUAL
SPI read; // Read XACTUAL

うまくいけば、これでモータが動くようになるはずです。もし動かない場合は、SPIバスの通信を再確認してください。たまたま同じSPIバスに加速度センサがあったので、その部品が動作していることを確認しました。

StealthChopを設定する

上記の例では、stealthChopのセットアップ方法も紹介しています。現在stealthChopを使用していない作業コードから変更する必要がある3つのレジスタがあります。
GCONF - 0x00:ビット2(1 << 2)を設定し、PWM モードを有効にする。
TPWMTHRS - 0x17:stealthChopが動作する上限速度(下限時間遅延)を設定します。これを低く設定し過ぎないようにしてください。低くしすぎると、モータが切り替わる時にスムーズに動作しません。例では500を使用していますが、私は5000を使用しました。
PWMCONF - 0x70:これは stealthChopの主要な構成レジスタです。もしstealthChopが奇妙な振る舞いをするなら、このレジスタの設定をチェックしてください。

  • autoscaleビット(1 << 18)を設定することで、素早くstealthChopを設定できます。
  • 依然として雑音が出る場合は、pwm_frequencyのビットフィールドに高い周波数を設定してみてください。
  • PWM_GRADのビットフィールドを1以上に設定します。
  • PWM_AMPLフィールドは64以上を推奨します。値が大きい程、モータ電流が大きくなります。

データシートでは、この点についても詳しく説明しています。

stallGuard2ホーミングを使用する

ハードストップを持つstallGuard2を使用すると、リファレンススイッチのように簡単に設定することはできません。リファレンススイッチは、stallGuard2よりもはるかに優れた耐性を持っています。いざという時、やはり便利なソリューションです。数ステップの違いで大きい違いとなるアプリケーションでは、この機能は使わないでください。絶対位置がそれほど重要でないアプリケーションでは、ぜひご使用ください。

triWrite(0x27,0)                        //To start, set the motor velocity to 0.
triWrite(0x20,1)                        //Put the chip in velocity mode                                   //Or 2 if other direction
triWrite(0x14,5000)                     //Set the coolStep upper velocity                                 //I suspect lower numbers may work better
triWrite(0x34, (1 << 10))             //Enable stop by stallGuard2                                      //Clear this bit to disable stallGuard2
triWrite(0x6D,(11 << 16))                 //Set Stall Guard Threshold                                       //This field will change if anything else changes. It will also vary from motor to motor. The EVAL kit is nice for this.
triWrite(0x27, 60000)                   //Start a motion                                                  //My application was geared down
Delay(1000)                             //Wait for motor to start                                         //Motor will stop when it stalls
while(triGetVel())                      //Poll vActual, wait for it to be 0                               //Poll the velocity instead of the     flags
triWrite(0x27,0)                        //Set the target velocity to 0                                    //This prevents the motor from moving
triWrite(0x34,0)                        //Clear the sg_stop bit                                           //Alternatively, read the     RAMP_STAT register
/*
To set where "home" is, you need to set xActual. If where you stopped is home, set xActual to 0. In my case, home was +187300 microsteps. So, I set xActual to -187300. Then, I set xTarget to 0. This will send the stepper home once you switch to position mode.
    */
triWrite(0x21,-187300)                  //Set home                                                        //I'm here in reference to home
triWrite(0x2D, 0)                       //Go home                                                         //I want to be here
triWrite(0x20,0)                        //Now set into position mode                                      //Position mode
triWrite(0x27,0x249F0)                  //Set upper velocity limit                                        //This is your upper operating velocity

このくらいで十分でしょう!結局、私のプロジェクトではポジションモードにする前に、xTargetをxActualに設定してしまいました。これが、私が設定したマクロの結果ですが、この順番でも問題ないはずです。用途によって、速度やストールガードの閾値を変える必要がありますが、プロセスは同じです。sg_stopビットをクリアすると、ストールガードが停止します。もし、アプリケーションでオンにしておきたい場合は、代わりに RAMP_STATレジスタを読み込んでください。

stallGuard2の設定方法は、データシートの78ページ以降で説明しています。stallGuard2機能は、正しくキャリブレーションするのに時間がかかります。他のモータドライバでもストールを検出することはできますが、これはかなり優れた機能です。他のドライバは過電流を検出することができますが、私がこれまで見た中では、過電流制限を設定できるものはありませんでした。

ユニポーラモータ

ユニポーラモータは、コイルがセンタータップされているバイポーラモータです。そのため、電流制御が非常に容易です。コイルの半分しか使えないので効率が悪いという欠点があります。ユニポーラの配線はここにつながっています。モータの配線が5本しかない場合、2つのセンタータップはすでに接続されています。

image

バイポーラモータはこうしてステップを刻みます。バイポーラモータでは、各ピンをハイにしたりローにしたりする必要があります。

ユニポーラモータでは、コイルエンドをグランドにするだけでよいのです。

これを駆動するための回路は単純明快です。

image

バイポーラモータと違って、隣り合った2つのトランジスタをオンにしても、部品が壊れることはありません。モータをステップ動作させるには、次の順序でコイルをオンにします。A1、B1、A2、B2。モータを逆回転させるには、この順序を逆にします。以下はコード例です。

フルステップを使用したコード例。

/**************************************************************************//**
 * @file
 * @brief Empty Project
 * @author Energy Micro AS
 * @version 3.20.2
 ******************************************************************************
 * @section License
 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
 *******************************************************************************
 *
 * This file is licensed under the Silicon Labs Software License Agreement. See
 * "http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt" 
 * for details. Before using this software for any purpose, you must agree to the
 * terms of that agreement.
 *
 ******************************************************************************/
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_system.h"
#include "em_gpio.h"
volatile uint32_t msTicks;
#define TOTAL_STEPS      4
uint32_t STEPS[TOTAL_STEPS] = {0b1000, 0b0010, 0b0100, 0b0001};             //1,3,2,4
uint16_t STEP = 0;
/* ************* Systick Handler ***************** */
void SysTick_Handler(void) {
    msTicks++;
}
/* ************* Delay function ****************** */
void Delay(uint32_t dlyTicks) {
    uint32_t curTicks = msTicks;
    while((msTicks - curTicks) < dlyTicks);
}
/* ************* Output to H-bridge ************** */
void setStep(void) {
      GPIO->P[3].DOUTCLR = 0xF;                  //Shut off all pins.
      GPIO->P[3].DOUTSET = STEPS[STEP];          //Output the steps
}
/* ************* Main function ******************* */
int main(void)
{
    CHIP_Init();
    CMU->HFRCOCTRL = 0x30; // Set RC clock to 1 MHz
    CMU->HFPERCLKEN0 =(1<<13); //Enable GPIO clock

    if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ;         //Setup SysTick

    /* ****************** Setup pushbuttons and H-bridge outputs ****************** */
    GPIO->P[1].MODEH = 0x110;                //Setup RB9 and RB10 as input
    GPIO->P[3].MODEL = 0x5555;               //Setup PD0-PD3 as push pull output. These go directly to the H-bridge
    GPIO->P[3].CTRL = 2;                     //High drivemode
    GPIO->P[3].DOUT = 0x0000;                //They should already be all low.
                                        //H-bridge pins 1,2,3,4 map to pins 3,2,1,0 on port D.
  /* Infinite loop */
  while (1) {
      if(!GPIO_PinInGet(gpioPortB,9)) {                         //If button 0 is pressed
          STEP = (STEP + 1) % TOTAL_STEPS;                      //Increment the step
          setStep();                                            //Output to the H-bridge
      }
      else if(!GPIO_PinInGet(gpioPortB, 10)) {                  //If button 1 is pressed.
          STEP = (STEP + TOTAL_STEPS-1) % TOTAL_STEPS;          //Decrement the step
          setStep();                                            //Output to the H-bridge
      }
      Delay(10);                                                //Short delay to let motor rotate
  }
}

ハーフステップを使用したコード例。

/**************************************************************************//**
 * @file
 * @brief Empty Project
 * @author Energy Micro AS
 * @version 3.20.2
 ******************************************************************************
 * @section License
 * <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
 *******************************************************************************
 *
 * This file is licensed under the Silicon Labs Software License Agreement. See
 * "http://developer.silabs.com/legal/version/v11/Silicon_Labs_Software_License_Agreement.txt" 
 * for details. Before using this software for any purpose, you must agree to the
 * terms of that agreement.
 *
 ******************************************************************************/
#include "em_device.h"
#include "em_chip.h"
#include "em_cmu.h"
#include "em_system.h"
#include "em_gpio.h"
volatile uint32_t msTicks;
#define TOTAL_STEPS      8
uint32_t STEPS[TOTAL_STEPS] = {0b1000, 0b1010, 0b0010, 0b0110, 0b0100, 0b0101, 0b0001, 0b1001};                     //1, 1and3, 3, 3and2, 2, 2and4, 4, 4and1

/* ************* Systick Handler ***************** */
void SysTick_Handler(void) {
    msTicks++;
}
/* ************* Delay function ****************** */
void Delay(uint32_t dlyTicks) {
    uint32_t curTicks = msTicks;
    while((msTicks - curTicks) < dlyTicks);
}
/* ************* Output to H-bridge ************** */
void setStep(uint32_t STEP) {
      GPIO->P[3].DOUTCLR = 0xF;                                  //Shut off all pins.
      GPIO->P[3].DOUTSET = STEPS[(STEP % TOTAL_STEPS)];          //Output the steps
}
/* ************* Main function ******************* */
int main(void)
{
 CHIP_Init();
    CMU->HFRCOCTRL = 0x30; // Set RC clock to 1 MHz
    CMU->HFPERCLKEN0 =(1<<13); //Enable GPIO clock

    if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ;         //Setup millisecond tick counter

    /* ****************** Setup pushbuttons and H-bridge outputs ****************** */
    GPIO->P[1].MODEH = 0x110;                //Setup RB9 and RB10 as input
    GPIO->P[3].MODEL = 0x5555;               //Setup PD0-PD3 as push pull output. These go directly to the H-bridge
    GPIO->P[3].CTRL = 2;                     //High drivemode
    GPIO->P[3].DOUT = 0x0000;                //They should already be all low.
                                            //H-bridge pins 1,2,3,4 map to pins 3,2,1,0 on port D.
    int32_t STEP = 0;

  /* Infinite loop */
  while (1) {
      if(!GPIO_PinInGet(gpioPortB,9)) {                         //If button 0 is pressed
          STEP += 1;                                            //Increment the step
          setStep(STEP);                                        //Output to the H-bridge
      }
      else if(!GPIO_PinInGet(gpioPortB, 10)) {                  //If button 1 is pressed.
          STEP -= 1;                                            //Decrement the step
          setStep(STEP);                                        //Output to the H-bridge
      }
      Delay(10);                                                //Short delay to let motor rotate
  }
}

このコードでは、ステッピングの増加・減少の方法を変更しました。STEPSベクトルを循環させるのではなく、その位置を記録しておき、ステップを設定するときに分割しています。これは位置を把握し、モータを動かすのに非常に有効です。唯一気をつけなければならないのは、数値がアンダーフローするときのゼロクロスです。ステップ数の合計が2の倍数であれば、問題ないでしょう。もう1つの変更点は、STEPを符号付き整数と宣言したことです。出力設定に使うときは符号なし整数としました。これによって、出力に影響を与えることなく、ネガティブステップを追跡することができるようになりました。

ユニポーラモータのドライバは、上図を置き換えるか、step/dirで制御できるようにします。これらはかなり簡単に設定できますので、詳細は省略します。ドライバの仕様については、必ずデータシートで確認してください。

その他の資料:

Hブリッジの秘訣 - Hブリッジの仕組みについて詳しく解説しています。

Jones on Stepping Motors - これは1995年にアイオワ大学の教授によって書かれたチュートリアルです。ステッピングモータの物理について非常に詳しく書かれています。ステッピングモータの駆動に関わる物理をより詳細に理解したい方はお読みください。



オリジナル・ソース(英語)