エクセルVBAでARDUINOにシリアル通信する

    エクセルVBA to ARDUINO

 次の記事を参考にさせて頂き、エクセルVBAからARDUINOへのシリアル通信を行ってみます。WindowsAPIを使ってシリアル通信を行います。
【Excel VBAでRS-232C通信】  
 https://qiita.com/pbjpkas/items/f81947ce38941356ebe4

 先日、ARDUINOとCNC‐SHIELD を用いたステッピングモーター駆動について書きました。パソコンからシリアル通信でARDUINOにGコード送信し、モーターを動かすというものでした。途中経路を考慮しない位置決めの場合、エクセルシートのセルに入力された座標に基づき “G90G0X***.**Y***.**” のフォーマットでシリアル送信することで、連続的位置決めが出来そうです。先ずエクセルVBAからシリアル通信する方法について調べました。

    プログラム概要

 動作は次の図の通り、エクセルシート上の送信データ欄に文字を入力し、右側の“送信ボタン”をクリックするとUSB(RS232C)を介して ARDUINO にシリアルデータ送信します。ARDUINOは受信したデータの先頭に [RECEIVED] という文字を付与し返送します。エクセル側では受信データをエクセルシートに表示します。(赤線枠内)


    エクセルVBA プログラム

 次はエクセルVBAのシリアル通信を行うプログラムです。
 Public Function StartSerialComm(str_TX As String, com_port As String) に送信データとポート番号を指定して、呼び出すとデータを送信し、返信データを受信することが出来ます。

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

 呼び出しは次の様な感じです。シートに貼り付けたコマンドボタンのクリックイベントで実行します。

Option Explicit

Private Sub CommandButton1_Click()
    Dim sht
    Dim res
    
    sht = ActiveSheet.Name
    
    Worksheets(sht).Cells(3, 3).Value = ""
    
    res = StartSerialComm(Trim(Worksheets(sht).Cells(2, 3).Value), "COM5")
    
    Worksheets(sht).Cells(3, 3).Value = res
    
End Sub


    ARDUINO プログラム

 ARDUINO 側のプログラムです。

void setup() {
  Serial.begin(9600);
  Serial.setTimeout(15000UL);
  Serial.println("Start!");
}

void loop() {
  // put your main code here, to run repeatedly:
  if( Serial.available() > 0 ){

    // \r:CR, \r\n:CRLF, \n:LF
    String str = Serial.readStringUntil('\n');
    Serial.println((String)"[RECEIVED] " + str);
  }
}


    まとめ

 バージョンアップしたWordPressに不慣れで疲れました。

「エクセルVBAでARDUINOにシリアル通信する」への1件のフィードバック

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です