Processing long delay

Hi,

I am trying to connect my arduino to and android phone via bluetooth(the program on the android phone is made in processing). So far so good. I can receive data to the phone in real-time(a couple of times per second) but when I write data to the arduino with the help of getoutputstream, It takes more than 10 seconds for the arduino to receive. Why is that? I had a similar problem when I connected the arduino to the computer via a serial cable and used a processing sketch on my computer to control a light. However when I used putty, the arduino instanteniously received the data(when it was with a serial cable)?!?!

Why is that?

Perhaps if we saw some code, we might be able to do more than guess.

Well, its long but ok:

private static final int REQUEST_ENABLE_BT = 3;
BluetoothAdapter adapter;
BluetoothDevice device;
BluetoothSocket socket;
InputStream ins;
OutputStream ons;
//boolean registered = false;
PFont f1;
PFont f2;
int state;
//////////////Values//////////////
int Throttle;
int Roll = 50;
int Pitch = 50;
int Yaw = 50;
String error;
///////////Accelerometer////////////////
AccelerometerManager accel;
float ax, ay, az;
////////////////Buttons///////////////
APWidgetContainer widgetContainer;  
APWidgetContainer Retry;  
APButton button1; 
APButton button2; 
APButton button3;
//////////////////////////////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {

  background(0);
  orientation(LANDSCAPE);
  f1 = createFont("Arial", 50, true);
  f2 = createFont("Arial", 25, true);
  textAlign(CENTER);
  translate(width / 2, height / 2);
  textFont(f1);
  text("Connecting...", 0, 0);
  stroke(255);

  /////////Accelerometer and Buttons///////////
  accel = new AccelerometerManager(this);
  widgetContainer = new APWidgetContainer(this);
  Retry = new APWidgetContainer(this); 
  button1 = new APButton(10, 245, 100, 75, "Decrease"); 
  button2 = new APButton(380, 245, 100, 75, "Increase");  
  button3 = new APButton(190, 215, 100, 50, "Retry");
  widgetContainer.addWidget(button1); 
  widgetContainer.addWidget(button2);
  Retry.addWidget(button3);
  widgetContainer.hide();
  Retry.hide();
  ////////////////////////////////////////////
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void draw() {
  switch(state)
  {

  case 0:
    connectDevice();
    break;
  case 1:
    MainLoop();
    break;
  case 4:
    Errors();
    break;
  }
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void onStart()
{
  super.onStart();
  println("onStart");
  adapter = BluetoothAdapter.getDefaultAdapter();
  if (adapter != null)
  {
    if (!adapter.isEnabled())
    {
      Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
      startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
    }
    else
    {
      state = 0;
    }
  }
}
////////////////////////////////Keeps the screen from turning off//////////////////////////////////////////////////////////////////////////
void onCreate(Bundle bundle) 
{
  super.onCreate(bundle);
  getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
void connectDevice() 
{
  try   
  {     
    device = adapter.getRemoteDevice("00:11:11:21:03:46");
    socket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
    /*    
     Method m = device.getClass().getMethod("createRfcommSocket", new Class[] { int.class });     
     socket = (BluetoothSocket) m.invoke(device, 1);             
    */
    socket.connect();


    ins = socket.getInputStream();  
    ons = socket.getOutputStream(); 
    println("Connected");    
    state = 1;
  }   
  catch(Exception ex)   
  {     
    state = 4;     
    error = "Could Not Connect";     
    println(error);
  }
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 
////////////////////ACELEROMETER////////////////////////////
public void shakeEvent(float force) {
  println("shake : " + force);
}


public void accelerationEvent(float x, float y, float z) {
  //  println("acceleration: " + x + ", " + y + ", " + z);
  ax = x;
  ay = y;
  az = z;
}

/////////////////////////////////////////////////////////////////////////////////////////


void MainLoop() 
{
  ////////////Send Data/////////////////
try
  {    
    /*while(ons.available() > 0)
     {
     valor = (byte)ins.read();
     }
     */
    ons.write(Throttle); // Throttle
    //ons.write(Roll); // Roll
    //ons.write(Pitch); // Pitch
    //ons.write(50); // Yaw
    // ons.write(50); //Aux1
  }
  catch(Exception ex)
  {
    state = 4;
    error = ex.toString();
    println(error);
  }


  ///////////MAIN LOOP//////////MAIN LOOP////////MAIN LOOP////////////////

  background(0);
  Retry.hide();
  widgetContainer.show();
  fill(255);
  textFont(f1);

  
  Throttle = constrain(Throttle, 0, 255);      
  text(Throttle, width/2, height/2); 

  textFont(f2);
  text("x: " + nf(ax, 1, 2) + "\n" + 
    "y: " + nf(ay, 1, 2) + "\n" + 
    "z: " + nf(az, 1, 2), 
  -190, 10, width, height);

  Roll  = int(round(map(ax, -10, 10, 0, 255)));         
  Pitch = int(round(map(ay, -10, 10, 0, 255)));
}

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void onClickWidget(APWidget widget) {      
  if (widget == button1) { //if it was button1 that was clicked     
    Throttle = 0;
  }
  else if (widget == button2) { //or if it was button2     
    Throttle = 1;
  }
  else if (widget == button3) {

    state = 0;
  }
}
/////////////////////////////////////////////////////////////////////////////////    




/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void Errors()
{
  widgetContainer.hide();
  Retry.show();
  background(255, 0, 0);
  translate(width/2, height/2);
  textFont(f1);
  text(error, 0, 0);
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void onStop()
{
  println("onStop");
  /*
  if(registered)
   {
   unregisterReceiver(receptor);
   }
   */

  if (socket != null)
  {
    try
    {
      socket.close();
    }
    catch(IOException ex)
    {
      println(ex);
    }
  }
  super.onStop();
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

BTW I should mention that I added a println(millis()); after the ons.wrtie(Throttle); and the value seem normal(maybe 50 millis delay between each.

This is the only time that I write data:

////////////Send Data/////////////////
try
  {    
    /*while(ons.available() > 0)
     {
     valor = (byte)ins.read();
     }
     */
    ons.write(Throttle); // Throttle
    //ons.write(Roll); // Roll
    //ons.write(Pitch); // Pitch
    //ons.write(50); // Yaw
    // ons.write(50); //Aux1
  }
  catch(Exception ex)
  {
    state = 4;
    error = ex.toString();
    println(error);
  }

Perhaps the problem is on the Arduino end...

I dont think so but..just to be safe heres my code:

int ledpin = 9;
int value;

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

void loop(){

if (Serial.available() > 0) {

value = Serial.read();

analogWrite(ledpin, value);
delay(100);
}
}

When I go from 100 to 50 in steps of 5 (on the phone), I wait ten seconds, and
then in a split second, the led fades.It doesnt jump from 100 to 50, so thats why I think the problem is in the processing sketch. :confused:

EDIT: I removed the incomprehensible bit. :smiley:

EDIT 2: Additional info, if I connect and the value on the phone is (preset) to 100,the led goes to 100 immediatelly. Every time Iconnect and set a value, the led automatically goes to that value.
Ex: on phone 25, Connect, led 25, disconnect
on phone 200,connect,led200.
And I have no delay.

Still need help :smiley:

Still need help

After an hour? A bit impatient, are we?

  delay(100);

Not the sole cause of your issue, but, why is this here (on the Arduino)? I would think that if you send a value from the phone, you would expect instantaneous response, not for the Arduino to diddle around doing nothing for any period of time.

    /*while(ons.available() > 0)
     {
     valor = (byte)ins.read();
     }
     */

If there is data on the output stream, read from the input stream? I'd suggest uncommenting this, correcting the error (ons should be ins), and displaying, on the phone, the data you get from the Arduino.

Then, I'd add some Serial.print() statements to the Arduino code (in setup() and in the Serial.available() block), to see what the Arduino is doing.

Theelectronicguy:
Still need help :smiley:

It's taken me an hour to make a response on this forum. To anything.

EDIT: I removed the incomprehensible bit.

Good.

Yes, but It seems that when topics go to mthe bottom of the page, they get lost... Anyways, I have found something interesting, it seems strings dont seem to like getoutputstream and a solution is to incase it in a buffered outputstream. However, Now it doesnt even work anymore,maybe I did something wrong?

ons = new BufferedOutputStream(socket.getOutputStream());

Yes, but It seems that when topics go to mthe bottom of the page, they get lost

No, they just go onto the next page.

Anyways, I have found something interesting, it seems strings dont seem to like getoutputstream and a solution is to incase it in a buffered outputstream.

You need to post some code that illustrates just what "strings don't seem to like getoutputstream" means. And any error messages.

No, they just go onto the next page.

No really? :smiley: As for the code, the strings take a loooong time to send.Ill post the code when I get home but bassically, where it was ons = getOutputstream(), I now put ons = new BufferedOutputStream(socket.getOutputStream()); and the led doesnt even get updated(it stays off or 0).

and the led doesnt even get updated

Maybe the phone is waiting for the buffer to fill up. There are times to use buffered output, and there are times not to.

OMG and I thought that microcontrollers were logic :D. I saw that in the multiwii code(for flying a quad thats why I startted this project) had a 200 millisecond delay. Well, what do you know, I put a 200 millisecond delay between writes and IT WORKS :D:D:D:D:D. Seems like the arduino was overwhelmed or something. Anyways I hope that I can now fly(finnaly) my quadcopter!!!(I have been working on this for about a month)

You are trying to process messages consisting of a single byte.

The symptoms you're describing are probably caused by buffering (I'd guess in the output driver for the phone). You want to flush each character to the device as soon as you have written it i.e. no buffering.

Adding even more buffering on the other side is probably not going to help.

Oh, I removed the ons = new BufferedOutputStream(socket.getOutputStream());
and only left ons = socket.getOutputStream(); but if I understood correctly after the write, I should put ons.flush();? Also, thanks PaulS for the suggestion of listening for an input(and arduino acting as an echo), it helped me debug. As for the 100ms delay, well I dont know why I put it(maybe because all the others put it)... Would it really have influenced something?

but if I understood correctly after the write, I should put ons.flush();?

You'd need to look at the outputstream class, to determine if the output is buffered or not. I'd guess not, since you have the option of wrapping the instance in a buffering class. If the output is buffered, flush() should send the data in the buffer, even if the buffer is not full. If the output is not buffered, then flush() does nothing, and need not be called.

Also, thanks PaulS for the suggestion of listening for an input(and arduino acting as an echo), it helped me debug.

Good. It feels good when you can determine for yourself what is wrong, doesn't it?

Would it really have influenced something?

An unnecessary delay is all.