BRML Drivers


Linmot Driver

This driver support controlling a Linmot using the LinRS serial protocol. It has been tested using a Linmot E1250-EC-UC drive, but should be compatible with more drives that support the LinRS protocol. In our setup a standard RS232-to-USB adapter is used to connect the serial port of the drive to a PC.

The driver is provided by the BRML.Drivers.LinmotT type. An instance of this type is fully thread-safe. Movement requests will be queued and executed in arrival order.

Drive parameter configuration

Using the LinMot-Talk software the LinRS drive parameters must be configured as follows:

  • LinRS -> Dis-/Enable: Enable
  • LinRS -> RS Config -> Stop Bit: 1
  • LinRS -> RS Config -> Parity: None
  • LinRS -> Protocol Config -> MACID: as desired
  • LinRS -> Protocol Config -> Checksum: None
  • LinRS -> Protocol Config -> MC Response Configuration: Enable the following: Communication State, Status Word, State Var, Monitoring Channel 1. Disable all others.
  • LinRS -> Protocol Config -> MC Response Configuration -> Channel 1 UPID: 1B8Dh (Actual Position)

Note the value of the variable LinRS -> MACID as you will need to specify it in the driver configuration.

Driver configuration

Instantiating the driver requires providing a configuration record of type BRML.Drivers.LinmotCfgT.

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
open BRML.Drivers

let cfg : LinmotCfgT = {
    PortName       = "COM6"    // adjust
    PortBaud       = 57600     // adjust
    Id             = 0x11      // adjust
    DefaultVel     = 50.0
    DefaultAccel   = 200.0    
}

PortName is the serial port name. PortBaud must match the baud rate configured in the drive, using the LinRS -> RS Config -> Baud Rate parameters. Id must match the drive variable LinRS -> MACID. DefaultVel specifies the default movement velocity in \(\mathrm{mm}/\mathrm{s}\). DefaultAccel specifies the default acceleration and deceleration in \(\mathrm{mm}/\mathrm{s^2}\).

Driver instance

We can now instantiate the driver.

1: 
let linmot = new LinmotT (cfg)

Initialization and checking of communication is performed automatically.

All driver instance methods return an Async<_> instance. You can perform asynchronous control or pipe all results into the Async.RunSynchronously to perform immediate command execution and wait for the operation to finish before your program continues.

Homing

The drive must be homed (finding the zero reference position) before movement commands can be send. Use the linmot.Home method for that. By default, homing is only performed if the drive is currently not homed. You can override this behavior and force homing, by specifying an additional parameter with the value true.

1: 
linmot.Home () |> Async.RunSynchronously

Getting the current position

The current position in \(\mathrm{mm}\) is available in the linmot.Pos property.

1: 
printfn "The Linmot is currently at %.3f mm." linmot.Pos

Moving

Use the linmot.DriveTo method to move the Linmot to the specified position in \(\mathrm{mm}\).

1: 
linmot.DriveTo -10. (* mm *) |> Async.RunSynchronously

You can specify additional parameters corresponding to the velocity and acceleration.

1: 
linmot.DriveTo (-20. (* mm *), 10. (* mm/s *), 100. (* mm/s^2 *)) |> Async.RunSynchronously

Power

You can turn motor power off, by calling the linmot.Power method with a false argument.

1: 
linmot.Power false |> Async.RunSynchronously

The slider can now move freely. You can still use the linmot.Pos property to obtain the actual position.

Specify a true argument to linmot.Power to re-enable the motor.

1: 
linmot.Power true |> Async.RunSynchronously

It is not necessary to home the motor again after toggling power off and then on.

Close the driver

You should dispose the driver instance when not using it anymore.

1: 
linmot.Dispose()

This will close the serial port.

val cfg : obj

Full name: Linmot.cfg
val linmot : obj

Full name: Linmot.linmot
Multiple items
type Async
static member AsBeginEnd : computation:('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit)
static member AwaitEvent : event:IEvent<'Del,'T> * ?cancelAction:(unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate)
static member AwaitIAsyncResult : iar:IAsyncResult * ?millisecondsTimeout:int -> Async<bool>
static member AwaitTask : task:Task -> Async<unit>
static member AwaitTask : task:Task<'T> -> Async<'T>
static member AwaitWaitHandle : waitHandle:WaitHandle * ?millisecondsTimeout:int -> Async<bool>
static member CancelDefaultToken : unit -> unit
static member Catch : computation:Async<'T> -> Async<Choice<'T,exn>>
static member FromBeginEnd : beginAction:(AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg:'Arg1 * beginAction:('Arg1 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * beginAction:('Arg1 * 'Arg2 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromBeginEnd : arg1:'Arg1 * arg2:'Arg2 * arg3:'Arg3 * beginAction:('Arg1 * 'Arg2 * 'Arg3 * AsyncCallback * obj -> IAsyncResult) * endAction:(IAsyncResult -> 'T) * ?cancelAction:(unit -> unit) -> Async<'T>
static member FromContinuations : callback:(('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T>
static member Ignore : computation:Async<'T> -> Async<unit>
static member OnCancel : interruption:(unit -> unit) -> Async<IDisposable>
static member Parallel : computations:seq<Async<'T>> -> Async<'T []>
static member RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:CancellationToken -> 'T
static member Sleep : millisecondsDueTime:int -> Async<unit>
static member Start : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions * ?cancellationToken:CancellationToken -> Task<'T>
static member StartChild : computation:Async<'T> * ?millisecondsTimeout:int -> Async<Async<'T>>
static member StartChildAsTask : computation:Async<'T> * ?taskCreationOptions:TaskCreationOptions -> Async<Task<'T>>
static member StartImmediate : computation:Async<unit> * ?cancellationToken:CancellationToken -> unit
static member StartWithContinuations : computation:Async<'T> * continuation:('T -> unit) * exceptionContinuation:(exn -> unit) * cancellationContinuation:(OperationCanceledException -> unit) * ?cancellationToken:CancellationToken -> unit
static member SwitchToContext : syncContext:SynchronizationContext -> Async<unit>
static member SwitchToNewThread : unit -> Async<unit>
static member SwitchToThreadPool : unit -> Async<unit>
static member TryCancelled : computation:Async<'T> * compensation:(OperationCanceledException -> unit) -> Async<'T>
static member CancellationToken : Async<CancellationToken>
static member DefaultCancellationToken : CancellationToken

Full name: Microsoft.FSharp.Control.Async

--------------------
type Async<'T>

Full name: Microsoft.FSharp.Control.Async<_>
static member Async.RunSynchronously : computation:Async<'T> * ?timeout:int * ?cancellationToken:System.Threading.CancellationToken -> 'T
val printfn : format:Printf.TextWriterFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.printfn
Fork me on GitHub