Patz Skrevet 13. desember 2005 Del Skrevet 13. desember 2005 (endret) Først av alt, jeg er totalt amatør på dette, begynte såvidt å lese om Delphi i går. Jeg tenkte jeg skulle lage et enkelt program for å styre stepmotorer fra paralellporten, og har til nå fått dette: (bruker inpout32.dll) procedure TForm1.FormCreate(Sender: TObject); label start; begin start: Out32($378,3); Out32($378,5); Out32($378,9); Out32($378,17); GOTO start; end; end. Men jeg trenger en pause på f.eks 7ms mellom hver gang den sender ny verdi til paralellporten: procedure TForm1.FormCreate(Sender: TObject); label start; begin start: Out32($378,3); PAUSE 7ms Out32($378,5); PAUSE 7ms Out32($378,9); PAUSE 7ms Out32($378,17); PAUSE 7ms GOTO start; end; end. Hva er "kommandoen" for dette? Endret 13. desember 2005 av Patz Lenke til kommentar
Patz Skrevet 13. desember 2005 Forfatter Del Skrevet 13. desember 2005 (endret) Takker! EDIT: Post 300 Endret 13. desember 2005 av Patz Lenke til kommentar
Patz Skrevet 17. desember 2005 Forfatter Del Skrevet 17. desember 2005 Ser at hele programmet "låser" seg under sleep, finnes det noe alternativ til dette som gjør at programmet fortsatt svarer? Lenke til kommentar
sinnaelgen Skrevet 17. desember 2005 Del Skrevet 17. desember 2005 (endret) Du kan prøve ut timer componeten. set interval på 7 - så sender den en handling hver 7ende ms. for at den skal virke så må også enabled settes til true hvis det er forskjelige verdier som sendes kan man bruke en variabel som økes med 1 hver gang en verdie er sendt og når man er kommet gjenomm alle så settes variabelen til 1 - og alt begynner på nytt procedure TForm1.Timer1Timer(Sender: TObject); begin inc(teller) if teller > 10 teller =1 case teller of 1:out(verdi1) 2:out(verdi2) 3:out(verdi3) o.s.v. end; end; variabelen teller må defineress i begynelsen av programet ditt var teller:integer; Endret 17. desember 2005 av elg-elg123 Lenke til kommentar
Patz Skrevet 17. desember 2005 Forfatter Del Skrevet 17. desember 2005 Hva gjør jeg om interval skal leses fra en variabel? Lenke til kommentar
NextGenTel-bruker Skrevet 18. desember 2005 Del Skrevet 18. desember 2005 timer1.interval := dinvariabel; hvis dinvariabel er string kan du: timer1.interval := strtoint(dinvariabel); Lenke til kommentar
Patz Skrevet 18. desember 2005 Forfatter Del Skrevet 18. desember 2005 Har prøvd ut denne metoden nå, men det er et problem med den: var teller: integer; variabel: cardinal; function Inp32(wAddr:word):byte; stdcall; external 'inpout32.dll'; function Out32(wAddr:word;bOut:byte):byte; stdcall; external 'inpout32.dll'; procedure TForm1.Timer1Timer(Sender: TObject); begin variabel := 10; Timer1.interval := variabel; if teller = 4 then teller := 1; inc(teller); case teller of 1:out32($378,6); 2:out32($378,3); 3:out32($378,9); 4:out32($378,12); end; end; end. Tror årsaken er denne: Når teller = 1 så klarer ikke programmet å sende out32($378,6) før teller er kommet til 2. Når teller = 0 så blir det en ekstra pause på 1ms mellon out32($378,12) og out32($378,6), noe som får motoren til å ga ujevnt (og saktere) ved høy fart (lite interval) Noen ideèr? Lenke til kommentar
PoseFant Skrevet 19. desember 2005 Del Skrevet 19. desember 2005 Prøv å spille av en AVI film fra samme disk/partisjon som du kjører programmet i og se om du får noen hastighetsvariasjoner på stepmotoren --- /pF Lenke til kommentar
Legion Skrevet 19. desember 2005 Del Skrevet 19. desember 2005 ut ifra caseoperasjonen din så tolker jeg det slik at teller kun skal være fra 1-4? et potensielt problem er dersom teller =< 0 eller teller >=5, i det første tilfellet så vil caseoperasjonen bomme på x antall kjøringer, i det siste så vil den aldri(?) kjøre flere ganger. en bedre kontroll må til initialiserer du teller før denne kodesnutten? du inkremeterer den før case, hadde vært penere å initialisere først, så inkremetere teller etter case. en annen ting er at både teller og variabel (finn på et bedre navn?) er globale variabler, spørs om det hadde vært bedre med lokale variabler for prosedyren, evt. som argument for prosedyren dersom de blir brukt utenfor også. Lenke til kommentar
PoseFant Skrevet 19. desember 2005 Del Skrevet 19. desember 2005 Heisann. Føler at jeg må komme med noen tips her. TTimer er uaktuell å bruke for applikasjoner som krever den nøyaktigheten du henviser til. Generelt sett vil dette knapt fungere i Windows på en Intel prosessor, nettop fordi prosessoren ikke er i stand til å utføre det du vil og at Windows ikke er et ekte MutliTaskin system. Men som for alle regler finnes det unntak. Vi har spill som har høye krav og disse har spesielle timere i programkoden som tilfredstiller de høye kravene. Måten å få til dette på er å lage en egen komponent derivert av TThread og bruke Sleep(1). Du kan bruke GetTickCount() for å se hvor mange CPU cycles det går mellom hver operasjon. Hvis du googler litt vil du også finne endel eksempler på ThreadSafe timere som er adskillig bedre enn TTimer. --- /pF Lenke til kommentar
tasle Skrevet 30. desember 2005 Del Skrevet 30. desember 2005 Ser at hele programmet "låser" seg under sleep, finnes det noe alternativ til dette som gjør at programmet fortsatt svarer? 5305162[/snapback] Det låser seg fordi du har en uheldig og evigvarende løkk der. Bruk heller noe sånt som Repeat Out32($378,3); Sleep (7); Out32($378,5); Sleep (7); Out32($378,9); Sleep (7); Out32($378,17); Sleep (7); [B]Application.ProcessMessages;[/B] Until Ferdig; Ferdig kan (må) være en global variabel, eller tilhøre objektet. Ferdig er i utgangspunktet satt til False, men endres f.eks. av å klikke på en knapp der du setter den til True. Avhengig av hvor kjapp motoren er til å reagere, må du i verste fall bruke Application.ProcessMessages; for hver Out32. Application.ProcessMessages gjør at programmet fanger opp et klikk på en stopp-knapp. Med bare en Application.ProcessMessages kan det hende at du må vente i noen sekunder før programmet reagerer. Jeg regner med at stepmotoren ikke er så veldig tidskritisk heller, at du trenger spesialtimere til dette. Det er vel neppe et F-16 jagerfly som skal kontrolleres.. Lenke til kommentar
Patz Skrevet 30. desember 2005 Forfatter Del Skrevet 30. desember 2005 (endret) Har funnet en annen komponent som heter Sleeper, den fungerer mye bedre. Legger ved hele programmet slik det er til dags dato. unit Step; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ComCtrls, ExtCtrls, Sleeper; type TForm1 = class(TForm) EditInput: TEdit; EditPause: TEdit; ProgressBar1: TProgressBar; Headline: TLabel; UpDown1: TUpDown; ButtonClock: TButton; LabelM: TLabel; Sleeper: TSleeper; ButtonAntiClock: TButton; LabelFinished: TLabel; ButtonEmergency: TButton; procedure ButtonAntiClockClick(Sender: TObject); procedure ButtonClockClick(Sender: TObject); procedure ButtonEmergencyClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} // LABELDEKLARASJONER //procedure TForm1.FormCreate(Sender: TObject); //begin //end; function Inp32(wAddr:word):byte; stdcall; external 'inpout32.dll'; function Out32(wAddr:word;bOut:byte):byte; stdcall; external 'inpout32.dll'; //BEGYNNELSE: ROTER MED KLOKKE procedure TForm1.ButtonClockClick(Sender: TObject); var i, r, f, s: integer; //I=input r=repeats f=FOR variabel s=sleep m: extended; //m=millimeter s=sleep (ms) begin i := StrToInt(EditInput.Text); m := i * 1.5; //1,5mm pr. runde på fres r := i * 50; // 200 (1 rotasjon) / 4 (4 step) = 50 s := StrToInt(EditPause.Text); begin for f := r downto 1 do //Gjennomfør variabel r begin ProgressBar1.Position := (f); ProgressBar1.Position := f; //Progressbar følger FOR loop ProgressBar1.Max := r; //F er på starten = R ProgressBar1.Min := 1; //F teller ned til 1 LabelFinished.Caption := 'AKTIV'; Sleeper.SleepFor(s); //Sleep (s); Out32($378,12); //Singlestep: 1 Sleeper.SleepFor(s); //Sleep (s); Out32($378,9); //Singlestep: 2 Sleeper.SleepFor(s); //Sleep (s); Out32($378,3); //Singlestep: 4 Sleeper.SleepFor(s); //Sleep (s); Out32($378,6); //Singlestep 8 end; LabelFinished.Caption := 'VENT'; Sleeper.SleepFor(800); Out32($378,0); LabelFinished.Caption := 'PROSEDYRE GJENNOMFØRT, KLAR FOR NYE PULSER'; end; end; //BEGYNNELSE: ROTER MOT KLOKKE procedure TForm1.ButtonAntiClockClick(Sender: TObject); var i, r, f, s: integer; //I=input r=repeats f=FOR variabel s=sleep m: extended; //m=millimeter s=sleep (ms) begin i := StrToInt(EditInput.Text); m := i * 1.5; //1,5mm pr. runde på fres r := i * 50; // 200 (1 rotasjon) / 4 (4 step) = 50 s := StrToInt(EditPause.Text); // LabelM.Caption := m; begin for f := r downto 1 do //Gjennomfør variabel r begin ProgressBar1.Position := (f); ProgressBar1.Position := f; //Progressbar følger FOR loop ProgressBar1.Max := r; //F er på starten = R ProgressBar1.Min := 1; //F teller ned til 1 LabelFinished.Caption := 'AKTIV'; Sleeper.SleepFor(s); //Sleep (s) Out32($378,6); //Singlestep: 1 Sleeper.SleepFor(s); //Sleep (s) Out32($378,3); //Singlestep: 2 Sleeper.SleepFor(s); //Sleep (s) Out32($378,9); //Singlestep: 4 Sleeper.SleepFor(s); //Sleep (s) Out32($378,12); //Singlestep 8 end; LabelFinished.Caption := 'VENT'; Sleeper.SleepFor(800); Out32($378,0); LabelFinished.Caption := 'PROSEDYRE GJENNOMFØRT, KLAR FOR NYE PULSER'; end; end; //Written by Pat, http://pat.selfip.com procedure TForm1.ButtonEmergencyClick(Sender: TObject); begin Out32($378,0); Halt; end; end. Det er da litt kritisk at motoren faktisk gjennomfører alle step den blir bedt om, da det er en metall-fres som skal kontrolleres. Application.ProcessMessages brukes altså dersom jeg skal stoppe programmet? (trøtt nå, skal se videre på det i morgen.) EDIT: Leif Endret 30. desember 2005 av Patz Lenke til kommentar
tasle Skrevet 30. desember 2005 Del Skrevet 30. desember 2005 Application.ProsessMessages brukes ikke i og for seg til å avbrryte programmet, det må du gjøre med andre midler, f.eks. ved å klikke på en avslutningsknapp eller en tast på tastaturet. Men opprinnelig hadde du motorkontrollen i en evigvarende løkke som det ikke var nubbtjangs å bryte inn i. Når du legger til Application.ProsessMessages så skjer dette: Windows får tid til å behandle andre hendelser (messages) i ditt program, hvis du museklikker på en knapp i ditt program, vil Windows klare å fange opp museklikket uten å være 100 % opptatt med løkka di. En Application.ProsessMessages gjør at Windows stopper opp et lite millisekund og spør seg selv "har det skjedd noe rundt omkring, enten i dette programmet eller i andre programmer, som jeg må være oppmerksom på?" Hvis ingenting har skjedd, så fortsetter løkka di en runde til, hvis det er kommet en message fra en knapp eller noe annet, vil windows behandle den, f.eks. sette en variabel til true, slik som i eksemplet mitt. Jeg skjønner at det er litt kritisk hva stepmotoren driver med, så dette må du prøve ut i praksis for å se effekten av nøyaktigheten. Hvor langt "avbruddet" med en Application.ProsessMessages egentlig blir i praksis vil avhenge fra PC til PC, hvor kjappe de er. Lenke til kommentar
PoseFant Skrevet 4. januar 2006 Del Skrevet 4. januar 2006 Application.ProcessMessages() er enda mer intensiv og ødeleggende for en applikasjon enn Sleep(). En morsom illustrasjon: ... procedure WndProc(Msg: TMessage); override; ... TForm1.WndProc(Msg: TMessage); begin inherited; Application.ProcessMessages; end; ... Lenke til kommentar
Anbefalte innlegg
Opprett en konto eller logg inn for å kommentere
Du må være et medlem for å kunne skrive en kommentar
Opprett konto
Det er enkelt å melde seg inn for å starte en ny konto!
Start en kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå