pthread es a pthread_cond_timedwait

 ( BlinTux | 2010. október 5., kedd - 19:38 )

Udv!

Soha nem irtam meg tobb szalon futo programot, plane nem C-ben, de most elkerulhetetlen volt.
Viszont egy ponton elakadtam.
Amit el szeretnek erni az ennyire egyszeru:
Ha az egyik szal nem fut le 5 masodperc alatt, akkor hagyja a csudaba es lepjen ki a fuggveny.

Viszont ez a timeout dolog nem igazan jon ossze.

Bemasolom a kodomat, annak remenyeben, hogy valaki tud segiteni :)
Tudom, nem tul szep, meg minden, de eloszor csak azt akarom elerni, hogy mukodjon.

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int dataok = 0;

void *SensorComm(void *cmd) {
char dist;
int i;

// Read
if (cmd == 'r') {
i = 0;

printf("INFO: Szal '%c' elindult...\n", cmd);

pthread_mutex_lock (&mutex);

while (i <= 10) {
read(fd, &dist, sizeof(dist));

if (dist >= 0) {
printf("Ertek: %d \n", dist);
}
i++;
}

dataok = 1;
pthread_mutex_unlock (&mutex);
pthread_cond_signal (&cond);

pthread_exit((int *)dist);
}

// Write
if (cmd == 'w') {
i = 0;

printf("INFO: Szal '%c' elindult...\n", cmd);

while (i <= 10) {
send_data( " VA " );

usleep(80000);
i++;
}
}

printf("INFO: Szal '%c' lefutott.\n", cmd);

pthread_exit(NULL);
}

int get_dist () {

pthread_t thread[2];
pthread_attr_t attr;
int rc;
int t;
void *status;
char cmd[3];
struct timespec to;

// Set timeout
memset(&to, 0, sizeof to);
to.tv_sec = time(0) + 5;
to.tv_nsec = 0;

// Commands: r - read, w - write
cmd[0] = 'r';
cmd[1] = 'w';

// Initialize and set thread detached attribute
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);

// Create threads
for(t = 0; t < 2; t++) {
rc = pthread_create(&thread[t+1], &attr, SensorComm, cmd[t]);
if (rc) {
printf("HIBA; pthread_create() visszateresi erteke: %d\n", rc);
exit(-1);
}
}

/* Itt dolne el, hogy tortent-e idotullepes */

int ret = 0;
while (ret!=ETIMEDOUT) {
ret = pthread_cond_timedwait(&cond, &mutex, &to);
}

if (ret == ETIMEDOUT) {
printf("PFFF \n");
}

// Free attribute and wait for the other threads
pthread_attr_destroy(&attr);

for(t = 0; t < 2; t++) {
rc = pthread_join(thread[t+1], &status);
if (rc) {
printf("HIBA; pthread_join() visszateresi erteke: %d\n", rc);
exit(-1);
}
}

printf("INFO: get_dist lefutott. \n\n");

return 1;
}

int main(int argc, char **argv) {

printf ("ELSO OLVASAS \n");
get_dist();

sleep (2);

printf ("MASODIK OLVASAS \n");
get_dist();

printf ("VEGE! \n");

pthread_exit(NULL);
}

Ket szal fut, egyik ir, masik olvas. Ami problemas lehet, az az "r" (read) szal, ez befagyhat. Ezert kellene ra a timeout.
Remelem ertheto a problema es a kod is:)

Update:
Jobban olvashato kod

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

ha kimondottan adat-beolvasas a problema gyokere, es arra kell valamifele timeout-ot adni, akkor a select() a bara'tod. tehat ne az 1. sza'l figyelgesse a 2. sza'lat hogy minden oke'-e (elfutott idoben) hanem az adott szal minden mastol fuggetlenul figyelje az idoziteseket, a saja't idoziteseit. ami me'g kellhet esetleg az a gettimeofday() fv, illetve egyszeru modon ke't struct timeval kozotti idopont kozott eltelt idonek a szamolasa (aka. kivona's).

