Home » Robots » Make:it Robotics Starter Kit – Binary Part 1

Make:it Robotics Starter Kit – Binary Part 1

In our last blog post we captured some sensor data from the three different positions that our robot can encounter when following the black line, (left sensor black, left sensor/right sensor white, right sensor black).

In this blog post we are going to take that sensor data and run it thorough our readOptical.py Python program and evaluate what is happening in our lineFollow.ino program.

We are going to look at the following sections of code:


if((sensor_in & 0xf00) == 0)
sensorValue1 = sensor_in & 0xff;
else if((sensor_in & 0xf00) >> 8 == 1)
sensorValue2 = sensor_in & 0xff;
if (sensorValue1 == 0x00)
action1 = action1 & 0xfe;
if (sensorValue1 == 0xFF)
action1 = action1 | 0x01;
if (sensorValue2 == 0x00)
action1 = action1 | 0x02;
if (sensorValue2 == 0xFF)
action1 = action1 & 0xfd;

if(action1 != action2)
{
if (action1 == 3 )
line_following.go_forward(50);
if (action1 == 1)
line_following.line_following_turn_left(50);
if (action1 == 2)
line_following.line_following_turn_right(50);
if (action1 == 0)
line_following.go_forward(50);
}
action2=action1;

Our readOptical.py Python program pretty much contains the above code, but also calculates the Bitwise operators and converts the program statements (expressions) to binary so we can easily see what the program is really doing.

If you have not do so already, install Python and create the readOptical.py program using your favorite text editor, If you are using Windows, notepad is fine. Create a folder on your computer and place this readOptical.py program in this folder.

I am using Python 2.7, install the latest 2.x of Python from the below web site:

https://www.python.org/download/

Here is a YouTube video, how to install Python and include Python in your Path. This is assuming you are running Windows operating system.

In order to run our program we need to start a Command Prompt, (located in All Programs->Accessories-Command Prompt) Launch this program type the following command at the prompt in the window:

You want to change to the location of the folder where you placed your readOptical.py program.
On my computer I created the folder C:CodePythonreadOptical. So I would type in the following command at the Command Prompt:


>cd CodePythonReadOptical

We are now going to edit our readOptical.py program to include the sensor readings that we wrote down when we captured the sensor data.

So using your favorite text editor, edit readOptical.py and edit the below line to include your sensor readings.

We are going to run our readOptical.py two times, Once with data from our sensors for when both sensors are white and the left sensor black, and a second time with data from our sensors when both sensors are white and the right sensor is black.

This way we can view all of the readOptical.py program output without any data being cut off from the command prompt window.

Edit this line in your readOptical.py program:

optValues = [0xff, 0x100, 0x00, 0x100, 0xff, 0x100]

We have included sensor readings from when both sensors are white, when the sensors on the left sensor is black and again when both sensors are white.

The reason we are doing this is the give you a real example of what the robot would see as it is following a line.

