Как обработать принятые данные

basilblinov
Offline
Зарегистрирован: 02.06.2013

Кто может на пальцах объяснить как переводить принятые байты в нужные типы данных. Отправлять-то легко... Я недавно программирую Ардуину, и эти тонкости передачи не освоил. Прошу без фуканья. Гугл по этому поводу ничего внятного не говорит. Пробовал по всем описаниям - получается катавасия. ... Все когда-то учились. ...

Ну т.е. принял я массив из байтов. В каждом байте висит разряд. Как мне их расставить в одну переменную float. А если дробь??? А если отицательное число??? Прошу рассказать.

Andrey_Y_Ostanovsky
Offline
Зарегистрирован: 03.12.2012

Дак это у Вас не по ардуино вопрос, а по "преобразованию типов на языке с/с++" - и в гугле это точно есть. Если Вы приняли _массив_ данных - то типизация там уже какая-то уже есть.

Geronimo
Offline
Зарегистрирован: 06.05.2013

basilblinov пишет:

Кто может на пальцах объяснить как переводить принятые байты в нужные типы данных. Отправлять-то легко... Я недавно программирую Ардуину, и эти тонкости передачи не освоил. Прошу без фуканья. Гугл по этому поводу ничего внятного не говорит. Пробовал по всем описаниям - получается катавасия. ... Все когда-то учились. ...

Ну т.е. принял я массив из байтов. В каждом байте висит разряд. Как мне их расставить в одну переменную float. А если дробь??? А если отицательное число??? Прошу рассказать.

union
{
char bytes[4];
int ival;
float fval;
} type_converter;

 

кладешь в массивbytes 4 байта из ival забираешь int или из fval float
кладешь в ival целое забираешь из bytes байты

basilblinov
Offline
Зарегистрирован: 02.06.2013

А можно на конкретном примере?

Geronimo
Offline
Зарегистрирован: 06.05.2013
char unput_data[10];
int values[5];
int k;
union 
{
   char bytes[2];
   int ival;
} type_converter;

get_input(input_data);

k = 0;
for(int i = 0; i<9;i+=2)
{
  type_converter.bytes[0] = input[i];
  type_converter.bytes[1] = input[i+1];
  values[k++] = type_converter.ival;
}

for(int i = 0;i<5;i++)
{
 Serial.println(values[i]);
}


 

Geronimo
Offline
Зарегистрирован: 06.05.2013

ну или через сдвиги можно

 

jmas
Offline
Зарегистрирован: 02.06.2013

Я программирую на ардуине не так давно, но понял, что переводить из одного типа данных в другой можно специальными фукциями или ключевыми словами.

int a = 1;
float b = float(a);
char c = char(a);

Как то так.

Geronimo
Offline
Зарегистрирован: 06.05.2013

Как я понимаю тс, он хочет из байтов восстановить тип, тут просто приведение типов не поможет

basilblinov
Offline
Зарегистрирован: 02.06.2013

Geronimo пишет:

char unput_data[10];
int values[5];
int k;
union 
{
   char bytes[2];
   int ival;
} type_converter;

get_input(input_data);

k = 0;
for(int i = 0; i<9;i+=2)
{
  type_converter.bytes[0] = input[i];
  type_converter.bytes[1] = input[i+1];
  values[k++] = type_converter.ival;
}

for(int i = 0;i<5;i++)
{
 Serial.println(values[i]);
}


 

Может я чё не вкуриваю, но не получается.

На выходе - абра-кадабра.

Уточню поставленную задачу.

Есть ли код, универсальный что ли... Для следующей задачи: Я считываю данные - 1 байт - 1 разряд числа типа float (например 58.12) Я его передаю из Processing в Arduino. Я не знаю какое это число (высчитывается автоматически). Вот подсчитал Processing - передаю данное число через Serial.print в Arduino. Получил его в выше сказанном виде (1 байт - один разряд). Как мне теперь это число собрать в кучу и привести его в тип float для того, что бы работать с ним дальше... Я упростил задачу (для тренировки) и через serial monitor сам себе отсылаю число и отправляю его обратно. Если отсылать байты - всё чётко, но байты не так наглядны для пересчёта и т.п. Читал пример: float D  =  (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0] //// ничего не получилось - на выходе ересь. Короче я в тупике

basilblinov
Offline
Зарегистрирован: 02.06.2013

