Seite 2 von 4

Verfasst: 20.02.2007 21:54
von Toshy
Also da es nur kurze Datenblöcke sind (die Werte), kann man Problemlos ein Array nutzen. Wichtiger ist wohl, das die Daten lückenlos aufgezeichnet werden. Bei allen Dingen wo ich optimal Daten speichern will, mache ich es grundlegend so:
Ich nutze DREI Speicherstrukturen. Zwei sind "identisch" und meißt statisch, in eines dieser lese ich die Daten ein, nach einem bestimmten Zeitintervall (Millisekunden,Sekunden,Minuten-> hängt vom Programm ab) wechsele ich auf den zweiten Speicher und der erste kann so ausgelesen werden. Dann kopiere ich diese Daten in den Dritten rein. Ich nutze also zwei Buffer und einen "Hauptspeicher". Beim "umkopieren" ist dann nur wichtig, das dies nicht in einem Rutsch geschieht, sondern Stückweise, damit das auslesen der Daten nicht stoppt. Hierzu würde sich ein zweiter Thread anbieten, was aber nicht unbedingt sein muß.

Eine Million Datensätze sind ja gar nicht so viel. Wenn die Daten in ein Long oder gar nur Word oder Byte geschrieben werden, kommt das nicht viel zusammen, selbst wenn man X und Y-Werte speichert. Ein paar Megabyte RAM auf 20h sind ja extrem wenig. So ein Programm bekommt man wohl auch einem 100Mhz-Rechner problemlos zum laufen :-)

Lege also beispielweise zwei Arrays an, jeweils mit z.B. 10.000 Elementen und dann einer Variable welche die genutzte Anzahl zählt. Sind alle Elemente gefüllt, wird der zweite Array benutzt und der erste kann umkopiert werden. Die aktuellen Daten aus dem gerade zum schreiben genutzten Buffer kann man natürlich auch nutzen um sie in eine aktuelle Anzeige auszugeben. Aber wie man das macht, bleibt jedem überlassen.

Verfasst: 21.02.2007 11:13
von #NULL
vielleicht macht es sinn ein long-array zu nehmen, und für den x- und den y-wert jeweils die zwei ersten bzw die zwei letzten bytes zu benutzen. dann hast du ein long pro koordinate.

Verfasst: 21.02.2007 15:05
von NicTheQuick
Hab mal was kleines gebastelt. Hatte grad ein wenig Zeit.

Code: Alles auswählen

Global Hz.l = 20  ;Auflösung in Hertz (Messwerte pro Sekunde)
Global MaxValue.l = 20 * 60 * 60 * Hz ;Maximaler Wert für das Array (20 Std. zu 20 Hz)
Global Dim Value.POINT(MaxValue)  ;Array für die Werte
Global ActValue.l = 0 ;Der aktuelle Index des Arrays
Global MousePos.POINT ;Die aktuelle Position der Maus
Global MouseReset.POINT ;Die Nullpunkt-koordinate der Maus
Global IsMeasuring.l = #False ;#True, wenn die Messung gerade läuft
Global IsPlaying.l = #False ;#True, wenn die Messung gerade abgespielt wird
Global ActValuePlay.l ;Aktueller Index beim Abspielen
Global PlayingWidth.l, PlayingHeight.l, PlayingMinPeek.POINT, PlayingMaxPeek.POINT, PlayingDeltaPeek.POINT

InitSprite()

Procedure EndMeasure() ;Beendet Messung
  If IsMeasuring
    EndTimer(0) ;Stoppe den Timer
    IsMeasuring = #False
    
    ProcedureReturn ActValue - 1
  EndIf
  ProcedureReturn #False
EndProcedure
Procedure Measuring() ;Misst
  Protected Mouse.POINT
  
  If ActValue > MaxValue  ;Falls der Index höher ist als zulässig
    EndMeasure()
    ProcedureReturn
  EndIf
  
  GetCursorPos_(Mouse)  ;Nimm die Mauskoordinaten
  SetCursorPos_(MouseReset\x, MouseReset\y) ;Stelle den Mauscursor wieder zurück
  
  MousePos\x + Mouse\x - MouseReset\x ;Addiere die Änderung zum Nullpunkt der aktuellen Position
  MousePos\y + Mouse\y - MouseReset\y
  
  Value(ActValue)\x = MousePos\x  ;Weise die aktuelle Position dem Array zu
  Value(ActValue)\y = MousePos\y
  ActValue + 1  ;Erhöhe den Index um 1
