J'envoie une liste des positions des servos via la connexion série à l'arduino dans le format suivant
1:90&2:80&3:180
Ce qui serait interprété comme :
servoId : Position & ; servoId : Position & ; servoId : Position
Comment puis-je diviser ces valeurs et les convertir en un nombre entier ?
Contrairement à d'autres réponses, je préfère ne pas utiliser String
pour les raisons suivantes :
Dans un environnement embarqué comme Arduino (même pour un Mega qui a plus de SRAM), je préfère utiliser les fonctions C standard :
strchr()
][1] : recherche d'un caractère dans une chaîne C (i.e. char *
)strtok()
][2] : divise une chaîne C en sous-chaînes, en se basant sur un caractère séparateur.atoi()
][3] : Convertit une chaîne C en un int
.Cela donnerait l'exemple de code suivant :
// Calculate based on max input size expected for one command
#define INPUT_SIZE 30
...
// Get next command from Serial (add 1 for final 0)
char input[INPUT_SIZE + 1];
byte size = Serial.readBytes(input, INPUT_SIZE);
// Add the final 0 to end the C string
input[size] = 0;
// Read each command pair
char* command = strtok(input, "&");
while (command != 0)
{
// Split the command in two values
char* separator = strchr(command, ':');
if (separator != 0)
{
// Actually split the string in 2: replace ':' with 0
*separator = 0;
int servoId = atoi(command);
++separator;
int position = atoi(separator);
// Do something with servoId and position
}
// Find the next command in input string
command = strtok(0, "&");
}
L'avantage ici est qu'il n'y a pas d'allocation dynamique de mémoire ; vous pouvez même déclarer input
comme une variable locale à l'intérieur d'une fonction qui lirait les commandes et les exécuterait ; une fois la fonction retournée, la taille occupée par input
(dans la pile) est récupérée.
[1] : http://www.cplusplus.com/reference/cstring/strchr/ [2] : http://www.cplusplus.com/reference/cstring/strtok/ [3] : http://www.cplusplus.com/reference/cstdlib/atoi/
Vous pourriez faire quelque chose comme ce qui suit, mais tenez compte de plusieurs éléments :
Si vous utilisez readStringUntil()
, il attendra jusqu'à ce qu'il reçoive le caractère ou le timeout. Ainsi, avec votre chaîne actuelle, la dernière position durera un peu plus longtemps, car elle doit attendre. Vous pouvez ajouter un &
de fin de chaîne pour éviter ce délai d'attente. Vous pouvez facilement vérifier ce comportement dans votre moniteur, essayez d'envoyer la chaîne avec et sans le &
supplémentaire et vous verrez ce délai d'attente.
En fait, vous n'avez pas besoin de l'index du servo, vous pouvez simplement envoyer votre chaîne de positions, et obtenir l'index du servo par la position de la valeur dans la chaîne, quelque chose comme : 90&80&180&
. Si vous utilisez l'index du servo, vous voudrez peut-être le vérifier (en le convertissant en int
, puis en le faisant correspondre à l'index i de la boucle) pour vous assurer que rien ne s'est mal passé dans votre message.
Vous devez vérifier que la chaîne de retour de readStringUntil
n'est pas vide. Si la fonction perd son temps, c'est que vous n'avez pas reçu suffisamment de données, et donc toute tentative d'extraction de vos valeurs int
produira des résultats étranges.
void setup() {
Serial.begin(9600);
}
void loop() {
for(int i=1; i<=3; i++) {
String servo = Serial.readStringUntil(':');
if(servo != ""){
//here you could check the servo number
String pos = Serial.readStringUntil('&');
int int_pos=pos.toInt();
Serial.println("Pos");
Serial.println(int_pos);
}
}
}
Vous pouvez utiliser [Stream.readStringUntil(terminator)
][1] en passant un terminateur différent pour chaque partie.
Pour chaque partie, vous pouvez ensuite appeler [String.toInt
][2].
[1] : http://arduino.cc/en/Reference/StreamReadStringUntil [2] : http://arduino.cc/en/Reference/StringToInt