Posielam zoznam pozícií serv cez sériové pripojenie do arduina v nasledujúcom formáte
1:90&2:80&3:180
Ktorý by sa analyzoval ako:
servoId : Position & servoId : Position & servoId : Position
Ako by som tieto hodnoty rozdelil a previedol na celé číslo?
Na rozdiel od iných odpovedí by som sa radšej vyhol String
z nasledujúcich dôvodov:
Vo vstavanom prostredí, ako je Arduino (dokonca aj v prípade Mega, ktoré má viac pamäte SRAM), by som radšej použil štandardné funkcie C:
strchr()
: hľadanie znaku v reťazci C (t. j. char *
)strtok()
: rozdelí reťazec C na podreťazce na základe oddeľovacieho znakuatoi()
: konvertuje reťazec C na int
To by viedlo k nasledujúcej ukážke kódu:
// 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, "&");
}
Výhodou je, že tu nedochádza k dynamickému prideľovaniu pamäte; môžete dokonca deklarovať input
ako lokálnu premennú vo vnútri funkcie, ktorá by čítala príkazy a vykonávala ich; po návrate funkcie sa obnoví veľkosť obsadená input
(v zásobníku).
Mohli by ste urobiť niečo podobné, ale berte do úvahy niekoľko vecí:
Ak použijete readStringUntil()
, bude čakať, kým nedostane znak alebo časový limit. Teda pri vašom aktuálnom reťazci bude posledná pozícia trvať o niečo dlhšie, pretože musí čakať. Môžete pridať koncovku &
, aby ste sa tomuto časovému limitu vyhli. Toto správanie si môžete ľahko overiť v monitore, skúste poslať reťazec s dodatočným &
a bez neho a uvidíte takéto oneskorenie timeoutu.
V skutočnosti nepotrebujete index serva, môžete jednoducho poslať reťazec pozícií a získať index serva podľa pozície hodnoty v reťazci, niečo ako: 90&80&180&
. Ak použijete index serva, možno ho budete chcieť skontrolovať (previesť na ```int```` a potom porovnať s indexom slučky i), aby ste sa uistili, že sa vo vašej správe nič nepokazilo.
Musíte skontrolovať, či vracaný reťazec z readStringUntil`` nie je prázdny. Ak sa funkcia oneskorí, nedostali ste dostatok údajov, a tak akýkoľvek pokus o získanie vašich hodnôt
int```` prinesie čudné výsledky.
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);
}
}
}
Môžete použiť Stream.readStringUntil(terminator)
, pričom pre každú časť zadáte iný terminátor.
Na každej časti potom zavoláte String.toInt