Arduino and Android Bluetooth Connection (Java) - Inputstream storing old data

Asked

Viewed 7,507 times

3

I’m making a class in Java very simple, just to simulate the communication of Android with Arduino via Bluetooth. The idea is the following:

The Arduino every 5 seconds will light and erase an LED. If the LED is lit, the String "1" will be sent to the serial port, if it is deleted it will be String "2".

Already on the phone, when the "Receive data" button is pressed, an Edittext should show "1" if the LED is on (which should be the message received from Arduino) and "2" if the LED is off (which should be the message received from Arduino).

The problem is in the following: from the moment I make the Bluetooth connection between the mobile phone and the module, Arduino messages are getting "stacked" in InputStream (byte source), and pressing the "Receive Data" button does not show the real status on the LED ("1" for on and "2" for off), but rather the information that is "stacked" on InputStream.

Trying to exemplify step-by-step to be clearer:

  • Bluetooth connection established

  • LED ON > Arduino writes "1" on Serial port

  • ...5 seconds
  • LED Off > Arduino writes "2" on Serial port
  • ...5 seconds
  • LED ON > Arduino writes "1" on Serial port
  • ...5 seconds
  • LED Off > Arduino writes "2" on Serial port
  • "Receive Data" button pressed on mobile phone when LED is OFF
  • Output that appears in Edittext: 1.

That is, should appear "2", but appeared "1" because he was the "first in line", Arduino sent to the Serial port at the beginning of the program.

Finally, the question is: how can I always access the last byte that is in Inputstream to receive the real state of the LED, without having to receive old information?

