Tutorial: TMS remote control

This page describes how to remotely control the TMS parameters and trigger the various TMS machines available at Campus Biotech: MagStim Bistim (left), MagStim Rapid Plus (middle), and MagVenture MagPro XP (right).

In summary, many approaches can be chosen to trigger the TMS pulse:

  • serial connection,
  • coaxial cable connected to computer parallel port
  • coaxial cable connected to CED Power3 1401.

However, various TMS parameters (amplitude, number of pulses, inter-pulse interval…) can only be modified through a direct serial connection between the computer and:

  • the TMS RS232 null-modem cable for MagVenture
  • the TMS DA26 cable for MagStim.

All the cables required to control the TMS can be found in the neuromodulation room at FCBG.

When in doubt, please contact the FCBG neuromodulation manager at neuromodulation@fcbg.ch.

Controlling the TMS using Signal

  • A conventional setup at FCBG is to trigger the Signal software (Cambridge Electronics) using the foot pedal switch connected to the CED Power3 1401 input, and then control the timing of the TMS trigger / navigation using the two digital outputs of the same Power3 1401.
  • This is very useful to precisely characterize the delay between the TMS pulse and muscle response (MEP) recorded in Signal:
    • without using any additional synchronization markers
    • without losing any potential immediate response. No serial connection is needed if the TMS parameters remain constant during the experiment.
Trigerring using Signal: necessary cables
  • Foot pedal switch connected to “Trigger port” of the Power3 1401
  • Coaxial cable between “Digital output 0” of Power3 1401 and TMS “Trigger In” port.
    • For MagStim, a simple BNC to BNC cable can be used.
    • For Magventure, use the BNC to DB9 cable available inside the facility.
  • In addition, the second Power3 1401 digital output “Digital output 1” can be used to record the coil position using BrainSight and/or synchronize this setup with any other additional stimulus.
Trigerring using Signal: Signal configuration
  • Load a pre-existing Signal configuration.

  • In the ‘output’ tab, make sure that the DIG0 line sends a square pulse some time (typically 1s) after the onset.

  • A total time of 2s is well enough to record a MEP response when the trigger happens at 1s.

  • If you are using a synchronized device (stimulus / neuronavigation), make sure a square pulse is sent on DIG1 (at the same time for BrainSight, or earlier/later depending on your stimulus timing).

  • Click on OK.

  • Then click on Run.

  • Start the acquisition using Start.

  • Make sure to record the data by ticking ‘save data to disk’.

  • You can switch between continuous or trigger mode (ie triggered by the foot pedal) by ticking / unticking trigger.

Full control using Signal: necessary cables
  • Serial port (DB9) to DA26 for MagStim
  • RS232 null-modem cable for MagVenture (connected to COM2).
Full control using Signal: Signal configuration
  • In Signal, click on ‘Preferences’ and choose ‘MagStim’ or ‘Magventure’ under ‘External control’.

  • Exit signal and restart to update the software.

  • Load your pre-existing configuration and enable ‘multiple states’ on the first tab. A new button becomes available on the fourth tab: either ‘MagStim’ or ‘MagVenture’. Click on it.

  • Specify first which machine you are working on, then specify the TMS parameters (amplitude, number of pulses, inter-pulse interval…) for each of the multiple states you want to use.

  • Test the link between the TMS and the computer using ‘Test TMS’. Press OK it this is successful, then ‘Run now’ to start.

  • You can navigate between the different predefined states by hand (clicking on them) or set up an infinite loop between them (State A > State B > State C > State A…).

  • For more complex variations of TMS parameters (ie randomized order or very long experiments), we recommend to use Matlab instead of Signal. This will be explained in the next section.

Controlling the TMS using Matlab

  • Complex / sophisticated experiment can be easily designed using Matlab, and readily combined with additional stimuli in the same single script using Psychtoolbox.
  • A serial connection is required to control the TMS parameters, while triggering the TMS can be performed using either a serial or parallel connection.
  • The parallel connection should be preferred for rigorous timing control (delay below 1ms versus 20ms via the serial port).