First the robot would see both sensors white (robot straddling the black line) then as the circle turns the robot would see the left sensor become black, at which the robot would turn right until both sensors would see white again. (again I am using Left and Right sensors as I look at the front of the robot.

After editing our readOptical.py program we would type the following at the Command Prompt, (you should be sitting at your folder location where you put your readOptical.py program)


>Python readOptical.py

At this point the program should run and you should see the following output in the Command Prompt.

Copy the output and paste it in another Windows Notepad window, so we can look at this in a minute.

If you receive any errors, edit your readOptical.py program. Python is sensitive to indentation, Python uses space indentation to determine how the program should behave when it executes.

If you receive any indentation errors, you are going to have to go back and check that you pasted the readOptical.py program into your text exitor, that you did not move any indentation on any line of code.

Our first program output should look like the following:
(just look this over for now, we are going to dig deeper in a bit)
(Also refer to your output, it will be formatted so the columns line up better)


Sensor readings (where black strip is located)
Center Left Center

C:CodePythonreadOpticalsrc>python readoptical.py

sensor _in = 0xff
action1 = 0x0
action2 = 0x0
sensorValue1 = 0x0
sensorValue2 = 0x0

0xff & 0xf00
0xff = 0b0000000011111111
0xf00 = 0b0000111100000000
if 0xff & 0xf00 == 0
inside if sensor_in & 0xf00 == 0
0xff & 0xff
sensorValue1 = 0b0000000011111111
& 0b0000000011111111
------------------
0b0000000011111111
sensorValue1 = 0xff

inside of sensorValue1 == 0xff
0x0 | 0x01
action1 = 0b0000000000000000
| 0b0000000000000001
------------------
0b0000000000000001
action1 = 0x1

inside of sensorValue2 == 0x00
0x1 | 0x02
action1 = 0b0000000000000001
| 0b0000000000000010
------------------
0b0000000000000011
action1 = 0x3

go forward

sensor _in = 0x100
action1 = 0x3
action2 = 0x3
sensorValue1 = 0xff
sensorValue2 = 0x0

0x100 & 0xf00
0x100 = 0b0000000100000000
0xf00 = 0b0000111100000000
if 0x100 & 0xf00 == 0
inside elif

0x100 & 0xff
sensorValue2 = 0b0000000100000000
& 0b0000000011111111
------------------
0b0000000000000000
SensorValue2 = 0x0

inside of sensorValue1 == 0xff
0x3 | 0x01
action1 = 0b0000000000000011
| 0b0000000000000001
------------------
0b0000000000000011
action1 = 0x3

inside of sensorValue2 == 0x00
0x3 | 0x02
action1 = 0b0000000000000011
| 0b0000000000000010
------------------
0b0000000000000011
action1 = 0x3

sensor _in = 0x0
action1 = 0x3
action2 = 0x3
sensorValue1 = 0xff
sensorValue2 = 0x0

0x0 & 0xf00
0x0 = 0b0000000000000000
0xf00 = 0b0000111100000000
if 0x0 & 0xf00 == 0
inside if sensor_in & 0xf00 == 0
0x0 & 0xff
sensorValue1 = 0b0000000000000000
& 0b0000000011111111
------------------
0b0000000000000000
sensorValue1 = 0x0

inside sensorValue1 == 0x00
0x3 & 0xfe
action1 = 0b0000000000000011
& 0b0000000011111110
------------------
0b0000000000000010
action1 = 0x2

inside of sensorValue2 == 0x00
0x2 | 0x02
action1 = 0b0000000000000010
| 0b0000000000000010
------------------
0b0000000000000010
action1 = 0x2

turn right

sensor _in = 0x100
action1 = 0x2
action2 = 0x2
sensorValue1 = 0x0
sensorValue2 = 0x0

0x100 & 0xf00
0x100 = 0b0000000100000000
0xf00 = 0b0000111100000000
if 0x100 & 0xf00 == 0
inside elif

0x100 & 0xff
sensorValue2 = 0b0000000100000000
& 0b0000000011111111
------------------
0b0000000000000000
SensorValue2 = 0x0

inside sensorValue1 == 0x00
0x2 & 0xfe
action1 = 0b0000000000000010
& 0b0000000011111110
------------------
0b0000000000000010
action1 = 0x2

inside of sensorValue2 == 0x00
0x2 | 0x02
action1 = 0b0000000000000010
| 0b0000000000000010
------------------
0b0000000000000010
action1 = 0x2

sensor _in = 0xff
action1 = 0x2
action2 = 0x2
sensorValue1 = 0x0
sensorValue2 = 0x0

0xff & 0xf00
0xff = 0b0000000011111111
0xf00 = 0b0000111100000000
if 0xff & 0xf00 == 0
inside if sensor_in & 0xf00 == 0
0xff & 0xff
sensorValue1 = 0b0000000011111111
& 0b0000000011111111
------------------
0b0000000011111111
sensorValue1 = 0xff

inside of sensorValue1 == 0xff
0x2 | 0x01
action1 = 0b0000000000000010
| 0b0000000000000001
------------------
0b0000000000000011
action1 = 0x3

inside of sensorValue2 == 0x00
0x3 | 0x02
action1 = 0b0000000000000011
| 0b0000000000000010
------------------
0b0000000000000011
action1 = 0x3

go forward

sensor _in = 0x100
action1 = 0x3
action2 = 0x3
sensorValue1 = 0xff
sensorValue2 = 0x0

0x100 & 0xf00
0x100 = 0b0000000100000000
0xf00 = 0b0000111100000000
if 0x100 & 0xf00 == 0
inside elif

0x100 & 0xff
sensorValue2 = 0b0000000100000000
& 0b0000000011111111
------------------
0b0000000000000000
SensorValue2 = 0x0

inside of sensorValue1 == 0xff
0x3 | 0x01
action1 = 0b0000000000000011
| 0b0000000000000001
------------------
0b0000000000000011
action1 = 0x3

inside of sensorValue2 == 0x00
0x3 | 0x02
action1 = 0b0000000000000011
| 0b0000000000000010
------------------
0b0000000000000011
action1 = 0x3

Like i said in an earlier blog, I have done all of the math and logic for you, all you have to do is follow along.

Here is your chance to get use to reading binary and hexadecimal numbers. At first is looks like gibberish, but you will get use to it. If you are having problems, Read the tutorials that I have made reference to in my earlier blog posts. If you do not want to go into this great of detail then just look for the sections of output where the results indicate either “go forward”, “turn left” or “turn right”

Lets analyze what is happening inside the program:

First off lets look at the comments of the readOptical() method in our lineFollow.ino program:

0x000 optical1 black
0xff optical1 white
0x100 optical1 white
0x1ff optical1 black
0x2XX not ready; don't use this value

Notice that three optical sensor readings start with either 0x1 or 0x2 hex. The rest start with 0x0 or 0xf.

If you convert these numbers to binary you will see a pattern.
Load Python Idle and type the following:

>>> format(oxff, ‘#018b’)

The format parameter ‘#018b’ indicates to show the passed number as a binary 16 bit number

so the format command will return the following:
‘0b0000000011111111′

Notice that there are 8 zeros followed by 8 1’s.
This 16 bit number has the least significant 8 bits set to 1.
If you type in the following in Python:

>>>hex(int(‘11111111′,2))

You will get:
‘0xff’

Now lets try the following:

>>>format(0x0, ‘#018b’)

Python will return:

‘0b0000000000000000′

Lets try the other two values that the readOptical() function returns.

>>>format(0x1ff, ‘#018b’)
‘0b0000000111111111′

>>> format(0x100, ‘#018b’)
‘0b0000000100000000′

How many 1’s are shown in the binary representation of 0x1ff?
What position is the 1 in, counting from the right, for 0x100?

Correct, In both cases 1 is showing up in the ninth bit position from the right.

The readOptical() method in the lineFollow.ino only returns values that have a distinct pattern.

Optical 1 sensors only return numbers that are set within 8 bits
Optical 2 sensors can have numbers that are set in the ninth bit position, or 16 bit numbers.

Let’s start looking at our results from the readOptical.py Python program.

First we look at the variables that are setup in the beginning of the lineFollow.ino program:

sensor _in = 0xff
action1 = 0x0
action2 = 0x0
sensorValue1 = 0x0
sensorValue2 = 0x0

The first sensor value we are reading is 0xff, the rest of the variables are 0x0
The first If statement performs an BitWise AND on two values:


if((sensor_in & 0xf00) == 0)

Look at the output again:
0xff & 0xf00
0xff = 0b0000000011111111
0xf00 = 0b0000111100000000
if 0xff & 0xf00 == 0
inside if sensor_in & 0xf00 == 0
0xff & 0xff
sensorValue1 = 0b0000000011111111
& 0b0000000011111111
——————
0b0000000011111111
sensorValue1 = 0xff

Look closely at the AND bitwise operation, we are checking to see if any of the upper 8 bits of the 16 bit number sensor_in is set. In this case the AND comparison return 0 as there are no bits greater than the lest significant 8 bits set in the variable sensor_in. So the first part of the if statement will only be true if sensor_in contains 0x000 or 0xff.

Since the first if statement is true, we execute the command of:

sensorValue1 = sensor_in & 0xff;

ANDing a number with itself gives us the same number, sensorValue1 = 0xff

0xff & 0xff
sensorValue1 = 0b0000000011111111
& 0b0000000011111111
——————
0b0000000011111111
sensorValue1 = 0xff

Let’s move on to the second if statement:

if (sensorValue1 == 0x00)

If we look at the sensorValue1 variable, it contains 0xff so this if statement is false and does not get executed.

Moving on:

if (sensorValue1 == 0xFF)

sensor_in is equal to 0xff so we execute the if statement:

action1 = action1 | 0x01;

In this case we are setting the variable of action1 to equal action and apply the Bitwise OR operator to the value of 0x01.
Looking at the results of the OR operation action1 gets set to a value of 0x01.

inside of sensorValue1 == 0xff
0x0 | 0x01
action1 = 0b0000000000000000
| 0b0000000000000001
——————
0b0000000000000001
action1 = 0x1

On the next if statement:

if (sensorValue2 == 0x00)

We check if sensorValue2 is equal to 0x00, and of course currently sensorValue2 is equal to 0x00 so we execute the if statement:

action1 = action1 | 0x02;

inside of sensorValue2 == 0x00
0x1 | 0x02
action1 = 0b0000000000000001
| 0b0000000000000010
——————
0b0000000000000011
action1 = 0x3

In the last if statement we check:

if (sensorValue2 == 0xFF)

sensorValue2 is not equal to 0xff so we move on.

The final value of action1 is 0x03, we exit the last if statement and proceed on the the next set of if statements:


if(action1 != action2)
{
if (action1 == 3 )
line_following.go_forward(50);
if (action1 == 1)
line_following.line_following_turn_left(50);
if (action1 == 2)
line_following.line_following_turn_right(50);
if (action1 == 0)
line_following.go_forward(50);
}
action2=action1;
}

action1 = 0x3
action2 = 0x0

We check the first if statement:

if(action1 != action2)

This is true so we enter the nested if statement:

action1 = 0x3 so we execute the true if statement:

line_following.go_forward(50);

Now in our readOptical.py program we return to the top of the for loop and we begin again with the next value:

sensor_in = 0x100
action1 = 0x3
action2 = 0x3
sensorValue1 = 0xff
sensorValue2 = 0x0

In this case sensor_in variable is equal to 0x100

Let’s look at the first if statement again:

if((sensor_in & 0xf00) == 0)
sensorValue1 = sensor_in & 0xff;
else if((sensor_in & 0xf00) >> 8 == 1)
sensorValue2 = sensor_in & 0xff;

As we pointed out during the last loop, the first if statement is looking for either 0xff or 0x00. In this case the if statement is false, so we jump to the else if statement:

In this case the if statement is doing a Bitwise AND and a Right Shift 8 bits. So we are taking the 1 in the 9 bit location and shifting it 8 times to the right,

0x100 = 0b0000000100000000
0xf00 = 0b0000111100000000
————————–
& 0b0000000100000000

Right Shift
0b0000000000000001

This value does equal 1 so we execute the if statement.

sensorValue2 = sensor_in & 0xff;

0x100 & 0xff
sensorValue2 = 0b0000000100000000
& 0b0000000011111111
——————
0b0000000000000000
SensorValue2 = 0x0

Moving down the if statements, we check the next if statement:

if (sensorValue1 == 0x00)

sensorValue1 equals 0xff so we skip this if statement.

Next if statement:

if (sensorValue1 == 0xFF)
action1 = action1 | 0x01;

The if statement is true so we execute the if statement

inside of sensorValue1 == 0xff
0x3 | 0x01
action1 = 0b0000000000000011
| 0b0000000000000001
——————
0b0000000000000011
action1 = 0x3

Next if statement:


if (sensorValue2 == 0x00)
action1 = action1 | 0x02;

The if statement is true so we execute the if statement

inside of sensorValue2 == 0x00
0x3 | 0x02
action1 = 0b0000000000000011
| 0b0000000000000010
——————
0b0000000000000011
action1 = 0x3

We finish up the if statements and move on the the next set of if statements:

if(action1 != action2)

In this case action1 is equal to action2 so we skip the if statement that sends motor instructions.

We loop back around to the for loop again and select the next sensor_in value.

At this point we have sent the motor driver one set if instructions to go forward, as the sensors are both reading white.

In the next blog post we will move on reading the sensor values when the left sensor is black.

2 thoughts on “Make:it Robotics Starter Kit – Binary Part 1

  1. Joe,
    Custom Sketches
    Is it possible to write a custom sketch using the MakeItRobotics library? I have attempted to write a very basic sketch to drive the robot forward for 5 secs and then stop. I have received some very odd results from the robot that suggest there is more going on then what meets the eye on the included shield. I have used the following code to build the sketch with the loop section.

    void loop()
    line_following.go_forward(50);
    delay(5000);
    line_following.all_stop();
    delay(1000);

    1. Hello Regman, Sorry I have been out of town on vacation. Yes, you should be able to write custom code for the driver board. The best way is to use the methods that were provided, like you tried with the motor control. If you want to look in the MakeItRobotics.cpp you will see how the motor control methods were written.
      There are also some more example code that cam with the download. Check out these sketches. You did not indicate what messages you were getting. But the best way to start is to take the entire linfollowing sketch and cut out the sections you do not need. make sure you include all header file (.h) and #include files in the copy that you are editing. Try this out, if you are still having problems, send me the error messages or describe the problems that you are having.

      Thanks

      Joe

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>