egyebkent mi az alap-problema? hardver-kozelibb? kicsit furcsa ez a bytonkent olvasas.

Ennek utana nezek, koszi!

A problema forrasa az az, hogy a soros portrol szeretnek adatokat begyujteni. Ezek egy szenzor mintavetelezesei. Legalabb 10 mintara lenne szuksegem. Viszont a read() fuggveny neha befagy. Ezaltal a program sem fut tovabb. Ezt akartam orvosolni egy iro, es egy olvaso szalal, es ha az olvasas szal nem adna eredmenyt 5 masod perc alatt, akkor egy uj minta vetelezest inditana.

Ez egészen biztosan nem jó megoldás így.
select() és poll() a barátaid.
Ezen felül man fcntl, azon belül F_SETFL és O_NONBLOCK.

Ezen felül man fcntl, azon belül F_SETFL és O_NONBLOCK.
ez sem rossz, elvileg, de nem nagyon meno". nehezebb tobb forrasbol jovo adatot kezelni, nehezebb a kulonbozo esetet megkulonboztetni (pl. a read() latszolag hibaval ter vissza, ha nincs adatat, de egyebkenet minden oke, ekkor kezzel me'g az errno-t is ellenorizni kell, es csak akkor kell panikolni, ha az nem EAGAIN); konnyebb belefutni egy busywait-ciklusba, kulon kell a timeout-okat fuggetlenul me'rni (a select()-ben ugye ez alapbol benne van, raadasul egyszeruen akkumulalhato modon), stbstb.

ha a kollega me'g nem probalt ilyesmit, akkor szerintem is a select() es a poll() a baratja elso kozelitesben, mintsem a nonblock mode.

A select/poll IS kell, meg az O_NONBLOCK IS kell. Trust me.

Tehát kapásból mindenkit non-blockingra kapcsolunk (ezt praktikusabb, ha rögtön az open()-en keresztül meg tudjuk tenni, de ha pl. socketünk van, akkor ott csak az fcntl() marad), PLUSZ select/poll segítségével várunk az eseményre. A hibakezelést, az errno nézegetést sehogy sem lehet megúszni. A select()-ben levő timeout-ot használni okos dolog, a "remaining time" viszont szerintem nem jó semmire sem, mivel csak a rendszerhívás alatt eltelt időt számolja, a mi user space kódunkban eltöltött időt nem, így ha ismételten meg-meghívjuk a selectet az eredeti timeoutból megmaradt idővel, akkor akár sokkal többet is várhatunk, mint eredetileg akartuk. Mondjuk pl. ha van egy signal handlerünk, amire valaki rendszeresen küld egy-egy signalt, ami után a select megy tovább.

A select/poll IS kell, meg az O_NONBLOCK IS kell.
erdekes. olyan me'g nem volt hogy a read() blokkolt volna akkor ha a select() azt mondja hogy oke, van adat. milyen esetekben fordulhat elo"? ha egy fd-rol egyszerre tobb sza'l/processz is olvas, es nem vagyunk esznel, akkor lehet race condition ilyen formabanan, de ezen felul? aki effelet csinal az mar elegge meredek forma lehet. max akkor lehet talan, ha ez all fenn (mmint osztott olvasa's), es az adott processz nem tudja az fd hattere't. pl alapertelmezett fd (stdin) amit ugy orokol valamely mas processzto"l, es nem tudja hogy mi van a vegen. de ez sem hangzik tul hetkoznapinak.

egyebkent a select()/poll() ill a o_nonblock mellett a 3ik vicces lehetoseg az a signal/sigio hasznalata. ezutobbit sem kellett tul gyakran hasznalnom (bar meg mindig tobbet mint a nonblock-ot).

Nem emlékszem már a problémára, valami soksocketos progi volt, és úgy emlékszem, hogy nem standard read/write volt, hanem valami egyéb esemény, talán az accept() volt képes olyat csinálni, hogy a select() szerint okés volt, a valóságban meg néha nem. Csak arra emlékszem, hogy két napig kerestük, miért áll meg néha a program...
Igazából az O_NONBLOCK használata kb. ingyen van, egy extra open() paraméter / fcntl() hívás, plusz egy extra errno érték ellenőrzés, cserébe garantáltan nem fordulhat elő, hogy megáll a progi.

A sigio-val sose barátkoztam meg. :)

