Graph darfstellen mit UTFT Library

Hallo zusammen,

ich benutze ein Mega2560 mit einem Display und möchte ein mobiles EKG programmieren.
Das klappt soweit so gut, allerdings habe ich ein Problem.

Ich zeichne meine Daten und habe im Hintergrund ein Raster.
Bin ich am Ende des Displays angekommen, so beginne ich von vorne und lösche die vorherigen Daten ähnlich der “moving-sinus-wave” aus dem UTFT Beispiel.

Jetzt zu meinem Problem: Überschreibe ich die alten Daten mit weißen Pixeln, so überschreibe ich auch mein Raster und habe somit weiße Flecken. Daher meine Frage, ob es eine Möglichkeit gibt, das Raster nicht mit weißen Pixeln überschreiben zu können?

Ich habe euch mal ein Bild angehängt zur veranschaulichung. Ich hoffe es ist einigermaßen verständlich.

Ich bin für jeden tipp dankbar.

Danke und viele Grüße

Du kannst das Raster neu zeichnen. Horizontale und vertikale Linien gehen eigentlich sehr schnell, da kaum was gerechnet werden muss.

Wirklich flüssig wird es natürlich nicht werden. Dafür sind ist sind die 8 Bit Arduinos einfach zu langsam

grfa1012: Ich bin für jeden tipp dankbar.

Zuerst wollte ich schreiben, dass Du das ganze Bild löschen und die Gitterlinien neu zeichnen kannst (ich nehme an, dass das ist, was Serenifly vorschlägt).

Nachdem ich das Foto eine Weile angeguckt habe, scheint mir aber, dass die jeweils neuen Daten die alten überschreiben sollen. Dann bleibt Dir IMO nichts anderes übrig, als eine „Bitmap“ anzulegen, in der nur das Gitter enthalten ist. Und beim Löschen der alten Daten prüfst Du bei jedem Pixel, ob es in der Bitmap an der gleichen Position ein „Gitterpixel“ gibt oder nicht. Dann hast Du allerdings das Problem, dass das Gitter an manchen Stellen die Farbe der Kurve hat, es sei denn, Du malst an den entsprechenden Stellen ein rotes statt weißes Pixel.

HTH

Gregor

gregorss: Dann bleibt Dir IMO nichts anderes übrig, als eine „Bitmap“ anzulegen, in der nur das Gitter enthalten ist.

Das dauert ewig. So ein Gitter kann man einfach und schnell erzeugen wenn man in einer for-Schleife immer die Koordinaten der Linien inkrementiert.

Serenifly: Das dauert ewig. So ein Gitter kann man einfach und schnell erzeugen wenn man in einer for-Schleife immer die Koordinaten der Linien inkrementiert.

Das stimmt. Statt mit einer Kontroll-Bitmap zu hantieren, dürfte es wesentlich schneller gehen, für jedes zu löschende Pixel per Rechnung zu prüfen, ob es auf einer Gitterlinie liegt.

Gruß

Gregor

Hallo, schaue mal nach, ob Dein Display einen ansprechbaren Speicher für eine "zweite" Seite hat. Die kannst Du nach dem löschen aufrufen.

Oder- NextionDisplay, die haben einen frei konfigurierbaren "OzziSchirm" on Board- und sind sau schnell. Du brauchst nur Werte übertragen, Rest macht das Nextion. Suche mal auf YouTube nach. Gruß und Spaß Andreas

Keine Ahnung, ob ein Mega2560 schnell genug ist, aber warum keinen scrollenden Graphen?

So hier.

  1. bis letzte Displayspalte um eine Spalte nach links kopieren und anschließend den neuen Messwert in die letzte Spalte schreiben.

Rasterzeichnung entsprechend anpassen, so dass alle x Samples die Punkte in die letzte Spalte gezeichnet werden.

Ggf. einen Teensy nehmen, um das Display etwas flotter anzusteuern.

Gruß, H.

Hallo, er möchte es aber so: Nextion das geht aber wesentlich schneller. Gruß und Spaß Andreas

Hi, verstehe.

Ein mitlaufendes Raster wäre einfacher und auch schöner, aber wenn er das nicht will, dann ist das eben so.

Wenn ein Nextion (mir unbekannt) das alles intern macht und man nur die Messwerrte hinschicken muss ist ja alles fein.

Beste Grüße, H.

gregorss: Das stimmt. Statt mit einer Kontroll-Bitmap zu hantieren, dürfte es wesentlich schneller gehen, für jedes zu löschende Pixel per Rechnung zu prüfen, ob es auf einer Gitterlinie liegt.

Gruß

Gregor

Das wäre eigentlich die beste Option. Vorgabe ist es eben, dass ich die alten Daten so löschen soll wie beschrieben.

Allerdings stellt sich hier das Problem. Ich habe 41 Linien von x=30 bis x=750 und nochmal mehr Linien von y=30 bis y=460. Das kann ich alles nicht so einfach und schnell abfragen oder?

Zum besseren Verständnis: Video

Bei 1:17 min in diesem Video kann man ungefähr sehen, wie es aussehen soll, allerdings möchte ich einen größeren Abstand zwischen alten und neuen Werten.

Das Raster brauche ich aber unbedingt um es besser interpretieren zu können.

Hallo, ja, das sind die üblichen Diagramme die jeder mit dem Arduino kritzelt. Wie gesagt, am besten mit einem Display, das zwei Seiten hat. Dieses nutze ich z.B. http://www.exp-tech.de/adafruit-3-5-tft-320x480-touchscreen-breakout-board-w-microsd-socket Das hat zwei Seiten, die man unabhängig voneinander beschreiben kann. Für lfd. Grafen ist die Lib/Arduino oder TFT aber zu langsam. Das Raster nach dem überschreiben wieder herzustellen, halte ich in Anbetracht der Leistungen Arduino, Lib und TFT für nicht realisierbar. Es sei den, Du gibst mit 1S/sek wieder.

