Передача дробного числа в процессинг.

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

Подскажи как передать дробь?

Мысли пока такие, процессинг принимает только целые. В Ардуино я умножаю дробь на (пусть десятичная) 10, получаю целое значение и передаю его в процессинг, как в процессинге его пробразовать в дробь?

 

Может есть еще способы?

 

Спасибо!

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

Всё зависит от лени подумать. Можно передавать отдельно целую, и отдельно дробную части. Можно преобразовать число в строку и передать "как есть". А ваш вариант с умножением на 10 вообще непонятно почему вызывает вопросы, если в дуине умножили, в процессинге разделите обратно. Или есть проблемы с использованием функции float()?

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

ourlive пишет:

Всё зависит от лени подумать. Можно передавать отдельно целую, и отдельно дробную части. Можно преобразовать число в строку и передать "как есть". А ваш вариант с умножением на 10 вообще непонятно почему вызывает вопросы, если в дуине умножили, в процессинге разделите обратно. Или есть проблемы с использованием функции float()?

Есть проблемы с float. 

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

 

Спасибо!

 


//открываем порт Serial
import processing.serial.*;
Serial port;

//Задаем переменные
String t = ""; //температура
String h = ""; //влажность
String data = ""; //хранит строку целиком
int index = 0; //задается строка где будет стоять запятая.
PFont font;  //задаем шрифт


void setup()
{
  size (300, 300); //задаем размер окна
  port = new Serial(this, "COM3", 9600);
  port.bufferUntil('.');
  font = loadFont("BookmanOldStyle-Bold-96.vlw"); //задаем шрифт
  textFont (font, 64);
}


void draw()
{
  background(255,255,255); //задаем фон
  fill(82, 171, 82);
  text("T=", 40, 100);
  text(t, 128, 100); //задаем пустую строку где будут содержаться данные температуры
  text("H=", 40, 200);
  text(h, 128, 200); //задаем пустую строку где будут содержаться данные влажности
  
}

void serialEvent (Serial port)

{
  data = port.readStringUntil ('.');
  data = data.substring(0, data.length() - 1);
  
  index = data.indexOf(",");
  t = data.substring(0, index);
  h = data.substring(index+1, data.length());
}
  

 

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

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

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Лучше так и оставить, строками, потому что "числами" не получится, ввиду разных размеров (возможно, представления и прочих нюансов) float на Ардуино и на компе.

Вообще, обмен бинарными, даже целыми числами сопряжен с множеством проблем (размер, big-endian/little-endian и т.п.)

 

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

Для функции serialEvent нет комментариев, разберитеть для чего нужна каждая строка в отдельности, это должно снять вопросы о том, как передать данные в другом формате. А с точки зрения понимания процесса возможно лучше вообще отказаться от данной функции в пользу структуры

while (Port.available() > 0) { 
}

 

ingener.solovyev
Offline
Зарегистрирован: 12.02.2013

Разобрался немного. Сделал вот так:

 

import processing.serial.*;
Serial port;
PFont font;
int T1, T2, T3, T4, H1, H2, H3, H4, R, G, B;
float t, h;



void setup()
{
  size (400, 400); //задаем размер окна
  port = new Serial(this, "COM3", 9600);
  port.bufferUntil('.');
  font = loadFont("Andalus-100.vlw"); //задаем шрифт
  textFont (font, 100);
}

void draw() {
 
 while (port.available() > 0)
 {
 T1 = port.read();
 delay(10);
 T2 = port.read();
 delay(10);
 T3 = port.read();
 delay(10);
 T4 = port.read();
 delay(10);
 H1 = port.read();
 delay(10);
 H2 = port.read();
 delay(10);
 H3 = port.read();
 delay(10);
 H4 = port.read();
   }

 background(255, 255, 255);
 fill(46, 209, 2);
 text("T=", 15, 150);
 text(T1-48, 120, 150);
 text(T2-48, 180, 150);
 text(".", 230, 150);
 text(T4-48, 245, 150);
 text("C", 305, 150);
 text("H=", 15, 300); 
 text(H1-48, 120, 300);
 text(H2-48, 180, 300);
 text(".", 230, 300);
 text(H4-48, 245, 300); 
 text("%", 305, 300);
 
 
}

 

 

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

delay() - это плохо, очень вероятны непредсказуемые глюки в чтении кома.

обычно данные по com-порту передаются в формате [заголовок строки] [данные].

String bufer="";  //буфер чтения
import processing.serial.*;

//открытие порта и другие начальные установки упущены

void draw() { //***********************основной цикл
 while (myPort.available() > 0) {
    char inByte = myPort.readChar(); // прочитать символ с порта
    if (inByte==char(13)) { // после прочтения символа начала строки: char(13) - пример
      fi(); // отправить буфер на обработку
      bufer=""; } // сбросить буфер
    else {bufer=bufer+inByte;} // сбор данных в буфер до обнаружения нового заголовка
    }  
} //***********************************draw

void f1 () {
  if (bufer.length()==64) { //если буфер чтения правильной длины (64 - пример)
 // выполнить обработку буфера (разделить на подстроки и преобразовать в нужный формат)
  }
}

 

корявенько написал, но как то так лучше

Vanovich
Offline
Зарегистрирован: 16.05.2012

Код на с++ для ардуино, преобразующий float (или массив float)
в последовательность символов постоянной длины.
 

void serialPrintFloatArr(float * arr, int length) {
  for(int i=0; i<length; i++) {
    serialFloatPrint(arr[i]);
    Serial.print(",");
  }
}


void serialFloatPrint(float f) {
  byte * b = (byte *) &f;
  for(int i=0; i<4; i++) {
    
    byte b1 = (b[i] >> 4) & 0x0f;
    byte b2 = (b[i] & 0x0f);
    
    char c1 = (b1 < 10) ? ('0' + b1) : 'A' + b1 - 10;
    char c2 = (b2 < 10) ? ('0' + b2) : 'A' + b2 - 10;
    
    Serial.print(c1);
    Serial.print(c2);
  }
}


void writeArr(void * varr, uint8_t arr_length, uint8_t type_bytes) {
  byte * arr = (byte*) varr;
  for(uint8_t i=0; i<arr_length; i++) {
    writeVar(&arr[i * type_bytes], type_bytes);
  }
}


// thanks to Francesco Ferrara and the Simplo project for the following code!
void writeVar(void * val, uint8_t type_bytes) {
  byte * addr=(byte *)(val);
  for(uint8_t i=0; i<type_bytes; i++) { 
    //Serial1.write(addr[i]);
    Serial.write(addr[i]);
  }
}

В процессинге распарсиваем эту строку обратно во float
 

float decodeFloat(String inString) {
  byte [] inData = new byte[4];
  
  if(inString.length() == 8) {
    inData[0] = (byte) unhex(inString.substring(0, 2));
    inData[1] = (byte) unhex(inString.substring(2, 4));
    inData[2] = (byte) unhex(inString.substring(4, 6));
    inData[3] = (byte) unhex(inString.substring(6, 8));
  }
      
  int intbits = (inData[3] << 24) | ((inData[2] & 0xff) << 16) | ((inData[1] & 0xff) << 8) | (inData[0] & 0xff);
  return Float.intBitsToFloat(intbits);
}

Работает отлично.
Придумно не мной, это часть библиотеки http://www.varesano.net/projects/hardware/FreeIMU#v0.4