EndProcedure
Procedure NewMeasure() ;Startet Messung
  If IsMeasuring = #False
    SetCursorPos_(MouseReset\x, MouseReset\y) ;Setze die Maus in den Nullpunkt
    MousePos\x = 0
    MousePos\y = 0
    
    ActValue = 0
    If StartTimer(0, 1000 / Hz, @Measuring())  ;Starte den HighResolution-Timer
      IsMeasuring = #True
      ProcedureReturn #True
    EndIf
  EndIf
  ProcedureReturn #False
EndProcedure

Procedure Save(File.s) ;Speichert Messung
  Protected FileId.l
  
  If FileSize(File) <> -1
    If MessageRequester("Speichern", "'" + File + "' existiert bereits." + Chr(13) + "Datei überschreiben?", #PB_MessageRequester_YesNo) = #PB_MessageRequester_No
      ProcedureReturn #False
    EndIf
  EndIf
  
  FileId = CreateFile(#PB_Any, File)
  If FileId
    WriteLong(FileId, Hz)
    WriteLong(FileId, MaxValue)
    WriteData(FileId, @Value(), (MaxValue + 1) * SizeOf(POINT))
    CloseFile(FileId)
    ProcedureReturn #True
  EndIf
  
  ProcedureReturn #False
EndProcedure
Procedure Load(File.s) ;Lädt Messung
  Protected FileId.l
  
  FileId = ReadFile(#PB_Any, File)
  If FileId
    Hz = ReadLong(FileId)
    MaxValue = ReadLong(FileId)
    Redim Value.POINT(MaxValue)
    ReadData(FileId, @Value(), (MaxValue + 1) * SizeOf(POINT))
    CloseFile(FileId)
    ProcedureReturn #True
  EndIf
  
  ProcedureReturn #False
EndProcedure

Procedure MaxPeek(*Peek.POINT)
  Protected a.l
  *Peek\x = 0
  *Peek\y = 0
  
  For a = 0 To MaxValue
    If Value(a)\x > *Peek\x : *Peek\x = Value(a)\x : EndIf
    If Value(a)\y > *Peek\y : *Peek\y = Value(a)\y : EndIf
  Next
EndProcedure
Procedure MinPeek(*Peek.POINT)
  Protected a.l
  *Peek\x = 0
  *Peek\y = 0
  
  For a = 0 To MaxValue
    If Value(a)\x < *Peek\x : *Peek\x = Value(a)\x : EndIf
    If Value(a)\y < *Peek\y : *Peek\y = Value(a)\y : EndIf
  Next
EndProcedure

Procedure StopPlaying()
  If IsPlaying
    EndTimer(1)
    IsPlaying = #False
    
    ProcedureReturn ActValuePlay - 1
  EndIf
  
  ProcedureReturn #False
EndProcedure
Procedure Playing()
  Protected x.l, y.l
  
  If ActValuePlay > MaxValue
    StopPlaying()
    ProcedureReturn
  EndIf
  
  ClearScreen(0)
  
  x = (Value(ActValuePlay)\x - PlayingMinPeek\x) * PlayingWidth  / PlayingDeltaPeek\x
  y = (Value(ActValuePlay)\y - PlayingMinPeek\y) * PlayingHeight / PlayingDeltaPeek\y
  ActValuePlay + 1
  
  StartDrawing(ScreenOutput())
    Circle(x, y, 4, $FFFFFF)
  StopDrawing()
  
  FlipBuffers(0)
EndProcedure
Procedure PlayMeasure(Width.l, Height.l, *min.POINT = 0, *max.POINT = 0)
  If IsPlaying = #False
    ActValuePlay = 0
    
    PlayingWidth = Width
    PlayingHeight = Height
    If *min
      PlayingMinPeek\x = *min\x
      PlayingMinPeek\y = *min\y
    Else
      MinPeek(PlayingMinPeek)
    EndIf
    If *max
      PlayingMaxPeek\x = *max\x
      PlayingMaxPeek\y = *max\y
    Else
      MaxPeek(PlayingMaxPeek)
    EndIf
    PlayingDeltaPeek\x = PlayingMaxPeek\x - PlayingMinPeek\x
    PlayingDeltaPeek\y = PlayingMaxPeek\y - PlayingMinPeek\y
    
    If StartTimer(1, 1000 / Hz, @Playing())
      IsPlaying = #True
    EndIf
  EndIf
EndProcedure

ExamineDesktops() ;Lege den Nullpunkt in der Mitte des ersten Desktops fest
MouseReset\x = DesktopWidth(0) / 2
MouseReset\y = DesktopHeight(0) / 2

; MESSEN
Define EndValue.l
MessageRequester("Messen", "OK drücken, um die Messung zu beginnen. Sie wird 5 Sekunden dauern.")

If NewMeasure()
  Delay(5000)
  EndValue = EndMeasure()
EndIf

MessageRequester("Ende", "Die Messung wurde beendet und es wurden insgesamt " + Str(EndValue + 1) + " Werte gespeichert.")

; DARSTELLEN
Define Width.l = 800, Height.l = 600

OpenWindow(0, 0, 0, Width, Height, "Player", #PB_Window_ScreenCentered | #PB_Window_SystemMenu | #PB_Window_SizeGadget)
OpenWindowedScreen(WindowID(0), 0, 0, Width, Height, #True, 0, 0)

PlayMeasure(Width, Height)

Delay(6000)

StopPlaying()

CloseWindow(0)
Nach Drücken auf OK, werden 5 Sekunden lang mit 20 Messungen pro
Sekunde genau 100 Werte gespeichert. Nach weiterem Klick auf OK, wird
das ganze in einem 800x600-Fenster wieder abgespielt. Dabei werden die
Messwerte allerdings auf x- und y-Achse unterschiedlich stark skaliert.

Wichtig: PBOSL mit der Timer-Library wird benötigt.

Verfasst: 21.02.2007 19:41
von RolandIV
es sollten auch alle bisher gemachten messwerte noch während der messung ausgelesen werden...

ich ahtte schonmal so ein programm geschrieben, allerdings nur für messungen über 20 minuten etwa.

da gings in screen, mausbewegung wurde aufgezeichnet und die x-koordinate der maus immer in kleinen abständen weiterbewegt. damit nicht vor jedem flipbuffers alles neu gezeichnet werden musste, habei ch einfach clearscreen weggelassen, weil ja sosnt alle punkte einzeln wieder angezeigt werden müssten. aber das ist ja nicht gerade eine elegante methode.

@nic: interessanter ansatz das so aufzuzeichnen, mit dem ´vergrößern danach wieder. probnlem is immer, dass ich alles für pb 3.9 umcoden muss ^^ aber noch gings

Verfasst: 22.02.2007 12:35
von Kaeru Gaman
dann schreib bitte deine version in die signatur.
mal Updaten wär bestimmt auch nicht schlimm...
oder hast du ne riesen menge code in 3.9 vorliegen?
btw. du kannst auch verschiedene versionen parallel installiert haben,
ich hab bei mir 3.30, 3.94 und 4.02 drauf.
außerdem gibts nen code-konverter für 3.9->4.0


soweit ich dich verstanden hatte, ging es nur um einen y-meßwert,
und nicht um ein koordinatenpaar, oder?

wobei mich noch interessieren würde,
ob du die hauptmessung wirklich am Mauseingang durchführst,
oder ob du eine extra-maus an einem extra abgefragten Port angeschlossen hast.

wenn du mit einem globalen Array arbeitest, ist eigentlich problemloser
zugriff auf sämtliche bereiche möglich, auch von mehreren threads aus.
du musst lediglich sicherstellen, dass du nicht von mehreren routinen aus gleichzeitig schreiben willst.
aber das was du planst - thread1 schreibt kontinuierlich werte, thread2 liest aus für grafikdarstellung, thread3 liest aus für rückspeichern auf platte - ist relativ einfach und effektiv.

die idee von Toshy mag für andere anwendungen sinnvoll sein.

------------------------------------------------------------
#NULL hat geschrieben:vielleicht macht es sinn ein long-array zu nehmen, und für den x- und den y-wert jeweils die zwei ersten bzw die zwei letzten bytes zu benutzen. dann hast du ein long pro koordinate.
schau dir mal die native struktur COORD an. ;)

Verfasst: 22.02.2007 16:19
von RolandIV
kostet das update ab 3.9 nicht geld?? ich dachte, das wär nicht mehr kostenlos wie früher?!
den meisten code habe ich natürlich für versionsn <3.9

okay das mit den threads werde ich wohl machen...

allerdings kann ich für die bildschirmdarstellung nicht in jedem frame 100000 werte auslesen. das haut doch jeden rechner um, wie könnte man das eleganter lösen?

Verfasst: 22.02.2007 16:30
von ts-soft
>> kostet das update ab 3.9 nicht geld??
Alle Updates sind lebenslänglich frei :wink:
Ausnahme: PB 3.3 Topos Version. Hier kostet das Update einmalig für
lebenslang.

Alle User, die nicht die aktuelle Version (4.02) verwenden, sollten Ihre
Version in die Signatur schreiben, dann kann man besser drauf eingehen.

PS: Den Hasen nicht zu vergessen!
-\/-------------------------------------

Gruß
Thomas

Verfasst: 22.02.2007 16:52
von Kaeru Gaman
> kostet das update ab 3.9 nicht geld?? ich dachte, das wär nicht mehr kostenlos wie früher?!
nö.. wieso?
es hieß "lebenslang kostenfreie updates" ;)

> allerdings kann ich für die bildschirmdarstellung nicht in jedem frame 100000 werte auslesen.
brauchst du ja auch nicht, oder ist dein screen 100.000 pixel breit? :?
es genügt, immer soviele werte auszulesen, wie der screen breit ist.

Code: Alles auswählen

InitSprite()
InitKeyboard()
OpenWindow(0,0,0,600,300,"Werte Display", #PB_Window_ScreenCentered | #PB_Window_SystemMenu )
OpenWindowedScreen(WindowID(0),0,0,600,300,0,0,0)
Global Dim Werte.l(99999)
For n=0 To 99999 : f.f = n : Werte(n) = Sin(#PI * f / 200)*100 + Sin(#PI * f / 20)*40 + Random(20)+140 : Next
Pos = 5000 : Scale = 1
Repeat
  ExamineKeyboard()
  EVT = WindowEvent()
  If KeyboardPushed(#PB_Key_Left) And Pos > 0 : Pos -4 : EndIf
  If KeyboardPushed(#PB_Key_Right) And Pos < 99999-2400 : Pos +4 : EndIf
  If KeyboardReleased(#PB_Key_PageDown) : Scale = 1  : EndIf
  If KeyboardReleased(#PB_Key_PageUp) : Scale = 2  : EndIf
  
  If KeyboardPushed(#PB_Key_Escape) Or EVT = #PB_Event_CloseWindow : EXIT = 1 : EndIf
  ClearScreen($402010)
  StartDrawing(ScreenOutput())
    FrontColor($80C020)
    For n=0 To 600
      APos = Pos+n*Scale
      LineXY(n,Werte(APos),n+1,Werte(APos+Scale))
    Next
  StopDrawing()
  FlipBuffers()
Until EXIT = 1

Verfasst: 22.02.2007 19:21
von RolandIV
nein du musst dir das so vorstellen, die maus zeiht am bildschirm eine bahn und es werden in jedem durchlauf die positionen gespeihert. währenddessen rückt die maus automatisch um einen pixel nach rechts, das heißt, es entsteht eine spur wie etwa die hier http://www.math.uni-frankfurt.de/~fereb ... ingung.gif

nur halt viiel mehr schwingungen also alles viel enger und nicht so starke dämpfung wie auf dem bild... das heißt auf jeden x-wert kommen mehrere y-werte je nach stärke der x-verschiebung, da das pendel ja nur in y-richtung hin und her schwingt. da kommen vllt bis zu 100.000 pro screen schon drauf und bei jedem durchlauf für 100.000 plots die werte auszulesen?? das verlangsamt doch alles enorm

habe einmal für so einen "updatecode" bezahlt wenn ich mich recht entsinne ist schon ein paar jährchen her, letztes update war wohl auch iwann 2005 schätz ich mal (hatte jahr pause gemacht ca). Und ich hatte eben gehört, dass ich für weitere updates nochmal son ding holen muss nd geld bezahlen muss, das seh ich aber nicht ein

Verfasst: 22.02.2007 21:21
von Kaeru Gaman
also, die umsetzung finde ich ziemlich unpraktisch...
ich würde da einfach etwas schneller nach rechts rücken,
damit du weniger werte auf einmal aufm screen haben musst.

ich würd sowieso das anders umsetzen als über die maus,
die zur bedienung da ist...


> Und ich hatte eben gehört, dass ich für weitere updates nochmal son ding holen muss nd geld bezahlen muss

und wer bitteschön erzählt so nen unfug? :?

wenn du eine vollversion hast, dann musstest du die einmal bezahlen,
und kannst immer wieder updaten.

wenn du ursprünglich die 3.30 gekauft hast, die es preisgünstig in der schachtel gab,
dann musstest du ein mal eine gebühr zahlen, um zukünftig updaten zu können.