Wie gesagt, wenn Du das ernsthaft betreiben willst, dann würde ich das mit einem Nextion machen. Du brauchst Dir das Display noch nicht einmal kaufen. Lade Dir einmal den NextionEditor runter. Der simuliert Dir das Display 1:1 und läßt sich vom Arduino mit den Integer Werten bedienen und gibt sie, wie von Dir gewünscht wieder. Gruß und Spaß Andreas

grfa1012: Allerdings stellt sich hier das Problem. Ich habe 41 Linien von x=30 bis x=750 und nochmal mehr Linien von y=30 bis y=460. Das kann ich alles nicht so einfach und schnell abfragen oder?

Das kann man mit einer Modulo Division machen. z.B. wenn der Abstand der Linien 10 Pixel ist, dividiert man die Koordinate durch 10 und wenn der Rest 0 ist liegt man auf der Linie.

Hallo,

Hier macht das jemand, aber kein normales TFT

das scheint aber möglich zu sein

mußt Du Dir mal das richtige suchen, da scheint es ja schon fertige Lösungen zu geben. Gruß und Spaß Andreas

// Three color Fast analog Oscilloscope
// By Bob Davis
// UTFT_(C)2012 Henning Karlsen
// web: http://www.henningkarlsen.com/electronics
//
#include <UTFT.h>
#ifdef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#endif
#ifdef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif
// Declare which fonts we will be using
extern uint8_t SmallFont[];
extern uint8_t BigFont[];
//extern uint8_t SevenSegNumFont[];
UTFT myGLCD(ITDB43,38,39,40,41);
int Input=0;
int OldInput=0;
int MaxSample=0;
int MinSample=0;
int Sample[480];
int OldSample[480];
int StartTime=0;
int EndTime=0;
int rate=1;

void DrawMarkers(){
  myGLCD.setColor(0, 200, 0);
  myGLCD.drawLine(0, 0, 0, 240);
  myGLCD.drawLine(54, 0, 54, 240);
  myGLCD.drawLine(107, 0, 107, 240);
  myGLCD.drawLine(160, 0, 160, 240);
  myGLCD.drawLine(213, 0, 213, 240);
  myGLCD.drawLine(266, 0, 266, 240);
  myGLCD.drawLine(319, 0, 319, 240);
  myGLCD.drawLine(372, 0, 372, 240);
  myGLCD.drawLine(425, 0, 425, 240);
  myGLCD.drawLine(478, 0, 478, 240);
  
  myGLCD.drawLine(0, 0, 479, 0);
  myGLCD.drawLine(0, 50, 479, 50);
  myGLCD.drawLine(0, 100, 479, 100);
  myGLCD.drawLine(0, 150, 479, 150);
  myGLCD.drawLine(0, 200, 479, 200);
  myGLCD.drawLine(0, 239, 479, 239);
}

void setup() {
  myGLCD.InitLCD();
  myGLCD.clrScr();
  myGLCD.setBackColor(0, 0, 0);
  myGLCD.setFont(BigFont);
}

void loop() {
  // set color(Red, Green, Blue) range = 0 to 255
  char buf[12];
  while(1) {
    // Set sample speed according to switch on A1
      if (analogRead(A1) < 500){
      cbi(ADCSRA, ADPS2);
      rate=0;
    }
    else {
      sbi(ADCSRA, ADPS2);
      rate=1;
    }
    DrawMarkers();
    // wait for a trigger of a positive going input
    OldInput=analogRead(A1);
    Input=analogRead(A1);
    while (Input < OldInput)
    {
      Input=analogRead(A1);
    }
    // collect the analog data into an array
    // do not do division here, it makes it slower!
    StartTime = micros();
    for(int xpos=0; xpos<481; xpos++) {
      Sample[xpos]=analogRead(A1);
    }
    EndTime = micros();
    // display the collected analog data from array
    // Sample/4.1 because 1024 becomes 250 = 5 volts
      for(int xpos=0; xpos<481; xpos++) {
      myGLCD.setColor( 0, 0, 0);
      myGLCD.drawLine (xpos, OldSample[xpos]/4.1, xpos+1, OldSample[xpos+1]/4.1);
      myGLCD.setColor(255, 255, 255);
      myGLCD.drawLine (xpos, Sample[xpos]/4.1, xpos+1, Sample[xpos+1]/4.1);
    }
    // Determine sample voltage peak to peak
    MaxSample = Sample[10];
    MinSample = Sample[10];
     myGLCD.setColor(200, 0, 0);
    for(int xpos=0; xpos<481; xpos++) {
      OldSample[xpos] = Sample[xpos];
      if (Sample[xpos] > MaxSample) MaxSample=Sample[xpos];
      if (Sample[xpos] < MinSample) MinSample=Sample[xpos];
    }
    // Display sample voltage and time
    myGLCD.setColor(0, 0, 255);
    int SampleSize=MaxSample-MinSample;
    myGLCD.print("MV=     ", 1, 248);
    myGLCD.print(itoa(SampleSize, buf, 10), 44, 248);
    int SampleTime=EndTime-StartTime;
    myGLCD.print("uS=    ", 161, 248);
    // Adjust time according to sample speed
    if (rate==1) {
      SampleTime=(EndTime/1000-StartTime/1000);
      myGLCD.print("mS=     ", 161, 248);
    }
    myGLCD.print(itoa(SampleTime, buf, 10), 210, 248);
  }
}

probier mal ob dir das weiterhilft
Gruß Matthias

Erwähnte ich schon, das ein Teensy für solche Jobs besser geeignet ist?

Könnte dann so aussehen.

Gruß, H.