Communication RS232 (programmation)

Bonjour à tous,

J'ai déjà posté pas mal de fois sur ce sujet alors j'ai jugé bon de créer un nouveau topic pour la partie programmation.

Niveau hardware : pas de problème, mes deux Uno sont interfacés via deux MAX202

Je souhaite envoyé :

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

void loop()
{
  delay(500);
  Serial.write('D');
  Serial.write(1);
  Serial.write(64);
  Serial.write(128);
  Serial.write(255);
}

Le caractère D me permet de détecter que j'envoie bien les commandes de PWM pour mes moteurs : il me sert de "top départ". J'envoie donc ensuite 4 commandes de PWM sur la liaison série et c'est ces 4 valeurs que je souhaite récupérer.

J'ai donc utilisé le code ci dessous pour les récupérer :

char message[4];
int n_octet = 5;

void setup()
{
  Serial.begin(9600);
  //pinMode(13, OUTPUT);
}

void loop()
{
  if (Serial.available()>0)
  {
    if(Serial.read()!='D')
    {
      delay(50);
    }
    
    else
    {
      for(int n=1; n<n_octet; n++)
      {
        message[n]=Serial.read();
        Serial.print(message[n]);
      }
    }
  }
}

Malheureusement, je visualise sur le port série : FF FF FF 01 au lieu du 01 40 80 FF attendu...
Je ne comprends vraiment pas pourquoi ...

bonjour,

Vérifie le bon fonctionnement de ton montage à base de MAX202 en réalisant une "boucle locale".
Pour ce faire relie le Tx au Rx d'un côté et regarde si ce que tu envoi de l'autre coté te revient correctement.

Ps: Tu as bien croisé Rx et Tx entre tes deux UNO ?
Si tu ne croise pas tu auras Tx -> Tx et Rx -> Rx ce qui ne marchera pas.

La liaison est opérationnelle... j'ai l'impression que c'est un problème de code...

Voila ce qu'à donné ma boucle :

mon code :

char message[4];

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

void loop()
{
  delay(500);
  Serial.write('D');
  Serial.write(1);
  Serial.write(64);
  Serial.write(128);
  Serial.write(255);
  
  if (Serial.available() > 0)
  {
   for(int n=0; n<5; n++)
      {
        message[n]=Serial.read();
        Serial.print(message[n]);
      }
  }
  Serial.flush();
}

Et les résultats obtenus avec XCTU en PJ.

Ce que je vois :

La trame envoyée apparaît bien correctement : 44 01 40 80 FF
La trame reçue est bien identique à la trame envoyée...

ds.bmp (800 KB)

Le problème qu'il y a c'est que le Serial.read "rate" des octets.

Je joins deux screens pour argumenter mon propos :

Le premier [COM11] correspond aux trames envoyées
Le second [COM13] correspond aux trames reçues (puis réaffichée)

Je joins aussi les deux codes utilisés :

Code écriture :

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

void loop()
{
  delay(500);
  Serial.write('D');
  Serial.write(1);
  Serial.write(64);
  Serial.write(128);
  Serial.write(255);
}

Code lecture :

char message[4];
int n_octet = 5;

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

void loop()
{ 
  if (Serial.available()>0)
  {
    if(Serial.read()!='D')
    {
     delay(50);
    }
    
    else
    {
      for(int n=0; n<n_octet; n++)
      {
        message[n]=Serial.read();
        Serial.print(message[n]);
      }
    }
  }
  Serial.flush();
}

fg.bmp (1.55 MB)

Bonjour,

Tu doit ajouter une boucle d'attente avant de lire un octet :wink:

// ...
while(Serial.available() < 1);
message[n]=Serial.read();
// ...

Bizarrement ça marche beaucoup mieux... :wink:

Merci (encore) Skywodd !

Encore quelques ajustements avec mes deux programmes complets mais ça devrait le faire... j'ai une bonne base maintenant !

rhum187:
Bizarrement ça marche beaucoup mieux... :wink:

Si tu savais le temps que j'ai mis avant de trouver cette astuce au début ...
Le truc bête par excellence dont la doc arduino ne parle pas :stuck_out_tongue_closed_eyes:

J'en ai vraiment marre... je pensais avoir terminer mon code avec tes précieux conseils et voilà que je viens de m'apercevoir que la PWM des pins 10,9 et la PWM des pins 6,5 ne sont pas cadencés de manière identique... :confused:

