Chapter 7 Solutions

Question Solutions

  1. 38 kHz is the frequency of the signal. Although the 8 in tone call’s ms parameter calls for a signal that lasts for 8 ms, the book said that testing indicated it lasted for 1.1 ms.  The IR LED must be connected to the digital pin 8 socket for the tone signal to make it flash on/off at 38 kHz. 
  2. The code has to pause for 1 ms with delay(1) and then store the IR value by copying whatever digitalRead returns to a variable; for example, delay(1) followed by irLeft = digitalRead(10).
  3. A low signal means that 38 kHz IR was detected, which means that the 38 kHz flashing light the IR LED transmitted must have reflected off an object in its path.  In other words: object detected.  A high signal means no 38 kHz IR was detected, so, there wasn’t any object to reflect the IR LED’s light.  In other words: object not detected.
  4. For both red and infrared LEDs, a smaller resistor will cause the LED to glow more brightly.  A larger resistor results in dimmer LEDs. In terms of results, brighter IR LEDs make it possible to detect objects that are farther away.  But it can also have annoying side effects, like seeing the reflection of the surface it is rolling on and misinterpreting it as an obstacle.

Exercise Solutions

  1. Let’s remove the left IR detector from the code.  Comment out int irLeft = digitalRead(10) by placing // to its left.  Then, change if((irLeft == 0) || (irRight == 0)) to if(irRight == 0).
  2. Remember that linear wheel speed control is in the -100 to 100 range.  So -75 should be a little slower than full speed backward.  With that in mind, try changing  maneuver(-200, -200, 250) to maneuver(-75, -200, 250).

Project Solutions

  1. One approach would be to add this code at the end of the setup function in FastIrRoaming.  It will wait until an object is detected before allowing the code to move on to the roaming code in the loop function.
  int irLeft = 1;                         // Declare IR variables and
  int irRight = 1;                        // initialize both to 1
 
  while((irLeft == 1) && (irRight == 1))  // Wait for detection
  {
    irLeft = irDetect(9, 10, 38000);      // Check for object on left
    irRight = irDetect(2, 3, 38000);      // Check for object on right
  }    
  1. Rotating in place and waiting to see an object is almost the same as project 1.  The trick is to call the maneuver function to make it rotate slowly.  Remember that the maneuver function’s msTime parameter just dictates low long the maneuver routine prevents another maneuver from making the BOE Shield-Bot do something different.  You can instead use it to start a maneuver in a set-it-and forget-it fashion.  Then, let the code continue to the loop that monitors the IR detectors until it detects an object.
  int irLeft = 1;                         // Declare IR variables and
  int irRight = 1;                        // initialize both to 1
 
  while((irLeft == 1) && (irRight == 1))  // Wait for detection
  {
    irLeft = irDetect(9, 10, 38000);      // Check for object on left
    irRight = irDetect(2, 3, 38000);      // Check for object on right
  }    

Now, to chase after an object, the if…else if…else statement needs to be updated so that it goes forward when it sees an object with both sensors.  It should also turn toward an object instead of away from it.  Here is a modified loop function.

void loop()                              // Main loop auto-repeats
{
 
  int irLeft = irDetect(9, 10, 38000);   // Check for object on left
  int irRight = irDetect(2, 3, 38000);   // Check for object on right

  if((irLeft == 0) && (irRight == 0))    // If both sides detect
  {
    maneuver(200, 200, 20);              // Forward 20 ms, chase object
  }
  else if(irLeft == 0)                   // If only left side detects
  {
    maneuver(-200, 200, 20);             // Left toward object 20 ms
  }
    else if(irRight == 0)                // If only right side detects
  {
    maneuver(200, -200, 20);             // Right toward object 20 ms
  }
  else                                   // Otherwise, no IR detects
  {
    maneuver(200, 200, 20);              // Forward 20 ms
  }
}

The example above goes forward for 20 ms if it does not see the object.  Optionally, it could spin in place until it sees an object and then chase after it again.  For this, you could place the code that spins and waits for a detection in a function.  Then, your code could call that function from the end of the setup function to wait until it sees something, and also from the else statement in the loop function for when it can’t see the object any more.

  1. The key to solving this problem is to combine FastIrRoaming and the tone portion of IrInterferenceSniffer in a single sketch.  This example also turns on the lights while it sounds the alarm.  One note, the compiler in the Arduino software won’t let you declare a variable twice in the same code block.  So, in the loop function, the first time the irLeft and irRight variables are used, they are declared with int.  The second time within the loop, they are just reused for detection (without using int to declare them) because they have already been declared.  Modified setup and loop functions are shown here: 
void setup()                                 // Built-in initialization block
{
  pinMode(10, INPUT);  pinMode(9, OUTPUT);   // Left IR LED & Receiver
  pinMode(3, INPUT);  pinMode(2, OUTPUT);    // Right IR LED & Receiver
  pinMode(8, OUTPUT); pinMode(7, OUTPUT);    // LED indicators -> output

  tone(4, 3000, 1000);                       // Play tone for 1 second
  delay(1000);                               // Delay to finish tone

  servoLeft.attach(13);                      // Attach left signal to pin 13
  servoRight.attach(12);                     // Attach right signal to pin 12
}  
 
void loop()                                  // Main loop auto-repeats
{
  // Sniff  

  int irLeft = digitalRead(10);              // Check for IR on left
  int irRight = digitalRead(3);              // Check for IR on right
 
  if((irLeft == 0) || (irRight == 0))
  {                                         
    for(int i = 0; i < 5; i++)               // Repeat 5 times
    {
      digitalWrite(7, HIGH);                 // Turn indicator LEDs on
      digitalWrite(8, HIGH);
      tone(4, 4000, 10);                     // Sound alarm tone
      delay(20);                             // 10 ms tone, 10 between tones
      digitalWrite(7, LOW);                  // Turn indicator LEDs off
      digitalWrite(8, LOW);
    }
  }  

  // Roam

  irLeft = irDetect(9, 10, 38000);       // Check for object on left
  irRight = irDetect(2, 3, 38000);       // Check for object on right

  if((irLeft == 0) && (irRight == 0))        // If both sides detect
  {
    maneuver(-200, -200, 20);                // Backward 20 milliseconds
  }
  else if(irLeft == 0)                       // If only left side detects
  {
    maneuver(200, -200, 20);                 // Right for 20 ms
  }
    else if(irRight == 0)                    // If only right side detects
  {
    maneuver(-200, 200, 20);                 // Left for 20 ms
  }
  else                                       // Otherwise, no IR detects
  {
    maneuver(200, 200, 20);                  // Forward 20 ms
  }
}