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

C++ Discussion :

Communication série avec Arduino


Sujet :

C++

  1. #1
    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 Communication série avec Arduino
    Bonjour,

    j'essaye de réaliser un programme C++ qui me permet d'envoyer des commandes (chaînes de caractères) et de lire les réponses d'un Arduino Mega2560. Autant avec la console Arduino, le système est très réactif : j'envoie la commande et l'Arduino répond dans la foulée (environ 1 à 2ms). Autant avec mon programme C++, le système devient très lent : j'ai pratiquement 1s entre l'envoi des données et la réponse !
    Je pense que l'un des soucis est dans le contrôle des flux (DSR, DTR, RTS, CTS), je ne dois pas les gérer correctement.

    Savez-vous comment je peux accélérer la communication entre mon PC et mon Arduino ? Quels sont les flags que je dois activer ou désactiver ?

    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
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
     
    // ArduinoCom.cpp : Ce fichier contient la fonction 'main'. L'exécution du programme commence et se termine à cet endroit.
    //
     
    #include <iostream>
    #include <string>
    #include <windows.h>
    #include <chrono>
     
    using namespace std;
    using namespace chrono;
     
    class ArduinoCom
    {
    	public:
    		ArduinoCom() {};
    		~ArduinoCom() {};
     
    		int initArduino(string comPort)
    		{
    			bool fSuccess = true;
    			wstring ws;
    			ws = wstring(comPort.begin(), comPort.end());
     
    			hCom = CreateFile(ws.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
     
    			if (hCom == INVALID_HANDLE_VALUE)
    			{
    				return -1;
    			}
     
    			comParams.DCBlength = sizeof(comParams);
    			GetCommState(hCom, &comParams);
    			comParams.BaudRate = 1200;
    			comParams.ByteSize = 8;
    			comParams.Parity = NOPARITY;
    			comParams.StopBits = ONESTOPBIT;
     
    			/*
    			comParams.fOutxCtsFlow = false;
    			comParams.fRtsControl = RTS_CONTROL_DISABLE;
     
    			comParams.fOutxDsrFlow = false;
    			comParams.fDtrControl = DTR_CONTROL_DISABLE;
     
    			comParams.fBinary = true;
    			comParams.fDsrSensitivity = false;
    			comParams.fTXContinueOnXoff = true;
    			comParams.fOutX = true;
    			comParams.fInX = true;
    			*/
    			fSuccess = SetCommState(hCom, &comParams);
     
    			CloseHandle(hCom);
    			return 0;
    		}
     
     
    		int openArduino(string comPort, DWORD baudRate)
    		{
    			bool fSuccess = true;
    			wstring ws;
    			ws = wstring(comPort.begin(), comPort.end());
     
    			hCom = CreateFile(ws.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
     
    			if (hCom == INVALID_HANDLE_VALUE)
    			{
    				return -1;
    			}
     
    			comParams.DCBlength = sizeof(comParams);
    			GetCommState(hCom, &comParams);
    			comParams.BaudRate = baudRate;
    			comParams.ByteSize = 8;
    			comParams.Parity = NOPARITY;
    			comParams.StopBits = ONESTOPBIT;
     
    			comParams.fOutxCtsFlow = true;
    			comParams.fRtsControl = RTS_CONTROL_ENABLE;
     
    			comParams.fOutxDsrFlow = true;
    			comParams.fDtrControl = DTR_CONTROL_ENABLE;
     
    			comParams.fBinary = true;
    			comParams.fDsrSensitivity = true;
    			comParams.fTXContinueOnXoff = true;
    			comParams.fOutX = true;
    			comParams.fInX = true;
     
     
    			fSuccess = SetCommState(hCom, &comParams);
     
    			Sleep(1500);
     
    			if (!fSuccess)
    				return -1;
    			return 0;
    		}
     
    		int writeArduino(string cmd)
    		{
    			bool fSuccess;
    			const char *buf;
    			DWORD nbw;
     
    			buf = cmd.c_str();
    			fSuccess = WriteFile(hCom, buf, strlen(buf), &nbw, NULL);
    			//FlushFileBuffers(hCom);
     
    			return fSuccess;
    		}
     
    		int readArduino(string &resp, char endChar)
    		{
    			char buf;
    			bool fSuccess;
    			DWORD nbr;
     
    			while (true)
    			{
    				fSuccess = ReadFile(hCom, &buf, 1, &nbr, NULL);
    				cout << buf;
    				if (buf == endChar)
    					break;
    			}
    			//resp = buf;
    			return fSuccess;
    		}
     
    		int closeArduino()
    		{
    			if (hCom == INVALID_HANDLE_VALUE)
    				return -1;
     
    			CloseHandle(hCom);
    			return 0;
    		}
     
    	private:
    		HANDLE hCom;
    		DCB comParams = { 0 };
    };
     
     
     
    int main()
    {
    	ArduinoCom *ac = new ArduinoCom();
    	string msg = "-";
     
    	cout << "init " << ac->initArduino("COM7") << "\n";
    	Sleep(1000);
     
    	cout << "open " << ac->openArduino("COM7", 115200) << "\n";
     
    	auto start = high_resolution_clock::now();
     
    	cout << "Top écriture ";
    	cout << "write " << ac->writeArduino("BrLed,Pulse,31,2500\\n") << "\n";
     
    	cout << "Top lecture ";
    	ac->readArduino(msg, '\n');
    	cout << msg << "\n";
     
    	auto stop = high_resolution_clock::now();
     
    	auto duration = duration_cast<milliseconds>(stop - start);
    	cout << duration.count() << endl;
     
     
    	cout << "close " << ac->closeArduino();
    	free(ac);
     
    	system("pause");
        //std::cout << "Hello World!\n";
    }

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Ligne 160, pourquoi un double \\? Je pense que ta carte Arduino attend une fin de ligne qui doit surement être un caractère \n ou \r mais certainement pas un \ suivi d'un n.

  3. #3
    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
    Effectivement la carte attend un "\n" mais j'échappe le "\" en le doublant pour qu'il ne soit pas interprété par ma fonction write(). Mais j'avoue que tu me fais douter. J'essaierai d'enlever le "\\".

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 147
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 147
    Billets dans le blog
    4
    Par défaut
    Ta lib std supporte cette syntaxe ?
    string comPort, ...
    wstring ws = wstring(comPort.begin(), comPort.end());
    Parce que convertir un std::string en std::wstring de cette façon, j'ai jamais vu, et ça me parait donc un peu cavalier.
    Ça passait par le header codecvt et (w)string_convert, déprécié en C++17. Il faut utiliser les API plateformes pour le faire maintenant. mbstowcs sous Windows.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    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
    Citation Envoyé par Bousk Voir le message
    Ta lib std supporte cette syntaxe ?
    Mon Visual Studio, oui. J'avoue avoir récupéré cette syntaxe sur divers forums.

  6. #6
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Citation Envoyé par Bousk Voir le message
    Ta lib std supporte cette syntaxe ?

    Parce que convertir un std::string en std::wstring de cette façon, j'ai jamais vu, et ça me parait donc un peu cavalier.
    Ça passait par le header codecvt et (w)string_convert, déprécié en C++17. Il faut utiliser les API plateformes pour le faire maintenant. mbstowcs sous Windows.
    Bien vu, en interne ça va provoquer l'équivalent de wchar_t x = y; avec y de type const char&, ce qui doit être accepté par la STD. Ce qui est correct pour de l'ASCII 7 bits mais si la chaine contient autre chose, ça ne peut que faire n'importe quoi, et je pense qu'il n'y aura même pas un warning.
    Il faudrait donc passer par mbstowcs_s(), mais dans le cas présent ça peut fonctionner sans.

  7. #7
    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
    Bon, un des problèmes était justement cet encodage des caractères. Je me suis mélangé les pinceaux entre les wchar_t, char, wstring et string.

  8. #8
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Auteur Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    	ArduinoCom *ac = new ArduinoCom();
     
    	...
     
    	free(ac);
    À malloc()/calloc()/realloc() du C correspond free().
    À new du C++ doit correspondre delete.
    Ou encore mieux ici : une simple variable locale .

    Dans la fonction writeArduino(), strlen(buf) => cmd.size().
    Dans la fonction readArduino(), tu bénéficierais probablement de lire plus d'un caractère à la fois.

  9. #9
    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'est bien vrai : new et delete.
    Décidément

    Dans la fonction readArduino(), tu bénéficierais probablement de lire plus d'un caractère à la fois.
    je ne sais pas combien de caractères mon Arduino va me renvoyer.

  10. #10
    Invité
    Invité(e)
    Par défaut
    Je te demande pas de prévoir le nombre final, juste d'avoir un buffer de lecture légèrement plus grand .
    Et dans cette optique ton nbr dont tu passes l'adresse contiendra le nombre d'éléments effectivement lus.

  11. #11
    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
    ah... si ça peut m'éviter une boucle.

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

Discussions similaires

  1. Utiliser Processing avec Arduino, communication série.
    Par jeanclaude83 dans le forum Arduino
    Réponses: 43
    Dernier message: 03/10/2021, 17h23
  2. [Embarqué] Communication avec le port série vers Arduino
    Par YannGTT dans le forum Plateformes
    Réponses: 0
    Dernier message: 05/04/2020, 04h45
  3. Réponses: 3
    Dernier message: 06/04/2014, 20h01
  4. Communication série avec QtSerialPort
    Par JusteUneIdee dans le forum Débuter
    Réponses: 1
    Dernier message: 08/07/2013, 12h42
  5. Bug communication serie avec arduino (busy)
    Par Invité dans le forum MATLAB
    Réponses: 2
    Dernier message: 09/07/2012, 09h39

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