void loop()
{
while (Serial.available() != 0)
{
switch (Serial.read())
{
case 'H':
digitalWrite(13,HIGH);
break;
case 'L':
digitalWrite(13,LOW);
break;
}
}
}
Cet exemple fonctionne mais est très restreint car je souhaiterais envoyer à l'arduino des commandes beaucoup plus longues contenant entre autre des int et des float.
Voila un petit script que j'ai réalisé mais je bloque car travailler avec char ne me permet pas d'utiliser switch et un ifelse ne fonctionne pas non plus...
char para3[5] = {data[8],data[9],data[10],data[11]}; //PARAMÈTRE 3* } [/quote] N'y a-t-il pas une façon plus simple de recevoir des données ? J'avoue que la je bloque sur un truc qui parait simple...
Je vais jeter un oeil à tous ça je constate que faire communiquer l'aduino vers l’extérieur reste relativement complexe...
Dans la pratique, c'est assez simple:
Tant qu'il y a quelque chose dans le buffer du port série
Lire 1 caractère dans le buffer série (le buffer 'avance' tout seul d'un cran. C'est à dire qu'il 'éjecte' le caractère lu)
Si ce caractère lu n'est pas le caractère choisi de fin de séquence, le concaténer à la chaine
sinon, on boucle
Traiter la chaine (sscanf par exemple)
exemple (moche)
char Buf; // 1 caractère
String Ligne; // La ligne de stockage
void setup()
{
Serial.begin(9600);
Serial.println("Debut transmission");
// ... etc
}
void loop()
{
while (Serial.available() > 0) // tant qu'il y a à manger sur le port série
{
Buf = Serial.read(); // lire 1 caractère dans le buffer serie
Serial.print(Buf); // afficher le caractère (sert à rien, juste à contrôler sur le moniteur série)
Ligne = Ligne + Buf; // concaténer le caractère dans la chaine (peut aussi s'écrire: Ligne += Buf c'est plus lisible)
if (Buf == '*') // --- Ici, j'utilise l'* comme caractère de fin de séquence.
{
Serial.print("Sequence: ");
Serial.println(Ligne);
// Traitement avec sscanf pour extraire les données de la ligne
}
}
Serial.end();
}
char Buf; // 1 caractère
String Ligne; // La ligne de stockage
float val1;
float val2;
float val3;
void setup()
{
Serial.begin(9600);
}
void loop()
{
while (Serial.available() > 0) // tant qu'il y a à manger sur le port série
{
Buf = Serial.read(); // lire 1 caractère dans le buffer serie
if (Buf == '') // --- Ici, j'utilise l' comme caractère de fin de séquence.
{
Serial.print("Sequence: ");
Serial.println(Ligne);
val1, val2, val3 sont déclarés en float (nombres à virgules) alors que %d fait reference a des entiers.
De plus sscanf prend en premier parametre un pointeur sur char.
Donc tu peux modifier ton code par exemple de cette façon :
char Buf; // 1 caractère
char Ligne[80]; // La ligne de stockage 79 caractères au maximum
int val1, val2, val3; // trois valeurs entieres
void setup()
{
Serial.begin(9600);
}
void loop()
{
while (Serial.available() > 0) // tant qu'il y a à manger sur le port série
{
Buf = Serial.read(); // lire 1 caractère dans le buffer serie
if (Buf == '*') // --- Ici, j'utilise l'* comme caractère de fin de séquence.
{
Serial.print("Sequence: ");
Serial.println(Ligne);
sscanf(Ligne, "%d, %d, %d",&val1, &val2, &val3);
}else{
strcat(ligne, buf); // strcat ajoute à ligne la chaine buf
}
}
//Serial.end();
}
Il y a peut-être encore des erreurs, je n'ai pas testé ce code
De plus, d'après ce que je googlise depuis 1/4 d'heure, sscanf version Arduino a des problèmes pour traiter le type float (qui s'utilise d'habitude avec un simple %f (et pas %d qui est pour un entier, comme indiqué))
Il semble que certains traitent le problème en deux fois
elriri:
Je vais jeter un oeil à tous ça je constate que faire communiquer l'aduino vers l’extérieur reste relativement complexe...
Tout dépend du protocole utilisé, textuelle ou binaire.
Tu travail en textuelle ici (avec du texte) ce qui est le plus compliqué, avec du binaire tu aurais juste eu quelques lignes de code.
Mais côté PC cela aurait etait plus compliqué pour transmettre des commandes binaire (pas de serial monitor, obligation d'utiliser un terminal série ou un prog maison).
elriri:
Serial.end(); empêche l'affichage dans le terminal.
NON !
Serial.end() désactive le port série, qu'il faut ensuite réactiver par un nouveau Serial.begin().
En aucun cas cette fonction ne permet "d'empécher" l'affichage dans le terminal.
Disables serial communication, allowing the RX and TX pins to be used for general input and output. To re-enable serial communication, call Serial.begin().
elriri:
Pourtant à aucun moment sscanf utilise de char.... je capte rien
"Ligne" est un objet de type String, pas une chaine de caractére.
Il faut d'abord utiliser l'opérateur String.toCharArray() pour copier les caractéres dans un vrai tableau de char :
Marc56:
De plus, d'après ce que je googlise depuis 1/4 d'heure, sscanf version Arduino a des problèmes pour traiter le type float (qui s'utilise d'habitude avec un simple %f (et pas %d qui est pour un entier, comme indiqué))
Pas seulement la "version arduino", la version de base de scanf, sprintf, etc ne gére pas les float car cela augmente considérablement la taille du programme.
Pour activer la version avec support des nombres flottants il faut normalement ajouter les options compilateurs suivantes :
-Wl,-u,vfprintf -lprintf_flt -lm
Par défaut sans support des flottants les options sont :
-Wl,-u,vfprintf -lprintf_min
Comme il est impossible d'ajouter / supprimer des options via l'ide arduino tu n'as pas le choix de la version de sprintf, scanf, etc ...
Marc56:
Il semble que certains traitent le problème en deux fois
extration en format chaine (%s)
conversion en float (atof)
Un float n'est rien d'autre que deux int séparé par un point !
Beaucoup de monde ce casse la tête pour rien :
int entier, flottant;
scanf(buf, "%d.%d", &entier, &flottant);
Aprés tu rassemble la partie entiére et la partie flottante dans un int (et t'oublie pas de diviser la partie flottante par une puissance de 10 flottante)
elriri:
Je découvre le C alors que je programme uniquement en PHP où pour la même chose un simple explode(' ',$var) aurait suffit !
PHP gère les tableaux de manière trés particulière et sans typage ce qui facilite beaucoup de chose.
char Buf; // 1 caractère
char Ligne[80]; // La ligne de stockage 79 caractères au maximum
float val1, val2, val3; // trois valeurs décimales
char valtxt1[10], valtxt2[10], valtxt3[10];
int i;
void setup()
{
Serial.begin(9600);
}
void loop()
{
while (Serial.available())
{
Buf = Serial.read();
Ligne[i] = Buf;
i++;
if (Buf == '*')
{
Ligne[i] = '\0';
Serial.print("Sequence: "); Serial.println(Ligne);
sscanf(Ligne, "%s %s %s", &valtxt1, &valtxt2, &valtxt3);
val1 = atof(valtxt1);
val2 = atof(valtxt2);
val3 = atof(valtxt3);
Serial.print("Val1: "); Serial.println(val1);
Serial.print("Val2: "); Serial.println(val2);
Serial.print("Val3: "); Serial.println(val3);
i = 0;
}
}
}
est très bien, meric pour ce code, ça fait longtemps que je veux manipuler les chaînes de caractères avec arduino, mais pour mon projet il faudrait que la séquence contiennent aussi du texte ou du moins des lettres genre a b c d.... ce qui correspondrait à ue instruction puis les flottants derrières constituraits la valeur, par exemple si mon code python envoi arduino.write('C 24.25*') l'arduino doit extraire val1 et val2 et voir que val1=C et val2=24.25 puis après une comparaison if(val1==B) arduino comprend qu'il faut mettre la consigne de la chaudière à 24.25°C, comment prendre en charge du texte dans la séquence ?
au lieu de t'embeter avec des lettres tu choisit des valeurs style 1;2;3 ou si ca te dérange car c'est trop près des températures voulu 55;56;57 etc comme ça tu peux réutiliser le code direct