I read the Arduino documentation (http://arduino.cc/en/Reference/Serial) to try to "clean" the data from the Serial port but found nothing of the type. I also tried some method from the Inputstream class (http://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html) but I was unsuccessful.

I appreciate any help or idea!

Follow the codes:

1 - Do Arduino:

void setup(){

  // Começa comunicação via USB com PC
  Serial.begin(9600);
  // Começa comunicação com o módulo Bluetooth, que está ligado no pino RX1, TX1
  Serial1.begin(9600);

  pinMode(led,OUTPUT);

}

void loop(){

  digitalWrite(led,HIGH);
  Serial1.print("1");
  delay(5000);

  digitalWrite(led,LOW);
  Serial1.print("2");
  delay(5000);

}

2 - Java/Android (The only crucial method for the problem I think is the "Receive data")

public class MainActivity extends Activity {    

    // Widgets do Layout
    Button conectar;
    Button desconectar;
    Button receberDados;
    EditText textoRecebido; 

    // Represents a remote Bluetooth device.
    private BluetoothDevice dispositivoBluetoohRemoto;

    // Represents the local device Bluetooth adapter.
    private BluetoothAdapter meuBluetoothAdapter = null;

    // A connected or connecting Bluetooth socket.
    private BluetoothSocket bluetoothSocket = null;

    private static final String endereco_MAC_do_Bluetooth_Remoto = "20:14:05:15:32:00";

    public static final int CÓDIGO_PARA_ATIVAÇÃO_DO_BLUETOOTH = 1;

    // Anyone can create a UUID and use it to identify something with 
    // reasonable confidence that the same identifier will never be 
    // unintentionally created by anyone to identify something else
    private static final UUID MEU_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");

    // A readable source of bytes.
    private InputStream inputStream = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);     

        fazerConexoesDoLayout_e_Listeners();

        verificarCondiçãoDoBluetooth(); 

    }

    public void fazerConexoesDoLayout_e_Listeners(){

        conectar =     (Button)findViewById(R.id.conectar);
        desconectar =  (Button)findViewById(R.id.desconectar);
        receberDados =  (Button)findViewById(R.id.enviarDados);

        textoRecebido = (EditText)findViewById(R.id.textoEnviado);

        conectar.   setOnClickListener(new Conectar());
        desconectar.setOnClickListener(new Desconectar());
        receberDados.setOnClickListener(new ReceberDados());

    }

    public void verificarCondiçãoDoBluetooth() {        

        // Get a handle to the default local Bluetooth adapter.
        meuBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        // Verifica se o celular tem Bluetooth
        if(meuBluetoothAdapter == null){    

            Toast.makeText(getApplicationContext(), "Dispositivo não possui adaptador Bluetooth", Toast.LENGTH_LONG).show();

            // Finaliza a aplicação.
            finish();           

        } else {

            // Verifica se o bluetooth está desligado. Se sim, pede permissão para ligar.
            if(!meuBluetoothAdapter.isEnabled()){

                // Activity Action: Show a system activity that allows the user to turn on Bluetooth.

                // This system activity will return once Bluetooth has completed turning ON, or the
                // user has decided not to turn Bluetooth on.

                // Notification of the result of this activity is posted using the
                // #onActivityResult callback. The resultCode will be RESULT_OK if 
                // Bluetooth has been turned ON or RESULT_CANCELED if the user has
                // rejected the request or an error has occurred.
                Intent novoIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(novoIntent, CÓDIGO_PARA_ATIVAÇÃO_DO_BLUETOOTH);

            }
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        switch(requestCode){

        case CÓDIGO_PARA_ATIVAÇÃO_DO_BLUETOOTH:

            if(resultCode == Activity.RESULT_OK){
                Toast.makeText(getApplicationContext(), "Bluetooth foi ativado", Toast.LENGTH_LONG).show();
            } else { 
                Toast.makeText(getApplicationContext(), "Bluetooth não foi ativado", Toast.LENGTH_LONG).show();
            }       

            break;
        }
    }

    public class Conectar implements OnClickListener {

        @Override
        public void onClick(View v) {

            // Validate a Bluetooth address, such as "00:43:A8:23:10:F0".
            // (Alphabetic characters must be uppercase to be valid)            
            if(BluetoothAdapter.checkBluetoothAddress(endereco_MAC_do_Bluetooth_Remoto)){

                // Get a BluetoothDevice object for the given Bluetooth hardware.
                // Valid Bluetooth hardware addresses must be upper case, in a format
                // such as "00:11:22:33:AA:BB"
                dispositivoBluetoohRemoto = meuBluetoothAdapter.getRemoteDevice(endereco_MAC_do_Bluetooth_Remoto);

            } else{ 
                Toast.makeText(getApplicationContext(), "Endereço MAC do dispositivo Bluetooth remoto não é válido", Toast.LENGTH_SHORT).show();
            }

            try{

                // Create an RFCOMM BluetoothSocket socket ready to start an insecure
                // outgoing connection to this remote device using SDP lookup of UUID.
                // The RFCOMM protocol emulates the serial cable line settings and 
                // status of an RS-232 serial port and is used for providing serial data transfer
                bluetoothSocket = dispositivoBluetoohRemoto.createInsecureRfcommSocketToServiceRecord(MEU_UUID);

                // Attempt to connect to a remote device.
                bluetoothSocket.connect();

                Toast.makeText(getApplicationContext(), "Conectado", Toast.LENGTH_SHORT).show();

            } catch(IOException e){

                Log.e("ERRO AO CONECTAR", "O erro foi" + e.getMessage());
                Toast.makeText(getApplicationContext(), "Conexão não foi estabelecida", Toast.LENGTH_SHORT).show();

            }               
        }
    }

    public class Desconectar implements OnClickListener {

        @Override
        public void onClick(View v) {

            if(bluetoothSocket != null) {
                try{
                    // Immediately close this socket, and release all associated resources.
                    bluetoothSocket.close();

                    bluetoothSocket = null;
                    Toast.makeText(getApplicationContext(), "Conexão encerrada", Toast.LENGTH_SHORT).show();

                } catch(IOException e){

                    Log.e("ERRO AO DESCONECTAR", "O erro foi" + e.getMessage());
                    Toast.makeText(getApplicationContext(), "Erro - A conexão permanece estabelecida", Toast.LENGTH_SHORT).show();  
                }

            } else{
                Toast.makeText(getApplicationContext(), "Não há nenhuma conexão estabelecida a ser desconectada", Toast.LENGTH_SHORT).show();
            }                           
        }           
    }

    public class ReceberDados implements OnClickListener {

        @Override
        public void onClick(View v) {

            // Verifica se há conexão estabelecida com o Bluetooth.
            if(bluetoothSocket != null){

                textoRecebido.setText("");

                try{

                    // Get the input stream associated with this socket.
                    inputStream = bluetoothSocket.getInputStream();

                    byte[] msgBuffer = new byte[1];

                    // Reads bytes from this stream and stores them in the byte array
                    inputStream.read(msgBuffer);

                    textoRecebido.setText(new String(msgBuffer));                   

                    Toast.makeText(getApplicationContext(), "Mensagem foi recebida", Toast.LENGTH_LONG).show();

                } catch(IOException e){
                    Log.e("ERRO AO RECEBER MENSAGEM", "O erro foi" + e.getMessage());
                    Toast.makeText(getApplicationContext(), "Mensagem não recebida", Toast.LENGTH_LONG).show();
                }
            } else {                
                Toast.makeText(getApplicationContext(), "Bluetooth não está conectado", Toast.LENGTH_LONG).show();
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();   
    }
}

4 answers

2

Maybe what you need is to "wipe" the data from Inputstream before calling the read().

The method available() checks if it has "dirt", and returns the number of bytes that can be "dropped".

int available = inputStream.available();
if (available > 0) {
    // Cria um buffer para ler a "sujeira"
    byte[] uselessBuffer = new byte[available];

    // Lê a "sujeira"
    mmInStream.read(uselessBuffer);
}

After this snippet of code, you do the read() of the data you want:

            byte[] msgBuffer = new byte[1];

            // Reads bytes from this stream and stores them in the byte array
            inputStream.read(msgBuffer);

More information on the method available() of Inputstream: http://developer.android.com/reference/java/io/InputStream.html

  • Cool, I’ll try. Thanks

0

Create a function to listen to the serial from time to time, assign the serial value to an example variable: "current", this variable stores the current value in the serial, so if you don’t send anything to the serial or clean it up, the value is still there. (clean the serial always before using).

Then to know if the current value matches that in the serial, which was the last value sent, compare the two, if equal, a switch to set the pin as HIGH or LOW.

If the values are not equal, there was a delay, in the serial, or something like that, so it will not trigger the LED.

0

I’ve been through this myself. My solution was similar to what was suggested by Caio

What I did was this:

  • Create a message type, for example: a numeric code or String, as you prefer.
  • In the Android app, just when establishing the BT connection, send this message.
  • In the West:

    • Clear buffer until you receive this message to start running flashes
    • Use flush to avoid communication problems (optional)

Suggested Arduino code:

========================================= /* Example for communication between Arduino and Android * * In this case, Arduino is waiting to receive a message to start the * processing. * And then keeps flashing the led and sending messages to android on led status * */

// Pino do led

#define PINO_LED 13

// Mensagem para iniciar o processamento, que a aplicacao Android vai enviar

#define MENSAGEM_INICIAR 'I' 

// Em execucao ?

boolean emExecucao = false;

//*** SETUP

void setup(){

  // Começa comunicação via USB com PC
  Serial.begin(9600);
  // Começa comunicação com o módulo Bluetooth, que está ligado no pino RX1, TX1
  Serial1.begin(9600);

  pinMode(PINO_LED,OUTPUT);

  // Limpa buffer de entrada

  limpaBufferEntrada ();

}

// *** Loop de processamento

void loop(){

  // Espera receber uma mensagem do android para iniciar a execucao

  if (emExecucao) { // Execuca o processamento, neste caso piscar os leds e enviar o status para o android

    digitalWrite(PINO_LED,HIGH);
    Serial1.print("1");
    Serial1.flush(); // Aguarda o buffer de saida
    delay(5000);

    digitalWrite(PINO_LED,LOW);
    Serial1.print("2");
    Serial1.flush(); // Aguarda o buffer de saida
    delay(5000);

  } else { // Ainda aguardando o android

    leDadosSerial();

  }
}

// Limpa buffer de entrada

void limpaBufferEntrada() {

  while (Serial1.available()) {

    Serial1.read();

  }

}

// Le dados da porta serial

void leDadosSerial() {

  // Le dados da porta serial 1

  while (Serial1.available()) {

    char caract = (char)Serial1.read();

    if (caract == MENSAGEM_INICIAR) {

      //Mensagem de inicio da execucao recebida

      emExecucao = true;

     } else {

       // ignora qualquer outra entrada

        delay (50); // Uma pequena pausa, para reduzir o processamento

     }
  }
}

0

Have this tutorial here (Bluetooth communication between Arduino and Android). It took me a while to understand how the code works, but after a good study I managed to mold my app on top of the code changing only the parts I needed, I hope it helps, good luck there hehe

Browser other questions tagged

You are not signed in. Login or sign up in order to post.