Loop i VB6 & andra problem

Elektronik- och mekanikrelaterad mjukvara/litteratur. (T.ex schema-CAD, simulering, böcker, manualer mm. OS-problem hör inte hit!)
Användarvisningsbild
Cenorpa
Inlägg: 737
Blev medlem: 11 juli 2005, 20:58:03
Ort: Stockholm | Borlänge
Kontakt:

Loop i VB6 & andra problem

Inlägg av Cenorpa »

Hej.
Sitter hemma och småpysslar med ett litet program i Visual Basic 6 och har stött på et problem.

Det jag vill göra är att när jag trycker på en knapp så ska en variabel räknas upp var tiondels sekund i en loop tills man trycker på en stoppknapp, hur löser man detta?

Variabeln är döpt enligt följande:

Dim linepos as Integer

Altså den heter linepos och har värdet 0 från början, sen ska den stega upp med ett angivet värde t.ex. +10 var tiondels sekund.
Hur löser jag det och får det hyffsat exakt?
Senast redigerad av Cenorpa 17 februari 2006, 11:24:54, redigerad totalt 3 gånger.
v-g
EF Sponsor
Inlägg: 7875
Blev medlem: 25 november 2005, 23:47:53
Ort: Kramforce

Inlägg av v-g »

Timer
Användarvisningsbild
Cenorpa
Inlägg: 737
Blev medlem: 11 juli 2005, 20:58:03
Ort: Stockholm | Borlänge
Kontakt:

Inlägg av Cenorpa »

Problemet är att jag inte förstår hur man använder en timer så jag tänkte att någon kanske skulle kunna visa ett kodexempel.
Har inte gått nån kurs eller nått i programmering så det är därför jag inte har lärt mig och undrar den här antagligen enkla frågan.
v-g
EF Sponsor
Inlägg: 7875
Blev medlem: 25 november 2005, 23:47:53
Ort: Kramforce

Inlägg av v-g »

Dåså då ska du få det :)

Du skapar en timer (den syns inte i runtime) på panelen.

Dubbelklicka på den så får du "eventet" som händer varje gång den aktiveras.

Sen kodar du som följer där du vill att timern ska starta.

Kod: Markera allt


Dim linepos as Integer 

linepos = 0 ' Startvärde för linepos
Timer1.Interval = 100 ' (ms) Sätter intervallet med vilken timern ska aktiveras.
Timer1.Enabled = True ' Startar timern



Private Sub Timer1_Timer() ' detta event händer nu var 100'e millisekund.
     linepos = linepos + 1 'ökar på variabeln linepos med 1
End Sub
Observera att det övre blocket kanske inte ska stå ihop med det nedre utan kanske i initialize e.dyl där du känner för att ha det.

Lycka till!
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Hur exakt på tiden måste det vara? Alltså vilken precision?

Mvh
speakman
Användarvisningsbild
Cenorpa
Inlägg: 737
Blev medlem: 11 juli 2005, 20:58:03
Ort: Stockholm | Borlänge
Kontakt:

Inlägg av Cenorpa »

Tack V-g!

Nu fungerar det som jag vill, appropå precisionen så ska det inte dra sig mer än 0,5 sekund på 5 minuter men den precisionen man kanske uppnår med timern?
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Nja, det skulle jag inte lita på. :D
Ett betydligt säkrare alternativ är att gör en loop i koden och läsa av Timer-variabeln. "Timer" är en sekundräknare med flyttal och 2 decimaler = 10ms precision.

Kod: Markera allt

Dim quit As Boolean
Dim n As Long
Dim t As Double

quit = False
t = Int(Timer * 10)

Do
   If Int(Timer * 10) <> t Then
      n = n + 1
   End If

   If quit Then Exit Do

   DoEvents
Loop
Exemplet förutsätter att "quit" och "n" är globaler och "quit" sätts till True när Stop-knappen trycks in.
"n" är tiden som räknas upp.

Mvh
speakman
v-g
EF Sponsor
Inlägg: 7875
Blev medlem: 25 november 2005, 23:47:53
Ort: Kramforce

Inlägg av v-g »

Speakman: Helt rätt den stämmer inte 100% över långa tidsperioder men för att få det smidigt får vi kombinera våra exempel.

Hade lite för lite att göra så jag gjorde allt :) Bara att ladda ner HÄR. Antigen ta spara mål som eller öppna direkt.

En "känd" bugg är att om man trycker flera gånger på stoppknappen blir totaltiden "fel" fast egentligen blir den inte det, svårt att förklara :D

Koden är som följer:

Kod: Markera allt

Dim StartTime, TotalTime

' Körs varje gång BTN_Start_Click nedtryckes
Private Sub BTN_Start_Click()
    ' StartTime sätts till timer (för att lagra starttiden)
    StartTime = Timer
    
    ' Startar Timer1
    Timer1.Enabled = True
End Sub

' Körs varje gång BTN_Start_Click nedtryckes
Private Sub BTN_Stop_Click()
    ' Här räknas totaltiden ut (formatnumber formatterar talet så att det ALLTID har två decimaler
    TotalTime = FormatNumber(Round(Timer - StartTime, 2), 2)
    
    ' Stoppar Timer1
    Timer1.Enabled = False
    
     ' Sätter LBL_Time till den uträknade tiden en sista gång
    LBL_Time.Caption = FormatNumber(Round((TotalTime), 1), 1) & " sekunder"
    
    ' Skickar en MsgBox med sluttiden med 2 decimaler.
    MsgBox ("Tiden från start till stopp var " & Chr(13) & TotalTime & " sekunder.")
End Sub

