Introduction: Make:it Robotics Starter Kit - Understanding Bitwise Math
This blog post is a continuation on my tinkering with the Make:it Robotics Kit. Hopefully I can pass on some of the information that I have learned so it will make it easier for others to get up to speed on working with the Robotics Kit.
After building the line following robot, the manual had a link to download the software for the robot. I tried to navigate to the link and it was not available: http://shack.net/MakeitRobotics.
This is a common problem when manufactures are writing documents, links seem to change and revisions often miss each other. Not a problem Radio Shack was good enough to provide a link to the download files on their web site: http://blog.radioshack.com/2014/05/radioshack-mak...
I will not post the entire source code here as you can download it and follow along. The source code contains library and include files for the Main Robotics Kit, Project 1 and Project 2 Kits and the Sensor Kit. There are individual Arduino Sketch files for each robot provided in the kits.
All of the sketches depend on the a MakeItRobotics.cpp file and a MakeItRobotics.h file. If you need assistance understanding what these files are, google for .cpp file and .h include file. If you need further help drop me an email on this site. Since I built the line following robot this blog post will discuss the line following code, which is named linefollow.ino.
This file is a text file that the Arduino IDE reads or any development environment can read. The linefollow.ino file is documented and should provide a basic understanding of what is going on with the program. But I did find a typo that could cause some confusion. Also I will try to provide some additional information for those folks that are rather new to robotics, Arduino and programming in general.
For more info check out my blog:
Step 1: Arduino Sketch
The linefollow.ino is pretty much a standard Arduino Sketch file, at the beginning of the file is a main comments section, a declaration/include section, a setup() function and a loop() function.
The declaration/include section includes header files, which include definitions and resources that the sketch will used during program execution.
Global objects and variables can also be declared and initialized at this location as well. For example in the linefollow.ino sketch the line_following object is created (or in programming language, this is called instantiated)
Everything in the setup() function is run once when the Arduino first powers up. The setup() function is where you place start up code that initialize things that your loop program needs for program execution. For Example the Arduino needs to talk to the robot motor driver/sensor board using the serial port.
So the setup() function calls the Serial.begin(10420) method to setup the serial port so the Arduino can take with the motor driver board. The loop() function is where all of the action in the program takes place. the loop() function loops or repeats over and over without stopping until the power is removed from the Arduino. This is why the function is called loop().
Step 2: Parsing ReadOptical() Method
As I said there is are a few typos in the comments of the code in linefollow.ino.Every loop the program calls the following function:sensor_in=line_following.read_optical();
The comments for this read_optical() method reads the following:
0×000 optical1 black
0x0ff optical1 white
0×100 optical1 white
0x1ff optical1 black
0x2XX not ready; don’t use this value
Actually is should be the following
0×000 optical1 black
0xff optical1 white
0×100 optical2 white
0x1ff optical2 black
0x2XX not ready; don’t use this value(either sensor can return this value)
Actually 0x0ff should be 0xff
Refer to blog post Software Part 3
You will see in the below paragraphs the importance of these typos.(has to do with reading every other sensor) On the line following robot there are two optical sensors, every time the loop() function executes the linefollow.ino sketch calls a method to see if one of the sensors is seeing light or dark.
On a micro-controller, such as the Arduino, one second is a very long time. The loop() function can execute many thousand times a second. Just how long each loop takes depends on how many program instructions take place. Some instructions take longer to execute than other instructions.
Instruction (what functions and methods are made up of) execution time is measured in CPU clock cycles. The Arduino by default operates at 16 MHz or 16 million clock cycles a second. The linefollow.ino sketch performs some pretty simple logic.
After setting up some variables, the loop() calls a function to see if one sensor is light or dark, Depending on the answer some fancy logic is executed to reduce the answer to a value of 0, 1, 2 or 3. These values are then used to tell the motors to either go forward, turn left or right.
Every 15 milliseconds the loop program is told to switch and read the other sensor. So you have a program that loops reading first one sensor, converts the answer to 0, 1, 2 or 3 ,tell the motors what to do, and then read the other sensor, convert the answer to 0, 1, 2 or 3 and then tell the motors what to do. In many cases, depending on the values of the action1 and action2 variables, the instructions to control the motors are skipped. Refer to a later blog post.
These operations are done again at thousands of times a second. The rest of this blog and later blogs are going to teach you what is happening with the fancy logic that reads the sensor and converts the answer to 0, 1, 2, or 3. The following code segment is the fancy code that converts the sensor readings to a value of0, 1, 2 or 3. This code involves some program instructions that can be quite confusing for newmicro-controller programmers.
Please refer another blog entry that I wrote called “Tutorial – Bit Banging and Boolean Math without the Math” This tutorial goes hand in hand with understanding the following code segment:
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;
This segment of code uses three special operators (instructions that operate on given values) The code uses the following binary operators: & Bitwise AND operator, | Bitwise OR operatorand the >> Bitwise Right Shift operator.
(Read the tutorial)
Step 3: Python to the Rescue
To make this easier so you do not have to convert this by hand I wrote a Python program that does all of the math for you and shows you what is taking place at the binary level, so all you have to do is look at the results.
Install Python on your computer, it is free. Read the tutorial, Everything is explained on how to get started with Python. I have done all of the work for you.
In the next tutorial we will capture some sensor data from the robot and analyze the data with our readOptical.py Python program