Hallo liebes Forum,
ich versuche mit meinem selbstentwickelten Testsystem, Bilddaten eines
ADNS390 auszulesen und in Matlab einzulesen um diese Daten später
weiterzuverarbeiten.
Mein Testsystem sieht folgendermaßen aus:
Mit dem Bildsensor ADNS 3090 von PixArt, 8 Bit, 30 x 30-Matrix
lese ich die Daten per SPI von einem STM32F4 aus und diese werden auf
eine USART weitergeleitet. Auf der Platine selber habe ich einen FTDI-IC
verbaut. In HTerm und auf dem Oszilloskop bzw. mit einem LA kann ich die
Bilddaten sehen. In derzeitiger Konfiguration (30x30x8 Bit) liegen ca.
60 fps auf den Bus.
Mein Lösungsansatz ist folgender: Ich erzeuge in Matlab eine
30x30-Matrix und diese Matrix fülle ich mit den Werten, die ich von der
seriellen Schnittstelle bekomme. Mit dieser Matrix werde ich weitere
mathematische Operationen durchführen.
Mein Problem ist, das die Matlab-Schnittstelle extrem langsam ist:
Matlab-Code
1
% Öffne serielle Schnittstelle
2
adns3090_data = serial ('COM28', 'Baudrate',256000);
3
4
%Wenn ich diesen auf 900 setze, dauert das ewig
5
adns3090_data.InputBufferSize = 1;
6
fopen(adns3090_data);
7
8
n = 0;
9
horizontal_pixel = 30;
10
vertical_pixel = 30;
11
12
%Erzeuge 30x30 Matrix gefüllt mit 0
13
Picture = zeros(horizontal_pixel,vertical_pixel);
14
15
%Die Schleife
16
while(n<900)
17
n = n + 1;
18
Picture = uint8(fread(adns3090_data));
19
disp(n);
20
end
Kann mir jemand einen Tipp geben, warum alles so langsam ist? Vielen
Dank im Voraus!
Gruß
Daniel
30*30 Pixel = 900 Bytes.
* 60 fps = 54000 Bytes / sec.
= 432 KBit / Sekunde.
Deine Schnittstelle macht aber nur 256 Kbit?
Habe ich mich da verrechnet?
Oder ist ein Uart da etwas falsch am Platz?
Sorry, ich hatte den falschen Code gepostet, eingestellt habe ich 512000
Baud (in der Senderoutine im µC-Code und im Matlabcode. Deine Rechnung
stimmt jedoch.
Erhöhe ich den Buffer z.B. auf 15, wird alles sehr langsam und im Array
"Picture" sind die Werte (0 - 255), allerdings nur in einer Spalte. Die
ausgelesenen Werte scheinen zu stimmen. Die Prozedur dauert aber viel zu
langsam (> 5 s).
Normalerweise brauche ich 900 Bits und das dauert fast 5 Minuten für ein
Bild.
So, das habe ich nun getan. Im µC auf 921600 Baud eingestellt und im
Matlab ebenso. So sieht meine Implementierung aus (siehe Datei).
Ziel ist es, die Bilderdaten meines ADNS3090 als 30x30-Matrix als csv zu
speichern. Diese lese ich anschließend wieder ein und mache z.B. eine
Opticalflow-Messung.
Führe ich das Skript aus, kommt die Fehlermeldung
Warning: Unexpected Warning: The input buffer was filled before the
Terminator was reached.
Ich interpretiere daraus, das mein Buffer zu schnell gefüllt wird. Wie
definiere ich in Matlab ein Buffer, am besten 900 Bytes groß?
Danke und Gruß
Daniel
Daniel V. schrieb:> Warning: Unexpected Warning: The input buffer was filled before the> Terminator was reached.>> Ich interpretiere daraus, das mein Buffer zu schnell gefüllt wird. Wie> definiere ich in Matlab ein Buffer, am besten 900 Bytes groß?
im neuen Beispielcode verwendest du fgetl(), das ist aber nur für
Ascii-Daten brauchbar. Warum nicht wie am Anfang fread() verwenden, das
ist für Binärdaten und man kann als size[30,30] zurückgegeben um sofort
ein zweidimensionaes array mit den Bilddaten zu erhalten.
Siehe:
https://de.mathworks.com/help/matlab/ref/serial.fread.html
ja, wenn soviel schon im seriellen Puffer ist, sonst wartet read() bis
genug Daten da sind um das 30x30-Array zu füllen.
Allgemein ist es in Matlab immer besser selbstprogrammierte Schleifen zu
vermeiden, die Funktionen die ganze Arrays/Zeilen/Spalten auf einen
Rutsch bearbeiten sind um Größenordnungen schneller.
HG schrieb:> ja, wenn soviel schon im seriellen Puffer ist, sonst wartet read()> bis> genug Daten da sind um das 30x30-Array zu füllen.>> Allgemein ist es in Matlab immer besser selbstprogrammierte Schleifen zu> vermeiden, die Funktionen die ganze Arrays/Zeilen/Spalten auf einen> Rutsch bearbeiten sind um Größenordnungen schneller.
Wie realisiere ich das denn? Kannst Du mir ein Beispiel geben? Ich muss
ja im diesen Falle die Arrays ja füllen. Später benutze ich ja die
komplette Matrix um z.B. Vektoren zu bestimmen.
Danke und Gruß
Daniel
Danke dir, ich werde das heute abend zuhause mal testen. Dann war mein
erster Ansatz gar nicht so falsch. Danach kann ich diese eigentlich in
einer csv- oder xls-Datei speichern und für spätere Analysen verwenden.
Ich sag bescheid.
Danke und Gruß
Daniel
So, jetzt habe ich mal Deine Lösung implementiert. Das auslesen dauert
immer noch viel zu lang, aber zumindest habe ich schonmal ein Bild. Nach
ungefähr 533 Bytes kommt die Fehlermeldung:
Irgendwo habe ich einen Flaschenhals. Siehe Bild. Gerne kann ich auch
den µC-Code (STM34F4) hochladen.
1
% USART Kommunikation
2
clc; clear all, close all;
3
4
if ~isempty(instrfind)
5
fclose(instrfind);
6
end
7
8
adns3090_data = serial ('COM28', 'Baudrate',921600);
Dein Flaschenhals lautet MATLAB. Alles über 115200 Baud ist leider reine
Glückssache, bzw. stark abhängig von der PC-Hardware und dem OS.
Solltest du wirklich was schnelleres brauchen, dann empfehle ich auf
Python inkl. pyserial umzusteigen. Damit fahre ich problemlos 2MBaud
inklusive Echtzeit-Plots.
Wie lautet denn die Fehlermeldung nun?
Das Bild hat ja nur 900 Byte, also sollte auch bei einer Baudrate vom
9600 die Übertragung nur eine Sekunde brauchen. Das wär für Matlab
erstmal einfacher, wenn das klappt kann man immer noch testen wie
schnell man die Übertragung noch hochkitzeln kann.
HG schrieb:> Wie lautet denn die Fehlermeldung nun?>> Das Bild hat ja nur 900 Byte, also sollte auch bei einer Baudrate vom> 9600 die Übertragung nur eine Sekunde brauchen. Das wär für Matlab> erstmal einfacher, wenn das klappt kann man immer noch testen wie> schnell man die Übertragung noch hochkitzeln kann.
Sorry, hatte den Beitrag editiert, somit ist das obige erste Bild
obselet. Die Datenübertragung dauert jetzt 1,8 s.
Ich denke ich habe den Fehler in meiner µC-Controller-Software
ausgemacht. Auf den SPI-MISO-Bus liegen 54 Datenpakete a 900 Byte
(gemessen mit meinem LA). Mit dem Oszi habe ich auf der USART-Seite
gemessen, Dort gibt es Verzögerungen zwischen den Datenpaketen von ca 20
ms. Ich könnte sogar mit der Baudrate runtergehen.
Aber mit Deiner Hilfe bin ich einen sehr gutes Stück weitergekommen.
Danke Dir erstmal. Ich halte euch auf den Laufenden.
Daniel V. schrieb:> Mit dem Oszi habe ich auf der USART-Seite> gemessen, Dort gibt es Verzögerungen zwischen den Datenpaketen von ca 20> ms. Ich könnte sogar mit der Baudrate runtergehen.
Bau lieber Flusskontrolle (RTS/CTS) ein. Damit gehen auch bei hohen
Baudraten keine Bytes Richung PC verloren - wenn Matlab das unterstützt.
kurzes Update:
Es lag an meiner Firmware auf dem STM32F4:
Dieser Routine holt die Pixeldaten vom ADNS3090 aus dem
Frame_Capture_Register (0x13) und sendet diesen direkt auf die USART.
Vorher habe ich noch eine for-Schleife erstellt, d.h. diese Routine
unten und in der main ebenfalls
Als Baudrate habe ich jetzt 912600. Ich kann definitiv runter gehen.
Hier die Routine auf dem STM32: