Holding sending data while waiting for data

Hi guys;

I am trying to send data from an Ardiuno ( reading a analog pin ) to a PC and from the PC to the Arduino ( LCD display ).

So far, I did send, received and display the data, but how can I wait for the incomming data without keep sending serial out.

My code just do that at the moment. I send the data like : < 345>< 678>< 234>.... can not hold yet... In the Serial Sending Box : I type : 2.365> and it display on the LCD --> V : 2.365 Volt I leat I got that working, but I want to hold or wait for the incomming data. I did that ---> the comment section but it do : < 567> I type : 2.356 I received : 2 and it send < 789>< 675>

Here my code. Any tips and help will be nice. Programming is not my strong point here. About the values being send, I simply read an open analog pin at the moment.

#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,10,9,8,7);

const byte anapin = 2;

unsigned int my_value;

unsigned char incom[8];

int j;

boolean state;

void setup()
{
  analogReference(DEFAULT);
  Serial.begin(9600);
  lcd.begin(16,2);
  lcd.clear();
  lcd.print("V : ");
  lcd.setCursor(11,0);
  lcd.print(" Volt");
  for (int i=0;i<8;i++)
  {
     incom[i]=0x20; 
  }  
}

void loop()
{
   my_value = analogRead(anapin);
   Serial.print("<");
   if ( my_value < 999 )
   {
     Serial.print(" "); 
   }  
   Serial.print(my_value, DEC);
   Serial.print(">");
   delay(1000);
 /*  
   state=1;
   if (Serial.available() >0) state=0;
   else state=1;
   while (state==1)
   {
     if (Serial.available() >0) state=0;
     else state=1;
   }
*/   
   j=0;
   while ( Serial.available() > 0 )
   {
       incom[j] = Serial.read();
       if (incom[j]=='>' ) break;
       j++;
       if (j==8) break;
   }
   for (int i=0;i<8;i++)
   {  
     if (incom[i]=='>') break;
     lcd.setCursor((4+i),0);
     lcd.write(incom[i]);
   }
   delay(1000);
   
}

Try something like this?

if(Serial.available())
     {
       //Send and display data here, will only run once when data is received
       while(Serial.available()) 
         {
           //process incoming serial data, will do this until serial is out of characters
         }
     }

@mweisz481

Thank for the tip. But that code will work for the Processing - PC side. Because it is waiting for data and process it and send data.

In my case, I am sending data first... waiting for a responce / data back and display it. So I have to code in a way that after sending its data, wait for incomming data and display it.

Thank for the effort.

Put the data into two arrays, when one is receved, send the other, then update your array pointer.

@CrossRoads

Put the data into two arrays, when one is receved, send the other, then update your array pointer.

I think I understand what you are trying to say. That is the PC side... I want to do : send data, wait for incomming data, send the next set, wait for the new set, ....repeat.

I was thinking about the problem, and I was think about the post office. I send a package, I received an acknowledge of sending the package, And I wait for package, and I received an acknowledge of receiving the package. In that context, I can use a state. I init the state, check the state, I send data depending of the state, I updated a new state after being send, I received the data, I updated the state, repeat...

I re-code the program and it it now working. Send data, wait the data, repeat.... well you know the story...

Time to do a Processing code.

Here the new code.

#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,10,9,8,7);

const byte anapin = 2;

unsigned int my_value;

unsigned char incom[8];

int j;

boolean state;

void setup()
{
  analogReference(DEFAULT);
  Serial.begin(9600);
  lcd.begin(16,2);
  lcd.clear();
  lcd.print("V : ");
  lcd.setCursor(11,0);
  lcd.print(" Volt");
  for (int i=0;i<8;i++)
  {
     incom[i]=0x20; 
  }
  state=0;  
}

void loop()
{
   if (state==0)
   {
     my_value = analogRead(anapin);
     Serial.print("<");
     if ( my_value < 999 )
     {
       Serial.print(" "); 
     }  
     Serial.print(my_value, DEC);
     Serial.print(">");
     state=1;
   }
   delay(1000); 
   j=0;
   while ( Serial.available() )
   {
       incom[j] = Serial.read();
       if (incom[j]=='>' )
       {
         state=0;
         break;
       }  
       j++;
       if (j==8) break;
   }
   for (int i=0;i<8;i++)
   {  
     if (incom[i]=='>') break;
     lcd.setCursor((4+i),0);
     lcd.write(incom[i]);
   }
   delay(1000);
}
 j=0;

while ( Serial.available() )
  {
      incom[j] = Serial.read();
      if (incom[j]=='>' )
      {
        state=0;
        break;
      }  
      j++;
      if (j==8) break;
  }

This is pretty reliant on all 8 bytes coming at once. Why not buffer it up in loop() and act when you get the lot, whenever that is?

(edit) Then you don't need the big delay.

@Nick Gammon

Thank for the link and tips. I will look into it and study the code.

I was doing my best to code it. I did test my code, using the serial monitor, and it work "fine" <-- so far... but not to well with the PC side. Processing code.

