エクセルでステッピングモーター位置決め

エクセルでステッピングモーター位置決め

 ARDUINO CNC-SHILDの使い方とパソコンからARDUINOにシリアル通信でGコードを送信するGRBLの使い方について投稿しました。また、パソコンからエクセルVBAを使って、ARDUINOにシリアル通信する方法についても投稿しました。
 これら投稿の内容をベースに、エクセルからARDUINOにGコード送信し、ステッピングモーターの位置決めを行ってみます。
 実際にスライドテーブルがあると良いのですが、準備が大変なので、モーターの角度で簡易的に判断したいと思います。

エクセルの準備(関連投稿記事)

 既に投稿した下表の記事の通り、配線・設定とエクセルVBAでシリアル通信できるようにAPI設定します。

【関連投稿記事】

番号 関連投稿
  ARDUINOでCNCシールドを使う
  ARDUINOでのGRBLの使い方
  エクセルVBAでARDUINOにシリアル通信する

エクセルプログラム概要

 次の図は今回作成したプログラムのエクセルシートです。
 シート上にコマンドボタンを3つ配置し、①原点復帰,②増量移動,③連続運転(絶対位置指定)の3つの動作を実行します。
 基本的には過去の投稿記事に書いた内容をエクセルVBAで連続的に位置決め出来る様にしたものです。
 

 図の通り、増量指定移動では、X軸(3列),Y軸(4列)に現在位置に対する増加量(単位:mm)を指定し移動します。“増量移動”ボタンをクリックすると、Gコード(G91X**Y**)を生成しARDUINO側にシリアル送信します。引き続き、” ? ” コマンドでARDUINO側ステータスを確認し、“Idle” (停止)状態データ受信後、Gコード(G92X0Y0)を送信し動作原点を初期化します。

 同様に連続運転では、X軸(3列),Y軸(4列)に 指定した絶対位置に対応する Gコード(G90X**Y**)を生成し、ARDUINO側に送信します。連続運転では最大10ヶ所の位置を登録することが出来、1~10の順番(2列)に位置決めを行います。位置指定が無い場合は処理を中断します。
 シート4列には送信したGコード,5列には受信した “Idle” (停止)状態データ を表示します。今回、実際にはスライドテーブルがありませんので、ステッピングモーターの回転角度で適切に処理されていることを確認する為に、指定移動量を40(mm/回転)として回転角度に変換表示しています。

ステッピングモーター位置決め動画

 動画内の矢印(↑)が上向き状態を0度として、右回りに回転すると角度が増加します。

 動画は次エクセルシートの通り、位置決めをしています。 
 指定位置に対して、回転方向・量は決まるので、必ずしも動画内の表示角度に対して最短方向・量にはなりません。

プログラム

 エクセルVBAのプログラムを掲載します。

Option Explicit

Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)



'原点復帰
Private Sub CommandButton3_Click()
    Dim res
    Dim msg
    Dim G_CD As String
    Dim sht
    
    sht = ActiveSheet.Name
    
    Worksheets(sht).Range("E1:F1").ClearContents
    
    G_CD = "$H"
    Worksheets(sht).Cells(1, 5).Value = G_CD
    
    res = StartSerialComm(G_CD, "COM4")

  
    Do
        Sleep (500)
        DoEvents
        
        res = StartSerialComm("?", "COM4")
  
        If InStr(res, "Idle") Then
            Exit Do
        End If
        
    Loop
  
    res = Replace(Replace(Replace(res, "ok", ""), ")", ""), "(", "")
    
    Worksheets(sht).Cells(1, 6).Value = res
  
    msg = MsgBox("原点復帰を終了しました。" + vbCrLf + vbCrLf + "(" + res + ")", vbOKOnly)
    
End Sub

'増量移動
Private Sub CommandButton1_Click()

      
    Dim sht
    Dim res
    Dim pos_X, pos_Y
    Dim G_CD As String

    
    
    sht = ActiveSheet.Name
    
    Worksheets(sht).Range("E5:F5").ClearContents
    

    pos_X = Trim(Worksheets(sht).Cells(5, 3).Value)
    pos_Y = Trim(Worksheets(sht).Cells(5, 4).Value)
        
    If pos_X = "" & pos_Y = "" Then Exit Sub
        
    If pos_X = "" Then pos_X = "0"
    If pos_Y = "" Then pos_Y = "0"
        
        
    G_CD = "G91G0X" & pos_X & "Y" & pos_Y
    Worksheets(sht).Cells(5, 5).Value = G_CD
            
    res = StartSerialComm(G_CD, "COM4")

    Do
        Sleep (500)
        DoEvents
        
        res = StartSerialComm("?", "COM4")
  
        If InStr(res, "Idle") Then
            Exit Do
        End If
    Loop
  
    res = StartSerialComm("G90G92X0Y0", "COM4")
    
    Do
        Sleep (200)
        DoEvents
        
        res = StartSerialComm("?", "COM4")
  
        If InStr(res, "Idle") Then
            Exit Do
        End If
    Loop
 
    Worksheets(sht).Cells(5, 6).Value = res

    MsgBox "増量運転完了", vbOKOnly

End Sub



