Comunicazione seriale tra due microcontrollori ..

Ciao .. vorrei sentire la vostra opinione a questo riguardo:

... devo mettere in collegamento due microcontrollori, un ATmega644 ed un 328 (credo sia un 328) sull'arduino ethernet.

... non posso e non voglio usare i normali pin tx e rx (di ciascuno dei due micro) che sono riservati per la comunicazione al pc (serial monitoe e per la progrmmazione)... quindi userò altri pin tra quelli liberi.

Se non ho capito male, posso usare qualsiasi pin tramite la libreria NewSoftSerial.h ...questo credo di aver capito.

poi ... la comunicazione consiste nella richiesta del contenuto di alcuni byte nella eeprom del 644, che il 328 dovrebbe richiedere appunto al 644, e nell'impostazione del contenuto di alcune viariabili .

.. che voi sappiate esiste già, di uso libero, un protocollo facilmente adattabile a questi usi?..
o mi consigliate di riscriverlo tutto?

... si lo sò qualcuno dirà ... ma questo vuole la pappa pronta'??... ebbene si, se la trovo e più o meno quello che sto chiedendo. Ma mi impegno a pubblicare tutto il lavoro una volta ultimato!!!
..

comunque se dovessi scriverlo, questo protocollo via seriale, doveri usare gli interrupt per avvisare il micro destinatario che cè una richiesta, o una disposizione nella seriale?... giusto per non lasciarlo sempre in lettura sulla seriale???...

... ringrazio, come sempre, chi mi darà un qualsiasi suggerimento, indizio o consiglio ...

Saluti
... e buon anno!!!!

Ci sono almeno 256 topic sull'argomento. ]:smiley:
Comunque si, puoi usare la softserial e per il protocollo c'è la libreria EasyTransfert --> GitHub - madsci1016/Arduino-EasyTransfer: An Easy way to Transfer data between Arduinos
Volendo funziona anche su I2C.

Esatto

poi ... la comunicazione consiste nella richiesta del contenuto di alcuni byte nella eeprom del 644, che il 328 dovrebbe richiedere appunto al 644, e nell'impostazione del contenuto di alcune viariabili .

.. che voi sappiate esiste già, di uso libero, un protocollo facilmente adattabile a questi usi?..
o mi consigliate di riscriverlo tutto?

Mah... scomodare una intera libreria per farsi spedire dei byte mi pare un po' uno spreco di risorse.
Fai la richiesta, il 644 la riceve e spedisce i dati nel formato che vuoi tu: 1 byte, diversi byte uno dietro l'altro, ecc.

comunque se dovessi scriverlo, questo protocollo via seriale, doveri usare gli interrupt per avvisare il micro destinatario che cè una richiesta, o una disposizione nella seriale?... giusto per non lasciarlo sempre in lettura sulla seriale???...

La SoftwareSerial riceve i dati in background e li immagazzina in un buffer di ricezione. Il tuo sketch basta che controlli periodicamente che sia arrivato qualcosa e, ne caso, evada la richiesta.

[/quote]

Grazie ad entrambi ....

in fondo mi pare sia abbastanza semplice .. comincio subito a lavorarci .. grazie
ciao

ci "andrebbe" che qualche guru facesse una FAQ seria seguita da dimostrazioni su questo argomento, perché è la cosa più richiesta

gingardu:
ci "andrebbe" che qualche guru facesse una FAQ seria seguita da dimostrazioni su questo argomento, perché è la cosa più richiesta

La questione non è fare la guida. La questione è che la gente la cerchi, quella guida.
La comunicazione fra 2 MCU è stata trattata un sacco di volte, basterebbe fare una ricerca per vedere che si tratta di una semplice comunicazione seriale. E' che nessuno cerca.

sarebbe un ottima cosa, (SANTO SUBITO)
l'unica cosa che mi sento di "consigliare" è quella di tenere sempre in mente il possibile scopo finale dell'utilizzare la trasmissione seriale tra 2 micro
detto in altre parole gia se si riuscirebbe a inviare un numero e ricevere il numero inviato
hai fatto gia molto e per numero si intende un int o float
che il ricevente lo vede come un int o float

leo72:

gingardu:
ci "andrebbe" che qualche guru facesse una FAQ seria seguita da dimostrazioni su questo argomento, perché è la cosa più richiesta

La questione non è fare la guida. La questione è che la gente la cerchi, quella guida.
La comunicazione fra 2 MCU è stata trattata un sacco di volte, basterebbe fare una ricerca per vedere che si tratta di una semplice comunicazione seriale. E' che nessuno cerca.

certo La comunicazione fra 2 MCU è stata trattata un "sacco di volte",

ma quando si cerca di adattare al proprio progetto e mettere in pratica quasi niente funziona

anche perche le "cose" non sono cosi semplici da mettere in pratica in un progetto vero e proprio
se conosci dei post gia fatti (e validi ) si potrebbero mettere i link nella FAQ

che è utile anche per evitare richieste ripetitive

@GINGARDU
Ho iniziato il lavoro ...

il primo problema, il minore, l'ho risolto approssimativamente così:
.... per ricevere la stringa via seriale.... faccio così:

#define dimVettore 25                // lunghezza max del buffer di lettura (stringa seriale)
#define baudSeriale  4800            // velocità seriale
char stringaSERIALE[dimVettore+1]; // stringa buffer destinata a contenere la stringa ricevuta dalla seriale 
boolean stringaOK = false;

void setup() 
{
Serial.begin(baudSeriale);
}

void loop()
{
if (Serial.available()>0){leggiSeriale();}
}

void leggiSeriale()
 { 
   unsigned long count = millis();      //interrompe la lettura dalla seriale se passano più di countMax ms senza che arrivino caratteri
   unsigned long const countMax = 10;   // limite max millisecondi senza che arrivino caratteri .. oltre chiude il ciclo di lettura (non scendere sotto i 5 per 4800 bps e 10 1200bps) 
   boolean fineLettura;                 // controllo sul checksum della stringa Seriale ricevuta

   int index=1;
   // LEGGE i primi dimVettore caratteri ........
   do    
     { if(Serial.available()> 0) {stringaSERIALE[index]=Serial.read(); count = millis(); index++; } 
       fineLettura = ((index > dimVettore) || (millis() - count > countMax));}
   while (!fineLettura);   
   
   stringaSERIALE[0]= index-1; // in posizione 0 pone l'indice massimo ... servirà per il parser della stringa ...
   fineLettura = false;

    byte tempByte;
   // CANCELLA il buffer, se c'è ancora qualcosa nel buffer .....
   do
     { if(Serial.available()> 0) { tempByte = Serial.read(); count = millis();} 
       fineLettura = (millis() - count > countMax);}
   while (!fineLettura);

     int k=0;
     Serial.print("\n ......................................................................");
     Serial.print("\n\t k=0\t   "); Serial.print(stringaSERIALE[0], DEC); Serial.print(" dimensione Vett");
     while (k < stringaSERIALE[0])
     {  k++;
        Serial.print("\n\t k="); Serial.print(k); 
        Serial.print("\t   ")  ; Serial.print(stringaSERIALE[k], DEC);
        Serial.print("\t   ")  ; Serial.print(stringaSERIALE[k]); 
       }
      Serial.print("\n ...................................................................... \n\n\n");
}

... la stringa viene ricevuta e messa nel vettore stringaSeriale[] .. in posizione 0 viene messo il valore massimo raggiunto dal puntatore..... mi pare che funzioni sempre, con qualsiasi velocità di bps.....
per adesso, per il debug, uso la seriale standard, ma poi l'idea è di usare la libreria softSerial per usare qualsiasi PIN ed usare la seriale standard come eco dei comandi e dei messaggi ricevuti ...

Ho anche abozzato la mia idea della decodifica della stringa comando in questo modo:

#define dimVettore 25                // lunghezza max del buffer di lettura (stringa seriale)
#define baudSeriale  4800            // velocità seriale
char stringaSERIALE[dimVettore+1]; // stringa buffer destinata a contenere la stringa ricevuta dalla seriale 
boolean stringaOK = false;

void setup() 
{
Serial.begin(baudSeriale);
}

void loop()
{
if (Serial.available()>0){leggiSeriale();}
if (stringaOK) {analizzaStringa();}
}

