Send Arduino Data to Android (Ultrasonic Sensor)

Question:

I made this code to receive data from an ultrasonic sensor on an Android cell phone. After passing the app to the cell phone and the code to the Arduino, it can only connect, but it doesn't show the sensor distance data. Could someone help me solve this problem?

 //Activity principal que realiza a conexão e mostra os dados do sensor package com.example.sensor; import java.io.IOException; import java.io.OutputStream; import java.util.UUID; import com.example.appenthernet.R; import android.annotation.SuppressLint; import android.app.Activity; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothSocket; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.view.Menu; import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; @SuppressLint("HandlerLeak") public class MainActivity extends Activity { //Handler é parte da estrutura do sistema Android para gerenciar threads. Um manipulador de objeto recebe mensagens e executa o código para //lidar com as mensagens. Normalmente, você cria um manipulador para um novo tópico, mas você também pode criar um manipulador que está conectado //a uma linha existente. Quando você conecta um manipulador para o seu segmento interface do usuário, o código que manipula mensagens é executado //no segmento interface do usuário. //Ou seja, é a estrutura que manipula as mensagens recebidas por bluetooth pelo ceular Handler bluetoothIn; final int handlerState = 0; private BluetoothAdapter btAdapter = null; private BluetoothSocket btSocket = null; private StringBuilder recDataString = new StringBuilder(); private OutputStream outStream = null; private static final int SolicitaAtivaçao = 1; private static final int SolicitaConexao = 2; //Entrada das informações para fazer a interação entre o celular e o módulo bluetooth private BluetoothAdapter meuBluetooth = null; // SPP UUID service - isso deve funcionar para a maioria dos dispositivos private static final UUID MEU_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); // String para o endereço MAC //quando usa lista de dispositivos, se não colocar igual a null da erro private static String MAC = null; TextView textView1, textViewMedida, textViewString; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView1 = (TextView) findViewById(R.id.textView1); textViewMedida = (TextView) findViewById(R.id.textViewMedida); textViewString = (TextView) findViewById(R.id.textViewString); //obtém o adaptador local bluetooth meuBluetooth = BluetoothAdapter.getDefaultAdapter(); //Verifica se o didpositivo tem bluetooth if(meuBluetooth == null){ //Se não tiver, a mensagem abaixo será mostrada e o programa será encerrado Toast.makeText(getApplicationContext(), "Seu dispositivo não possui bluetooth", Toast.LENGTH_LONG).show(); finish(); return; } //Se o bluetooth não estivver ativado, será solicitada a ativação do mesmo //Através do intent, que inicia uma nova ação if(!meuBluetooth.isEnabled()){ Intent solicita = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);//Cria o intent startActivityForResult(solicita,SolicitaAtivaçao);//Starta o intent } bluetoothIn = new Handler() { public void handleMessage(android.os.Message msg) { if (msg.what == handlerState) { //se a mensagem é o que queremos, String readMessage = (String) msg.obj; // msg.arg1 = bytes de conexão thread recDataString.append(readMessage); //Pega os dados doa sensores até a string '~' int endOfLineIndex = recDataString.indexOf("~"); // que determina o final de linha if (endOfLineIndex > 0) { String dataInPrint = recDataString.substring(0, endOfLineIndex); // extrai a string textViewString.setText("Data Received = " + dataInPrint); int dataLength = dataInPrint.length(); //Pega o tamanho dos dados recebidos textView1.setText("String Length = " + String.valueOf(dataLength)); if (recDataString.charAt(0) == '#') //se ele começa com # sabemos que é o que estamos procurando { String sensor0 = recDataString.substring(1, 5); //obtem o valor do sensor entre índices 1-5 textViewMedida.setText(" Sensor 0 Voltage = " + sensor0 + "cm"); //coloca o valor recebido no textview } recDataString.delete(0, recDataString.length()); //limpa as strings // strIncom =" "; dataInPrint = " "; } } } }; } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // TODO Auto-generated method stub super.onActivityResult(requestCode, resultCode, data); switch(requestCode){ case SolicitaAtivaçao: if(resultCode ==Activity.RESULT_OK)//Se o bluetooth for ligado, a mensagem abaixo será mostrada { //E o progrma continuará sendo executado Toast.makeText(getApplicationContext(), "O BLUETOOTH FOI LIGADO!", Toast.LENGTH_LONG).show(); }else//Se o bluetooth não foi ativado, a mensagem abaixo será mostrada e o programa será fechado { Toast.makeText(getApplicationContext(), "O BLUETOOTH NÃO FOI LIGADO!", Toast.LENGTH_LONG).show(); finish(); } break; case SolicitaConexao: if(resultCode==Activity.RESULT_OK){ MAC = data.getExtras().getString(ListadeDispositivos.EnderecoMAC); //Para se ter um bluetoothdevice é necessário uilizar o BluetoothAdapter.getRemoteDevice(string) //Que representa um endereço Mac conhecido, que já foi apresentado no início BluetoothDevice device = meuBluetooth.getRemoteDevice(MAC); try{ //A função device.createRfcommSocketToServiceRecord(MEU_UUID) abre m conexão //Entre o dispositivo e o módulo btSocket = device.createRfcommSocketToServiceRecord(MEU_UUID); //É iniciada a saída d dados do dispositivo btSocket.connect(); //Se der tudo certo na hora da conexão, irá aparecer a tela do controle if(btSocket!=null){ Toast.makeText(getApplicationContext(), "A CONEXÃO FOI BEM SUCEDIDA!", Toast.LENGTH_LONG).show(); } }catch(IOException e){ Toast.makeText(getApplicationContext(), "ERRO AO FAZER CONEXÃO", Toast.LENGTH_LONG).show(); } }else{ Toast.makeText(getApplicationContext(), "Falha ao obter o endereço MAC", Toast.LENGTH_LONG).show(); } break; } } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.Conectar) { conectar(); return true; } if (id ==R.id.Desconectar){ if(btSocket !=null){ desconectar(); }else{ Toast.makeText(MainActivity.this, "O módulo bluetooth não está conectado", Toast.LENGTH_LONG).show(); } return true; } return super.onOptionsItemSelected(item); } //Método que faz o envio de dados, ou seja, envia os caracteres public void dadosEnvio (String data){ try{ //Permite a saída de dados a partir de um socket outStream = btSocket.getOutputStream(); }catch(IOException e ){} String mensagem = data; byte[] msgBuffer = mensagem.getBytes();//Array de bytes que armazena a informação da string try{ //Envia a mensagem para o módulo outStream.write(msgBuffer); }catch(IOException e ){} } //Definição da função conectar public void conectar(){ Intent abreLista = new Intent(MainActivity.this,ListadeDispositivos.class); startActivityForResult(abreLista, SolicitaConexao); } //Definição da função desconectar public void desconectar(){ try{ btSocket.close();//Fecha a conexão btSocket = null;//E a conexão volta a ser nula }catch(IOException e){ } } }
 <!-- begin snippet: js hide: false -->
 //Programa do arduino #include <Ultrasonic.h> //Define os pinos TRIGGER e ECHO do sensor ultrassonico #define PINO_TRIGGER 13 #define PINO_ECHO 10 //Inicializa o sensor ultrassonico Ultrasonic sensor(PINO_TRIGGER, PINO_ECHO); float cmMsec;//variável que irá armazenar os dados do sensor void setup() { Serial.begin(9600); } void loop() { valores_para_envio(); long microsec = sensor.timing();// contabiliza o tempo necessário para o sinal ir e voltar cmMsec = sensor.convert(microsec, Ultrasonic::CM);//calcula a distância em centímetros delay(1000); } void valores_para_envio() { //indica que a comunicação foi iniciada Serial.print("#"); //Envia o valor medido pelo sensor Serial.print(cmMsec); //Usado para identificar o fim da trasmissão Serial.print('~'); Serial.println(); delay(10); }
