I have been using a Make-It Robotics kit, that I picked up from a RadioShack that was closing, to learn more about Arduino, C, etc. After building the line-following robot and downloading the correct libraries, I can get the robot to function as intended. It uses 2 optical sensors in front of 2 driving wheels that are controlled by independent DC motors. The optical sensors determine if the left or right side of the front of the robot is over a white or black area on the test track. The necessary motor then turns on to keep the black line roughly between the 2 sensors as the robot moves along. The default test track that came with the kit was a large black circle on a white background.

I want to make some modifications to the code (and maybe the underlying library files) to try to make the robot able to handle other types of paths with more acute angles and sharper turns, etc. But, I don't understand some aspects of the highest level .ino source code file.

I am a little unsure of pasting such a long code block below and also don't think an image of it will help. The version data for the file I'm using is below. The files can be found online @ LINK

// ******************************************************************************    **
// * File Name          : linefollow
// * Author             : RadioShack Corporation
// * Version            : V1.0
// * Date               : 2014/01/16
// * Description        : Optical sensors send feedback to PCB 
// *                      to make the robot follow a black line on a white background.
// ********************************************************************************

In this .ino file, I don't understand the code from line 68 onwards: from the Read Left/Right Optical Status onward...

I don't understand some of the bitwise operations there and don't really see how the sensor readings (whether it is over a white or black area on the surface) correlates to which motor activates to keep the robot on the course...

From my limited understanding of Arduino, this robot kit, and the code, it seems like the software and hardware have to interact in this way:

  1. Robot moves forward using both motors turning the wheels in the same direction. It approaches the black test circle at a shallow angle (i.e. almost tangent to it) to allow one sensor to go over the black line before the other one does.
  2. Optical readings of each sensor are taken periodically.
  3. If both sensors detect white space, robot continues to move forward.
  4. If the right sensor detects that it has gone from white to black and then to white, it means that the robot needs to turn to the left to stay on the path.
  5. To turn left, the left motor is un-powered and the right motor is powered until the right sensor detects black again.
  6. Now that the robot is on course, it will keep turning in the direction of the sensor that detects a white to black to white transition.

I am not seeing how my intuitive understanding of the robot's operation matches with that of the code...

  • The files can be found online. - Where online...?
    – Majenko
    Commented Nov 28, 2015 at 16:59
  • @Majenko Please see added LINK in original post. The original "OEM" link that came with the kit's manual gave Error 404, so another site had the files. Commented Nov 28, 2015 at 17:29

2 Answers 2


Indeed, the way the bitwise operations are written is confusing.

  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;  

Basically you have two input values that can be in the same variable - differentiated by the 9th bit of the value. Values between 0 and 255 relate to one sensor, between 256 and 511 to the other. The bitwise operators split that into sensorValue1 and sensorValue2 accordingly.

Then those sensor values are compared to 0 or 255 and used to define the action to perform - that action being comprised of the lowest two bits of a byte variable, so you have three possible actions:

0 = both sensors off
1 = sensor 1 on, sensor 2 off
2 = sensor 1 off, sensor 2 on
3 = both sensors on

The comments in the program also tell you this information:

         left        right
0x00    black        black
0x01    black        white
0x02    white        black
0x03    white        white

Now you have how to deal with the action value:

if(action1 != action2)
  if (action1 == 3 )
  if (action1 == 1)
  if (action1 == 2)
  if (action1 == 0)

So if the action has changed, we can change what we are doing:

  • If action is 3, so if both sensors read as white, or if action is 0, so both sensors read black (in other words if both sensors read the same) then move forwards.

  • If action is 1 (so the left sensor reads black) then turn to the left.

  • If action is 2 (so the right sensor reads black) then turn to the right.

So basically if it doesn't know anything better, it drives forwards, otherwise it turns in the direction that it finds the black line, thus keeping it always on that line. As it drifts off the line one sensor will sense white, so the robot will turn away from that whiteness and back on to the line.

  • Thanks for taking the time to answer my questions. What tripped me up at first was all the values being in Hex and the bit-wise math. I had to read up on bitwise math on the Arduino reference website. Commented Nov 29, 2015 at 20:16

In addition to the answer given on this site, I had to do some reading up on what bit-wise operations are and how they are useful. I did most of that reading on the Arduino website reference section.

I also stumbled across an online tech blog that actually dissected the inner workings of this program! The blog's author seemed glad to help Arduino beginners who got this kit, but had trouble understanding how exactly the robot moved in response to the sensor data.


Someone even asked the blog's author about why anyone would code the logic in this manner. I too was wondering the same as to why it wasn't done at a higher (thus easier to understand level). Below is the author's response to that question. Can anyone here comment on it in terms of its veracity?

Hello Richard, Yes I agree this logic is non-intuitive. I would have done the >logic on the mirco-controller, that lives on the driver board, and just had >the read_Optical() method return a 0, 1, 2, or 3. But there is one possible >reason for this logic. Performing bitwise operations in most cases takes up >less CPU cycles than complex number comparisons. Since Radio Shack is not >providing us the source code that runs on the driver board. Then we can only >guess. Also sometimes bare metal programmers think in these terms, which may >seem non-intuitive at times, but the more we start working at the bit level >the more it makes sense.

Thanks for the post.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.