Changer la valeur d'une variable depuis l'invite de commande

Bonjour,

dans le cadre d'un projet il nous est demandé de créé un mode de configuration d'un système embarqué.
Problème étant que pour modifier certains modes, il nous ai demandé de rentré directement une commande depuis l'invite de commande et non dans le programme lui même.
Par exemple,
Dans mon programme :

int *LUMIN = 0
int *PRESSURE = 3
printf("si vous voulez changer une valeur, entrez la commande"\n)
scanf(" Commande : %d", Je ne sais pas)

Je voudrais que depuis ce scanf je puisse rentrer par exemple "PRESSURE = 8"
Sans avoir des if dans tout les sens, car l'objectif est d'optimiser la mémoire.
Je précise bien que LUMIN et PRESSURE sont des pointeurs.(J'ai fais comme ça pour économiser encore la mémoire.

Bonjour,

Si tu comptes optimiser la mémoire il ne faut pas utiliser de pointeurs, mais utiliser directement les variables.
De plus un pointeur (comme son nom l'indique) doit pointer sur une variable et donc typiquement contenir l'adresse de la variable. Quand tu fais int *LUMIN = 0 ou int *PRESSURE = 3, c'est n'importe quoi.

scanf prend beaucoup de mémoire et n'est certainement pas le meilleur moyen d'optimiser la mémoire.

Tu parles d'un système embarqué. printf et scanf sont supposés correspondre à quel périphérique?

Bonjour,

Actuellement je bosse sur Arduino uno. En effet j'avais un doute pour mes pointeurs. Je suis repassé sur une configuration plus simple mais si l'on reprend le problème avec des variables je ne parviens toujours pas a récupéré l'information de l'utilisateur pour changer la variable.

Merci de ton aide

Sur une Uno, l'interface utilisateur passe soit par la liaison série, soit par une interface dédiée que tu vas créer.

Etant donné la formulation " il nous est demandé de rentré directement une commande depuis l**'invite de commande**" on peut supposer que c'est de la liaison série dont il est question.
Il faut donc que tu écrives le code nécessaire à l'acquisition de l'information par l'intermédiaire de ce lien.

Oui en effet il faut utiliser la liaison serie. Mais le problème c'est justement que je ne connais pas le programme. Peut être y'a t'il une fonction qui peut résoudre mon problème.

La librairie Serial et les exemples associés que tu trouveras dans l'IDE ou ici.

commander-un-arduino-par-la-ligne-serie

L'exemple 3.2. ReadBytesUntil est assez proche de ce que tu veux faire.

Les commandes sont simple :
HELLO : affichage de HELLO
UPPER azertyuiop : transforme l'argument en majuscules
LOWER AZERTYUIOP : transforme l'argument en minuscules
ADD 33 12 : additionne deux arguments
Il est facile de modifier pour accepter d'autres commandes :
LUMIN 0
PRESSURE 3

int lumin;
int pressure;

  if (!strncmp(buf, "PRESSURE", 8)) {
    char s[20];
    char arg[20];
    if (sscanf(buf, "%s %s", s, arg) != 2) {
      // invalid arguments
      Serial.println("EINVAL");
      return true;
    }
    pressure = atoi(arg);         // affectation variable
  }  else if (!strncmp(buf, "LUMIN", 5)) {
    char s[20];
    char arg[20];
    if (sscanf(buf, "%s %s", s, arg) != 2) {
      // invalid arguments
      Serial.println("EINVAL");
      return true;
    }
    lumin = atoi(arg);         // affectation variable
  }
  // etc...

au dessus tu as un exemple pour le programme arduino

ici tu as un exemple du coté windows ( powershell ou invite de commande )

ICi dan l'exemple c'est le port COM3... chez toi c'est un autre...

[System.IO.Ports.SerialPort]::getportnames() <= permet de connaitre les ports ouvert..

un autre exemple ici =>

https://learn.sparkfun.com/tutorials/terminal-basics/command-line-windows-mac-linux

J'avoue que pour l'instant je ne m'y connais pas trop en windows ...
En tout cas j'ai essayé la méthode de hbachetti et ca semble être ce que je recherche mais le soucis étant que j'ai un problème avec les return. Voila le code que j'ai entré :

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Boot message"));
}

#define CMD_MAX               100

void loop()
{
  static char buf[CMD_MAX];

  if (!Serial.available()) {
    return false;
  }
  memset(buf, 0, CMD_MAX);
  size_t size = Serial.readBytesUntil('\n', buf, CMD_MAX - 1);

  // exécution de la commande

int lumin;
int pressure;

  if (!strncmp(buf, "PRESSURE", 8)) {
    char s[20];
    char arg[20];
    if (sscanf(buf, "%s %s", s, arg) != 2) {
      // invalid arguments
      Serial.println("EINVAL");
      return true;
    }
    pressure = atoi(arg);         // affectation variable
  }  else if (!strncmp(buf, "LUMIN", 5)) {
    char s[20];
    char arg[20];
    if (sscanf(buf, "%s %s", s, arg) != 2) {
      // invalid arguments
      Serial.println("EINVAL");
      return true;
    }
    lumin = atoi(arg);         // affectation variable
  }
}

Et il me renvoie ce genre d'erreurs :
C:\Users\33695\Desktop\test2\test2.ino: In function 'void loop()':
C:\Users\33695\Desktop\test2\test2.ino:14:12: warning: return-statement with a value, in function returning 'void' [-fpermissive]
return false;
^~~~~
C:\Users\33695\Desktop\test2\test2.ino:30:14: warning: return-statement with a value, in function returning 'void' [-fpermissive]
return true;
^~~~
C:\Users\33695\Desktop\test2\test2.ino:39:14: warning: return-statement with a value, in function returning 'void' [-fpermissive]
return true;

void loop()
{
  static char buf[CMD_MAX];

  if (!Serial.available()) {
    return false;
  }

La fonction loop est déclarée void, c'est à dire qu'elle ne renvoie rien. On ne peut pas utiliser de return dans cette fonction car return est fait pour retourner une valeur.
Par ailleurs un return dans la fonction loop n'a pas de sens, car c'est une demande de sortir de la fonction. Pour aller où?

Comme loop est appelé en boucle par main, qui n'est pas visible dans l'IDE arduino, je pense qu'un return fait repartir la loop à son début.

Je pense aussi que le return renvoie à la boucle, mais je vais essayer de le mettre dans une autre fonction ... peu de chance de réussite.

OK j'ai été mauvaise langue,
le programme semble tourner comme ca :

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Boot message"));
}

#define CMD_MAX               100

void loop()
{
  boucle();
}

int boucle()
{
  static char buf[CMD_MAX];

  if (!Serial.available()) {
    return false;
  }
  memset(buf, 0, CMD_MAX);
  size_t size = Serial.readBytesUntil('\n', buf, CMD_MAX - 1);

  // exécution de la commande

int lumin;
int pressure;

  if (!strncmp(buf, "PRESSURE", 8)) {
    char s[20];
    char arg[20];
    if (sscanf(buf, "%s %s", s, arg) != 2) {
      // invalid arguments
      Serial.println("EINVAL");
      return true;
    }
    pressure = atoi(arg);         // affectation variable
  }  else if (!strncmp(buf, "LUMIN", 5)) {
    char s[20];
    char arg[20];
    if (sscanf(buf, "%s %s", s, arg) != 2) {
      // invalid arguments
      Serial.println("EINVAL");
      return true;
    }
    lumin = atoi(arg);         // affectation variable
  }
}

Problème maintenant c'est que je n'arrive pas a changer la valeur de ma variable ... Pourtant j'ai rentré "PRESSURE 3" mais il semble dire que l'argument est invalide ...

Chez moi c'est bon : J'entre PRESSURE 1024, puis LUMIN 254 et j'obtiens dans la console (j'ai ajouté des Serial.println pour suivre l'exécution) :

14
trouve PRESSURE
1024
10
trouve LUMIN
254

Oui effectivement, petite erreur de ma part. J'ai corrigé l'article sur mon blog.
La compilation passe sur ARDUINO mais pas sur ESP par exemple.

vileroi:
Par ailleurs un return dans la fonction loop n'a pas de sens, car c'est une demande de sortir de la fonction. Pour aller où?

Cela a du sens, si l'on désire sortir rapidement d'une fonction, sans avoir une suite de if / else imbriqués.
Pour aller où ? retourner à la fonction appelante, c'est à dire main()

@MaolCESI : comme tu utilises des commandes courtes tu peux réduire CMD_MAX pour gagner un peu de mémoire RAM.
Une vingtaine ou trentaine de caractères devrait suffire.

OK je vais un peu raccourcir mes tableaux.
J'ai fais la meme chose que toi lesept.
J'ai entré "PRESSURE 8" mais il me renvoie "EINVAL".
Après n'aillant pas le matériel sur moi j'utilise ceci :

https://www.tinkercad.com/things/89rMk7GqLi8-start-simulating/editel?lessonid=EHD2303J3YPUS5Z&projectid=OIYJ88OJ3OPN3EA&collectionid=OIYJ88OJ3OPN3EA#/lesson-viewer

Peut être que le problème viens de la ?

Je ne peux pas voir ce lien, car je n'ai pas de compte.
J'ai fait le test sur un ESP32

Voici le code :

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Boot message"));
}

