Multiple Serial Port

Hello,

is it possible with XOJO to write multiple serial ports at same time?

Br
Sebastian

Definitely possible and i have done it

Ok. Is there an example available?

You could look into xojo examples.

1 Like

I’ve found nothing…

Or is it somehow possible to run some tasks in parallel? For example I have three DMM’s which are connected via serial port and SCPI and I want to measure 4 diff currents. So my plan is to start to measure with DMM #1 and in parallel DMM #2 & DMM #3.

Examples → Serial → Communication

If you have a number of essentially identical ports, then I’d use a thread for each. Set up the thread to work with a single port and feed each thread with the parameters it needs. See:

Example → Advanced → Thread

Not difficult at all, and since everything is event-driven, there’s not really any need to use threads. You need a SerialConnection for each device you want to talk to. I usually subclass serial connection - in your case you’d make a class called DMM and set its super to SerialConnection. In the DataReceived event I add the new data to a buffer string and set a brief timer to call a parsing routine that parses the buffer. You don’t want to do your parsing in the DataReceived event - use a timer so that the parsing and subsequent handling gets done on the main thread, otherwise DataReceived may miss data. The parsing routine can raise events based on the received data. Here’s one for a SCPI-controlled ground bond tester I did recently:

Set sends a SCPI command, GET, sends a SCPI query.

You’ll also need a routine that scans the host’s serial ports and presents the user with a list of available devices and a “Connect” button. In some cases you can make the connection automatic based on USB PID/VID. The Xojo examples show a simple port scanner.

1 Like

Thanks. This helps a lot. I can already send by using a method set a command but I have problems to understand how to receive/get the data. With the Event Handler DataReceived its no problem. But I don’t know how to get/parse the data without?

Is it possible to share your GroundBondTester? So that I can understand how it works. I’m new to XOJO and have to learn much.

Here’s the code in DataReceived:

// The point of the poll timer is not to delay, but to get the parsing code out of the DataAvailable event.

RXBuffer = RXBuffer + Me.ReadAll
PollTimer.Reset // PollTimer.Action is handled by ParseRX

RXBuffer and PollTimer are properties of the subclassed SerialDevice.

Here’s ParseRX, which is the handler for PollTimer’s Action event:

// This is the handler for PollTimer, which is a one-shot fired by our DataReceived event. RegEx is great for parsing received serial data, because you don't have to worry about data alignment or scanning the data yourself.

Dim rgx As new RegEx
rgx.SearchPattern = ".+\r\n" // 1 or more characters followed by CR
dim rgm As RegExMatch

Dim RXMsg As String

rgm=rgx.Search(RXBuffer)
If rgm <> nil then
  
  RXBuffer = "" // Clear the buffer
  
  if rgm.SubExpressionCount > 0 then
    RXMsg = rgm.SubExpressionString(0).Replace(chr(13)+chr(10),"")
    
    Select Case LastGET // Cases in order of query sends
    Case SCPI.STATUS
      
      If RXMSG = "Stopped" then
        Status = RXMsg
        RaiseEvent Stopped
        
      ElseIf RXMsg = "Running" Then
        Status = RXMsg
        RaiseEvent Running
      End
      
    Case SCPI.RESISTANCE
      Resistance = Val(RXMsg)
      RaiseEvent GotResistance(Resistance)
    Case SCPI.CURRENT
      Current = Val(RXMsg)
      RaiseEvent GotCurrent(Current)
    Case SCPI.TIME
      Time = Val(RXMsg)
      RaiseEvent GotTime(Time) // Time is the last one and will call FinishTest
    End Select
    
  End
End

Here’s the constructor for the class:

// Polltimer is a one-shot, fired by DataAvailable, and serves simply to get the buffer parsing code out of the
// DataAvailable event.

PollTimer = new Timer
PollTimer.Period = PollTime 
PollTimer.Mode = timer.ModeSingle
PollTimer.Enabled = True
AddHandler PollTimer.Action, AddressOf ParseRX

Thanks a lot. It’s nearly working as exptected. But I have one more question. If I write to the DMM I expect a response. In my case I write three commands to the DMM but I got then one string back from the buffer. This is not I want. I want to write a command and get back the response and then write the next command. How can I do this? Any idea?

Send one command at a time. The sent command is stored in LastGET, so that when you receive the response, a Select Case statement can branch on LastGET to decide what to do with the response. My ground bond test app is for production test, so I always send the same commands in the same sequence, and I made a simple state machine that sequences the test using the events GotResistance, GotCurrent, etc., each of which sends the next command. A more general application might have one event “GotResponse”, with the Select Case statement and logic in the main window’s handler for that event.

1 Like

Thanks. I thought to write on the 3 DMM’s and wait for their reponse. If I get no response in a specific time a timeout should occur. What do you think? Is this possible?

Sure, easy-peasy. Add a timer property to your DMM object and instantiate it in the constructor, with its mode sent to single (one-shot). Make a handler method for the timer’s Action event, in which you raise a Timeout event added to your DMM class. When you send a query (GET) message to the meter, restart the timer. You will have 3 DMM objects in your window and you can write commands to all of them. When the responses come in or timeouts occur, their corresponding events will fire, and in those events in your window you can add code to deal with those results.