# How can I control fast real time sensor (250Hz) with slow system display(60Hz)

We do some experiments of real time representation of sensor position on TV. In this experiments, we used sensors for collect real time position in 3D at 250Hz and TV for Display the sensor position at 60Hz. Also, we used MATLAB and C++ for programming with OpenGL platform.

In programming, Every iteration dat display on the TV, erase and draw the circle (Object, which is represent real time position on the display). In this program I collect to only 60 points and loose other 190 points in every second, becuase, I think that refresh rate of TV is 60Hz.

I have gone through the thread "How can I control a fast (200Hz) realtime system with a slow (30Hz) system?"(How can I control a fast (200Hz) realtime system with a slow (30Hz) system?), but i don't understand, How to implement two loop on 200Hz and 30Hz.

My Question is, How can we implement in MATLAB/C++? So I can store 250 data of sensors as well as 60 points for real time display on the TV.

If you help me through pseudo code, I appreciate your help.

P.S. Code

%Display main window using Psychtoolbox

win=Screen(2,'OpenWindow',[1 1 1])

while (1)
% Setup for data collection at 250Hz
Error   = calllib('ATC3DG64', 'GetSynchronousRecord',  hex2dec('ffff'), pRecord, 4*numBoards*64);
errorHandler(Error);
Record = get(pRecord, 'Value');

%sensor number
count=2;

evalc(['tempPos(1, count) ='  'Record.x' num2str(count - 1)]);
evalc(['tempPos(2, count) ='  'Record.y' num2str(count - 1)]);
evalc(['tempPos(3, count) ='  'Record.z' num2str(count - 1)]);

% Record X and Y position of  sensor 2

if SensorNumAttached(count)
% Real time position and minus world origin so that real
% time position display on the TV
table1(count,1)=(2.54*tempPos(2,count))-X_world_origin;
table1(count,2)=(2.54*tempPos(3,count))-Y_world_origin;
end

% Some conversion for the Pixel to centimeter ratio
x_center_new = x_center - (x_ratio * table1(2,1));
y_center_new = y_center - (y_ratio * table1(2,2));

% conversiorn for display circle on the TV, is represent the real time poistion of the sensor
x1  =round(x_center_new - R_num_data);
y1 = round(y_center_new - R_num_data);

x2 = round(x1 + 2*R_num_data);
y2 = round(y1 + 2*R_num_data);

% Display command for TV.
Screen('FrameOval',win,[255 0 0], [x1 y1 x2 y2]);
Screen('Flip',win);
end


I'm not entirely sure what you're asking for because your question title mentions control but your question body seems to all be about display. You said,

My Question is, How can we implement in MATLAB/C++? So I can store 250 data of sensors as well as 60 points for real time display on the TV.

If you want to store samples for display at some particular interval, try the following:

sensorPeriod = 1/250;
displayPeriod = 1/60;
displayInterval = floor (displayPeriod/sensorPeriod);
sensorHistory(end+1) = sensorData;
displayData = sensorHistory(1:displayInterval:end);


You can use any integer to select indices of an array in Matlab. The value is optional and if you don't specify it then it defaults to 1. So, for instance, where

displayData = data(1:end);


would put every data point into displayData, the following:

displayData = data(1:N:end);


would take every Nth point and put that into displayData. Dividing display period by the sample period gives the number of samples that occur between each displayed frame. Take the floor of that to get an integer because Matlab can only handle integer indexing of arrays.

## :EDIT:

As I go through your code, here are things that I notice:

% Display main window using Psychtoolbox

win=Screen(2,'OpenWindow',[1 1 1])

while (1)
% Setup for data collection at 250Hz
Error   = calllib('ATC3DG64', 'GetSynchronousRecord',  hex2dec('ffff'), pRecord, 4*numBoards*64);
errorHandler(Error);
Record = get(pRecord, 'Value');