//Activity para a lista de dispositivos 

package com.example.sensor;

import java.util.Set;

import android.app.ListActivity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;

public class ListadeDispositivos extends ListActivity {

    private BluetoothAdapter meuBluetooth;
    static String  EnderecoMAC = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        ArrayAdapter<String> ArrayBluetooth = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1);

        //obtem o bluetooth local do dispositivo
        meuBluetooth= BluetoothAdapter.getDefaultAdapter();

        //Pega os dispositivos paredaos 
        Set<BluetoothDevice> dispositivospareados = meuBluetooth.getBondedDevices();

        //Se o tamanho dos dispositivos for maior que zero, serão adicionados os dispositivos na lista
        if(dispositivospareados.size()>0){
            for (BluetoothDevice bluetoothDevice : dispositivospareados) {
                String nome = bluetoothDevice.getName();
                String mac = bluetoothDevice.getAddress();

                ArrayBluetooth.add(nome +"\n"+mac);

            }
        }

        setListAdapter(ArrayBluetooth);     
    }

    //Método de click na lista
    @Override
    protected void onListItemClick(ListView l, View v, int position, long id) {
        // TODO Auto-generated method stub
        super.onListItemClick(l, v, position, id);

        //Obtém todos os dados do item que foi clicado
        String InfoGeral = ((TextView)v).getText().toString();

        //Retira o endereço MAC que são os ultimos 17 caracteres da informação
        String mac = InfoGeral.substring(InfoGeral.length()-17);

        Intent retornaMac = new Intent();
        retornaMac.putExtra(EnderecoMAC, mac);

        //Atribui o resultado como OK e fecha a lista
        setResult(RESULT_OK,retornaMac);
        finish();
    }




}

Answer:

In fact, as far as I can tell, you're not reading incoming data, as you don't do this anywhere:

InputStream in = bluetoothkSocket.getInputStream();

What you need to do is create another thread that will loop awaiting submissions from your Arduino sensor, something like this:

// Faça isso a partir do momento que o seu bluetooth socket for diferente de null
    // Que é quando você tem a conexão
    final InputStream in = bluetoothkSocket.getInputStream();

    new Thread(new Runnable() {
        @Override
        public void run() {
            byte[] bytes = new byte[1024];
            int length;
            while (running) {
                try {
                    length = in.read(bytes);
                    // Isso supondo que a mensagem que você envia seja uma string
                    String msg = new String(bytes, 0, length);
                    // Método para atualizar a interface
                    msgReceived(msg);
                } catch (Exception e) {
                    running = false;
                }
            }
        }
    }).start();

Only the UI Thread can refresh the screen on android:

private void msgReceived(final String msg) {
        // Vai rodar na UI Thread.
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // Faça o que quiser com a msg. Atualizar um textView, por exemplo.
            }
        });
    }

As said, don't forget that all this needs to be done on another Thread.

As for the part of sending information on Arduino, if it is being done correctly, I can't tell you.

Edit:

Remembering that the in.read(bytes); method in.read(bytes); , is blocking, that is, it will be stopped in this method until an answer comes. According to Java's own documentation on the method:

This method blocks until input data is available, end of file is detected, or an exception is thrown.

What makes it clearer the importance of using another Thread to wait for the answer.

Scroll to Top
AllEscort