What do I use for SevenBitHuh parameter to change I2C sensor address?

I got 3 of the Maxbotix MB1222 sonic sensors for a bot and am trying to figure out how to change the address of 2 of them. The default address is 0x70 and I want to change one to 0x68 and the other to 0x72. I know I have to hook each one up separately and run the change on each one, but I’m not sure what the heck I am supposed to pass in as the “SevenBitHuh” for the ChangeAddress function.

/* Commands a sensor at oldAddress to change its address to newAddress
oldAddress must be the 7-bit form of the address that is used by Wire
7BitHuh determines whether newAddress is given as the new 7 bit version or the 8 bit version of the address
If true, if is the 7 bit version, if false, it is the 8 bit version
*/
/* Code for Arduino Mega 2650
Assumes the sensor is using the default address
Sensor Connections:
Pin 7 to GND
Pin 6 to 5V
Pin 5 to SCL(21)
Pin 4 to SDA (20)

*/
#include "Wire.h"
#define SensorAddress byte(0x70)
//These are the two commands that need to be sent in sequence to change the sensor address
#define ChangeAddressCommand1 byte(0xAA)
#define ChangeAddressCommand2 byte(0xA5)


void setup() {
 Serial.begin(9600); //Open serial connection at 9600 baud
 Wire.begin(); //Initiate Wire library for I2C communications with the I2CXL-MaxSonar-EZ

 changeAddress(0X70,0x68, ????????? );//run once...comment this line out and uncomment one below
// changeAddress(0X70,0x72, ????????? );
}

void changeAddress(byte oldAddress, byte newAddress, boolean SevenBitHuh){
 Wire.beginTransmission(oldAddress); //Begin addressing
 Wire.write(ChangeAddressCommand1); //Send first change address command
 Wire.write(ChangeAddressCommand2); //Send second change address command
 byte temp;
 if(SevenBitHuh){ 
     temp = newAddress << 1; 
} //The new address must be written to the sensor
 else { temp = newAddress; } //in the 8bit form, so this handles automatic shifting

 Wire.write(temp); //Send the new address to change to
 Wire.endTransmission();
}


void loop() {
}

if(SevenBitHuh){ temp = newAddress << 1; }

The wire lib should take care of the shifting of the address. What happens if you completely remove it?

I tried that using this modified code. Now it doesn’t recognize the sensor at all.

#include "Wire.h"
#define SensorAddress byte(0x70)

//These are the two commands that need to be sent in sequence to change the sensor address
#define ChangeAddressCommand1 byte(0xAA)
#define ChangeAddressCommand2 byte(0xA5)


void setup() {
 Serial.begin(9600); //Open serial connection at 9600 baud
 Wire.begin(); //Initiate Wire library for I2C communications with the I2CXL-MaxSonar-EZ
 changeAddress(0X70,0x68);
}
void changeAddress(byte oldAddress, byte newAddress){
//void changeAddress(byte oldAddress, byte newAddress, boolean SevenBitHuh){
Wire.beginTransmission(oldAddress); //Begin addressing
 Wire.write(ChangeAddressCommand1); //Send first change address command
 Wire.write(ChangeAddressCommand2); //Send second change address command
 //byte temp;
// if(SevenBitHuh){ temp = newAddress << 1; } //The new address must be written to the sensor
 //else { temp = newAddress; } //in the 8bit form, so this handles automatic shifting

 //Wire.write(temp); //Send the new address to change to
 Wire.write(newAddress); //Send the new address to change to
 Wire.endTransmission();
}


void loop() {
}

Here is a link for the code I was using:

I am able to temporarily get readings again if I disconnect the sensor from power, then hook it up with pin 1 grounded and have it polling the default sensor address.

According to the MB1222 datasheet:
“Pin 1-Temporary Default: This pin is internally pulled high. On power up, the state of this pin is checked; if left high or disconnected, the sensor will use the address stored memory for I2C communications. If pulled low, the sensor will use its default address for the current power cycle.”


can you see the device with an i2cscanner?

what address does it return?

