Salve a tutti, anche se leggo il forum da tempo questo è primo il mio primo post.
Vi espongo subito il problema che mi attanaglia da qualche giorno.
Ho scritto il codice su Arduino Ethernet board per comunicare via rs485 (max485) con un inverter al fine di loggarne (passatemi la terribile italianizzazione) la produzione. La macchina comunica con un baud di 19200, valore con cui inizializzo la comunicazione seriale. Naturalmente ho usato SoftwareSerial (sui pin 7,8) per rx e tx. Studiato il protocollo, ho inviato la giusta sequenza di byte (8 byte dati + 2 crc), ho ricevuto la giusta sequenza di byte per risposta (6 byte dati + 2 crc) e tutto ciò mi ha reso felice per un po di tempo.
Mi sono anche programmato uno sniffer con arduino uno e un ulteriore max485 per verificare il passaggio dei byte sul bus 485, dati che visulizzo su coolterm, un serial monitor per mac ( os x 10.6.8 ). Idilliaco!
Ma come per ogni storia che si rispetti, arriva il momento in cui fa l'ingresso in scena il cattivo. Per me il cattivo è rappresentato dall'esaurimento dello spazio sulla mia board.
La soluzione? Passo a Arduino Mega 2560 e ethernet shield....e qui arrivano i problemi.
Avendo a disposizione diverse seriali hardware metto da parte SoftwareSerial (che comunque non funzionava, o meglio trasmetteva ma non riceveva) e sposto la comunicazione sui pin 19 (rx) e 18 (tx) o, per gli amici, Serial1. Il primo giorno sono stato sulla soglia del pianto per diverse ore. Il serial monitor sul mega mi mostrava i giusti byte, ma gli stessi, inviati su Serial1 venivano mostrati dallo sniffer in maniera assurda. A fronte di 10 trasmessi ne vedevo 3...e pure sbagliati! Naturalmente l'inverter, non ricevendo la giusta query, non rispondeva. Leggi e rileggi, cerca e ricerca, aggiungo (banale) un delay per ogni byte trasmesso e tutto magicamente va per il verso giusto. Urrà! Lo sniffer mi mostra la giusta sequenza di byte che parte dal mio mega e la giusta sequenza di byte che parte, come risposta, dall'inverter.
Ecco, finalmente, il problema. La risposta parte dall'inverter, viene visualizzata dallo sniffer, ma sul mega il serial monitor mi fa vedere byte a caso! Quindi sul bus transitano i dati corretti (come succedeva con arduino eth), ma in ricezione sul pin 19 leggo valori assurdi. Ho cercato e ricercato, ma questa volta ho ritenuto fosse il caso di disturbare la comunità.
Ecco il codice con cui ricevo i dati:
#define LENGHT 8
#define myserial Serial1 // substitute
byte *cmdquery; //punta ad un vettore che viene riempito di volta in volta con il comando da inviare da apposita funzione
byte buffer[LENGHT]={0,0,0,0,0,0,0,0};
byte *buffer_pntr;
void setup(){
Serial.begin(9600);
Serial.println("Start!");
/*RS485 Setup Start*/
myserial.begin(19200);
pinMode(CS_485,OUTPUT);
digitalWrite(CS_485,HIGH);
buffer_pntr = buffer;
/*RS485 Setup Stop*/
if (!SD.begin(CS_SD)) {
Serial.println("Card failed, or not present");
//return;
}
/*Ethernet start*/
avviaEthernet();
/*Ethernet Stop*/
/*NTP Setup Start*/
NTPSetup();
doTimeSync();
/*NTP Setup Stop*/
}
/*
OMISSIS
*/
//false se va in timeout o CRC non corretto
boolean receiveMsg(){
boolean res =false;
rxMode();
delay(100);
while(myserial.available() < LENGHT){
if((millis()-PREVIOUS_TIME)>TIME_OUT){ //qui gestisco un timeout di 2 secondi
String msg ="";
msg += " TIMEOUT on ";
for(int i=0;i<LENGHT;i++){
msg += cmdquery[i];
msg += " ";
}
logToSD(msg);
return res;
}
}
int k = 0;
while(myserial.available()>0){
byte dato = myserial.read();
buffer_pntr[k] = dato;
k=k+1;
if(k==8){
res = checkTrama(); //calcola il crc e controlla che la trama ricevuta sia corretta
k=0;
break;
}
}
return res;
}
Scusate se ho esagerato nello scrivere, e se ho dimenticato qualcosa. Ringrazio in anticipo tutti quelli che vorranno dare il loro contributo.
aggiornamento
Continuando a provare e riprovare, mi sono accorto che stranamente il buffer della Serial1 è sempre pieno, anche quando il dispositivo a cui è collegato il bus è spento!!! Non solo, ma Serial1.available() mi ritorna 63. Non dovrebbe esserci niente in quel buffer, sbaglio?
e invece
Waits for the transmission of outgoing serial data to complete. (Prior to Arduino 1.0, this instead removed any buffered incoming serial data.) http://arduino.cc/it/Serial/Flush
yes!
ho semplificato la funzione di ricezione per capire dove fosse il problema facendomi stampare tutto il contenuto del buffer:
boolean receiveMsg(){
rxMode();
boolean res =false;
int k = 0;
Serial.print("bytes in ingresso: ");
Serial.print(myserial.available());
Serial.println();
while(myserial.available()){
Serial.print(myserial.read());
Serial.print(" ");
}
Serial.println();
myserial.flush(); //<----eccolo!
return checkTrama();
}
eseguo anche un flush "preventivo" prima di inviare il messaggio al dispositivo.
Domanda:
sto usando eth shield r3 sul mio mega 2560 r3. è normale che il led tx sullo shield blinki in accordo con quello della porta eth? Non è che i dati che leggo in seriale, per qualche motivo misterioso, vengono dalla eth???
per chiarezza uso i seguenti pin:
53 per comandare la modalità di trasmissione del max485
5v e gnd per alimentare lo stesso integrato (presi dall shield)
rispondo da solo alla cavolata precedente sui dati che vengono da eth..NO
ho tolto cavetto e sto girando solo con la comunicazione seriale.....no è cambiato nulla
questo è quello che ottengo sul serial monitor:
Ulteriore aggiornamento.
vorrei sapere se è il seguente risultato rientra, secondo voi, nella normale condizione di funzionamento del mio mega2560, se sbaglio qualcosa a livello di codice o se devo cambiare board.
Ho ridotto il codice al minimo per provare la comunicazione seriale. Ho spento il dispositivo (inverter) quindi la mia board invia un comando via Serial1 e non riceve (ovviamente) risposta. Ecco lo sketch:
Come vedete la prima volta ho un treno di 0, poi byte "a caso" a volte nulla....
Qualcuno mi sa dire da dove vengano sti byte e cosa diamine sta succedendo???? =(
Grazie della risposta Paolo...
forse un po troppo criptica per me
1 - la prima riga (quella sequenza di 0) dici che è un buffer non correttamente inizializzato.
Che devo fare per inizializzarlo correttamente? pensavo che Serial1.begin(19200) servisse anche a questo.
2 - Che significa che lascio l'ingresso flottante?
3 - Perchè tutto ciò si verifica solo col mega?
superp:
la prima riga (quella sequenza di 0) dici che è un buffer non correttamente inizializzato.
Che devo fare per inizializzarlo correttamente? pensavo che Serial1.begin(19200) servisse anche a questo.
e non lascio mai il valore del pin "indefinito"; rxMode() e txMode() settano sempre il pin 53 a HIGH o LOW a seconda che io stia trasmettendo o ricevendo.
Per essere chiari, (e smentire la tua faccina ) la riga che vedi è il contenuto del buffer seriale. viene fuori dal while....per questo chiedo come faccio ad inizializzarlo, non ho visto nessun esempio di comunicazione seriale in cui il buffer viene inizializzato.
Poi ripongo la 3a domanda: perchè tutto ciò solo col mega2560 e con ethernet board no?