Bluetooth connection Arduino and Android (Java) - InputStream storing old data

3

I'm making a very simple Java class just to simulate Android's communication with the Arduino via Bluetooth. The idea is as follows:

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

On cellphone, when the "Receive Data" button is pressed, an EditText should show "1" if the LED is lit (which should be the message received from the Arduino) and "2" if the LED is off should be the message received from Arduino).

The problem is as follows: from the moment I connect the Bluetooth between the cell phone and the module, the Arduino messages are being "stacked" in InputStream (byte source), and pressing the ("1" for lit and "2" for erased), but the information that is "stacked" in InputStream .

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

  • Established Bluetooth connection

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

  • ... 5 seconds
  • LED OFF > Arduino writes "2" on the Serial port
  • ... 5 seconds
  • LED ON > Arduino writes "1" on the Serial port
  • ... 5 seconds
  • LED OFF > Arduino writes "2" on the Serial port
  • "Receive data" button pressed on the cell phone when the LED is OFF
  • Result that appears in EditText: 1 .

In other words, it should appear "2", but it appeared "1" because it was the "first in the queue", which the Arduino sent to the serial port there at the beginning of the program.

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

I've read the Arduino documentation ( link ) to try to "clean" the Serial port data but found nothing type. I also tried some method of the InputStream class ( link ) but I did not succeed .

Thanks for any help or ideas!

Here are 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 "GetDatabase")

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();   
    }
}
    
asked by anonymous 13.07.2014 / 18:48

4 answers

2

You may need to "clean" the InputStream data before calling read() .

  

The available() method checks for "dirt", and returns the number of bytes that can be "discarded."

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 code snippet, you make 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 about the InputStream% method : link

    
17.07.2014 / 16:43
0

I also went through this situation. My solution was similar to what was suggested by Caio

What I did was the following:

  • Create a message type, for example: a numeric code or String, as you like.
  • In the Android application, when you establish the BT connection, send this message.
  • No arduino:

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

Suggested Arduino code:

=============================================     / * Example for communication between Arduino and Android      *      * In this case, the arduino is waiting to receive a message to start the      * processing.      * And there is flashing the led and sending messages to the android on the 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

     }
  }
}
    
31.07.2014 / 14:44
0

Create a function to listen to the serial from time to time, assign the value of the serial to an example variable: "current", this variable saves the current value in the serial, so if you do not send anything else to the serial nor clean it , the value is still there (clean the serial always before using).

To see if the current value matches the serial value, which was the last value sent, compare the two, if equal, a switch to set the pin to HIGH or LOW.

If the values are not equal, a delay has occurred in the serial or something like this, so it will not trigger the LED.

    
08.06.2015 / 21:59
0

There is this tutorial here (Bluetooth Communication between Arduino and Android) . It took me a while to understand how the code works, but after giving a nice study I was able to wrap my app on top of the code by changing only the parts I needed, hope it helps, good luck there hehe

    
30.06.2016 / 02:23