Programming the Tinker Pi Robot for Arduino Using App Inventor Part 2 #tt27

Tinkerer: Lory Livezey

In Part 2 of this series, we're going to continue with developing the forward motion of the robot.

TAGS{ turbo_tinker=27 } CATEGORIES{ Tinker Pi->Tinker Pi Robot for Arduino }

In Part 2 of this series, we're going to continue with developing the forward motion of the robot.

Objective

You will learn and practice how to:

  • Create the blocks that use the speed and differential formulas to calculate the speed of the wheels
  • Concatenate strings using blocks

Previous Step

We learned about the formula that we'll be using to determine the speed of the wheels, and we started on the programming.

<<Programming the Tinker Pi Robot for Arduino Using App Inventor Part 1 #tt27<<


Starter Breakpoint

The App Inventor Project (continuing from #tt27, Part 1):

Starter AIA

Mobile App Images

What you will need

!!Tinker Pi Robot Kit for Arduino!! !!Android Phone, Tablet or Kindle!!


Forward Motion

Our first task is to program for the forward motion. We'll add a horizontal arrangement container, and set it to Fill parent....

Horizontal Alignment

Then we'll add 3 more containers inside it. Set them to Height and Width of 50px and click on the PARENT container and select Align Horizontal = Center:

3 containers


Upload and Set Images for Forward Motion

Next, upload all the images we'll be using in our project.

Upload Images

Set the images to the 3 containers we just added:

Set Images

Rename the containers:

Rename Images


Forward Images

If you think about what you would expect to happen as you tilt the phone to steer your robot, you would want there to be a little tolerance in the forward motion -- in other words, you don't want to have to hold the phone exactly 0,0 to go forward or to see the forward image. The diagram below shows the x and y values as we set the images and determine the values to send to the robot.

Set Images

forwardLeft:  y > 0 and x < -30
forward:  y > 0 and x > -30 and x < 30
forwardRight: y > 0 and x > 30 

It often helps to visualize what you're trying to do, and understand it conceptually before you begin programming. Let's build our blocks.

Hint:  If you get stuck on where the blocks are, look at the colors in the picture and click
on that color square in the menu

Set up your blocks like below inside the timer block. If X < 0, we're moving left. If it's greater than 0 we're moving right. + or - 30 and we're moving forward. For now, we're just setting the image on the screen:

Forward Reverse If Else Blocks


Global Variables

Next, we need to determine the values that will be sent to the Arduino. We will set up some global variables to hold these values:

direction:  forward, reverse (string, will eventually also hold stop, go, and pivot)
leftRight:  left or right (string)
speed:  will hold the speed of the faster wheel
differential:  will hold the speed of the slower wheel
leftSpeed:  speed of the left wheel
rightSpeed: speed of the right wheel

NOTE: All of these variables may not be necessary, but were added to make the code more clear

Add Global Variables

Now, set the variables based on the current direction:

Set Global Variables


Calculating the Formulas

Now we'll calculate the speed and differential.

To make the formulas a little simpler, we'll first set the x and y to their absolute values:

Absolutes


Calculate the Speed

The speed formula is:

speed = 255 times y / 255

And we'll format that so it doesn't have a bunch of decimal numbers. If the speed is over 255, then we'll want to set it to 255, because that's our max.

Cap the Speed


Calculate the Differential

We'll use the speed to calculate the differential and format it as a 0 decimal number:

differential = speed - speed times x / 255.  

Calculate Differential

Again, don't allow that to be more than 255.

Cap the Differential


Set the Speed and Differential

We've already calculated the speed and differential. We now need to determine which wheel gets assigned those values. Here is the pseudocode:


PSEUDOCODE: Pseudocode is a way of writing code in plain english, that describes how to program something that is understandable and not specific to a particular language.
You should be able to navigate the blocks well enough by now to write using pseudocode


PSEUDOCODE:
--- if leftRight = "left"
--- --- leftSpeed = differential
--- --- rightSpeed = speed
--- if leftRight = "right"
--- --- leftSpeed = speed
--- --- rightSpeed = differential 
--- else
--- --- both are set to speed

The blocks:

Set the Speed and Differential


Send Values to the Arduino

Next, we'll send 3 values to the Arduino, separated by commas:

direction,leftSpeed,rightSpeed\n

Example:  left,41,124\n

Create the blocks to send these values to the Arduino:

PSEUDOCODE:
... if bluetooth is connected
... ... then send text over bluetooth in format "<direction>,<left speed>,<right speed>"
... ... ... (end the string with a new line)
... end if

Your blocks should now look like this:

Send to Arduino

One more thing before we head back to the Arduino...


Debugging Feedback

I always put some kind of debugging feedback in my code. It makes finding errors much easier, not only for me now, but for someone else modifying my code in the future.

Let's create a label on the screen that shows what is being sent to the Arduino:

Debugging Label

We'll populate the label with the same values that we're passing to the Arduino, if the bluetooth is connected:

Debugging Label

In the else (so if the bluetooth is not connected), display Not Connected:

Debugging Label

We're finally ready to program the Arduino...


Programming the Forward Motion in Arduino

We're starting in the Arduino sketch where we left off after TurboTinker #25. If you don't have it, you can download it from the link at the top of this tutorial. The first thing you'll need to do is add the initialization for the second motor.

Initialize Second Motor

Since I'm passing the values for direction, left and right from the Android, i'm going to set up variables to hold them.

float accel = 0;
String direction = "";
long left = 0;
long right = 0;

Set up variables

Here, we were reading the serial port as a stream, one character at a time. But now, i'm going to use this function called readStringUntil, which will read up until it reaches the string I specify, which is the \n. If you recall, that represents a new line or as we used to say, a carriage return.

Read String Until

Now that we have the direction, left and right in the string, we need to parse out those individual values. And I have a function here that you can copy and paste. Just like the function we wrote in App Inventor, we're going to use a function because we need to call it mulitple times, and I don't want to have to duplicate that code.

Copy/Paste this into the bottom of your sketch:

String getValue(String data, char separator, int index)
{
  int found = 0;
  int strIndex[] = {0, -1};
  int maxIndex = data.length()-1;

  for(int i=0; i<=maxIndex && found<=index; i++){
    if(data.charAt(i)==separator || i==maxIndex){
        found++;
        strIndex[0] = strIndex[1]+1;
        strIndex[1] = (i == maxIndex) ? i+1 : i;
    }
  }

  return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}

So here i'm calling the function 3 times, and passing in the position, 0, 1 and 2, because the array starts at 0.

Call Function

You can copy this code:

    String cmd = mySerial.readStringUntil('\n');
    Serial.println(cmd);
    direction = getValue(cmd,',',0);
    left = getValue(cmd,',',1).toInt();
    right = getValue(cmd,',',2).toInt();

    Serial.print(direction);
    Serial.print(", ");
    Serial.print(left);
    Serial.print(", ");
    Serial.println(right);

Notice we are using the actual serial port (not the software serial) to display the debugging information. This will give you feedback in the terminal showing the values coming through. This is very important troubleshooting information!

Debugging Info

No matter whether we're going in forward or reverse, the left and right wheels will go in the speed of the value that was passed in, so we'll set that first. The speed is set using analogWrite, because we're using something called Pulse Width Modulation. I will have a separate video for that, but for now, think of it as a way of making something digital (1's and 0's) act like it's analog (a wide range of values).

Analog Write

Now i'll add an if block, and if the direction is forward, then set them to HIGH/LOW, reverse set them to LOW/HIGH and stop, set them to LOW/LOW.

Set Motor Values

  analogWrite(enA,left);                          // the speed of the left motor, no matter the direction
  analogWrite(enB,right);                         // the speed of the right motor, no matter the direction
              
  if (direction=="forward") {                     // if the direction is forward, then HIGH/LOW
      digitalWrite(in1, LOW);
      digitalWrite(in2, HIGH);
      digitalWrite(in3, LOW); 
      digitalWrite(in4, HIGH); 
  }
  else if (direction=="reverse") {                // if the direction is reverses, then LOW/HIGH
      digitalWrite(in1, HIGH);
      digitalWrite(in2, LOW);
      digitalWrite(in3, HIGH);
      digitalWrite(in4, LOW);
  }
  else {
      digitalWrite(in1, LOW);                      // if stopped then LOW/LOW
      digitalWrite(in2, LOW);
      digitalWrite(in3, LOW);
      digitalWrite(in4, LOW);
  }

Documenting your code is always a good idea. It helps you remember later, and helps anyone modifying your code later. So as a recap, we're getting the String from Serial port, we're parsing out the values into variables, doing some debugging, setting the speed, then we're setting the direction, turning them off.

Code Documentation Recap

There's the start of our sketch. As always, you can download the final sketch at the bottom of this tutorial.


Finish Breakpoint

Finish AIA


Summary

In Part 2, we uploaded the images and set the forward buttons on the screen. We programmed the Arduino to accept the direction and left/right speeds and to spin the motors accordingly. In Part 3, we're going to finish up our robot by programming out the left/right pivot, stop/go and reverse directions.


Part 3

Be sure to subscribe to our channel!