Transferts de données entre arduino par la liaison série

Bonjour

Il me semble avoir presque tout lu (dans le forum Français), sur ce qui se rapporte aux communications séries. Et du coup, cela me paraît bien compliqué pour le noob que je suis. Maintenant, je ne sais plus trop quelle serait la procédure à employer.

Je dois faire s’échanger des variables (int, float et long) d’une carte à l‘autre (entre Duemilanove et Mega 2560).

La configuration matérielle :
Duemilanove (Pin 0(Rx) et 1(Tx)) raccordée en croisant les fils, au port serial1 de la Mega (Pin 18(Tx) et 19(Rx)).
La Mega est raccordée au Pc par le port série standard (0/1) pour contrôler la réception des valeurs sur le terminal.

La première étape que j’ai réussi à faire, c’est enregistrer les variables à transférer dans un tableau (3 variables pour commencer). Les envoyer sur le port série de la Duemilanove (pin 0 et 1), et ainsi les lire sur le terminal.

Sur la Mega, je n’arrive pas à les enregistrer. Ce qui m’apparait maintenant comme normal, au regard de ce que j’ai pu lire. Ce n’est pas aussi simple que je le pensais.

Dois-je transformer mes variables afin qu’elles aient toutes le même format dans le tableau (long, float, … ?)
Dois-je formater les variables avant l’envoi ? Comment ? (dois-je les modifier en char ? > Que faire des long ?)

Le nombre de données du tableau de l’émetteur (et donc recevoir sur l’autre) est fixe et connu.
Le format à l’arrivée serait donc à reformater pour retrouver le même type qu'avant l'envoi de la carte émettrice (connu également).

Je me pose beaucoup plus de questions après avoir potassé pendant plusieurs jours qu‘avant !
Si vous avez des exemples fonctionnels, je suis preneur…

Franck

BONNES FETES DE FIN D'ANNEE !!!!!!!

Bonjour,

Pour envoyer / recevoir des variables il faut d'abord les transformé en une suite d'octets.

Exemple, un char ou un byte = un octet,
Envoi :

Serial.write(variableDeTypeChar);

Réception :
char variable = Serial.read();

Exemple, un int = 2 octets,
Envoi :

Serial.write(variableDeTypeInt & 0xFF); // Envoi l'octet de poids faible
Serial.write((variableDeTypeInt >> 8) & 0xFF); // puis l'octet de poids fort

Réception :

int variableRecu = Serial.read() + (Serial.read() << 8);

Exemple, un long = 4 octets,
Envoi :

Serial.write(variableDeTypeLong & 0xFF); // Envoi l'octet de poids faible
Serial.write((variableDeTypeLong >> 8) & 0xFF); 
Serial.write((variableDeTypeLong >> 16) & 0xFF); 
Serial.write((variableDeTypeLong >> 24) & 0xFF); // puis l'octet de poids fort

Réception :

long variableRecu = Serial.read() + (Serial.read() << 8) + (Serial.read() << 16) + (Serial.read() << 24);

Edit: Le plus simple est de faire des fonctions exemple pour le int :

void sendInt(int valeur) {
  Serial.write(valeur & 0xFF);
  Serial.write((valeur >> 8) & 0xFF);
}

int recevInt() {
  while(Serial.available() < 2);
  return Serial.read() + (Serial.read() << 8);
}

Bonjour et MEILLEURS VŒUX A TOUS !!

Merci pour ton aide Skywood.

Ok, çà confirme, ce n’est pas aussi simple de transférer des donnés. Je ne pense pas que les bulles de la nuit en soit la seule explication …

Il faut donc bien que toutes les données soient selon le même format.
Pour info, j’ai une quinzaine de variables à transférer. La plupart sont des "int", et les "long" devraient pouvoir être passées en "int". Mais j’ai deux "double" qui gèrent le PID (librairie ici : Arduino Playground - PIDLibraryConstructor ). Et là, je ne pense pas pouvoir les changer.
A moins qu’il soit possible d’écrire ceci : int valeur_Réduite = double Valeur
Il est également possible que d’autres variables viennent compléter la liste avec le temps.

