sono nuovo nel forum e scusate se vi chiedo subito aiuto, ma spero che qualcuno mi possa dare qualche consiglio sul mio progetto. Come scritto nella presentazione, sto cercando di fare un progetto per controllare un fermentatore tramite Arduino e mandare tutti i dati a Visual Basic per un interfaccia grafica e registrare i dati.
Ho già provato con Firmata, ma dopo qualche minuto (a volte anche secondo) si interrompe la comunicazione e si blocca tutto. Ho caricato su arduino un insieme di Simple Analog e Simple Digital Firmata come visto su un tutoria su internet, caricato in VisualBasic l'applicazione e controllato i pin di Arduino con "FirmataVB1.DigitalWrite(pin, stato)". Tutto funziona perfettamente, ma dopo un po' sembra che si interrompe la comunicazione e su VB mi dice che una periferica collegata non è infunzione.
Ho provato anche a fare una libreria mia ma credo che è troppa la mole di dati da scambiare (forse uso int al posto di Char o qualcosa di simile).
Ciao,
allora ... se ben capisco da una parte hai un PC con VB e dall'altra Arduino ...
Arduino, collegato tramite la USB al PC, viene visto da quest'ultimo come una porta COM: quindi, da VB, dovrai aprire la COMx: e parlare con essa.
Dal lato Arduino, lascia stare Firmata e scriviti tu il codice per fare ciò che ti serve. Avrai più flessibilità e tutto sotto controllo
Ricorda solo che su Arduino la porta seriale lavora "carattere a carattere" ... un carattere alla volta ... quindi, qualsiasi cosa devi trasmettere/ricevere, devi farlo con dei loop che spediscono/ricevono un carattere alla volta.
Studiati attentamente tutti i vari metodi della classe Serial e vedrai che puoi fare veramente di tutto ...
In merito all'uso della porta seriale, qui sul forum ci sono decine e decine di discussioni ... comunque ... se serve, noi siamo qui ...
innanzitutto grazie mille per la risposta. Come hai capito perfettamente ho un Arduino che comunica tramite USB com il PC sul quale ho Visual Basic dal quale gestisco tutti i parametri. Per la comunicazione in se per se non ci sono problemi, ovvero riesco a comunicare sia lato Arduino che lato PC, ma usando Firmata dopo un po si blocca tutto, cos' ho deciso di fare una libreria per conto mio (come hai giustamente consigliato tu ;)). Ma anche ora ho dei piccoli problemi: ogni tanto Arduino non fa precisamente quello che voglio io e soprattutto ci mette tanto (5 - 10 secondi) prima di agire, ma non sempre il che provoca problemi (aziono pompe, iniezione di gas, eccc). Vorrei sapere se per caso è un problema di programmazione o è solo un problema di velocità di scambio di dati?
Ecco il codice lato Arduino (lo so, è un cavernicolo come codice) per mandare al PC il valore dell'entrata analogica A0
int sensoreDig;
void setup(){
Serial.begin(57600);
pinMode(5, INPUT);
}
void loop(){
sensoreDig = digitalRead(5)
if (sensoreDig == HIGH){
Serial.println ("A");
}
dal lato PC gli dico che se arriva una "A" vuol dire che il valore del sensoreDig e HIGH
e invece per ricevere comandi, nel loop metto :
int comando;
comando = Serial.read();
if (movemento == 'P'){
digitalWrite(12, HIGH);
}
//avendo dichiarato nel setup che il pin 12 era di OUTPUT
ho decine di segnali da mandare e poteri fare il loop da parte PC ogni 1000 millisecondo e mettere un deley ma ugualmente non va come vorrei? Potrei mettere qualcosa come Byte al posto di int ma non me lo legge da perte PC?
Il primo :
quello è un loop veramente stretto, nella realtà immagino che farai un'acquisizione dal canale analogico, la trasmetterai e ... aspetterai X millisecondi prima di rileggere, quindi ... aggiungi un delay ...
Il secondo :
... stessa cosa ... se il segnale rimane HIGH ... in un loop così stretto hai una trasmissione continua ... metti anche qui un delay()
Il terzo :
c'è un errore di base che sicuramente ti crea problemi ... non puoi leggere dalla seriale se prima non verifichi che ci sia qualche cosa da leggere (... pena ricevere a raffica il valore -1) ... devi condizionare la Serial.read() ad una :
... aggiungo, relativamente al primo e secondo pezzo di codice che, come puoi leggere nel reference :
"As of version 1.0, serial transmission is asynchronous; Serial.print() will return before any characters are transmitted."
il che significa che ciò che tu dai da trasmettere viene bufferizzato, ma ... il buffer è piuttosto limitato (credo 64 bytes) e quindi devi dargli il tempo di svuotarsi o ... perdi i dati che trasmetti ...
Sembra che possa essere questo il problema. Proverò a condizionare la seriale prima di inviare tutti i dati e metto un delay dopo ogni lettura (ne ho una decina digitali e 7 analogici, per questo uso il Mega) delay(50); può andare bene, anche per far scuotere il buffer o è meglio mettere un delay maggiore tra la parte dello sketch che riceve i dati e quello che manda al PC?
... vedo che hai la seriale a 57600 ... il che significa che ogni char impiega come minimo, solo per la trasmissione fisica 1/5760 sec. e quindi, in funzione di quanti caratteri invii (caratteri, mi raccomando ... il numero intero 32500 inviato con una Serial.print via seriale sono come minimo 5 caratteri più, se li trasmetti il CR e LF finali, che fanno in tutto 7) cambia il tempo ...
Comunque, con un delay(50) ... ci dovresti stare dentro alla grande
Rieccomi qui e purtroppo non sono riuscito a risolvere i miei problemi :~
sembra che vada tutto bene, i valori analogici mandati da Arduino arrivano bene, ma dopo un po che gli mando dei comandi, a un certo punto si blocca tutto. Dalla parte di VB mi esce un Msg box con scritto:
IOException non è stata gestita
Una periferica collegata al sistema non è in funzione.
Ma fino a un secondo fa reagiva perfettamente e tutto di un tratto si è impuntata.
ti metto il codice per intero, l'ho snellito ma anche così non funziona
int pH1;
int pH2;
int DO;
int Co2 = 8;
int O2 = 12;
void setup(){
Serial.begin(57600);
pinMode(Co2, OUTPUT);
pinMode(O2, OUTPUT);
}
void loop(){
pH1 = analogRead(A1);
Serial.println(pH1);
delay(50);
pH2 = analogRead(A0);
Serial.println(pH2);
delay(50);
DO = analogRead(A2);
Serial.println(DO);
delay(50);
if (Serial.available() > 0){
int iniezione = Serial.read();
if (iniezione == '1'){
digitalWrite(Co2, HIGH);
digitalWrite(O2, LOW);
}
if (iniezione == '2'){
digitalWrite(Co2, LOW);
digitalWrite(O2, HIGH);
}
if (iniezione == '0'){
digitalWrite(Co2, LOW);
digitalWrite(O2, LOW);
}
delay(50);
}
}[code]
dove il comando "iniezione" lo mando da VB con un timer ogni 300 ms, il cui valore lo cambio premendo dei pulsanti.
Che possa essere un problema di Hardware o che il Pc che sto usando è un po' vecchiotto (ha ancora Windows XP).
Non saprei più cosa provare. Non c'è un comando per svuotare il buffer?
Ti ringrazio ancora per l'infinita pazienza.
Giacomo.
Mmm ... a me sembra che non ci sia nulla di sbagliato ...
Comunque ...
... relativamente ai buffer ci sono due strade, una per il TX buffer ed una per il RX buffer :
TX Buffer:
Usare la Serial.flush() che ferma il programma fino a quando il TX buffer non è vuoto. Qundi allo statement successivo, sei sicuro che il TX buffer e completamente stato trasmesso.
RX Buffer:
Per svuotare completamente il RX buffer puoi fare un loop stretto del tipo :
while (Serial.available()) {
Serial.read();
delay(1);
}
... e all'uscita dal while non ci sono più caratteri disponibili nel buffer.
Solo per fare una prova, allunga il tempo ogni quanto trasmetti da PC qualche cosa ... da 300 msec. prova a fare 750 msec. .... tanto per vedere ...
Ho anche provato a mandare i comandi "iniezione" dalla seriale di Arduino e fino a un po' funziona e poi chiude la connessione e i led di comunicazione TX e RX o rimangono sempre accesi o rimangono sempre spenti. Invece se non mando nulla tutto ve bene e ho provai a lasciarlo anche tutta la notte senza problemi.
ora il codice è così:
int pH1;
int pH2;
int DO;
int Co2 = 8;
int O2 = 12;
void setup(){
Serial.begin(57600);
pinMode(Co2, OUTPUT);
pinMode(O2, OUTPUT);
}
void loop(){
pH1 = analogRead(A1);
Serial.println(pH1);
delay(50);
Serial.flush();
pH2 = analogRead(A0);
Serial.println(pH2);
delay(50);
Serial.flush();
DO = analogRead(A2);
Serial.println(DO);
delay(50);
Serial.flush();
if (Serial.available() > 0){
int iniezione = Serial.read();
if (iniezione == '1'){
digitalWrite(Co2, HIGH);
digitalWrite(O2, LOW);
}
if (iniezione == '2'){
digitalWrite(Co2, LOW);
digitalWrite(O2, HIGH);
}
if (iniezione == '0'){
digitalWrite(Co2, LOW);
digitalWrite(O2, LOW);
}
while (Serial.available()){
Serial.read();
delay(1);
}
}
inizio a pensare sul serio che sia un qualche problema di HW. Una cosa: una volta ho collegato il cavo USB ad Arduino mentre era collegato all'alimentazione (9V tramite il Jack) è possibile che si sia danneggiato qualcosa?
Proverò in questi giorni a montare il tutto su un nuovo Arduino Uno che ho e provo a vedere che succede.
Ti ringrazio ancora per la disponibilità.
Ti farò sapere lo sviluppo della vicenda. Buon Week end
Se ti può aiutare mi esce questa scritta quando si impianta il tutto
Dimensione del file binario dello sketch: 5.380 bytes (su un massimo di 258.048 bytes)
java.io.IOException: Input/output error in writeArray
at gnu.io.RXTXPort.writeArray(Native Method)
at gnu.io.RXTXPort$SerialOutputStream.write(RXTXPort.java:1124)
at processing.app.Serial.write(Serial.java:517)
at processing.app.Serial.write(Serial.java:540)
at processing.app.SerialMonitor.send(SerialMonitor.java:200)
at processing.app.SerialMonitor.access$100(SerialMonitor.java:32)
at processing.app.SerialMonitor$3.actionPerformed(SerialMonitor.java:89)
at javax.swing.JTextField.fireActionPerformed(JTextField.java:492)
at javax.swing.JTextField.postActionEvent(JTextField.java:705)
at javax.swing.JTextField$NotifyAction.actionPerformed(JTextField.java:820)
at javax.swing.SwingUtilities.notifyAction(SwingUtilities.java:1636)
at javax.swing.JComponent.processKeyBinding(JComponent.java:2851)
at javax.swing.JComponent.processKeyBindings(JComponent.java:2886)
at javax.swing.JComponent.processKeyEvent(JComponent.java:2814)
at java.awt.Component.processEvent(Component.java:6040)
at java.awt.Container.processEvent(Container.java:2041)
at java.awt.Component.dispatchEventImpl(Component.java:4630)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.KeyboardFocusManager.redispatchEvent(KeyboardFocusManager.java:1848)
at java.awt.DefaultKeyboardFocusManager.dispatchKeyEvent(DefaultKeyboardFocusManager.java:704)
at java.awt.DefaultKeyboardFocusManager.preDispatchKeyEvent(DefaultKeyboardFocusManager.java:969)
at java.awt.DefaultKeyboardFocusManager.typeAheadAssertions(DefaultKeyboardFocusManager.java:841)
at java.awt.DefaultKeyboardFocusManager.dispatchEvent(DefaultKeyboardFocusManager.java:668)
at java.awt.Component.dispatchEventImpl(Component.java:4502)
at java.awt.Container.dispatchEventImpl(Container.java:2099)
at java.awt.Window.dispatchEventImpl(Window.java:2475)
at java.awt.Component.dispatchEvent(Component.java:4460)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:599)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
scusami ancora, ma ho fatto spendere un bel po al dipartimento pensando che potevo farcela, ma credo che sia più difficile di quanto pensassi
Ora sembra che funzioni perfettamente almeno mettendo i dati direttamente dalla seriale
Sulla testa dell'IDE c'era scritto solo 1.0.5 e quindi ho cancellato tutto (anche Visual Basic però ) e rimesso tutto facendo attenzione che sia r2. Ho anche usato il switch/case che mi hai proposto. Sembra che vada alla grande. Ti farò sapere se va tutto perfettamente anche con VB.
Il problema è che su arduino UNO si sono dimenticati di mettere il controllo di flusso hardware, in arduino2009 non c'era questo problema perchè il segnale DSR è disponibile sul pin2 di X3, basta collegare questo pin ad un qualsiasi pin di meg328 così quando arduino è impegnato abilita l'ingresso DSR per comunicare al PC l'interruzione del flusso.
La cosa identica l'ho fatta quì: ARDUINO1
vedi lo schema in PACK LNCNC
E' comunque possibile variare il firmware su mega16u2 aggiungendo le funzioni per la linea DSR, non sò se è già disponibile in rete