SRF08 blocking Adafruit Motor Shield v2.3

Hi! I have another problem with my Arduino Uno based robot. I have an Adafruit Motor Shield v2.3 and an SRF08 distance sensor. The motors run fine and the distance sensor, which is connected to I2C pins 4 and 5 works fine too. But when I try to use them together, the motors stop working after the first ranging by the sensor. The code below turns the motors only once. The distance sensor data is printed to Serial Monitor but the motors no longer turn.

So whats going on? I have stared at the adafruit library and wire library and googled this but I cant figure it out.

#include <Servo.h> 
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
#include <SonarSRF08.h>


#define MAIN_08_ADDRESS (0x70)
#define GAIN_REGISTER 0x09
#define LOCATION_REGISTER 0x8C

char unit = 'c'; // 'i' for inches, 'c' for centimeters, 'm' for micro-seconds

    SonarSRF08 MainSonar;
    
    Servo panServo;  // create servo object to control a servo 
                // a maximum of eight servo objects can be created 
    Servo tiltServo;

    // Motor settings
    Adafruit_MotorShield AFMS = Adafruit_MotorShield(); 
    
    Adafruit_DCMotor *leftRearMotor = AFMS.getMotor(1);
    Adafruit_DCMotor *rightRearMotor = AFMS.getMotor(2);
    Adafruit_DCMotor *rightFrontMotor = AFMS.getMotor(3);
    Adafruit_DCMotor *leftFrontMotor = AFMS.getMotor(4);
    
    
void setup() 
{ 
    MainSonar.connect(MAIN_08_ADDRESS, GAIN_REGISTER, LOCATION_REGISTER);
    isConnected("SRF08", MainSonar.getSoft());
     Serial.begin(9600);
    AFMS.begin();
     
} 
  
void loop() 
{ 
        leftRearMotor->run(BACKWARD);
        rightRearMotor->run(BACKWARD);
        rightFrontMotor->run(BACKWARD);
        leftFrontMotor->run(BACKWARD);
        
        leftRearMotor->setSpeed(150);
        rightRearMotor->setSpeed(150);
        rightFrontMotor->setSpeed(150);
        leftFrontMotor->setSpeed(150);
        delay(500);
        
        leftRearMotor->run(RELEASE);
        rightRearMotor->run(RELEASE);
        rightFrontMotor->run(RELEASE);
        leftFrontMotor->run(RELEASE);
        delay(500); 
    
    float sensorReading = 0;
    sensorReading = MainSonar.getRange(unit);
    
    distance("sensor", sensorReading);
    
    
        
  }
  
// Print out distance
void distance(String reference, int sensorReading) {
    Serial.print("Distance from " + reference + ": ");
    Serial.print(sensorReading);
    Serial.println(unit);
}

void isConnected(String reference, int sensorSoft) {
    if (sensorSoft >= 0)
    {
        Serial.print("Sensor " + reference + " connected (");
        Serial.print(sensorSoft);
        Serial.println(")");
    }
    else
    {
        Serial.println("Sensor " + reference + " not detected");
    }
  
  }

EDIT: I did some testing and calling begin() on the Adafruit Motor Shield Library to start the motor shield fixes the problem and allows for the commands to get through to the motors. begin() seems to do the following:

  • calls begin() from the Wire library,
  • calls begin() from the Adafruit PWMServoDriver library,
  • sets PWM frequency for the PWMServoDriver instance, and
  • stops all motors using the PWMServoDriver instance.

That is, I believe this is what is does, I’m not 100 % confident I understand the libraries. My understanding is that the PWMServoDriver is used for PWM by the shield to drive the DC motors.

So I really dont understand why the shield stops working but it seems that one of those things seems to fix the issue. I dont think I’m supposed to keep calling begin(). Also, I’m not quite sure if this is something related to I2C or something else…

Just an update on this in case someone stumbles upon this. The cause was that the SRF08 range finder uses the same I2C address as the Adafruit Motor Shield v2.3. The solution was running an Arduino code that changes the range finder I2C address by calling the SRF08 library changeAddress function. You only need to run it once.

I used this piece of code to set the address to 0xF8:

#include <Wire.h>
#include <SonarSRF08.h>

SonarSRF08 MySonar;

#define MAIN_08_ADDRESS (0xE0 >> 1)
#define GAIN_REGISTER 0x09
#define LOCATION_REGISTER 0x8C

int New_Address = 248; // 0xF8

void setup()
{
  MySonar.connect(MAIN_08_ADDRESS, GAIN_REGISTER, LOCATION_REGISTER);  
  MySonar.changeAddress(New_Address);
}

void loop()
{
}

You only need to run this once. After this, the address will be 0xF8 and so you can define the address for your connect function call by #define MAIN_08_ADDRESS 0xF8 if you use the above connect function call.

Its nice to have much cleaner code now, since I was able to remove the extra calls to motor shield’s begin() function! Besides cleaning up code, I’m adding a Raspberry Pi to the robot and will run a simple OpenCV computer vision code on it to spot a blue ball in a webcam feed! I’m thrilled with OpenCV and the stuff you can do. I have the code running on my Pi, just a matter of connecting it to my Arduino, but that’s a story for another time!