Donc pour simplifier le traitement pré-envoi, ce qui me semble le plus logique en fonction de ce que tu proposes, serait de toutes les convertir en "double" afin de n’avoir qu’un seul type de traitement. En créant des fonctions.
Mais comment les appelles tu ? Encore un apprentissage pour moi.

Franck

Bubule:
Ok, çà confirme, ce n’est pas aussi simple de transférer des donnés. Je ne pense pas que les bulles de la nuit en soit la seule explication …

C'est pas simple mais ce n'est pas énormément compliqué non plus :wink:

Bubule:
Il faut donc bien que toutes les données soient selon le même format.
Pour info, j’ai une quinzaine de variables à transférer. La plupart sont des "int", et les "long" devraient pouvoir être passées en "int". Mais j’ai deux "double" qui gèrent le PID (librairie ici : http://arduino.cc/playground/Code/PIDLibraryConstructor ). Et là, je ne pense pas pouvoir les changer.
A moins qu’il soit possible d’écrire ceci : int valeur_Réduite = double Valeur
Il est également possible que d’autres variables viennent compléter la liste avec le temps.

Un double est sur 4 octets comme pour un long, regarde sur la référence arduino tu as tout les types de données basique.

Bubule:
Donc pour simplifier le traitement pré-envoi, ce qui me semble le plus logique en fonction de ce que tu proposes, serait de toutes les convertir en "double" afin de n’avoir qu’un seul type de traitement. En créant des fonctions.
Mais comment les appelles tu ? Encore un apprentissage pour moi.

imaginons une fonctions :

void faireQuelqueChose(char variable) {
// ...
}

tu l'appellerai ainsi :

char c = '.'; // variable quelconque pour l'exemple
// ...
faireQuelqueChose(c); // appel de la fonction

Je te conseil de faire un tour sur ce tutoriel :
http://www.siteduzero.com/tutoriel-3-13982-les-fonctions.html

Merci :wink:

Je m'en vais lire tout çà et je reviens.

Hello

Pas mal le tuto ! Les fonction vont bien se tenir avec moi maintenant ! :smiley:

J’ai tenté la mise en application, mais çà ne commence pas bien...
Voici le code :

//Tableau de variable
long tableauDonnees[4]; //Déclare un tableau à x lignes

void setup() {  // DEBUT DE SETUP  
  
  // Initialise la liaison série
  Serial.begin(19200);                // Initialise la liaison série Hard
   delay(50);

Void loop() {

if (topToutesLesSecondes == 1) {   // bit F.Montant toutes les secondes
   	 int i;
	for (i = 0; i < 4; i = i + 1) {
 	 envoiLong(tableauDonnees[i]);
 	 delay(2);
   	   }
     } // Fin de if

// Renseignement Tableau
tableauDonnees[0] = 'D';
tableauDonnees[1] = pos_servo_1;
tableauDonnees[2] = 357;
tableauDonnees[3] = '357';


} // Fin de loop

 
 void envoiLong (long valeur) {
  
  Serial.println(valeur & 0xFF);// Envoi l'octet de poids faible
  Serial.println((valeur >> 8) & 0xFF); 
  Serial.println((valeur >> 16) & 0xFF); 
  Serial.println((valeur >> 24) & 0xFF); // puis l'octet de poids fort
  
}

Je lit bien sur le terminal 4 fois 4 lignes qui correspondent aux 4 envois de 4 octets.
Mais ne sont renseignés que les 2 premiers octets de chaque donnée. Les 2 suivants restent à 0. Je lis :

68 (D en Hexa)
0
0
0
40 (correspond bien à l'angle du servo en °)
0
0
0
101 (??)
1 (??)
0
0
55 (7 en Hexa)
53 (5 en Hexa)
0 ( on devrait trouver 51 (3 en Hexa))
0

C'est où que j'ai déconné ? :.

C'est où que j'ai déconné ?

humm comment dire ...

-> Il manque un } pour setup() dans ton code,
-> topToutesLesSecondes n'est pas déclaré, de même pour pos_servo_1,
-> tableauDonnees[3] = '357'; n'est pas une écriture autorisé, '357' ça n'existe pas (simple quote -> pour 1 caractère) et "357" (double quote -> une chaine de caractères) n'est pas autorisé dans ce cas (pas de conversion possible de char[] vers long).

Je sais pas pourquoi tu veut absolument tous mettre dans un tableau de long !
Fait une fonction par type et envoi les variables "normalement", sans quelle soit dans un tableau, se serait plus intelligent que de vouloir à tout prix stocker des variables de type différent dans un tableau d'un type fixe...

Tu devrait faire un tour ici :
http://www.siteduzero.com/tutoriel-3-14189-apprenez-a-programmer-en-c.html?all=1#chap_14023

et peut être faire un tour du coté des structures :
http://www.siteduzero.com/tutoriel-3-14189-apprenez-a-programmer-en-c.html?all=1#chap_14043

Cette librairie te sera d'une grande aide si tu te tourne vers la solution des structures :

Bonjour

Oui, en fait j’ai voulu ne recopier que les parties importantes de mon programme (celles relatives au transfert). En oubliant de recopier ‘}’ et de montrer les déclarations de variables (Celles-ci sont déclarées en global en début de sketch.

Pour le type de variables du tableau de l’exemple, j’ai mis différents types de variables, car je souhaitais comprendre comment s’envoyait des données, et à quoi elles ressemblaient à l’arrivée.
C’est là que j’ai remarqué que seuls les 2 premiers octets passaient. Je ne comprends pas pourquoi la valeur 123 (donne 101 et 1). J’ai donc tenté d’envoyer ensuite d’autres formats (comme char 123). Mais au final, je pense n’envoyer que des doubles.

Il me semblait plus judicieux d’envoyer les données par paquets. Et donc renseigner les champs du tableau en fin de programme en fonction de l’évolution des variables à transférer. Puis d'envoyer tout le tableau. Ce qui m’impose de toutes les avoir au même format (double).
Je m’en vais lire tes liens afin d’être un peu plus calé, et très certainement revoir mes copies en fonction. Mais les vacances sont finies, et cela va me prendre un peu plus de temps.
Je reviens ensuite !

Bon courage également à ceux qui reprennent le taf…

Franck

Bubule:
Oui, en fait j’ai voulu ne recopier que les parties importantes de mon programme (celles relatives au transfert). En oubliant de recopier ‘}’ et de montrer les déclarations de variables (Celles-ci sont déclarées en global en début de sketch.

Je me doutai bien qu'il y avait une histoire dans ce gout là, mais le mieux c'est de tout envoyer pour avoir une vision d'ensemble du code.

Bubule:
Pour le type de variables du tableau de l’exemple, j’ai mis différents types de variables, car je souhaitais comprendre comment s’envoyait des données, et à quoi elles ressemblaient à l’arrivée.
C’est là que j’ai remarqué que seuls les 2 premiers octets passaient. Je ne comprends pas pourquoi la valeur 123 (donne 101 et 1). J’ai donc tenté d’envoyer ensuite d’autres formats (comme char 123). Mais au final, je pense n’envoyer que des doubles.

Tu n'envoi que des doubles car ton tableau est constituer de double ...
Pour le format en entrée et en sortie c'est simple, en entrée tu as des octets, en sortie tu a des octets, octets qui mis bout à bout donne un type.
C'est pas compliqué, tout ce qui peut être stocker dans la ram peut être transformer en une suite d'octet, que ce soit une variable, une structure, etc ...

Bubule:
Il me semblait plus judicieux d’envoyer les données par paquets. Et donc renseigner les champs du tableau en fin de programme en fonction de l’évolution des variables à transférer. Puis d'envoyer tout le tableau. Ce qui m’impose de toutes les avoir au même format (double).

Si tu veut faire un envoi par paquets de variables avec des types différents ce n'est pas un tableau que tu doit utiliser mais une structure, les tableaux ne sont utiles que pour stocker des valeurs d'un seul et unique type.

Pour reprendre au début, il y a probablement une infinité de moyens de transférer ces données.

Si on considère que le duemilanove est déporté (ou "esclave", etc), on peut partir du postulat que c'est mieux de concentrer l'intelligence sur le MEGA qui est toujours connecté au PC. Donc,
tu peux allègrement simplifier en utilisant les librairies standard sur le duemilanove, et envoyer Serial.println( tavariable, DEC ou autre); (avec un serial.print ( "tonetiquette1 : ") avant ) puis laisser le MEGA "se débrouiller". Remplacer evidemment tavariable et tonetiquette par des mots plus adaptés.

Plus fouillé, tu peux utiliser la librairie firmata (utilise des message pseudo MIDI) ou bien le "aProtocol" qui utilise des strings de 12 caractères. Plus compliqué au début, mais plus souple pour les nombreuses additions que tu ne manqueras pas de faire par la suite...

En fait, ce n'est pas parce que tu définis un tableau de long que tout ce que tu y mets en devient un, la conversion de type suit des règles pas toujours évidentes. Ton premier exemple est un Char, le deuxième un byte ou int, le troisième un int, etc. et ... un tableau n'est qu' un pointeur ! Donc ton int 357 est envoyé comme 1x256 + 101 , logique. Ton '357' n'est en effet pas correct, je ne sais pas pourquoi on retrouve 2 chars (probablement une conversion typecast vers int ?). Si tu utilise des floats, ils ont la même longueur que les long (4 bytes) mais un tout autre format (mantisse exposant)

Bonsoir à tous

Je suis en train de reprendre les bases sur le site du zéro que m’a donné skywood. Et j’ai du taf vu mon niveau XD. Mais c’est tellement intéressant que je m’y prends au jeu, et ai repris la lecture au tout début. :wink:

Je comprends qu’il me faudrait en dire plus, mais cela risque de perdre un peu le sens du topique. Cependant, je serais prêt à vous transférer tout le sketch (17K) afin que vous y jetiez un œil d’expert. :wink: Surtout que j’ai parfois quelques plantages ( http://arduino.cc/forum/index.php/topic,82815.0.html ).

Pour expliquer ma démarche et mon installation. J’ai reçu ma Duemilanove il y a un an, avec laquelle j’ai commencé à piloter 2 servomoteurs (accessoires d‘un aquarium récifal de 500L). Mon niveau de programmation était presque nul (qui a dit qu‘il l‘était encore ? ]:D). Et puis avec le temps, je me suis dit que je pouvais adjoindre d’autres fonctionnalités à la carte. Mesures, régulations, pilotage de pompes… Tout cela est maintenant fonctionnel.
Et ensuite qu’il serait bien de pouvoir lire et modifier des paramètres avec un afficheur tactile ( http://arduino.cc/forum/index.php/topic,78741.0.html ) Et là les problèmes commencent (ou sont mis en évidence).

La Duemilanove n’est plus suffisante (Entrées/sorties) et sera plus tard remplacée par la Mega. Mais la Duemilanove est en place et gère déjà pas mal de choses que je ne veux pas arrêter tant que je n’ai pas suffisamment avancé sur ce projet. Les plantages de la Duemilanove m’ont fait réfléchir à la nécessité de redondance (il y a un gros risque pour la vie des occupants du bac si une sortie vient à dérailler dans une mauvaise configuration).
Donc à terme, la Mega gèrera la partie opérative (gestion du bac), et dialoguera avec la Duemilanove pour envoyer ses données, et recevra les nouvelles consignes de la Demilanove par une liaison série.
La Duemilanove effectuera une vérification du bon fonctionnement de la Mega (capteurs en double, vérification d’un top émis par la Mega toutes les 5 secondes, …). Et effectuera les liaison avec la dalle tactile (4D en mode GFX) et la Mega par des liaisons softserial, puisque la Duemilanove n’a qu’un seul port série, qui sera très certainement réservé pour le PC

Mais il me faut débuter, et c’est pour cela que pour le moment je tente l’envoi de données par les liaisons série ‘hard’.
La première étape était que la Duemilanove en place, envoie ses données à la Mega. Et que je puisse retrouver ces valeurs dans la Mega grâce au PC.
Comme déjà là je ne m’en sortais pas, j’ai tenté d’envoyer une série de variables d’un tableau de la Mega au terminal du PC. Et me voilà.
Mais je ne désespère pas. Je réussirais avec votre aide, et j’en sortirais encore plus riche de connaissances.

Dès que j’ai un moment, je tente l’envoi de plusieurs variables ’long’ de la Mega vers le terminal. C’est pas encore gagné.

Voilà, j’ai été un peu long (pas char) mais si cela vous inspire d’autres pistes, je suis preneur.

Franck

Bubule:
Je suis en train de reprendre les bases sur le site du zéro que m’a donné skywood. Et j’ai du taf vu mon niveau XD. Mais c’est tellement intéressant que je m’y prends au jeu, et ai repris la lecture au tout début. :wink:

Tu peut passer outre les parties "pc" (SDL, etc ...), quoi qu'il en soit c'est une bonne philosophie de vouloir progresser (et mieux si c'est en s'amusant :P) :wink:

Bubule:
Je comprends qu’il me faudrait en dire plus, mais cela risque de perdre un peu le sens du topique. Cependant, je serais prêt à vous transférer tout le sketch (17K) afin que vous y jetiez un œil d’expert. :wink: Surtout que j’ai parfois quelques plantages ( http://arduino.cc/forum/index.php/topic,82815.0.html ).

Tu peut toujours le joindre en pièce jointe on y jettera un oeil, si ça ce trouve tes bug sont de simple erreurs toute bête (plus c'est bête plus c'est difficile de les détecter :stuck_out_tongue_closed_eyes:, qui n'as jamais copier/coller d'un morceau de code avant de se rendre compte d'une petite erreur sans modifié le morceau copié hein ;))

Bubule:
La Duemilanove n’est plus suffisante (Entrées/sorties) et sera plus tard remplacée par la Mega. Mais la Duemilanove est en place et gère déjà pas mal de choses que je ne veux pas arrêter tant que je n’ai pas suffisamment avancé sur ce projet. Les plantages de la Duemilanove m’ont fait réfléchir à la nécessité de redondance (il y a un gros risque pour la vie des occupants du bac si une sortie vient à dérailler dans une mauvaise configuration).
Donc à terme, la Mega gèrera la partie opérative (gestion du bac), et dialoguera avec la Duemilanove pour envoyer ses données, et recevra les nouvelles consignes de la Demilanove par une liaison série.

Si c'est purement un probléme de nombre d'entrées sortie regarde du coté du PCF8575 ou PCF8574, si ça ce trouve tu doit pouvoir garder ton systéme actuelle moyenne des modifications minim de ton code.

Bubule:
La Duemilanove effectuera une vérification du bon fonctionnement de la Mega (capteurs en double, vérification d’un top émis par la Mega toutes les 5 secondes, …). Et effectuera les liaison avec la dalle tactile (4D en mode GFX) et la Mega par des liaisons softserial, puisque la Duemilanove n’a qu’un seul port série, qui sera très certainement réservé pour le PC

Si tu veut tu peut faire un systéme de "failover", en gros si la mega plante prévoit un systéme de "soft reset" pour tenter de résoudre le probléme au plus vite.
C'est valable dans les deux sens, si la mega ne répond pas à ton "ping" par un "pong" toute les 5sec alors déclenche le "soft reset" de même si la duemilanove ne génère pas de "ping" aprés 10sec par exemple déclenche un "soft reset" coté duemilanove.
Bon évidement fait déja ton code de base, et vérifie chaque fonction pour s'assurer de son bon fonctionnement. Une fois que tout sera ok tu pourrait faire ton systéme de failover.

Me revoilà après quelques lectures. Je n’ai pas encore tout ingurgité. J’espère que vous me pardonnerez :blush:.
Cela prend du temps…

Mais j’ai tout de même essayé de progresser avec sur les bases données par Skywood un peu plus haut.

Cela fonctionne avec des variables int, mais pas avec des long.

Pour commencer, j’ai mis ce code dans la carte émettrice (Duemilanove), :

void loop() {

    if (topToutesLesSecondes ==1) {     // (Je vous fais abstraction de la déclaration et de la création du top seconde. 
                                         //Il passe à ‘1’ toutes les secondes pendant un cycle loop).

     envoiInt(1534);  // envoi de la valeur 1534 (que j’imagine être un entier décimal) dans la fonction « envoiInt » ci-dessous.
             }
     }  // Toutes les secondes, la valeur 1534 est ainsi envoyée une fois à la fonction envoiInt

 void envoiInt (int valeur) {  
      Serial.write(valeur & 0xFF);            // Envoi l'octet de poids faible
      Serial.write((valeur >> 8) & 0xFF); // puis l'octet de poids fort
   }

Sur le terminal raccordé à la carte émettrice on peux lire, toutes les secondes :
254
5

La valeur 1534 correspond en binaire à 000000101 11111110
Soit 11111110 pour le premier octet (= 254) et 00000101 pour le second octet (= 5)
Cela me semble donc correct

Dans la carte réceptrice (Mega) j’ai mis le code :

void setup()
{
  Serial.begin(19200);
  Serial1.begin(19200);
  
  digitalWrite(18, HIGH);  // Pull-up, nécessaire pour avoir une liaison série fiable
  digitalWrite(19, HIGH);  // Sans cela, je perdais des données
}


void loop() {               
     if (Serial1.available()) {
         int ValEntree = Serial1.read();
          Serial.print(ValEntree); 
       }
delay(50);
}

Je retrouve sur le terminal relié à la carte réceptrice, toutes les secondes, la réception de 2545 (254, puis 5).

Cela prouve que je reçois bien et correctement les données envoyées sur le port sérial1 de la Méga.
1er octet : 254 (3 char (2, 5 et 4), second octet : 5 (1 seul char).

Je rajoute entre le setup et le loop la fonction

 int recevInt() {
   while (Serial1.available() <2 ); 
     int donnee = (Serial1.read() + (Serial1.read() << 8 ));
    return(donnee);
  }

Je remplace ce qu’il y a dans le loop par :

 int variable = recevInt();
   if (topToutesLesSecondes ==1) {     // je vous fais abstraction du traitement du top Toutes les secondes
               Serial.print("Variable : ");
               Serial.println(variable); 
          }

Cela fonctionne, je reçois bien sur le terminal la valeur 1534. J’ai déjà fais un pas.

Je modifie maintenant l’ensemble pour passer aux long. Et là çà se corse dès que j‘envoi des valeurs qui dépassent les 32768 (plus de 2 octets) :

Par exemple, je modifie la variable à envoyer par une valeur supérieure à 65535 :
Dans le loop, je mets la valeur 67534, qui sera émis toujours une fois toutes les secondes.
envoiInt(67534);

Partie émettrice je modifie la fonction en y rajoutant le traitement des 2 octets supplémentaires :

 void envoiInt (long valeur) {  
      Serial.write(valeur & 0xFF);          // Envoi l'octet de poids faible
      Serial.write((valeur >> 8) & 0xFF);       
      Serial.write((valeur >> 16) & 0xFF); 
      Serial.write((valeur >> 24) & 0xFF);  // puis l'octet de poids fort     
  } // FIN de la fonction

Je retrouve bien sur le port série de l’émettrice les valeurs 206, 7, 1, 0 qui correspondent bien aux 4 octets qui représentent la valeur 67534.

Dans la carte réceptrice je modifie également la fonction ainsi (je pense que c’est là que se trouve le problème):

long recevLong() {    
    while (Serial1.available() < 4 );  
     long recu = (Serial1.read()  + (Serial1.read() << 8 ) + (Serial1.read() << 16) + (Serial1.read() << 24));
       return (recu);
  }

Et dans le loop

 long variable = recevLong();

Et cette fois la variable prend la valeur 1998, ce qui correspond aux deux octets 206,7. Les 2 octets suivants ne passent pas.

Une idée. Je cherche depuis quelques jours…

Franck

Bubule:

long recevLong() {    

while (Serial1.available() < 4 ); 
     long recu = (Serial1.read()  + (Serial1.read() << 8 ) + (Serial1.read() << 16) + (Serial1.read() << 24));
       return (recu);
  }



Et cette fois la variable prend la valeur 1998, ce qui correspond aux deux octets 206,7. Les 2 octets suivants ne passent pas.

essaye :

long recevLong() {    
  while (Serial1.available() < 4 );  
    long recu = (Serial1.read()  | (Serial1.read() << 8 ) | ((unsigned long)Serial1.read() << 16) | ((unsigned long)Serial1.read() << 24));
    return (recu);
}

Je peut pas tester mon morceau de code tout de suite donc à prendre avec des pincettes :wink:
(eeepc, wifi, cours en amphi, tout ça :grin:)

Bonjour

Bon, j’ai testé rapidement hier soir. Ça a l’air de fonctionner XD :D. La déclaration (unsigned long) semble être la parade. Le ‘|’ semble également pouvoir être remplacé par le ‘+’. Je testerais avec plus de valeurs lorsque j’aurais un peu plus de disponibilité également.

C’est quand même cool d’avoir des dieux de la programmation… :grin: ;)(Je n’aurais jamais trouvé :fearful:).

Merci !

Les étapes suivantes :

  • Transfert de plusieurs valeurs par le biais de tableaux.
  • Passage du port Uart 0/1 aux ports ‘softserial’
  • Déclenchement de l’envoi sur quel critère ? (variation d’une variable du tableau, top horloge, réponse à une interruption, …)
  • Envoi de toutes les données du tableau, ou juste celle modifiée ?
  • Augmentation de la vitesse de transfert.

A bientôt
Franck

Bubule:
Bon, j’ai testé rapidement hier soir. Ça a l’air de fonctionner XD :D. La déclaration (unsigned long) semble être la parade. Le ‘|’ semble également pouvoir être remplacé par le ‘+’. Je testerais avec plus de valeurs lorsque j’aurais un peu plus de disponibilité également.

Le + et le | (ou bits à bits) ont le même effet dans le cas d'un calcul "bitwise", mais dans le doute comme je pouvais tester pas mon code j'ai utilisé le | qui marche dans tout les cas.

Bubule:
C’est quand même cool d’avoir des dieux de la programmation… :grin: ;)(Je n’aurais jamais trouvé :fearful:).

"Dieux de la programmation" :grin:

Bubule:
Les étapes suivantes :

  • Transfert de plusieurs valeurs par le biais de tableaux.
  • Passage du port Uart 0/1 aux ports ‘softserial’
  • Déclenchement de l’envoi sur quel critère ? (variation d’une variable du tableau, top horloge, réponse à une interruption, …)
  • Envoi de toutes les données du tableau, ou juste celle modifiée ?
  • Augmentation de la vitesse de transfert.
  • boucle for, tableaux
  • lib NewSoftSerial
  • (for/if, lib MsTimer, attachInterrupt())
  • transfert complet -> simple et rapide, transfert partiel -> envoi d'une adresse, longueur du paquet, ... -> compliqué, mais pratique lors de l'envoi de grosse quantité de données.

skywodd:

  • lib NewSoftSerial

Il me semble avoir lu que la version V1.0 intègre maintenant les fonctionnalités de la NewSoftSerial sous la dénomination de la Softserial.

Bubule:
Il me semble avoir lu que la version V1.0 intègre maintenant les fonctionnalités de la NewSoftSerial sous la dénomination de la Softserial.

Ouaip en faite ils ont juste renommé NewSoftSerial en SoftSerial ^^

Me revoici :slight_smile:

Ca avance !
Mais il y a au moins un hic :

Je n’arrive pas à chopper la première valeur (tableauDonnée[0]).
Sinon, toutes les valeurs (tableauDonnée[1 à 4]) sont quant à elles correctes.

A l’émission j’ai mis dans le loop :

// Renseignement Tableau
  tableauDonnees[0] = 999999999;    // valeur arbitraire signalant le début de la transmission
  tableauDonnees[1] = pos_servo_1;  // Variable oscillant entre 10 et 130
  tableauDonnees[2] = millis();         
  tableauDonnees[3] = pH*100;       // Variable (double) multipliée par 100 pour chopper 2 décimales
  tableauDonnees[4] = 111111111;    // valeur arbitraire signalant la fin de la transmission

// Toutes les secondes :
 int e;
    for (e = 0; e < 5 ; e = e + 1) {
      envoiInt(tableauDonnees[e]);
      }

  Fin de loop


 void envoiInt (long valeur) {
  
      Serial.write(valeur & 0xFF);          // Envoi l'octet de poids faible
      Serial.write((valeur >> 8) & 0xFF);       
      Serial.write((valeur >> 16) & 0xFF); 
      Serial.write((valeur >> 24) & 0xFF);  // puis l'octet de poids fort

Dans la carte réceptrice :

// Déclaration des variables et constantes horloge
  unsigned long refTemps;      // Mémoire de l'horloge millis pour horloge
  int topsec = 0;              // Impulsion topsec toutes les secondes 
  int topmin = 0;              // Impulsion topmin toutes les minutes

 // Permet de remettre l'horloge à l'heure sur init
  int heure = 14;              // Heures de l'horloge >>>> Permet de remettre l'horloge à l'heure sur init
  int minute = 35;             // Minutes de l'horloge >>> Permet de remettre l'horloge à l'heure sur init
  int seconde = 0;             // Secondes de l'horloge
 
  //Tableau de variable
  long tableauDonnees[5] = {0};         //Déclare un tableau à 5 lignes
  
    // Valeurs du tableau de variable qui doivent être reçues de la carte emettrice
  long var0;          // Doit recevoir la valeur 999999999 (valeur fixe)
  long milli;         // Doit recevoir la valeur millis() de la carte emettrice (variable)
  long posServo1;     // Doit recevoir la position du servo 1 (10 à 130) (variable)
  double pH = 0.00;   // Doit recevoir la mesure de pH (variable)
  long var4;          // Doit recevoir la valeur 111111111 (valeur fixe)
    
  
void setup() {
  Serial.begin(19200);
  Serial1.begin(19200);
  
// Pull-up de la liaison série
  digitalWrite(18, HIGH);  
  digitalWrite(19, HIGH);
  
} //FIN de SETUP


  long recevLong() {    
    while (Serial1.available() < 4 );  
      long recu = ((unsigned long)Serial1.read() | ((unsigned long)Serial1.read() << 8 ) | ((unsigned long)Serial1.read() << 16) | ((unsigned long)Serial1.read() << 24));
     return (recu);
    }


void loop() {              
   
    if (recevLong()) {  
       int r;       
       for (r = 0; r < 4; r = r + 1){       // Passer à  'r < 5' ne permet pas de renseigner le champ [0]. Et les valeurs suivantes sont erronées.
         tableauDonnees[r + 1] = recevLong(); // Et du coup, afin de pouvoir renseigner les bonnes cases du tableau, je dois passer à r + 1
          }
      }
    
     var0 =      tableauDonnees[0] ;
     posServo1 = tableauDonnees[1] ;
     milli  =    tableauDonnees[2] ;
     pH =        tableauDonnees[3] / 100.00;
     var4 =      tableauDonnees[4];
     
          // LIAISON SERIE POUR TESTS
     if (topsec) {  
        Serial.println(var0);
        Serial.println(posServo1);
        Serial.println(milli);
        Serial.println(pH);
        Serial.println(var4);
        Serial.println("fin"); 
        Serial.println();     
    }
       
  
   topsec = 0; 
   topmin = 0;

      // HORLOGE 
      if (millis() >= refTemps){
         refTemps += 1000;
         seconde++;           // Incrémentation des secondes
         topsec = 1;          // Monte le bit topsec toutes les secondes
        if (seconde >= 60) {  // à chaque 60 secondes
            minute++ ;        // Incrémentation des minutes
            seconde = 0; 
            topmin = 1;       // Monte le bit topmin toutes les minutes
          if (minute >= 60) {
              heure++ ;       // Incrémentation des heures
              minute = 0 ;
            if (heure >=24) {
                  heure = 0 ; // réinitialise l'horloge toutes les 24h
               }
              }
             }
            }
                
 /*     
     // POUR TEST réception Port Serial1 et transfert sur port Uart           
    if (Serial1.available()) {
       long ValEntree = Serial1.read();
       Serial.print(ValEntree); 
      }

 */
       
} // FIN de LOOP

Puis-je mieux faire ?

Tu as fait une erreur dans la partie réception :

if (recevLong()) {  
  int r;       
  for (r = 0; r < 4; r = r + 1){       // Passer à  'r < 5' ne permet pas de renseigner le champ [0]. Et les valeurs suivantes sont erronées.
    tableauDonnees[r + 1] = recevLong(); // Et du coup, afin de pouvoir renseigner les bonnes cases du tableau, je dois passer à r + 1
  }
}

Le if(recevLong()) te "mange" le 1er long reçu donc par la suite tout ta réception est faussé :wink:

if (tableauDonnees[0] = recevLong()) {     
  for (int r = 1; r < 5; r++){ 
    tableauDonnees[r] = recevLong();
  }
}