Sto inviando una lista di posizioni del servo attraverso la connessione seriale all'arduino nel seguente formato
1:90&2:80&3:180
Che verrebbe analizzato come:
servoId : Posizione & servoId : Posizione & servoId : Posizione
.
Come potrei dividere questi valori e convertirli in un intero?
Contrariamente ad altre risposte, preferisco stare lontano da String
per i seguenti motivi:
In un ambiente embedded come Arduino (anche per un Mega che ha più SRAM), preferirei usare funzioni C standard:
strchr()
: cerca un carattere in una stringa C (cioè char *
)strtok()
: divide una stringa C in sottostringhe, basandosi su un carattere separatoreatoi()
: converte una stringa C in un `intQuesto porterebbe al seguente esempio di codice:
// 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, "&");
}
Il vantaggio qui è che non ha luogo alcuna allocazione dinamica di memoria; si può anche dichiarare input
come variabile locale all'interno di una funzione che leggerebbe i comandi e li eseguirebbe; una volta che la funzione viene restituita si recupera la dimensione occupata da input
(nello stack).
Potreste fare qualcosa come la seguente, ma tenete conto di diverse cose:
Se usate readStringUntil()
, aspetterà finché non riceve il carattere o va in timeout. Quindi, con la tua stringa attuale, l'ultima posizione durerà un po' di più, dato che deve aspettare. Puoi aggiungere un trailing &
per evitare questo timeout. Puoi facilmente controllare questo comportamento nel tuo monitor, prova a inviare la stringa con e senza l'extra &
e vedrai questo ritardo di timeout.
In realtà non hai bisogno dell'indice del servo, puoi semplicemente inviare la tua stringa di posizioni, e ottenere l'indice del servo dalla posizione del valore nella stringa, qualcosa come: 90&80&180&
. Se usi l'indice del servo, forse vuoi controllarlo (convertire in int
, e poi abbinare l'indice i del loop) per assicurarti che nulla sia andato storto con il tuo messaggio.
Devi controllare che la stringa di ritorno da readStringUntil``` non sia vuota. Se la funzione va in timeout, non hai ricevuto abbastanza dati, e quindi ogni tentativo di estrarre i tuoi valori
int``` produrrà strani risultati.
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);
}
}
}
Potete usare Stream.readStringUntil(terminator)
passando un terminatore diverso per ogni parte.
Su ogni parte si chiama poi String.toInt