2D-Grafik EKG Signal in Echtzeit plotten

P@u1

Aktives Mitglied
Hallo,

ich arbeite gerade daran, ein EKG-Signal, dass ich über eine serielle Schnittstelle auslese (bei mir kommt das Signal in Form von zahlen von 0 bis 255 an) in Echtzeit zu plotten.
Ich habe schon verschiedenes versucht - zunächst einfach jede paar millisekunden oder immer wenn ein neues signal kommt alles neu zu zeichenen, was sehr starkes flimmern verursacht hat.
Dann habe ich das ganze mit bufferung versucht, also erst in eine image variable reingemalt und die dann als ganzes bei jeder änderung auf den bildschirm malen lassen.
Das Ergebnis: kein Flimmern mehr, aber der Plot kommt mit dem Datenstrom nicht mehr mit und hängt total hinterher.
Jetzt hatte ich die Idee, dass ich nur die neuen Daten zeichne und alte die "im Weg sind" mit der Hintergrundfarbe übermale.
Theoretisch sollte das halbwegs funktionieren, nur finde ich es relativ unflexibel, z.B. wenn man das Fenster verschiebt oder die Größe ändert trifft man auf Probleme.
Kennt ihr vielleicht noch eine gute Möglichkeit, wie ich das lösen kann?
Auf jeden Fall sollte es nicht flackern und das Signal muss in Echtzeit ohne Verzögerung geplottet werden.

Vielen Dank schonmal für eure Hilfe!

In der Zeit bis eine Antwort kommt werde ich das mit dem Übermalen nochmal ausprobieren, wie gesagt ist das wie ich denke relativ schnell, aber man muss dann im Paintevent wahrscheinlich noch einiges behandeln.
 

P@u1

Aktives Mitglied
ich kann einsetzen, was ich will (solanges nicht zu viel kostet), nur sollte es wenn möglich in java sein.
Also könnte ich das was du verlinkt hast denk ich mal benutzen.
Ich guckes mir jetzt mal an.
Vielen dank für den Link auf jeden Fall!
Das einzige Problem, wenn ich soetwas vorgefertigtes benutze könnte sein, dass ich die Vorgabe habe, dass das Signal wenn es am rechten Bildschirmrand angekommen ist links wieder anfangen soll und das vorherige Signal "auffressen" soll und es nicht einfach alles weiter nach rechts "geschoben" werden soll (hoffe das ist verständlich :D)
Wenn das damit auch gehen würde, dann wärs natürlich super.

Edit: Link aufgemacht und sofort gesehen, dass genau das der Fall ist.
Sieht so aus, als wär das genau das richtige für mich, ich werds mir jetzt mal genauer angucken.

Edit2: Sieht immer noch sehr gut aus, nur hab ich Schwierigkeiten nen Download davon zu finden und was genaues über die Lizenz zu finden.
 
Zuletzt bearbeitet:

ARadauer

Top Contributor
mhn das Oscilloscope Widget schaut ziehmlich cool aus...

zunächst einfach jede paar millisekunden oder immer wenn ein neues signal kommt alles neu zu zeichenen, was sehr starkes flimmern verursacht hat.
mhn... was sind ein paar millisekunden für dich?

Ich würd nach dem neuzeichnen immer einwenig warten...
Sagen wir mal 40 Frames.
warten = 1000/frames - Dauer zum Signal ermitteln-Dauer fürs neuzeichen

hab zwar nicht viel ehrfahrung damit, aber vielleicht hilft dir das....

Java:
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Random;

import javax.swing.JComponent;
import javax.swing.JFrame;


public class HeartBeat extends JComponent implements Runnable{
   
   
   public static void main(String[] args) {
      JFrame frame = new JFrame();
      frame.setSize(250, 150);
      HeartBeat beat = new HeartBeat();
      frame.setContentPane(beat);
      new Thread(beat).start();
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.setVisible(true);
   }
   
   
   Point[] points;
   
