Collecting long values from serial port

Hi,
I am trying to collect values for several variables for my sketch in Arduino, from serial. My problems are that the variables are 53 and most of them time_t or Epoch date time format. If using DateTime library, on its playground page an example to collect the value for a 10 bytes variable is presented, which updates the clock in Arduino. However, this approach was not useful in my case due to the large number of variables, ending by overloading Arduino (Duemillanove 328). So, looking for a better way to retrieve long values from a Serial Port, I saw Firmata. Great but there is still not a version for Java, and my API to send the values to the Serial port to Arduino is a Java API.
Check: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1244065761
There, Agib, got a good step on that direction.

I attempted another path, by using Messenger library from:
http://www.arduino.cc/playground/Code/Messenger
I had problems with the "send" feature of Arduino IDE's Monitor. Thomas was very nice to help me looking for alternatives.
After getting readList example sketch up and running, I noticed that it can only retrieve int and char values using the functions readInt() or readChar()... very sad because it is a great tool that can collect the values for several variables just separated by a space or another character but limited to integers and the first char of strings.
I needed a readLong() that is not existing in the library.

If you need it as well, then this is what worked for me:

  1. download the last version of Messenger Library and install it.
  2. edit with Kate (linux) or notepad (windows) all the three main files of its Messenger folder as follows:
  3. add in Messenger.cpp, between the blocks for int and char:

long Messenger::readLong() {
if (next()) {
dumped = 1;
return atol(current); // atol for long instead of atoi for int variables
}
return 0;
}

  1. added inside keywords.txt, between the lines for int and char:
    readLongKEYWORD2

  2. added on Messenger.h, under "public" between int and char lines:
    long readLong();

IF you did not run a sketch with the Messenger library before, you are set. But if you did it, now you may get the error:

undefined reference to `Messenger::readLong()'

This is because when running the library, it creates a Messenger.o file. If you have it, just delete it, and compile your sketch using the new function readLong() as you would use the readInt().

Now you can collect values in Long, using this library just as Int and Char.

regards,

Gian Paolo

The library was just updated including the readLong() feature. :smiley:

here I post as well an example on using Message library, to set the values of several variables of different type. I have several tens of variables in my project and this approach has provided the best results.

-------------------------------------------------------

/**
*

  • By using Thomas Ouellet's Messenger library with a switch/case method,
  • this example sets the values of several variables from serial port readings.
  • The variables are char, integer and long separated by "|".
  • From serial port, the incoming message can be something like:
  • "Y|N|10|1000|123456789|987654321"
  • You can test it by copy and pasting this string into the terminal or console window
  • and pressing "enter key".
  • by Gian Paolo Sanino
    */

#include <Messenger.h>
Messenger message = Messenger('|'); // Instantiate Messenger object with "|" as separator

// list of variables that will be updated from a serial port message
char charvar1;
char charvar2;
int integervar1 =0;
int integervar2 =0;
long longvar1 =0;
long longvar2 =0;

void setup() {
Serial.begin(115200); // Initiate Serial Communication
}

void loop() {
// The following two lines is the most effective way of using Serial and Messenger

int Read =0; // this variable will be used as a counter or "readings"
// to synchronize the values and their respective variables
// It is important to define it here as "0" reset its value
// with each loop.

char charValue;
int intValue =0;
long longValue =0;

while ( Serial.available() ) {

if ( message.process(Serial.read() ) ){

// To update char variable values
while( message.available() && Read < 2 ) {
Read++;
charValue = message.readChar();
switch (Read) {
case 1:
charvar1 = charValue;
Serial.print("Char 1 value is : ");
Serial.println(charvar1);
break;
case 2:
charvar2 = charValue;
Serial.print("Char 2 value is : ");
Serial.println(charvar2);
break;
}
}

// To update integer variable values
while( message.available() && Read >= 2 && Read < 4 ) {
Read++;
intValue = message.readInt();
switch (Read) {
case 3:
integervar1 = intValue;
Serial.print("Integer 1 value is : ");
Serial.println(integervar1);
break;
case 4:
integervar2 = intValue;
Serial.print("Integer 2 value is : ");
Serial.println(integervar2);
break;
}
}

// Section to update long variable values
while( message.available() && Read >= 4 && Read <= 6 ) {
Read++;
longValue = message.readLong();
switch (Read) {
case 5:
longvar1 = longValue;
Serial.print("Long 1 value is : ");
Serial.println(longvar1);
break;
case 6:
longvar2 = longValue;
Serial.print("Long 2 value is : ");
Serial.println(longvar2);
break;
}
}

}
}
}

I don't get it!! :-[and i have tried soo hard. i would like to send 3 longs, but nothing happens with messenger.i have last version of messenger wich include readLong();

thank you .

here's my code

PROCESSING

import processing.serial.*;



Serial myPort;   

String[] tokens; 
float x []=new float[1000000];
float y []=new float[1000000];
float z []=new float[1000000];

int xc []=new int[1000000];
int yc []=new int[1000000];
int zc []=new int[1000000];


int inbyte=0;

int a=0;
 
String xs;
String ys;
String zs;
String entre;
String tot;

void setup() {


  
  size(400,400);

  String[] lines = loadStrings("p.txt");
  String allText = join(lines, " ");
  tokens = splitTokens(allText, " ,");

  String portName = Serial.list()[0];
  myPort = new Serial(this, portName,115200);
  myPort.write("err");
}
void draw(){
 inbyte=0;
for(int i=0;i<tokens.length;i+=3){
    x[i]=float(tokens[i]);
    y[i]=float(tokens[i+1]);
    z[i]=float(tokens[i+2]);
    
    xc[i]=int(x[i]*1000);
    yc[i]=int(y[i]*1000);
    zc[i]=int(z[i]*1000);
 
 

 } 
 inbyte= myPort.read();
 if((myPort.available()>0)&&(inbyte=='A')){
   myPort.clear();
   xs=str(xc[a]);
   ys=str(yc[a]);
   zs=str(zc[a]);
   entre="|";
    myPort.clear();

 myPort.write(xs+entre+ys+entre+zs);

  
}
 if((myPort.available()>0)&&(inbyte=='B')){
   myPort.clear();
   a+=3;
   xs=str(xc[a]);
   ys=str(yc[a]);
   zs=str(zc[a]);
   entre="|";
   tot=xs+entre+yc+entre+zs;
    myPort.clear();

 myPort.write(tot);

  
}
println(xs+entre+ys+entre+zs);}
 if((myPort.available()>0)&&(inbyte=='C')){
  println(ok); 
 }

ARDUINO

#include <Messenger.h>
Messenger message = Messenger('|'); 

int dirpinx = 2;
int steppinx = 3;
int dirpiny = 5;
int steppiny = 6;
int dirpinz = 8;
int steppinz = 9;
long xc = 0;         
long yc = 0;  
long zc = 0;  

int xtot=0;
int ytot=0;
int ztot=0;
int xold=0;
int yold=0;
int zold=0;
int xval=0;
int yval=0;
int zval=0;

boolean xdir=true;
boolean ydir=true;
boolean zdir=true;
int start=-1;  

int a=0;
void setup() {
Serial.begin(115200);

pinMode(dirpinx, OUTPUT);
pinMode(steppinx, OUTPUT);
pinMode(dirpiny, OUTPUT);
pinMode(steppiny, OUTPUT);
pinMode(dirpinz, OUTPUT);
pinMode(steppinz, OUTPUT);

}

void loop(){

long xi=0;
long yi=0;
long fini=0;
int Read =0; 

 long longValue =0;


Serial.print('A', BYTE);
 
 
 while ( Serial.available() ) {

   if ( message.process(Serial.read() ) ){

     
     while( message.available() && Read <=3 ) {
      Read++;
      longValue = message.readLong();    
      switch (Read) {
         case 1:
           xc = longValue;
      
          
           break;
         case 2:
           yc = longValue;
        
           
           break;
            case 3:
           zc = longValue;
          
          
           break;
}
}   
}
}


if(xc>10000){
  Serial.print('C',BYTE);
  }
  
  
     
 xtot=xc;
 ytot=yc;
 ztot=zc;
 
if ( xold<=xtot){
  xval=xtot-xold;
  xdir=true;
}
else{
  xval=xold-xtot;
 xdir=false;
}
  if ( yold<=ytot){
  yval=ytot-yold;
  ydir=true;
}
else{
  yval=yold-ytot;
   ydir=false;
}
  if ( zold<=ztot){
  zval=ztot-zold;
  zdir=true;
}
 else{
  zval=zold-ztot;
zdir=false;
}
 




if (xval<yval){
  for(yi=0;yi<yval+1;yi++){
    
   avancey(ydir);


if(yi<xval){
    
  avancex(xdir);
   
  }
    

if(yi<zval){
  
  avancez(zdir);

 }
 delayMicroseconds(200); 

fini+=1;

  }

if (fini<yval){
  Serial.print('B', BYTE);

} 

}

if (xval>yval){
  for(xi=0;xi<xval+1;xi++){
avancex(xdir);
 if(xi<xval){
avancey(ydir);
}
if(xi<zval){
avancez(zdir);
}
delayMicroseconds(200); 
fini+=1;

 
  }
  if (fini<xval){
  Serial.print('B', BYTE);
}

 }

 xold=xtot;
yold=ytot;
zold=ztot;
 
}


void avancex(boolean dirx){ //x+y+z+
  
 if(dirx==true){
  digitalWrite(dirpinx, LOW); 
   }
   if(dirx==false){
    digitalWrite(dirpinx, HIGH);  
}
    digitalWrite(steppinx, LOW);  
    digitalWrite(steppinx, HIGH); 
     
  }   
  
void avancey(boolean diry){ //x+y+z+
  
 if(diry==true){
  digitalWrite(dirpiny, LOW); 
   }
   if(diry==false){
    digitalWrite(dirpiny, HIGH);  
}
    digitalWrite(steppiny, LOW);  
    digitalWrite(steppiny, HIGH); 
        
  } 
  
  void avancez(boolean dirz){ //x+y+z+
  
 if(dirz==true){
  digitalWrite(dirpinz, LOW); 
   }
   if(dirz==false){
    digitalWrite(dirpinz, HIGH);  
}
    digitalWrite(steppinz, LOW);  
    digitalWrite(steppinz, HIGH); 
         
  }

Hi Adrian,
I am not familiar with PROCESSING. But I would recommend to start by using something that works and from there to do the change you need in one step, test, next step, test and so on.
Too many changes in one step, make harder to find the problem.

The code I posted works. Use it making the change to the type and number of variables you have. Then include it into your main sketch.

In case it helps:

  1. check on messenger.h the size of the buffer (see the files of your messenger library - you can change it with notepad or Kate, etc). I set it on 128 bytes. Then in packages of six or five variables linked by the counter number of the code I provided, I have been able to set 53 variables without any problem in Arduino. But check your buffer size despite you are only downloading 3 variables. After doing this, remember to delete the file messenger.o and compile again your sketch so it uses the new library settings.

  2. I had a weird behavior of Arduino when using Serial.println(). Check my code and you will see two lines of "print" on each variable, to check if it is working fine. Alone it works fine but when I ported this code to my main sketch (quite big), Arduino did not worked anymore or if downloading the values they had mistakes. This happened to me until I commented (//) the lines of print() and println().

  3. I noticed that you used code to clear the port... not a good idea. At least to me, it did a mess. Use a 128 buffer size on the library, same as the capacity of Arduino Duemillanove. In the code I posted, you will see no flushing port as well as in the code of a Java API that I built to upload the values to Arduino. As I mentioned, It works great for my sketch of 53 variables, without flushing the port. When I send the values, to Arduino, it restarts and get them.

  4. Your problem(s) may be on Arduino sketch as well as in your processing sketch, or both. In the Arduino, after a fast check I did not find any problem so far - other than maybe the buffer size too small. Then I recommend you to test your Arduino code before to sue Processing, by sending the values through terminal/console (here the used tool depends on if you are using linux or M$. The monitor of Arduino IDE is not good for this since it does not have the \n character at the end of the line that is sent.

in linux, I open Kterminal, copy/paste on it:

stty -F /dev/ttyUSB1 cs8 115200 ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts

(of course changing the speed and port to match them with Arduino)

then:
screen /dev/ttyUSB1 115200

and then I copy paste my string with the values.

On windows, check here: Arduino Playground - InterfacingWithSoftware

The idea is to check that Arduino is retrieving the values well before to go to Processing. Remember that Messenger library needs to find a "\n" at the end of the string containing the values to retrieve them. A fast check to your PROCESSING code, and I did not find this character on your code at the end of the value's string. This is needed. On my java API I just added ...+ "\n"); at the end of the line containing the values for the variables, and I send them as a string. It should not be too different for Processing.

As an example your 4 values can well be sent to Arduino by java or Processing as:

// set the string that will be sent to Serial Port
String message1 = value1 + "|" + value2 + "\n");
String message1 = value3 + "|" + value4 + "\n");

Then I used a delay between each variable while being sent to give Arduino some time to retrieve them.

try {
Thread.sleep(400);
} catch (Exception e) {}
out.write(message1.getBytes());

Thread.sleep(400);
} catch (Exception e) {}
out.write(message2.getBytes());
System.out.println("Closing Serial Port");
closePort(); // this is needed

in this example 4 values would go in two messages (strings), but they can go well in a single message if you incremented the buffer on Messenger library as described before.
Something like this:
String message = val1 + "|" + val2 + "|" + val3 + "|" + val4 + "\n");

Also you can use a "header", as a character to be sent before the message string, and having Arduino set to retrieve the values only after that char has been received. This would be just as another message but only of one char. As an example, for the header 'Z',

String header = "Z\n"; Do not forget the "\n".

Good luck!