Go Down

Topic: [C] Inviare dati ad Arduino (Read 2078 times) previous topic - next topic

astrobeed

Infatti "Indipendentemente dal sistema operativo" mi sembra un po' troppo ottimistico
Non è troppo ottimistico, se parliamo di Ansi C vero è così, poi se qualche compilatore si prende delle libertà, diverge dallo standard, questo è un altro paio di maniche.
Per quanto ne so io in ambiente Windows, tutte le versioni a partire da Win 98, i compilatori di Microsoft e Borland (ora Embarcadero) hanno sempre permesso di usare la seriale come file, poi ci sono anche delle librerie ottimizzate, legate ad uno specifico sistema operativo e hardware, che mettono a disposizione funzioni dedicate per l'uso della seriale.
Del TurboC per DOS ricordo poco, è una vita che non lo uso più, il modo di accesso indicato da Dally è l'equivalente di quello che si fa adesso con le MCU quando si passa direttamente per i registri delle periferiche hardware, cosa più che logica anche con i processori X86 visto che anche se sono dei crisp le varie periferiche, esterne al micro vero e proprio, sono comunque mappate sotto forma di registri.
Scientia potentia est

dally

#16
Dec 29, 2016, 02:22 pm Last Edit: Dec 29, 2016, 03:08 pm by dally
Infatti "Indipendentemente dal sistema operativo" mi sembra un po' troppo ottimistico
In teoria e' fattibile a patto che chi fornisce la toolchain si sia preso la briga di scrivere bene le varie primitive base dello standard I/O senza partire per la tangente. Costa un layer, e costa un po' piu' di fatica (per loro), pero' poi rende il codice un zichinello piu' portabile.

Notare che sistemi operativi come OS/2 Warp3 si inRazzano come dei ricci se una applicazione DOS prova a toccare le port-IO senza chiederne il permesso, ed arrivano subito le bastonate: applicazione DOS abortita.

La stessa cosa vale per WindowsNT e suoi derivati: l'OS vuole che la App faccia esplicito uso di servizi kernel appositi. Guai ad accedere direttamente all'hw, per cui questo e' un valido incentivo per scrivere bene lo standard I/O con le brave primitive di cui sopra.

Al loro interno ci sono chiamate a servizi kernel. E l'OS e' felice.

Anche linux e tutti gli UNIX hanno la stessa motivazione. Difatti se proprio uno volesse accedere direttamente all'hw (come si faceva col DOS, esempio qui sopra) dovrebbe scrivere un kernel module (un driver) apposito.

(tralascio alcuni trucchi porcherie per aggirare la cosa. Pericolossissimi)

Con Windows pero' c'e' proprio la cattiva abitudine di fare oggetti di sistema, fisicamente delle DLL caricate e linkage dinamicamente con il kernel (tipicamente nelle cartelle system e system32), E questa cosa, tipicamente usata e motivata da Borland Delphi, un dialetto del Pascal, ha causato altri fork dello standard I/O.

Nel caso specifico fino al 2004 andava di moda usare un oggetto chiamato COM, con dei metodi, get, put, setbaud, etc, il quale era facilissimo da usare: ciccavi sul bottone, il tool te lo appoggiava sul form, ci ciccavi sopra una seconda volta per definirne le proprietà, Et voilà le jeux, anzi, una volta invocato nel resto del codice si preoccupava lui di richiamare il corretto servizio kernel lato Windows.

Fantastico? Beh, faceva da passacarte, da wrapper. Bello (forse), pero' se lo usi nel tuo codice applicativo poi non e' portabile!

Difatti oggi Delphi e' RIP, se si vuole riutilizzare il vecchio codice, magari migrarlo su FreePascal + Lazarus, tocca rivederlo tutto da capo mandando in pensione COM, da rimpiazzare altro codice.

La cosa ironica e' che alcuni utenti Visual C hanno iniziato a copiare l'oggetto COM del Delphi, scrivendone un clone per il loro ambiente C. Altra cattiva abitudine che e' andata avanti per un po'.

Mi chiedo, ma ha senso riscrivere le cose n-mila volte? :D

dally

#17
Dec 29, 2016, 02:45 pm Last Edit: Dec 29, 2016, 07:39 pm by dally
cosa più che logica anche con i processori X86 visto che anche se sono dei crisp le varie periferiche, esterne al micro vero e proprio, sono comunque mappate sotto forma di registri.
Dal punto di vista architetturale pero' e' una pura questione legacy. C'era su z80, c'era su 8080, l'ha ereditato x86, e ce lo portiamo dietro come una palla al piede. Ti faccio notare che avere istruzioni I/O diverse dalla load/store nella ISA rompe non poco le scatole ai progetti superscalari, sopratutto quando tocca andare fuori ordine. Tocca aggiungere un secondo stadio con un sacco di roba lungo il datapath per l'enforce in-order execution of IO, e questa cosa aggiunge altra complexity al progetto della CPU.

Tanto di cappello agli ingegneri Intel che riescono a non farsi venire il mal di testa, o a buttarsi dalla finestra per la disperazione :D

arduinopro44

Grazie intanto per tutte le risposte.
Rispondo:
1- ho fatto i debug con il monitor seriale per verificare la parte Arduino: inviando un valore, Arduino risponde correttamente ed inoltre con Serial.println() verifico che il valore viene letto correttamente.
2- il modo per collegarmi alla seriale sembra corretto: di fatto quando invio un intero/char, Arduino riceve qualcosa e risponde. Il problema è capire cosa arriva anche perché a volte funziona ed altre no: ho provato ad inviare un char 'a' e le prime due volte funzionava (entrando nel ciclo if(input='a') e poi è entrato nell' else; sembra tutto regnato dal caso, non ha senso.

E' quindi possibile inviare dati ad Arduino tramite C?
Possibile che nessuno abbia mai utilizzato il C per comunicare con Arduino?? (Su internet di fatto non ho trovato assolutamente nulla!)

Grazie!

dally

#19
Dec 29, 2016, 02:53 pm Last Edit: Dec 29, 2016, 07:38 pm by dally
Nel tuo caso dipende cosa hai cercato. In rete e' pieno di esempi. Basta cercare bene con la giusta parola di ricerca. Di Windows moderno pero' ne so meno di zero.

Quindi ti propongo il piano B: installati una macchina virtuale sotto VirtualBox, installati linux nella macchina virtuale, collega una periferica usb-serial, mappala sulla VM; a quel punto puoi rifarti agli esempi linux in C.

SukkoPera

#20
Dec 29, 2016, 03:07 pm Last Edit: Dec 29, 2016, 03:17 pm by SukkoPera
Non è troppo ottimistico, se parliamo di Ansi C vero è così
Mi diresti in quale paragrafo dello standard ANSI C si parla di porte seriali?

Il fatto che "di solito" funzioni così può anche andarmi bene (su Unix & Co. è scontato, ma ammetto che su Windows non me lo aspettavo), ma non mi risulta sia un requisito explicito dello Standard. A mio avviso è una scelta implementativa dell'OS, a cui si può eventualmente sopperire con la runtime library del C, indipendentemente da come funziona l'hardware.

@arduinopro44: Hai verificato, come suggerito da qualcuno, a che velocità è configurata la porta su Windows?
"Code is read much more often than it is written, so plan accordingly. Design for readability."

Guida rapida a ESP8266: https://goo.gl/kzh62E

astrobeed

E' quindi possibile inviare dati ad Arduino tramite C?
Certo che è possibile dialogare con Arduino da PC tramite C, se poi lo fai considerando la seriale un file, oppure tramite librerie C, per il tuo compilatore, dedicate per la seriale questa è una tua scelta.
Di esempi di codice, per pc, ne trovi quanti ne vuoi sia generici che specifici per un determinato compilatore se rimaniamo in quelli più usati, ovvero Visual C Microsoft, Cbuilder Borland/Embarcadero, GCC per Windows.
Scientia potentia est

dally

non mi risulta sia un requisito explicito dello Standard. A mio avviso è una scelta implementativa dell'OS, a cui si può eventualmente sopperire con la runtime library del C, indipendentemente da come funziona l'hardware.
la penso anche io allo stesso modo.

astrobeed

Mi diresti in quale paragrafo dello standard ANSI C si parla di porte seriali?
In ANSI C non esistono le periferiche nel senso classico del concetto, è tutto un file sotto forma di buffer o streaming, poi è compito del compilatore, che è specifico per l'hardware su cui gira, indirizzare correttamente sul hardware i flussi dati.
Anche col caro vecchio dos se usavo il comando "type pippo.txt > com1:" il contenuto del file pippo.txt veniva inviato sulla porta com1, ovvero veniva eseguito uno streaming dati verso una specifica periferica hardware.
Scientia potentia est

dally

se ci butti un occhio, per python uso la pyserial, ha un po' di doc ed esempi.

arduinopro44

Ragazzi alla fine ho fatto altre prove: inviare un char, inviare un int, leggere un int, leggere un char, sottrarre valori, utilizzare stringhe ed array, considerare gli ascii, cambiare il nome della porta con uno equivalente, ecc...
Alla fine improvvisamente ha funzionato. Ho cercato di capire cosa fosse cambiato dal codice iniziale e non vi è alcuna differenza. Come si suol dire "Non funziona, non so perché. Funziona, non so perché" :D



SukkoPera

#26
Dec 29, 2016, 03:27 pm Last Edit: Dec 29, 2016, 03:28 pm by SukkoPera
Appunto, per cui cosa ti garantisce che la porta seriale sia accessibile come se fosse un file e non solo tramite una qualche libreria? Niente, quindi si tratta solo di una sorta di consuetudine, non di una cosa garantita dall'aderenza di un compilatore allo standard ANSI.

Peraltro propio l'esempio del DOS che hai fatto conferma questo, perché la presenza di quei due punti vuol dire che "com1" (senza i due punti) non è di per sé un file che "punta" alla seriale. Per fare questo serve aggiungere i due punti, con i quali "com1" diventa un riferimento ad un device che l'OS gestisce separamente.

@arduinopro: forse ora funziona perché in qualche modo hai cambiato la velocità della porta. Prova a riavviare :D.
"Code is read much more often than it is written, so plan accordingly. Design for readability."

Guida rapida a ESP8266: https://goo.gl/kzh62E

dally

#27
Dec 29, 2016, 03:30 pm Last Edit: Dec 29, 2016, 03:35 pm by dally
Non so come sia il tuo codice, pero' considera anche che se non chiudi gli stream alla fine del tuo programma (fclose), la cosa potrebbe bloccare la porta. In teoria se succede la fopen restituisce NULL.


astrobeed

Appunto, per cui cosa ti garantisce che la porta seriale sia accessibile come se fosse un file e non solo tramite una qualche libreria?
La seriale rientra nelle periferiche hardware supportate dal C da sempre, se non altro perché ai tempi della prima stesura del C giravano ancora computer dotati di terminali collegati tramite porta seriali e/o telescriventi.
Per esempio su tutte le mcu stdout di default è la UART1, se presente sulla mcu, questo vale per tutti i compilatori che conosco.

Un estratto dal documento che descrive lo standard ANSI C99

Code: [Select]
A stream is associated with an external file (which may be a physical device) by opening
a file, which may involve creating a new file.


In effetti non c'è nessuna garanzia che la seriale sia gestibile tramite file, non viene citata nel documento, però tutti i compilatori C, per pc, che ho visto/usato, e sono tanti, hanno sempre permesso l'accesso alla seriale come file.
Scientia potentia est

SukkoPera

In effetti non c'è nessuna garanzia che la seriale sia gestibile tramite file, non viene citata nel documento, però tutti i compilatori C, per pc, che ho visto/usato, e sono tanti, hanno sempre permesso l'accesso alla seriale come file.
Ecco, così siamo d'accordo ;).
"Code is read much more often than it is written, so plan accordingly. Design for readability."

Guida rapida a ESP8266: https://goo.gl/kzh62E

Go Up