Ich weiß nicht ob mir jemand hier helfen kann aber ich versuchs einfach
mal.
Ich möchte mit dem Parallelport eine Messung machen. Ich habe mir eine
Platiene zurecht gelötet, wo ich schon mal LED´s An und aus schalten
kann.
Nun mein Problem: Ich bekomme keine Daten IN den PC.
Ich habe als Betriebssystem Win XP.
In Borland c++ 6.0 habe ich mit eine Oberflache zum Ansteuern meiner
Platiene Programmiert. Damit ich den Parallelport ansprechen kann,
benutze ich die inpout32.dll.
Leider kann ich nur Leienhaft mit der C++ Sprache umgehen und noch mit
keiner andren.
Wie sage ich in C++ das er an Port 0x378 den Pin 2 ( Data0) Einlesen
soll?
Das Ganze ist für eine Facharbeit und deswegen were ich über hilfe sehr
dankbar.
Gruss Testfahrer
Hi,
du musst auf dem Port 0x378+2 32 ausgeben, dann kannst du 0x378 als
Eingang verwenden.
Sei aber vorsichtig, bau lieber noch Angstwiderstände ein ;)
HTH
@juppi:
Ist doch peinlich, wenn man nicht mal den Jargon des Hobbys in seiner
Landessprache beherrscht...
@testfahrer:
Mal an eine serielle Verbindung zum PC gedacht? Lässt sich wesentlich
leichter handhaben. Außerdem gibt es eine Menge fertiger Software, z.B.
zum Datenloggen - HTerm wäre hier mein Favorit.
Testfahrer wrote:
> Ich weiß nicht ob mir jemand hier helfen kann aber ich versuchs einfach> mal.>> Ich möchte mit dem Parallelport eine Messung machen. Ich habe mir eine> Platiene zurecht gelötet, wo ich schon mal LED´s An und aus schalten> kann.acharbeit und deswegen were ich über hilfe sehr> dankbar.
Aber pass auf, dass Du Vorsicht walten laesst. Wenn Du den Port lieferst
ist meistens das ganze Mainboard geschrottet, da dann noch andere
Peripherieeinheten daran glauben muessen.
@Juppi
Nachdem dein erster Satz eine Frage darstellt, würde ich dahinter auch
das korrekte Satzzeichen setzen ("?").
Nun zur Antwort: nein, bin ich nicht. Bin nur Inschinör. Aber einer, der
seine erste Fremdsprache in Wort und Schrift einigermaßen beherrscht;
die Muttersprache allerdings in Wort besser als in Schrift, weil sich
Dialekt besser sprechen als schreiben lässt.
Und wenn dann Worte wie "Platiene" oder "Wiederstand" auftauchen,
kräuseln sich meine Fußnägel doch recht schmerzhaft.
Zurück zum Thema:
@Testfahrer:
Schau mal im BIOS nach, wie der Parallel-Port konfiguriert ist.
Hintergrund :
Ursprünglich war diese Schnittstelle nur für die Datenausgabe (Drucken)
gedacht. Später wurde sie als Dateneingang erweitert.
Den Modus kann man im BIOS einstellen.
Bei Normal/Standard/SPP ist nur eine Datenausgabe (unidirektional)
möglich.
Wenn auch eine Dateneingabe (bidirektional) möglich sein soll, muß
Extended/EPP eingestellt sein.
Es gibt auch noch den ECP-Modus, dieser benötig jedoch zusätzlich noch
einen DMA-Kanal.
Danke für die Antworten bzw. Hilfen.
ICh bin ein wenig weiter gekommen, ich kann nun die Basis Adresse des
Parallelportes Auslesen. Diese liegt bei den meisten Rechenern auf Adr.
0x378 = #888.
Ich benutzte eine DLL zum Ansprechen des Controllers, somit muss ich im
BIOS nix einstellen. Nun hab ich aber noch immer das Problem, wenn ich
die Data Register einlese kommt immer 0 Raus. Lese ich das Status
Register, bekomme ich 126 und Lese ich das Control Register bekomme ich
immer 204 heraus.
Was sind das für Werte?
Und meine Nächste Frage, wie Filter ich aus dem Data Register an welchem
Data Pin des Sub 25 Steckers das Eingehende Signal Liegt?
Pin 2 = Data0
Pin 3 = Data1
Pin 4 = Data2
Pin 5 = Data3
Pin 6 = Data4
Pin 7 = Data5
Pin 8 = Data6
Pin 9 = Data7
@GeraldB
> Hintergrund :> Ursprünglich war diese Schnittstelle nur für die Datenausgabe (Drucken)> gedacht. Später wurde sie als Dateneingang erweitert
Das stimmt so nicht ganz, es kommt darauf an wie man die Daten an der
Schnittstelle einlesen will. Es gab schon immer das Signal für
OutOfPaper oder Online - diese lassen sich Wunderbar als eingang nutzen,
da sollte sogar die einstellung im Bios egal sein.
Frage an Testfahrer:
Kannst du ein paar Details zum anschluss sagen, an welchen Pins willst
du als eingang Nutzen, wie viele eingänge brauchst du überhaupt?
Ich brauche nur 1 Pin ist sogar egal welcher. Es wird warscheinlich
einer der Data Reihe werden.
Was ich mir noch so überlegt habe, wie sieht es aus, MUSS im Controll
Register nicht irgend ein Bit auf 1 sein, damit die Data Register als
Eingang und nicht all Ausgang Gesetzt sind? WIe macht man denn so was?
So ich habe es nun hinbekommen eine Messaufnahme mit dem Parallelport zu
machen.
Leider ist das ergebniss nicht so wie ich es mir vorgestellt habe.
Es heißt ja, das der Parallelport einen zeitliche Abgriff von 1 µs
erlaubt.
Das mag wohl sein, leider schafft mein schnellster PC, 2,1GHz CPU mit
400MHz Speichertakt, maximal 1,25 ms Pro Sample einer Messreihe.
Das Signal welches ich aber messen möchte, liegt zwischen 10-12 µs.
Nun such ich eine alternative diese Messung durchzuführen, und auch
einen Messprotkoll zu haben. Das ganze natürlich ohne RISEN Kosten.
Da musst du halt eine externe Hardware benutzen. Ein Microcontroller mit
meinetwegen serieller Schnittstelle. Der liest die Daten mit 1MHz in
seinen Speicher und wenn der voll ist, schickt er sie zum PC. Kostet 5
Euro und bissl Programmieren.
> Es heißt ja, das der Parallelport einen zeitliche Abgriff von 1 µs> erlaubt.
Ohne Betriebssystem oder auf Devicetreiberebene ist das locker möglich,
auch sehr viel langsameren Rechnern. Sobald aber ein Betriebssystem wie
Windows oder Linux dazukommt, wars das auch schon. Mit Hacks wie
"giveio.sys" lässt sich zwar auch hier die Geschwindigkeit erhöhen, aber
deterministisch oder zuverlässig ist das nicht.
Die Druckerschnittstelle ist für Deine Aufgabe schlichtweg vollkommen
ungeeignet.
Nimm Dir den Rat von Christian zu Herzen, mit einem geeigneten µC kannst
Du mit ziemlich wenig Aufwand auch mit höherer Genauigkeit Pulsdauern
etc. messen.
Ersmal Dank für die Antworten.
An supachris:
Dann werd ich das wohl mit einem µIC machen müssen.
Was brauch ich denn alles, damit ich mit dem Messen loslegen kann.
Für deteijierte Infos wer ich sehr dankbar.
MFG
Testfahrer
testfahrer wrote:
> Ersmal Dank für die Antworten.>> An supachris:>> Dann werd ich das wohl mit einem µIC machen müssen.> Was brauch ich denn alles, damit ich mit dem Messen loslegen kann.>> Für deteijierte Infos wer ich sehr dankbar.
Nö, Denken musst du schon alleine. Das geht mit nahezu jedem µC. Aber
ich wette, du hast noch nie was damit gemacht. Dann wirds schwierig...
Hm Mein Programm ist um einiges zu gross fürs forum. Ist mit c++ Borland
geschriegen.
Und ja ich hab noch nie was mit µC´s gemacht. Ich komm aber bestimmt gut
rein in die Theorie so als R u. F Techniker.
testfahrer (Gast)
muss ja nicht das ganze Programm sein, es reicht ja die stelle die für
das auslesen da ist, und warum sollt das Programm zu gross sein, ich
glaube kaum das es ein paar MB quelltext sind - auch nicht mit borland.
Also mein QuellStext hat schon 1,3 MB. ;-)
Hm Die reine einlese Schleife sieht so aus:
do
{
x = x +1;
mess = StrToInt(messintervall->Caption);
erg = (inp32)(address);
erg = erg -grd;
Sleep (1);
}
while (x <1500);
inp32 ist von meiner DLL zum Wert einlesen.
address ist bei mir h379.
Sleep muss ich haben, damit der Rechner nicht festhängt.
@testfahrer
da kann man doch schon noch etwas machen
do
{
x = x +1;
mess = StrToInt(messintervall->Caption); # Viel zu langsam in der
schleife
# warum muss das hier sein?
# für was ist mess überhaupt
da?
erg = (inp32)(address);
erg = erg -grd;
Sleep (1); #der Aufruf von Sleep mit 1(ms?)
#wie willst du denn auf µs kommen wenn du schon 1ms wartest?
}
while (x <1500);
also erstmal das StrToInt und messintervall->Caption weglassen und dann
mal testen.
Dann das Sleep(1) mal durch eine kleine schleife ersetzen.
(mal ein wenig testet damit der optimierer es nicht wegschmeist)
Ist zwar zum schluss reine Resourcenverschwendung aber für diese Problem
fällt mir spontan nicht weiters ein.
jetzt kann noch passiere das das Betriebsystem dir immer mal Zeit
wegnimmt, das kann man noch ein wenig verbessern in dem man für diese
Zeit den Thread als TimeCritial ausführt.
float nix;
for( x = 0; x < 10; ++x ) { nix = sqrt(x); };
Ich muss was verbessern.
Ich habe den Sleep(1) Raus genommen. Der hat die Zeit auf 1m Sekunde
begrenzt. Nun komm ich deutlich weiter runter. Aber noch nicht genug.
Ich liege nun bei 250µs. Wie gesagt, ich brauch aber so ca. 10µs
aufnahme möglichkeit.
Den Treiber oder Dll welche ich benutze heißt INPOUT32.DLL.
Mit giveio.sys ging die Messung nicht, den dafür ist das Signal irgenwie
zu schwach.
@testfahrer
hast du auch das StrToInt(messintervall->Caption) entfernt?
> Den Treiber oder Dll welche ich benutze heißt INPOUT32.DLL.> Mit giveio.sys ging die Messung nicht, den dafür ist das Signal irgenwie> zu schwach.
eine dll kann wohl kaum entschieden ob ein Bit schwach oder stark ist!
Kann du bei dir Assembler einbauen in den Code? Wenn ja kann man damit
den Overhead durch den dll aufruf einsparen.
Also ich hab ersmal
StrToInt(messintervall->Caption)
rausgemacht.
Wie kann ich mir nun genau anzeigenlassen, wieviel zeit er für die
messung braucht, ich hab immer sekunden gezählt, wieviel er für 2000
Messproben in der sec braucht. Ich kahm auf 5500 für 2s.
Hier das komplette Prog:
************************************************************************
mmess->Clear();
mmess->Lines->Add ("Dies ist eine 10 Sekunden Aufnahme mit 5500
Werten");
address = StrToInt (Edit1->Text);
address = address +1;
AnsiString zeit, tag, pin;
byte erg;
int x =0, grd;
zeit = Time();
tag = Date();
mmess->Lines->Add ("Die Messung erfolgte am "+tag +" Um "+zeit);
grd = (inp32)(address);
do
{
x = x +1;
erg = (inp32)(address);
erg = erg -grd;
if ( erg != 0)
{
mmess->Lines->Add ("1");
}
else
{
mmess->Lines->Add ("0");
Neingp2->Checked=0;
Neingp3->Checked=0;
Neingp4->Checked=0;
Neingp5->Checked=0;
Neingp6->Checked=0;
}
if ( erg == 248)
{
pin = 15;
Neingp2->Checked=0;
Neingp3->Checked=0;
Neingp4->Checked=0;
Neingp5->Checked=0;
Neingp6->Checked=1;
}
if ( erg == 240)
{
pin = 13;
Neingp2->Checked=0;
Neingp3->Checked=0;
Neingp4->Checked=0;
Neingp5->Checked=1;
Neingp6->Checked=0;
}
if ( erg == 224)
{
pin = 12;
Neingp2->Checked=0;
Neingp3->Checked=0;
Neingp4->Checked=1;
Neingp5->Checked=0;
Neingp6->Checked=0;
}
if ( erg == 128)
{
pin = 11;
Neingp2->Checked=0;
Neingp3->Checked=1;
Neingp4->Checked=0;
Neingp5->Checked=0;
Neingp6->Checked=0;
}
if ( erg == 192)
{
pin = 10;
Neingp2->Checked=1;
Neingp3->Checked=0;
Neingp4->Checked=0;
Neingp5->Checked=0;
Neingp6->Checked=0;
}
//Sleep (1);
}
while (x <5500);
mmess->Lines->Add ("Die Messung erfolgte an Pin " +pin);
Neingp2->Checked=0;
Neingp3->Checked=0;
Neingp4->Checked=0;
Neingp5->Checked=0;
Neingp6->Checked=0;
*****************************************************************
Wieso machst du denn die gesamte Auswertung immer noch während der
Messung? Mach doch mal 2 Schleifen. Die erste misst nur, schreibt alle
Werte in einen Speicher, und die zweite macht die Auswertung der
Ergebisse aus dem Speicher.
@Testfahrer
ich muss mich Christian anschliesen, wenn man etwas Zeitkritischen
macht, dann sollte man auch nur das nötigste machen.
Mach der eine grosses Array und liese den Port in das array ein - mehr
nicht. In einer 2.Schleife wertest du dann das Array aus.
Hast du mal versucht nachzuvollziehen, was dein Rechner alles macht wenn
du etwas mit mmess arbeitest - das ist doch bestimme eine MessageBox.
Dabei werden haufenweise Nachrichten zwischen Windows und deinen
Programm ausgetauscht, man sollte NIE ein ein solchen schleife die GUI
ansprechen. Da waren ja meine messungen auf einen 286er schneller.
unsigned char buffer[10*1024]=0;
for( int i = 0; i < sizeof( buffer ); ++i ) {
buffer[i] = (inp32)(address);
}
dann wirst du vermutlich das Problem haben, das es viel zu schnell ist,
dann kannst du versuchen mit dummy schleifen die ganze sache zu
verlangsamen oder ein größers Array zu nehmen, aber zu langsam dürfte
das dann nicht mehr sein.
Nachtrag:
um in etwas abschätzen zu können wie lange die Messung gedauert hat
würde vor und hinter der Messschleife die Zeit ermitteln, aber die
normalen Zeitfunktionen sind dafür bstimmt zu ungenau dafür gibt es
QueryPerformanceCounter, dann kann man nur noch davon ausgehen das die
Messerergebnisse gleichmäßig verteilt sind (was aber durch windows nicht
ganz so sein wird).
Wenn die kleine Scheife schnell genug ist könnte man auch versuche den
wert von QueryPerformanceCounter für jeden Messwert zu speichern, müsste
man mal testen ich kenn die overhead von QueryPerformanceCounter nicht.
> aber die normalen Zeitfunktionen sind dafür bstimmt zu ungenau
GetSystemTime/GetLocalTime liefert die Systemzeit auf 100 nsec genau.
Allerdings wird man die Schedulergranularität erkennen, die, wenn man
keine Gegenmaßnahmen ergreift, bei 10 msec liegt. Mit timeBeginPeriod
(einer Funktion aus der Multimedia-Unterstützung) kann die
Schedulergranularität auf 1 msec reduziert werden.
Also mess ist ein Memo Feld. Ich habe auch schon überlegt, erstmal ins
Memo Speichern, und dann die Messwerte auswerten.
Nur hab ich das Problem;
Wie greife ich auf eine Bestimmte Zeile eines Memo zu?
z.B. Ich möchte den Wert aus Line1 Auslesen durch Schleife jagen um 1
oder NULL aus dem Messergebnis zu machen, dann in ein 2tes Memofeld
hinzufügen. Nun soll Line1 Gelöschtwerden, und die Restlichen Lines
aufrücken.
Mit
Lines->Add();
wird eine Zeile hinzugefügt.
Wie Lösche ich eine?
Wie Lese ich eine Bestimmte aus?
Hallo,
>Also mess ist ein Memo Feld. Ich habe auch schon überlegt, erstmal ins>Memo Speichern, und dann die Messwerte auswerten.
Das ist der der völlig falsche weg, das memo feld gehört zu der GUI von
Windows ist ist LANGSAM, mach es doch wie ich oben in dem Beispiel
geschrieben habe in ein array und dann kannst du die werte bequem
auslesen.
@Rufus t. Firefly
Also meine msdn sagt mir bei GetSystemTime, das dieStruktur nur ms
enthalten kann, damit ist kann sie als min 1ms darstellen, mit
QueryPerformanceCounter bekommt man es genauer hin. Das der Scheduler
dazwischenfunkt ist klar, aber wenn innherhalb von 2 messungen kein
Taskwechsel auftritt, dann kan man die Zeiten noch unterscheiden was bei
GetSystemTime nicht mehr geht.
So ich hab es mit einem Array versucht. Das scheint echt schnell zu
sein. Nun kommt aber ein NEUES Problem bei diesem Array.
Und zwar ich bekomme IMMER nur den ersten wert in jede Zeile des
Array´s.
Hier mein Programm:
int array[10000];
int i,j, grd;
grd = (inp32)(address);
for(i=0; i<10000; i++)
{
array[i] = (inp32)(address);
}
for(j=0; j<10000; j++)
{
i=0; i++;
mmess->Lines->Add(array[i]);
}
Ich hab das mal mit
"array[i] = random(50);"
statt
"array[i] = (inp32)(address)"
da bekomm ich wirklich nur 10000 mal die 4 oder so. Woran kann das
liegen?
i=0; i++;
was erwartest du auch wenn du i auf 0 machst und danach +1 rechnest?
eventuell mal mit
for(j=0; j<10000; j++)
{
mmess->Lines->Add(array[j]);
}
testen
und warum hast das array auf int gemacht? ich hatte nicht ohne grund
unsigned char geschrieben, ein port hat nur 1Byte warum sollte man dann
3Byte verschenken? immerhin sind das bei deiner größe schon 3kb zu viel.
Ist zwar noch nicht der Tragisch, aber muss so eine Verschwendung denn
sein?
Jo das lag an dem J hab das echt verpeilt. ;-)
Ok hab auch das int ersetzt.
nun weiß ich immer noch nicht wie lang ich wirklich brauch für eine
Messung.
Ich mach nun 100.000 Messungen und bekomme nur 2 recht kurze Ausschläge.
ICh glaube es ist noch immer zu langsam.
http://img3.imagebanana.com/img/imynvmwz/messtest.JPG
Hat alles geklappt. Nun das Letzte was noch ist, ist die Sache mit der
Zeit.
Wie erfasse ich diese so genau wie möglich?
mit
Time();
bekommt man ja minimal nur die Sekunden.
@testfahrer
Lies doch mal bitte die Kommentare genau durch, ich hatte doch oben
extra noch geschrieben welche methoden es zur Zeitmessung gibt
1. du machst vor der Schleife die Abfrage der Zeit und nach der Schleife
dann weisst du das die ergebnisse dezwischen liegen müssen und
kannst sie gleic
@testfahrer
Lies doch mal bitte die Kommentare genau durch, ich hatte doch oben
extra noch geschrieben welche methoden es zur Zeitmessung gibt
1. du machst vor der Schleife die Abfrage der Zeit und nach der Schleife
dann weisst du das die ergebnisse dezwischen liegen müssen und
kannst sie gleichmässig verteilen.
2. du machst ein 2. Array wo du zu jeden messergebniss die Zeit
speicherst
das ist dann zwar etwas langsamer (sollte aber für deine zwecke noch
schnell genug sein) kannst dafür aber genau sagen wenn welcher
zustand
war.
Für die Zeitmessung stehen dir die GetSystemTime funktion aus der
windows api zur verfügung die aber nur ms liefert, wenn es etwas genauer
sein soll dann sollte man QueryPerformanceCounter verwenden, sie liefert
mindestens ms kann aber abhängig vom prozessor auch genauer sein (kann
aber auch probleme bei einen fehler im Bios und einen Dualcore system
erzeugen)
vorschlag für die Lösung 1
ZeitStart = GetSystemTime
for ( ... ) {
array[x] = messert
}
ZeitStop = GetSystemTime
Dann weiss du wie welche zeit zwischen den messergebnissen vergangen
ist.
die Etwas schönere/langsamere lösung bei der du weiss wann welches
ergebniss ermittelt wurden ist.
unsigned char array1[10000] = {0};
LARGE_INTEGER array2[10000] = {0};
for( int x = 0; x < 10000; ++x ) {
array1[x] = port;
QueryPerformanceCounter( array2[x] );
}
Damit hat du 2. Arrays, eines mit den messwerten und eines mit den
zeiten dazu. QueryPerformanceCounter liefert keine wirkliche Zeit es
liefert einfach eine Zahl die hochzählt, wie viel sei pro sec hochzählt
bekommt man mit QueryPerformanceFrequency raus. Man kann sie auch nich
in eine Zeit umrechnen aber man kann sagen der vom start der messung bis
x sind so und so viele µs vergangen.
Die Doku für die Funktionen findet man bei Microsoft in der MSDN.
>Ich mach nun 100.000 Messungen und bekomme nur 2 recht kurze Ausschläge.>ICh glaube es ist noch immer zu langsam.
Ich würde sagen ist es viel zu schnell, du unterschätzt die heutigen
Computer. Für ihn ist eine ms eine Ewigkeit wenn man es richtig
anstellt.
Ich hatte da ganze schon zu Zeiten vom 286er mit 12Mhz gemacht und das
war schon schnell genug.
@Profieprogrammierer
normalerweisse würde ich denn messwert und die Zeit in eine
Stuktur/Klasse packen, 2Arrays geht für den zweck auch.