jmas пишет:

Я программирую на ардуине не так давно, но понял, что переводить из одного типа данных в другой можно специальными фукциями или ключевыми словами.

int a = 1;
float b = float(a);
char c = char(a);

Как то так.

 

Это не то.

basilblinov
Offline
Зарегистрирован: 02.06.2013

byte t[100];
int i, y;
void setup()
{
  Serial.begin(9600);
}
void loop(){
  i = 0;
  y = 0;
  while (Serial.available() > 0) {
    t[i] = Serial.read();
    i++;
  }
  while (y != i) {
    Serial.print(t[y]);
    y++;
  }
  Serial.println();
  delay(1000);
}

Здесь я принимаю и отсылаю четко. Но вот t - byte.

 

Geronimo
Offline
Зарегистрирован: 06.05.2013

Serial.print()

Передает данные через последовательный порт как ASCII текст. Эта функция может принимать различные типы данных. Так целые числа выводятся соответствующими им символами ASCII. Вещественные выводятся с помощью двух ASCII символов, для целой и дробной части. Байты передаются как символ с соответствующим номером. Симоволы и строки отсылаются как есть.

 

таким образом посылая тип данных через print отличный от byte, то происходит конвертация числа в строку и отправка кодов соотвествующих символов.

т.е.

float a = 2.3;

Serial.print(a);

отправит  3 символа '2' '.' '3' т.е. в виде кодов символов и получающая строна получит числа 50 46 51.

далее ты делаешь float D  =  (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]

и естественно получаешь ересь, так как в data у тебя не байтовое представления float, а аски сиволы цифр.

как вариант решения проблемы используй Serial.write

или преобразуй строку в число с помощью функции atof

 

basilblinov
Offline
Зарегистрирован: 02.06.2013

Странно, что нет какой-то простой функции по этому злосчастному преобразованию!!! А от этих непонятных кодов крыша едет. Буду искать полный перечень команд для arduino. Может там найду ответ...

 

__Alexander
Offline
Зарегистрирован: 24.10.2012

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

basilblinov
Offline
Зарегистрирован: 02.06.2013

__Alexander пишет:

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

Коды я прописал все. И в Processing и в Arduino. И не так они и легки, как кажется некоторым. Но вот состыковать эти два чудовища - проблема этих чёртовых байтив!!!

И можете быть уверены, что я их победю!!! Вопрос времени. Просто не хочется изобретать велосипед.

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

basilblinov пишет:

Странно, что нет какой-то простой функции по этому злосчастному преобразованию!!! А от этих непонятных кодов крыша едет. Буду искать полный перечень команд для arduino. Может там найду ответ...

 

Да есть все. Причем и на форуме обсуждалось, навреное, уже не один десяток раз.

Первое что вам нужно решить - что же именно вы будете по Serial передавать, строки или бинарный боток (Int,float и т.п.)

Если бинарный - то вам, вообщем-то ничего и конвертировать не нужно. Послали, скажем float, ну и прочитали во float. Все. Но тогда в Serial мониторе, глазами, это прочитать/посмотреть не выйдет. Там бракодабра будет. Это путь Serial.write/Serial.readBytes - просто для ардуины, сложно человеку читать.

Второй вариант: слать строки. Человеко-читаемый вариант. Это путь Serial.print (он все в строки конвертит). Тогда, на принимающией стороне - нужно будет строку распарсивать обратно в числовое значение. С помощью atoi, руками "по цифре" и т.п.

Покопайтесь, не один раз уже это описывалось тут (как прочитать число из Serial и т.п.). В том числе и варианты с процессингом пробегали.

И, кстати, происывать все коды - соверншено нет нужды. Если вы действительно их все прописали, то могли заметить, что для цифр 0,1,2,3,4... соотвествуют коды 48,49,50,51,52....   То есть тоже идут подряд. Вот тут как раз нужно включить "здоровую лень" и увидеть, что одно в другое можно преобразовать, банальным вычитанием

Например перевод кода в цифру (не число):

byte number=code-48; 

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

byte number=code-'0';

Вместое '0' - компилятор сам подставить нужный код.

__Alexander
Offline
Зарегистрирован: 24.10.2012

ну, если вы выложите свои коды, то победите эти чертовы байты гораздо быстрее.

basilblinov
Offline
Зарегистрирован: 02.06.2013

