Macro to summarise content from several messages

Comprehensive CAN monitor for Windows® and its add-ins: Plotter, CANdb Import, Instruments Panel, and J1939
Post Reply
PCANUser
Posts: 26
Joined: Fri 14. Dec 2012, 10:40

Macro to summarise content from several messages

Post by PCANUser » Fri 14. Dec 2012, 20:47

Hi,

We are using PCAN Explorer 5 to display a panel that shows various parameters from our device. One of the fields in the CAN message is a fault ID. If more than one fault is present the message cycles round each of the faults in turn, one at a time.

What I would like to be able to do is order the fault codes and display the associated fault text for each fault code in the panel.

I have made the basics work using a macro by writing the information to a label but I have several questions:
1. The messages are coming at 5ms intervals. VBScript seems to be struggling to keep up. Is a plug-in a possible alternative? Is there any guidance about writing a plug-in using C# for example? Can a plug-in access a component on a panel?

2. There are quite a lot of components on the panel. Is there a way to change the rate at which the panel updates (i.e. make it update slower) independently of the rate at which the messages are being received?

3. Is it possible to make a macro run automatically when a panel is loaded?

Thanks in advance for your help.
Richard

K.Wolf
Software Development
Software Development
Posts: 141
Joined: Wed 22. Sep 2010, 15:37

Re: Macro to summarise content from several messages

Post by K.Wolf » Tue 18. Dec 2012, 11:17

Hi,

1. I believe the overhead of writing an Add-in is not justified here. Yes, Add-ins can access panel components. But displaying values e.g. in a Label can only be done in the same way as in a VBS macro, by setting the value of the signal that is assigned to a Label. You cannot set the Label caption directly.

Perhaps the solution to your problem is to set up a separate Client as demonstrated in the WaitForID100 example macro, specifying a filter that exactly matches the CAN-ID of the message containing the fault ID. In this way, you would not miss any fault IDs, all relevant messages are buffered in the receive queue of the separate client.
Your macro simply reads all the messages from the queue and processes the fault IDs one by one. But you would have to decode the fault IDs yourself from the message's raw data bytes. I made a short test with a 1 ms message, absolutly no performance problem here.

2. At the moment there is no way to control the update speed of a panel. If you use CAN-based signals in your panel, every received message updates the corresponding component immediately. You could use virtual signals for some components in the panel that are updated most often, and control updating of these signals in your macro in a slower rate, for example.

3. No, you can only run a macro automatically when a project is loaded. See the "Post Load Command" property in the Project properties.

PCANUser
Posts: 26
Joined: Fri 14. Dec 2012, 10:40

Re: Macro to summarise content from several messages

Post by PCANUser » Mon 14. Jan 2013, 13:00

Thanks for the response. I am confused by your reference to the WaitForID100 example macro. Where would I find it? I can't find it anywhere in my installation and a search of your web site also turns up no hits.

I assume you are referring to a sample macro that calls the WaitId method.

Thanks,
Richard

PCANUser
Posts: 26
Joined: Fri 14. Dec 2012, 10:40

Re: Macro to summarise content from several messages

Post by PCANUser » Mon 14. Jan 2013, 13:03

I just found it. For anybody else searching for this it lives in the Sample.pem macro file.

User avatar
PEAK-Support
Sales & Support
Sales & Support
Posts: 1646
Joined: Fri 10. Sep 2010, 19:34

Re: Macro to summarise content from several messages

Post by PEAK-Support » Mon 14. Jan 2013, 13:07

Yes, in the sample.pem are a lot of sample functions implemented. Here the code of the current version:
(14th of January 2013)

Code: Select all

'FILE DESCRIPTION: Test and sample macros

Sub EnumDocuments()
'DESCRIPTION: Displays all open documents
  PrintToOutputWindow peVBSMacro
  Dim doc
  For Each doc In Documents
    PrintToOutputWindow doc.FullName
  Next
End Sub


Sub EnumWindows()
'DESCRIPTION: Displays all open windows
  Dim win
  For Each win In Windows
    PrintToOutputWindow win.Caption
  Next
End Sub


Sub SendMail()
'DESCRIPTION: Sends a test E-Mail to PEAK-System
  Dim outlook
