Send Arduino data to Android (ultrasonic sensor)

3

I made this code to receive data from an ultrasonic sensor on a Android cell. After passing the application to the cell phone and the code for the Arduino, it can only connect, but does not show the data of the sensor distance. 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();
    }




}
    
asked by anonymous 11.11.2015 / 02:14

1 answer

1

In fact, as far as I can tell, you are not reading incoming data, since you do not do this anywhere:

InputStream in = bluetoothkSocket.getInputStream();

What you need to do is to create another looped thread waiting for your sensor to send in Arduino, 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 in 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, do not forget that all this needs to be done on another Thread.

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

Edit:

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

  

This method blocks 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.

    
11.11.2015 / 02:47