Spi entre arduino, bof

Bonsoir à tous,

cela fais quelque jours que je bricole sur le protocole SPI actuellement j'arrive à communiquer dans un sens mais dans l'autre.

Voici dans la théorie ce qu'il doit se passer.
Un logiciel via envoyé sur le port série des informations à un arduino maître qui celui-ci selon des paramètres définis envoie en SPI des informations à un second arduino esclave.

Cet esclave fait réagir un servo moteur. Jusque là tout vas très bien.

on obtient quelque chose du genre:
Logiciel envoie à l'arduino maître"<Y100"
Arduino maître interprète et envoie à l'arduino esclave "01:04:FF:01:00:00:00:00"
l'arduino esclave interprète et agis sur le servo "Rpm_1_Servo.write(100);"

maintenant je suis à l'étape:
s'il y a un creux dans la transmition logiciel, le maitre envoie "01:FF:FF:FF"
l'esclave répond par exemple "01:02:<B:04"

mais je m'y prend mal pour communiquer dans l'autre sens et les 2 arduinos se plante.
A priorie l'esclave commence à répondre mais n'envoie pas les données d'un coup il est entrecoupé par une autre boucle, et le maitre doit attendre la fin de transmition. Mais là je suppose.

Code du maitre

#include <SPI.h>
String Data_R="";//Donnée reçu de l2fs
char buf [100];//tampon de réception
volatile byte pos;//position dans le tampon
volatile boolean process_it;//information récupérée

int Priority = 9;
int Com_Avaible=10;




void setup (void)
 {
 Serial.begin(115200);
 Serial.println("Communication Carte 1 OK");

 SPI.begin ();
 SPI.setClockDivider(SPI_CLOCK_DIV8);
 pinMode(Priority, INPUT);
 }

ISR (SPI_STC_vect)
 {
 if(digitalRead(Com_Avaible) == LOW)
 {
 byte c = SPDR;  // grab byte from SPI Data Register
 if (pos < sizeof (buf))
 {
 buf [pos++] = c;
 if (c == '\n')
 process_it = true;
 }
 }
 }

void SPI_callback()
 {
 if (process_it)
 {
 buf [pos] = 0;
 pos = 0;

 String Buffer  = buf;
 Serial.print("data:");
 Serial.println(Buffer);
 }

 process_it=false;
 }

void spi_send(int com_b,int role,long info)
 {
 String data;

 if(digitalRead(Priority) == LOW)
 {
 int count;
 int sep=0;
 int modulo=0;
 //indication de l'instrument visé sur la carte réceptrice
 String S_role=String(role, HEX);
 if (S_role.length()<2){for(int i=0; i<2-S_role.length(); i++){data+="0";}}
 data+=S_role;
 data+=":";

 String S_info=String(info);
 //Serial.print(S_info);

 if(S_info.length()%2!=0){count=int((S_info.length()/2)+1);modulo=0;}
 else{count=S_info.length()/2;modulo=1;}

 if(count>15){data+=String(count, HEX);}
 else{data+="0";data+=String(count, HEX);}

 data+=":";
 if(info>=0)
 {
 data+="FF:";
 }
 else
 {
 data+="AA:";
 info=info*-1;
 }

 


 if(modulo==1)
 {
 for (int i=0; i< S_info.length(); i++)
 {

 if(i%2!=0)
 {
 data+=S_info.charAt(i);
 if(i+1!=S_info.length()){data+=":";}
 }
 else{data+=S_info.charAt(i);}

 //Serial.print(data.charAt(i));
 }
 }
 else
 {
 data+="0";
 //Serial.print("0");
 for (int i=0; i< S_info.length(); i++)
 {

 if((i+1)%2!=0)
 {
 data+=S_info.charAt(i);
 if(i+1!=S_info.length()){data+=":";}
 }
 else{data+=S_info.charAt(i);}

 //Serial.print(data.charAt(i));
 }
 }

 

 //cloture des data
 data+="\n";
 pinMode(Com_Avaible, OUTPUT);//indicateur de donnée à réceptionné
 digitalWrite(Com_Avaible, LOW);//réveil électrique de la carte réceptrice
 delayMicroseconds(20);
 
 for (int i=0; i< data.length(); i++)
 {
 SPI.transfer (data.charAt(i));delayMicroseconds(20);
 Serial.print(data.charAt(i));

 }

 digitalWrite(Com_Avaible, HIGH);
 pinMode(Com_Avaible, INPUT);//indicateur de donnée à réceptionné

 }
 }



void LESSTHAN(String& Tampon)
 {
 long info;
 //Serial.println(Tampon); // Used for testing
 
 if(Tampon[0]=='A'||Tampon[0]=='B'||Tampon[0]=='C' ||Tampon[0]=='Y')
 {
 
 switch(Tampon[0])
 {
 case 'Y'://Train avant
 {
 char floatbuf[32]; // make this at least big enough for the whole string
 Tampon.substring(1).toCharArray(floatbuf, sizeof(floatbuf));
 float Info_F = atof(floatbuf);
 info=Info_F*1000000;
 spi_send(10,1,info);
 }

 break;
 case 'B'://Train gauche
 break;
 case 'C'://Train droit
 break;
 }
 }
 
 }
//....////
void Traitement (String& Commande)
 {
 //Serial.println(Commande);
 String Tampon;
 if (Commande.length() < 3) return; // Il s'agit d'un commande invalide en longueur
 Tampon = Commande.substring (1); // on copie le reste de la commande dans un tampon


 switch (Commande[0])
 {
 case '=':
 EQUALS(Tampon);
 break;
 case '#':
 DIESE(Tampon);
 break;
 case '<':
 LESSTHAN(Tampon);
 break;
 case '?':
 QUESTION(Tampon);
 break;
 case '/':
 SLASH(Tampon);
 break;
 default:
 break;
 }
 }
void loop()
 {
 unsigned int td = millis();
 char Bloc; //Donnée extraite
 //!!début!!récupération des donnéees envoyés par l2fs
 while (Serial.available()) //Tant qu'il y a des données sur le port série
 {
 Bloc=Serial.read(); //on stock le caractére

 if((Bloc == '=') || (Bloc == '#') || (Bloc == '<') || (Bloc == '?') || (Bloc == '/') || (Bloc == '\r') || (Bloc == '\n')) //Si on a affaire à un char de fin de commande
 {
 // Si on a une chaine déjà entamée il s'agit d'une fin de commande
 if (Data_R.length()>1)
 {
 Traitement (Data_R);// La commande est complète alors on l'analyse
 Data_R="";//On réinitialise Le tampon d'entrée avec le premier char de commande
 }
 }
 if ((Bloc!='\n') && (Bloc!='\r'))
 {
 Data_R+= Bloc;
 }
 }
 //SPI_callback();
 
 }

et le code de l'escalve

#include <SPI.h>
#include <Servo.h>
char buf [100];//tampon de réception
volatile byte pos;//position dans le tampon
volatile boolean process_it;//information récupérée
boolean test_data=false;//résultat information testé
int Priority = 9;
int Com_Avaible=10;
Servo Rpm_1_Servo;
String  C_role="01";
float data;
String datac="coucou les petit enfant\n";
char* hexadec[]={"0", "1", "2", "3", "4", "5", "6","7", "8", "9", "a", "b", "c", "d", "e", "f","\n"};




void setup (void)
 {
 Serial.begin (115200);
 Serial.println ("Esclave ok");

 pinMode(Priority, INPUT);//coupure de toute les transmitions sortantes
 pinMode(Com_Avaible, INPUT);//indicateur de donnée à réceptionné
 pinMode(MISO, OUTPUT);//Réglage en mod esclave
 pinMode(5, OUTPUT);//Information pour le servo en sortant
 SPCR |= _BV(SPE);//Réglage en mod esclave

 pos = 0;   // purge du buffer
 process_it = false;//pas d'info en stock
 SPI.attachInterrupt();
 SPI.setClockDivider(SPI_CLOCK_DIV8);

 pinMode(5, OUTPUT);// For the servo.
 Rpm_1_Servo.attach(5);
 for(int i=0; i<180; i=i+10)
 {
 Rpm_1_Servo.write(i);
 delay(200);
 }
 Rpm_1_Servo.write(5);
 }


