26. juli 2004 - 16:26Der er
39 kommentarer og 2 løsninger
Tegning af kurve ved temperaturmåling.
Eksperthjælp søges!
Jeg er ved at lave et program til opsamling af måledata fra en temperaturføler. Indtil videre bliver temperaturen vist ved hjælp af en label, men det skulle gerne være muligt at se temperatur udviklingen, f.eks. over de sidste 2 minutter. Dette skal ske ved, at der bliver tegnet en ”real time” kurve (i stil med en løgndetektor), hvor ”papiret” bevæger sig. Skalleringen af X og Y aksen skal være programmerbar, således at der kan vælges f.eks. 10 sek. i stedet for de 2 min. osv. Til sidst skal det være muligt at gemme målingen (ikke kun grafisk, men også alle måledata), såledet, at den kan hentes frem igen på et senere tidspunkt.
Den aktuelle temperatur ligger i et word.
Hvordan laver man sådan en ”trendviewer”, og hvordan gemmes de målte data?
Det vil selvfølgelig være fedt med konkrete informationer til projektet, men ellers links til noget brugeligt.
Værsgo.. Nedenstående er ikke frembragt af Delphi, men af et andet måleprogram. Er det sådan noget lignende, jeg skal have frem, før jeg kan generere en kurve?
-> Borrisholt. Jeg har downloadet kbmMemTable v.3.01, og lagt alle filerne i samme mappe som indeholder filerne du har lavet. Når jeg så forsøger at køre projektet fra Delphi, viser compileren "Undeclared identifier" + andre fejl gennem hele unit "kbmMemTable". Når jeg følger installation.txt filens beskrivelse af, hvordan kbmMemTable skal indstalleres, får jeg her en "read error on 'c:\programme\borland\delphi\Lib\vcl.dcp" fejl.
Hvis jeg åbner Projekt1.exe filen direkte, kører projektet uden problemer.
Håber du forstår, hvad jeg mener, og kan forklare, hvad der er galt!
Det, jeg skal bruge i sidste ende, er dog en ”real time” opdatering af temperaturen, således, at grafens baggrund hele tiden bevæger sig mod venstre (evt. mod højre), og kurven derved altid viser f.eks. de sidste 10 sek.(skal være valgbart) opdatering (i stil med en løgndetektor eller jordskælvdetektor(!), hvor papiret bevæger sig).
Temperaturen ligger som et word, der bliver opdateret 100 gange i sek. i Delphi programmet. Det vil sige, at opdateringen allerede foregår med en timer, og skal således ”bare” skives til en eller anden form for liste, og vises som en graf. Jeg kom et godt stykke længere med de sidste forslag, men mangler stadigvaek det med ”real time” opdateringen. Er det noget du/I har tid/lyst til at kigge på? :-)
Hvad mener du i øvrigt med, at din løsning ikke er så hurtig som Borrisholts?
Hvad mener du med "Temperaturen ligger som et word" ? Den Tstringlist jeg har lavet adder du bare nye målinger til og læser listen bagfra med (tid * 100) alt sammen pakket ind i en timer.
Vedr. hastighed så er Borrisholt's hurtigere end min, man opdager det bare ikke med dagens PC'ere. Men du kan prøve at måle med Gettickcount.
Jeg mener, at dataformatet er et word (temperaturen ligger i dette tilfælde som en 12 bits værdi, dvs. mellem 0 og 4096), som jeg så efterfølgende skallere om til at vise temperaturen i grader celcius (float).
Når du skriver, at jeg skal lægge nye målinger til, bliver de nye målinger vel bare vist sammen med de "gamle", således at det man ser på skærmen ikke altid kun er f.eks. de sidste 10 sek? Ligesom hvis jeg trykker flere gange på knappen "Indlæs", bliver de indlæste målinger lagt til de eksisterende på skærmen, i stedet for at erstatte dem.
Som du selv er inde på, kan man vel bare læse listen bagfra, og så definere, hvor mange sekunder man vil tage med af listen.
Stoney>> Dit eksempel er meget godt, men jeg vil lige angribe et enkelt punkt.
Jeg bryder mig ikke om du piller i DecimalSeparatoren det er en uskik, og en levn fra gamle dage, hvor man ikke havde TFormatSettings. js_Delphi nævner eksplisit Delphi 7, og derfor bruger jeg TFormatSettings. I øvrigt er det Thread safe, hvilket ikke er en uvæsenlig parameter.
js_delphi>> Hvis instalation af komponenter volder dig problemer, kan jeg godt lave en version hvor man sætter den på dynamisk, men jeg synes nu det er det bedste at du finder ud af hvordan man instalerer dem ;) En TMemTable kan bruges til mange ting !
1. Hvorfor skal han overhovedet bruge en memtable? Er temperaturer ikke noget man plejer at banke i en (filbaseret)tabel for derefter at køre en query på data? Men ja, en memtabel er en fin lille tingest.
2. Hvad er det der er galt med DecimalSeparatoren? Jeg plejer selv at bruge denne opbygning:
OldDecSep := DecimalSeparator; DecimalSeparator := '.'; try // ... En query der arbejder med decimaltal finally DecimalSeparator := OldDecSep; end;
hrc> 1) Jeg vil bruge en Database, fordi så kunne man smide det direkte i et Chart ting, og lave databehandling på dem senere. Det der med først at impotere dem fra en fil var noget jeg lavede fordi jeg ingen Live målinger har.
2) Download mit eksempel og se. Den vil sikkert brokke sig over du ikke har TMemTable instaleret, men bare ignorer det, fordi det er jo det andet du er kommet efter. Det er lidt lettere at se hvad jeg mener me rigtig kode.
-> Stoney: Det med at rydde charten var jo meget logisk - bare ikke for mig... Jeg mangler stadigvæk muligheden for at bestemme, hvor mange af de sidste målinger (eller sek.) jeg vil have med fra listen. Så vidt jeg kan forstå, indlæser den hele textfilen, som programmet kører nu. En andet ting er, at jeg på et eller andet tidspunkt skal til at se på, hvordan jeg får de nye målinger skrevet til denne liste!
-> Borrisholt: Hvad mener du med en version, "hvor man sætter den på dynamisk"? Mht. problemerne ved at bruge "decimalSeparatoren": er det mere usikkert at bruge denne metode (bliver programmet mere ustabilt - læs: går ned), eller hvori ligger problemerne? Jeg synes umiddelbart Stoneys metode virker enklest, men når jeg på et senere tidspunkt skal til at gemme mine målinger, udskrive osv., kan det måske være, at din metode er den rigtige. Hvad siger du til det?
Jeg troede du fik målingerne fra et delphi program. Nå, men hvis du vil læse de nyeste målinger læser du filen bagfra på denne måde:
Ændre denne linie for i := 1 to sl.Count -1 do til for i:= sl.Count-1 downto (sekunder * 100) do
Hvis du får målingerne fra et delphi program ligger du bare målingerne i en Tstringlist og læser direkte fra memory i stedet for en txt fil. Det går også meget hurtiger.
Ændringen i linien medfører, at hvis alle målingerne i .txt filen er 15 sek. i alt, og jeg skriver 10 sek. i linien "for i:= sl.Count-1 downto (sekunder * 100) do", så får jeg de sidste 5 sek. at se på kurven. Dvs., det tal jeg skriver, angiver hvor mange sek. af starten, jeg ikke vil have med.
Ang. hvor målingerne kommer fra:
som udgangspunkt eksisterer der slet ikke nogen .txt fil. Hver gang "procedure TForm1.Timer1Timer(Sender: TObject);" bliver aktiveret, læses værdien af integer "Temperatur". Lige så snart værdien er blevet læst, skal den gemmes et eller andet sted (i RAM eller på harddisk, hvad ved jeg...). Næste gang "procedure TForm1.Timer1Timer(Sender: TObject);" bliver aktiveret, læses værdien igen, og denne gang gemmes værdien det samme sted, men selvfølgelig som en ny linie. Delphi læser hele tiden værdierne fra dette sted, og opdaterer dermed kurven.
Når man så vælger at stoppe timeren (enable := false), stopper opdataringen af målingerne selvfølgelig. Når det er gjort, skal det være muligt at gemme de målte data, evt. som en .txt fil.
Hvis man på et senere tidspunkt så ønsker at se en gammel måling, skal denne, klart nok, læses fra den gemte .txt fil.
Sorry, hvis jeg ikke har beskrevet det godt nok tidligere..
Hvordan målingerne ser ud, afhænger af, hvordan det laves i Delphi, da Delphi programmet jo aflæser temperaturen, og derefter genererer listen. Jeg kunne forestille mig, at denne liste så sådan ud:
Første linie bliver genereret første gang "procedure TForm1.Timer1Timer(Sender: TObject);" bliver aktiveret
Anden linie anden gang "procedure TForm1.Timer1Timer(Sender: TObject);" bliver aktiveret osv.
Værdierne i kollone "ChanA", er temperaturen i en ovn, og bliver læst fra et word (integer) i Delphi programmet.
Værdierne i kollone "ChanB", er temperaturen uden for ovnen, og bliver læst fra et andet word (integer) i Delphi programmet.
I første omgang behøves der kun at tages hensyn til "ChanA", da jeg efterfølgende selv kan tilføje resten (håber jeg...).
Hvis brugeren vælger at gemme målingerne, efter han har stoppet opdateringen, er det fint med mig, hvis de bliver gemt som en .txt fil, eller noget andet standart, som f.eks. .csv (kommasepareret).
Den .txt fil jeg har sendt til dig, er genereret af et andet måleprogram, som jeg slet ikke skal bruge i denne sammenhæng.
Det ser sgu godt ud! Men... De nye data bliver stadigvæk "lagt til" de data, som i forvejen ligger i sl. Det betyder, at sl bliver længere og længere, jo længere tid opdateringen kører. Er det ikke muligt at bestemme mængden af data, sl må indeholde, således, at hvis man har valgt f.eks. 10 sek. i en editbox, bliver lænden af BottomAxis (på charten) ikke længere end de 10 sek? Dvs., når de 10 sek. er fyldt ud, bliver de nye målinger stadigvæk lagt til sl, mens de ældste målinger i sl "ryger ud".
Håber du gider bruge lidt tid på ovennævnte, da jeg derefter selv kan komme videre!!
Jeg må hellere forhøje til 200 point - er det ikke det, man max må give?
knald en edit på formen og ændre koden på timeren til
procedure TForm1.Timer1Timer(Sender: TObject);
var
i : integer; min,max : real; begin chart1.SeriesList.Series[0].Clear; min := 5000; max := -5000; sl.Add(floattostr(RandExt(71))); if (sl.Count > (strtoint(edit1.Text)*100)) then begin for i := 0 to (sl.Count -(strtoint(edit1.Text)*100)-1) do sl.Delete(i); end;
for i := 0 to sl.Count -1 do begin
if max < strtofloat(sl[i]) then max := strtofloat(sl[i]); if min > strtofloat(sl[i]) then min := strtofloat(sl[i]);
-> Stoney: Det virker jo perfekt, tusind tak for ulejligheden! Jeg læser lige lidt på, hvordan man fordeler point, da Borrisholt også lige får et par stykker for sine forslag. Er 185/15 i orden med dig?
Hva' dælen... Jo længere tid opdateringen kører, desto langsomere kører timeren! Kan det laves om, da opdateringstiden (10mSek) meget gerne skulle være konstant?
Ligeledes XP. CPU belastningen stiger fra 1 til 100 % i løbet af ca. 10 sek., når jeg kører med en opdateringstid på 10 mSek. Sætter jeg opdateringstiden til 100 mSek., er belastningen steget til 40 % efter 500 sek., og den stiger stadigvæk. Men indtil videre er opdateringstiden (100 mSek) stabil.
Nåh, jeg troede du mente grafen hakkede i det. Min bruger også ca 100% CPU. Den thread der er i Timeren er vist ikke helt stueren. Ellers skal du til at kigge på Setpriorityclass
Om du kan "overrule" thread processen i timeren ved jeg ikke, men man kan sætte prioteten på en alm. exe fil om end der ikke er så meget at vælge i mellem.
Opdateringstiden begynder først at blive længere, når CPU belastningen har nået 100 %. Når jeg kører programmet på en anden, og langsomere, PC (med Windows 98), er opdateringstiden fra starten længere (ca. 20 mSek), og bliver så først endnu længere, når CPU belastningen har nået 100 %.
Jeg tror du lader dig snyde af et optisk bedrag. Lad os sige graffen skal plotte 100 målinger. Det gør den på samme areal som ved 2000 målinger. Der for ser det ud som om den arbejder hurtiger i starten. Så når den når max antal målinger skal den "flytte" stregerne et kortere stykke.
Oven over grafen står der, hvor mange målinger, der ligger i sl. De første ca. 10 sek. kan man se, at den rigtig nok tæller 100 målinger pr. sek. Når CPU'en så arbejder 100 %, er det tydeligt at se, at opdateringen bliver langsomere. Er det ikke lidt mærkeligt, at opdateringtiden (10 mSek) ikke overholdes på en langsomere PC, selvom CPU'en ikke arbejder 100 %?
Man kan åbenbart kun give det antal point, som man angivede, da man stillede spørgsmålet. -> Stoney: jeg har oprettet et nyt spørgsmål til dig, så du kan få de sidste 65 point (og jeg kan få et svar...).
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.