Brauche Echtzeit für RS232-Interface

Message
Author
pcAlko

Brauche Echtzeit für RS232-Interface

#1 Post by pcAlko »

An alle C-Programmer!

Ich programmiere ja eigentlich schon etwas länger,
zur Zeit aber nicht mehr viel in C
und auf Linux erst seit kurzem.

Habe folgende zwei Probleme:
Ich möchte einen Thermometer an meinem COM-Port realisieren.
die Pin's ansteueren und abfragen funktioniert ja schon
aber um den Wiederstand zu messen brauche ich Echtzeitprioritaeten!

zur zeit frage ich innerhalb einer while Schleife ob das Signal angekommen ist
das schaut in etwa so aus:

while( (!(inb(0x3F8+6) & 0x020) && usleepTime < 1500000)
{
usleep(1);
++usleepTime;
}

damit komme ich auf so ca. 74 - 83 millisecunden.
wenn ich den Process mit nice -n -20 starte
auf 81 - 83 millisekunden

keine Ahnung ob diese Werte stimmen, (obwohl mir diese Werte etwas nieder vorkommen)
jedoch möchte ich den Process nicht fortwährend in einer Echtzeitschleife laufen lassen
sondern eben nur diese eine Schleife
dann warte ich vielleicht wieder eine sekunde
und messe dann wieder.
In einem Thread hat Janka geschrieben
dass das mit sched_setscheduler geht
hab aber keine Ahnung wie ich die man-Pages für diesen Befehl aufrufe
vermute mal ich brauche dafür ein extra Paket.

Nun zu meiner zweiten Frage:
Ich hab da von der Firma Conrad das Buch "Elektronik am PC"
Da wird in Visual Basic programmiert über eine port.dll
mich interresiert weniger die Elektronik als das Programmieren
(die Elektronik macht dann mein Bruder)

Aus diesem Buch habe ich die folgende Formel
wie ich von den millesecunden,
wenn ich einen NTC-Wiederstand dazwischen hänge,
auf die Temperatur komme.

T= <millisekunden>
T= T * 1.0000000001;
R= 2200 + 7800 * (T - 76300) / (294600 - 76300);
R= (int)R
Temp= 1 / (log(R / 10000) / 4300 + 1 / 298) -273
Temp= (int)(Temp * 10) / 10

mein Problem liegt beim Befehl log()
das ist der natürliche Logarithmus.
ich habe danach gegoogelt und herausgefunden
dass ich die Bibliothek math.h dafür includieren muss.
leider erkennt der gcc compiler diesen Befehl trotzdem nicht.

Ich hoffe ich war mit meiner Erklärung Verständlich
und irgendjemand kann mir weiterhelfen.

8) pcAlko

pcAlko
Posts: 70
Joined: 14. May 2007 19:27

#2 Post by pcAlko »

Ich war noch nicht registriert!!!
dafür dass ich auch eine E-Mail für eine Antwort bekomme
habe ich jetzt noch diesen Beitrag als registrierter Benutzer nachgepostet.


8) pcAlko

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

Re: Brauche Echtzeit für RS232-Interface

#3 Post by Janka »

pcAlko wrote: die Pin's ansteueren und abfragen funktioniert ja schon
aber um den Wiederstand zu messen brauche ich Echtzeitprioritaeten!
Die gibt es als *root* (oder SUID-root), wenn man mittels sched_setscheduler den SCHED_FIFO auswählt. Aber Achtung! Nicht mit X rumprobieren, sondern nur mit einer ebenfalls auf SCHED_FIFO gesetzten Shell, denn man klemmt sich bei falscher Programmierung (Busy-Loops) schnell den Draht zum Rechner ab und muss sonst den Stecker ziehen.

$ man sched_setscheduler
In einem Thread hat Janka geschrieben
dass das mit sched_setscheduler geht
hab aber keine Ahnung wie ich die man-Pages für diesen Befehl aufrufe
vermute mal ich brauche dafür ein extra Paket.
Das Eintippen des Befehls oben in einer Konsole reicht. Manchmal gibt es ein extra (Pseudo-)Paket "allman", dass *alle* Manpages installiert. Welche Distribution benutzt du?



