0
\$\begingroup\$

I am having difficulty reading a USB virtual comm port into GNU Octave, and there are some bizarre goings-on that I would like some input on.

Currently I have a USB CDC virtual comm port device that I programmed to respond to commands over serial with the computer. The device is a microcontroller board (STM32F401C Discovery board) with a gryoscope. The gryoscope is read over SPI onto the microcontroller and then the micro relays the data to the computer. It waits until it receives the "x", "y", or "z" commands to send data and then it continues to send data for that coordinate until a stop bit (anything other than "x", "y", or "z", I usually use "s") is sent.

Using CuteCom I am able to interact well with the device e.g. sending the command "xs" will return a single 6-byte packet of the x-axis angular rate data (maybe something like "+00021"). Using GNU Octave and its instrument-control package I can read in all coordinates, but sending the string "xs" will cause the device to only receive the "x" byte and it will relay x-axis data continuously.

This can be worked around by adding a 1ms character delay. The STM device reading the serial commands waits 1ms between bytes it reads in as well, because previously it was able to send many strings for the x-axis before it received the "s" command.

So it works then, right? Apparently not. The strange behavior starts here, as when I run the command-then-read sequence in Octave by one time everything works, but in a loop the data read in is only the x-axis. I thought this was a timing problem, and I was curious to see what was being read from the port directly using CuteCom.

When CuteCom is monitoring the serial port for data, Octave reads data properly for the duration of the loop. But when it is not monitoring the serial port, it will only read the x-axis.

I do not understand why having CuteCom running in parallel with the Octave script would cause the process to perform as expected, but without CuteCom running the data comes in corrupted. Here is the GNU Octave script:

pkg load instrument-control;
pkg load signal;

s1 = serial("/dev/ttyACM0");
set(s1,'baudrate',115200);
set(s1, 'bytesize',8);
set(s1,'parity','n');
set(s1,'stopbits',1);
set(s1,'timeout',100); %10.0 seconds

sleep(0.5);
srl_flush(s1);

datax = [];
datay = [];
dataz = [];
negativex = false;
negativey = false;
negativez = false;
xd = 0;
yd = 0;
zd = 0;
delaytime = 1000; %delay time in microseconds (us)

hold on;
for i = 1:500
  srl_write(s1,"x");
  usleep(delaytime);
  xd = str2num(char(srl_read(s1,6)));
  srl_write(s1,"s");
  usleep(delaytime);

  srl_write(s1,"y");
  usleep(delaytime);
  yd = str2num(char(srl_read(s1,6)));
  srl_write(s1,"s");
  usleep(delaytime);

  srl_write(s1,"z");
  usleep(delaytime);
  zd = str2num(char(srl_read(s1,6)));
  srl_write(s1,"s");
  usleep(delaytime);

  datax = [datax xd];
  datay = [datay yd];
  dataz = [dataz zd];

  if mod(i, 10) == 0
    hold off;
    plot(datax,'r');
    hold on;
    plot(datay,'b');
    plot(dataz,'g');
    drawnow;
  endif
endfor
%

The result for the three axes when CuteCom is not running (note how the data is copied for all three lines, with the small delay between them):

Bad data result (CuteCom not running)

The result for the good data output, when CuteCom is running (note the data for each axis is consistent and clear):

Good data result (CuteCom running)

Has anyone come across something like this before? What mistakes were made to cause this to happen?

Thanks in advance.

Sam

\$\endgroup\$
  • \$\begingroup\$ This is likely an issue either with serial port driver settings (line termination, character mapping, the infamous canonical mode, etc) or else invalid assumptions originating with misunderstanding of what having a normally bytewise serial stream packetized for USB does to inter-arrival times and groupings as seen via calls to read() or even worse fread(). You may want to develop a tool (in python, C, or whatever) that reliably gets data and then pipe that into your plotting program. \$\endgroup\$ – Chris Stratton Jul 19 '17 at 16:33
  • \$\begingroup\$ I would rather not add another level of abstraction to the system, though I'm not completely against adding the interface. What can I do to troubleshoot the problem through Octave? I don't assume you're particularly knowledgeable in the mechanics of Octave, and I chose it for the plotting as opposed to the serial interface. But homogeneity is preferred so I'm interested in options. \$\endgroup\$ – Sam Gallagher Jul 19 '17 at 17:25
  • \$\begingroup\$ You could try running it under strace - be prepared to do some grepping of the result! I think you can also use something like wireshark to get at the raw USB transfers from that side. Also use stty to examine and compare the line settings when the two programs are running. All-in-one solutions are nice, but don't forget the virtues of "the Unix way" with little single-task programs strung together with output piped to input. \$\endgroup\$ – Chris Stratton Jul 19 '17 at 17:28
0
\$\begingroup\$

I have solved the problem, so I will post the answer. It was indeed a timing problem. To repair the above program, I actually removed the delay in between the command "x" and the read. I cannot say for sure why the program would not behave properly with this delay, but the best way to get the data was to remove it: send the command, read immediately, send the stop command, delay.

Thanks for the help @Chris Stratton. Although the problem was a smaller one than expected!

Sam

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.