Перевод принятого символа с com-порта в число

ArcaN0id
Offline
Зарегистрирован: 11.03.2012

 Как перевести символ(заведомо число) с com-порта в число на ардуино? желательно пример кодом привести. Заранее благодарю

maksim
Offline
Зарегистрирован: 12.02.2012

Arduino.ru -> Программирование -> Преобразование типов данных. Непосредственно символ можно преобразовать не в число, а в цифру. Символы можно собрать в строку т.е. массив символов, а строку в свою очередь перевести в число. Попробуйте так, сейчас проверить не на чем, поэтому не знаю как будет работать.

char a[6];
int b, i = 0;
boolean End = 0;

void setup() {                
  Serial.begin(9600);
}

void loop() {
  if(Serial.available()){
    delay(2); 
    a[i] = Serial.read();
    i++;
    End = 1;
  }
  else if(End == 1){
    b = int(a);
    Serial.println(b, DEC);
    i = 0;
    End = 0;   
  }
}

 

Но может есть способ и проще.
 

step962
Offline
Зарегистрирован: 23.05.2011

 сомневаюсь, что приведенная функция будет работать в исходном виде.

Если я правильно понимаю проблему топикстартера, число вводится на компьютере ручками в каком-нибудь терминале и отправляется микроконтроллеру (программным способом всегда можно отправить число в бинарном виде и не насиловать мозг). Терминал, отправляя строку, завершает ее символом конца строки, а то и двумя - конца строки и возврата каретки. Эти символы принимающая программа должна уметь отсеивать. Это раз.

Строки в си представляют собой последовательность ячеек памяти, в которых хранятся отдельные символы. Эта последовательность должна завершаться ячейкой с признаком конца строки - 0x00. Без такого завершения строки любая строчная функция будет обрабатывать "строку" вплоть до падшей восьмерки, то бишь до бесконечности. Ну, или случайно встретившейся на задворках памяти пустой ячейки. Естественно, с непредсказуемым результатом. Это два.

Но подход в целом правильный. Хотя и не единственно возможный. 

maksim
Offline
Зарегистрирован: 12.02.2012

Я всегда делал так:

char a = 0;
long b = 0;
boolean End, minus = 0;

void setup() {                
  Serial.begin(9600);
}

void loop() {
  if(Serial.available()){
    delay(2);
    a = Serial.read();
    if(a == 45){
      minus = 1;
    }
    if(a >= 48 && a <= 57){
      b += a - 48;
      b *= 10;
      End = 1;
    }
  }
  else if(End == 1){
    b /= 10;
    if(minus == 1){
      b = -b;
    }
    Serial.println(b, DEC);
    b = 0;
    minus = 0;
    End = 0;     
  }
}

И не использовал преобразование типов данных, но если есть уже такие функции, то на них в первую очередь и ссылаюсь.

step962
Offline
Зарегистрирован: 23.05.2011

 Предположим, у нас на входе число 1 (строка, состоящая из единственного символа "1").

Условие if(a >= 48 && a <= 57) истинно (a=49) и мы попадаем в блок расчета числа b:
b += a - 48; => b=0+49-48=1;
b *= 10; => b=1*10=10;

Упс... получили число в 10 раз большее переданного.

Я бы исправил это, поменяв операторы местами:
b*=10;
b += a - 48;

maksim
Offline
Зарегистрирован: 12.02.2012

Вы не внимательно смотрите код - по завершению чтения из буфера окончательное число делится на 10 , 10/10 = 1.

maksim
Offline
Зарегистрирован: 12.02.2012

Но действительно, что бы убрать деление на 10 в конце, можно поменять местами строки, для оптимизации кода:

char a = 0;
long b = 0;
boolean End, minus = 0;

void setup() {                
  Serial.begin(9600);
}

void loop() {
  if(Serial.available()){
    delay(2);
    a = Serial.read();
    if(a == 45){
      minus = 1;
    }
    if(a >= 48 && a <= 57){
      b *= 10;
      b += a - 48;      
      End = 1;
    }
  }
  else if(End == 1){
    if(minus == 1){
      b = -b;
    }
    Serial.println(b, DEC);
    b = 0;
    minus = 0;
    End = 0;     
  }
}

