最初にお断りしておくが、まだL6470の機能に熟知しているわけではなく間違いも多いと思う。ご指摘願いたい。
とは言え実際に動作させることは出来ている。
2022.02.18時点では情報が少ない秋月電子から発売されているバイポーラステッピングモータードライバをPIC16F1827にて駆動する方法を記載する。駆動方法だけで無くUARTを使った外部制御とLCD1602の使い方も合わせて記載する。
当記事を記載するにあたっては以下のサイトからの情報を元にしている。感謝
https://rikeden.net/?p=501
https://tyokota.hateblo.jp/entry/2017/06/16/191852
【主な部品リスト】
・直流安定化電源秋月電子 2022.02.18時点
・L6470使用 ステッピングモータードライバ 通販コード K-07024
・バイポーラ ステッピングモーター ST-57BYG076-0604 通販コード P-7601 ※バイポーラ仕様ならば目的に応じて適宜選択可。今回産業機器で使用する為、静止トルク重視で選択した。末尾が0604である点に注意
・PICマイコン PIC16F1827-I/P 通販コード I-04430
12V → 5V変換用
・三端子レギュレータ 5V1.5A NJM7805FA 通販コード I-08678
・TO-220用 小型放熱器(ヒートシンク) 30x30x30mm 通販コード P-00429
・熱伝導グリス ※今回はKryonaut TG-K-001-RS 熱伝導率 12.5W/mkを使用したが適当でOK
・0.3μFコンデンサ
積層セラミックコンデンサー 0.33μF50V X7R 5mm
・0.1μFコンデンサ 2個
積層セラミックコンデンサー 0.1μF250V X7R 5mmピッチ
Amazon
LCD1602 ※今回PICのピンアサインの制限でパラレル接続で使用する。I2C/SPI/EUSARTを同時使用するとかぶってしまいます。
FT232RLモジュール ※搭載されているチップが本物では無いと謎の説明が本文にあります...
使った感じだとWindows10からだとちゃんと認識されます。ドライバーも本家のものが入りますが、産業機器と接続すると認識しませんでした。
おそらく送受信バッファが少ない為と思われます。産業機器との接続は別途考える。本物使えば可???
【回路図】
クリックすると拡大表示されます。右クリックでダウンロード可 転載禁止 ![16F1827_L6470.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672650/0ebbebc8-7830-b004-1fd8-b6aac40557fd.png) <解説> ①L6470モジュールのJP1は外部電圧使用に設定 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672650/ea9b681d-90a7-4a5f-8085-a06692cf01e0.png)②LM7805に流れる電流は28mAと直流安定化電源で表示されている為、熱損失は(12V) - (5V) x 0.028A = 0.196W
多分ヒートシンクもいらない....
熱抵抗の計算は以下のサイトを参照したが理解に至っていない。
http://www.picfun.com/heatsink.html
③FT232RLの接続で問題になるのはVCCをどうするか?製品によって異なるようで外部電源を使用する場合は外部電源に接続とか、そもそもUSBからの電源供給しか想定していなく説明が無いとか(今回のものはこれに該当)
④SW1/SW2 への接続はプルダウン抵抗を接続して入力。+5VでロジックHigh
テスト回路なので作りこんでおらず、特にリミットスイッチにセンサーなどを使う場合は回路ごと変更しなければならない。
⑤FLAGとBUSYのPICへの入力はPIC内部でプルアップを有効にするので外部抵抗無し。
ここで、最初RA5をSPI通信のCSに接続してしまいはまった。MRCLピンをは出力に使えず入力専用だと知るまで2日間悩んだ。
注意点は以上だが、PICのピンが足りていない為最終的に産業機器と連携させる為には少なくとも28ピンのPICを使う必要がある。別途記事にする予定
MPLAB X IDE MCCの設定
PeripheralsにEUSARTとMSSP1を追加してから設定開始①Internal Clockを8Mhzに設定 PLL有効 これ32MHz動作
③Pin Moduleの割り込みを最優先に設定 特にリミットスイッチのONが遅れると事故になる為、
ソースコード
①L6470制御部 http://zattouka.net/GarageHouse/index.htm http://zattouka.net/GarageHouse/micon/MPLAB/16F1786/Stepper/Stepper.htm 基本的に上記サイトのコードを使用した。多謝 変更点はSPI通信のメソッドと各種レジスタの設定となる。 変更点を含めて転載して良いか迷ったが、特に転載禁止などの文言が無かった為載せておく。 プロジェクトフォルダ構造Root
--build
--debug
--dist
--ext
--L6470
--skL6470.h
--skL6470.c
--mcc_generated_files
--nbproject
--main.c
--lcd.c
--lcd.h
skL6470.h
/*******************************************************************************
* skL6470.h - L6470ステッピングモータドライバ関数ライブラリ用ヘッダファイル *
* *
* ============================================================================ *
* VERSION DATE BY CHANGE/COMMENT *
* ---------------------------------------------------------------------------- *
* 1.00 2016-07-07 きむ茶工房(きむしげ) Create *
* 1.10 2021-07-22 きむ茶工房(きむしげ) ステップ設定とアラームON機能を追加 *
* 1.10α 2022-02-18 Kamoshika レジスタをST-57BYG076-0604仕様に変更 *
* SPI関連メソッドをMCC仕様に変更 *
* ============================================================================ *
* PIC 16F1827 *
* MPLAB X (v5.50) *
* MPLAB(R) XC8 C Compiler Version 1.3.90/2.32 *
*******************************************************************************/
#ifndef _SKL6470_H_
#define _SKL6470_H_
/*
#ifndef _XTAL_FREQ
// Unless already defined assume 64MHz system frequency
// This definition is required to calibrate __delay_us() and __delay_ms()
#define _XTAL_FREQ 32000000 // 使用するPIC等により動作周波数値を設定する
#endif
*/
#define L6470_CS RB6 // L6470のSPI-CSのピン番号
#define L6470_BUSY RA5 // L6470のBUSYのピン番号
// レジスタのアドレス
#define L6470_ACC 0x05 // 加速時の係数(12bit)
#define L6470_DEC 0x06 // 減速時の係数(12bit)
#define L6470_MAX_SPEED 0x07 // 最大回転速度(10bit)
#define L6470_MIN_SPEED 0x08 // 最少回転速度(13bit)
#define L6470_KVAL_HOLD 0x09 // 停止時の電圧(8bit)
#define L6470_KVAL_RUN 0x0A // 定速回転時の電圧(8bit)
#define L6470_KVAL_ACC 0x0B // 加速時の電圧(8bit)
#define L6470_KVAL_DEC 0x0C // 減速時の電圧(8bit)
#define L6470_OCD_TH 0x13 // 過電流の閾値(4bit)
#define L6470_STALL_TH 0x14 // ストール電流の閾値(7bit)
#define L6470_STEP_MODE 0x16 // ステップモードの設定(8bit)
#define L6470_ALARM_EN 0x17 // 各種アラームの有無設定(8bit)
#define L6470_CONFIG 0x18 // コンフィグの設定(16bit)
#define L6470_STATUS 0x19 // 現在のステータス(16bit)
#define L6470_FS_SPD 0x15 //フルステップ速度のしきい値(10bit))
// 定数の定義
#define Forward 1 // モータは正転で回転
#define Reverse 0 // モータは逆転で回転
#define SOFTSTOP 0 // 減速停止、保持トルク有り
#define HARDSTOP 1 // 即時停止、保持トルク有り
#define SOFTHIZ 2 // 減速停止、保持トルク無し
#define HARDHIZ 3 // 即時停止、保持トルク無し
#define FULL_STEP 0 // フルステップ(モータと同じステップ数)
#define HALF_STEP 1 // ハーフステップ(モータと同じステップ数x2)
#define MICROSTEP8 3 // 1/8 マイクロステップ(モータと同じステップ数x8)
#define MICROSTEP64 6 // 1/64 マイクロステップ(モータと同じステップ数x64)
#define MICROSTEP128 7 // 1/128 マイクロステップ(モータと同じステップ数x128)
#define OSC_INT16MHZ 0 // クロックは内蔵16MHz
// レジスタの構造体定義
// STEP_MODE Register
union STEP_MODE_t { // ステッピングモードレジスタ(デフォルト=0x07)
unsigned char DT ;
struct {
unsigned STEP_SEL :3 ; // ステッピングモードの設定
unsigned SP :1 ; // 予備
unsigned SYNC_SEL :3 ; // 同期周波数の選択
unsigned SYNC_EN :1 ; // BUSY/SYNCの選択
} ;
} ;
// CONFIG Register
union CONFIG_t { // コンフィグレジスタ(デフォルト=0x2E88)
unsigned int DT ;
struct {
unsigned OSC_SEL :3 ; // クロックの選択
unsigned EXT_CLK :1 ; // クロック出力の有無
unsigned SW_MODE :1 ; // SW機能の選択
unsigned EN_VSCPMP :1 ; // モータの電源電圧補償の有無
unsigned SP :1 ; // 予備
unsigned OC_SD :1 ; // 過電流発生時のブリッジ回路停止の有無
unsigned POW_SR :2 ; // モータ出力のスルーレート値の設定
unsigned F_PWM_DEC :3 ; // PWM周波数生成の整数分周比を設定
unsigned F_PWM_INT :3 ; // PWM周波数生成倍率を設定
} ;
} ;
// 関数のプロトタイプ宣言
unsigned long L6470_Init() ;
unsigned long L6470_GetRegister(char regadrs,int num) ;
void L6470_SetStep(unsigned char mode) ; // (v1.10)
int L6470_ALARM() ;
void L6470_Run(char dir,unsigned long speed) ;
void L6470_Move(char dir,unsigned long step) ;
void L6470_Stop(int mode) ;
#endif
skL6470.c
/*******************************************************************************
* skL6470.c - L6470ステッピングモータドライバ関数ライブラリ *
* *
* L6470_Init - L6470の初期化を行う処理 *
* L6470_GetRegister - レジスタのデータを読み込む処理 *
* L6470_SetStep - レジスタにステップモードを書き込む処理 (v1.10)*
* L6470_ALARM - アラームの情報を読み込む処理 *
* L6470_Run - モータを一定速度で回転させる処理 *
* L6470_Move - モータを指定ステップ数まで回転させる処理 *
* L6470_Stop - モータを停止させる処理 *
* *
* ============================================================================ *
* VERSION DATE BY CHANGE/COMMENT *
* ---------------------------------------------------------------------------- *
* 1.00 2016-07-07 きむ茶工房(きむしげ) Create *
* 1.10 2021-07-22 きむ茶工房(きむしげ) ステップ設定とアラームON機能を追加 *
* 1.10α 2022-02-18 Kamoshika レジスタをST-57BYG076-0604仕様に変更
* SPI関連メソッドをMCC仕様に変更
* ============================================================================ *
* PIC 16F1827 *
* MPLAB X (v5.50) *
* MPLAB(R) XC8 C Compiler Version 1.3.90/2.32 *
*******************************************************************************/
#include "../../mcc_generated_files/mcc.h"
#include "skL6470.h"
int Busy ;
// L6470にコマンドを送信する処理
void CMD_Send(char cmd,unsigned long val,int num)
{
unsigned char dt[4] ;
int i ;
for (i=0 ; i<num ; i++) {
dt[i] = val & 0xff ;
val = val >> 8 ;
}
L6470_CS = 0 ;
SPI1_ExchangeByte(cmd) ; // コマンドの送信
L6470_CS = 1 ;
switch (num) {
case 3:
L6470_CS = 0 ;
SPI1_ExchangeByte(dt[2]) ; // パラメータ2の送信
L6470_CS = 1 ;
case 2:
L6470_CS = 0 ;
SPI1_ExchangeByte(dt[1]) ; // パラメータ1の送信
L6470_CS = 1 ;
case 1:
L6470_CS = 0 ;
SPI1_ExchangeByte(dt[0]) ; // パラメータ0の送信
L6470_CS = 1 ;
break ;
}
}
/*******************************************************************************
* ans = L6470_Init() *
* L6470の初期化を行う処理 *
* *
* ans : 現在のSTATUS情報を返す *
*******************************************************************************/
unsigned long L6470_Init()
{
union STEP_MODE_t step_mode ;
union CONFIG_t config ;
long val ;
int i ;
// L6470にリセットを掛ける
for (i=0 ; i<4 ; i++) {
L6470_CS = 0 ;
SPI1_ExchangeByte(0x00) ; // NOPの送信
L6470_CS = 1 ;
}
L6470_CS = 0 ;
SPI1_ExchangeByte(0xC0) ; // ResetDeviceコマンドの送信
L6470_CS = 1 ;
// 各種レジスタに設定を行う(SetParam)
CMD_Send(L6470_ALARM_EN,0xFF,1) ; // 全てのアラーム信号を ON に選択(v1.10)
CMD_Send(L6470_ACC,0x008A,2) ; // 加速時の係数
CMD_Send(L6470_DEC,0x0008A,2) ; // 減速時の係数
CMD_Send(L6470_MAX_SPEED,0xF,2) ; // 最大回転速度
CMD_Send(L6470_MIN_SPEED,0x0000,2) ; // 最少回転速度(0 Step/s^2 低速の最適化機能無効)
CMD_Send(L6470_KVAL_HOLD,0xFF,1) ; // 停止時の電圧(最大 L6470_KVAL_HOLD/0xFF*vs)
CMD_Send(L6470_KVAL_RUN,0xFF,1) ; // 定速時の電圧(同上)
CMD_Send(L6470_KVAL_ACC,0xFF,1) ; // 加速時の電圧(同上)
CMD_Send(L6470_KVAL_DEC,0xFF,1) ; // 減速時の電圧(同上)
CMD_Send(L6470_OCD_TH,0x08,1) ; // 過電流の閾値(3A) 375mAステップ 3000mA/375mA=0x08
CMD_Send(L6470_STALL_TH,0x20,1) ; // ストール電流の閾値(1A) 31.25mAステップ 1000mA/31.25mA=0x20
CMD_Send(L6470_FS_SPD,0x3FF,2); //フルステップ速度のしきい値(常にマイクロステップ動作)
// ステップモードの設定
step_mode.DT = 0x07 ; // デフォルト値
step_mode.STEP_SEL = MICROSTEP8 ; // 1/8ステップに設定 1600ステップで1回転
step_mode.SYNC_EN = Busy = 0 ; // BUSY出力モード 値が'0'でBUSY出力 :ピン出力はLOWでBUSY
val = step_mode.DT ;
CMD_Send(L6470_STEP_MODE,val,1) ;
// コンフィグの設定
config.DT = 0x2E88 ; // デフォルト値(PWM周波数:15.6KHz)
config.OSC_SEL = OSC_INT16MHZ ; // クロックは内蔵16MHz
config.EXT_CLK = 0 ; // クロック出力(OSCOUT)はなし
config.SW_MODE = 0 ; // ハード停止モード
config.EN_VSCPMP = 1; // モータの電源電圧補償の有 VR1の調整が必要です。
config.F_PWM_DEC = 0b000; //PWM 2.8kHz 高周波が耳障りなので変更した
config.F_PWM_INT = 0b110; //PWM 2.8kHz 高周波が耳障りなので変更した
val = config.DT ;
CMD_Send(L6470_CONFIG,val,2) ; // コンフィグの設定
return L6470_GetRegister(L6470_STATUS,2) ;// 現在のステータスを返す。
}
/*******************************************************************************
* ans = L6470_GetRegister(regadrs,num) *
* レジスタのデータを読み込む処理 *
* *
* regadrs : 読み取りたいレジスタのアドレスを指定(0x01-0x1B) *
* num : レジスタの読み取るデータのバイト数(1-3byte) *
* ans : 読み取ったデータをlong値で返す *
*******************************************************************************/
unsigned long L6470_GetRegister(char regadrs,int num)
{
unsigned long ans , dt ;
int i ;
L6470_CS = 0 ;
if (regadrs == L6470_STATUS) SPI1_ExchangeByte(0xD0) ; // GetStatusコマンドの送信
else SPI1_ExchangeByte(regadrs|0x20) ; // GetParamコマンドの送信
L6470_CS = 1 ;
ans = dt = 0 ;
for (i=0 ; i<num ; i++) {
ans = ans << 8 ;
L6470_CS = 0 ;
dt = SPI1_ExchangeByte(0x00) ; // レスポンデータを得る為にダミーの送信
L6470_CS = 1 ;
ans = ans | dt ;
}
return ans ;
}
/*******************************************************************************
* L6470_SetStep(mode) (v1.10) *
* レジスタにステップモードを書き込む処理 *
* *
* mode : ステップモードを指定します *
*******************************************************************************/
void L6470_SetStep(unsigned char mode)
{
union STEP_MODE_t step_mode ;
long val ;
// ステップモードの設定
step_mode.DT = 0x07 ; // デフォルト値
step_mode.STEP_SEL = mode ; // 指定のステップに設定
step_mode.SYNC_EN = Busy = 0 ; // BUSY出力モード
val = step_mode.DT ;
while( (Busy==0) && (L6470_BUSY==0) ) ; // コマンド実行中なら待つ
CMD_Send(L6470_STEP_MODE,val,1) ;
}
/*******************************************************************************
* ans = L6470_ALARM() *
* アラームの情報を読み込む処理 *
* FLAGピンがLOWにてアラーム発生です、割り込みで受けましょう。 *
* この関数は、”GetStatus”コマンドを発行しているのでアラームは解除されます *
* *
* ans:発生したアラーム情報を返す *
* 0=アラームは発生していない *
* 3=スイッチイベントを検出 *
* 7=コマンドが実行できない *
* 8=コマンドが全く存在しない *
* 9=定電圧を検出 *
* 10=熱警告を検出 *
* 11=サーマルシャットダウンを検出 *
* 12=過電流を検出 *
* 13=A相ストールを検出 *
* 14=B相ストールを検出 *
*******************************************************************************/
int L6470_ALARM()
{
unsigned long dt ;
int i ;
dt = L6470_GetRegister(L6470_STATUS,2) ;
for (i=14;i>=9;i--) {
if ((dt & (1<<i)) == 0) return i ;
}
for (i=8;i>=7;i--) {
if ((dt & (1<<i)) != 0) return i ;
}
if ((dt & (1<<3)) != 0) return 3 ;
return 0 ;
}
/*******************************************************************************
* L6470_Run(dir,speed) *
* モータを一定速度で回転させる処理 *
* 選択されているステッピングモードにより回転します *
* *
* dir : 回転させる方向を指示します(0=逆転 1=正転) *
* speed : 回転させる目標速度を指示します *
* 0.015step/sの分解能で0(0.015)-104166(15625)のステップです。 *
* MAX_SPEEDより低く、MIN_SPEEDより大きくなければなりません。 *
*******************************************************************************/
void L6470_Run(char dir,unsigned long speed)
{
while( (Busy==0) && (L6470_BUSY==0) ) ; // コマンド実行中なら待つ
CMD_Send(0x50|dir,speed,3) ; // 一定速度回転コマンドの送信
}
/*******************************************************************************
* L6470_Move(dir,step) *
* モータを指定ステップ数まで回転させる処理 *
* 選択されているステッピングモードによりステップ当りの回転角度は変わります。 *
* 例えば、step=200でフルステップモードなら1回転(360度)です。 *
* *
* dir : 回転させる方向を指示します(0=逆転 1=正転) *
* step : 回転させる目標ステップ数を指示します(0-4194303:22bit) *
*******************************************************************************/
void L6470_Move(char dir,unsigned long step)
{
while( (Busy==0) && (L6470_BUSY==0) ) ; // コマンド実行中なら待つ
CMD_Send(0x40|dir,step,3) ; // 移動コマンドの送信
}
/*******************************************************************************
* L6470_Stop(mode) *
* モータを停止させる処理 *
* Hizはモータを停止させた後、モータの出力をOFF(ハイインピーダンス)にします。 *
* *
* mode : 停止モードを指定します *
* 0 = SoftStop 減速しながらモータを停止させます、保持トルク有り。 *
* 1 = HardStop 即時にモータを停止させます、保持トルク有り。 *
* 2 = SoftHiz 減速しながらモータを停止させます、保持トルク無し。 *
* 3 = HardHiz 即時にモータを停止させます、保持トルク無し。 *
*******************************************************************************/
void L6470_Stop(int mode)
{
unsigned char cmd[4] = {0xB0,0xB8,0xA0,0xA8} ;
//while( (Busy==0) && (L6470_BUSY==0) ) ; // コマンド実行中なら待つ
L6470_CS = 0 ;
SPI1_ExchangeByte(cmd[mode]) ; // ストップコマンドの送信
L6470_CS = 1 ;
}
モータードライバ制御部解説
コードの中で使用されているレジスタ設定の意味は下記サイトを参照した https://tyokota.hateblo.jp/entry/2017/06/16/191852 https://strawberry-linux.com/support/12023/1488227秋月電子からダウンロードできるマニュアルを見ると以下の記載があるが、この意味の理解に時間がかかったので記載する。
tick・・・250ns ※動作クロックが250ns(4MHz?)なんか合わないな250nsの根拠が不明
MAX_SPEEDレジスタの単位は step/tickと記載されており、step/秒に換算する式が示されている。
試しに初期値を計算して合っているか見てみる。
991.8(step/s) = {0x412^-18}/(25010^-9)
まあ合っているんだが...248e-6(step/tick)と0x41の換算がどうなっているかわからん。248e-6を固定小数点で表現すると0x41になるのか...固定小数点の小数点の位置が記載無いが、指定が無い場合は一般的な考え方で調べてみる。
仮数部が第9bti目で残り8bitが小数部なのか??2^-18の意味からするとそうなる仮定する。
0x41 = 0b0001000001
仮数部が'0' 小数部は0b001000001
MATLABまで使って調べてみたが、合わんし...もうわからん だれか教えて
(初期値)
細かいところは解らないが...
今回使用するモーターが脱調せずに回転可能な速度が300setp/秒らしいので計算してみる。
300 = MAX_SPEED x 2^(-18) / 250 10^(-9)
式変形して、
MAX_SPEED = 300 / {2^(-18)/ 250 10^(-9)}
=300 / 15.25878906
=19.6608 ≒ 20 =0x14h
実際にやってみたが、300step/秒だと脱調してしまった。徐々に下げていって最終的に0x0fで脱調が収まった。
step/秒に換算すると
(0x0f2^-18)/(25010^-9)≒229step/秒 68.7rpm..ステッピングモーターってこんなに遅かった???
脱調の原因なんだろ、Duty比が50%から大きく外れているんじゃないだろうかオシロで調べてみた。
OWON SDS1022にて計測
画像には表示されていないがDuty比h20%と計測されている。
やっぱり外れていた...どうしよう
http://spinelify.blog.fc2.com/blog-entry-65.html
北の国からサイトさんに情報がありました。
このレジスタを2倍にしてみる。初期値が61.5step/secなので...
INT_SPEED=((61.52)(250*10^-9))/2^-26=2064=0x080F
duty比74% が脱調する。
その後、ST_SLPとFN_SLP_ACCをそれぞれ2倍にするとフルステップでMAX_SPEED =0x20までは脱調しなくなったが、結局よくわからん
運用は1/8マイクロステップで動作させるので前記3つのレジスタはデフォルトで運用、MAX_SPEED=0x0Fとした。
ちなみに、ソースコードは1/8マイクロステップ動作だが、フルステップにしても1回転の速度が同じだったことからレジスタの値はフルステップを基準に設定することがわかった。
次にわからなかったのはWSとWHの違い
ストップ時のみというのはそのままの意味でハイインピーダンスの意味は、モーターのコイルに電圧がかかっていないときの意味であった。
停止していても静止トルクを出す為に電圧をかけると変更できない。
main.cの中で示すがソースコード中でL6470_Stop(3)としてからで無いとステップモードの変更が出来ないなどの制限がかかる。
ステップモードを変更した瞬間にモーターが微動するので、対策としては精度が重要な場面ではステップモードは変更しない事にした。
// ステップモード変更 1/128
L6470_Stop(3);
L6470_SetStep(MICROSTEP64);
EUSARTとLCD1602の解説は後回しにして先にメインルーチンを載せておく
main.c#include "mcc_generated_files/mcc.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ext/L6470/skL6470.h"
#include "lcd.h"
void limitpos_int(void);//RB0(POS_LIMIT)の割り込み
void flag_int(void);//モータードライバからの割り込み
void org_btn(void);//原点復帰ボタン
void Wait(int num);// num x 10msの間delayさせる
void putch(char c){
lcd_DATA(c);
}
/*
Main application
*/
void main(void)
{
char rxData;
char strBuf[20];
int srtBufPointer=0;
int16_t pos=0;
int16_t moveStep = 0;
unsigned long ans ;
SYSTEM_Initialize();
// Enable the Global Interrupts
INTERRUPT_GlobalInterruptEnable();
// Enable the Peripheral Interrupts
INTERRUPT_PeripheralInterruptEnable();
//割り込みハンドラの設定
IOCBF0_SetInterruptHandler(limitpos_int);//POS_LIMIT
IOCBF3_SetInterruptHandler(org_btn);//ORG_BTN
IOCBF7_SetInterruptHandler(flag_int);//FLAG
//液晶モジュールLCD1602Aの初期化
lcd_Init();
//EUSART受信バッファ初期化
memset(strBuf, '\0', sizeof(strBuf));
//SPI通信の初期化
SPI1_Open(SPI1_DEFAULT);
//モータードライバの初期化
ans = L6470_Init() ;
//メインループ
while (1)
{
if(EUSART_is_rx_ready()){ //受信したデータがあるか
rxData = EUSART_Read(); //受信データを取得
if( rxData == '\n' ){
lcd_INST(0x01); //ディスプレイクリア
Wait(2);
int i = 0;
int p = 0;
while(strBuf[i]!='\0'){
if( (strBuf[i]>='0' && strBuf[i]<='9') || strBuf[i]=='-'){
strBuf[p++]=strBuf[i];
}
i++;
}
strBuf[p++]='\0';
pos = atoi(strBuf);
lcd_SetCursor(0,0);//カーソル移動
printf("POS=%d",pos);
//-------------------------------------------------------------------
//ステッピングモーターの制御処理を記述
//1600ステップで1回転
//posとmoveStepを分けているのは機械座標の換算の為、ここでは換算していない
//-------------------------------------------------------------------
moveStep = pos;
if( RB0 == 0){
L6470_Move(p2offset>0?Forward:Reverse,(unsigned long)abs(moveStep)) ;
}
while( L6470_BUSY==0 ) ; // コマンド実行中なら待つ
Wait(100);
//--------------------------------------
lcd_SetCursor(1,0);//カーソルを2行目に移動
printf("moveStep=%d",moveStep);
srtBufPointer = 0;
memset(strBuf, '\0', sizeof(strBuf));
}else{
lcd_SetCursor(0,14);
printf("%c",rxData);
strBuf[srtBufPointer] = rxData;//受信データーをバッファに追加
srtBufPointer++;
if( srtBufPointer > 19){//19文字を超えても「CR」未受信ならばエラー表示
lcd_SetCursor(1,0);
printf("Er1");
srtBufPointer = 0;
memset(strBuf, '\0', sizeof(strBuf));
}
}
}
}
}
//RB0(POS_LIMIT)の割り込み
void limitpos_int(void){
//即時停止
L6470_Stop(3);
lcd_INST(0x01); //ディスプレイクリア
Wait(2);
lcd_SetCursor(0,0);//カーソルを1行目に移動
printf("LIMIT!!");
Wait(100);
}
//モータードライバからの割り込み
void flag_int(void){
int alm = L6470_ALARM();
lcd_INST(0x01); //ディスプレイクリア
Wait(2);
lcd_SetCursor(1,0);//カーソルを2行目に移動
printf("FLAG!! %d",alm);
Wait(100);
}
//原点復帰ボタン
void org_btn(void){
unsigned int value0 = 0;//原点復帰時の移動量
unsigned int value1 = 0;//1回転で+1
lcd_INST(0x01); //ディスプレイクリア
Wait(2);
//LIMITセンサー割り込み無効
IOCBNbits.IOCBN0 = 0;
IOCBPbits.IOCBP0 = 0;
// ステップモード変更 1/64
L6470_Stop(3);
L6470_SetStep(MICROSTEP64);
while( RB0 == 0){
//回転
L6470_Move(Reverse,1) ;//-5μm移動 (1/64ステップ 12800pluse/1回転 M6ねじピッチ1mm)
while( L6470_BUSY==0 ) ; // コマンド実行中なら待つ
lcd_SetCursor(0,0);//カーソルを1行目に移動
printf("MOVE=%d step ",++value0);
if(value0>12800){
value0=0;
value1++;
if( value1 > 10){
lcd_SetCursor(1,0);//カーソルを1行目に移動
printf("ORG ERROR");
break;
}
}
}
// ステップモードの戻し
L6470_Stop(3);
L6470_SetStep(MICROSTEP8);
if(value1<=10){
lcd_INST(0x01); //ディスプレイクリア
Wait(2);
lcd_SetCursor(0,0);//カーソルを1行目に移動
printf("ORG DONE");
int alarm = L6470_ALARM();
if( alarm != 0){
lcd_SetCursor(1,0);
printf("ALARM=%d",L6470_ALARM());
}
}
Wait(1000);
//LIMITセンサー割り込み有効
IOCBNbits.IOCBN0 = 0;
IOCBPbits.IOCBP0 = 1;
position=0;//絶対値リセット
}
/*
//シリアルへ文字列出力
void EUSART_StringWrite(char var[] ){
for( int i=0;i<sizeof(var);++i){
EUSART_Write(var[i]);
}
}
*/
// num x 10msの間delayさせる
void Wait(int num)
{
// numで指定した回数だけ繰り返す
do {
__delay_ms(1); // 10msプログラムの一時停止
} while(--num > 0);
}
/**
End of File
*/
-------------2022/02/19----------続きは後日