Quand j'observe au scope j'ai une fréquence de environ 490Hz pour les pins 10 et 9 et j'ai le double pour les 6 et 5.

Alors il me vient deux quetions :

1/ Est-ce que ça sera la même chose sur la Nano (car je développe mon code sur une Uno)
2/ Est-ce que c'est possible de la changer facilement ? J'ai regardé un peu... :fearful:

rhum187:
1/ Est-ce que ça sera la même chose sur la Nano (car je développe mon code sur une Uno)

Oui c'est une différence logiciel liée au "core arduino", pas à la carte.

rhum187:
2/ Est-ce que c'est possible de la changer facilement ? J'ai regardé un peu... :fearful:

Oui et non

Regarde ici :
http://arduino.cc/playground/Code/PwmFrequency

Ok,

ce qui veut dire que je ne peux ni faire tomber les pins 5 et 6 à 490Hz ni monter les pins 9 et 10 à 970Hz car il manque le case 128

rhum187:
ce qui veut dire que je ne peux ni faire tomber les pins 5 et 6 à 490Hz ni monter les pins 9 et 10 à 970Hz car il manque le case 128

C'est vraiment un point critique que tes PWM est une fréquence identique ?

Ben je me posais la question justement...

Je pense que le composant auquel je les envoie s'en moque un peu...

EDIT : C'est la ds de mon pont en H : http://www.ti.com/lit/ds/symlink/drv8432.pdf

Yep!

Si çà peut aider, tu peux piloter autant de servos que tu veux avec un seul PWM et sur n'importe quelle pinoche.

Je viens de plus ou moins faire le tour ce week-end de mes servos :wink:

@+

Zoroastre.

Merci zoroastre,

J'ai regardé ton topic avec beaucoup d'attention et ça pourra éventuellement m'aider :wink:

Je viens de rentrer dans la 4ème dimensions... ^^

Non, pas encore, malheureusement, il y a un problème que je n'arrive pas à résoudre.

Je fais communiquer deux Arduino. Avec le premier j'envoie ça :

  Serial.print('M'); // Permet l'identification des commandes moteurs par le programme robot
  Serial.write(ZONE); // Permet le débogage des conditions à l'aide du VI
  Serial.write((int)PWM1);
  Serial.write((int)PWM2);
  Serial.write((int)PWM3);
  Serial.write((int)PWM4);

et avec le deuxième je veux lire la valeur des PWM donc j'ai écrit (avec l'aide de Skywodd ;)) :

byte PWM_MOT[4]; // Tableau de 6 octets
int n_octet = 4;
int pin_PWM_A = 10;
int pin_PWM_B = 9;
int pin_PWM_C = 6;
int pin_PWM_D = 5;

void setup()
{
  Serial.begin(9600); // Paramétrage de la vitesse de la liaison série
}

/*********************** DEBUT DE LA BOUCLE PRINCIPALE ********************************************/
void loop()
{ 
  if(Serial.available()>0)
  {
    if(Serial.read()!='M')
    {
     delay(50);
    }
    else
    {
      for(int n=1; n<=n_octet; n++)
      {
        while(Serial.available() < 1);
        PWM_MOT[n]=Serial.read();
      }
    }
    //analogWrite(pin_PWM_A, PWM_MOT[1]);
    //analogWrite(pin_PWM_B, PWM_MOT[2]);
    //analogWrite(pin_PWM_C, PWM_MOT[3]);
    //analogWrite(pin_PWM_D, PWM_MOT[4]);
    
    //Serial.print(PWM_MOT[0]);
    Serial.print(PWM_MOT[1]);
    Serial.print(PWM_MOT[2]);
    Serial.print(PWM_MOT[3]);
    Serial.print(PWM_MOT[4]);
    //Serial.print(PWM_MOT[5]);
    
    Serial.println();
    
  }
  else
  {
    analogWrite(pin_PWM_A, 0);
    analogWrite(pin_PWM_B, 0);
    analogWrite(pin_PWM_C, 0);
    analogWrite(pin_PWM_D, 0);
  }
  
  Serial.flush();
  delay(50);
}

Et je vous joins les deux screen XCTU qui m'ont permis de constater que il y avait +1 sur la PWM4 alors que je n'ai rien fait pour... enfin je pense
COM11 : Arduino qui envoit les infos
COM13 : Arduino qui reçoit et qui les (ré)affichent

rhum187:
Ben je me posais la question justement...