This section all appears to look okay, and it appears to me that Record is the data point you are interested in storing. There is no reference to 'ATC3DG64' or 'pRecord', but there is also no complaint about retrieving data, so I can only assume this works okay. However, I would like to note that the calllib() function accepts arguments inside the parenthesis, not outputs, so I don't see where/how pRecord ever gets updated.

  %sensor number
count=2;

evalc(['tempPos(1, count) ='  'Record.x' num2str(count - 1)]);
evalc(['tempPos(2, count) ='  'Record.y' num2str(count - 1)]);
evalc(['tempPos(3, count) ='  'Record.z' num2str(count - 1)]);


I do not know why you are using evalc to do this. That function evaluates an argument and copies the output to a variable, but you don't make an output assignment. Instead you're just converting everything to a string to make Matlab parse the string, when you could just leave everything off and call the functions directly. Also, your string conversion doesn't leave you with a proper indexing for the Record.x functions. You wind up calling:

tempPos(1, count) =Record.x 0


when you probably should be calling

tempPos(1, count) =Record.x(0)


If you are using evalc() to suppress the output, you can always do that with a semicolon at the end of the line. I think you should probably re-write this section of code to the following:

tempPos(1, count) = Record.x(count-1);
tempPos(2, count) = Record.y(count-1);
tempPos(3, count) = Record.z(count-1);


Moving on...

  % Record X and Y position of  sensor 2

if SensorNumAttached(count)
% Real time position and minus world origin so that real
% time position display on the TV
table1(count,1)=(2.54*tempPos(2,count))-X_world_origin;
table1(count,2)=(2.54*tempPos(3,count))-Y_world_origin;
end


The function SensorNumAttached() is not a Matlab function, so I don't know what that is checking for. That said, this portion of the code is a little confusing because you switch between indexing the data to the sensor on the columns to indexing on the rows, but otherwise this looks okay.

  % Some conversion for the Pixel to centimeter ratio
x_center_new = x_center - (x_ratio * table1(2,1));
y_center_new = y_center - (y_ratio * table1(2,2));


This section of code will not do what you want it to do. This looks like you are trying to update coordinates, but you are combining a relative position with an absolute position. It looks like you are trying to go for:

  x_center_new = <old center> + <difference between old center and new center>;


When in actuality you have:

  x_center_new = <old center> + <difference between origin and new center>