void leggiSeriale()
 { 
   unsigned long count = millis();      //interrompe la lettura dalla seriale se passano più di countMax ms senza che arrivino caratteri
   unsigned long const countMax = 10;   // limite max millisecondi senza che arrivino caratteri .. oltre chiude il ciclo di lettura (non scendere sotto i 5 per 4800 bps e 10 1200bps) 
   boolean fineLettura;                 // controllo sul checksum della stringa Seriale ricevuta

   int index=1;
   // LEGGE i primi dimVettore caratteri ........
   do    
     { if(Serial.available()> 0) {stringaSERIALE[index]=Serial.read(); count = millis(); index++; } 
       fineLettura = ((index > dimVettore) || (millis() - count > countMax));}
   while (!fineLettura);   
   
   stringaSERIALE[0]= index-1; // in posizione 0 pone l'indice massimo ... servirà per il parser della stringa ...
   fineLettura = false;

    byte tempByte;
   // CANCELLA il buffer, se c'è ancora qualcosa nel buffer .....
   do
     { if(Serial.available()> 0) { tempByte = Serial.read(); count = millis();} 
       fineLettura = (millis() - count > countMax);}
   while (!fineLettura);

  stringaOK = true;
}


/* ipotesi di mappatura della stringa di comando

byte 0 - lunghezza max del vettore-buffer, (n: numero di byte - caratteri di cui si compone la stringa dati) 
byte 1 - ID destinatario (0 - 128) (al momento inutilizzato)
byte 2 - ID mittente (0 - 128) (al momento inutilizzato)
byte 3 - PIN prima parte, per riconoscere il comando/interrogazione (al momento inutilizzato)
byte 4 - PIN seconda parte, per riconoscere il comando/interrogazione (al momento inutilizzato)
byte 5 - inutilizzato (al momento inutilizzato)
byte 6 - inutilizzato (al momento inutilizzato)
byte 7 - inutilizzato (al momento inutilizzato)
byte 8 - comando/dispositivo (A: interrogazione;     B: comando;     C: invio dati;     D: comunicazione ricevuto Ok;     E: comunicazione errore ricezione ... etc.)
byte 9 - inutilizzato (al momento)
byte 10 - inutilizzato (al momento)

byte 11 - inizio sequenza del comando\dispositivo, 1 byte
byte 12 - continuo sequenza del comando\dispositivo, 2 byte
byte 13 - continuo sequenza del comando\dispositivo, 3 byte
... ...
... ...
byte n-2 - penultimo byte della sequenza comando\dispositivo, n-2'esimo byte
byte n-1 - ultimo byte della sequenza comando\dispositivo, n-1'esimo byte
byte n   - checksum (al momento inutilizzato), n'esimo byte
*/

void analizzaStringa ()
{ stringaOK = false; 

 if (stringaSERIALE[0] >= 12) //  ci sono i caratteri minimi necessari
    {
        switch (stringaSERIALE[8]) // byte in posizione 8
        {
        case 'A': //interrogazione
        Serial.print("\n\t Scelta:A");
        
        break;

        case 'B': //comando
        Serial.print("\n\t Scelta:B");
        
        break;
        
        case 'C': //comunicazione: ricevuto ok
        Serial.print("\n\t Scelta:C");
        
        break;

        case 'D': //comunicazione: errore ricezione
        Serial.print("\n\t Scelta:D");
        
        break;
        } 

     // stampa i dati ricevuti .....
     int k=0;
     Serial.print("\n ......................................................................");
     Serial.print("\n\t k=0\t   "); Serial.print(stringaSERIALE[0], DEC); Serial.print(" dimensione Vett");
     while (k < stringaSERIALE[0])
     {  k++;
        Serial.print("\n\t k="); Serial.print(k); 
        Serial.print("\t   ")  ; Serial.print(stringaSERIALE[k], DEC);
        Serial.print("\t   ")  ; Serial.print(stringaSERIALE[k]); 
       }
      Serial.print("\n ...................................................................... \n\n\n");
    }
 else //  non ci sono i caratteri minimi necessari
    {
     Serial.print("\n\t Stringa comando non corretta. Ricevuti solo ");  Serial.print(stringaSERIALE[0], DEC);  Serial.print(" caratteri!!");
    }
}

ipotizzo che la stringa di comando abbia questa forma:

byte 0 - lunghezza max del vettore-buffer, (n: numero di byte - caratteri di cui si compone la stringa dati)
byte 1 - ID destinatario (0 - 128) (al momento inutilizzato)
byte 2 - ID mittente (0 - 128) (al momento inutilizzato)
byte 3 - PIN prima parte, per riconoscere il comando/interrogazione (al momento inutilizzato)
byte 4 - PIN seconda parte, per riconoscere il comando/interrogazione (al momento inutilizzato)
byte 5 - inutilizzato (al momento inutilizzato)
byte 6 - inutilizzato (al momento inutilizzato)
byte 7 - inutilizzato (al momento inutilizzato)
byte 8 - comando/dispositivo (A: interrogazione; B: comando; C: invio dati; D: comunicazione ricevuto Ok; E: comunicazione errore ricezione ... etc.)
byte 9 - inutilizzato (al momento)
byte 10 - inutilizzato (al momento)
byte 11 - inizio sequenza del comando\dispositivo, 1 byte
byte 12 - continuo sequenza del comando\dispositivo, 2 byte
byte 13 - continuo sequenza del comando\dispositivo, 3 byte
... ...
... ...
byte n-2 - penultimo byte della sequenza comando\dispositivo, n-2'esimo byte
byte n-1 - ultimo byte della sequenza comando\dispositivo, n-1'esimo byte
byte n - checksum (al momento inutilizzato), n'esimo byte

lo so, ci sono molti bit inutilizzati ed inutili per la comununicazione seriale ... ma io, poi, vorrei utilizzarlo anche per altre cose.... quindi vorrei fare una sorta di protocollo generale utilizzabile per molti casi....

una volta stabilita la lunghezza max del buffer contenente la stringa, nella variabile dimVettore, che nel mio caso ho messo a 25, perchè certamente bastano per gestire il mio progetto ..... la decodifica della stringa sarebbe da fare con opportuni switc case.

Adesso comincio a scrivere la parte di decodifica specifica per il mio progetto che sostanzialmente consiste in:

  • il primo micro interroga il secondo per estrarre il contenuto di 12 byte della eeprom, a partire da in una certa posizione , quindi invia i dati al 2 micro;
  • il primo micro invia i dati per modificare i 12 byte della eeprom ...

aspetto opinioni al riguardo ....
ciao

certo La comunicazione fra 2 MCU è stata trattata un "sacco di volte",
ma quando si cerca di adattare al proprio progetto e mettere in pratica quasi niente funziona

weeee gingardu sei sempre incazzato??
ci sei mancato .... ma dove eri finito??!! XD XD XD XD

... wee gingardu.. ci sei o non ci sei ????? ...

... ho sviluppato un'altra parte.
innazitutto ho modificato la mappatura della stringa interrogazione/comando , usando questo schema:

/* MAPPATURA STRINGA DATI
byte 0 - lunghezza max del vettore-buffer, (n: numero di byte - caratteri di cui si compone la stringa dati) 
byte 1 - ID destinatario (0 - 128) (al momento inutilizzato)
byte 2 - ID mittente (0 - 128) (al momento inutilizzato)
byte 3 - PIN prima parte, per riconoscere il comando/interrogazione (al momento inutilizzato)
byte 4 - PIN seconda parte, per riconoscere il comando/interrogazione (al momento inutilizzato)
byte 5 - inutilizzato (al momento inutilizzato)
byte 6 - inutilizzato (al momento inutilizzato)
byte 7 - COMANDO/DISPOSIZIONE (A: interrogazione;     B: comando;     C: invio dati; )
byte 8 - COMANDO/DISPOSIZIONE, sotto categoria di quanto specificato al byte 7
byte 9 - COMANDO/DISPOSIZIONE, sotto categoria di quanto specificato al byte 8 
byte 10 - al momento utilizzato in ricezione facendo (-65) .. così uso un carattere ascii per ricevere un numero <33
byte 11 - inizio sequenza del comando\dispositivo, 1 byte
byte 12 - continuo sequenza del comando\dispositivo, 2 byte
byte 13 - continuo sequenza del comando\dispositivo, 3 byte
... ...
... ...
byte n-2 - penultimo byte della sequenza comando\dispositivo, n-2'esimo byte
byte n-1 - ultimo byte della sequenza comando\dispositivo, n-1'esimo byte
byte n   - checksum (al momento inutilizzato), n'esimo byte
*/

lo sviluppo lo sto facendo interrogando il micro inviandogli una stringa secondo la convenzione di cui sopra.. e ricevendo sempre via seriale la risposta ...
qui allego gli esempi a cui sto lavorando già testati e funzionanti.

in seguito conto di inserire la softserial e rendere utilizzabile la connessione tra due micro..

io, nel mio caso, devo controllare il contenuto della eeprom ed eventualemnte modificarne i valori ..
... domani aggiungo maggiori dettagli ...

comunicazioneSeriale_8_11_01_13.zip (5.68 KB)