Теперь буду делать так.

ArcaN0id
Offline
Зарегистрирован: 11.03.2012

 Спасибо. На днях попробую, по результатам отпишусь

mixail844
Offline
Зарегистрирован: 30.04.2012

есть функция atoi в Cи для перевода из символв в цифры.не знаю как онамно другие Си'шные функции рабоали в Аrduino IDE хорошо

int atoi ( const char * str );

ASCII to integer

то есть если аргумент функции '0'(0х30) типа char,то функция вернет 0 типа integer.
функция для того и есть что бы переводить символы цифр в цифры.поэтому как она будет работать с буквами,понятия не имею.









 

mixail844
Offline
Зарегистрирован: 30.04.2012

обьясняю :

допустим есть массив 

char ch[10]={1,2,3,4,5,6,7,8} \\сотоящий из сивмолов (кодов ascii цифр) а не самих цифр

int i;\\вспомогательная переменная

int nums[10];массив цифр


for(i=0;i<10;i++)

{
 nums[i]=atoi(ch[i]);
}


данный код переведет все цифры из массива символов в массив целых.

 

если брать данные споследовательного порта,то как то так : 

loop
{
int i;
while(!Serial.available);\\задержа пока не прийдет данных на последовательный порт
i=atoi(Serial.read());перевод пришедших данных в int
Serial.flush();\\только первый байт будет считан
}

 

maksim
Offline
Зарегистрирован: 12.02.2012

Хотя нет компилируется, только если аргумент массив.

 

mixail844
Offline
Зарегистрирован: 30.04.2012

то есть по вашему функция  Serial.read(); не возвращает константу?)))а что же ,по вашему, она возвращает? 
 

обьясняю; 

 i=atoi(Serial.read());

в очень короткий промежуток времени происходит следующее : 

функция Serial.read(); считывает то что было на последовательном порте.эти данные становяться константой,котоую функция atoi() переводит в integer.

 

 

 

 

 

maksim
Offline
Зарегистрирован: 12.02.2012
i=atoi(Serial.read());

так не компилируется т.к.  Serial.read() возвращает не указатель.

Вот так компилируется:

char a[1];
long b = 0;
boolean End, minus = 0;

void setup() {                
  Serial.begin(9600);
}

void loop() {
  if(Serial.available()){
    delay(2);
    a[0] = Serial.read();
    if(a[0] == 45){
      minus = 1;
    }
      b *= 10;
      b += atoi(a);    
      End = 1;
    }
  else if(End == 1){
    if(minus == 1){
      b = -b;
    }
    Serial.println(b, DEC);
    b = 0;
    minus = 0;
    End = 0;     
  }
}

 

ArcaN0id
Offline
Зарегистрирован: 11.03.2012

 а если усложнить задачу и, например, будет с ком порта приходить символ и цифра: f500 -  f будет рассматриваться как флаг на выполнение какой то операции, а 500 - как длительность выполнения данной операции. Как тогда разложить на символ и число в две переменные?

maksim
Offline
Зарегистрирован: 12.02.2012

 А так же как и с минусом

char a[1];
long b = 0;
boolean End, minus = 0;

void setup() {                
  Serial.begin(9600);
}