// SPI interrupt routine
ISR (SPI_STC_vect)
 {
 if(digitalRead(Com_Avaible) == LOW)
 {
 byte c = SPDR;  // grab byte from SPI Data Register
 if (pos < sizeof (buf))
 {
 buf [pos++] = c;
 if (c == '\n')
 process_it = true;
 }
 }

 
 }

boolean DATA_test(String Buffer)
 {
 boolean sepa=true;
 boolean carac=false;
 int Buffer_size=Buffer.length();

 Serial.print("data:");
 Serial.println(Buffer);


 //vérification de la cohérence des données
 for(int i=1; i<Buffer_size+1; i++)
 {
 carac=false;
 if(i!=0 && i!=Buffer_size)
 {
 if(i%3==0)
 {
 if (Buffer.substring(i-1,i) ==":"){sepa=true;}
 else{sepa=false;break;}
 }
 else{
 for(int a=0; a<16; a++){if(Buffer.substring(i-1,i) == hexadec[a]){carac=true;}}
 if(carac==false || sepa==false){break;}
 }

 }
 else if(i==Buffer_size)
 {
 if(Buffer.substring(i-1,i) == "\n"){}
 else {break;}
 }
 else
 {
 for(int a=0; a<16; a++){if(Buffer.substring(i-1,i) == hexadec[a]){carac=true;}}
 if(carac==false || sepa==false){break;}
 }
 }

 
 return true;
 }

float Data_extract(String Buffer)
 {
 int signe;
 if(Buffer.substring(6,8)=="AA"){signe=-1;}
 else if(Buffer.substring(6,8)=="FF"){signe=1;}

 int size_data;
 size_data=Buffer.substring(3,5).toInt();

 float data;
 String data_t;
 for(int i=0; i<size_data; i++){data_t+=Buffer.substring(9+(3*i),11+(3*i));}
 data=data_t.toInt();
 data=signe*(data/1000000);
 return data;
 }

void loop (void)
 {

 if (process_it)
 {
 buf [pos] = 0;
 pos = 0;

 String Buffer  = buf;
 data=0;

 if(DATA_test(Buffer))
 {
 data=Data_extract(Buffer);
 }

 String role;
 role=Buffer.substring(0,2);

 Rpm_1_Servo.write(data+5);
/* début de la partie qui catouille
 delay(2000);
 pinMode(Com_Avaible, OUTPUT);//indicateur de donnée à réceptionné
 digitalWrite(Com_Avaible, LOW);//réveil électrique de la carte réceptrice
 
 
 for (int i=0; i< datac.length(); i++)
 {
 SPI.transfer (datac.charAt(i));delayMicroseconds(20);
 Serial.println(datac.charAt(i));

 }
 digitalWrite(Com_Avaible, HIGH);
 pinMode(Com_Avaible, INPUT);//indicateur de donnée à réceptionné
*/ fin de partie qui catouille
 
 }

 process_it=false;

 }

je recherche de la doc, des exemples pour la communication entre arduino bidirectionnel, mais je ne trouve que sur des périphériques et pour moi ce n'est pas explicite.

Pourriez vous m'aider.

Merci d'avance Flo

je me permet de remonter une fois le sujet, mais j'ai l'impression que je n'inspire pas avec ma question

Pourquoi du SPI et pas une simple liaison série en croisant Tx / Rx ?

Sinon ici : Gammon Forum : Electronics : Microprocessors : SPI - Serial Peripheral Interface - for Arduino

Christian_R:
Pourquoi du SPI et pas une simple liaison série en croisant Tx / Rx ?

parce que je ne vais pas m'arrêter à un seul esclave

B@tto:
Sinon ici : Gammon Forum : Electronics : Microprocessors : SPI - Serial Peripheral Interface - for Arduino

très interessant

je reviens sur le sujet avec une question simple, en comparant avec du sérial basic:
peut on faire

master send=>serial.println("bonjour')
slave receive<=if serial..("bonjour")
slave send("tiens bonjours comment allez vous")
master receive<=if serial..("tiens bonjours comment allez vous")
....
je ne trouve pas de réponse qui me permettrait de le savoir, le spi ne semble pas prévue pour le faire