en is talalkoztam ilyen esettel linux alatt:
- sok tcp-socket
- select szerint mehet a read
- a read megis blokkol
szep kis debug volt mire rajottem

azota se tudom hogy mi volt ez

Igen. A select() celja nem az, hogy nonblocking I/O-t tudj hasznalni, es teljesen termeszetes az, hogy a select() visszater hogy olvashatsz, de a kovetkezo read() blokkolni fog. Ez, by design igy van. Ha non-blocking I/O-t akarsz, akkor hasznalj azt.

[szerk] Termeszetesen en is beszoptam a mantrat a select ugyeben (google alapu tanulas rulez) :)

man select:


DESCRIPTION
select() and pselect() allow a program to monitor multiple file descriptors, waiting until one or more of the file
descriptors become "ready" for some class of I/O operation (e.g., input possible). A file descriptor is considered
ready if it is possible to perform the corresponding I/O operation (e.g., read(2)) without blocking.


BUGS
Under Linux, select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent
read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is
discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it
may be safer to use O_NONBLOCK on sockets that should not block.

nekem ezalapjan ugytunik hogy ennek nem igy kene mukodnie by design

Ha vetted volna a faradtsagot es vegig elolvasod a szalat amit linkeltem, akkor kiderult volna szamodra hogy de, megis. Ertsd: nem bug, feature; akarmilyen szabvany ellenere.

vegigolvastam
es nem gyozott meg
gondolom a rossz lehetosegek kozul ezt valasztottak legkevesbe rossznak
de ettol meg nem lesz feature

(ha mar ilyen hangnemben irsz akkor megenkedek magamnak egy szemelyes megjegyzest: attol hogy a neten olvasod meg nem biztos hogy igaz)

data has arrived but upon examination has wrong checksum and is discarded
hat elegge meredek dolgok vannak az eletben, az biztos.

mondjuk probaltam en is mestersegesen ilyeneket generalni (tcp/ip), egyelore nem sikerult. valszeg egy modell interface azert kell hozza, letezo fizikai eszkozokkel ez inkabb random es azonbelul is kvazi szokoevbenegyszer elofordulo jelenseg lehet...

Ha jól tudom, akkor blocking módban a read() addig olvas, amíg a kért mennyiségű adat meg nem jön vagy hiba nem következik be. Ergo ha a select() szól hogy van adat és ezért te olvasni akarsz pl. 10 byte-ot, de csak 3 jön, akkor blocking mód esetén hacsak hiba nem történt, a read() megáll és várja a további 7 byte-ot.
A select() csak annyit mond meg, hogy van adat - azt nem mondja meg, mennyi. Ezért kell a NONBLOCK mód, mert akkor ha kérsz 8k-t és csak 3 byte jön, akkor a read() vissza fog jönni 3 byte-tal. Persze azt illik ellenőrizni, hogy mennyi adat jött és ha neked mindenképp több kell, akkor pufferelsz és újra olvasol.
Persze ezt megkerülheted azzal, hogy minden esetben 1 byte-ot akarsz olvasni - annyi tuti lesz, ha szólt a select(). Ezzel csak az a baj, hogy nagyon nem hatékony módja a beolvasásnak és a pufferelést hacsak nem byte-oként kell feldolgoznod az inputot, ugyanúgy nem úszod meg, mintha NONBLOCK módban a kértnél kevesebb adat jönne.