On Error Resume Next
  Set outlook = CreateObject("Outlook.Application")
  If outlook Is Nothing Then
    MsgBox "Microsoft Outlook is not installed!",,"SendMail"
    Exit Sub
  End If
On Error GoTo 0
  Dim mail
  Dim outbox
  Dim mapi
  Dim recipient
  Dim address
  address = "support@peak-system.com"
  address = InputBox("Send a test E-Mail to:", "SendMail", address)
  If address = "" Then
    Exit Sub
  End If
  Set mapi = outlook.GetNameSpace("MAPI")
  Set outbox = mapi.GetDefaultFolder(4)
  Set mail = outbox.Items.Add(0)
  Set recipient = mail.Recipients.Add("support@peak-system.com")
  recipient.Type = 1
  mail.Subject = "Test"
  mail.Body = "This is a PCAN-Explorer 5 macro test."
  mail.Send
End Sub


Sub CreateOutputPane()
'DESCRIPTION: Creates a new pane in the Output window  
  Dim win
  Dim OutputWin
  Dim pane
  Set win = Windows(peWindowKindOutput)
  win.IsVisible = True
  Set OutputWin = win.Object
  Set pane = OutputWin.OutputWindowPanes("My pane")
  If pane Is Nothing Then
    Set pane = OutputWin.OutputWindowPanes.Add("My pane")
  End If
  pane.Activate		'Make pane visible
  pane.OutputString("This is a text" & vbCrLf)
End Sub


Sub NewClientSend()
'DESCRIPTION: Sends CAN messages using a new PCAN client
  Dim UseConn, conn
  ' Find the first enabled connection in the project that uses the CAN protocol
  Set UseConn = Nothing
  For Each conn In Connections
    If conn.IsEnabled And conn.Protocol = peProtocolCAN Then
      Set UseConn = conn
      Exit For
    End If
  Next 
  If UseConn Is Nothing Then
    MsgBox "Project does not contain any enabled CAN connections"
    Exit Sub
  End If

  ' Create a new client and connect it to the same Net that the
  '  found connection uses
  Dim MyClient, PcanConn
  Set MyClient = CreateObject("PCAN3.PCANClient")
  MyClient.Device = UseConn.Device
  MyClient.Name = "Macro"
  Set PcanConn = MyClient.Connections.Add(UseConn.CommunicationObject.NetName)

  ' Now create and initialize a new transmit message
  Dim msg
  Set msg = MyClient.Messages.Add
  timestamp = MyClient.GetSystemTime + 1000
  With msg
    .ID = &H100
    .DLC = 4
    .MsgType = pcanMsgTypeExtended
    .Data(0) = &H11
    .Data(1) = &H22
    .Data(2) = &H33
  End With
  for i = 1 To 20
    msg.Data(3) = i
    msg.Write PcanConn, timestamp
    timestamp = timestamp + 500
  next
  ' Wait until all messages have been sent before finishing macro,
  '  since this would terminate the client and delete all messages
  '  that are still in the queue
  While not MyClient.XmtQueueEmpty
    Wait 500
  Wend
  Wait 500
End Sub

Sub WaitForID100()
'DESCRIPTION: Waits until CAN-ID 100h is received
  ' To view the output messages of this macro, open the Output Window and
  '  select the "Macro" tab
  Dim UseConn, conn
  ' Find the first enabled connection in the project that uses the CAN protocol
  Set UseConn = Nothing
  For Each conn In Connections
    If conn.IsEnabled And conn.Protocol = peProtocolCAN Then
      Set UseConn = conn
      Exit For
    End If
  Next 
  If UseConn Is Nothing Then
    MsgBox "Project does not contain any enabled CAN connections"
    Exit Sub
  End If

  ' Create a new client and connect it to the same Net that the
  '  found connection uses
  Dim MyClient, PcanConn
  Set MyClient = CreateObject("PCAN3.PCANClient")
  MyClient.Name = "Macro"
  MyClient.Device = UseConn.Device
  Set PcanConn = MyClient.Connections.Add(UseConn.CommunicationObject.NetName)

  PcanConn.RegisterMsg &H100, &H200, False, False
  i = 0
  Dim RcvMsg
  Set RcvMsg = MyClient.Messages.Add
  Do
    Do While not RcvMsg.Read
      ' Wait for a received message
    Loop
    If RcvMsg.LastError = pcanErrorOk Then
      PrintToOutputWindow "Received !"
      i = i + 1
    End IF
  Loop While RcvMsg.ID <> &H100
  PrintToOutputWindow "Finished, " & CStr(i) & " messages received !"