Сэньк ю. Ща домой с праци, пожру и душить биты!!!

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

basilblinov пишет:

Здесь я принимаю и отсылаю четко. Но вот t - byte.

Ну так сделайте его не байт, а "что вам там нужно". Например int.

А потом, используйте приведение типов. 

Примерно так:

  ((byte*)t)[i]=Serial.read();

Грубо говоря, мы тут указываем компилятору "Не обращай внимание что мы объявили t как int. Временно забудь про это. В этой строке считай что t, это указатель на массив байтов".

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

basilblinov пишет:

Сэньк ю. Ща домой с праци, пожру и душить биты!!!

А нужно байты :)

Цитата:

Что должен отличать настоящий интеллигент?

Гоголя от Гегеля,
Гегеля от Бебеля,
Бебеля от Бабеля,
Бабеля от кабеля,
кабеля от кобеля, а кобеля от суки.
 

 

basilblinov
Offline
Зарегистрирован: 02.06.2013

К чему это??? Троль?

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

basilblinov пишет:

К чему это??? Троль?

Это к тому что не нужно путать биты и байты.

Конечно, практически уверен - вы просто очепятались. Ну вот просто вспомнился анекдот по этому поводу. А так как вы уже задали шутливо-офтопное направление словами "пожрать, душить и т.п." - то решил рассказать. Поддержать ваше настроение, а не дразнить (тролить вас) вас. Тролить - нет ни желания, ни времени. Тем более земляка :)  (ага. "праця" вас выдала ;)

Наверное вы еще не успели "пожрать", поэтому и восприняли это как наезд :)

 

basilblinov
Offline
Зарегистрирован: 02.06.2013

1 Байт - 8 бит. Вот я буду душить по одному))) Проехали. Просто к слову было. Оффтоп короче.

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

basilblinov пишет:

1 Байт - 8 бит. Вот я буду душить по одному))) Проехали. Просто к слову было. Оффтоп короче.

Ну а как же без офтопа :) Это же место общения :)  Все мы человеки.

Вы лучше, как вам уже говорили, выложите свой вариант

> float D  =  (data[3] << 24) + (data[2] << 16) + (data[1] << 8) + data[0]

Только не забудет описать что именно вы шлете и какой именно "бред" вы получаете. "ничего не выходит" - это слишком не информативно.

И все, таки определитесь, в каком виде вы собираетесь данные передавать "бинарно" или "текстово".

Потому что вот это data[3]<<24 - подразумевает что полученны бинарные данные.

А "я шлю руками из терминалов" - означает что данные шлются в виде текстовой строки (встроенный терминал не умеет работать с бинарными).

И "принимать собирать" их, естественно нужно по разному.

Вообщем принятия этого решения  - вы никуда сдвинутся не сможете. Вначале определится с форматом данных, потом "как же этот формат читать".

А еще - начните, наверное с того что проще - с целых чисел. Потом уж дробными займетесь.

 

 

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

Вот тут, примерно похожую проблему обсуждали (правда там наоборот. из ардуины в процессинг числа слали, но разницу между текстовым и бинарным - обсудили)

Serial read | Аппаратная платформа Arduino

basilblinov
Offline
Зарегистрирован: 02.06.2013

У меня просто готовые скетчи и в ардуину и в процессинг. Но не хватает последнего звена - переслать уставку из процессинга в ардуину. Из ардуины я получаю все свои значения, а вот из процессинга я даже не знаю как отправить в ардуину. При поиске я заметил, что практически никто не отсылает данные из П в А. Поэтому я решил иммитационно принимать по serial ардуиной данные и обрабатывать их. И тут тоже тупик. По поводу пересылки из П в А я создал отдельную тему. Вот теперь жду пока там заплюют типа (гугли и т.п...... а нах ты тогда тут делаешь на форуме?).

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

void ОФФТОП(){

/*А вообще все мы когда-то жали на спектруме load"" и думали, что это заклинание... Так господа "ведающие" - не цурайтесь подсказывать менее опытным программистам, ибо объяcняя что-то кому-то - -можешь открыть что-то и для себя */

}

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

Я думаю, вам стоит пересмотреть свой подход.

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

Если посылают в поиск, так может стоит поискать? Посмотреть стандартные примеры и т.п.