+ néhány jótanács:

- az nem túl sikeres stratégia, hogy a read() visszatérési értékét meg sem nézzük, mert "biztos 1 karaktert olvasott pontosan"

- ha valaki errno-t ad vissza, nem túl praktikus a hibaüzenetbe ezt az értéket számmal beleírni; vagy nem írjuk ki egyáltalán ("hiba történt"), vagy ha már kiírjuk a hibát, akkor a számszerű érték mellé, vagy inkább helyette a szöveges verzióját (is) kiírjuk (man strerror, esetleg man printf-nél a %m definíciója), mert az ember által olvasható valami (mindig imádtam a windowsban az "error 000000042" c. hibaüzeneteket, hogy törne le a keze annak, aki kitalálta)

- "void *cmd; if (cmd == 'r') {" ez nem szerencsés kódolási gyakorlat; az 'r' típusa char, es ezért nem kéne pointerekkel összehasonlítani; ha tudjuk, hogy az a void * igazából egy intet vagy egy chart tartalmaz, akkor kéne oda egy cast is, pl. 'r' == (int)cmd, de igazán szép ez úgy lenne, ha a rögtön az elején át is raknánk egy megfelelő változóba az értéket, és utána ezt nézegetnénk

- a pthread_cond_* egyáltalán nem úgy működik, ahogy gondoltad; a mutexet a pthread_cond_* hívása előtt meg kell fogni:
The pthread_cond_timedwait() and pthread_cond_wait() functions shall
block on a condition variable. They shall be called with mutex locked
by the calling thread or undefined behavior results.

A hibauzenetet, foleg Open Source programnal inkabb a hibakoddal egyutt, es ne helyette adjuk meg. Neked mint fo supporternek melyik az egyertelmubb? Egy bolgar vagy mandaring kinai hibauzenet vs egy hibakod?

Egyetértek a problémafelvetéseddel, igaz, én ezt más úton oldom meg (a hibaüzenetek, logok nyelve az angol; az az interfész, ahol lokalizálásnak helye van, alapvetően nem alkalmas debug/log/státuszüzenetek dekódolására).

Ha az embernek nincs ráhatása, milyen locale alatt használják (pl. tipikus open-source community sw), ott abszolút jogos, amit mondasz.

Az uzenetek persze maskent lesznek megoldva, ezek csak gyorsan bekerultek, hogy lassam mivan...
Egyebkent a progi kizarolag nekem lesz, cel hardwarehez :)

akkor annál inkább olyat szeretnél látni, hogy "No such file or directory", minthogy "2" :)

pthread_t thread[2];
...
for(t = 0; t < 2; t++) {
    rc = pthread_create(&thread[t+1], &attr, SensorComm, cmd[t]);

Biztos t+1 ? A beolvasási problémára pedig szintén a select-et tudom ajánlani.

t+1 jo is meg felesleges is igazabol. Meg a kod egy korabbi valtozatabol maradt fent. Azota a join-t is egy for vegzi, ami szinten 0-tol szamol, igy valoban eleg siman a t :)
Selectet most nezegetem, meg nemigazan vagom, de google a baratom, remelem :)

Mondjuk az is jo kerdes, hogy egyaltalan miert fagy be a read() ? O.o

Ez egy nagyon jó kérdés, de akkor azt is meg kéne mondani, hogy mi az hogy befagy. :)

Azt, hogy van amikor megall a program a read() fuggvenynel.
Van amikor lefut 40-50x egyhuzamban, de van hogy a 3. futasnal befagy, vagy csak a 20.-nal. teljesen random. FOgalmam sincs mitol lehet. Erre akartam a fenti megoldast alkalmazni.

Azt, hogy van amikor megall a program a read() fuggvenynel.
mondjuk mert nincs adat? :)

