myPort.readString() читает не все.

Qwq
Offline
Зарегистрирован: 12.08.2013

Здравствуйте! 

только начинаю разбираться в arduino и в processing

попробовал прочитать многострадальный dht11 и по показаниям построить гарфик. Наловил всяких странных косяков:

1) процессинг довольно часто счтывает строку не польностью, из случайного места - т.е. не только начало, а может любой фрагмент

2)какието непонятки с прямоугольником, которым я стираю старую линию графика - он становится шире к ближе к концу. 

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

Где я накосячил? 

Привожу весь код целиком - его не много, а вдруг я чего не так объявил

1) ардуина

#include "DHT.h"

#define DHTPIN 2     // what pin we're connected to

// Uncomment whatever type you're using!
#define DHTTYPE DHT11   // DHT 11 
//#define DHTTYPE DHT22   // DHT 22  (AM2302)
//#define DHTTYPE DHT21   // DHT 21 (AM2301)

// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor

DHT dht(DHTPIN, DHTTYPE);
int led = 13;

void setup() {
  Serial.begin(38400); 
  //Serial.println("DHTxx test!");
  pinMode(led, OUTPUT); 
  dht.begin();
}

void loop() {
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  float h = dht.readHumidity();
  float t = dht.readTemperature();

  // check if returns are valid, if they are NaN (not a number) then something went wrong!
  digitalWrite(led,HIGH);
  if (isnan(t) || isnan(h)) {
    Serial.println("Failed to read from DHT");
  } 
  else {
    Serial.print("Humidity: "); 
    Serial.print(h);
    Serial.print("% Temperature: "); 
    Serial.print(t);
    Serial.println("*C  ");
    digitalWrite(led,HIGH);
    delay(20);
    digitalWrite(led,LOW);
  }
  digitalWrite(led,LOW);
  delay(480);
  digitalWrite(led,HIGH);
  delay(40);
  digitalWrite(led,LOW);
  delay(480);

}

2)Процесссинг 

import processing.serial.*;
Serial myPort;  // Create object from Serial class
int xn=0, yn=0, xk=0, yk=0, yz=0, yt=0; 
float val, val1;
String portName, myString;
void setup()
{
  size(640, 360);
  textFont(createFont("Arial-BoldMT", 36));
  background(0);
  portName = Serial.list()[0];
  println("Now slave device present on "+portName+" port");
  myPort = new Serial(this, portName, 38400);
}
void draw()
{
  textSize(14);
  while (myPort.available () > 0) 
  {
    myString = myPort.readString();
    //print(myString);//test line show myString content
    int LTest = myString.length();
    if (LTest < 37)
    {
      //это если мы всякую фигню прочли то ее только показать - при неправильном преобразовании вылетает. 
    }
    else
    {
      int  SerchVal = myString.indexOf("Humidity:"); 
      if (myString.indexOf("Humidity:")>=0) {
        val = parseFloat(myString.substring(myString.indexOf("Humidity:")+10, myString.indexOf("% ")));// откуда ошибка StringIndexOutOfBoundsExeption:string index out of range:-36
      }   
      if (myString.indexOf("Temperature:")>=0) {

        val1 = parseFloat(myString.substring(myString.indexOf("Temperature:")+13, myString.indexOf("*C")));
        println((val)+" hum"); 
        println((val1)+" temp");
      }
    }
    fill(0);
    noStroke();
    rect(0, 0, 640, 50);//прямоугольник
    fill(255);
    text("myString is: " + myString, 5, 20);
    stroke(50);
    line (0, 300, 640, 300);//опорная линия temp
    line (0, 200, 640, 200);//опорная линия hud   

    yk=(int)val;//temp
    fill(0);
    noStroke();
    rect (xn+3,50,xn+6,298);//почему становится шире? 
    
    stroke(190);
    line (xn, 300-yn, xk, 300-yk);
    yn=yk;

    yz=(int)val1;//hud
    stroke(220);
    line (xn, 200-yt, xk, 200-yz);
    xn=xk;
    yt=yz;
    xk++;
    if (xk > 635) {xn=0;xk = 1;}
  }
}

 

Версия processing 2.0.1 Mac

Версия Arduino IDE 1.0.5 Mac

arduino nano v3 китайская на 328 меге, кормится от USB

Заранее спасибо. 

 

 

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

Зачем в строке передавать имена ваших переменных ? Исключить за ненадобностью !)

Вот мой код процессинга:



import processing.serial.*;
 
float H ;        
float T ;      


int lf = 10; 
Serial myPort;
 
 void setup() {
size(640, 480);
textSize(24);

 myPort = new Serial(this, "COM11", 9600);
 myPort.bufferUntil(lf);
 }
 
 void draw() {
   
 smooth();
 background(20);
 textSize(24);
 fill(250); 
 text("Влажность      " + H + "   %", 2, 50);
 text("Температура  " + T + "  °С", 2, 80);

 }
 
 
void serialEvent(Serial myPort) {
  
    String myString = myPort.readStringUntil('\n');
    if (myString != null) {
    myString = trim(myString);
 
    float sensors[] = float(split(myString, ','));

    H = sensors[0];
    T = sensors[1];
    // далее по мере добавления переменных в передаваемой стороке добавляем аналогично ,т.е. например
    // следующая переменная будет X= sensors[2]; ( где sensors[2] приходящая третья переменная в строке)
    
}
 }

 

А это с ардуины:



#include <DHT.h>
DHT dht(5, DHT21);

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

}
void loop(void)
{ 
 
float h = dht.readHumidity();
float t = dht.readTemperature();


  Serial.print(h);
  Serial.print(",");
  Serial.println(t);


  }

 

 
Qwq
Offline
Зарегистрирован: 12.08.2013

По моей идее должно быть можно обычным терминалом посмотреть в понятнлм человеку виде... Опять же данных может быть существенно больше и не только однотипно понятных - например передать на комп смску считанную с gsm-модуля Завтра буду внимательно с компа смотреть Ваши примеры. То что у меня код индийский я знаю-не программист я совсем.

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

Передавать имеет смысл толко данные, разделенные условным знаком.

например в таком виде

Serial.println (";"+H+";"+T);

А принимать в таком

str_data = split(list, ';');

Поясню. Ардуино передает показания, которые начинаются с ";".

Процессинг ловит их и записывает в переменную типа String  str_data[]

Ну а далее переводишь из String в float и строишь график.

Qwq
Offline
Зарегистрирован: 12.08.2013

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