If true, if is the 7 bit version, if false, it is the 8 bit version
reading this comments in top of the sketch makes me think you should use false; for this HUH parameter.

/* Commands a sensor at oldAddress to change its address to newAddress
oldAddress must be the 7-bit form of the address that is used by Wire
7BitHuh determines whether newAddress is given as the new 7 bit version or the 8 bit version of the address
If true, if is the 7 bit version, if false, it is the 8 bit version
*/

/* Code for Arduino Mega 2650
Assumes the sensor is using the default address
Sensor Connections:
Pin 7 to GND
Pin 6 to 5V
Pin 5 to SCL(21)
Pin 4 to SDA (20)

*/

#include "Wire.h"
#define SensorAddress byte(0x70)

//These are the two commands that need to be sent in sequence to change the sensor address
#define ChangeAddressCommand1 byte(0xAA)
#define ChangeAddressCommand2 byte(0xA5)


void setup() 
{
  Serial.begin(9600); //Open serial connection at 9600 baud
  Wire.begin(); //Initiate Wire library for I2C communications with the I2CXL-MaxSonar-EZ

  changeAddress(0X70, 0x68, false ); //run once...comment this line out and uncomment one below
  // changeAddress(0X70,0x72. false);
}

void changeAddress(byte oldAddress, byte newAddress, boolean SevenBitHuh) 
{
  Wire.beginTransmission(oldAddress); //Begin addressing
  Wire.write(ChangeAddressCommand1); //Send first change address command
  Wire.write(ChangeAddressCommand2); //Send second change address command
  byte temp;
  if (SevenBitHuh) 
  {
    temp = newAddress << 1;
  } //The new address must be written to the sensor
  else 
  {
    temp = newAddress;  //in the 8bit form, so this handles automatic shifting
  }

  Wire.write(temp); //Send the new address to change to
  Wire.endTransmission();
}


void loop() 
{
}

I uploaded the I2CScanner code you linked to and it found the device at address 0x34, so it had done a right shift, dividing the address I had input (0x68) by 2 when I attempted to change it the first time.

I was unable to change the address at all at this point without disconnecting the sensor, grounding pin 1, and reconnecting in order to temporarily change the address back to the default of 0x70. Then I ran the slightly modified code below to change the address to 0x68.

The program wouldn’t make any changes when the sensor address was 0x34.

I cleaned up the code a bit and got it to work. Thanks! Now I have 3 sensors with different addresses. You helped tremendously. Sometimes folks who have been programming for a long time assume others know what they do and don’t comment in programs to make it more understandable for relative newbies.

#include "Wire.h"
//The Arduino Wire library uses the 7-bit version of the address, so the code example uses 0x70 instead of the 8-bit 0xE0
#define SensorAddress byte(0x70)
//These are the two commands that need to be sent in sequence to change the sensor address
#define ChangeAddressCommand1 byte(0xAA)
#define ChangeAddressCommand2 byte(0xA5) 

boolean BitHuh = 1; //set to true...change to false (0) if using 8 bit

void setup() {
 Serial.begin(9600); //Open serial connection at 9600 baud
 Wire.begin(); //Initiate Wire library for I2C communications with the I2CXL-MaxSonar-EZ
 
 changeAddress(0X70,0x68,BitHuh);
}
/*For SevenBitHuh, use BitHuh = 1 (true) if address is 7 bit or 0 (false) if address is 8 bit*/
void changeAddress(byte oldAddress, byte newAddress, boolean SevenBitHuh){
  
 Wire.beginTransmission(SensorAddress); //Begin addressing
 Wire.write(ChangeAddressCommand1); //Send first change address command
 Wire.write(ChangeAddressCommand2); //Send second change address command
 if(SevenBitHuh){ newAddress = newAddress << 1; } //Perform a bitwise shift on newAddress if it is a 7 bit address
 Wire.write(newAddress); //Write the new address to the sensor
 Wire.endTransmission();
}

void loop(){

}

