Ich sende eine Liste der Servopositionen über die serielle Verbindung an den Arduino im folgenden Format
1:90&2:80&3:180
Das würde geparst werden als:
servoId : Position & servoId : Position & servoId : Position
Wie kann ich diese Werte aufteilen und in eine Ganzzahl umwandeln?
Im Gegensatz zu anderen Antworten würde ich mich aus den folgenden Gründen lieber von String
fernhalten:
In einer eingebetteten Umgebung wie Arduino (sogar für einen Mega, der mehr SRAM hat), würde ich lieber Standard-C-Funktionen verwenden:
strchr()
: Suche nach einem Zeichen in einem C-String (d.h. char *
)strtok()
: zerlegt einen C-String in Teilstrings, basierend auf einem Trennzeichenatoi()
: wandelt einen C-String in einen int
umDas würde zu folgendem Codebeispiel führen:
// 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, "&");
}
Der Vorteil hierbei ist, dass keine dynamische Speicherzuweisung stattfindet; man kann sogar input
als lokale Variable innerhalb einer Funktion deklarieren, die die Befehle liest und ausführt; sobald die Funktion zurückgegeben wird, wird die von input
(im Stack) belegte Größe wiederhergestellt.
Sie könnten z. B. wie folgt vorgehen, aber bitte beachten Sie dabei einige Dinge:
Wenn Sie `readStringUntil()
verwenden, wird es warten, bis es das Zeichen erhält oder eine Zeitüberschreitung eintritt. Bei Ihrer aktuellen Zeichenkette wird die letzte Position also etwas länger dauern, da sie warten muss. Sie können ein &
am Ende hinzufügen, um diese Zeitüberschreitung zu vermeiden. Sie können dieses Verhalten leicht in Ihrem Monitor überprüfen, indem Sie versuchen, die Zeichenkette mit und ohne das zusätzliche &
zu senden, und Sie werden diese Zeitüberschreitung sehen.
Sie brauchen den Servo-Index eigentlich nicht, Sie können einfach Ihren Positionsstring senden und den Servo-Index durch die Wertposition im String erhalten, etwa so: 90&80&180&
. Wenn Sie den Servo-Index verwenden, möchten Sie ihn vielleicht überprüfen (in `int
umwandeln und dann mit dem Schleifenindex i abgleichen), um sicherzustellen, dass nichts mit Ihrer Nachricht schief gelaufen ist.
Sie müssen überprüfen, ob der zurückgegebene String von readStringUntil`` nicht leer ist. Wenn die Funktion eine Zeitüberschreitung verursacht, haben Sie nicht genügend Daten erhalten, und jeder Versuch, die
int``-Werte zu extrahieren, wird zu seltsamen Ergebnissen führen.
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);
}
}
}
Sie können Stream.readStringUntil(terminator)
verwenden und dabei für jeden Teil einen anderen Terminator angeben.
Bei jedem Teil rufen Sie dann String.toInt
auf.