0

I am recently working on a project. The idea is to make a Bluetooth speaker which has playback controls like pause,play, next song on the speaker itself. The speaker is to be connected to the mobile phone via Bluetooth. Ultimately i wanted to achieve the button control(on speaker) of songs I play on mobile which is connected to speaker via Bluetooth.

I was able to make the speaker connected via Bluetooth to the phone and could play songs but the biggest challenge is i couldn't pause or forward the playlist on phone from speaker side. What i understood is that the speaker is able to receive signals from phone to play songs but how do i send a command(like next song via physical button) from the speaker to the phone(via a micro controller like arduino). I hope I stated my situation well. I came across idea like having multiple bluetooth pairing, custom programming of the BT module that i'll be using, etc.

I am open to all kinds of way this can be done and I really appreciate if anyone could recommend me the proper BT modules and micro-controller to be used.

  • But you wanna use the BLT speaker only as speaker(music stored on mobile phone), or you wanna use it to play music by itselves(music stored on flash memory) and phone will only send commands? About this info, I will give you more info. Anyway you gonna need some knowledges about electronic... – DynoZ Feb 26 '21 at 07:24
  • The first scenario where BLT speaker only as speaker. Music stored on mobile phone only. I was able to make the bluetooth speaker connected to phone similar to this : https://www.youtube.com/watch?v=d-Bv8j8Fw2Y But i wanted to add the playlist controls like pause , forward to the speaker. – Mano Bhargav Feb 26 '21 at 09:11
  • Alright. you wanna the controls (pause, play, stop, forward ecc...) are sent by the phone, or you wanna use some buttons to solder onto the speaker? – DynoZ Feb 26 '21 at 09:27
  • If you wanna use your phone to send commands, stop sending music and send a string as flag e.g. "play" / "pause" ecc... The microcontroller will check the byte array received and, if it is a flag, do the one – DynoZ Feb 26 '21 at 09:37
  • I want buttons to solder onto the speaker itself... – Mano Bhargav Feb 26 '21 at 11:03
  • That's easier then. In this way, you don't need to send both music and command. And also you could use Arduino... it's cheapier than Rasb – DynoZ Feb 26 '21 at 11:06
  • Google for a speaker circuit, the signal input will be the TX of the HC-05 (You don't need to connect TX pin to Arduino). Instead you have to connect the RX pin to Arduino (if you don't know, you have to think reversing the pinout of the HC-05). So the RX pin will broadcast the command, which after been received by the phone, will stop music. If you wanna more info about, I am gonna post an answer :-) – DynoZ Feb 26 '21 at 11:09
  • Okay. I will try it. It was really helpful. Thank you!! – Mano Bhargav Feb 26 '21 at 12:14

1 Answers1

0

About the BT module, I suggest you to use an HC-05. For the MCU, Arduino cannot be used to play music... so you should optain for Rasberry, but I am not sure. Also I never used it...

If you need some code similar, I mede an app for a greenhouse which displays temperature, humidity and light inside it.

If you wanna read these class in order: gitHub. But I have to post the code, too: maybe I could delete the repo a day

BLTSocket class:

public class BLTSocket extends Service {

private static final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
private static boolean isBtConnected = false;
private static BluetoothAdapter adapter = null;
private static BluetoothSocket socket = null;
private static InputStream is = null;
private static OutputStream os = null;

public BLTSocket(){

}

/**
 * Constructor called when a bluetooth device has been clicked in the layout
 * If the phone's bluetooth socket has not already connected , it tries to initialize
 * the new connection with the one clicked.
 * Get the stream and set @isBtConnected as true
 *
 * @param address - MAC address of the bluetooth device
 */
public BLTSocket(String address){
    if (!isBtConnected || !socket.isConnected()) {
        try {
            adapter = BluetoothAdapter.getDefaultAdapter();
            BluetoothDevice device = adapter.getRemoteDevice(address);
            socket = device.createInsecureRfcommSocketToServiceRecord(uuid);
            socket.connect();
            is = socket.getInputStream();
            os = socket.getOutputStream();
            isBtConnected = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

@Override
public void onCreate() {
    HandlerThread handlerThread = new HandlerThread("SURVEYS_SERVICE", Process.THREAD_PRIORITY_BACKGROUND);
    handlerThread.start();
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    survey();
    return START_STICKY;
}

/**
 * This handler keeps updating the three surveys reading their current value
 * from the bluetooth module's input stream.
 * Set the the circular progress bar and the own text view below as the relative value
 */
Handler handler = new Handler();
Runnable runnable;
private void survey() {

    runnable = new Runnable() {
        @RequiresApi(api = Build.VERSION_CODES.O)
        @Override
        public void run() {
            byte[] survey = new byte[12];
            try {
                /*
                    Once got the current values of the three surveys,
                    it sets the relative progress bar and the text view
                 */
                if(is.read(survey) > 0){
                    for(int i = 0; i < 3; i++){
                        MainActivity.getProgressBars()[i].setProgress(survey[i]);
                        MainActivity.getTextViews()[i].setText(String.valueOf(survey[i]) + (i == 0 ? "°C" : '%'));
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
                return;
            }
            handler.postDelayed(this, 2000);
        }
    };
    runnable.run();

}

/**
 * Called when the user click on the UPDATE SEED button
 * on the popup menu of the ViewSeed layout
 *
 * Send to the HC-05 the new recommended values
 *
 * @param values
 */
public void updateSeed(int[] values){
    try {
        handler.removeCallbacks(runnable);
        for(int value : values) {
            os.write(value);
        }
        os.flush();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        handler.postDelayed(runnable, 2000);
    }
}


@Nullable
@Override
public IBinder onBind(Intent intent) {
    return null;
}

/**
 * Close the socket and set @isBtConnected as false when the app is closed or crashes
 */
@Override
public void onDestroy() {
    try {
        this.socket.close();
        this.isBtConnected = false;
    }catch (IOException e) {
        e.printStackTrace();
    }
}

}

BLTActivity:

public class BluetoothActivity extends AppCompatActivity {

ActivityBluetoothBinding activityBluetoothBinding;

private BluetoothAdapter adapter;
private Set<BluetoothDevice> pairedDevices;
private ListView listBLTDevice;
private TextView bltTV;

private BluetoothDevice deviceSelected;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    activityBluetoothBinding = DataBindingUtil.setContentView(this, R.layout.activity_bluetooth);
    activityBluetoothBinding.setSettings(MainActivity.loadSettings);
    this.bltTV = findViewById(R.id.bltTV);
    this.listBLTDevice = findViewById(R.id.listBLTDevices);
    setBlt();
}

public static BLTSocket bltSocket;

private void setBlt(){
    this.adapter = BluetoothAdapter.getDefaultAdapter();
    //If the adapter is null, the user's phone hasn't a bluetooth radio
    if(adapter != null){
        if(!adapter.isEnabled()){
            //If the bluetooth is disabled, it asks to the user to enable it
            startActivityForResult(new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), 1);
        }

        //The bonded devices are those ones which have already been compared
        pairedDevices = adapter.getBondedDevices();
        this.bltTV.setText(pairedDevices.size() + " Devices Found");

        if(pairedDevices.size() > 0){

            /*
             *  Create a new list of strings which every one contains the name of one compared
             *  bluetooth radio. The array list is given to the adapter.
             */
            final ArrayList<String> arrayList = new ArrayList<>();
            for (BluetoothDevice device : pairedDevices){
                arrayList.add(device.getName());
            }
            final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, getListViewLayout(), arrayList);
            this.listBLTDevice.setAdapter(adapter);

            /*
                When an item (string that represents a bluetooth radio) has been clicked,
                its MAC address is given to the BLTSocket constructor, which will set
                the opportune variable, objects and connects our radio with the selected one
             */
            this.listBLTDevice.setOnItemClickListener( (parent, v, pos, id) -> {
                deviceSelected = (BluetoothDevice) pairedDevices.toArray()[pos];
                Toast.makeText(getApplicationContext(), "Device Selected: " + deviceSelected.getName() + "\n" + deviceSelected.getAddress(), Toast.LENGTH_SHORT).show();
                bltSocket = new BLTSocket(deviceSelected.getAddress());
                startService(new Intent(this, BLTSocket.class));
            } );
        }
    }else{
        Toast.makeText(getApplicationContext(), "Seems like your device hasn't any bluetooth adapter...", Toast.LENGTH_SHORT).show();
    }
}

/**
 * Called when setting the ArrayAdapter to chose list layout with the right color of the text
 * If the user has the dark mode enabled, this method returns the white list and vice versa
 *
 * @return the id of the opportune listview layout
 */
private int getListViewLayout() {
    return !MainActivity.loadSettings.isDarkMode() ? R.layout.listview_blacktext_layout : R.layout.listview_whitetext_layout;
}

}

DynoZ
  • 169
  • 1
  • 8