I may be wrong here, because you never set x_center = x_center_new, which is either a mistake or it could be that x_center is some offset information. I don't think this is the case, though, because there is no x_center(count), which means you don't have a distinct x_center for both sensors. Also of note - you don't reference count in this code at all, so you're updating both sensor displays with only one (#2's) position information. I would suggest you change this code to be:

  x_center_new = x_ratio * table(count,1);
y_center_new = y_ratio * table(count,2);


Moving on. . .

  % conversion for display circle on the TV, is represent the real time position of the sensor
x1  =round(x_center_new - R_num_data);
y1 = round(y_center_new - R_num_data);

x2 = round(x1 + 2*R_num_data);
y2 = round(y1 + 2*R_num_data);

% Display command for TV.
Screen('FrameOval',win,[255 0 0], [x1 y1 x2 y2]);
Screen('Flip',win);
end


For this section, Screen is also not a Matlab function, so I'm not sure what it does, and R_num_data is not defined in the code snippet you provided, so I don't know what that does, either. I would like to reiterate that, by your code, the display here never showed anything for sensor 1 because your x_center_new used a hard-coded '2' instead of 'count'.

Regarding display, there are two ways that you can go about showing data:

1. Collect the data in real time, then show the video after the fact.
2. Collect the data and display in real time.

If you attempt to display in real time, Matlab rendering will almost certainly hamper your data collection as I've found it seems to be generally about 100ms for Matlab to draw a basic scene. Also, if you collect data and display in real time with no bounds on time, you can't pre-allocate the memory for data storage, which can cause the program to run slower. That said, here's some sample code you can throw into your script for display:

## Method 1

nSensors = 2;       % Number of sensors
nOutputs = 3;       % How many outputs each sensor gives you
sampleDuration = 1; % Sample time in [s]
samplePeriod = 1/250; % Sampling period in [s]
displayPeriod = 1/60; % Display period in [s]

nDataPoints = floor(sampleDuration/samplePeriod);

sensorData = zeros(nOutputs,nSensors,nDataPoints);

count = 2;          % Whatever method you want to select the sensor
for i = 1:nDataPoints
<whatever method you need to get the data>
Record = get(pRecord, 'Value');
sensorData(1,count,i) = Record.x(count-1);
sensorData(2,count,i) = Record.y(count-1);
sensorData(3,count,i) = Record.z(count-1);

<any other things you want to do with the data>
end

sampleInterval = floor(displayFreq/sampleFreq);
displayData = nDataPoints(:,:,1:sampleInterval:end);

for i = 1:size(displayData,3)
<display 'displayData(:,:,i)'>
end


## Method 2

nSensors = 2;       % Number of sensors
nOutputs = 3;       % How many outputs each sensor gives you
samplePeriod = 1/250; % Sampling period in [s]
displayPeriod = 1/60; % Display period in [s]

sensorData = zeros(nOutputs,nSensors,0);
displayData = zeros(nOutputs,nSensors,0);

tic;                 % Start a timer
while 1
<whatever method you need to get the data>
Record = get(pRecord, 'Value');
sensorData(1,count,end+1) = Record.x(count-1);
sensorData(2,count,end+1) = Record.y(count-1);
sensorData(3,count,end+1) = Record.z(count-1);

elapsedTime = toc;
if elapsedTime + frameAdjustment > displayPeriod
tic;
displayData(:,:,end+1) = nDataPoints(:,:,end);

<display 'displayData(:,:,end)'>
end
end


Note in the above code that there is a variable, frameAdjustment. This term can account for the fact that your elapsedTime probably isn't going to sync exactly with your desired frame rate. It remembers how much time you were past the desired display call and calls the next display that much sooner. If the time it takes to display your data is longer than your displayPeriod then you'll wind up displaying every loop iteration. As mentioned earlier, this could mean that you don't build your sensorData history at the correct rate.

It looks like maybe the Screen command could let you bypass the time it takes for Matlab to draw a scene, but I haven't used any third-party Matlab tools so I can't comment on it. Your best bet would be to gather the data first and then display it, but as the designer, it's always up to you.

• Still my problem. For example, we record for every one second. In this time, I faced dragging problem. I not able to understood. How can store 250 data in one second as well as 60 data represent in this second. – Rushik Thumar Sep 20 '15 at 20:27
• @RushikThumar - I'm sorry I don't understand what you need help with. Can you post the code you are having issues with? – Chuck Sep 21 '15 at 2:18
• I shared the code – Rushik Thumar Sep 21 '15 at 13:41

I didnt see what is your processing unit (preocessor/ADC/DAC etc.) speed?. If your processor speed less than sensors speed you can try "sampling" or "quantization" techniques. you can look to any signal processing book for further readings. If you have fast processor and slow display unit this is not a problem. Just collect/ buffer your sensor readings for a second (or you can use 1/60 sec for fast display) than show all of them in display unit.

This is like controlling analogus systems with digital systems.

• Thanks acs, for your answer. I have used Ascention trakstar Sensor. I have implemented a buffer, but not worth it in my case. because after 1/3, real time movement is dragging. So, If you suggest any other option, than it is good for me. I have fast processor and slow display unit. I think that implementation two control loop simultaneously,which is mentioned in above mentioned thread. Can you suggest me some implementation. Really, I appreciate your help. – Rushik Thumar Sep 20 '15 at 12:11
• I need your code or pseudocode for implementation. – acs Sep 20 '15 at 20:23
• can you share your email ID? My email ID is thumar.rushik@gmail.com – Rushik Thumar Sep 20 '15 at 20:24