End Sub

Sub LosslessTrace()
'DESCRIPTION: Traces messages without losses and stores the data in multiple trace files
  
  ' Modify as required
  const DefaultDestDir = "c:\Trace"
  const DefaultConnection = "TestNet@pcan_pci"
  const MessagesPerTracer = 100000

  ' Explicit Variable declarations
  Dim CurrentTracer, NextTracer
  Dim doc, wnd
  Dim TracerNumber, NewTop
  Dim IsRunning
  Dim DestDir, Connection

  ' Prompt for the destination directory
  DestDir = InputBox("Destination Directory:", "LosslessTrace", DefaultDestDir)
  If DestDir = "" Then Exit Sub

  ' Make sure the selected directory exists
  Dim fso
  Set fso = CreateObject("Scripting.FileSystemObject")
  If Not fso.FolderExists(DestDir) Then
    MsgBox "The selected directory does not exist!",,"LosslessTrace"
    Exit Sub
  End If

  Set NextTracer = Nothing
  IsRunning = True
  TracerNumber = 0
  NewTop = 250

  If ActiveProject Is Nothing Then
    ' Create and configure a new project
    NewProject "LoslessTrace", ""
    ' Prompt for connection
    Connection = InputBox("Select Connection:", "LosslessTrace", DefaultConnection)
    Dim conn
    Set conn = Connections.Add(Connection)
    conn.IsEnabled = True
    If Not conn.IsEnabled Then
      MsgBox "Error while enabling the connection!",,"LosslessTrace"
      Exit Sub
    End If
  End If

  Set doc = Documents.Add(peDocumentKindTrace)
  Set wnd = doc.ActiveWindow
  wnd.Left = 0
  wnd.Top = 0
  wnd.Height = 250
  wnd.Width = 500

  Set CurrentTracer = wnd.Object.Tracer
  CurrentTracer.BufferType = peTraceBufferTypeLinear
  CurrentTracer.BufferSize = MessagesPerTracer
  CurrentTracer.Start

  Do While IsRunning

    ' Tracer records data until the filling level reaches 95%
    Do While IsRunning And (CurrentTracer.FillingLevel < 95)

      ' Prepare next tracer at a filling level of 90%
      If (NextTracer Is Nothing) And (CurrentTracer.FillingLevel > 90) Then
        Set doc = Documents.Add(peDocumentKindTrace)
        Set wnd = doc.ActiveWindow
        ' Arrange new tracer window
        wnd.Left = 0
        wnd.Top = NewTop
        wnd.Height = 250
        wnd.Width = 500
        if (NewTop = 0) Then
          NewTop = 250
        Else
          NewTop = 0
        End If
        Set NextTracer = wnd.Object.Tracer
        NextTracer.BufferType = peTraceBufferTypeLinear
        NextTracer.BufferSize = MessagesPerTracer
      End If
      Wait 50
      IsRunning = CurrentTracer.TraceState = peTraceStarted
    Loop
    If IsRunning Then
      NextTracer.Start
      CurrentTracer.Stop
    End If
  
    ' Save data of current tracer
    If CurrentTracer.FillingLevel > 0 Then
      TracerNumber = TracerNumber + 1
      CurrentTracer.Document.Save DestDir & "\Trace" & TracerNumber & ".trc"
      ' Wait until data is saved
      Do While CurrentTracer.TraceState = peTraceSaving
        Wait 10
      Loop
      Wait 100
    End If
    ' Close old tracer window
    CurrentTracer.Document.Close peSaveChangesNo
  
    Set CurrentTracer = NextTracer
    Set NextTracer = Nothing
  Loop

End Sub
--------------------------------
PEAK-System Technik
Technical Support Team
support[at]peak-system.com
-------------------------------

Post Reply