a read() fv az alapertelmezesben addig va'r ameddig 0-nal tobb (azaz legalabb 1) byte-ot be tud olvasni (vagyis atadni a hivo'nak). ezt hivjak blokking-modnak. a select() meg tarsai (poll(), stb) arra jok, hogy a read() fuggveny hivasa nelkul _es_ nonblokking-modba valo atkapcsolas nelkul meg tudd mondani, hogy van-e beolvashato' adat azaz (ami ezzel egyenerteku"), hogy a read() blokkolna-e vagy sem.

Az a gaz, hogy megall akkor is ha van bejovo adat a porton. Teszteltem. Ez konkretan befagy.

Az a gaz, hogy megall akkor is ha van bejovo adat a porton. Teszteltem. Ez konkretan befagy.
o"o"o"... ez biztos? azaz:
- biztos hogy van adat ill. szabalyos rs232-es adat jon?
- ha ebben nem vagy biztos, akkor probaltad monitorozni az adatforgalmat? az rs232-nek megvan ez az elonye hogy az rx-et egyszerre tobben is tudjak olvasni. csapold meg es dugd ra' (a fo"lddel egyu"tt) egy masik rs232-es portra, ahol egy fuggetlen program csak es kizarolag azt csinalja hogy ezt a masik portot olvassa es amit kiolvas azt, mondjuk egy timestamppal egyutt, hexa'ban kiirja a kepernyore.
- ha "megall" akkor biztos a read() all le, nem valami ma's? busywait mashol, ezek a mutex-ek amiket hasznalsz? vagy barmi?
- ha a hardver a gyanus, vagy akar mint egy fuggetlen alternativa: probald meg _ke't_ programrol vezerelni, bar nem tudom hogy linuxon egy ttyS*-ot megnyithat-e ketszer az ember ugyhogy 1x csak wronly modon, 1x meg rdonly. de ha ez megy, akkor ki lehet probalni ezt is, hatha igy konnyebben kiderul hogy mi a szuk keresztmetszet.
- a hardver konkret protokolja egyebkent micsoda? azalapjan lehet hogy itt konnyebben tud vki peldat adni hogy egy select()-alapu egyszeru implementaciot hogyan lehet felepiteni. tobbszalu program ilyen problemara egyebkent is kicsit agyu-vereb eset.

Nos, hat, gyorsteszkent elvegeztem egy egyszeru linux tty olvasast:
cat < /dev/tty/1

Majd a progimmal kuldtem az adatot, amire a szerkentyu (egyebkent egy ultrahangos tavolsagmero szenzor) kuldi a valasz adatot.
Jottek is a karakterek rendesen, majd ugy 100 utan semmi. A progi kuldte az adatokat, de a szenzor LED-je mar nem villogot ami az adatok fogadasat hivatott jelezni. Aztan amikor a cat -olos parancsot le CTR+C-ztem es ismet elinditottam a dolgot, akkor ismet jo volt, szinten egy darabig. Tehat olyan mintha a port fagyna be.
Egyebkent erdekes dolog, bar ez hibat nem okozott. Neha adatkent a 'PuTTY' jelenik meg. Na most az igaz, hogy a gep amin a progi fut, oda Puttyval vagyok bejelentkezve, de neten at. Hogy a fenebe kerulhet akkor oda a Putty kifejezes, portrol bejovo adatkent? O.o

cat < /dev/tty/1
mmint /dev/ttyS1? gondolom. egyebkent ez a nyers sorosportozas nem annyira nyero", ill elotte azert egy stty vagy valami azert atment rajta? ill hamar cat, akkor inkabb egy hexdump-ba bele, hatha az jobb.