'連続運転
Private Sub CommandButton2_Click()
    
    Dim sht
    Dim res
    Dim pos_X, pos_Y
    Dim G_CD As String
    Dim ln_CNT
    
    
    sht = ActiveSheet.Name
    
    Worksheets(sht).Range("E8:F2000").ClearContents
    
    ln_CNT = 0
    
    Do
        pos_X = Trim(Worksheets(sht).Cells(8 + ln_CNT, 3).Value)
        pos_Y = Trim(Worksheets(sht).Cells(8 + ln_CNT, 4).Value)
        
        If pos_X = "" Or pos_Y = "" Then Exit Do
        
        G_CD = "G90G0X" & pos_X & "Y" & pos_Y
        Worksheets(sht).Cells(8 + ln_CNT, 5).Value = G_CD
        
        res = StartSerialComm(G_CD, "COM4")

        Do
            Sleep (500)
            DoEvents
        
            res = StartSerialComm("?", "COM4")
  
            If InStr(res, "Idle") Then
                Exit Do
            End If
        Loop
  
        Worksheets(sht).Cells(8 + ln_CNT, 6).Value = res

        DoEvents
        ln_CNT = ln_CNT + 1
        
        If ln_CNT >= 10 Then Exit Do
    Loop
    
    MsgBox "連続運転完了(" & Trim(Str(ln_CNT)) & ")", vbOKOnly
    
End Sub

 シリアル送信(RS-232C)API,関数定義部のプログラムです。VBAの標準モジュールに追加します。

Option Explicit

Private Declare Function CreateFile Lib "kernel32" Alias "CreateFileA" _
   (ByVal lpFileName As String, _
    ByVal dwDesiredAccess As Long, _
    ByVal dwShareMode As Long, _
    ByVal lpSecurityAttributes As Long, _
    ByVal dwCreationDisposition As Long, _
    ByVal dwFlagsAndAttributes As Long, _
    ByVal hTemplateFile As Long) As Long

Private Declare Sub CloseHandle Lib "kernel32" (ByVal hObject As Long)

Private Declare Sub ReadFile Lib "kernel32" _
   (ByVal hFile As Long, _
    ByVal lpBuffer As String, _
    ByVal nNumberOfBytesToRead As Long, _
          lpNumberOfBytesRead As Long, _
    ByVal lpOverlapped As Long)

Private Declare Sub WriteFile Lib "kernel32" _
   (ByVal hFile As Long, _
    ByVal lpBuffer As String, _
    ByVal nNumberOfBytesToWrite As Long, _
          lpNumberOfBytesWritten As Long, _
    ByVal lpOverlapped As Long)

Private Declare Function SetCommState Lib "kernel32" (ByVal hFile As Long, ByRef lpDCB As DCB) As Long
Private Declare Sub SetCommTimeouts Lib "kernel32" (ByVal hFile As Long, lpCommTimeouts As COMMTIMEOUTS)

'SetCommState
Private Type DCB
    DCBlength As Long
    BaudRate As Long
    Fields As Long
    wReserved As Integer
    XonLim As Integer
    XoffLim As Integer
    ByteSize As Byte
    Parity As Byte
    StopBits As Byte
    XonChar As Byte
    XoffChar As Byte
    ErrorChar As Byte
    EofChar As Byte
    EvtChar As Byte
    wReserved1 As Integer
End Type

'SetCommTimeouts
Private Type COMMTIMEOUTS
    ReadIntervalTimeout As Long
    ReadTotalTimeoutMultiplier As Long
    ReadTotalTimeoutConstant As Long
    WriteTotalTimeoutMultiplier As Long
    WriteTotalTimeoutConstant As Long
End Type


'CreateFileパラメータ用定数
Private Const GENERIC_READ = (&H80000000)
Private Const GENERIC_WRITE = (&H40000000)
Private Const OPEN_EXISTING = 3


Public Function StartSerialComm(str_TX As String, com_port As String)
    Dim comPort As String
    Dim hFile As Long
    Dim cs As DCB          'CommState
    Dim ct As COMMTIMEOUTS 'CommTimeouts
    Dim length As Long
    Dim buf As String

    comPort = com_port

    'COMポートオープン
    hFile = CreateFile(comPort, GENERIC_READ Or GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0)
    If hFile = -1 Then
        StartSerialComm = "ERR_COM_OPEN"
        Exit Function
    End If

    'RS232C通信設定
    cs.BaudRate = 9600
    cs.ByteSize = 8
    cs.Parity = 0
    cs.StopBits = 0
    cs.Fields = &H3001
    SetCommState hFile, cs

    'RS232Cタイムアウト設定
    ct.ReadIntervalTimeout = 1000
    ct.ReadTotalTimeoutMultiplier = 1
    ct.ReadTotalTimeoutConstant = 500
    ct.WriteTotalTimeoutMultiplier = 1
    ct.WriteTotalTimeoutConstant = 500
    SetCommTimeouts hFile, ct

    '送信
    buf = str_TX + Chr(10)
    WriteFile hFile, buf, Len(buf), length, 0

    '受信
    buf = String(1024, vbNullChar)
    ReadFile hFile, buf, Len(buf), length, 0

    'COMポートクローズ
    CloseHandle hFile

    '受信データのパース
    buf = Replace(buf, vbNullChar, "")
    buf = Replace(buf, Chr(10), "")
    buf = Replace(buf, Chr(13), "")
    
    StartSerialComm = buf

End Function

 

まとめ

 位置決めと計測などを組み合わせて、実際に活用することも検討していきたいと思っています。