domenico.mosca Inserito: 5 dicembre 2010 Segnala Inserito: 5 dicembre 2010 Ciao a tuttisto cercando una centralina che sia in grado di pilotare 12 relè e sia in grado di leggere lo stato di 12 sensori.Questa centralina dovrebbe essere collegabile via USB o RS232 o RS485 ed essere compatibile con linux.Meglio ancora se sono presenti delle API che ne generalizzano e semplificano la programmazione.Potreste segnalarmi dei modelli o delle vostre esperienze?Praticamente dovrò controllare una macchina con un pc, utilizzando un software di controllo.Grazie a tutti in anticipo!
NoNickName Inserita: 5 dicembre 2010 Segnala Inserita: 5 dicembre 2010 http://www.precma.it/ELEXOL_USBIO24.htmhttp://www.precma.it/ELEXOL_AccessoryBoards.htm
max81 Inserita: 5 dicembre 2010 Segnala Inserita: 5 dicembre 2010 Ciao, ecco alcune aziende che trattano quello che cerchi.NIAdvantechSist. elettronici avanzatiTra questi ho utilizzato solo le schede della National Instruments con Labview.
domenico.mosca Inserita: 5 dicembre 2010 Autore Segnala Inserita: 5 dicembre 2010 grazie a tutti!era proprio quello che cercavo!Buona giornata
domenico.mosca Inserita: 8 gennaio 2011 Autore Segnala Inserita: 8 gennaio 2011 Ciao a tuttinel rigraziarvi nuovamente per i link interessanti che mi avete fornito a suo tempo, vorrei porvi un quesito:ho preso una scheda USBIO24, a cui ho collegato2 I/O Combo Board1 I/O Relay BoardIl tutto lo utilizzo per gestire una macchina spaccalegna con nastro trasportatore, blocco tronco, taglio legname, spaccalegna, etc etc, tutti i pistoni oleodinamici sono collegati a elettrovalvole che piloto con relè gestiti a loro volta dalle schede montate.Utilizzo anche dei fine-corsa che ho collegato ai sensori delle Combo Board.Il software è scritto in c++ in ambiente linux, ed è interfacciato ad un joystick per il controllo manuale + una procedura che fa il lavoro automatico (Avanza/Blocca/Taglia/Spacca/Sblocca/->Avanza.....)Il problema che ho sta proprio nei sensori, in quanto ho dei problemi di lettura della scheda, a volte mi ritorna dei valori errati e mi pare che non si riesca a gestire bene il sincronismo di lettura/scrittura.La scheda funziona in questo modo:/*scrivo il byte value (che deve essere un'intero) sulla porta A*/stream << 'A'<<(char)value;/*leggo il valore della porta A*/stream << 'a'/*leggo il valore della porta B*/stream << 'b'/*leggo il valore della porta B*/stream << 'c'Periodicamente, leggo i valori di A,B,C in un ciclo ed è qui che ho il problema nel senso che spesso ottengo dei valori errati.Utilizzo dei semafori per sincronizzare letture / scritture ma non mi pare che i risultati ottenuti siano affidabili.Posto un pò del codice scritto... solo per farvi capire meglio:/* * letttura valori */ void IOHandler::ReadProcess() { fstream in(this->device.c_str(), ios_base::in); char c; sem_post (&this->mutex); while (in.good()) { sem_wait (&this->mutex); c = in.get(); if(in.good()){ this->ReadPortValues[this->PortNumber2Read] = int(c); sem_post (&this->mutex); } } in.close(); } /* * scrittura/interrogazione valori */ while(true){ ... this->PortNumber2Read = 0; out << 'A' << char(this->WritePortValues[0]); out.flush(); out << 'a'; out.flush(); sem_post (&this->mutex); sem_wait (&this->mutex); usleep(this->SleepingInterval); this->PortNumber2Read=1; out << 'B' << char(this->WritePortValues[1]); out.flush(); out << 'b'; out.flush(); sem_post (&this->mutex); sem_wait (&this->mutex); usleep(this->SleepingInterval); this->PortNumber2Read=2; out << 'C' << char(this->WritePortValues[2]); out.flush(); out << 'c'; out.flush(); sem_post (&this->mutex); sem_wait (&this->mutex); usleep(this->SleepingInterval); ... } Forse qualcuno di voi ha già avuto esperienze con queste schede e può darmi un suo parere? Questo modo di operare è corretto? PS, ho anche provato a fare un solo thread che legge/scrive contemporaneamente, ma non vi è modo di farlo funzionare... forse questo semplificherebbe il tutto ma con il codice seguente leggo sempre e solo 0 o -1 dalla scheda: Idee? int main(int argc, char *argv[]) { fstream out("/dev/ttyUSB0", ios_base::out|ios_base::in|ios_base::binary); /* configuro le porte */ //4 in - 4 out out << "!A" << char(15); //8 out out << "!B" << char(0); //4 in - 4 out out << "!C" << char(15); char read; int value; while(true){ // spengo i rele su A out << 'A' << (char) 0; out.flush(); // attendo 1 secondo sleep(1) // accendo il rele sulla porta 5 out << 'A' << (char) 32; out.flush(); // leggo il valore della porta 5 out << 'a' out.flush(); out >> read; value=(int)read; cout << "valore di A="<<value<<endl; } out.close(); return 0; }
Livio Orsini Inserita: 8 gennaio 2011 Segnala Inserita: 8 gennaio 2011 Il problema principale sta nello SO del PC. SO da ufficio sono inadatti per controlli automatici anche semplici.I PLC basati su PC e I/O industriali, almeno quelli affidabili, hanno un loro SO vero real time.Il rimedio che puoi tentare è acquisire gli ingressi e aggiornare le uscite a tempi fissi.Cerco di chiarire banalizzando.TI fai un timer che genera un interrupt. Su questo interrupt aggiorni le uscite fisiche prelevandone los tato da una tabella immagine, similmente aggiorni la tabella immagine degli ingressi copiandovi lo stato degli ingressi fisici.Dopo di che elabori il programma usando le tabelle immagini.Se noti il tuo sistema dovrebbe la vorare come lavorano i PLC e non è casuale.
domenico.mosca Inserita: 8 gennaio 2011 Autore Segnala Inserita: 8 gennaio 2011 Ciao, ti ringrazio per la risposta.Il problema di fondo, non è come gestire lato software il programma, ma è come gestire la comunicazione con la scheda!Nel mio caso, quello che non riesco a capire è se la comunicazione deve essere gestita con 2 processi differenti sincronizzati (uno legge, ed uno scrive) oppure se c'è modo con un'unico processo di scrivere e leggere.Poi, che a livello di IO un PLC embedded sia più affidabile in termini di real time è fuori dubbio, è anche molto meno versatile però: nel mio caso ora ho un file XML che mi permette in modo molto veloce di customizzare i pulsanti del joystick, le uscite dei rele, le regole degli ingressi, etc etc. senza cambiare una riga di codice e senza dover ricompilare nulla.Quello che vorrei capire io però, è possibile comunicare con queste schede utilizzando un'unico processo, ed eventualmente in che modo!Grazie, ciao.
del_user_56966 Inserita: 8 gennaio 2011 Segnala Inserita: 8 gennaio 2011 Quello che dice Livio è esatto, la versatilità di un programma di automazione non sta nella grafica o nella semplicità d'usosempre che un programma come quello sopra si possa definire per tutti il più semplice... semmai è nelle prestazioni che l'Harware permette di gestire, in tutta la tua esposizione manca un dato importante che è caratteristicodi tutte le macchine, il tempo di scan degli I/O se questo non è corretto tutto il tuo programma soprastante, Linux compreso non ti sono d'aiuto...Poi, che a livello di IO un PLC embedded sia più affidabile in termini di real time è fuori dubbio, è anche molto meno versatile però: nel mio caso ora ho un file XML che mi permette in modo molto veloce di customizzare i pulsanti del joystick, le uscite dei rele, le regole degli ingressi, etc etc. senza cambiare una riga di codice e senza dover ricompilare nulla.In realtà tra poco non sarà più cosi visto che sta per uscire un sistema Open Source basato su Linux che gestisce direttamente gli I/O direttamente tramite le librerie fornite col kernal e in pratica è come se tu pilotassi la scheda audio...lo si può programmare sia tramite C/C++, Python, Java, un Visual Basic per linux...
Livio Orsini Inserita: 8 gennaio 2011 Segnala Inserita: 8 gennaio 2011 (modificato) Poi, che a livello di IO un PLC embedded sia più affidabile in termini di real time è fuori dubbio,A prescindere dall'affidabilità, che comunque è un problema reale, c'è il problema della fattibilità.Se i tempi di reazione del campo sono...ere geologiche, puoi usare il tuo Hw così come lo stai usando. Però una quelsiasi macchina, anche se lenta, risponde almeno in termini di decimi di secondo. In questo caso un SO da ufficio non può essere adatto.E' l'eterno problema di chi sa programmare un PC, crede che sia sempre una questione di programma applicativo. Invece spesso è una questione di Sw di base. Se non puoi controllare direttamente il tuo Hw, devi avere qaulche cosa che lo fa per te in modo sicuro e affidabile. Ecco perchè, per queste applicazioni, il DOS era molto più efficace: con questo SO hai direttaemente il controllo della periferia del sistema.Comunque il tuo problema lo può risolvere solo il fornitore dello Hw, fornendoti drivers adatti allo scopo e compatibili con lo SO che usi. Modificato: 8 gennaio 2011 da Livio Orsini
domenico.mosca Inserita: 8 gennaio 2011 Autore Segnala Inserita: 8 gennaio 2011 (modificato) Scusatemi se sono poco preciso, mi sto approcciando ad un mondo che per me è relativamente nuovo, quindi chiedo a voi...(spero di essere nella sezione corretta del forum, a questo punto)La scheda USBIO24 ha una frequenza di 4 Mhz e io vorrei fare una lettura/scrittura ogni decimo di secondo.A prescindere dal fatto che ci sono configurazioni del kernel linux che intervengono sullo scheduler e sulla sua frequenza per rendere lo scheduling dei processi più adatto alle necessità RT, ho capito che il PLC è la soluzione professionalmente ideale per questo tipo di ambienti, ma nel mio caso per vari motivi sto utilizzando un PC.Non escludo di montare un PLC più avanti...ma il punto non è questo, il mio problema è semplicemente nel capire come fare ad utilizzare correttamente questa scheda, c'è qualcuno che magari ci ha già lavorato, (forse chi mel'ha segnalata ?) e può fornirmi dei feedback?[edit]a scanso di equivocii malfunzionamenti della scheda adesso sono dovuti sicuramente ad un'errato interfacciamento, a prescindere dall'HW che ci sta sotto e dal SO che lo gestisce, parliamo di risposte dopo 5/6 secondi o addirittura di errate letture, quindi c'è sicuramente qualcosa che non quadra...Grazie Modificato: 8 gennaio 2011 da domenico.mosca
Livio Orsini Inserita: 8 gennaio 2011 Segnala Inserita: 8 gennaio 2011 Questa scheda non l'ho mai usata (ho usato qualche volta NI, ma queste hanno vere caratteristiche RT Hw&Sw); ho dato una veloce lettura delle specifiche. Spero tu abbia usato le DLL previste per l'ambiente Linux.Se, come dici, puoi configurare Linux similmente all'antenato da cui ha orgine (UNIX) per schedurlare meglio i processi RT fallo!Come ti ho scritto nel primo post devi leggere e scrivere le uscite fisiche in un momento ben preciso e tutte contemporaneamente. Il programma lo elabori sull'immagine degli ingressi letti e, similmente, aggiorni le immagini delle uscite.Questo modo di procedere è comune a tutti i sistemi di automazione. O è trasparente per l'utilizzatore, come nel caso dei PLC, o viene schedulato nello RTOS, oppure si usa qaulche altro marchingegno.Fanno eccezione i processi legati ad eventi particolari, generalmente gestiti ad interruzioni Hw.Il tuo vero problema è capire in quanto tempo riesci a passare dal tuo applicativo all'uscita/ingresso fisico/a, in altri termini come interagisce il tuo applicativo con i vari livelli dello SO.
del_user_56966 Inserita: 8 gennaio 2011 Segnala Inserita: 8 gennaio 2011 parliamo di risposte dopo 5/6 secondiAz... altro che lento è un eternità!... ma il problema potrebbe essere tutto di carattere hardware....come tutto di carattere software!ma anche una miscela dei due, in questo caso serve un bel debug approfondito, devi studiarti la parte hardware e vedere se il software che scrivi è allineato a quanto richiesto... insomma più che uno sviluppatore qui servirebbe un progettista...
AVC_Veronica Inserita: 9 gennaio 2011 Segnala Inserita: 9 gennaio 2011 cedo che la tua scheda venga vista dal sistema come una "seriale" ,quindi con dei tempi minimi di r/W verso O:S sotto ai cuali non puoi scendere , se ottieni tempi abissali e dati errati sicuramente la causa è da ricercarsi nel software (attuazione e ricezione alias asincronismo).Se il tu scopo era creare un'interfaccia PC based su linux , forse la strada giusta era un PLC con porta mdbus attraverso la quale passavi i comandi e leggevi i dati con tempi certi (20/40ms se ben "impacchettati")
domenico.mosca Inserita: 9 gennaio 2011 Autore Segnala Inserita: 9 gennaio 2011 Ho contattato la ditta produttrice, vi farò sapere.PS: le dll per linux non esistono ma è un'altro discorso....Ciao e grazie
Livio Orsini Inserita: 9 gennaio 2011 Segnala Inserita: 9 gennaio 2011 (modificato) PS: le dll per linux non esistono ma è un'altro discorso....meno di 30" usando google e, miracolo, guarda qua:Precmada cui si arriva qua, clickando su Linux Driver.Linux_DriverOvviamente quando ho scritto, per abitudine, Linux DLL non ho usato un termine corretto, ma lo scopo era evidente. Modificato: 9 gennaio 2011 da Livio Orsini
NoNickName Inserita: 9 gennaio 2011 Segnala Inserita: 9 gennaio 2011 Visto che sono stato io a suggerire la scheda nel secondo messaggio, che ho anche usato con successo (programmandola in BASIC!) senza tutti questi problemi, contatta pure la Precma (che conosco bene) e esponi il problema. Vedrai che te lo risolvono.
domenico.mosca Inserita: 9 gennaio 2011 Autore Segnala Inserita: 9 gennaio 2011 [at]Livio OrsiniGrazie Livio, il link alla precma lo trovi nella seconda risposta di questa discussione...comunque... i driver che uso sono quelli corretti come da documentazione e come da manuale, ma come detto più volte il problema è nel come interfacciarsi alla seriale lato software con 3 schedeSe implemento 2 processi uno che legge ed uno che scrive ho letture errate... se invece faccio un'unico processo che legge e scrive non ho proprio risposte.[at]NoNickNameGrazie NoNickName, ho già contattato la Precma qualche giorno fa ma non mi sono stati molto d'aiuto...hanno ipotizzato dei cali di tensione sugli optoisolatori ma lo escludo, ho fatto più prove sia in officina che il laboratorio, con alimentazioni a 12VDC sia da batteria che da alimentatore e il comportamento è sempre lo stesso, sbagliato.Io sono quasi certo che il problema sia nel mio programma, ed è questo (se leggete bene il mio post) che chiedevo semplicmente se qualcuno aveva già avuto esperienze pratiche con questa scheda ed in ambiente linux.Comunque, ho scritto a quelli della ELEXOL, che sono i reali produttori della scheda... e vediamo cosa mi dicono loro.Grazie, ciao.
Livio Orsini Inserita: 9 gennaio 2011 Segnala Inserita: 9 gennaio 2011 Se implemento 2 processi uno che legge ed uno che scrive ho letture errate... se invece faccio un'unico processo che legge e scrive non ho proprio risposte.Non è che scrivendo sempre le stesse cose risolvi il problema. Le linee da seguire ti son state indicate, poi fai come vuoi.
del_user_56966 Inserita: 9 gennaio 2011 Segnala Inserita: 9 gennaio 2011 hanno ipotizzato dei cali di tensione sugli optoisolatori ma lo escludobella risposta! è tutto un programma!...
NoNickName Inserita: 9 gennaio 2011 Segnala Inserita: 9 gennaio 2011 E' improbabile che ti abbiano risposto così. Conosco i titolari da anni.
domenico.mosca Inserita: 12 gennaio 2011 Autore Segnala Inserita: 12 gennaio 2011 Ciao a tutticonfermo che il problema era legato ad una errata sincronizzazione dei due thread di lettura / scrittura.Il mio errore era stato quello di usare un'unico semaforo sia per gestire i processi di scrittura che per gestire i processi di lettura e quindi ovviamente non si generavano dei lock esclusivi.Se può interessare a qualcuno posto i 2 metodi che utilizzo.void IOHandler::ReadProcess() { fstream in(this->device.c_str(), ios_base::in); char c; int CurrentPort = this->PortNumber2Read; // sblocco il processo di scrittura sem_post(&this->mutex_writer); while (in.good()) // loop while extraction from file is possible { sem_wait(&this->mutex_reader); c = in.get(); // get character from file CurrentPort = this->PortNumber2Read; if (in.good()) { this->ReadPortValues[CurrentPort] = int(c); } else { this->u->log->debug("IOHandler::ReadProcess errore di lettura"); } sem_post(&this->mutex_writer); } in.close(); } void IOHandler::WriteProcess() { this->u->log->debug("IOHandler::WriteProcess"); // attendo che il processo di lettura sia pronto sem_wait(&this->mutex_writer); fstream out(this->device.c_str(), ios_base::out); /* * configuro le schede */ //4 in - 4 out out << '!' << 'A' << char(15); out.flush(); //8 out out << '!' << 'B' << char(0); out.flush(); //4 in - 4 out out << '!' << 'C' << char(15); out.flush(); while (true) { out.flush(); /* * scrittura valori */ this->PortNumber2Read = 0; out << 'A' << char(this->WritePortValues[0]); out.flush(); out << 'a'; out.flush(); sem_post(&this->mutex_reader); sem_wait(&this->mutex_writer); this->PortNumber2Read = 1; out << 'B' << char(this->WritePortValues[1]); out.flush(); out << 'b'; out.flush(); sem_post(&this->mutex_reader); sem_wait(&this->mutex_writer); this->PortNumber2Read = 2; out << 'C' << char(this->WritePortValues[2]); out.flush(); out << 'c'; out.flush(); sem_post(&this->mutex_reader); sem_wait(&this->mutex_writer); // this->u->log->debug("IOHandler::WriteChannelValue A=%d,B=%d,C=%d",this->WritePortValues[0],this->WritePortValues[1],this->WritePortValues[2]); usleep(1000); } out.close(); }
domenico.mosca Inserita: 15 gennaio 2011 Autore Segnala Inserita: 15 gennaio 2011 ciao a tuttiper completezza, ho scoperto che impostando il comando 2>Sets unit to Mode 2 (Enables transmit on pin change)Si abilita la scheda a inviare automaticamente un comandoPORT+VALUEogni volta che un pin cambia valore.Questa funzionalità è molto comoda perchè consente di evitare il polling e togliere tutte le sincronizzazioni con i semafori, alleggerendo molto il tutto.posto il codice modificatovoid IOHandler::ReadProcess() { fstream in(this->device.c_str(), ios_base::in); char c1, c2; int value; // sblocco il processo di scrittura sem_post(&this->mutex_writer); struct timespec timeout; while (in.good()) // loop while extraction from file is possible { c1 = in.get(); // get character from file switch (c1) { case 'a': this->PortNumber2Read = 0; break; case 'b': this->PortNumber2Read = 1; break; case 'c': this->PortNumber2Read = 2; break; default: this->PortNumber2Read = -1; } if(this->PortNumber2Read>=0){ c2=in.get(); value=(int)c2; this->ReadPortValues[this->PortNumber2Read]=value; this->u->log->debug("IOHandler::ReadProcess[%c]=%d",c1,value); } } in.close(); } void IOHandler::WriteProcess() { this->u->log->debug("IOHandler::WriteProcess"); // attendo che il processo di lettura sia pronto sem_wait(&this->mutex_writer); fstream out(this->device.c_str(), ios_base::out); /* * configuro le schede */ //4 in - 4 out out << '!' << 'A' << char(15); out.flush(); //8 out out << '!' << 'B' << char(0); out.flush(); //4 in - 4 out out << '!' << 'C' << char(15); out.flush(); /* * imposto il modo di lavoro 2 in modo che ad ogni cambiamento trasmetta automaticamente il valore */ out << '2'; out.flush(); while (true) { /* * scrittura valori */ out << 'A' << char(this->WritePortValues[0]); out.flush(); usleep(5000); out << 'B' << char(this->WritePortValues[1]); out.flush(); usleep(5000); out << 'C' << char(this->WritePortValues[2]); out.flush(); usleep(5000); // this->u->log->debug("IOHandler::WriteChannelValue A=%d,B=%d,C=%d",this->WritePortValues[0],this->WritePortValues[1],this->WritePortValues[2]); } out.close(); }Ciao!
Messaggi consigliati
Crea un account o accedi per commentare
Devi essere un utente per poter lasciare un commento
Crea un account
Registrati per un nuovo account nella nostra comunità. è facile!
Registra un nuovo accountAccedi
Hai già un account? Accedi qui.
Accedi ora