Envoie String de 50 caractères entre VB.NET et Arduino

Bonjour,

Je travaille sur une interface entre VB.NET 2010 expresse et un Arduino uno.
J’utilise le port série.

#ifdef ARDUINO2PC

#define LONGUEUR_MSG_MAX   55
#define RETOUR_CHARRIOT    0x0D /* CR (code ASCII) */
#define PASSAGE_LIGNE      0x0A /* LF (code ASCII) */
#define BACK_SPACE         0x08
char Message[LONGUEUR_MSG_MAX + 1];
int pos = 0;

void readSerialFromVB()/* merci a LOUSSOUARN Philippe pour ce code */
{
  if( MsgDisponible() >= 0) //MsgDisponible() retourne la longueur du message recu; le message est disponible dans Message
  {
    //Serial << F("Recu: ") << Message << endl;
    pos = atoi(Message); //conversion Message ASCII vers Entier (ATOI= Ascii TO Integer)
    if( (pos >= 0) && (pos <= 180))//reception curseur 'servos'
    {        
      if(pos<=1) {pos=2;} //Servo making noise at 0 and 1. Need to be at least 2.
      ServoMoteur1[NORMAL].write(pos);
      ServoMoteur2[NORMAL].write(pos);
      Serial << F("Pos:  ") << pos << endl;
    }
    else if( (pos >= 181) && (pos <= 360))//reception curseur 'auxiliaire'
    {
      if(pos<=181) {pos=182;} //Aux Servo making noise at 0 and 1. Need to be at least 2.
//      ServoMoteur1[NORMAL].write(posAux - 180);
//      ServoMoteur2[NORMAL].write(posAux - 180);
      Serial << F("PosAux:  ") << pos << endl;      
    }
    else if(pos == 361)//reception bouton 'reset'
    {  
      software_Reboot();
      Serial << F("Reset:  ") << pos << endl;      
    } 
    else if(pos == 362)//reception bouton 'auto'
    { 
      modeServosTest();
      Serial << F("ServosTest:  ") << pos << endl;      
    } 
    else if(pos == 363)//envoie settings au port serie
    { 
      sendConfigToSerial();
      Serial << F("Envoie Config:  ") << pos << endl;      
    }
    else if(CountChar(Message,'|')==13)//reception settings du port serie
    { //format recu : 1656|1653|1385|1385|2|2073|1389|1225|2073|1|0|0|1|3
      EEPROMWriteInt(ID_ADDR + 1, getValueFromArray(Message, '|', 0).toInt());//centerposServo1
      EEPROMWriteInt(ID_ADDR + 3, getValueFromArray(Message, '|', 1).toInt());//centerposServo2
      EEPROMWriteInt(ID_ADDR + 5, getValueFromArray(Message, '|', 2).toInt());//idelposServos1
      EEPROMWriteInt(ID_ADDR + 7, getValueFromArray(Message, '|', 3).toInt());//idelposServos2
      EEPROMWriteInt(ID_ADDR + 9, getValueFromArray(Message, '|', 4).toInt());//responseTime
      EEPROMWriteInt(ID_ADDR + 11, getValueFromArray(Message, '|', 5).toInt());//fullThrottle
      EEPROMWriteInt(ID_ADDR + 13, getValueFromArray(Message, '|', 6).toInt());//beginSynchro
      EEPROMWriteInt(ID_ADDR + 23, getValueFromArray(Message, '|', 7).toInt());//minimumPulse_US
      EEPROMWriteInt(ID_ADDR + 25, getValueFromArray(Message, '|', 8).toInt());//maximumPulse_US
      EEPROMWriteInt(ID_ADDR + 15, getValueFromArray(Message, '|', 9).toInt());//auxChannel
      EEPROMWriteInt(ID_ADDR + 17, getValueFromArray(Message, '|', 10).toInt());//reverseServo1
      EEPROMWriteInt(ID_ADDR + 19, getValueFromArray(Message, '|', 11).toInt());//reverseServo2
      EEPROMWriteInt(ID_ADDR + 21, getValueFromArray(Message, '|', 12).toInt());//telemetry
      EEPROMWriteInt(ID_ADDR + 27, getValueFromArray(Message, '|', 13).toInt());//nbPales
      //Serial << F("Reception Config:  ") << Message << endl;
    }
    else if(pos == 365)//configuration par defaut
    {       
      SettingsWriteDefault();
      //Serial << F("ServosTest:  ") << pos << endl;      
    }    
    else
    {
      Serial << F("Hors limite!") << endl;
    }
       
  }
  SoftRcPulseOut::refresh();  
}

int CountChar(String input, char c )
{
  int retval = 0;
  for (int i = 0; i < input.length()+1; i ++)
  if (c == input [i])
  retval ++;
  return retval;
}