Aztan amikor a cat -olos parancsot le CTR+C-ztem es ismet elinditottam a dolgot, akkor ismet jo volt, szinten egy darabig.
marmint hogy volt olyan eset amikor egyszerre ke't program is lo'gott a soros porton? akkor lasd feljebb, ebbol kavarodasok lehetnek. ha _teljesen_biztosan_ akarsz soros adatforgalmat monitorozni, amiben semmi (beleertve az oprendszer hulyesegeit) sem avatkozik be; akkor kell egy analizator hardver. a legegyszerubb ebbol a passziv, rx megcsapola'sa. ez egy ilyen jatek, sajnos. a tobbi az mind-mind felrevezeto", ket program egyszerre pedig hatvanyozottan.

Majd a progimmal kuldtem az adatot, amire a szerkentyu (egyebkent egy ultrahangos tavolsagmero szenzor) kuldi a valasz adatot.
ha jol ertem, akkor ez egy master-slave rendszeru" valami? kuldesz vmit ("me'rje'l"), majd jon adat ("ezt me'rtem: ..."). azaz 1/ ku"tyu" nem kuld random indokolatlan adatot es 2/ ha kuldesz neki valamit akkor arra biztos definit es behatarolhato valasz jon?

Neha adatkent a 'PuTTY' jelenik meg.
hat ez elegge randomnak hat ;) lehet hogy itt van mas hiba is (felrecimzes, nullpointerezes, malloc/free, ...)

a) abban miért vagy ennyire biztos, hogy van mit olvasnia?

b) ha a read() nem tér vissza sose, azt hogyan képzelted volna a timeoutoddal megoldani? mivel vennéd rá azt a threadet, hogy elengedje a soros portot?

"a select() meg tarsai (poll(), stb) arra jok, hogy a read() fuggveny hivasa nelkul _es_ nonblokking-modba valo atkapcsolas nelkul meg tudd mondani, hogy van-e beolvashato' adat azaz (ami ezzel egyenerteku"), hogy a read() blokkolna-e vagy sem."

Nope.

Megiscsak a pthread-et alkalmaznam, bar mar sokkal egyszerubben.
Egy szal olvas, ha 5 sec-en bellul nem fut le a fuggveny, akkor timeoutol. Na most ez nagyon jol mukodik is, de engem aggaszt valami! Kiprobaltam ugy, hogy en akasztom be a kulon szalon futo fuggvenyemet ( sleep(20) - ami ugye tobb mint 5 sec) lett is timeout belole es indult a kovetkezo probalkozas. Azonban a 20 sec elteltevel lefutott az a fuggveny, mert ugye csak kesleltetes volt nem vegtelensegig megakadas.
A kerdes: ha nekem igy beragad mondjuk 1000+ szal, akkor azzal nem tellik meg a memoria elobb-utobb?
Valamint, hogy lehetne a timeoutolt szalat kinyirni, hogy ne is probaljon tovabb futni?
Nem igazan talaltam erre destroly fuggvenyt a doksikban :S

Mindig ez van, ha kerdezek, tuti 5 percre ra megtalalom a valaszt:
pthread_cancel()
:)

Szerintem ne akarjál olyan thread modellt használni, amiben futó, tevékenységet végző threadet "akaratán kívül", kívülről próbálsz lelőni. Ezzel még sok-sok szopásod lesz.
A korrekt thread kezelés úgy néz ki, hogy a thread önszántából nyom exitet, amikor ez neki alkalmas. Nagyon csúnya konzisztencia problémáid lesznek, ha pl. egy mutex-szal védett szakaszban nyomod neki a halált!

+1

ill altalaban erre a probemara a sima klasszikus i/o hivasok kellene'nek, azoknak a timeout-kezele'sei e's nem igazan thread-ek.

Ha tudnal iranyt mutatni afele, hogy mivel tudnam szebben megoldani a problemat, azert halas lennek:)
Milyen fuggveny, fuggveny parosok, esetleg egy oldal ahol van pelda erre. Google nem akar a baratom lenni :S
Azert megegyszer a problemam pontosan: Serial portrol olvasnek adatot, read fuggvennyel, ami ismeretlen okbol "befagy" megall a program. Van hogy 100. futasnal, van hogy 10.-nel, teljesen random. Azt szeretnem elerni, hogy ezen tovabblepjen a program es probalkozzon ujra.
Az en megoldasom mar majdnem jol mukodik, de nem tokeletes. Most, hogy mondjatok, hogy nem is elegans, plane nem jo :)

