IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Arduino Discussion :

Communication entre Arduino et Matlab via serial


Sujet :

Arduino

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Chercheur (postdoc)
    Inscrit en
    Août 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Chercheur (postdoc)

    Informations forums :
    Inscription : Août 2014
    Messages : 16
    Par défaut Communication entre Arduino et Matlab via serial
    Bonjour,

    J’essaye de créer un script relativement simple pour allumer et éteindre des LED en fonction de l’heure fourni par un module RTC. Ca fonctionne bien quand l’heure est définie dans void setup(), mais j’aimerais être en mesure de changer l’heure programmée via Matlab. Et ça, ça ne fonctionne pas. J’ai essayé plusieurs solutions trouvées sur le net dans des forums, mais quelque chose m’échappe. Mon manque de connaissance de l’environnement Arduino (et Matlab ?) m’empêche de trouver ce qui cloche et ce que je dois faire pour résoudre le problème.

    En quelques mots j’essaye d’envoyer quatre valeurs (heures et minutes pour allumer et éteindre les LED) via serial. Le code posté ici est de toute évidence incorrect, mais c’est la dernière version en date après de multiple essais.

    De manière ultime, j’aimerais aussi pouvoir envoyer de l’info de l’Arduino vers Matlab pour mettre à jour en temps réel les valeurs des heures et minutes.

    Voici mon code Arduino :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    #include "Wire.h"
    #define DS3231_I2C_ADDRESS 0x68
     
    // Convert normal decimal numbers to binary coded decimal
    byte decToBcd(byte val) {
      return( (val/10*16) + (val%10) );
    }
     
    // Convert binary coded decimal to normal decimal numbers
    byte bcdToDec(byte val) {
      return( (val/16*10) + (val%16) );
    }
     
    // Renames digital pins 2, 4 and 7 as LED1, LED2 and redLED
    int LED1 = 2;  // For controlling white LED1, using pin2 as an output
    int LED2 = 4;  // For controlling white LED2, using pin4 as an output
    int redLED = 7;  // For controlling red LED, using pin7 as an output
     
    // Defines L/D cycle (no "0" before values < 10)
    int hourON = 19; // Light ON at XX:.. (hour)
    int minuteON = 8; // Light ON at ..:XX (minute)
    int hourOFF = 19; // Light OFF at XX:.. (hour)
    int minuteOFF = 9; // Light OFF at ..:XX (minute)
     
    // Variables used to initiate the display time every second on serial monitor
    unsigned long timer; unsigned long timer_ref = 0;
     
    int answer[4];
     
    void setup() {
      Wire.begin();
      Serial.begin(9600);
      pinMode(LED1, OUTPUT);
      pinMode(LED2, OUTPUT);
      pinMode(redLED, OUTPUT);
    }
     
    void readDS3231time(byte *second,
    byte *minute,
    byte *hour,
    byte *dayOfWeek,
    byte *dayOfMonth,
    byte *month,
    byte *year) {
      Wire.beginTransmission(DS3231_I2C_ADDRESS);
      Wire.write(0); // set DS3231 register pointer to 00h
      Wire.endTransmission();
      Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
      // Request seven bytes of data from DS3231 starting from register 00h
      *second = bcdToDec(Wire.read() & 0x7f);
      *minute = bcdToDec(Wire.read());
      *hour = bcdToDec(Wire.read() & 0x3f);
      *dayOfWeek = bcdToDec(Wire.read());
      *dayOfMonth = bcdToDec(Wire.read());
      *month = bcdToDec(Wire.read());
      *year = bcdToDec(Wire.read());  
    }
     
    void LDcycle() {
      byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
      // Retrieve data from DS3231
      readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
      &year);
      if (hour == hourON && minute == minuteON) {
        digitalWrite(LED1, HIGH);
        digitalWrite(LED2, HIGH);
        digitalWrite(redLED, LOW);
      }
      if (hour == hourOFF && minute == minuteOFF) {
        digitalWrite(LED1, LOW);
        digitalWrite(LED2, LOW);
        digitalWrite(redLED, HIGH);
      }
    }
     
    void displayTime() {
      byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
      // Retrieve data from DS3231
      readDS3231time(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
      &year);
      // Send it to the serial monitor
      Serial.print(hour, DEC);
      // Convert the byte variable to a decimal number when displayed
      Serial.print(":");
      if (minute<10) {
        Serial.print("0");
      }
      Serial.print(minute, DEC);
      Serial.print(":");
      if (second<10) {
        Serial.print("0");
      }
      Serial.print(second, DEC);
      Serial.print(" ");
      Serial.print(dayOfMonth, DEC);
      Serial.print("/");
      Serial.print(month, DEC);
      Serial.print("/");
      Serial.print(year, DEC);
      Serial.print(" Day of week: ");
      switch(dayOfWeek) {
      case 1:
        Serial.println("Sunday");
        break;
      case 2:
        Serial.println("Monday");
        break;
      case 3:
        Serial.println("Tuesday");
        break;
      case 4:
        Serial.println("Wednesday");
        break;
      case 5:
        Serial.println("Thursday");
        break;
      case 6:
        Serial.println("Friday");
        break;
      case 7:
        Serial.println("Saturday");
        break;
      }
    }
     
    void loop() {
      LDcycle();
      timer = millis();
      if (timer - timer_ref >= 1000) { // Every second,
         displayTime(); // display the real-time clock data on the Serial Monitor
         timer_ref = millis();
      }
     
      if (Serial.available() > 0) {
        for (int i=0; i<4; i++) {
          answer[i] = Serial.parseInt();
        }
     
      hourON = answer[0];
      minuteON = answer[1];
      hourOFF = answer[2];
      minuteOFF = answer[3];
      }
    }
    Et mon code Matlab :

    Code MATLAB : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    clc
    instrreset
     
    arduino=serial('COM8','BaudRate',9600);
     
    fopen(arduino); % initiate arduino communication
     
    prompt = {'Hour ON','Min ON','Hour OFF','Min OFF'};
    dlg_title = 'Input';
    num_lines = 1;
    defaultans = {'21','0','9','0'};
    answer = inputdlg(prompt,dlg_title,num_lines,defaultans);
     
    full_answer = [answer{1},',',answer{2},',',answer{3},',',answer{4}];
     
    fprintf(arduino,'%s',char(full_answer));
     
    fclose(arduino); % end communication with arduino

    Merci beaucoup pour votre aide...

  2. #2
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut
    Bonjour,

    voici des exemples d'écriture et lecture sur le port série avec Matlab. Mon Arduino UNO est sur le COM 6. Pour que cela la fonctionne n'oublie pas de basculer DTR à "on" dans le code Matlab
    Désolé, je n'ai pas commenté les codes.
    Arduino vers Matlab:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
     
    /*
    Test ecriture port série :
    liaison Uno
    */
    void setup() 
    {
      Serial.begin(115200);
    }
     
    void loop() 
    {
        Serial.println("Hello");
        delay(500);
    }
    Avec une fonction callback
    Code Matlab : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    function serialPortRead
        disp('Lecture des données du port série');
     
        sPort = serial('COM6','BaudRate', 115200, 'DataBits', 8, 'Parity', 'none', 'StopBits', 1, ...
            'DataTerminalReady', 'on', 'RequestToSend', 'off', 'FlowControl', 'none', ...
            'Terminator', 'CR');
     
        % Ouverture du port série
        fopen(sPort);
     
        sPort.BytesAvailableFcnMode='Terminator';
        sPort.BytesAvailableFcn=@(src,event)lineCallback(src, event, sPort);
     
     
        i=0;
        while (i<10)
            i = i + 1;
            pause(1);   % durée de la lecture des données = pause(1) x 10
        end;
     
        % Fermeture du port
        fclose(sPort);
        delete(sPort);
    end
     
    function lineCallback(src, event, sPort)
        tline = fgets(sPort);
        disp(tline);
    end


    Matlab vers Arduino : La LED de l'Arduino doit clignoter 4 fois et s'éteindre.
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
     
    int led = 13;
     
    void setup() 
    {
      pinMode(led, OUTPUT);
      Serial.begin(115200);
    }
     
    void loop() 
    {
      if (Serial.available() > 0) 
      {
        char inChar = Serial.read();
     
        switch (inChar) 
        {   
        case 'a':
          digitalWrite(led, HIGH);
          break; 
        case 'z':
          digitalWrite(led, LOW);
          break;
        }
      }
    }
    Code Matlab : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    % Paramètres du port série
    sPort = serial('COM6','BaudRate', 115200, 'DataBits', 8, 'Parity', 'none', 'StopBits', 1, ...
        'DataTerminalReady', 'on', 'RequestToSend', 'off', 'FlowControl', 'none', ...
        'Terminator','');
     
    % Ouverture du port série
    fopen(sPort);
     
    for i=1:4
        fprintf(sPort, 'a'); % allumage LED
        pause(1);
     
        fprintf(sPort, 'z'); % extinction LED
        pause(1);       % pause de 1s
    end;
     
    % Fermeture du port
    fclose(sPort);

  3. #3
    Membre averti
    Homme Profil pro
    Chercheur (postdoc)
    Inscrit en
    Août 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Chercheur (postdoc)

    Informations forums :
    Inscription : Août 2014
    Messages : 16
    Par défaut Serial.readStringUntil()
    Merci beaucoup, mais malheureusement je n’arrive toujours pas à faire fonctionner mon code, et je n’arrive pas à comprendre ce qui cloche. J’ai décidé de simplifier les choses et d’essayer pour le moment de simplement me concentrer sur la com Matlab/Arduino avec un script plus petit.

    Depuis Matlab, j’aimerais envoyer l’expression "1;150" par exemple, pour qu’Arduino puisse stocker la valeur 1 et 150 quelque part. Si le premier chiffre est 1, alors il allume ma LED.

    Je voudrais utiliser Serial.readStringUntil() qui me semble approprié pour ce que je veux faire. J’ai lu beaucoup de forums, et je ne comprends pas ce qui ne va pas dans mon code Arduino. L’information ne doit pas transiter correctement depuis Matlab.

    Code Arduino
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    int ledPin = 2;
     
    void setup() {
      pinMode(ledPin, OUTPUT);
      Serial.begin(9600);
    }
     
    void loop() {
      if (Serial.available() > 0) {
        String str1 = Serial.readStringUntil(';');
        int str1int = str1.toInt();
        String str2 = Serial.readStringUntil('\n');
        int str2int = str2.toInt();
     
          if(str1int == 1) {
          digitalWrite(ledPin, HIGH);
          }
       }
    }
    Code Matlab
    Code MATLAB : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    clc
     
    arduino=serial('COM8','BaudRate',9600);
    fopen(arduino);
    toto = '1;130';
     
    t0 = clock;
    while etime(clock, t0) < 2
      fprintf(arduino,'%s',char(toto));
    end
     
    fclose(arduino);

    Des idées sur ce que je devrais changer ?

  4. #4
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut
    Côté Arduino lis toute la chaîne reçue puis décompose la. Dans le code ci-dessous l'Arduino attend une chaîne de la forme xx@yyy\n puis sépare les arguments (ici j'ai mi un @ comme séparateur et \n comme fin de chaîne). Attention ! La chaîne doit avoir strictement cette forme ! Ces syntaxes x@y\n ou xx@y\n ou xxx@y\n ou xx@yy\n par exemple ne fonctionnent pas.

    Pour séparer les différents champs tu peux aussi utiliser la fonction strtok. Mais dans ce cas ce ne sont plus des String que tu gères mais des char *
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    // - Attention les pins 0 (RX) et 1 (TX) sont connectés au port USB !
    // Ne pas les utiliser car les fonctions port série sont implémentées dans le script.
     
    // - la chaine de caractères à lire est de la forme "xx@yyy\n" (soit 7 caractères).  Le contenu de la chaine lue est placée dans  la variable buf.
     
    char buf[8];
    byte n;
    String strA, strB;
    int intA, intB;
     
    void setup()
    { 
      Serial.begin(9600);
      while (!Serial) 
      {
        // attente de connexion du port série. Pour Leonardo seulement.
        // boucle à supprimer pour UNO
      }
     
    }
     
     
    void loop()
    {
      if (Serial.available() > 0) 
      {
          // Lecture de la donnée reçue
          n = Serial.readBytesUntil('\n', buf, 7);
     
          if (n > 0)
          {
              strA = "__";
              strB = "___";
     
              strA[0] = buf[0];
              strA[1] = buf[1];
              // buf[2] = '@'
              strB[0] = buf[3];
              strB[1] = buf[4];
              strB[2] = buf[5];
              // buf[6] = '\n'
     
              intA = strA.toInt();
              intB = strB.toInt();
     
              // Debug
              /*
              Serial.println("Code=");
              Serial.println(buf);
              Serial.println(intA);
              Serial.println(intB);    
              */      
     
              // suite du code
     
          }
      }
    }


    Côté Matlab, regarde comment j'ai initialisé le port série.
    Code matlab : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    % Paramètres du port série
    sPort = serial('COM6','BaudRate', 9600, 'DataBits', 8, 'Parity', 'none', 'StopBits', 1, ...
        'DataTerminalReady', 'on', 'RequestToSend', 'off', 'FlowControl', 'none', ...
        'Terminator','');
     
    % Ouverture du port série
    fopen(sPort);
     
     
    fprintf(sPort, '123@45\n'); % envoi de la chaine de la forme 'xx@yyy\n'
    pause(1);
     
     
    % Fermeture du port
    fclose(sPort);

  5. #5
    Membre averti
    Homme Profil pro
    Chercheur (postdoc)
    Inscrit en
    Août 2014
    Messages
    16
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Chercheur (postdoc)

    Informations forums :
    Inscription : Août 2014
    Messages : 16
    Par défaut
    Fantastique, ça fonctionne très bien. J’ai en même temps compris un peu mieux comment manipuler les bytes.

    Merci beaucoup pour votre aide

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Communication entre Arduino et Raspberry Pi2 en python
    Par Alexis55000 dans le forum Général Python
    Réponses: 3
    Dernier message: 22/12/2016, 08h32
  2. [Débutant] Communication entre MATLAB et Arduino
    Par Wsert dans le forum MATLAB
    Réponses: 4
    Dernier message: 02/10/2015, 09h30
  3. Réponses: 4
    Dernier message: 07/04/2012, 10h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo