• Post author:
  • Post category:Android
  • Reading time:11 mins read

In the spirit of naming thing, let’s call this one LaRo cause why not!
The Laro is an Arduino powered dc motor vehicle controlled with a smartphone via bluetooth. It has 4 500RPM DC motors controlled with a L293D based motor driver circuit and an arduino uno. A smartphone app acting as a controller communicates and connects with arduino with the help of a bluetooth module(HC-05). A 12V LiPo battery powers the circuit. A voltage regulator IC (7809) has been used to provide a stable 9V to arduino.
All the components involved have been summerized below:

  1. Arduino Uno
  2. HC-05 Bluetooth module
  3. 2 dual H-bridge IC L293D
  4. 7809 voltage regulator IC
  5. 12V LiPo battery

Schematics

Shown below is the L293D motor driver circuit and its connections with Arduino.

schematics

And here’s how we connect the arduino with the bluetooth module. Please note that the Rx and Tx pin of the Bluetooth module goes to the Tx and Rx pin of arduino respectively.

schem1

Android App

We are gonna need to access the bluetooth of the smartphone to connect with the arduino, so we need to define the permissions in the AndroidManifest.xml file:

<uses-permission android:name="android.permission.BLUETOOTH"/>

Next we need to set the layout of the app in activity_main.xml

<TextView
android:id="@+id/textView2"
android:layout_width="73dp"
android:layout_height="33dp"
android:layout_marginBottom="8dp"
android:rotation="90"
android:text="TextView"
android:textAlignment="center"
app:layout_constraintBottom_toTopOf="@+id/seekBar2"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />

<TextView
android:id="@+id/textView1"
android:layout_width="73dp"
android:layout_height="33dp"
android:layout_marginTop="8dp"
android:rotation="90"
android:text="TextView"
android:textAlignment="center"
app:layout_constraintHorizontal_bias="0.501"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/seekBar1" />

<SeekBar
android:id="@+id/seekBar2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:minHeight="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />

<SeekBar
android:id="@+id/seekBar1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:minHeight="50dp"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/buttonStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:rotation="90"
android:text="Start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:onClick="onClickStart"/>

<TextView
android:id="@+id/textView3"
android:layout_width="165dp"
android:layout_height="189dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:rotation="90"
android:text="Status"
android:textAlignment="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/buttonStart"
app:layout_constraintTop_toTopOf="parent" />

The layout look like this:

wp-1505564825772.

Not very pretty i know, but it gets the job done.
The seek bar one the left is forward and backward motion and the right one is for turning. The start button activates the sliders only if the device is connected to the bluetooth module on arduino. The Arduino sends back the data it just got which is displayed in the TextView below the start button.

Now we need to code the brain of this app- MainActivity.java.

Shown below is the routine that tracks seekbar1 i.e. the left seek bar which controls the forward and backward motion:

public void seekbar1() {
seek_bar1 = (SeekBar) findViewById(R.id.seekBar1);
text_view1 = (TextView) findViewById(R.id.textView1);
seek_bar1.setProgress(50);
text_view1.setText(String.valueOf(seek_bar1.getProgress() - 50));

seek_bar1.setOnSeekBarChangeListener(
new SeekBar.OnSeekBarChangeListener() {

int progress_value;
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
progress_value = progress - 50;
//evaluating string to be sent
int scaledVal = abs(10*progress_value);
int ones = (scaledVal % 10);
int tens = ((scaledVal % 100) - ones)/10;
int hun = scaledVal/100;
String string = String.valueOf(hun)+String.valueOf(tens)+String.valueOf(ones);
if (progress_value >= 0){
string = "<+" + string;
}else{
string = "<-" + string;
}
//String evaluation ends
seek1Out = string;
send();
text_view1.setText(String.valueOf(progress_value));
Toast.makeText(MainActivity.this, "seekBar1 in progress", Toast.LENGTH_LONG).show();
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
Toast.makeText(MainActivity.this, "seekBar1 in start", Toast.LENGTH_LONG).show();
}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
text_view1.setText(String.valueOf(progress_value));
Toast.makeText(MainActivity.this, "seekBar1 in stop", Toast.LENGTH_LONG).show();
}
}
);
}

The code initializes the seek bar at 50% so that all values greater than 50 are positive and less are negative which can then be translated into forward and backward motion.

The code below tracks seek bar 2 i.e. the right seek bar that controls the direction.

public void seekbar2() {
seek_bar2 = (SeekBar) findViewById(R.id.seekBar2);
text_view2 = (TextView) findViewById(R.id.textView2);
seek_bar2.setProgress(50);
text_view2.setText(String.valueOf(seek_bar2.getProgress() - 50));

seek_bar2.setOnSeekBarChangeListener(
new SeekBar.OnSeekBarChangeListener() {

int progress_value;
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
progress_value = progress - 50;

//evaluating string to be sent
int scaledVal = abs(10*progress_value);
int ones = (scaledVal % 10);
int tens = ((scaledVal % 100) - ones)/10;
int hun = scaledVal/100;
String string = String.valueOf(hun)+String.valueOf(tens)+String.valueOf(ones);
if (progress_value &amp;amp;amp;amp;amp;amp;gt;= 0){
string = "l" + string + ">";
}else{
string = "r" + string + ">";
}
//String evaluation ends

seek2Out = string;
send();
text_view2.setText(String.valueOf(progress_value));
Toast.makeText(MainActivity.this, "seekBar2 in progress", Toast.LENGTH_LONG).show();
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
Toast.makeText(MainActivity.this, "seekBar2 in start", Toast.LENGTH_LONG).show();
}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
text_view2.setText(String.valueOf(progress_value));
Toast.makeText(MainActivity.this, "seekBar2 in stop", Toast.LENGTH_LONG).show();
}
}
);
}

Seek bar 2 is also initialized halfway through with values greater that 50 turn the bot left and values less than 50 turn the bot right. The intensity of turn/throttle depends on how far the seek bar is from the middle.

Now, the format in which data is sent to arduino is “<+200r050>”. Here, the “r050>” part of the output string is set by seekbar2 function. The “r” implies a right turn with intensity “050”. The “<” and “>” are markers that signify the start and end of the instruction.

This concludes the Android app section of the project.
Next is the Arduino code.

Arduino Code

Now that the controller app is sending the instructions, the arduino needs to catch it. The code below from this post in arduino forum accomplishes this task.

void recvWithStartEndMarkers(){
static boolean recvInProgress = false;
static byte i = 0;
char startMarker = '&lt;';
char endMarker = '&gt;';
char rc;

while(Serial.available() > 0 && newData == false){
rc = Serial.read();

if(recvInProgress == true){
if(rc != endMarker){
receivedChars[i] = rc;
i++;
}else{
recvInProgress = false;
i = 0;
newData = true;
}
}else if(rc == startMarker){
recvInProgress = true;
}
}
}

Now that we have our data in the array receivedChars, we can extract the instructions to drive the motors from it.

The below code extracts the left and right seekbar level from the array containing the recieve instruction.

int calculateLevelLin(){
int huns = receivedChars[1] - '0';
int tens = receivedChars[2] - '0';
int ones = receivedChars[3] - '0';

int level = 100*huns + 10*tens + ones;
return level;
}

int calculateLevelDir(){
int huns = receivedChars[5] - '0';
int tens = receivedChars[6] - '0';
int ones = receivedChars[7] - '0';

int level = 100*huns + 10*tens + ones;
return level;
}

Once we have the linear speed and the turn speed, we can turn the bot by creating a speed differential between the left and right motors. This has been done in the code below:

int calculatelevelRight(char dir, int levelDir, int levelLin){
if(dir == 'l'){
return (levelLin + levelDir/2);
}else{
return (levelLin - levelDir/2);
}

}

int calculatelevelLeft(char dir, int levelDir, int levelLin){
if(dir == 'l'){
return (levelLin - levelDir/2);
}else{
return (levelLin + levelDir/2);
}
}

Finally, we write these values to the output pins connected to the motors.

motion(receivedChars[0], levelLeft, levelRight);

void motion(char dir, int left, int right){
if(dir == '+'){
analogWrite(mleftA, left);
analogWrite(mleftB, LOW);
analogWrite(mrightA, right);
analogWrite(mrightB, LOW);
}else if(dir == '-'){
analogWrite(mleftB, left);
analogWrite(mleftA, LOW);
analogWrite(mrightB, right);
analogWrite(mrightA, LOW);
}else{
analogWrite(mleftB, LOW);
analogWrite(mleftA, LOW);
analogWrite(mrightB, LOW);
analogWrite(mrightA, LOW);
}
}

And that concludes this project for now. You can watch the demo below.

The complete codes are available on my GitHub so check that out here.

This was just a breadboard implementation and LaRo will return with some upgrades and a lot of Makeup.

If you are curious about using a camera with your Arduino, be sure to checkout this post.

Thanks for visiting.