String getValueFromArray(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }  
  return found>index ? data.substring(strIndex[0], strIndex[1]) : "" ;
}
    
int8_t MsgDisponible(void)/* merci a LOUSSOUARN Philippe pour ce code */
{
  int8_t Ret = -1;
  char CaractereRecu;
  static uint8_t Idx = 0;

  if(Serial.available() > 0)
  {
    CaractereRecu = Serial.read();
    switch(CaractereRecu)
    {
      case RETOUR_CHARRIOT:
      case PASSAGE_LIGNE:
        Message[Idx] = 0;
        Ret = Idx;
        Idx = 0;
        break; 
      case BACK_SPACE: // Gestion touche d'effacement du dernier caractere sur un terminal fonctionnant caractere par caractere (ex: HyperTerminal, TeraTerm, etc...)
        if(Idx) Idx--;
        break;
      default:
        if(Idx < LONGUEUR_MSG_MAX)
        {
            Message[Idx] = CaractereRecu;
            Idx++;
        }
        else Idx = 0; /* Reset index for the next message */
        break;
    }
  }
  return(Ret); 
}
#endif

La chaine que j’essaie d’envoyer à l’Arduino à partir de VB.ET a ce format:
1656|1653|1385|1385|2|2073|1389|1225|2073|1|0|0|1|3

C’est la partie ‘else if(CountChar(Message,’|’)==13)//reception settings du port serie’ qui la traite !
Si je fais un ‘send’ de cette trame dans la console série , chaque variable est bien sauvegardée d’en l’eeprom …

Par contre , ça ne fonctionne pas avec VB.NET !
Voici le code que j’utilise:

    Private Sub ButtonSauvegardeConfig_Click(sender As System.Object, e As System.EventArgs) Handles ButtonSauvegardeConfig.Click
        Try
            'format envoyé : 1656|1653|1385|1385|2|2073|1389|1225|2073|1|0|0|1|3
            Dim MessageToSend As String
            MessageToSend = textCentreServo1.Text & "|"     'centerposServo1
            MessageToSend &= textCentreServo2.Text & "|"    'centerposServo2
            MessageToSend &= textIdleServo1.Text & "|"      'idelposServos1
            MessageToSend &= textIdleServo2.Text & "|"      'idelposServos2
            MessageToSend &= textTempsReponse.Text & "|"    'responseTime
            MessageToSend &= textMaxiMoteurs.Text & "|"     'fullThrottle
            MessageToSend &= textDebutSynchro.Text & "|"    'beginSynchro
            MessageToSend &= textMiniGenerale.Text & "|"    'minimumPulse_US
            MessageToSend &= textMaxiGenerale.Text & "|"    'maximumPulse_US
            MessageToSend &= textAuxiliaireMode.Text & "|"  'auxChannel
            If CheckBoxInversionServo1.Checked = True Then MessageToSend &= "1|" Else MessageToSend &= "0|" 'reverseServo1
            If CheckBoxInversionServo2.Checked = True Then MessageToSend &= "1|" Else MessageToSend &= "0|" 'reverseServo2
            MessageToSend &= textTelemetrieType.Text & "|"  'telemetry
            'MessageToSend &= textAddresseI2C.Text & "|"     'I2C LCD
            MessageToSend &= textNombrePales.Text           'nbPales

            'MsgBox(MessageToSend)
            SerialPort1.Open()
            SerialPort1.Write(MessageToSend.ToString.Trim & vbCr)

            Thread.Sleep(5000)
            SerialPort1.Close()
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

Merci de votre aide par avance

Salut,

déjà le port série faut pas s'amuser à faire des open() close() ... Ouvre le au lancement de ton soft et ferme le à la fermeture du soft. Ensuite vérifie ce qui est envoyé sur une msgbox :

MsgBox(MessageToSend.ToString.Trim)

Merci de votre réponse,

J'ai testé avec un MsgBox et le texte que je souhaite envoyer semble bon !

tu ouvre le port avec les parametre par defaut de l'OS en .NET.
tu ouvre le port avec les parametre par defaut de l'IDE en mode console.

ces paramtres sont ils les memes?
9600/8/N/1 par defaut.

le .NET termine par cr seulement, la console série est elle configuré de meme?

Oui car toutes les autres commandes (0 à 180 pour faire bouger les servos) fonctionnent !

Est-ce que tu as bien modifié l'ouverture et la fermeture de ton port série comme je t'ai dit ?

Sinon poste la config complète de ton port série, y'a des petites subtilités sous entre .NET et Arduino ...

l'exemple en Rem est de 14 data et 13 '|'
le code renvoie 15 data et 14 '|'

Non, j'ai bien 14 data et 13 '|' , la ligne I2C dans VB étant commentée !!!