void loop() {
  if(Serial.available()){
    delay(2);
    a[0] = Serial.read();
    if(a[0] == 45){
      minus = 1;
    }
    if(a[0] == 'f'){
      // делаем что-то
    }
    if(a[0] == 'r'){
      // делаем что-то еще
    }
    if(a[0] == 'b'){
      // и еще
    }
      b *= 10;
      b += atoi(a);    
      End = 1;
    }
  else if(End == 1){
    if(minus == 1){
      b = -b;
    }
    Serial.println(b, DEC);
    b = 0;
    minus = 0;
    End = 0;     
  }
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

 >то есть по вашему функция Serial.read(); не возвращает константу?

Конешно. Фунции вообще не умеют возвращать константы. Они умеют возвращать только значения определенного типа.

Конкретно эта фунция возвращает значение типа int.

>Только проблема в том, что аргумент должен быть const

не путайте констаны и ключевое слово const. Что оно означает - зависит от контекста его применения. В данном случае он просто запрещает функцие atoi менять переданный параметр внутри себя. Но вы спокойно можете передавать, в качестве параметра - любые переменные. То есть если вы вызвали atoi(myvar);, то вы уверены что myvar - не изменило своего значения. 

Правда если переменная "указатель", то функция не сможет поменять "куда он указывает", но будет способна изменить значение по этому адресу. const от этого защитить не сможет.

>данный код переведет все цифры из массива символов в массив целых.

Данный код даже не скомпилируется. Так как atoi ждет УКАЗАТЕЛЬ на массив типа char, причем заканчивающийся символом конца строки \0.

Не говоря уже про то, что непонятны зачем вы пытаетесь ей скормить каждый символ отдельно, если ее назначение - парсить строку целиком. Почитайте ее описание.

Что бы перевести один символ в целое, достаточно из его кода вычесть 48. Что с успехом уже делалось в скетчах выше.

Вообщем  вот так выглядит перевод массива кодов, в целое

  char str1[]={50,51,52,0};   // 234  
  char str2[]="567"; // умный компилятор сам добавит символ конца строки
  
  // парсим строки
  int value1=atoi(str1);
  int value2=atoi(str2);


  // выводим целые
  Serial.println(value1); // print 234
  Serial.println(value2); // print 567

  // умножением демонстрируем что это именно целые, а не строки
  Serial.println(value1*2); // print 468
  Serial.println(value2*2);  // print 1134

Ну а с serial. Нужно будет, завести какой-то массив-буффер. Вычитывать из serial байты по одному и заполнять этот массив. Следить, при этом что-бы массив не переполнился. Не забыть добавить в конце нулевой символ (если он не приходит из порта).

А потом уже atoi кормить этот массив.

Ну и, напоследок, уже включая откровенного зануду

>есть функция atoi в Cи

В языке Cи - нет такой функции. Это библиотечная функция. Библиотека cstdlib . Стандартная библиотека, согласен, но это не часть языка.

 

 

 

maksim
Offline
Зарегистрирован: 12.02.2012
char a[10];
int b, i = 0;
boolean End = 0;

void setup() {                
  Serial.begin(9600);
}

void loop() {
  if(Serial.available()){
    delay(2);
    a[i] = Serial.read();
    i++;   
    End = 1;
  }
  else if(End == 1){
    a[i] = 0;
    b = atoi(a);
    Serial.println(b, DEC);
    b = 0;
    i = 0;
    End = 0;     
  }
}

 

maksim
Offline
Зарегистрирован: 12.02.2012

И еще, в последнем случае если в строке будет хоть один "левый" символ, то функция возвращает 0 так что b123 - не прокатит. А в предпоследнем (когда char a[1]) 123b - получим 1230.

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

А почему вы не применяете метод ToInt класса String String::toInt?

Вот есть даже пример стандартный:

  while (Serial.available() > 0) {
    int inChar = Serial.read();
    if (isDigit(inChar)) {
      // convert the incoming byte to a char 
      // and add it to the string:
      inString += (char)inChar; 
    }
    // if you get a newline, print the string,
    // then the string's value:
    if (inChar == '\n') {
      Serial.print("Value:");
      Serial.println(inString.toInt());
      Serial.print("String: ");
      Serial.println(inString);
      // clear the string for new input:
      inString = ""; 
    }
  }

 

ArcaN0id
Offline
Зарегистрирован: 11.03.2012

maksim пишет:

 А так же как и с минусом

char a[1];
long b = 0;
boolean End, minus = 0;

void setup() {                
  Serial.begin(9600);
}

void loop() {
  if(Serial.available()){
    delay(2);
    a[0] = Serial.read();
    if(a[0] == 45){
      minus = 1;
    }
    if(a[0] == 'f'){
      // делаем что-то
    }
    if(a[0] == 'r'){
      // делаем что-то еще
    }
    if(a[0] == 'b'){
      // и еще
    }
      b *= 10;
      b += atoi(a);    
      End = 1;
    }
  else if(End == 1){
    if(minus == 1){
      b = -b;
    }
    Serial.println(b, DEC);
    b = 0;
    minus = 0;
    End = 0;     
  }
}

 

В этом варианте у меня не выходит правильно запустить (((

получаем с ком порта например f500 -> если f то,  например, зажигаем светодиод с delay(500!!) (500 которое пришло с ком порта) и затем гасим его. И в добавок заставляем мигать его с данным делеем, повторяя процедуру несколько раз.

Так вот получилось добиться только того, что зажигается только 1 раз с заданным интервалом (((( более не воспринимает(

maksim
Offline
Зарегистрирован: 12.02.2012

Так конечно, вам нужно delay(500!!) вынести за цикл чтения из ком порта, так же как и с минусом - minus это свего лишь флаг, а действие, которое при изменении этого флага будет выполняется полсле чтения из ком порта:

char a[1];
long b = 0;
boolean End, minus, f, r = 0;

void setup() {                
  Serial.begin(9600);
  pinMode(13, OUTPUT);     
}

void loop() {
  while(Serial.available()){
    delay(2);
    a[0] = Serial.read();
    if(a[0] == 45){
      minus = 1;
    }
    if(a[0] == 'f'){
      f = 1;
    }
    if(a[0] == 'r'){
      r = 1;
    }
    b *= 10;
    b += atoi(a);    
    End = 1;
  }
  if(End == 1){
    if(minus == 1){
      b = -b;
      minus = 0;
    }
    Serial.println(b, DEC);

    if(f){
      digitalWrite(13, HIGH);   // set the LED on
      delay(b);              // wait for a second
      digitalWrite(13, LOW);    // set the LED off
      f = 0;
    }

    if(r){
      // Делаем что-нибудь
      r = 0;
    }

    b = 0;    
    End = 0;     
  }

}

 

maksim
Offline
Зарегистрирован: 12.02.2012

AlexFisher пишет:

А почему вы не применяете метод ToInt класса String String::toInt?

Вот есть даже пример стандартный:

  while (Serial.available() > 0) {
    int inChar = Serial.read();
    if (isDigit(inChar)) {
      // convert the incoming byte to a char 
      // and add it to the string:
      inString += (char)inChar; 
    }
    // if you get a newline, print the string,
    // then the string's value:
    if (inChar == '\n') {
      Serial.print("Value:");
      Serial.println(inString.toInt());
      Serial.print("String: ");
      Serial.println(inString);
      // clear the string for new input:
      inString = ""; 
    }
  }

 

А вы сами этот пример проверяли?

ArcaN0id
Offline
Зарегистрирован: 11.03.2012

maksim пишет:

Так конечно, вам нужно delay(500!!) вынести за цикл чтения из ком порта, так же как и с минусом - minus это свего лишь флаг, а действие, которое при изменении этого флага будет выполняется полсле чтения из ком порта:


Делал примерно также, но почему то не завелось))) Ваш код работает! Спасибо огромное)) С меня пиво! )))

Буду дальше педалить, если что отпишусь!

maksim
Offline
Зарегистрирован: 12.02.2012

 Либо вот так:

char a[1];
long b = 0;
boolean End, minus, f, r = 0;

void setup() {                
  Serial.begin(9600);
  pinMode(13, OUTPUT);     
}

void loop() {

  while(Serial.available()){
    delay(2);
    a[0] = Serial.read();
    if(a[0] == 45){
      minus = 1;
    }
    if(a[0] == 'f'){
      f = 1;
    }
    if(a[0] == 'r'){
      r = 1;
    }
    b *= 10;
    b += atoi(a);    
    End = 1;
  }

  if(End == 1){
    if(minus == 1){
      b = -b;
      minus = 0;
    }
    Serial.println(b, DEC);
    End = 0;     
  }

  if(f){
    digitalWrite(13, HIGH);   // set the LED on
    delay(b);              // wait for a second
    digitalWrite(13, LOW);    // set the LED off
    f = 0;  
  }
  
  if(r){
    // Делаем что-нибудь
    r = 0;  
  }
  
  b = 0;
  
}

 

ArcaN0id
Offline
Зарегистрирован: 11.03.2012

 а без while  как то можно организовать? а то у меня случается подвисание в ожидании символов с ком порта....

maksim
Offline
Зарегистрирован: 12.02.2012

Можно, только это не решит проблему т.к. пока не закончится чтение из коп порта никаких действий происходить не будет, так же как и с циклом. Наверное все-таки будет правильнее решеть проблему с зависанием...

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

maksim пишет:

AlexFisher пишет:

А почему вы не применяете метод ToInt класса String String::toInt?

...

А вы сами этот пример проверяли?

Проверял, у меня работает.

maksim
Offline
Зарегистрирован: 12.02.2012

Это если еще в конце числа послать '\n' 

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

maksim пишет:

Это если еще в конце числа послать '\n' 

Функция прекращает работу на любом символе, отличном от цифры

maksim
Offline
Зарегистрирован: 12.02.2012

Нет, только если '\n' к конце, а так даже 12d456 возвращает 12456. Хотя смотря что вы имели ввиду под словом "прекращает"... В общем можно сделать вывод числа после цикла чтения, а в целом этот вариант тоже приемлем.

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Мне даже интересно стало (по поводу нюансов) - сейчас в железе проверю :)