Here is my code to sequentially poll three sensors with these addresses: 0x68 (left sensor), 0x70 (middle), and 0x72 (right). I have mounted them on a servo hub with one pointing straight ahead, one at a 45 degree angle pointing left and the third at a 45 degree angle pointing right.

The servo will move left/right to find a clear path for my bot to travel depending on where an obstacle is encountered, though this code has not yet been created:

/* Code for ArduinoMega 2650
Sensor Connections:
Pin 7 to GND
Pin 6 to 5V
Pin 5 to SCL
Pin 4 to SDA
Requires pull-ups for SCL and SDA connected to 5V to work reliably
*/
#include "Wire.h"
//The Arduino Wire library uses the 7-bit version of the address, so the code example uses 0x70 instead of the 8-bit 0xE0
#define LEFT_SENSOR_ADDRESS byte(0x68)//address of Maxbotix MB122 mounted on left side of servo horn
#define MIDDLE_SENSOR_ADDRESS byte(0x70)//address of Maxbotix MB122 mounted at middle of servo horn
#define RIGHT_SENSOR_ADDRESS byte(0x72)//address of Maxbotix MB122 mounted on right side of servo horn

//The sensors ranging command has a value of 0x51
#define RANGE_COMMAND byte(0x51)

void setup() {
 Serial.begin(9600); //Open serial connection at 9600 baud
 Wire.begin(); //Initiate Wire library for I2C communications with the I2CXL-MaxSonar-EZ
}
void loop(){

 pollAllSensors();
 
}

/*Function to tells a sensor to take a reading 
  Receives: the address of a sensor
  Returns: nothing
  */
void takeRangeReading(byte sensorAddress){
 Wire.beginTransmission(sensorAddress); //Start addressing
 Wire.write(RANGE_COMMAND); //send range command
 Wire.endTransmission(); //Stop and do something else now
}
/*Function to poll a sensor for a range 
  Receives: the address of a sensor
  Returns: a range in cm from an object or 0 if there is no communication*/
  
word requestRange(byte sensorAddress){
 Wire.requestFrom(sensorAddress, byte(2));
 if(Wire.available() >= 2){ //Sensor responded with the two bytes
 byte HighByte = Wire.read(); //Read the high byte back
 byte LowByte = Wire.read(); //Read the low byte back
 word range = word(HighByte, LowByte); //Make a 16-bit word out of the two bytes for the range
 return range;
 }
 else {
 return word(0); //Else nothing was received, return 0
 }
}

/*Function to poll the left sensor
  Recieves:  nothing
  Returns:  nothing
  */
word leftSensorPoll(){
  byte sensorAddress = LEFT_SENSOR_ADDRESS;
  takeRangeReading(sensorAddress);
  delay(100); //Wait for sensor to finish
  word range = requestRange(sensorAddress); //Get the range from the sensor
 Serial.print("Left Range: \t"); Serial.print(range); Serial.print("\t");//Print to the user
}

/*Function to poll the middle sensor
  Recieves:  nothing
  Returns:  nothing
  */
word middleSensorPoll(){
  byte sensorAddress = MIDDLE_SENSOR_ADDRESS;
  takeRangeReading(sensorAddress);
  delay(100); //Wait for sensor to finish
  word range = requestRange(sensorAddress); //Get the range from the sensor
 Serial.print("Middle Range: \t"); Serial.print(range); Serial.print("\t");//Print to the user
}

/*Function to poll the right sensor
  Recieves:  nothing
  Returns:  nothing
  */
word rightSensorPoll(){
  byte sensorAddress = RIGHT_SENSOR_ADDRESS;
  takeRangeReading(sensorAddress);
  delay(100); //Wait for sensor to finish
  word range = requestRange(sensorAddress); //Get the range from the sensor
 Serial.print("Right Range: \t"); Serial.println(range); //Print to the user
}
/*Function to sequentially poll all three sensors mounted on the servo
  Recieves:  nothing
  Returns:  nothing
  */
void pollAllSensors(){
leftSensorPoll();
middleSensorPoll();
rightSensorPoll();
}