I was trying to send the data the "wrong" way, maybe right, but it did not work to well in Processing code. I have a "sychronazation" issue. I fix the initial problem, ( keep sending data, no waiting for the data ) using the state/flag methode. I was thinking about CrossRoads idea...so I decide the re-send the data one byte at the time, just I received one byte at a time. So I extract the numbers of an integer like : 1023 - take the BCD out, convert them in ASCII and send it. AT the receiving end, one byte at a time, convert ASCII to integer, and calculate the full integer data. And do the calculation ( find the voltage ) and convert to an integer and set the decimal point to 0.000. After that, extract the BCD numbers and send the data one byte at a time.

During testing, it work but, sometime, it have a few issues with a possible synchronization problem ?

Any second opinion will be nice. I will look into Nick Gammon link's.

Here the Arduino Code :

/*
   Size : 3566 bytes
   
   Serial data out and data in.
   
   Version 2.0
   
   Setup: a LCD 16 X 2 connect the the Arduino
   
   Author setup : Using a DIY LCD Sheild
   
   Analog pin 2 connected to nothing.   
      
   By Serge J Desjardins
   aka techone / tech37
   
   Toronto, Ontario, Canada
   
   Compile and Tested 

*/


#include <LiquidCrystal.h>

LiquidCrystal lcd(12,11,10,9,8,7);

const byte anapin = 2;

unsigned int my_value;

unsigned char incom[8];
int outdata[4];

int j;

boolean state;

void setup()
{
  analogReference(DEFAULT);
  Serial.begin(9600);
  lcd.begin(16,2);
  lcd.clear();
  lcd.print("V : ");
  lcd.setCursor(11,0);
  lcd.print(" Volt");
  for (int i=0;i<8;i++)
  {
     incom[i]=0x20; 
  }
  state=0;  
}

void loop()
{
   if (state==0)
   {
     my_value = analogRead( anapin );
     outdata[0] = my_value / 1000;
     my_value = my_value -( outdata[0] * 1000 );
     outdata[1] = my_value / 100;
     my_value = my_value -( outdata[1] * 100 );
     outdata[2] = my_value / 10;
     outdata[3]= my_value % 10;
     for (int i=0;i<4;i++)
     {
       Serial.write((outdata[i]+48));
     }
     Serial.print(">");
     state=1;
   }
   delay(100); 
   j=0;
   while ( Serial.available() )
   {
       incom[j] = Serial.read();
       if (incom[j]=='>' )
       {
         state=0;
         break;
       }  
       j++;
       if (j==8)
       {
          state=0;  
          break;
       }   
   }
   lcd.setCursor(4,0);
   lcd.print("        ");
   for (int i=0;i<7;i++)
   {  
     if (incom[i]=='>') break;
     lcd.setCursor((4+i),0);
     lcd.write(incom[i]);
   }
   delay(1000);
}

Here the Processing code.

/*
   The PC section. It received data , process it and send data

*/

import processing.serial.*;

Serial myPort;  

int[] inbyte = new int[5];
int[] outbyte = new int[4]; 
int j;

float voltage;

int answer;
int sendinfo;

boolean state;

void setup()
{
   println(Serial.list());
   myPort = new Serial(this, Serial.list()[3], 9600);
  //state=0;
  
}

void draw() 
{
    
  if ( myPort.available() > 0 )
  {
    j=0;    
    while ( myPort.available() >0 )
    {
      inbyte[j] = myPort.read();
      if (inbyte[j]=='>') break;
      j++;
      if (j==4) break;
    }
    
    answer=(inbyte[0]-48)*1000;
    answer=((inbyte[1]-48)*100)+answer;
    answer=((inbyte[3]-48)*10)+answer;
    answer=(inbyte[3]-48)+answer;
    
    voltage= float(answer)*(5.0/1023.0);
    voltage = voltage * 1000.0;
    sendinfo = int(voltage);
       
     outbyte[0] = sendinfo / 1000;
     sendinfo = sendinfo -( outbyte[0] * 1000 );
     outbyte[1] = sendinfo / 100;
     sendinfo = sendinfo -( outbyte[1] * 100 );
     outbyte[2] = sendinfo / 10;
     outbyte[3]=  sendinfo % 10;
    
     myPort.write((outbyte[0]+48));
     myPort.write(".");
     myPort.write((outbyte[1]+48));
     myPort.write((outbyte[2]+48));
     myPort.write((outbyte[3]+48));
     myPort.write(">");
      
  }  
}

Updated:

I test the Ardiuno code and the Processing code. It work about 90 % of the time. The raison I was doing it is : Programing exercise and test my opto-coupler linker project. Here the link : http://arduino.cc/forum/index.php/topic,92665.0.html

Good news : The linker work just fine. It send the data properly and display the data <-- kind of :roll_eyes:

Bad news : The voltage reading is a bit off, and it display is like : 2.456 and .456 <-- that shift to the left.

To monitor data : At the Processing side, I can monitor the data in and out. But at the Ardiuno side, I can not monitor the serial data... for now, but with another opto linker, I can monitor the data and it will use an another USB port. I will do it later after I build 2 opto linker.

At the Processing side, I did monitor the data and it is correct data in and out. I have to check the Arduino side.

Thank guys for the tips.