itten feljebb ezt-azt kerdezgettem, hogy pontosan milyen fajta is ez a protokoll. ha irni is es olvasni is kell, akkor ez szamit a prog megtervezeseben, egy kicsit. a.

A kutyu egy tavolsag mero szenzor, ami parancsra lemeri az elotte levo tavolsagot. A parancs mindossze ennyi : "VA"
Eutan o visszadob egy szamot 1 es 255 kozott. Minnel nagyobb a szam, annal tavolabb van a szenzor elott vaalami.
Sajnos neha teveszt, inkabb csak tavoli targyaknal, de teveszt. Ezert kis ido kihagyassal kernek tole 10 eredmenyt, majd ezekbol az egymashoz leginkabb kozelallot veszem biztos erteknek.
A gond ugye az, hogy tobb kiolvasas utan a read() fuggvenynel megall a program futasa. Ha nyomok egy ctrl-c -t ra es ujra elinditom, akkor par olvasasig megint oke.

aha, tehat sima master-slave. es mindig valaszol a "VA" parancsra?

Eutan o visszadob egy szamot 1 es 255 kozott.
marmint egy darab byte-ot, vagy egy ascii szamjegyekbol allo 1-3 karaketer hosszu sorozatot? (+ egy zaro karakter, ami micsoda? egy ujsor, egy ascii 0, vagy mi?)

Noh, bemasolom a teljes how-to uset rola:

Read Analog Inputs.

Example: "VA VB VC VD "
VA, VB, VC, and VD read the value on the input as analog. It returns a single byte with the 8-bit (binary) value for the voltage on the pin.
When the ABCD inputs are used as analog inputs the internal pullup is disabled. The inputs are digitally filtered to reduce the effect of noise. The filtered values will settle to their final values within 8mS of a change. A return value of 0 represents 0vdc. A return value of 255 represents +4.98vdc. To convert the return value to a voltage, multiply by 5/256.
At power up the ABCD inputs are configured for digital input with pullup. The first time a V* command is used, the pin will be converted to analog without pullup. The result of this first read will not return valid data.
Read Analog Input Example: "VA VB "
This example will return 2 bytes with the analog values of A and B. For example is the voltage on Pin A is 2vdc and Pin B is 3.5vdc, the return value will be the bytes 102 (binary) and 179 (binary).

Azt nem irja, hogy o mivel zarja a sort, de abbol kiindulva, hogy nekem -el kell, ugygondolom, hogy o is azzal.

akkor vmi ilyesmi:

...
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/time.h>
...

fd_set set;
struct timeval tv;
unsigned char buff[4];
int  adc;

...
fd=open("/dev/ttyS1",O_RDWR);
... /* termios: baud rate stb beallitasa */
tcflush(fd,TCIFLUSH);
tcflush(fd,TCOFLUSH); /* bufferek torlese, csak a biztonsag kedveert *

write(fd,"VA",2);
FD_ZERO(&set);
FD_SET(fd,&set);
tv.tv_sec =5;
tv.tv_usec=0;
n=select(fd+1,&set,NULL,NULL,&tv);
if ( FD_ISSET(fd,&set) )
 {   read(fd,buff,1);
     adc=(int)buff[0];
 }
else
 {   /* timeout */
 }

elvileg kb ennyi. gyakorlatban persze kerdes hogy 1/ mennyi timeout-ot adsz (5 sec vagy ilyesmi egy ilyen hardverre szerintem nagyon sok; ha jon valasz a "VA" parancsra, akkor gondolom az kb. par millisec utan megerkezik, ha nem jon, akkor viszont nagyon nem) 2/ mit csinalsz ha tenyleg timeout van? ujra elkuldod a parancsot?