Я как раз эту функцию предполагаю использовать дл яразбора строки терминала...

maksim
Offline
Зарегистрирован: 12.02.2012

Да, кстати, и отрицательные числа возвращаются положительными.

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Отрицательные возвращаются отрицательными, прекращает работу на любом нечисловом символе, как я и говорил, просто в тестовом скетче нужно заремарить фильтрацию цифр - строчку if (if (isDigit(inChar)) {, иначе до функции доходят, мягко говоря, не все символы :). Вот распечатка терминала:

Value:12
String: 12

Value:-12
String: -12

Value:0
String: Z12

Value:123
String: 123 456

Value:12
String: 12.2

 

leshak
Offline
Зарегистрирован: 29.09.2011

 http://arduino.cc/en/Reference/StreamParseInt

Так как Serial, наследуется от Stream, То можно использовать Serial.parseInt()

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Может быть. Но я имел в виду класс String arduino.cc/en/Reference/StringObject, кстати, там нет описания toInt, но всегда бывает полезно заглянуть в заголовочный файл, чтобы узнать, что вообще этот класс может hardware\arduino\cores\arduino\WString.h

Intr
Offline
Зарегистрирован: 15.06.2012

maksim пишет:

 Либо вот так:

char a[1];
long b = 0;
boolean End, minus, f, r = 0;

void setup() {                
  Serial.begin(9600);
  pinMode(13, OUTPUT);     
}

void loop() {

  while(Serial.available()){
    delay(2);
    a[0] = Serial.read();
    if(a[0] == 45){
      minus = 1;
    }
    if(a[0] == 'f'){
      f = 1;
    }
    if(a[0] == 'r'){
      r = 1;
    }
    b *= 10;
    b += atoi(a);    
    End = 1;
  }

  if(End == 1){
    if(minus == 1){
      b = -b;
      minus = 0;
    }
    Serial.println(b, DEC);
    End = 0;     
  }

  if(f){
    digitalWrite(13, HIGH);   // set the LED on
    delay(b);              // wait for a second
    digitalWrite(13, LOW);    // set the LED off
    f = 0;  
  }
  
  if(r){
    // Делаем что-нибудь
    r = 0;  
  }
  
  b = 0;
  
}

 

Решил воспользоваться этим примерном для управления положения сервы и тут возникла проблема....

При отсылке в ком-порт как программно так и через обычные терминалы когда шлю значение допустим r50 он мне выдает r52 и при посылке r51 число становиться уже 62 тоесть плюсует 10.... такое заметил только от 50 до 60 когда посылаешь

Как это можно побороть что бы все было как послал ? И с чем это связано ?

maksim
Offline
Зарегистрирован: 12.02.2012

Да, очень странный глюк, попробуйте так: 

long b = 0;
boolean End, minus, f, r = 0;

void setup() {                
  Serial.begin(9600);
  pinMode(13, OUTPUT);     
}

void loop() {

  while(Serial.available()){
    delay(2);
    char a = Serial.read();
    if(a == 45){
      minus = 1;
    }
    if(a == 'f'){
      f = 1;
    }
    if(a == 'r'){
      r = 1;
    }
    b *= 10;
    b += cifra(a);    
    End = 1;
  }

  if(End == 1){
    if(minus == 1){
      b = -b;
      minus = 0;
    }
    Serial.println(b, DEC);
    End = 0;     
  }

  if(f){
    digitalWrite(13, HIGH);   // set the LED on
    delay(b);              // wait for a second
    digitalWrite(13, LOW);    // set the LED off
    f = 0;  
  }

  if(r){
    // Делаем что-нибудь
    r = 0;  
  }

  b = 0;

}

int cifra(char a){
  int b = 0;
  if(a >= 48 && a <= 57){
    b = a - 48;     
  }
   return b;  
}

 

Intr
Offline
Зарегистрирован: 15.06.2012

Да теперь значения от 0 до 180 все посылаються нормально

Огромное спасибо

joseph kobzon
Offline
Зарегистрирован: 24.07.2012

Спасибо большое, последний пример помог.

Можно ли в строке как-то отыскивать символы?

Допустим чтобы в строке f1r200q500 символы разделяли бы цифры, присваиваемые переменным (символ f, например, отвечал бы за вращение двигателя в ту или иную сторону (f1, f2), r отвечал бы за шаги (200шагов), q определял бы частоту вращения (задержка 500)).

Вариант с последовательными командами скорее всего отпадает, т.к. он будет отправлять в три раза больше команд (если отправлять поочереди f1, r200, q500).

С уважением, Иосиф.

 

leshak
Offline
Зарегистрирован: 29.09.2011

 В строках 18 и 19 попробуйте f=1 и r=1 заменить на f=Serial.parseInt(); и r=Serial.parseInt();

Только тогда, после последней отправляемой цифры нужно еще слать какой-нибудь не цифровой символ (что-бы оно знало что "цифры закончились"). Если вы шлете это "руками из Serail монитора", то можно просто включить режим Line Ending CR (внизу справа, чуть левее скорости порта).

ourlive
Offline
Зарегистрирован: 26.05.2012

хм.. а имеет ли смысл строить сложные алгоритмы по декодированию строки на приёмной стороне (которая довольно ограниченна по ресурсам)? не проще ли разделить инфу на строгие кадры, где будет заведомо известно: где имена переменных, где их значения, где дополнительные команды и т.п.? наверняка возникнет некоторая избыточность передаваемых данных, но это позволит проверять подлинность инфы (особенно актуально при ручном наборе в терминал).

leshak
Offline
Зарегистрирован: 29.09.2011

ourlive пишет:

хм.. а имеет ли смысл строить сложные алгоритмы по декодированию строки на приёмной стороне (которая довольно ограниченна по ресурсам)?

А в чем их сложность?

ourlive пишет:

не проще ли разделить инфу на строгие кадры, где будет заведомо известно: где имена переменных, где их значения, где дополнительные команды и т.п.? наверняка возникнет некоторая избыточность передаваемых данных, но это позволит проверять подлинность инфы (особенно актуально при ручном наборе в терминал).

Нет. Не проще. Проще будет если перейти на бинарный протокол, тогда все что вы сказали - имеет смысл. В случае же если "руками шлем команды", то все равно нужно будет искать какой-то маркер "начала-конца команды", все равно нужно будет переводить строки в числа. Только очень сильно повысим риск "ошибки оператора". Он будет должен 

  • Помнить порядок и длины каждой команды
  • Не забыть дополнять цифры впереди ничего не значащими нулями (что-бы поддерживать фиксированую длину)
  • Передавать данные не только "те что поменялись", но и "все". То есть ему нужно будет помнить еще "текущие состояние" и каждый раз его вбивать. Либо, нужно будет заводить какие-то "магические цифры" означающие "ничего не изменилось" (и еще это проверять на стороне ардуины).

И главное - не понятно ради чего все. Попробуйте все это реализовать в виде кода и сильно подозреваю что он не выйдет короче (а возможно и длиней) чем изначальный вариант. 

Так что выбор обычно стоит между "бинарный формат - простой код" и "человеческий формат - танцы с конвертациями и парсингом".

ourlive
Offline
Зарегистрирован: 26.05.2012

тогда ещё вопрос по приведённому коду, есть ли какие либо преимущества в сборе буфера Serial в массив char перед сбором в одну переменную типа String? Строку вроде как нагляднее и проще анализировать, если команды длиннее одного байта.

а про терминал. врятли это итоговое решение, в результате будет какое либо приложение, которое и будет слать данные, а приложению уже всё равно что и как слать. Кадровую передачу данных я попробую воплотить, хотя бы ради того чтобы попробовать.

Peter
Peter аватар
Offline
Зарегистрирован: 25.02.2012

AlexFisher пишет:

А почему вы не применяете метод ToInt класса String String::toInt?

Вот есть даже пример стандартный:

  while (Serial.available() > 0) {
    int inChar = Serial.read();
    if (isDigit(inChar)) {
      // convert the incoming byte to a char 
      // and add it to the string:
      inString += (char)inChar; 
    }
    // if you get a newline, print the string,
    // then the string's value:
    if (inChar == '\n') {
      Serial.print("Value:");
      Serial.println(inString.toInt());
      Serial.print("String: ");
      Serial.println(inString);
      // clear the string for new input:
      inString = ""; 
    }
  }

 

 

Отлично работает! Спасибо большое! 

Только пример не очень удачный.

String string;
char char[]={1,2,3};


string=String(char[1]);
string+=String(char[2]);
string+=String(char[3]);

int Value=string.toInt();


Serial.print(Value);


 

AlexFisher
AlexFisher аватар
Offline
Зарегистрирован: 20.12.2011

Вообще-то должно работать просто

string=String(char);

А вообще, имена переменным не принято такие давать - отучайтесь!

Peter
Peter аватар
Offline
Зарегистрирован: 25.02.2012

AlexFisher пишет:

Вообще-то должно работать просто

string=String(char);

В моем примере надо было из определенных символов массива получить int. Тем не менее спасибо.

AlexFisher пишет:

А вообще, имена переменным не принято такие давать - отучайтесь!

Это всего лишь пример! Никто их так не задает.

Buzzer2010
Buzzer2010 аватар
Offline
Зарегистрирован: 10.03.2016

step962 пишет:
... (программным способом всегда можно отправить число в бинарном виде и не насиловать мозг)

А можно пару слов (и пару строк) об этом моменте? Предполагается передавать между двумя ардуинами некоторый односторонний протокол: цифры разеделенные каким-то символом. Что-то вроде этого:

data_out_off =  String(data_out_off + "0,0," + data_in[2] + ",500,500,0,0,0,0,0,0,0,0,0,0,0,000000000000000000000000000" + data_in[43] + data_in[44] +"0000" + "\n");
// и потом сразу:
Serial.println (data_out_off);

Как на ардуине-приемнике разобрать такую строку?

Спасибо.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Buzzer2010 пишет:

Как на ардуине-приемнике разобрать такую строку?

Вестимо, по разделителям. Например, юзая strchr, или просто вычитывая до разделителя в буфер, и как только вычитали очередное значение - чего-то предпринимать.

spa-sam
Offline
Зарегистрирован: 14.12.2012

Один добрый человек подсказал вот такую функцию, очень удобную и простую. За что ему и спасибо!

// Функция парсинга строки
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]) : "";
}
 
вызывая фунцию парсим строку:

String xval = getValue(myString, ':', 0);
String yval = getValue(myString, ':', 1);
Serial.println("Y:" + yval);
Serial.print("X:" + xval);

int xvalue = stringToNumber(xval); 
int yvalue = stringToNumber(yval);

 

 

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

spa-sam пишет:

Один добрый человек подсказал вот такую функцию

Жесть. Можно сильно проще. Но раз это работает - пущай.

 

spa-sam
Offline
Зарегистрирован: 14.12.2012

Собственно источник - http://arduino.stackexchange.com/questions/1013/how-do-i-split-an-incoming-string

Там же обсуждение и различные методы, выбираем, изучаем и творим )