Archiv verlassen und diese Seite im Standarddesign anzeigen : Matlab GUI Plot
HannoHupmann
31.12.2014, 18:08
Hallo zusammen,
in Matlab (R2009a) möchte ich gerne die Sensorwerte des SRF02 Sensors anzeigen lassen. Ich kann den Sensor bereits auslesen und die Messwerte verarbeiten, nur bekomm ich es nicht hin diese in der GUI anzeigen zu lassen. Ich wünsche mir einen Plot der auf der y-Achse die Distanz anzeigt und auf der x-Achse mit jeder Messung weiter wandert. So dass die alten Werte auch noch zu sehen sind. Sprich eine kontinuierliche Anzeige wie man das bei Messungen eben kennt ;-).
Kann mir da jemand helfen wie ich die Plot Funktion dafür einstellen muss?
Hallo Hanno!
Wenn ich mich recht erinnere, hattes Du schonmal danach gefragt, ich hatte seinerzeit hier (https://www.roboternetz.de/community/threads/54277-Vinculum-Hexabot?p=596702&viewfull=1#post596702) versucht mal zu zeigen, wie ich sowas mache. Vermutlich war meine Erklärung damals nicht sonderlich erhellend. Sag doch erstmal wie Du die Daten auf Matlab-Seite empfängst. Über ein serial Objekt? Der erste Schritt wäre dann einen Callback zu machen, in dem Du Zugriff auf die Daten hast (hast Du ja vielleicht schon). Die Darstellung basiert dann darauf, einen gewissen Vorrat an Meßwerten in einem Vektor dergestalt vorzuhalten, dass für jeden neuen Messwert alle Messwerte in ihrem Index um 1 verschoben werden, der älteste Messwert also rausfällt, und der neue Messwert an Index 1 geschrieben wird. Der ganze Vektor wird dann geplottet. Da Matlab matrizen-/vektororientiert arbeitet, ist das in einer Zeile erledigt. Ich glaube aber es ist sinniger das Schritt für Schritt zu machen, bevor ich hier Romane schreibe, die in die falsche Richtung gehen ... :-) Also erzähl doch erstmal, was Du aktuell konkret zum Empfangen der Daten hast.
Gruß
Malte
HannoHupmann
01.01.2015, 12:50
Hallo Malthy ja stimmt du hast mir da mal was gezeigt, hatte ich auch ausprobiert, aber ging dann - soweit ich mich erinnere - auch nicht richtig. Ist aber schon lange her, dass ich mich damit beschäftigt habe.
Bisher habe ich es so gelöst:
while on_off == 1
fopen(com);
fwrite(com, 'SE00051P', 'uint8'); //Sensor aktivieren
pause(0.065);
fwrite(com, 'SE103P', 'uint8'); //Sensor Werte abfragen
A = fscanf(com) //Einlesen
fclose(com);
// Konvertieren der Daten
A_b = regexp(A,' ','split');
Distanz = hex2dec([A_b{2} A_b{3}])
Daten{i}= Distanz
plot(i,Daten{i}, '.')
on_off = get(hObject,'Value');
i = i+1;
end
Da mein Plot auf der x-Achse aber nur bis Wert 100 geht, kann ich nur 100 Messwerte anzeigen, alle weiteren werde nicht mehr angezeigt. Ich hätte gerne, dass der Messwert 101 angezeigt wird dafür Messwert 1 verschwindet. Sprich die X-Achse weiter wandert. Es sollte dann eine kontinuierliche Messanzeige sein.
Hallo!
Hm, also so ganz optimal ist Dein Ansatz für meinen Geschmack eher nicht. Natürlich kannst Du die Daten in einem Loop abholen - Du könntest aber auch einen Callback machen, der jedesmal aufgrufen wird, wenn das serial Objekt Daten für Dich hat. Dann wird das Timing durch die einlaufenden Daten bestimmt und du müsstest nicht "pause" verwenden. Aber gut, kannst ja ggf mal ändern, erstmal mag es so gehen. Was man aber auf jeden Fall vermeiden sollte - insb wenn du alle 65 ms lesen willst - ist für jeden Lesevorgang die Schnittstelle auf- und wieder zuzumachen. Mach vor dem Loop einmal die Schnittstelle auf und danach, wenn das Programm beendet wird, wieder zu. Das eigentliche Plotten würde ich dann so machen, wie weiter oben schon beschrieben. Du legst Dir ein Vektor für Deine Daten (zB 500 Punkte) an und initialisiert ihn zB mit Nullen:
vals = zeros(500, 1);
Dann plottest Du den Vektor einmal und lässt Dir das Handle von dem plot (hier nennen wir es h1) zurückgeben:
h1 = plot(vals);
jetzt kommt ein kleiner Trick. Mit
set(h1, 'YDataSource', 'vals')
sorgst Du dafür, dass Du in Deinem Loop die Daten des Diagramms einfach updaten kannst. Das o.g. führst Du also einmal vor Deinem Hauptloop aus. Für den Loop übernehm ich mal Deine Art des Auslesens - auch wenn man da vielleicht noch einiges verbessern kann.
while run
fwrite(com, 'SE00051P', 'uint8');
pause(0.065);
fwrite(com, 'SE103P', 'uint8');
A = fscanf(com)
A_b = regexp(A,' ','split');
Distanz = hex2dec([A_b{2} A_b{3}])
vals(2:500) = vals(1:499);
vals(1) = Distanz;
refreshdata(h1, 'caller')
end
So müsste es in etwa gehen.
Gruß
Malte
HannoHupmann
01.01.2015, 14:21
Hallo Malte,
gleich mal ausprobiert, aber leider geht es nicht. Ich fürchte es liegt nicht an der Plot Idee sondern daran wie man die Parameter das Plot Fenster in der GUI setzt. Ich habe das ganze ja mit einer .fig versehen und dort kann ich manuell den Sensor ein und ausschalten. In den Einstellungen des Plot Fensters gibt es sehr viele möglichkeiten der Konfiguration aber ich hab nicht rausfinden können bisher wie ich die einstellungen Setzen muss, damit es wird wie ich es gerne hätte.
Mit dem Callback könnte man es natürlich auch machen, aber ich wollte nur eine schnelle quick und dirty Lösung um den Sensor in einer Schleife abzufragen. Dass ich die Schnittstelle nach jeder Abfrage wieder schließe liegt ein wenig am Testmodus, denn hier brech ich öfter mal spontan die Messung ab und wenn der Port dann nicht zu ist muss ich Matlab jedesmal neu starten. Also quasie auch nur ein Workaround.
- - - Aktualisiert - - -
Im GUI Plot lässt sich die x-Achse nicht verschieben. Ich kann es nur so einstellen, dass die x-Achse mit skaliert. D.h. bei 10 Ticks gibt sie die entsprechenden Werte von 0 bis 10 wieder und bei 100 Ticks werden die Werte bis 100 dargestellt. Entsprechend skaliert natürlich, womit die Punkte immer weiter zusammen rutschen.
- - - Aktualisiert - - -
Ok die Antwort auf die ganze Fragestellung ist so einfach, dass sie fast schon wieder langweilig ist.
Mit:
if i > 20
axis ([i-20 i+1 0 600])
end
Kann ich einfach die x-Achse wandern lassen und es zeigt mir immer den entsprechenden Abschnitt mit den alten Werten an. ;)
- - - Aktualisiert - - -
Ok die Antwort auf die ganze Fragestellung ist so einfach, dass sie fast schon wieder langweilig ist.
Mit:
if i > 20
axis ([i-20 i+1 0 600])
end
Kann ich einfach die x-Achse wandern lassen und es zeigt mir immer den entsprechenden Abschnitt mit den alten Werten an. ;)
Doch, das funktioniert schon. Hier mal die nackteste Variante, die direkt läuft:
vals = zeros(500, 1);
h1 = plot(vals);
set(h1, 'YDataSource', 'vals')
run = 1;
while run
Distanz = rand(1,1);
vals(2:500) = vals(1:499);
vals(1) = Distanz;
refreshdata(h1, 'caller')
pause(0.05)
end
Statt die Werte mit rand zu würfeln müsstest Du natürlich an der Stelle Deine Datenquelle einsetzen. Wenn bereits eine GUI mit einem Plot existiert, musst Du natürlich das ensprechende Handle verwenden. Mit axis änderst Du nur den Darstellungsbereich des Plots, d.h. dass so wie Du es gebaut hast im Hintergrund dein Datenvektor immer größer wird - das ist auf einem modernen Rechner erstmal nicht unbedingt ein Problem (viel Ram), aber natürlich nicht sehr elegant wenn man einfach nur die letzten 500 Werte darstellen will.
Gruß
Malte
Hi,
[...] denn hier brech ich öfter mal spontan die Messung ab und wenn der Port dann nicht zu ist muss ich Matlab jedesmal neu starten.
Sorry, habe den Satz vorhin irgendwie überlesen. Du kannst mit
fclose(instrfind)
immer sämtliche serial Objekte schließen, und mit
delete(instrfind)
sämtliche serial Objekte aus dem Speicher löschen.
Wenn mal ne ganze GUI hängt kann man die (und alles andere offene) oftmals mit
close all force
abschießen. Damit kann man in 98% der Fälle einen Neustart verhinden - ein bißchen auch abhängig davon wie dreckig man programmiert ;-). Aber ja, es gibt trotzdem Fälle in denen man sich ausgesperrt hat.
Gruß
Malte
HannoHupmann
02.01.2015, 01:17
Morgen probier ich mal deine Vorschläge aus. Für den SRF02 brauch ich es vielleicht noch nicht, aber für den Lagesensor und für die anderen Distanzsensoren ist es vermutlich ganz hilfreich es sauberer zu programmieren.
Du weißt doch Malte wir Hobbybastler mögen es dreckig programmiert ;-)
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.