Search code examples
.netserial-portmotionzaber

Script Zaber devices on multiple serial ports


Is it possible to connect Zaber devices to more than one serial port and control them all from a single script? The script is running in Zaber Console, and should be able to coordinate motion between devices on either port.


Solution

  • Yes, you can open more serial ports in a script. You just have to duplicate all the configuration that our Zaber Console program usually does for you. Once the serial port is open, you can use the conversation objects normally. To coordinate movement between two devices, you use conversation topic objects to wait for responses. For more details, read the Zaber library help file. You can find it in the script editor's help menu.

    // Example C# script showing how to open a second serial port and coordinate 
    // moves between the two.
    #template(methods)
    
    public override void Run()
    {
        // First port is the one that Zaber Console has already opened.
        var portFacade1 = PortFacade;
        // Now, we're going to open COM2 in the script.
        // The using block makes sure we don't leave it open.
        using (var portFacade2 = CreatePortFacade())
        {
            portFacade2.Open("COM2");
    
            // Start a conversation with a device on each port.
            // Note that the device numbers can be the same because they're on
            // separate ports.
            var conversation1 = portFacade1.GetConversation(1);
            var conversation2 = portFacade2.GetConversation(1);
    
            while ( ! IsCanceled)
            {
                MoveBoth(conversation1, conversation2, 0);
                MoveBoth(conversation1, conversation2, 10000);
            }
        }
    }
    
    private void MoveBoth(
        Conversation conversation1, 
        Conversation conversation2, 
        int position)
    {
        // Start a topic to wait for the response
        var topic = conversation1.StartTopic();
        // Send the command using Device.Send() instead of Request()
        // Note the topic.MessageId parameter to coordinate request and response
        conversation1.Device.Send(
                Command.MoveAbsolute, 
                position, 
                topic.MessageId);
    
        // While c1 is moving, also request c2 to move. This one just uses
        // Request() because we want to wait until it finishes.
        conversation2.Request(Command.MoveAbsolute, position);
    
        // We know c2 has finished moving, so now wait until c1 finishes.
        topic.Wait();
        topic.Validate();
    }
    
    private ZaberPortFacade CreatePortFacade()
    {
        var packetConverter = new PacketConverter();
        packetConverter.MillisecondsTimeout = 50;
        var defaultDeviceType = new DeviceType();
        defaultDeviceType.Commands = new List<CommandInfo>();
        var portFacade = new ZaberPortFacade();
        portFacade.DefaultDeviceType = defaultDeviceType;
        portFacade.QueryTimeout = 1000;
        portFacade.Port = new TSeriesPort(
            new System.IO.Ports.SerialPort(), 
            packetConverter);
        portFacade.DeviceTypes = new List<DeviceType>();
        return portFacade;
    }