mein Problem liegt beim Befehl log()
das ist der natürliche Logarithmus.
ich habe danach gegoogelt und herausgefunden
dass ich die Bibliothek math.h dafür includieren muss.
leider erkennt der gcc compiler diesen Befehl trotzdem nicht.
Man muss außerdem noch die libm.so hinzulinken. Also im Linkerschritt gcc -o myprog -lm main.o serial.o temp.o oder ähnlich.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#4 Post by Janka »

Mal ganz unabhängig davon rate ich dir eher zu diesen Chips:http://www.maxim-ic.com/pl_list.cfm/filter/21/ln/en

DS2480 als RS232-Interface, und DS1820 als Thermometer. Die sind laserabgeglichen, da braucht man nicht selbst Einmesskurven zu fahren. Außerdem kann man beliebig viele je DS2480/RS232-Port anschließen. Maxim rückt auch kostenlose Samples raus, wenn man es geschickt anstellt. Einen Treiber gibt es ebenfalls: http://www.owfs.org.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

pcAlko
Posts: 70
Joined: 14. May 2007 19:27

#5 Post by pcAlko »

Hi Janka!
Janka wrote:Das Eintippen des Befehls oben in einer Konsole reicht. Manchmal gibt es ein extra (Pseudo-)Paket "allman", dass *alle* Manpages installiert. Welche Distribution benutzt du?
Ich benutze kubuntu
und habe das Paket manpages-dev schon gefunden danke!
Janka wrote:Man muss außerdem noch die libm.so hinzulinken. Also im Linkerschritt gcc -o myprog -lm main.o serial.o temp.o oder ähnlich.
super, danke mit dem hat es auch geklappt.
Ich arbeite mit Eclipse dass mir ein makefile generiert
dort habe ich es eingefügt.

probleme habe ich jetzt mit der sched.h
die find ich nirgends auf meinem system! auch nicht der compiler
ist da wieder etwas zum hinzufügen?
Janka wrote:Aber Achtung! Nicht mit X rumprobieren, sondern nur mit einer ebenfalls auf SCHED_FIFO gesetzten Shell,
und wie setz ich eine Shell auf SCHED_FIFO?
Du meinst sicher mit nice --20
aber wie mach ich dass wenn ich den X-manager ausgeschaltet habe?
in Windows würde ich es mit CMD machen
reicht dann nice --20 bash?
Janka wrote:Mal ganz unabhängig davon rate ich dir eher zu diesen Chips:http://www.maxim-ic.com/pl_list.cfm/filter/21/ln/en
was bringt mir dieser Chip?
Bin noch nicht dazugekommen dass alles zu lesen.
Warscheinlich komme ich da auf genauere messungen.
Da muss ich noch mit meinem Bruder darüber reden
kostet ja sicher was.

8) pcAlko

pcAlko
Posts: 70
Joined: 14. May 2007 19:27

#6 Post by pcAlko »

ach ja,
bevor ich es vergesse ...

hast Du mit dem Befehl log() schonmal gearbeitet?
Er gibt bei mir immer NaN zurück.
obwohl ich mit -lm compile
vielleicht komm ich morgen nochmals dazu Ihn besser zu testen.

8) pcAlko

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#7 Post by Janka »

pcAlko wrote: probleme habe ich jetzt mit der sched.h
die find ich nirgends auf meinem system! auch nicht der compiler
ist da wieder etwas zum hinzufügen?
Eigentlich gehört das zu glibc-devel. Muss da sein.
Janka wrote:Aber Achtung! Nicht mit X rumprobieren, sondern nur mit einer ebenfalls auf SCHED_FIFO gesetzten Shell,
und wie setz ich eine Shell auf SCHED_FIFO?
Du meinst sicher mit nice --20
Nein. nice --20 setzt nur den nice-Wert auf die höchste Priorität. Das ist aber immer noch SCHED_OTHER, also niedriger, als irgendein Programm auf SCHED_FIFO. Und SCHED_FIFO-Prozesse laufen *immer*, wenn es keinen anderen SCHED_FIFO-Prozess mit höherer Priorität gibt, der ebenfalls lauffähig ist.