' Körs var 100'e millisekund
Private Sub Timer1_Timer()
    ' Sätter LBL_Time till den uträknade tiden
    LBL_Time.Caption = FormatNumber(Round((Timer - StartTime), 1), 1) & " sekunder"
End Sub

' Körs varje gång programmet startas
Private Sub Form_Load()
    ' Sätter intervallet(ms) med vilken timern ska aktiveras.
    Timer1.Interval = 100
    
    ' Stoppar Timer1
    Timer1.Enabled = False
End Sub
Är det såhär kod ska se ut eller? ;)

Mycket nöje!
Användarvisningsbild
Cenorpa
Inlägg: 737
Blev medlem: 11 juli 2005, 20:58:03
Ort: Stockholm | Borlänge
Kontakt:

Inlägg av Cenorpa »

Ojojoj.. :shock:
Nu blev det lite rörigt, jag tror att timern är tillräckligt pålitlig men jag ska kolla mer på era förslag.
Användarvisningsbild
AndLi
Inlägg: 17168
Blev medlem: 11 februari 2004, 18:17:59
Ort: Knivsta
Kontakt:

Inlägg av AndLi »

Hmm skulle verkligen en VB6 timer dra sig så mycket på 5 minuter?

Jag tycker det låter helt otroligt, nu har jag aldrig mätt på det, men skrivit div servrar med minut och sekundevent. Och dessa har snurrat i bra många fler minuter än 5 (altså borde en halv sekunds dragning i tiden märkas rätt tydligt)

Däremot kan ju eventen komma lite fördröjt om maskinen är hårt belastad.
Men det kommer du aldrig ifrån i ett så högnivå os som windows..
Speakmans do while loop har ju samma problem, säg att "DoEvents" tar en halvsekund... då får du ju inget event "i tid" endå.. (Den loopen ger väll förövrig en 100% cpu belastning hela tiden med, vilket i mina ögon är lite fulkodningvarning på)
v-g
EF Sponsor
Inlägg: 7875
Blev medlem: 25 november 2005, 23:47:53
Ort: Kramforce

Inlägg av v-g »

AndLi: Den är tyvärr inte så exakt antar att det har med prollen att göra också ju mer belastad den är desto längre tar det för koden i timern att exekveras.

Jag testade med en räknare parallelt med den riktiga tiden och den drog sig en del. Men frågan är ju hur EXAKT man måste ha det. Syslar man tex med dragracing är det ju en sak. Springer man runt ett motionsspår en annan.

Cenorpa: Du behöver bara ladda hem den jag gjorde ovan. Som du ser är det kommenterat så att du ska slippa fundera över allt. Kolla igenom och testa.

Funktionen med text beskrivet är detta.
1. Du trycker på start.
2. timern startas och starttiden sparas i en variabel.
3. varje 100 dels sekund uppdateras skärmen så man ser hur lång tid som just nu är gången.
4. Trycker du på stop subtraheras nuvarande tid mot starttid och man får därmed exekveringstiden
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

AndLi: Varför skulle min version fela i tiden? Den går ju på systemklockan, och missar den ett par ms första varvet, så tas det ju igen nästkommande varv. Enda missen som KAN uppstå är om den inte kör loopen på längre än 100ms, men hur stora är oddsen för det? :)
Sedan vad det gäller CPU, så är hela poängen med DoEvents att den INTE ska ta 100% CPU (utan överlåta till andra processer). Det är iaf enda möjligheten i VB.

Mvh
speakman
v-g
EF Sponsor
Inlägg: 7875
Blev medlem: 25 november 2005, 23:47:53
Ort: Kramforce

Inlägg av v-g »

Speakman: Citat: "Det är iaf enda möjligheten i VB." Eller så kör man med timer så som jag så fint skissat upp! :)
Användarvisningsbild
speakman
Inlägg: 4838
Blev medlem: 18 augusti 2004, 23:03:32
Ort: Ånge

Inlägg av speakman »

Jag rättar: Det är enda möjligheten i VB för tidskritiska applikationer.
Fast jag syftade även på att lämna ifrån sig CPU'n, eftersom ingen tidsangiven överlämning finns i VB (som Sleep i C), och ett anrop till Sleep genom Declare Function skapar ännu större belastning (total låsning, 100 %CPU).

Mvh
speakman
Användarvisningsbild
RRacer
Inlägg: 370
Blev medlem: 29 januari 2005, 19:40:17
Ort: Lerum

Re: Loop i VB6

Inlägg av RRacer »

Cenorpa skrev:...Det jag vill göra är att när jag trycker på en knapp så ska en variabel räknas upp var tiondels sekund i en loop tills man trycker på en stoppknapp, hur löser man detta?

Hur löser jag det och får det hyffsat exakt?
Här är ett förslag som blir betydligt mer exakt än med timers.
Det använder en multimediatimer istället.

Bild

Huvuddelen av programmet:

Sub TightLoop()
Randomize
Dim Nu As Long, Nxt As Long
Dim Incr As Long ' Värde att öka räknaren med
Static Value As Long ' Det aktuella värdet

Incr = Val(Me.txtStep.Text) ' Lägg till ev. felhantering...
Nu = GetTickCount()
Nxt = Nu + 100 ' Nästa event om 100 ms

Running = True ' Aktivera loopen

While Running ' Main loop
Nu = GetTickCount()
If Nu >= Nxt Then ' Nu är det dags!
Value = Value + Incr
Me.txtResult.Text = Value
Nxt = Nu + 100
End If
DoEvents
Sleep 50 'ms Förhindrar loopen från att ta all CPU.
Wend
End Sub

Du kan hämta hela programmet här: http://www.meter.se/elektronikforumet/TimerSample.zip

HTH
Skriv svar