a lenyeg ebben itt fent, hogy a select() az mindenkeppen leall a tv strukturaban megadott idointervallumban. ha van adat, akkor n==1 lesz a visszateresi ertek es az FD_ISSET() makro igaz lesz, ha nincs, akkor n==0 lesz a visszateresi ertek es az FD_ISSET() makro hamis lesz. mindkettot felhasznalhatod timeout tesztelesre, en inkabb a makrokat szoktam (ugye ha a &set-ben tobb fd is benne van, akkor... es altalaban tobb van).

kb igy. a.

Ohh, nagyon koszi, eleg jol mukodik most mar!
Egyebkent az olvasas egy ciklusban fut tizszer. Ennyi mar eleg a pontos adat megalapitasahoz. Neha dob fura erteket, igy ezeket nem veszem figyelembe...
Most teszteles celjabol vegtelen ciklusba tettem, 1 sec varakozassal a kiolvasasokat. Furcsa modon egy ido utan 0 ertekek jottek. Betettem a buffer uritest akkorra is ha timeout van, hogy tiszta lappal keruljon ujra ciklusba. 200+ lefutas utan is jonak tunik most :)
Koszi a helpet, remelem igy okes lesz es folytathatom a project erre epulo reszet.
Persze ha lesz kedvem, turelmem, akkor meg foglalkozok ezzel a beakadas uggyel, mert ez megsem termeszetes igy.

igen, ezt a timeout-ot erdemes jol beloni, szerintem erre a hw-re tenyleg valami tort-masodperc kell. ki kell kiserletezni, ill persze a specifikacio alapjan is. pl ha 9600 baudon megy a kommunikacio akkor egy byte lekuldese kb pont 1 ms korul van, igy ekkor gondolom egy 10ms-es timeout (tv.tv_sec=0, tv.tv_usec=10*1000;) teljesen jo. vagy persze meg is lehet me'rni: ha nincs timeout, akkor select() ugye 1-gyel te'r vissza, viszont a &tv strukturat is frissiti, abban igy a hatralevo" ido"t talalod meg. azaz igy meg lehet nezni es/vagy ki lehet me'rni egeszen pontosan hogy a hw mennyi ido alatt valaszol.

illetve, me'g a tcdrain(fd); fv-t is erdemes megnezni, hatha a write() utan erdemes va'ratni a programot addig ameddig teljesen biztos hogy nem jon adat. ez is hw-fuggo persze, mmint hogy erdemes-e ilyet csinalni.

ja, erdekes ertekek johetnek, erdemes megnezni a kabelt is. ne legyen tul hosszu, legyen jo minosegu (2 e'r + arnyekon a jelfo"ld), stb.

Nem olvastam teljesen végig a szálat, de nem az a probléma, hogy a kimeneti parancsnak nem adtál flusht? A példaprogramban sincs.

A write általában (nem tudom igaz-e ez soros portra) úgy működik, hogy ameddig nem flusholsz, addig határozatlan időre egy határozatlan méretű bufferben határozottan csücsülnek az adatok. Ennek teljesítmény okai vannak, de mikor 1-2 bájtról van szó, könnyű elfelejteni, mert ki gondol ilyenkor teljesítményre.

igen, a soros port kicsit ma's mint egy mezei file. jo kerdes, hogy ott milyen timeout van erre az egesz muveletre. socket-eknel (inet/stream/tcp) van valami ilyesmi hogyha keves a kiirt adat, akkor valami mas flag-ezessel (psh) kuldi ki az adatot, mert ott me'g a fogado oldalon is gond lehet az altalad is felvetett bufferelessel.

soros portnal egyebkent a tcdrain() a nyero", ezt is irtam feljebb. de lehet hogy egy fsync() + tcdrain() ami aztan tenyleg mindent megold ;]

a.