Mir ist kein Utility bekannt, dass Echtzeitpriorität setzen kann. Ein echter Mangel. Du kannst dir allerdings ein kleines Hilfsprogramm basteln, dass halt nur einen Aufruf von sched_setscheduler enthält und die pid auf der Kommandozeile entgegennimmt.
aber wie mach ich dass wenn ich den X-manager ausgeschaltet habe?
in Windows würde ich es mit CMD machen
reicht dann nice --20 bash?
Wir sind hier nicht bei MS-Windows. Es gibt eine Textkonsole [Strg]+[Alt]+[F1] z.B..

Bei MS-Windows kann man sich übrigens genauso aussperren, und da es keine vernünftige Textkonsole gibt, muss man dort zuvor *alle* Prozesse, die was mit der GUI zu tun haben, ebenfalls auf Echtzeitpriorität anheben. Oder halt den Stecker ziehen, falls man was falsch gemacht hat.
Janka wrote:Mal ganz unabhängig davon rate ich dir eher zu diesen Chips:http://www.maxim-ic.com/pl_list.cfm/filter/21/ln/en
was bringt mir dieser Chip?
Bin noch nicht dazugekommen dass alles zu lesen.
Warscheinlich komme ich da auf genauere messungen.
Da muss ich noch mit meinem Bruder darüber reden
kostet ja sicher was.
Einen NTC musst du einmessen, weil jedes Exemplar ein wenig streut. Eine größere Genauigkeit als 2..5°C solltest du mit der Kennlinie, wie sie der Hersteller im Datenblatt angibt, nicht erwarten. Da nackte NTCs üblicherweise nur in Regelkreisen als Temperatursicherung eingesetzt werden, macht das dort ja nichts. Für ein Thermometer musst du die Kennlinie jedes einzelnen NTC selbst aufnehmen. Also ein geeichtes Thermometer nehmen, Wasser erhitzen, NTC und Thermometer ins Wasser, und dann bei abkühlen zumindest 1 Messpunkt je 10°C aufnehmen. Danach die logarithmische Kurve hineininterpolieren.

Den Spaß kannst du dir mit den Chips oben sparen, weil diese bereits in der Fabrik einzeln ausgemessen wurden. Außerdem kannst du mehrere Messpunkte an ein dreiadriges Buskabel legen und dir die Treiberbastelei, wie du sie jetzt machst, sparen.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#8 Post by Janka »

pcAlko wrote:ach ja,
bevor ich es vergesse ...

hast Du mit dem Befehl log() schonmal gearbeitet?
Er gibt bei mir immer NaN zurück.
obwohl ich mit -lm compile
vielleicht komm ich morgen nochmals dazu Ihn besser zu testen.

8) pcAlko
Man kann Postings auch editieren.

In dem Fall solltest du mal die Variable "errno" prüfen.

$ man errno
$ man perror

Vermutlich versuchst du, den Logarithmus von 0 oder einer negativen Zahl zu ziehen. Der ist nicht definiert.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

pcAlko
Posts: 70
Joined: 14. May 2007 19:27

#9 Post by pcAlko »

hallo Janka,

das mit dem log() muss ich noch besser testen,
habe im moment leider keine Zeit dafür.

die sched.h habe ich schon gefunden
hab bei der Angabe das "c" vergessen :oops:

wie funktioniert dass mit dem 3 Parameter von sched_setscheduler() ?
einen sched_param struct kann ich nicht erzeugen
bin bzw. war halt nur ein C++ programmierer!!!

was ich mich erinnern kann
musste in C für jeden struct ein typedef deffiniert werden
aber das haut bei mir auch nicht so hin.

kannst Du mir dabei bitte nochmal helfen!?

8) pcAlko

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#10 Post by Janka »

Und wieder ein Grund mehr, warum C++ für Einsteiger eine absolut ungeeignete Sprache darstellt.

Code: Select all

#include <sched.h>
#include <stdlib.h>

void setprio&#40;pid_t pid&#41;
&#123;
  const struct sched_param sp=
  &#123;
    sched_priority&#58; 1,
  &#125;;

  if &#40;sched_setscheduler&#40;pid, SCHED_FIFO, &sp&#41;<0&#41; \
  &#123;
    perror&#40;"sched_setscheduler"&#41;;
    exit&#40;EXIT_FAILURE&#41;;
  &#125;
&#125;

int main&#40;int argc, char* argv&#91;&#93;&#41;
&#123;
  if &#40;argc>1&#41;
    setprio&#40;&#40;pid_t&#41;atoi&#40;argv&#91;1&#93;&#41;&#41;;
&#125;
Alternativ kannst du natürlich auch eine Variable sp definieren und dann mittels sp.sched_priority=... den Wert setzen. Guck dir mal lieber ein Lehrbuch zu C (nicht C++!) an.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

pcAlko
Posts: 70
Joined: 14. May 2007 19:27

#11 Post by pcAlko »

Ich habe die Alternative vorgezogen!
Dein Beispiel mit sched_priority: 1, ist sehr interresant
das ist wohl höchst tiefes C :wink:

Janka wrote:Und wieder ein Grund mehr, warum C++ für Einsteiger eine absolut ungeeignete Sprache darstellt.
diesen Joke verstehe ich aber nicht ganz!
eigentlich habe ich ja nur struct vor der definition vergessen.
Aber ich muss zugeben gerade bei den feinen Unterschieden
da haperts halt schon ein bisschen.
Und natürlich kommt dazu dass ich schon wieder viel vergessen habe.


also jetzt funktioniert wenigstens alles.
beim log war es doch eine Negative Zahl.
Ich hab das mal untersucht,
es müssen mindestens 14757 millisekunden sein
um einen positiven Wert für log zu erhalten.
ich komm aber nur auf 91 millisekunden
heute um 19:00 hatte es 21.2 °C bei mir im Zimmer
ich glaub ich hab da einen falschen NTC-Wiederstand
muss ich mal checken.

Mir kommt das nur komisch vor,
da ich mit dieser Rechnung
um auf 77°C zu kommen
60500000000 millisecunden brauche
irgendwas läuft da noch schief.

ist nicht eine Millisekunde 1/1000 einer sekunde?
ich hab das mal mit einem händischen abbruch der Schleife,
indem ich nach einer Minute DTR und DSR verbunden habe,
ausprobiert.
Ich komme da nur auf 14940 Millisekunden.
obwohl ich im Echtzeitmodus laufe
kann ich wärend dessen ohne weiteres
jedes beliebige Programm starten.
>> wo ist der bussy-Log? <<
sched_setscheduler gibt mir 0 zurück
also kein Fehler
sched_getscheduler(0) inerhalb der Schleife gibt mir 1 zurück.

ist das alles ok so?


8) pcAlko

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#12 Post by Janka »

Das kann ich dir nicht sagen... richtige PID erwischt?

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

pcAlko
Posts: 70
Joined: 14. May 2007 19:27

#13 Post by pcAlko »

laut man-pages steht ja
"If pid equals zero, the scheduler of the calling process will be set."
dass heisst für mich dass ich da 0 hineinschreiben kann.
aber ich habe es auch mit getpid() versucht.

kannst Du mal über meinen source-code blicken!?
vielleicht ist da ja irgend ein Fehler drin den ich übersehen habe.

Code: Select all

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sched.h>
#include <errno.h>
#include <unistd.h>

int main &#40; &#41;
&#123;	
	int	nMin;
	int nSec;
	int res;
	time_t tnow;
	struct tm *tmnow;
	unsigned long	usleepTime;
	const struct sched_param sp=
	&#123;
    	sched_priority&#58; 1
	&#125;;
	
	printf&#40;"aktuller PID %d\n", getpid&#40;&#41;&#41;;
	usleepTime= 0;
	res= sched_setscheduler&#40;getpid&#40;&#41;, SCHED_FIFO, &sp&#41;;
	if&#40;res != 0&#41;
	&#123;
		printf&#40;"set real-time scheduling \n"&#41;;
		printf&#40;"ERROR %d ", errno&#41;;
		perror&#40;"sched_setscheduller"&#41;;
		printf&#40;"\n"&#41;;
		return&#40;1&#41;;
	&#125; 
	printf&#40;"set to police %d\n", sched_getscheduler&#40;0&#41;&#41;;
	
	time&#40;&tnow&#41;;
	tmnow= localtime&#40;&tnow&#41;;
	nMin= tmnow->tm_min;
	nSec= tmnow->tm_sec;
	printf&#40;"Start %d&#58;%d\n", nMin, nSec&#41;;	
	do&#123;
		usleep&#40;1&#41;;
		++usleepTime;
		time&#40;&tnow&#41;;
		tmnow= localtime&#40;&tnow&#41;;
	&#125;while&#40;nMin == tmnow->tm_min || tmnow->tm_sec <= nSec&#41;;
	
	printf&#40;"End %d&#58;%d \n", tmnow->tm_min, tmnow->tm_sec&#41;;
	printf&#40;"%lu milliseconds\n", usleepTime&#41;;
	return &#40;0&#41;;
&#125;
hierbei hab ich nur eine Minute abgestopt
und ausgegeben wiviele Millisekunden er gerechnet hat.
normaler weise müssten doch 60.000 herauskommen.
bei mir ist es aber nur 15.099

ich hab in meinem Büchlein nochmals gelesen
und entdeckt dass ich sogar Mikrosekunden brauche
eine Mikrosekunde ist laut wikipedia 1000 Nanosekunden
das klapt natürlich nie und nimmer, solange ich keine Echtzeit schaffe.

8) pcAlko

User avatar
Janka
Posts: 3585
Joined: 11. Feb 2006 19:10

#14 Post by Janka »

Ähm. Du gehst davon aus, dass der einzige Aufruf, der in deiner Schleife Zeit verbraucht, usleep(1) sei. Das ist aber in diesen winzigen Dimensionen nicht mehr der Fall, time und localtime werden den Rechner auch einige Mikrosekunden beschäftigen.

So genau kann man nur einen Hardwaretimer Zeit messen lassen.

Janka
Ich vertonne Spam immer in /dev/dsp statt /dev/null.
Ich mag die Schreie.

pcAlko
Posts: 70
Joined: 14. May 2007 19:27

#15 Post by pcAlko »

Hallo Janka!

Ohne Dich wäre dieses Forum nur halb so gut!
Ich hoffe Du bleibst uns hier noch lange erhalten.

Ich kann aber leider nichts mit dieser Aussage anfangen.
Mir wäre eine Zeitmessung wie über localtime auch lieber.
Leider habe ich aber die funktion dafür noch nicht gefunden. (über eine genauigkeit von milli-, nanosekunden)
Mit dem Wort Hardwaretimer kann auch Google nichts anfangen.
bei man uslleep steht zwar SIHE AUCH settimer, gettimer
aber die sind in den manpages nicht enthalten.
ebenso in man nanosleep -> timer_create().
was ich gefunden habe ist der Profiler
aber der ist ja von aussen und wird über eine compileroption erreicht
welches mir dann mein ganzes Programm analysiert.

kann ich diese Hardware Zeit auch über mein C-App ereichen?


habe ich mit diesem Programm jetzt die Echtzeit aktiviert oder Nicht?
oder merke ich das die Minute lang gar nicht
weil ich ja usleep() einsetze
und die Millisekunde ist genug dass man das
vor lauter geschwidigkeit gar nicht merkt!?

8) pcAlko

Post Reply