Если посоветовали "посмотреть фирмату", так посмотрите. Вы тут кричали "дайте пример", ну так чем фирмата не пример? Не нужна она вам, ну так залезте и посмотрите как она данные шлет.

По поводу "подсказать менее опытным".

А вам подсказали: atoi, решите бинарные или текстовые данные парсить будете, выложите что у вас выходит...

Что вы из этих советов попытались сделать?  А пошли завели новую ветку и ждете пока вам выложат на блюде готовое.

А ведь эту задачу "посылать/принимать даныне через сериал" (не важно что там на другом конце провода Processin, другая ардуина, C#, передатчик) - не раз и не два решали. Десятки. И расписывали/разжовывали. Хочется понять? Ну так разбирайтесь. Потом адаптируйте к своей задаче. не выходит, показывайте, спрашивайте. А то... "а ну ка организуйте мне, иначе нах вы тут?".

Вот почему я могу взять гугл и найти пример http://my.safaribooksonline.com/book/hobbies/9781449399368/serial-communications/sending_binary_values_from_processing , а вы нет? Вот ровно то что вы говорили "а нет таких примеров" - посылать данные из процессинга в ардуину. 

А даже если бы и не небыло. То разобратся с подобными, и по тому же принципу - написать самому пример. Только вот разбиратся нужно не говорить, а делать. Самому прилагать усилия.

P.S. Кстати книга эта уже не раз на форуме упоминалась (но в данному случая я нашел этот пример 5-ть минут погуглив).

__Alexander
Offline
Зарегистрирован: 24.10.2012

basilblinov пишет:

Просто если я пишу программу, то делаю её всегда универсальной. 

Ого! Можно я рядом постою?

basilblinov
Offline
Зарегистрирован: 02.06.2013

Ты предлагаешь мне читать все форумы? Если я час искал на Яндексе - и не нашёл? А ты за 5 минут нашел!!! Так флаг тебе в руки и от меня спасибо!!! А я не нашёл! Просто у плохих учителей - плохие ученики. Ссылка полезная - буду читать. До встречи.

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

>Ты предлагаешь мне читать все форумы?

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

> Если я час искал на Яндексе - и не нашёл?

Ну значит нужно либо учится искать, либо - завязывать с програмированием. Еще существует гугл, еще существует встроенный по сайту поиск. Да много чего, было-бы желание (специализированые поисковики по коду и т.п.) . И да "поискать" - это тоже нужно усилия приложить. А если вспоминить что паралельной ветке вам еще и название примера Максим давал, то... видимо у вас какие-то особые методы поиска.

>Просто у плохих учителей - плохие ученики.

Я вот не понял, это меня назвали плохим учителем или себя занесли в плохие ученики? Так как я учителем не являюсь, не припомню что-бы брал в ученики хама-скомороха, видимо себя так охарактеризовали.

>Ссылка полезная - буду читать

Еще можете что-нибудь по культуре общения почитать.

 

basilblinov
Offline
Зарегистрирован: 02.06.2013

Задуманное получилось. http://my.safaribooksonline.com/book/hobbies/9781449399368/serial-communications/sending_binary_values_from_processing хороший пример. Очень удобный и тем более мне подошёл, тем что я передаю массивы.

Tagом передается имя переменной, indexом передаём индекс массива, а value передаёт непосредственно значение. Правда value передает только int, но я вышел из положения

void sendMessage(char tag, int index, float value){
  // send the given index and value to the serial port
  port.write(HEADER);
  port.write(tag);
  port.write(index);
  int val = int(value*100);// моя float имеет только сотые - умножил на сто и привёл в int
  char c = (char)(val / 256); // msb
  port.write(c);
  c = (char)(val & 0xff);  // lsb
  port.write(c);
}

в Arduino провёл обратные манипуляции

void to_Processing(){

  if ( Serial.available() >= MESSAGE_BYTES)
  {
    if( Serial.read() == HEADER)
    {
      char tag = Serial.read();
      if(tag == cTEMP)
      {
        int index = Serial.read(); // this was sent as a char

        float val = Serial.read() * 256;
        val = (val + Serial.read()) / 100; // обр. преобразование
        tContr[index] = val;
      }
    }
  }
}

отрицательные числа не передаёт к сожалению. Тут можно подумать как. Если кто может упростить или унифицировать этот процесс - милости просим. Могу предложить пока только детский вариант - передавать модуль числа, а минус привязать к tag или index.