   public HeartBeat(){
      points = new Point[200];      
   }
   
   
   @Override
   public void run() {
      int x = 0;
      Random rnd = new Random();
      
      
      
      
      while(true){
         long t = System.currentTimeMillis();
         
         x = (x+1)%199;
         points[x] = new Point(x, rnd.nextInt(100));
         
         this.validate();
         this.repaint();
         
         long d = t -System.currentTimeMillis();
         int wait = 25 - (int)d;
         if(wait>0)
            try {
               Thread.sleep(wait);
            } catch (InterruptedException e) { }
      }
      
   }
   
   
   @Override
   protected void paintComponent(Graphics g) {
      super.paintComponent(g);
      g.setColor(Color.black);
      g.fillRect(0, 0, 200, 100);
      
      g.setColor(Color.WHITE);
      for(int i =1; i < 200; i++){
         if(points[i-1] != null && points[i] != null)
            g.drawLine(points[i-1].x, points[i-1].y, points[i].x, points[i].y);
      }
      
   }


   
}
 

P@u1

Aktives Mitglied
Danke für deinen Beitrag!
Leider krieg ich folgenden Fehler wenn ich deine Klasse versuche zu benutzen:


C:\Dokumente und Einstellungen\MeinBenutzername\Desktop>javac HeartBeat
error: Class names, 'HeartBeat', are only accepted if annotation processing is e
xplicitly requested

Kann mit der Fehlerbeschreibung nicht wirklich was anfangen leider...
Wäre gut, wenn du mir nochmal kurz sagen kannst, was ich anders machen muss.

Und nen Download von dem Nebula Oscilliscope hab ich immer noch nicht gefunden, ich will das aber unbedingt haben.
Ich hab nur gefunden, wo ich die einzelnen Dateien runterladen kann, aber irgendwie fehlen da wenn ich nur die 3 . java Dateiene nehme ca. 100 imports und das ist dann nicht so das Wahre.
 

P@u1

Aktives Mitglied
ok, danke, jetzt funktionierts.
Ist nur etwas klein :D
Wenn man das ganze was größer macht wirds möglicherweise nicht mehr so besonders gut sein, befürchte ich.
Aber ich werd nochmal paar Sachen ausprobieren.

Nur ich würde wirklich sehr gerne das Nebula Oscilliscope zum laufen bringen, krieg es aber nicht runtergeladen...
Wär echt gut, wenn ihr mir helfen könnt.
Das ganze kann man irgendwie mit VCS runterladen, ich kriegs aber nicht hin...

Edit: Habs jetzt hinbekommen, allerdings sieht das für mich ziemlich kompliziert aus, das anzuwenden...
 
Zuletzt bearbeitet:

ARadauer

Top Contributor
Verwendest du deine IDE? Eclipse, Netbeans oder so?
Solche Dinge auf der Konsole compilieren und mit Notepad zu coden kannst vergessen...

allerdings sieht das für mich ziemlich kompliziert aus, das anzuwenden...
jup... java ist halt kein VisualBasic ;-)
Um solche Dinge zu benutzen, benötigt man schon ein bisschen Grundlagenwissen...

Wir helfen gerne, dazu musst du aber konkrete Fragen stellen... Viel Glück damit!
 
G

Gastredner

Gast
Edit: Habs jetzt hinbekommen, allerdings sieht das für mich ziemlich kompliziert aus, das anzuwenden...
Nun ja, Nebula erstellt Widgets für SWT und nicht für Swing - und die beiden GUI-Toolkits unterscheiden sich stark voneinander. SWT benötigt daher eine gewisse Eingewöhnungsphase, lässt sich anschließend meiner Meinung nach aber größtenteils sehr gut verwenden.
Schau dir am Besten einige der Snippets auf der SWT-Seite an, um grundlegende Dinge zu begreifen. Ansonsten solltestdu dir auch noch die entsprechenden Abschnitte im RCP-Buch ansehen, auch wenn dieses nur auf SWT im RCP-Kontext eingeht und keine eigenständigen SWT-Anwendungen beschreibt: Einführung SWT: Standard Widget Toolkit
 

P@u1

Aktives Mitglied
Hallo,

ich bins nochmal.