Сейчас попробую перепилить пачку print`ов в 1 строчку - по идее должно стать лучше. 

Qwq
Offline
Зарегистрирован: 12.08.2013

Заменил в ардуине 

    Serial.print("Humidity: "); 
    Serial.print(h);
    digitalWrite(led,HIGH);
    delay(1);
    digitalWrite(led,LOW);
    //Serial.print("/n");
    Serial.print("% Temperature: "); 
    Serial.print(t);
    Serial.println("*C  ");

на 

    String hi=String(int (h));
    String ti=String(int (t));
    String outpotline = "Humidity: "+hi+".00% Temperature: "+ti+".00*C  ";
    Serial.println(outpotline);

стало намного лучше, но все равно не редко строку не целиком считывает... думаю дальше

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

Qwq пишет:

Заменил в ардуине 

    Serial.print("Humidity: "); 
    Serial.print(h);
    digitalWrite(led,HIGH);
    delay(1);
    digitalWrite(led,LOW);
    //Serial.print("/n");
    Serial.print("% Temperature: "); 
    Serial.print(t);
    Serial.println("*C  ");

на 

    String hi=String(int (h));
    String ti=String(int (t));
    String outpotline = "Humidity: "+hi+".00% Temperature: "+ti+".00*C  ";
    Serial.println(outpotline);

стало намного лучше, но все равно не редко строку не целиком считывает... думаю дальше

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

Qwq
Offline
Зарегистрирован: 12.08.2013

ingener.solovyev пишет:

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

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

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

Qwq пишет:

ingener.solovyev пишет:

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

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

а зачем тект то передавать? Ты и запутался во все этом. Упрости. Передал данные, на том конце пнгчитал и все. А текст в самом процессинге и добавь.

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

У компа буду пример постараюсь развернутей написать. Сам недавно все это проходил. Спасибо форуму, дали направление.

Qwq
Offline
Зарегистрирован: 12.08.2013

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

ну или же у нам к ардуине gsm-шилд прикручен и там СМС-ка, которую парсить вообще не надо а просто передать на комп и показать... 

в переспективе будет недологер 4-шт температуры-влажности-состояния 4-х концевиков который будет жаловаться\сбрасываться по смс и на комп показывать график влажность-темпиратуры и под этим всем последняя пришедшая смс-ка. Причем графики вторичны.

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

А что за текст ты собрался передавать в смс?

Qwq
Offline
Зарегистрирован: 12.08.2013

1) запрос на состояние датчиков

2)сброс тревог + кто сбросил соответственно.

3)сообщение для того кто первый прдет проверять все и посмотрит на консоль типа "сделай некое действие"

dead_mazai
Offline
Зарегистрирован: 22.08.2013

Если вопрос еще актуален могу скинуть реализацию протокола для ардуины и процессина для кидания между ними любого текста.  

 

Qwq
Offline
Зарегистрирован: 12.08.2013

Актуален с аккадимической точки зрения. Пока я проблему решли тем что строю график в консоли псевдографикой на cgi. 

dead_mazai
Offline
Зарегистрирован: 22.08.2013

Ардуинка

boolean sp_packetAvailable;      // Флаг завершения приема пакета
String sp_startMarker;           // Переменная, содержащая маркер начала пакета
String sp_stopMarker;            // Переменная, содержащая маркер конца пакета
String sp_dataString;            // Здесь будут храниться принимаемые данные
int sp_startMarkerStatus;        // Флаг состояния маркера начала пакета
int sp_stopMarkerStatus;         // Флаг состояния маркера конца пакета
int sp_dataLength;               // Флаг состояния принимаемых данных

// Процедура инициализация протокола sp_SetUP задает маркеры начала и конца пакета и обнуляет протокол
void sp_SetUp()
  {
    sp_startMarker = "<bspm>";     // Так будет выглядеть маркер начала пакета
    sp_stopMarker = "<espm>";      // Так будет выглядеть маркер конца пакета
    sp_ResetAll();                 // Полный сброс протокола
  }
//Процедура полного сброса протокола
void sp_ResetAll()
  {
    sp_dataString = "";           // Обнуляем буфер приема данных
    sp_Reset();                   // Частичный сброс протокола
  }
//процедура частичного сброса протокола
void sp_Reset()
  {
    sp_startMarkerStatus = 0;     // Сброс флага маркера начала пакета
    sp_stopMarkerStatus = 0;      // Сброс флага маркера конца пакета
    sp_dataLength = 0;            // Сброс флага принимаемых данных
    sp_packetAvailable = false;   // Сброс флага завершения приема пакета
  }
  
  void sp_Send(String data) //отправка данных на ПК
{
  delay(10);
  Serial.write("<bspm>");         // Отправляем маркер начала пакета
  Serial.write(data.length());          // Отправляем длину передаваемых данных
  for (int i=0; i < data.length(); i++){
   Serial.write(byte(data.charAt(i)));
     
}
  Serial.write("<espm>");
  
  
   
}  
void sp_Read()
{
  while(Serial.available() > 0 && sp_packetAvailable==false)            // Пока в буфере есть что читать и пакет не является принятым
  {
      
    int bufferChar = Serial.read();                           // Читаем очередной байт из буфера
    if(sp_startMarkerStatus < sp_startMarker.length())        // Если стартовый маркер не сформирован (его длинна меньше той, которая должна быть) 
    {  
     if(sp_startMarker[sp_startMarkerStatus] == bufferChar)   // Если очередной байт из буфера совпадает с очередным байтом в маркере
     {
       sp_startMarkerStatus++;                                // Увеличиваем счетчик совпавших байт маркера
     }
     else
     {
       sp_ResetAll();                                         // Если байты не совпали, то это не маркер. Нас нае****, расходимся. 
     }
    }  
    else
    {
     // Стартовый маркер прочитан полностью
       if(sp_dataLength <= 0)                                 // Если длинна пакета на установлена
       {
         sp_dataLength = int (bufferChar);                          // Значит этот байт содержит длину пакета данных
       }
      else                                                    // Если прочитанная из буфера длинна пакета больше нуля
      {
        if(sp_dataLength > sp_dataString.length())            // Если длинна пакета данных меньше той, которая должна быть
        {
          sp_dataString =sp_dataString+ (char)bufferChar;                  // прибавляем полученный байт к строке пакета
        }
        else                                                  // Если с длинной пакета данных все нормально
        {
          if(sp_stopMarkerStatus < sp_stopMarker.length())    // Если принятая длинна маркера конца пакета меньше фактической
          {
            if(sp_stopMarker[sp_stopMarkerStatus] == bufferChar)  // Если очередной байт из буфера совпадает с очередным байтом маркера
            {
              sp_stopMarkerStatus++;                              // Увеличиваем счетчик удачно найденных байт маркера
              if(sp_stopMarkerStatus == sp_stopMarker.length())
              {
                // Если после прочтения очередного байта маркера, длинна маркера совпала, то сбрасываем все флаги (готовимся к приему нового пакета)
                sp_Reset();    
                sp_packetAvailable = true;                        // и устанавливаем флаг готовности пакета
              }
            }
            else
            {
              sp_ResetAll();                                      // Иначе это не маркер, а х.з. что. Полный ресет.
            }
          }
          //
        }
      } 
    }    
  }
}

sp_Read - читает возвращает значение sp_datastring

sp_Send - отправляет на комп или любое другое устройство например на ту же Ардуинку

Processing

boolean sp_packetAvailable;      // Флаг завершения приема пакета
String sp_startMarker;           // Переменная, содержащая маркер начала пакета
String sp_stopMarker;            // Переменная, содержащая маркер конца пакета
String sp_dataString;            // Здесь будут храниться принимаемые данные
int sp_startMarkerStatus;        // Флаг состояния маркера начала пакета
int sp_stopMarkerStatus;         // Флаг состояния маркера конца пакета
int sp_dataLength;               // Флаг состояния принимаемых данных

// Процедура инициализация протокола sp_SetUP задает маркеры начала и конца пакета и обнуляет протокол
void sp_SetUp()
  {
    sp_startMarker = "<bspm>";     // Так будет выглядеть маркер начала пакета
    sp_stopMarker = "<espm>";      // Так будет выглядеть маркер конца пакета
    sp_ResetAll();                 // Полный сброс протокола
  }
// Процедура полного сброса протокола 
void sp_ResetAll()
  {
    sp_dataString = "";           // Обнуляем буфер приема данных
    sp_Reset();                   // Частичный сброс протокола
  }  
//Процедура частичного сброса протокола  
void sp_Reset()
  {
    sp_startMarkerStatus = 0;     // Сброс флага маркера начала пакета
    sp_stopMarkerStatus = 0;      // Сброс флага маркера конца пакета
    sp_dataLength = 0;            // Сброс флага принимаемых данных
    sp_packetAvailable = false;   // Сброс флага завершения приема пакета
    
  }  
//Процедура отправки данных роботу, отправка идет по байтово связано с особенностями библиотеки
void sp_Send(String data) 
{
  //отправляем маркер начала пакета по байтам 
  for (int i=0; i < sp_startMarker.length(); i++){
   server.write(byte(sp_startMarker.charAt(i)));
  
}
  // Отправляем длину передаваемых данных
 
  server.write(byte(data.length()));          
  // Отправляем сами данные
  for (int i=0; i < data.length(); i++){
   server.write(byte(data.charAt(i)));
     
}
  //отправляем маркер конца пакета  
  
  for (int i=0; i < sp_stopMarker.length(); i++){
   server.write(byte(sp_stopMarker.charAt(i)));  
  
}


}  
//Процедура чтения полученных данных от робота
void sp_Read()
{
  
  while(sp_packetAvailable==false)            // Пока пакет не является принятым
  {
  
    byte bufferChar = byte (server.read());                           // Читаем очередной байт из буфера
      if(sp_startMarkerStatus < sp_startMarker.length())        // Если стартовый маркер не сформирован (его длинна меньше той, которая должна быть) 
    {  
      if(sp_startMarker.charAt(sp_startMarkerStatus) == char(bufferChar))   // Если очередной байт из буфера совпадает с очередным байтом в маркере
     {
       sp_startMarkerStatus++;                                // Увеличиваем счетчик совпавших байт маркера
     }
     else
     {
       sp_ResetAll();       // Если байты не совпали, выходим нафиг, это не маркер. Нас нае**** 
     }
    }  
    else
    {
     // Стартовый маркер прочитан полностью
     if(sp_dataLength <= 0)                                 // Если длинна пакета на установлена
       {
        sp_dataLength = int (bufferChar);                          // Значит этот байт содержит длину пакета данных
       }
      else                                                    // Если прочитанная из буфера длинна пакета больше нуля
      {
        if(sp_dataLength > sp_dataString.length())            // Если длинна пакета данных меньше той, которая должна быть
        {
          sp_dataString = sp_dataString + char(bufferChar);                  // прибавляем полученный байт к строке пакета
        }
        else                                                  // Если с длинной пакета данных все нормально
        {
          if(sp_stopMarkerStatus < sp_stopMarker.length())    // Если принятая длинна маркера конца пакета меньше фактической
          {
            if(sp_stopMarker.charAt(sp_stopMarkerStatus) == char(bufferChar))  // Если очередной байт из буфера совпадает с очередным байтом маркера
            {
              sp_stopMarkerStatus++;                              // Увеличиваем счетчик удачно найденных байт маркера
              if(sp_stopMarkerStatus == sp_stopMarker.length())
              {
                // Если после прочтения очередного байта маркера, длинна маркера совпала, то сбрасываем все флаги (готовимся к приему нового пакета)
                sp_Reset();    
                sp_packetAvailable = true;                        // и устанавливаем флаг готовности пакета
                break;  
            }
            }
            else
            {
              sp_ResetAll();                                      // Иначе это не маркер, а х.з. что. Полный ресет.
                
          }
          }
          
        }
      } 
    }    
  }
}

Все то же самое  ! только проверь sp_Read и sp_Send, так как я использую bluetoothDesktop поэтому без Serial

dDoom
Offline
Зарегистрирован: 22.11.2013

А можно для процессинга дополнить пример, как реагировать на эти данные?