Seriell über USB-Lesen mit GNU Octave-Problemen

Ich habe Schwierigkeiten, einen virtuellen USB-Comm-Port in GNU Octave einzulesen, und es gibt einige bizarre Vorgänge, zu denen ich gerne etwas Input hätte.

Derzeit habe ich ein virtuelles USB-CDC-Comm-Port-Gerät, das ich so programmiert habe, dass es auf Befehle über die serielle Schnittstelle mit dem Computer reagiert. Das Gerät ist ein Mikrocontroller-Board (STM32F401C Discovery Board) mit einem Gyroskop. Das Gyroskop wird über SPI auf den Mikrocontroller gelesen und dann leitet der Mikro die Daten an den Computer weiter. Er wartet, bis er die Befehle „x“, „y“ oder „z“ empfängt, um Daten zu senden, und sendet dann weiterhin Daten für diese Koordinate, bis ein Stoppbit (alles andere als „x“, „y“ oder „ z", ich verwende normalerweise "s") gesendet.

Mit CuteCom kann ich gut mit dem Gerät interagieren, z. B. das Senden des Befehls "xs" wird ein einzelnes 6-Byte-Paket der x-Achsen-Winkelgeschwindigkeitsdaten zurückgeben (vielleicht so etwas wie "+00021"). Mit GNU Octave und seinem Instrumentensteuerungspaket kann ich alle Koordinaten einlesen, aber das Senden der Zeichenfolge "xs" führt dazu, dass das Gerät nur das "x"-Byte empfängt und kontinuierlich x-Achsendaten weiterleitet.

Dies kann umgangen werden, indem eine Zeichenverzögerung von 1 ms hinzugefügt wird. Das STM-Gerät, das die seriellen Befehle liest, wartet ebenfalls 1 ms zwischen den Bytes, die es einliest, da es zuvor viele Zeichenfolgen für die x-Achse senden konnte, bevor es den "s" -Befehl erhielt.

Dann funktioniert es also, oder? Scheinbar nicht. Das seltsame Verhalten beginnt hier, denn wenn ich die Befehls-dann-Lese-Sequenz in Octave by One Time ausführe, funktioniert alles, aber in einer Schleife werden die eingelesenen Daten nur auf der x-Achse angezeigt. Ich dachte, dies sei ein Timing-Problem, und ich war neugierig zu sehen, was direkt mit CuteCom vom Port gelesen wurde.

Wenn CuteCom den seriellen Port auf Daten überwacht, liest Octave die Daten für die Dauer der Schleife richtig. Aber wenn es die serielle Schnittstelle nicht überwacht, liest es nur die x-Achse.

Ich verstehe nicht, warum das Ausführen von CuteCom parallel zum Octave-Skript dazu führen würde, dass der Prozess wie erwartet ausgeführt wird, aber ohne das Ausführen von CuteCom werden die Daten beschädigt. Hier ist das GNU Octave-Skript:

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
%

Das Ergebnis für die drei Achsen, wenn CuteCom nicht läuft (beachten Sie, wie die Daten für alle drei Zeilen kopiert werden, mit der kleinen Verzögerung zwischen ihnen):

Schlechtes Datenergebnis (CuteCom läuft nicht)

Das Ergebnis für die gute Datenausgabe, wenn CuteCom läuft (beachten Sie, dass die Daten für jede Achse konsistent und klar sind):

Gutes Datenergebnis (CuteCom läuft)

Ist jemandem so etwas schon einmal begegnet? Welche Fehler wurden gemacht, um dies zu bewirken?

Vielen Dank im Voraus.

Sam

Dies ist wahrscheinlich ein Problem entweder mit den Treibereinstellungen für serielle Ports (Zeilenabschluss, Zeichenzuordnung, der berüchtigte kanonische Modus usw.) oder anderen ungültigen Annahmen, die auf Missverständnisse darüber zurückzuführen sind, was ein normalerweise byteweiser serieller Stream, der für USB paketiert wird, mit Ankunftszeiten und Gruppierungen wie gesehen über Aufrufe an read()oder noch schlimmer fread(). Möglicherweise möchten Sie ein Tool (in Python, C oder was auch immer) entwickeln, das zuverlässig Daten abruft, und diese dann in Ihr Plotprogramm leiten.
Ich würde dem System lieber keine weitere Abstraktionsebene hinzufügen, obwohl ich nicht vollständig gegen das Hinzufügen der Schnittstelle bin. Was kann ich tun, um das Problem über Octave zu beheben? Ich nehme nicht an, dass Sie sich mit der Mechanik von Octave besonders gut auskennen, und ich habe es für das Plotten im Gegensatz zur seriellen Schnittstelle gewählt. Aber Homogenität wird bevorzugt, also interessiere ich mich für Optionen.
Sie könnten versuchen, es unter Strace laufen zu lassen - seien Sie darauf vorbereitet, das Ergebnis zu prüfen! Ich denke, Sie können auch so etwas wie Wireshark verwenden, um die rohen USB-Übertragungen von dieser Seite zu erhalten. Verwenden Sie auch stty, um die Leitungseinstellungen zu untersuchen und zu vergleichen, wenn die beiden Programme laufen. All-in-One-Lösungen sind nett, aber vergessen Sie nicht die Tugenden des "Unix-Wegs" mit kleinen Einzelaufgabenprogrammen, die aneinandergereiht sind und deren Ausgabe an die Eingabe geleitet wird.

Antworten (1)

Ich habe das Problem gelöst, also werde ich die Antwort posten. Es war tatsächlich ein Timing-Problem. Um das obige Programm zu reparieren, habe ich tatsächlich die Verzögerung zwischen dem Befehl "x" und dem Lesen entfernt. Ich kann nicht sicher sagen, warum sich das Programm bei dieser Verzögerung nicht richtig verhalten würde, aber der beste Weg, die Daten zu erhalten, war, sie zu entfernen: Befehl senden, sofort lesen, Stoppbefehl senden, Verzögerung.

Danke für die Hilfe @Chris Stratton. Obwohl das Problem kleiner war als erwartet!

Sam