peut etre une question d'encodage des caracteres.
demande a .NET d'afficher le code ascii de '|'.

jean-I:
peut etre une question d'encodage des caracteres.
demande a .NET d'afficher le code ascii de '|'.

C'est pour ça que je demande la config du port série, y'a des paramètres à préciser car par défaut ils ne sont pas bons pour l'Arduino

Le port est configuré ainsi :

        SerialPort1.PortName = My.Settings.COMPort 'change com port to match your Arduino port
        SerialPort1.BaudRate = ComboBox2.SelectedItem
        SerialPort1.DataBits = 8
        SerialPort1.Parity = Parity.None
        SerialPort1.StopBits = StopBits.One
        SerialPort1.Handshake = Handshake.None
        SerialPort1.Encoding = System.Text.Encoding.Default 'very important!

Je ne devrais pas essayer :
SerialPort1.Encoding = System.Text.Encoding.ASCII ???

essaye.
tu pourrai egalement demander au UNO de te renvoyer l'echo de ce qu'il recoit

J'aurai bien aimer , mais le port série est déjà occupé !!! Comment faire ?

Occupé par ton logiciel ... Donc c'est bon

Oui, je comprend ! Je vais essayer cela !

Ca ne fonctionne pas !

J’ai essayé les lignes qui suivent sans succès …

    Private Sub ButtonSauvegardeConfig_Click(sender As System.Object, e As System.EventArgs) Handles ButtonSauvegardeConfig.Click
        Try
            'format envoyé : 1656|1653|1385|1385|2|2073|1389|1225|2073|1|0|0|1|3
            Dim MessageToSend As String
            MessageToSend = textCentreServo1.Text & "|"     'centerposServo1
            MessageToSend &= textCentreServo2.Text & "|"    'centerposServo2
            MessageToSend &= textIdleServo1.Text & "|"      'idelposServos1
            MessageToSend &= textIdleServo2.Text & "|"      'idelposServos2
            MessageToSend &= textTempsReponse.Text & "|"    'responseTime
            MessageToSend &= textMaxiMoteurs.Text & "|"     'fullThrottle
            MessageToSend &= textDebutSynchro.Text & "|"    'beginSynchro
            MessageToSend &= textMiniGenerale.Text & "|"    'minimumPulse_US
            MessageToSend &= textMaxiGenerale.Text & "|"    'maximumPulse_US
            MessageToSend &= textAuxiliaireMode.Text & "|"  'auxChannel
            If CheckBoxInversionServo1.Checked = True Then MessageToSend &= "1|" Else MessageToSend &= "0|" 'reverseServo1
            If CheckBoxInversionServo2.Checked = True Then MessageToSend &= "1|" Else MessageToSend &= "0|" 'reverseServo2
            MessageToSend &= textTelemetrieType.Text & "|"  'telemetry
            'MessageToSend &= textAddresseI2C.Text & "|"     'I2C LCD
            MessageToSend &= textNombrePales.Text           'nbPales

            SerialPort1.ReadTimeout = 5000
            SerialPort1.WriteTimeout = 5000

            MsgBox(MessageToSend)
            'MsgBox(Asc("|"))
            ReadSettings = ""
            SerialPort1.Open()
            SerialPort1.Write(MessageToSend.ToString.Trim & vbCr)
            Thread.Sleep(1000)
            ReadSettings = SerialPort1.ReadLine
            Thread.Sleep(500)
            SerialPort1.Close()
            If ReadSettings <> "" Then
                MsgBox(ReadSettings)
            Else
                MsgBox("RIEN")
            End If

            LabelModifications.Text = "Modifications sauvegardées !"
            LabelModifications.ForeColor = Color.Green
        Catch ex As Exception
            MsgBox(ex.Message)
            SerialPort1.Close()
        End Try
    End Sub

Pour la troisième fois : STOP AVEC LES OPEN CLOSE :

SerialPort1.Open()
SerialPort1.Write(MessageToSend.ToString.Trim & vbCr)
Thread.Sleep(1000)
ReadSettings = SerialPort1.ReadLine
Thread.Sleep(500)
SerialPort1.Close()

Je viens de me rendre compte que j'initialise l'objet SerialPort1 dans ma fenêtre principale mais aussi dans ma seconde form et avec le même nom . Les commandes de la form principale fonctionnent , et pas celles de la form deux ...

Je m’emmêle les pinceaux .

Il faudrait que j'arrive à définir un seul objet serialport pour les deux form !!!

bin oui y’a rien a faire, mis à part que dans la form qui n’a pas instancié le port série il faut appelé celui de l’autre form. Par exemple si on a form1 et form2 et form 1 a instancié le porté série, dans form il faudra appelé le port série comme ça :

form1.SerialPort1