Serial connection: configuration
  • Connect to the MagStim BiStim via the DB9 to DA26 cable, or to the MagVenture MagPro XP via the RS232 null-modem cable. The inner cable configuration necessary to build them can be found here
  • Matlab toolboxes for TMS control (MAGIC, developed by Nigel Rogash) and wiki documentation can be found here: https://github.com/nigelrogasch/MAGIC/releases. You can ask the FCBG neuromodulation facility manager if the link is broken.
  • Import the files into your Matlab path or copy them into your working Matlab directory.
  • Find the correct COM port associated to the serial cable using Windows device manager.
Serial connection: example of MagStim code
  • Assuming the TMS is connected to COM1 (standard port if you are not using a USB to COM adapter, otherwise use windows device manager to find out), a simple piece of code for controlling the MagStim TMS with Matlab is the following:

myMS=bistim(‘COM1); % create object

myMS.connect();% connect to TMS

% Set Amplitudes & Pulse Interval (i.e. 43% 47% and 21ms)




 [err,resp]=myMS.getParameters();% retrieve coil parameters

 myMS.arm();% arm the TMS

myMS.fire();% fire the TMS (13-20ms delay)

myMS.disarm();% disarm the TMS

myMS.disconnect();% disconnect


Serial connection: example of MagVenture code
  • Assuming the TMS is connected to COM1 (standard port if you are not using a USB to COM adapter, otherwise use windows device manager to find out), a simple piece of code for controlling the MagVenture TMS with Matlab is the following:

myMV=magventure(‘COM1’); % create object

myMV.connect();% connect to TMS

myMV.arm();% arm the TMS

myMV.setAmplitude(50); % change amplitude (to 50%)

myMV.getStatus(); % get info on parameters

myMV.fire(); % fire the TMS (13-20ms delay)

myMV.disconnect(); % disconnect

  • Additional features exist (for sending a train of pulses, etc…) if necessary.


Parallel port: configuration and example code
  • Alternatively you can use the parallel port to trigger a square pulse on the coaxial cable ‘TRIG PC’ lying on the neuromodulation facility table.
  • Connect this port directly to the TMS, or to the Power3 1401 (trigger port) to replace the foot pedal switch. The latter allows you to use Signal to record MEP, while controlling the trigger timing in Matlab.



  • Simply add at the beginning of your script:


address = hex2dec(‘D020′); % address of the parallel port in the neuromodulation facility
byte = 1;
 % only the first byte of the parallel port will be activated
trig_duration = 0.0001; % in seconds (this will generate a 100 us pulse)

  • In order to trigger, use at the proper timing:

outp(address,byte);% actual triggering of the pulse.

pause(trig_duration);% pause

outp(address,0); % trigger goes back to baseline

The best of both worlds
  • Ideally, complex experiments require:
    • a serial connection to modify / update TMS parameters
    • a parallel connection to trigger the TMS when timing must be perfectly synchronized with additional stimuli.
  • Simply replace the line myMS.fire(); or myMV.fire(); in the previous examples by the parallel approach outp(address,byte);pause(trig_duration);outp(address,0); to use both.
  • Make sure you allow some time for the TMS to charge before firing the next pulse when changing parameters. 

Here are two schematic examples of controlling the MagStim BiStim and MagPro XP in the neuromodulation room and MRI facility, respectively.

Examples of TMS scripts

SICI experiment using Matlab

clear all; close all; clc;
st=input(‘Activate TMS? (1/0): ‘,’s’);
file=input(‘FileName for sequence order?: ‘,’s’);
TS=input(‘1mV amplitude(%)=’,’s’);TS=str2double(TS);

% configure trigger Int/Out

% Measurement Information (3 states here, to be randomized later)
List_amp_A=[TS round(0.8*TS) round(0.8*TS)];
List_amp_B=[0 TS TS];
List_delay=[10 3 15];
Nrepetitions = 8; Nzeros = 6;

% randomize the measurement list and save it
AmpA=[repmat(List_amp_A,[1 Nrepetitions]) zeros(1,Nzeros)];
AmpB=[repmat(List_amp_B,[1 Nrepetitions]) zeros(1,Nzeros)];
DEL=[repmat(List_delay,[1 Nrepetitions]) zeros(1,Nzeros)];
AmpA=AmpA(order); AmpB=AmpB(order); DEL=DEL(order);

