Как прочитать строковое значение с разделителем на Arduino?
Я должен управлять сервоприводами с компьютера.
Поэтому я должен отправлять управляющие сообщения с компьютера на Arduino. Мне нужно управлять номером сервопривода и углом. Я думаю о sendin что-то вроде этого: "1;130" (первый сервопривод и угол 130, разделитель ";").
Есть ли лучшие методы для достижения этой цели?
Вот мой этот код:
String foo = "";
void setup(){
Serial.begin(9600);
}
void loop(){
readSignalFromComp();
}
void readSignalFromComp() {
if (Serial.available() > 0)
foo = '';
while (Serial.available() > 0){
foo += Serial.read();
}
if (!foo.equals(""))
Serial.print(foo);
}
Это не работает В чем проблема?
5 ответов
- Вы можете использовать Serial.readString() и Serial.readStringUntil() для анализа строк из Serial на Arduino
- Вы также можете использовать Serial.parseInt() для чтения целочисленных значений из последовательного
Пример кода
int x;
String str;
void loop()
{
if(Serial.available() > 0)
{
str = Serial.readStringUntil('\n');
x = Serial.parseInt();
}
}
Значение для отправки через последовательный будет "моя строка \n5", а результат будет str = "моя строка" и х = 5
Большинство других ответов являются либо очень подробными, либо очень общими, поэтому я подумал, что приведу пример того, как это можно сделать на вашем конкретном примере с использованием библиотек Arduino:
Вы можете использовать метод Serial.readStringUntil для чтения, пока ваш разделитель из Serial
порт.
А затем используйте toInt, чтобы преобразовать строку в целое число.
Итак, для полного примера:
void loop()
{
if (Serial.available() > 0)
{
// First read the string until the ';' in your example
// "1;130" this would read the "1" as a String
String servo_str = Serial.readStringUntil(';');
// But since we want it as an integer we parse it.
int servo = servo_str.toInt();
// We now have "130\n" left in the Serial buffer, so we read that.
// The end of line character '\n' or '\r\n' is sent over the serial
// terminal to signify the end of line, so we can read the
// remaining buffer until we find that.
String corner_str = Serial.readStringUntil('\n');
// And again parse that as an int.
int corner = corner_str.toInt();
// Do something awesome!
}
}
Конечно, мы можем немного упростить это:
void loop()
{
if (Serial.available() > 0)
{
int servo = Serial.readStringUntil(';').toInt();
int corner = Serial.readStringUntil('\n').toInt();
// Do something awesome!
}
}
Это отличная субмарина, которую я нашел. Это было очень полезно, и я надеюсь, что это будет с вами.
Это метод, который вызывает подпрограмму.
String xval = getValue(myString, ':', 0);
Это суб!
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = {
0, -1 };
int maxIndex = data.length()-1;
for(int i=0; i<=maxIndex && found<=index; i++){
if(data.charAt(i)==separator || i==maxIndex){
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
Вам нужно создать буфер чтения и вычислить, где ваши 2 поля (серво # и угол) начинаются и заканчиваются. Затем вы можете прочитать их и преобразовать символы в целые числа для использования в остальной части вашего кода. Примерно так должно работать (не проверено на Arduino, но стандартно C):
void loop()
{
int pos = 0; // position in read buffer
int servoNumber = 0; // your first field of message
int corner = 0; // second field of message
int cornerStartPos = 0; // starting offset of corner in string
char buffer[32];
// send data only when you receive data:
while (Serial.available() > 0)
{
// read the incoming byte:
char inByte = Serial.read();
// add to our read buffer
buffer[pos++] = inByte;
// check for delimiter
if (itoa(inByte) == ';')
{
cornerStartPos = pos;
buffer[pos-1] = 0;
servoNumber = atoi(buffer);
printf("Servo num: %d", servoNumber);
}
}
else
{
buffer[pos++] = 0; // delimit
corner = atoi((char*)(buffer+cornerStartPos));
printf("Corner: %d", corner);
}
}
Похоже, вам просто нужно исправить
foo = ''; >>to>> foo = "";
foo += Serial.read(); >>to>> foo += char(Serial.read());
Я сделал также shomething похожий..
void loop(){
while (myExp == "") {
myExp = myReadSerialStr();
delay(100);
}
}
String myReadSerialStr() {
String str = "";
while (Serial.available () > 0) {
str += char(Serial.read ());
}
return str;
}
Это универсальный парсер
struct servo
{
int iServoID;
int iAngle;
};
std::vector<std::string> split(const std::string& str, const std::string& delim)
{
std::vector<std::string> tokens;
size_t prev = 0, pos = 0;
do
{
pos = str.find(delim, prev);
if (pos == std::string::npos) pos = str.length();
std::string token = str.substr(prev, pos-prev);
if (!token.empty()) tokens.push_back(token);
prev = pos + delim.length();
}
while (pos < str.length() && prev < str.length());
return tokens;
}
std::vector<servo> getServoValues(const std::string& message)
{
std::vector<servo> servoList;
servo servoValue;
std::vector<std::string> servoString;
std::vector<std::string> values = split(message, ",");
for (const auto& v : values)
{
servoString.clear();
servoString = split(v, ";");
servoValue.iServoID = atoi(servoString[0].c_str()); //servoString[0].toInt();
servoValue.iAngle = atoi(servoString[1].c_str());// servoString[1].toInt();
servoList.emplace_back(servoValue);
}
return servoList;
}
звонить:
std::string str = "1;233,2;123";
std::vector<servo> servos = getServoValues(str);
for (const auto & a : servos)
std::cout<<a.iServoID << " " << a.iAngle << std::endl;
Результат
1 233
2 123
Этот код читает строку, пока не увидит '>'
характер
void loop() {
// put your main code here, to run repeatedly:
String msg = getMessage();
}
String getMessage() {
String msg = "";
while (Serial.available()>0) {
msg = Serial.readStringUntil('>');
}
return msg;
}