Bei Conrad gibt es eine komplette Relaisplatine 8-fach seriell unter der Bezeichnung 8FA für relativ günstige 39,95 EUR. Die Platine hat 8 Relais und es können bis zu 255 Relaiskarten kaskadiert werden (255 Relaiskarten * 8 Relais = 2040 schaltbare Relais insgesamt). Conrad gibt zwar nur eine Belastbarkeit von 24 V und max. 2 A an, aber die Relais schaffen laut Aufdruck 250 V und 6 A, so dass man damit bis 1380 W schalten kann, was für die meisten Geräte ausreicht. Im Netzt habe ich dazu diese Seite gefunden: http://www.netzmafia.de/skripten/hardware/relais/relais.html aber dem Programm fehlten noch ein paar Sachen wie Überprüfung des Timings der ausgetauschten Datenpakete, Empfangen der Daten mittels select, Timeout beim Öffnen des Devices, exklusives Öffnen (damit nicht mehrere Programme gleichzeitig auf derselben Schnittstelle arbeiten) usw.. Deshalb habe ich die überarbeitete Version angehängt. Mit onboard-Ports funktioniert es problemlos, aber über einem noname USB-RS232-Adapter, den ich von KM habe, funktioniert es nicht zuverlässig; vermutlich ist die Ausgangsspannung der Karte für den Adapter zu klein. Die Hardware-Bilder dazu habe ich hier (bandbreitenbegrenzt): http://random.linux-site.net/files/unsorted/powerbox2/powerbox2_a.jpg http://random.linux-site.net/files/unsorted/powerbox2/powerbox2_b.jpg http://random.linux-site.net/files/unsorted/powerbox2/powerbox2_c.jpg http://random.linux-site.net/files/unsorted/powerbox2/powerbox2_d.jpg http://random.linux-site.net/files/unsorted/powerbox2/powerbox2_e.jpg http://random.linux-site.net/files/unsorted/powerbox2/powerbox2_f.jpg http://random.linux-site.net/files/unsorted/powerbox2/powerbox2_g.jpg Durch das Eisenblech-Gehäuse gibt's weder EMV- noch ESD-Probleme und damit die Masse von der Karte nicht frei driftet, wenn die Schnittstelle nicht angeschlossen ist, habe ich zur Gehäusemasse einen Leistungswiderstand von 560 Ohm genommen; dadurch werden auch Brummströme begrenzt. Getestet habe ich das Programm nur unter Linux, aber mit mimimalen Änderungen sollte es unter jedem Posix-Kompatiblem Betriebssystem funktionieren. Wegen den Posix-Threads muß man den Sorcecode mit der Option -lpthread kompilieren. Ich benutze dafür diese Funktion in der .bashrc: # Funktion zum Kompilieren. Bsp.: "c bsp" kompiliert bsp.c und produziert bsp. function c { gcc -Wall -I. -O3 -D_GNU_SOURCE -D__SMP__ -DLINUX -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_REENTRANT -lpthread -lrt -mcpu=i686 -fexpensive-optimizations -DCPU=686 -ffast-math -m486 -lm -lz -o $1 $1.c && prelink -fmRv ./$1 && strip $1 } Übrigens gibt's hier ein größeres Programm, mit dem man mehrere kaskadierte Karten ansprechen kann, dem aber Sachen wie select und die anderen oben aufgelisteten Sachen fehlen: http://www.relaiskarte.thomas-dohl.de/
Weil mir aufgefallen ist, das die Adresse nicht überprüft wird, habe ich die entsprechende Überprüfung eingebaut (Anhang). Allerding zeigt sich hier ein Bug der Karte: Laut Kapitel 4.5 der Bedienungsanleitung sollte die Karte in ihrer Antwort ihre Adresse verwenden, und die ist laut Kapitel 4.5 bei der ersten Karte immer 1. Diese Adresse kommt aber nur zu ca. 1 %; zu 99 % kommt als Adresse 2 zurück! Es funktioniert aber trotzdem; es ist nur ein irgnorierbarer Bug in der Karten-Firmware. Bei der Gelegenheit, und weil zu 1 % die Karte keine Antwort schickt, habe ich auch eingebaut, dass das Programm im Fehlerfall -1 zurück gibt und 0 bei keinen Fehlern und ignorierbaren Bugs.
Das die Relais 250 V / 6 A können glaub ich Dir ja. Hast du mal überprüft, ob die Leiterplatte und die Anschlussklemmen das auch können? Stichwort Leiterbahnabstand, Querschnitt, ... Ansonsten finde ich 39 Euro für ein Schieberegister nicht sonderlich günstig. Werner
"Hast du mal überprüft, ob die Leiterplatte und die Anschlussklemmen das auch können? Stichwort Leiterbahnabstand, Querschnitt, ..." Ja, deshalb habe ich die Leiterbahnen an den Relais-Ausgängen mit Lötzinn verdickt (man kann auch Draht nehmen), so dass 6 A kein Problem sind. Die Abstände stimmen auch, also über 4 mm Abstand zu Masse und anderen Niedervolt-Leitungen. Ich bin ja nicht der einzige, der die Karte problemlos so verwendet (1. URL). "Ansonsten finde ich 39 Euro für ein Schieberegister nicht sonderlich günstig." Hast Du mal nachgesehen, was Du dafür bekommst? In dem Karton ist neben der Bedienungsanleitung mit dem Schnittstellen-Protokoll eine bestückte Platine an der man nichts löten muß; plug and play! Für die Euro-Platine mit fertig programmierten Mikrocontroller, 8 Leistungs-Relais mit separater LED, Spannungsregler, Quarz, RS232-Buchse, 4 Befestigungs-Löchern, zweite Schnittstelle zum Kaskadieren uws. ist es günstig. Wenn Du sowas selbst machst, werden allein die Material-Kosten kaum niedriger sein.
"Hast Du mal nachgesehen, was Du dafür bekommst?" Erstmal können ! "Ihre Suche nach dem Begriff "8FA" in allen Kategorien ergab keine genauen Treffer." Und eine Software, die nur zu 99% funktioniert, würde ich gleich wegschmeißen. Peter
""Ihre Suche nach dem Begriff "8FA" in allen Kategorien ergab keine genauen Treffer."" Dann hast Du nicht auf conrad.de gesucht, denn da bekommt man die Karte als ersten Treffer: http://www1.conrad.de/scripts/wgate/zcop_b2c/~flN0YXRlPTI4NzUxOTAwMzE=?~template=PCAT_AREA_S_BROWSE&glb_user_js=Y&shop=B2C&p_init_ipc=X&~cookies=1 "Und eine Software, die nur zu 99% funktioniert, würde ich gleich wegschmeißen." Die Software funktioniert zu 100 %; sonst würde die nicht einmal eine Fehlermeldung ausgeben (so wie die Software, bevor ich sie überarbeitet habe). Der Rückgabewert des Programms stimmt immer, auch wenn die Karte nicht antwortet! Gelegentlich antwortet die Karte einfach überhaupt nicht; es ist ein Bug in der Karte. Deshalb, und wegen der falschen Adresse in der Antwort, habe ich mal bei Conrad nachgefragt. Eine Applikation muß ja nur den Befehl über das Programm so lange wiederholen, bis der Rückgabewert 0 ist oder nach z. B. einer Minute abbrechen. Weil ich in der neuesten Version noch die Ausgabe der Firmware-Version eingebaut habe, anbei die neueste Version. Bei meiner Karte ist die Version 10 drinn.
Anbei die neueste Version, die 100 % nur dann terminiert, wenn die Relais erfolgreicht gesetzt/abgefragt werden konnten. Die Timeouts habe ich auf 2 s reduziert, so dass bei fehlender Karte alle 2 s versucht wird mit der Karte zu kommunizieren. Man sieht damit nun, dass während des Einschaltens der MC verwirrt ist und erstmal dutzende fehlerhafter Pakete schickt. Das ist ein weiterer Bug. Eine sauber programmierte MS-SW enabelt die UARTs ja erst dann, wenn sie korrekt verwendet werden können, so dass fehlerhafte Datenpakete nicht produziert werden können. Es kann auch an einer quick and dirty-SW liegen, die das Timing nicht überprüft und dadurch Anfang und Ende eines Datenpakets nicht richtig erkennt. Jedenfalls funktioniert's nun auch so und durch die Prüfsumme wird nichts falsches eingeschaltet.
Gemäß Murphys Law ist mir noch aufgefallen, dass die while-Schleife falsch war, weil die nur auf Empfang gewartet hat, aber nie gesendet hat, bei falschem Parameter fälschlich mit return code 0 terminiert wurde, für's Prettyprinting Klammern bei dem großen else if -Block fehlten usw. anbei die überarbeitete Version.
Gemäß Murphys Law war in der letzten Version noch ein longjmp zuviel für den Fall, daß #define EXIT_ONLY_ON_SUCCESS auskommentiert wird, für die Variate, die nach einem Versuch in jedem Fall terminiert (innerhalb 2 s).
So nun habe ich eine Antwort von Conrad und danach soll man die Beispiel-Programme nehmen. Demnach wird die Adresse in der Antwort immer ignoriert; d. h. der Bug wird einfach ignoriert! Und daß die Karte sich zu 1 % nicht initialisieren läßt, auch mit den Beispiel-Programmen, liegt daran, dass die Karte mindestens 200 ms Pause braucht; das fehlt in der Bedienungsanleitung einfach. Anbei deshalb die neueste Version, mit der es nun auch die dutzende fehlerhafte Pakete nach dem Einschalten der Karte nicht mehr gibt. Außerdem ist noch pthread_cancel durch pthread_join ersetzt, damit es keine ständig wachsende Anzahl von Thread-Zombies gibt.
Bei der letzten Version fehlten für den seltenen Fall, daß das device nicht geöffnet werden kann, Signal-Handler zur korrekten Interprozesskommunikation. Anbei die neueste Version bei der die Signal-Handler eingebaut sind. Außerdem werden nun auch die alte und die neue Schalterstellung ausgegeben, damit man auch beim Stellen stehen kann, was vorher eingestellt war.
Hi, ich habe mir mal die letzte Version des Relais Programms gezogen. Beim Compilieren kommen aber nur Fehlermeldungen: audib4@speedy:~/Documents/Relaiskarte/relaisv1> gcc -o relais relais.c /tmp/ccMWLU2d.o(.text+0x88e): In function `func_timeout': : undefined reference to `pthread_kill' /tmp/ccMWLU2d.o(.text+0x9ed): In function `main': : undefined reference to `pthread_create' /tmp/ccMWLU2d.o(.text+0xa43): In function `main': : undefined reference to `pthread_create' /tmp/ccMWLU2d.o(.text+0xa92): In function `main': : undefined reference to `pthread_join' /tmp/ccMWLU2d.o(.text+0xab4): In function `main': : undefined reference to `pthread_join' collect2: ld returned 1 exit status Da ich im C programmieren noch nicht die Ahnung habe könnte mir jemand helfen diese Fehler wegzubekommen? Oder habe ich beim Compilieren was falschgemacht? System Suse 8.2 in einer ziemlichen Standart Installation. Danke Ingo
Wer lesen kann ist klar im vorteil. OK compilieren tut er jetzt aber funktioniern tuts immer noch nicht das Programm bleibt mit: Signal 11, program exiting... einfach stehen. Was habe ich nun wieder falschgemacht? Danke Ingo
Das ist von hier nicht genau feststellbar. Das Programm wird immer ohne Fehler/Warnungen compiliert und bei mir läuft das Programm auf mehreren Rechner unter SuSE und Debian und zwar auch dann problemlos, wenn ich es mit lefence (das findet Signal 11 -Fehler bevor sie das Programm beenden) benutze. Du solltest mal prelink und strip weglassen und deinen Rechner mit einem Speichertest checken: http://www.ayukov.com/essays/signal11.html
Weil ich inzwischen noch ein paar Debugging-Ausgaben (aktiviert wenn DEBUG per define gesetzt ist) eingebaut habe und noch ein paar Kleinigkeiten wie const bei read-only-Parametern eingebaut habe, anbei die aktuelle Version. Auf einem dritten PC (Supermicro 370DL3, dual P III 1000) mußte ich aber feststellen, dass es mit den onboard-Ports nicht richtig funktioniert, obwohl sonst damit alles geht; auch ein Selbst-Update eines MCs, der die Daten (60 kB) mit einem RAMloader und Bit-Banging über RS232 einliest (was kritisch ist bezüglich Timing und nicht an jedem PC/Adapter funktioniert). Offensichtlich synchronisiert der UART der Karte nicht sauber, weil er mit dem Timing außerhalb des RS232-Standards liegt! Bei anderen PCs (z. B. mit Tyan Tiger MPX) funktioniert es und es geht mit dem USB2.0-Adapter weil die UARTs toleranter sind, aber es geht schon nicht mit dem USB1.1-Adapter; da geht ungefär die Hälfte der Bytes verloren. Bei den Adaptern ist es unabhängig vom Rechner. Bei Gelegenheit werde ich mal versuchen das durch den Austauch des Quarzes der Karte zu korrigieren ...
Hallo, hat bisher alles nichts gebracht, rufe ich Relais ohne Pararmeter auf kommt die Hilfe seite mit Pararmeter kommt das Signal 11. Wenn noch jemand andere Ideen hat Bitte melden sonst war das ein netter versuch. Danke Ingo
Wie genau rufst Du es denn auf? Und was ist, wenn Du nur "-on" oder "-off" als Parameter verwendest? Ich habe die Eingabeprüfung nicht ausgearbeitet, sondern nur übernommen, so daß da fehlende Eingabeüberprüfungen drinn sein können.
Hallo, ohne Pararmeter so: audib4@speedy:~/Documents/Relaiskarte/relaisv1> relais Ansteuerprogramm fuer die serielle Relaiskarte von Conrad No Parameters! mit entsprechender Pararmeter übergabe so: audib4@speedy:~/Documents/Relaiskarte/relaisv1> relais -on Signal 11, program exiting... so stellt sich das entsprechen der hilfe Seite im ersten Bsp. als richtig dar. Gebe ich das /dev/ttyS0 mit an genau dasselbe auch mit/ohne Relaiskarte. Relaiskarte funktioniert mit einem WIN rechner eines Bekannten meine serielle funktioniert mt einem testweise angeschlossenem Modem. Zur HW ein Tyan Trinity100 AT mit einem K6-2-550, also gut abgehangene HW älteren Baujahres. Danke Ingo
Was sagt denn Memtest86, wenn Du es ein paar Stunden laufen läßt? Ohne die Kiste kann ich von hier nichts dazu sagen. Du kannst ja mal mit der Option -ggdb compilieren und dann mit gdb relais run -on starten. Mit list sollte angezeigt werden, wo das signal 11 passiert.
Hallo, hier mal die gewünschten angaben: audib4@speedy:~/Documents/Relaiskarte/relaisv1> gdb relais GNU gdb 5.3 Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i586-suse-linux"... (gdb) run -on Starting program: /home/audib4/Documents/Relaiskarte/relaisv1/relais -on [New Thread 16384 (LWP 12466)] [New Thread 32769 (LWP 12467)] Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 32769 (LWP 12467)] 0x40028f5e in pthread_handle_create () from /lib/libpthread.so.0 (gdb) list 410 #ifdef DEBUG 411 printf("g_fd=%d\n", g_fd); 412 #endif 413 pthread_exit ((void *) &retval); 414 } 415 416 417 int 418 main (int argc, char *argv[]) 419 { // static asserts that all values are initialized with 0 recursively (gdb) also wenn ich die Ausgaben richtig deute habe ich ein Segmentation fault von /lib/libpthread.so.0 die list ausgabe sagt mir aber garnichts (C Programmcode) hast Du noch Ideen sollte ich mir eine neuere /lib/libpthread.so.0 besorgen? Danke Ingo
Zu früh gesendet Memtest ist vor ca. 2Wochen ein ganzes Wochenende gelaufen ohne Fehler. Danke Ingo
Hm, also wenn der Fehler im Programm wäre, hätte gdb sowas wie main (argc=2, argv=0xbffff0c4) at relais.c:439 gemeldet; d. h. der Fehler ist wirklich in der lib die Du verwendest. Das ist merkwürdig, da es Posix Threads seit rund 20 Jahren gibt. Am Besten machst Du ein Update; damit sollte das Problem beseitigt sein. Anbei eine Version, die ich unter SuSE 9.2 compiliert habe. Ich konnte die aber nicht statisch linken.
Hallo, Suse und Updates bisher nur schlechte Erfahrung gemacht. Am Wochenende werde ich mir mal die sache in Ruhe anschauen. Danke Ingo
Gemäß Murphys Law hatte get_time noch einen selten sichtbaren Bug, weil die Zeit in µs mit zwei getrennten Aufrufen bestimmt wurde. In der angehängten Version ist dieser Bug mit nur einem Aufruf von gettimeofday beseitigt. Inzwischen konnte ich auch das statische Linken mit gcc -g -Wall -O3 -D_GNU_SOURCE -D__SMP__ -DLINUX -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_REENTRANT -funroll-loops -fexpensive-optimizations -ffast-math -DCPU=686 -c -o relais.o relais.c gcc -g -static -Wall -O3 -D_GNU_SOURCE -D__SMP__-DLINUX -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_REENTRANT -lrt -funroll-loops -fexpensive-optimizations -ffast-math -lm -DCPU=686 -I/usr/lib/ -o relais relais.o /usr/lib/libpthread.a hinbekommen, aber offenbar durch einen Bug in libpthread.a bewirkt der Aufruf von pthread_create ein Segmentation Violation (Signal 11); d. h. das statisch gelinkte Programm funktioniert nicht. Dabei ist es egal ob man es unter SuSE oder Debian compiliert und linkt. Da bleibt nur dynamisches Linken, wie oben beschrieben; damit funktioniert es unter SuSE wie unter Debian problemlos.
Also der Bug ist in der glibc, wie der Debugger (DDD) zeigt:
Core was generated by /home/nobody0/c/8fa/1/relais -on'.
Program terminated with signal 11, Segmentation fault.
#0 0x0804a4fc in __pthread_manager ()
Inzwischen habe ich herausgefunden, daß es auch an den
Thread-Attributen liegt: Laut Man-Page kann man pthread_create als
zweites Argument einen Null-Pointer oder einen Pointer auf eine
Variable vom Typ pthread_attr_t übergeben.
Wird die Variable aber nur mit Null initialisiert indem man sie z. B.
als static deklariert, bewirkt das sowas wie ein nicht abgefangenes
Dereferenzieren eines Null-Pointers beim statisch gelinkten Programm.
Wird die Variable mit pthread_attr_init initialisiert, tritt der Bug
nicht auf.
Wieso der Bug bei dynamisch gelinkten Programmen nicht auftritt, habe
ich noch nicht herausgefunden.
Anbei das Programm im Source mit pthread_attr_init und auch als
statisch gelinktes executable.
Es funktioniert auch ohne die Hardware und gibt dann dies aus:
> ./relais -on
init port
opened port 0, g_fd=0
Connection timeout (select failed).
FAIL: card init failed (0 0 0 255).
init port
...
Es scheint einen weiteren Bug zu geben. Bei mehr als 18 Karten die Verbunden sind werden alle antworten geschluckt. Es werden die Karten mit der einfachen stateless ansteuerung von thomas (http://www.thomas-dohl.de/relaiskarte/) zwar angesteuert aber ich bekomme einen Timeout und strace zeigt open("/dev/ttyS0", O_RDWR|O_NONBLOCK|O_NOCTTY) = 4 ioctl(4, TCFLSH, 0) = 0 ioctl(4, TCSETS, {B19200 -opost -isig -icanon -echo ...}) = 0 ioctl(4, SNDCTL_TMR_TIMEBASE, {B19200 -opost -isig -icanon -echo ...}) = 0 read(4, 0x804c680, 4) = -1 EAGAIN (Resource temporarily unavailable) Bei mehr als 12 musste ich bereits die Timeouts auf 10000 usec erhöhen. Bis 18 gings dann wieder. Jetzt klappts überhaupt nicht mehr mit der Rückmeldung. Dein Programm liefert bei -stat: clone(Process 1129 attached child_stack=0x80ffe90, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND) = 1129 [pid 1128] write(4, "\0\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\20(\363"..., 148) = 148 [pid 1128] rt_sigprocmask(SIG_SETMASK, NULL, [RTMIN], 8) = 0 [pid 1128] write(4, "\240\202\v\10\0\0\0\0\240\252\v\10P\224\4\10\210\252\v"..., 148) = 148 [pid 1128] rt_sigprocmask(SIG_SETMASK, NULL, [RTMIN], 8) = 0 [pid 1128] rt_sigsuspend([] <unfinished ...> [pid 1129] --- SIGSTOP (Stopped (signal)) @ 0 (0) --- [pid 1129] rt_sigprocmask(SIG_SETMASK, ~[TRAP 33], NULL, 8) = 0 [pid 1129] read(3, "\0\0\0\0\5\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\20(\363"..., 148) = 148 [pid 1129] poll([{fd=3, events=POLLIN, revents=POLLIN}], 1, 2000) = 1 [pid 1129] getppid() = 1128 [pid 1129] read(3, "\240\202\v\10\0\0\0\0\240\252\v\10P\224\4\10\210\252\v"..., 148) = 148 [pid 1129] old_mmap(0xbf600000, 2097152, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xbf600000 [pid 1129] mprotect(0xbf600000, 4096, PROT_NONE) = 0 [pid 1129] clone(Process 1130 attached child_stack=0xbf7ffbd0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGRT_1) = 1130 [pid 1129] kill(1128, SIGRTMIN) = 0 [pid 1128] --- SIGRTMIN (Unknown signal 32) @ 0 (0) --- [pid 1128] <... rt_sigsuspend resumed> ) = -1 EINTR (Interrupted system call) [pid 1128] sigreturn() = ? (mask now [RTMIN]) [pid 1128] rt_sigprocmask(SIG_SETMASK, NULL, [RTMIN], 8) = 0 [pid 1128] write(4, "\240\202\v\10\0\0\0\0\240\252\v\0100\225\4\10\214\252\v"..., 148) = 148 [pid 1128] rt_sigprocmask(SIG_SETMASK, NULL, [RTMIN], 8) = 0 [pid 1128] rt_sigsuspend([] <unfinished ...> [pid 1129] poll([{fd=3, events=POLLIN, revents=POLLIN}], 1, 2000) = 1 [pid 1129] getppid() = 1128 [pid 1129] read(3, "\240\202\v\10\0\0\0\0\240\252\v\0100\225\4\10\214\252\v"..., 148) = 148 [pid 1129] old_mmap(0xbf400000, 2097152, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xbf400000 [pid 1129] mprotect(0xbf400000, 4096, PROT_NONE) = 0 [pid 1129] clone(Process 1131 attached child_stack=0xbf5ffbd0, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|SIGRT_1) = 1131 [pid 1129] kill(1128, SIGRTMIN <unfinished ...> zu mehr bin ich bis jetzt nicht gekommen. Wenn ich später im Büro bin schicke ich mal die gegenprobe mit 18 karten.( bin per ssh auf der maschine)
Die Karten brachen einige Zeit zum Verarbeiten, sind nicht fullduplex
fähig und vermutlich gilt das für beide Richtungen (serielle Verbindung
Richtung PC + weitere Karten), da sie quick and dirty programmiert
wurden, wie man am Bug mit falschen Empfangsadresse und der nicht
gerade zuverlässigen Übertragung sieht.
Ich habe für eine Karte 200 ms Wartezeit eingebaut und für 18 Karten
ergäbe das 3,6 Sekunden.
> read(4, 0x804c680, 4) = -1 EAGAIN (Resource temporarily unavailable)
Aus der Man-Page von read:
EAGAIN Non-blocking I/O has been selected using O_NONBLOCK and no
data
was immediately available for reading.
D. h. das Programm vom Thomas verwendet kein select, überprüft also
nicht ob etwas empfangen wurde und read liefert durch den leeren Puffer
entsprechend EAGAIN zurück.
Dem Programm vom Thomas fehlt zumindest select.
Hi, wie ich sehe scheint es doch noch ein paar Probleme mit meinem Programm zu geben. Hallo Michael, tritt der Fehler nur auf, wenn du massig Karten dran hängst? Wie genau ist denn die Fehlermeldung von meinem Programm? Ich bin gerade am entwerfen eines neuen Relaiskartenprogramms, aber das wird noch ein weilchen dauern, denn ich bin gerade im Prüfungsstress. Ich habe vor es auch mal mit Java zu versuchen. :-) Wenn du die beiden Programme lesen und schreiben nutzt, wie verhalten sich dann die Antworten der Relaiskarten? Also wie lange brauchen die Antworten, bis die erste eintrifft. Gruß Thomas
Inzwischen habe ich rausgefunden, daß das tcflush (fd, TCOFLUSH); nach dem write den Ausgangspuffer nicht leert (flush), wie der Name von tcflush nahelegt, sondern löscht (discharge)! Das erklärt den Datenverlust, denn dadurch wurde gelöscht, was noch nicht abgeschickt werden konnte! Anbei nun die Version ohne diesed tcflush, bei der es anscheinend keinen Datenverlust mehr gibt.
@Thomas: Das Problem tritt immer auf wenn mehr als 17 Karten kaskadiert werden. Es werden die Karten zwar angesprochen, aber mit den Rückmeldungen klappt es nicht mehr. Bis 17 Karten werden alle erkannt beim -i. Ich hab jetzt auch experimente mit einer 8fach seriell Karte gemacht. Selbes Problem. Da ich ca. 40 Karten ansteuern muss mache ich jetzt einen Split nach 17 Karten und verpasse den nächsten 17 einen anderen ttyS. Genaue Fehlermeldung beim -i: Es wurden keine Daten empfangen! (timeout) Es wurden keine Relaiskarten gefunden! :-( Das Programm wird auf Grund eines Fehlers beendet. The programme terminated due to an error. Ich teste nur ungern im Produktivsystem. Aber die nächsten 30 Karten warten schon auf einbau.
@Michael Miss doch bitte mal die Zeit, mit dem Programm lesen.cpp und schreiben.cpp, wie lange die Antworten der Karten benötigen. Wenn es immer länger dauert, je mehr Karten kaskadiert werden ist es klar, dass mein Programm abbricht. Gruß Thomas Dohl
Die Ursache ist sicherlich, daß nicht lange genug auf die Antwort gewartet wird, denn die Antwort von der Karte X dauert ja um so länger je weiter hinten sie ist (je größer X ist), da die Daten ja 2X-1 mal komplett empfangen werden müssen, dekodiert werden und dann weiter geschickt werden müssen. Die Wartezeit auf die Antwort muß proportional 2X-1 sein. Bei 100 bis 200 ms pro Karte braucht man für die 18. Karte also 3,5 bis 7 Sekunden. Übrigens kann man nach dem write noch ein tcdrain(fd); // wait till the output has been transmitted einfügen, damit die Software danach erst dann, und genau immer nur dann weiterläuft, wenn wirklich alle Daten rausgeschickt wurden. Damit kann man die Wartezeit auf die Antwort genauer einstellen. Anbei meine Version damit.
endlos :) ein strace zeigt auch warum: open("/dev/ttyS0", O_RDWR|O_NOCTTY) = 3 ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B19200 -opost -isig -icanon -echo ...}) = 0 ioctl(3, TCFLSH, 0) = 0 ioctl(3, SNDCTL_TMR_START or TCSETS, {B19200 -opost -isig -icanon -echo ...}) = 0 ioctl(3, SNDCTL_TMR_TIMEBASE or TCGETS, {B19200 -opost -isig -icanon -echo ...}) = 0 read(3, 0xbffff270, 255) = ? ERESTARTSYS (To be restarted) --- SIGWINCH (Window changed) @ 0 (0) --- read(3, 0xbffff270, 255) = ? ERESTARTSYS (To be restarted) --- SIGWINCH (Window changed) @ 0 (0) --- read(3, <unfinished ...> wie soll ich bei schreiben die Zeit messen ? Das Programm möchte eine eingabe und ich seh jetzt auch keine commandline options im source um einen time ./senden sinnvoll laufen zu lassen. Die befehler werden sofort ausgeführt. Wenn ich -r0 -s rrrrrrrr mache geht das recht flott ( unter 3 sekunden) bis alle ihren status geändert haben. Nur das lesen macht probleme.
Mich würde einfach interessieren, ob die Nachrichten nacheinander immer etwas zeitlich verstetzt eintreffen, oder ob alle nach eine immer längeren Zeit (je nach dem, wie viele Karten angehängt sind) eintreffen. Gruß Thomas
@ Michael Reck: In meinem Programm sind zwei Zeitmessungen drinn, unter anderem einmal (Zeit des Empfangs des ersten Bytes) - (Zeit direkt nach dem Senden), also die Ping-Zeit, die ich mit Minimum, Maximum und Durchschnitt sowie Fehler-Statistik von einem anderen Programm (für andere Hardware) ausgeben lasse. Du kannst den Code ja einfach übertragen und dann die Ping-Zeit ausgeben. Übrigens habe ich mein Programm nun so angepaßt, daß bei unvollständig empfangenen Paketen noch auf die letzten Bytes gewartet wird, denn ich hatte über einen USB-RS232-Adapter das Problem, daß nach dem select zwar etwas im Puffer war, aber die zweite Hälfte des Datenpaketes noch nicht angekommen war.
@ Rolf: mit deinem Programm bekomme ich gar keine ansteuerung hin. Es scheint durch die verschiedenen checks alles zu unterbinden. linux:/usr/src # ./relais /dev/ttyS0 -off got file descriptor fd=3 frame warning Firmware-Version 10 frame warning FAIL: second part of card init failed (254 2 10 0). An der Kasakade hängen 17 Karten. Die andere hat immo 6: linux:/usr/src # ./relais /dev/ttyS14 -off got file descriptor fd=3 Connection timeout (select failed). FAIL: card init failed (0 0 0 255). @thomas: An der 17er kaskade ist mir was aufgefallen. Ein -i schlägt fehl wenn bereits ein relais angesteuert wude: resetter -d /dev/ttyS0 -i COM Port: "/dev/ttyS0" Es wurden keine Daten empfangen! (timeout) Es wurden keine Relaiskarten gefunden! :-( Das Programm wird auf Grund eines Fehlers beendet. The programme terminated due to an error. Aber: linux:/usr/src # resetter -d /dev/ttyS0 -r0 -s 00000000 COM Port: "/dev/ttyS0" OK oder: linux:/usr/src # resetter -d /dev/ttyS0 -r1 -s 00000001 COM Port: "/dev/ttyS0" OK linux:/usr/src # resetter -d /dev/ttyS0 -r1 -s 00000000 COM Port: "/dev/ttyS0" OK
@Michael hm, interessant. Versuche mal mit -s 00000001 eine Karte höher 17 anzusprechen. Mich würde interessieren, ob dann vielleicht wieder ein Timeout kommt. Bei -s habe ich eine kleine Optimierung eingebaut. Und zwar wird erst bei "x,t" der aktuelle Zustand der Karte abgefragt, ansonsten wird einfach rausgeschrieben. Gruß Thomas
@Michael Reck: Mein Programm ist für EINE Karte! Daß die Checks jede Aktion verhindern stimmt also. Für mehrere Karten muß man das Programm vom Thomas nehmen.
Hier kann man sich eine günstige Platine bauen http://www.ees-hartz.de/P64_HLP/ 10 Bit 4 Kanal AD Wandler in Vorbereitung 1 Befehl senden 4 Ergebnisse zurück mfg F.Hartz
Wenn Probleme auftretten mit relais -on alle setzen relais -r5 relais 5 ausschlaten und dann steht alles kein zugriff mehr möglich Das liegt dann das als crc byte eine 0x13 uebertragen wird. Diese loest im Input Buffer des ioctl ein XON / XOFF aus. Abhilfe: Die Schnittstelle so bearbeiten. stty -ixon -ixoff -F /dev/ttyS0 Mgf Norbert
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.