Je pense que le composant auquel je les envoie s'en moque un peu...

Ça n'as aucune réelle importance, dans le pire des cas cela ne joue que sur le sifflement / grésillement résiduelle du moteur en sortie (si tu utilise un moteur).

Oui je pense aussi.

Par contre ma différence de 1, même si ce n'est que 1 me perturbe un peu plus...

rhum187:
Par contre ma différence de 1, même si ce n'est que 1 me perturbe un peu plus...

Rooo! Je sort le fusil et les cartouches si tu ne vois pas tes erreurs :wink:

Erreur 1 :
Prototype :

Serial.write(uint8_t);

Ton code :

Serial.write((int)PWM4);

Note : uint8_t = 1 octet non signé (0 ~ 255), int = 2 octets signé (-32767 ~ 32767)

--

Erreur 2 :
Déclaration :

byte PWM_MOT[4]; // Tableau de 6 octets

(hummm 6 tu est sûr ;))

Ton code ensuite :

//Serial.print(PWM_MOT[0]);
    Serial.print(PWM_MOT[1]); // <-
    Serial.print(PWM_MOT[2]);
    Serial.print(PWM_MOT[3]);
    Serial.print(PWM_MOT[4]); // <- 
    //Serial.print(PWM_MOT[5]);

Note : en C/C++ les tableaux commencent à 0 et se terminent à taille_max - 1, exemple int[2] -> int[0], int[1]

--

Erreur 3 :
Déclaration :

byte PWM_MOT[4];
int n_octet = 4;

Ton code :

for(int n=1; n<=n_octet; n++) // -> n = 1, n = 2, n = 3, n = 4
{
  while(Serial.available() < 1);
  PWM_MOT[n]=Serial.read(); // <- 
}

Voir note plus haut.

Erreur 4 :

Tu envois 6 octets mais tu en lit seulement 4 (+ 1 pour le if) :wink:

--

Correction :

Envoi :

Serial.write((uint8_t)'M'); // Permet l'identification des commandes moteurs par le programme robot
Serial.write((uint8_t)ZONE); // Permet le débogage des conditions à l'aide du VI
Serial.write((uint8_t)PWM1);
Serial.write((uint8_t)PWM2);
Serial.write((uint8_t)PWM3);
Serial.write((uint8_t)PWM4);

Réception :

const byte NB_OCTETS = 5;
const byte PIN_PWM_A = 10;
const byte PIN_PWM_B = 9;
const byte PIN_PWM_C = 6;
const byte PIN_PWM_D = 5;

byte PWM_MOT[NB_OCTETS];

void setup() {
  Serial.begin(9600); // Paramétrage de la vitesse de la liaison série
}

/*********************** DEBUT DE LA BOUCLE PRINCIPALE ********************************************/
void loop() { 
  
  if(Serial.available() > 0) {
    
    if(Serial.read() != 'M') {
      delay(50);
    } 
    else {

      for(int n = 0; n < NB_OCTETS; ++n) {
        while(Serial.available() < 1);
        PWM_MOT[n] = Serial.read();
      }

      //analogWrite(PIN_PWM_A, PWM_MOT[1]);
      //analogWrite(PIN_PWM_B, PWM_MOT[2]);
      //analogWrite(PIN_PWM_C, PWM_MOT[3]);
      //analogWrite(PIN_PWM_D, PWM_MOT[4]);

      Serial.print(PWM_MOT[0]);
      Serial.print(PWM_MOT[1]);
      Serial.print(PWM_MOT[2]);
      Serial.print(PWM_MOT[3]);
      Serial.print(PWM_MOT[4]);
      Serial.println();
    } 
  } 
  else {
    
    analogWrite(PIN_PWM_A, 0);
    analogWrite(PIN_PWM_B, 0);
    analogWrite(PIN_PWM_C, 0);
    analogWrite(PIN_PWM_D, 0);
  }

  // Serial.flush(); // Pas de flush() quand on ne sait pas ce que ça signifie ;)
  delay(50);
}

Pas de flush() quand on ne sait pas ce que ça signifie :wink:

Heu, pour moi je vidais le buffer de lecture à chaque fois que j'ai terminé mais je me suis rendu compte que je mettre ou pas n'avais aucun effet...

Ca a du te faire pas mal de boulot alors merci pour ton temps je regarde ça et je te fais un retour avant 19h (si mon chef me sort pas une réunion surprise du chapeau...)