Der Zwischenstand ist jetzt folgender:
Ich hab das mit dem Nebula jetzt erstmal gelassen und habe eine eigene Lösung versucht umzusetzen.
Ich habs jetzt so gemacht, dass ich neue Werte draufmale und alte übermale, also nicht alles neumale.
Funktioniert auch sehr gut.
Das einzige Problem:
Wenn ich die Größe verändere oder minimiere und wieder maximiere oder ein Fenster im Vordergrund habe und das verschiebe, verschwindet die Zeichnung dahinter einfach.
Jetzt habe ich eine Methode geschrieben, die alles neu zeichnet, die ich genau in einem solchen Fall aufrufen möchte.
Ich habe den Aufruf der Methode jetzt in
Java:
@Override protected void paintComponent( Graphics g )
reingeschrieben.
Wenn ich jetzt z.B. davor ein anderes Fenster verschiebe, wird es wie gewollt aufgerufen und dann neugezeichnet, aber bei manchen anderen Sachen, wie z.B. minimieren und maximieren, funktioniert das leider nicht, bzw. sehr komisch.
Komischerweise klappt es manchmal, das nach dem maximieren nach einer ganz kurzen Wartezeit alles neu gezeichnet wurde. Meistens ist es aber so, dass wenn ich maximiere, dass dann ganz kurz die alten Linien sichtbar sind, die hoffentlich neu geziechnet wurden, oder kanns auch sein, dass die von vorher irgendwie noch da sind und dann weggehen? Das ist dann auch nur für einen Bruchteil einer Sekunde sichtbar und verschwindet dann...
Also ich bräuchte etwas Hilfe von euch, wäre gut, wenn ihr mir sagen könnt, wie ich diese Sachen am besten lösen kann.
Vielen Dank schonmal!

Edit:
Ich habe nochmal ein bischen mit dem Problem rumgespielt^^
und habe dabei sehr komische Sachen erlebt.
Erstmal gab es irgendwie einen Unterschied, ob ich zum malen graphics benutze, oder erst in graphics2D caste und ich habe mal das graphics was bei der paintComponent methode übergeben wird mit dem graphics, das bei getGraphics rauskommt verglichen und sie sind komischerweise nicht identisch, ich hatte eigentlich vermutet, dass beide ein Pointer auf das selbe Graphics objekt sind, dem ist aber irgendwie nicht so.
Wenn ich das graphicsobjekt, das ich kurz nach Start des Programms mit getGraphics geholt und in einem attribut gespeichert habe benutzt habe zum zeichnen, trat der Effekt wie vorher beschrieben auf, dass die Änderung nur ganz kurz aufflackert und dann verschwindet.
Nehme ich aber das Graphicsobjekt, das übergeben wird, dann funktioniert es richtig.
Allerdings passiert es dann irgendwie, dass irgendwas nicht mehr ganz synchron ist, was heißt, das das übermalen nicht mehr vollständig funktioniert und einige punkte aus irgendeinem Grund daneben gehen.
Im Moment habe ich jetzt eine relativ schlechte Notlösung genommen:
Ich habe von der paintComponent-Methode aus das Attribut refreshRequested auf true gesetz und beim normalen zeichnen der linien am anfang abgefragt und wenn es true ist, zeichne ich alles einmal neu und setze dann refreshRequested auf false.
Das funktioniert jetzt halbwegs gut, nur manchmal kommt es wenn man z.B. die Größe ändert vor, dass es nicht neugezeichnet wird, oder zu früh oder so und danach wieder übermalt wird oder so, zumindest ist es dann manchmal so, dass das Fenster nicht den schwarzen Hintergrund hat, der dann eigentlich gezeichnet werden soll, sondern die standardhintergrundfarbe grau/weiß hat...
Ich hoffe, ihr könnt das ungefähr nachvollziehen, ich brauche wenn möglich eine bessere Lösung.
Ich hatte gedacht einfach so und so oft neuzeichnen, aber das führt jedes mal zu einem kurzen unschönen Flackern...
Dann hab ichs mal mit nem BufferedImage versucht und aus irgendeinem Grund ist es dann wieder unsynchron geworden und einige Punkte sind daneben gegangen...
Ich weiß nicht mehr wirklich weiter....
 
Zuletzt bearbeitet:

Ähnliche Java Themen

Neue Themen


Oben