#define CMD_MAX               100

void loop()
{
  static char buf[CMD_MAX];

  while (!Serial.available());
  memset(buf, 0, CMD_MAX);
  Serial.readBytesUntil('\n', buf, CMD_MAX - 1);
  Serial.print(buf);

  int lumin;
  int pressure;

  if (!strncmp(buf, "PRESSURE", 8)) {
    Serial.print(" trouve PRESSURE --> ");
    char s[20];
    char arg[20];
    if (sscanf(buf, "%s %s", s, arg) != 2) Serial.println("EINVAL");
    else {
      pressure = atoi(arg);         // affectation variable
      Serial.println(pressure);
    }
  }  else if (!strncmp(buf, "LUMIN", 5)) {
    Serial.print(" trouve LUMIN --> ");
    char s[20];
    char arg[20];
    if (sscanf(buf, "%s %s", s, arg) != 2) Serial.println("EINVAL");
    else {
      lumin = atoi(arg);         // affectation variable
      Serial.println(lumin);
    }
  }
}

Quand je mets n'importe quoi comme 'TOTO 42', je n'obtiens pas de message EINVAL

Boot message
PRESSURE 1024 trouve PRESSURE --> 1024
LUMIN -125 trouve LUMIN --> -125
TOTO 42
TITI

Il faut ajouter un else :

  else {
    // command not supported
    Serial.println("WHAT'S UP DOC ?");
  }

En effet, le programme fonctionne! Je vous remercie tous pour votre aide !
Et si j'ai d'autre problème sur ce sujet je reviendrai sur ce post. ^^

Bon, j'ai un nouveau problème.
Je dois ajouter une nouvelle variable nommé LUMIN_MAX.
Lorsque j'utilise la meme commande en entrant "LUMIN_MAX".
Il me change la valeur de LUMIN et de LUMIN_MAX alors que je ne voulais que LUMIN_MAX initialement... J'ai essayé de changer certaines valeurs dans le tableau mais rien n'y fais :confused: