Соединение с последовательным портом MATLAB слишком медленное - PullRequest
0 голосов
/ 30 ноября 2011

У меня есть детектор, который выдает два числа с высокой скоростью, когда я включаю его. Я собираю свои данные с помощью HyperTerminal, который, кажется, способен идти в ногу с устройством.

Я хотел автоматизировать процесс и полностью контролировать устройство через Matlab, но обнаружил, что менее половины данных поступает в Matlab. Есть ли какие-либо известные проблемы со скоростью Matlab в этой области?

Вот что я использую для чтения данных:

s = serial('COM1', 'BaudRate', 115200, 'DataBits', 8, 'Terminator','CR/LF', 'InputBufferSize', 1024);
T1 = 1;       % Initial T1, T2 values
T2 = 10000;
timer = 300;

% Inputs to serial device: T1, T2, runtime (seconds)    
fprintf(s, sprintf('%d %d %d\r', T1, T2, timer));
tdata = zeros(1e5,2,'uint16');
data = fopen(sprintf('%s.txt',date_and_trial),'w');
tic;
while toc <= timer
% Read data into an array, and write to file.
    if s.BytesAvailable >= 13
            line = fgets(s);
            if length(line) == 13
                a = sscanf(line, '%u %u');
                if length(a) == 2
                    tdata(i,1) = a(1);
                    tdata(i,2) = a(2);
                    fprintf(data, sprintf('%d %d\r', tdata(i,1), tdata(i,2)));
                    i++;
                end
            end
        else
            pause(0.01);
        end       
    end
    disp(toc);
    fclose(s);
    fclose(data);
    fprintf('Finished!\r');

Я думал, что условные выражения могут замедлять его, но они также необходимы для сохранения нужного мне формата "% i% i \ n". Может быть, есть какой-нибудь способ прочитать все данные и обработать их после завершения?

1 Ответ

2 голосов
/ 30 ноября 2011

Поскольку вы передаете 'Terminator', 'CR/LF' в открытом вызове последовательного порта, вы можете заменить

if s.BytesAvailable >= 13
        line = fgets(s);
        if length(line) == 13

на line = fscanf(s);.fscanf будет ожидать терминатора и вернет целую строку (при условии, что в проводе нет ошибок).Вы также можете удалить часть else pause.Эти изменения должны сделать цикл достаточно быстрым, чтобы не отставать от последовательных данных.Я бы предположил, что s.BytesAvailable и pause на самом деле занимают гораздо больше времени, чем вы ожидаете - первое, потому что оно вызывает ОС, а второе, потому что пауза может идти намного дольше, чем вы указываете, в зависимости от временного среза.*

При внесении этого изменения возникает новая проблема: fscanf заблокирует ожидание терминатора, то есть, если устройство прекратит отправку до того, как ваше условие toc >= timer станет истинным, программа зависнет.Поэтому вы должны убедиться, что в вызове serial установлено разумное время ожидания.

Вы можете сделать два небольших ускорения в теле цикла: tdata(i,:) = a'; заполнит строку за один выстрел, а fprintf(data, '%s\r', line); пропустит printf.Итак, все вместе:

s = serial('COM1', 'BaudRate', 115200, 'DataBits', 8, 'Terminator','CR/LF', 'InputBufferSize', 1024, 'Timeout', 3);
T1 = 1;       % Initial T1, T2 values
T2 = 10000;
timer = 300;

% Inputs to serial device: T1, T2, runtime (seconds)    
fprintf(s, sprintf('%d %d %d\r', T1, T2, timer));
tdata = zeros(1e5,2,'uint16');
data = fopen(sprintf('%s.txt',date_and_trial),'wt');
tic;
while toc <= timer
% Read data into an array, and write to file.
    line = fscanf(s); %# waits for CR/LF terminator
    a = sscanf(line, '%u %u');
    if length(a) == 2
        tdata(i,:) = a'; %# ' assumes sscanf returned a column vector
        fprintf(data, '%s\r', line);
        i++;
    end
end
disp(toc);
fclose(data);
fclose(s);
fprintf('Finished!\r');
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...