% define delays
delay_preTMS = 10; % before first TMS pulse (s)
delay_betweenTMS = 5; % inbetween two measurements (s)
jitter=2; %(s)
delay_signal=1; % delay between trigger signal and trigger TMS, to be also set in signal software (s)
delay_end = 1; % delay at the end of program (s)

% ——————– Initialization of TMS single pulse ————— %
if (st == ‘1’)
myMS= bistim(‘COM1’);
myMS.setAmplitudeA(TS); % 10% for testing
myMS.setPulseInterval(3); % delay for SICI

for i=delay_preTMS:-1:1
uid = uicontrol(‘Style’, ‘text’,’String’, num2str(i), ‘FontSize’, 200, ‘ForegroundColor’, ‘b’, ‘Units’,’normalized’,’Position’, [0 0 1 1]);
disp(‘Experiment starts.’);

for loop=1:length(AmpA) % measurement loop

fprintf(‘This is measurement # %i out of %i (amplitude are %d / %d and delay is %d) ‘,loop,length(AmpA),AmpA(loop),AmpB(loop),DEL(loop));disp(‘ ‘);

if (st == ‘1’)
myMS.arm(); % make sure the device is armed

pause(max(delay_betweenTMS-delay_signal-0.2+jitter*rand(1),0)); % delay before the pulse (taking into account delay from the software Signal)

disp(‘Send trigger to Signal’) % for testing purposes
if (st == ‘1’)
sendTrigger(); % send trigger to Signal

pause(0.2+delay_signal); % (delay from the software Signal)


disp(‘Experiment has finished.’);

if (st == ‘1’)

%% subroutine for sending 1ms trigger
function sendTrigger()
pause(0.001); % 1ms trigger

Concurrent TMS-fMRI experiment using Matlab

clear all; close all; clc;
st=input(‘Activate TMS? (1/0): ‘,’s’);

% [TMS-fMRI – technical study]

% ——————– Initialization of TMS single pulse ————— %
if (st == ‘1’)

% ———————- Initialization: parameters ——————— %

% Paradigm structure = Nblocks * [Nbaseline + Nstim]
Nstim = 1;
delay_preTMS = 1;
delay_postTMS = 1;

% Auxiliary variables
a1=zeros(1,256); a2=zeros(1,2);

% ———————– Initialization: objects ———————– %

% Priority level, port setting
Priority(1); pt=hex2dec(‘2008’); 

% Keyboard queue
KbName(‘UnifyKeyNames’); a2(:)=[KbName(‘t’); KbName(‘r’)]; a1(1,a2)=1;
KbQueueCreate([],a1); KbQueueStart();

% ————————- Paradigm execution ————————– %

disp(‘experiment started.’);

for outer_loop=1:Nblocks
fprintf(‘This is block # %i’,outer_loop);disp(‘ ‘);

for kb=1:Nbaseline
disp(‘baseline (TMS is OFF)’);
fprintf(‘Volume # %i’,kb);disp(‘ ‘);
% MR-trigger check (standby)
a1(:)=0; KbQueueFlush();
while a1(1,a2(1))==0, [~,a1(:),~,~,~]=KbQueueCheck(); end 

% Here, a trigger was just detected.

for kb=1:Nstim
disp(‘Stimulation (TMS is ON)’);
fprintf(‘Volume # %i’,kb);disp(‘ ‘);
% MR-trigger check (standby)
a1(:)=0; KbQueueFlush();
while a1(1,a2(1))==0, [~,a1(:),~,~,~]=KbQueueCheck(); end 

% Here, a trigger was just detected.

% delay for MRI acquisition
fprintf(‘pre TMS delay is %d’,delay_preTMS);disp(‘ ‘);

disp(‘fire TMS’)
if (st == ‘1’)
myMV.fire(); % fire the TMS



end % end of outer loop

% Clean-up
ShowCursor; Screen(‘CloseAll’); clear Screen;
KbQueueStop(); KbQueueRelease(); Priority(0); clear mex;