The main problem: We're using 2 RD02 sets for our 4wd robot; of course we need to change the address of one of them. I wrote the following code based on MD25 documentation to change the address, but it does not work. There are unknown communication errors writing to the command register. I am able to communicate with the devices and write speed changes if only 1 MD25 is connected. I am using 3.3kOhm pullups on a Teensy++. When running this sketch, a single MD25 is the only device on the bus. I've tried w/ + w/o a shared 5v connection, w/ + w/o power applied to the MD25 battery terminal.
Regardless of what the solution turns out to be, I need clarification on what the right arguments to this line should be.
- Code: Select all
changeI2Caddress(0xB0, 0xB4, 16); // also tried with (0x58, 0x59, 16), (58, 59, 16), (0x58, 0xB4, 16), (176, 178, 16)
Note: there was a bit of not strictly necessary debug and human feedback code added when I realized this wasn't working. The main functionality is in this function.
- Code: Select all
void changeI2Caddress(uint8_t oldAddress, uint8_t newAddress, uint8_t commandRegister)
- Code: Select all
/*
addressChange.pde
Author: Dustin Maki 11/10/11
Arduino 022 sketch running on Teensy++
Objective: provide universal method to change I2C address on Devantech I2C devices
Devices available for testing: 2x RD02 w/MD25, 1x CMPS10, 1X TPA81, 1X SD20, 1X LCD03 20X4 GREEN, 1X GPIO14
*/
#include <Wire.h>
static const uint8_t BUTTON = 3;// active low
static const uint8_t LED = 6;
uint8_t transmissionStatus = -1;
void setup()
{
Serial.begin(57600);
Serial.println("Initialized serial.print");
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
pinMode(BUTTON, INPUT);
digitalWrite(BUTTON, HIGH);// engage internal pullup resistor
delay(2000);
while (HIGH == digitalRead(BUTTON))//button NOT pressed
{
delay(1);
// __asm__("nop\n\t"); //do nothing, just wait for button to be pressed
}
digitalWrite(LED, HIGH);//turn led on during address change.
changeI2Caddress(0xB0, 0xB4, 16); // also tried with (0x58, 0x59, 16), (58, 59, 16), (0x58, 0xB4, 16), (176, 178, 16)
delay(1000);// the function happens fast, keep the LED on a bit so a human perceives something was actually done.
/*
TODO: Programatically verify that address has been sucessfully changed.
Perhaps read firmware version at new address, however that method varies by device.
*/
}
void loop()
{
//flash LED following sucessful address change
digitalWrite(LED, LOW);//blink LED when address change complete.
delay(250);
digitalWrite(LED, HIGH);
delay(250);
}
void changeI2Caddress(uint8_t oldAddress, uint8_t newAddress, uint8_t commandRegister) //must be run with ONLY the device whose address is to be changed connected to the I2C bus
{
Serial.println("Entered changeI2Caddress function");
Wire.beginTransmission(oldAddress);
Wire.send(commandRegister);
Wire.send(0xA0); // also tried changing this arguement to 160
transmissionStatus = Wire.endTransmission();
Serial.println("First byte sent");
printI2Cstatus(transmissionStatus);
delay(101);
Wire.beginTransmission(oldAddress);
Wire.send(commandRegister);
Wire.send(0xAA); // also tried changing this arguement to 170
transmissionStatus = Wire.endTransmission();
Serial.println("Second byte sent");
printI2Cstatus(transmissionStatus);
delay(101);
Wire.beginTransmission(oldAddress);
Wire.send(commandRegister);
Wire.send(0xA5); // also tried changing this arguement to 165
transmissionStatus = Wire.endTransmission();
Serial.println("Third byte sent");
printI2Cstatus(transmissionStatus);
delay(101);
Wire.beginTransmission(oldAddress);
Wire.send(commandRegister);
Wire.send(newAddress);
transmissionStatus = Wire.endTransmission();
Serial.println("New address sent");
printI2Cstatus(transmissionStatus);
delay(1000);
Serial.println("Leaving changeI2Caddress function");
}
void printI2Cstatus(uint8_t I2Cstatus)
{
switch (I2Cstatus)
{
case 0:
Serial.println("0 Success");
break;
case 1:
Serial.println("1 data too long to fit in transmit buffer");
break;
case 2:
Serial.println("2 received NACK on transmit of address");
break;
case 3:
Serial.println("3 received NACK on transmit of data");
break;
case 4:
Serial.println("4 other error");
break;
default:
// if nothing else matches, do the default
Serial.print("unrecognized value: ");
Serial.println(I2Cstatus);
}
}
Output from the serial monitor looks like this:
Initialized serial.print
Entered changeI2Caddress function
First byte sent
4 other error
Second byte sent
4 other error
Third byte sent
4 other error
New address sent
4 other error
Leaving changeI2Caddress function
I then remove and reconnect power to the MD25 to see if that green 'communication' LED on MD25 will flash more than once. It never does. FYI, it seems to be a fairly brief flash, well under 1 second. Is that the length of the single 'long' flash indicating the default 0xB0 address?
