Help with connecting to Gamoto motor controller

Hi - this is probably a lot to ask but I've spent the better part of 2 full days trying to just get an I2C connection going with the Gamoto motor controller. I must be missing something really basic but am now reduced to poking at code without a clue.

Anyway, if someone has the time, the site for the controller is here:
http://tinyurl.com/dy9ymw

This is the user manual with the I2C stuff
http://www.gamatronix.com/gamoto/docs/gamoto_um.pdf

Some sample code for using OOPic
http://www.gamatronix.com/gamoto/software/Gamoto_I2C_sample.html

And this is what I have: (I am sure I have things connected correctly to analog pins 4 + 5, plus Gnd)

--Roy

///gamotoWIRE

byte val;         // variable to receive data from the serial port 
int ledPin = 13;

#include <Wire.h>

void setup()  
{ 

  pinMode(ledPin, OUTPUT);

  int i;
  for (i =0; i < 3; i++){
    digitalWrite(ledPin, HIGH);  
    delay(100); 
    digitalWrite(ledPin, LOW);  
    delay(100);  
  }

  Serial.begin(9600);       // serial to Director 
  Wire.begin();
} 

void loop() { 

  digitalWrite(ledPin, HIGH); 
  Serial.print(1); 

  Wire.beginTransmission(0x92);
  Wire.send(0x92); //write
  Wire.send(0x24); //reg
  Wire.send(0x92); //write
  Wire.endTransmission();     // stop transmitting 

  delay(5);
  Serial.print(2); 

  Wire.beginTransmission(0x93);
  Wire.send(0x92);
  // Wire.send(0x93);
  // Wire.send(0x24); //reg
  Wire.endTransmission(); 
  delay(5);

  /*
  Wire.beginTransmission(1);
   
   Wire.send(146); //write
   Wire.send(36); //reg
   
   Wire.endTransmission();     // stop transmitting 
   delay(5);
   Serial.print(2); 
   
   Wire.beginTransmission(1);
   
   Wire.send(147);
   Wire.send(36); //reg
   Wire.endTransmission(); 
   delay(5);
   */

  Serial.print(3); 
  Wire.requestFrom(0x1, 2);    // request 2 bytes from slave device #0 

  delay(5);
  Serial.print(4); 
  while(Wire.available()){
    char c = Wire.receive(); // receive a byte as character 
    Serial.print(c);         // print the character 
  } 

  // }
  Serial.print(5); 
  delay(1000);
  digitalWrite(ledPin, LOW); 

  delay(1000); 

}

The problem is with the slave address you're using for the motor controller. Assuming you have the 3 address dip switches set to 0 (the default), the slave address you need to use is 0x48.

I know it looks like it should be 0x90, but the Wire library only wants the 7-bit address of the device. The low bit is the R/W bit and that is set automatically by the library depending on the action.

A common way to simplify this is to do something like:

int slaveAddress = 0x90;
Wire.beginTransmission(slaveAddress >> 1);
...
Wire.endTransmission();

If you do the binary math, 0x90 shifted right one bit is 0x48.

Also make sure you have pull-up resistors on the SDA and SCL signal lines.

Wow - that makes a difference! Thanks! Now I am getting a series of HEX
that represents the LSB and MSB.

FF
90
FF
90
FF

According to the Gamoto docs

"All registers are stored with the LSB first, MSB at the highest address. Where noted, some registers have a fractional component. "

How do I combine these to get the actual value? (in this case the register I am reading should have a value of 36 (or 0x24)

(basic question but I've never got the hang of bit shifting.)

Thanks again!

--Roy

///gamotoWIRE

byte val;         // variable to receive data from the serial port 
int ledPin = 13;

#include <Wire.h>

void setup()  
{ 
  pinMode(ledPin, OUTPUT);

  int i;
  for (i =0; i < 3; i++){
    digitalWrite(ledPin, HIGH);  
    delay(100); 
    digitalWrite(ledPin, LOW);  
    delay(100);  
  }

  Serial.begin(9600);       // serial to Director 
  Wire.begin();
} 

void loop() { 
  digitalWrite(ledPin, HIGH); 

  Wire.beginTransmission(0x48);
  Wire.send(0x90); //write
  Wire.send(0x24); //reg
  Wire.send(0x90); //write
  Wire.endTransmission();     // stop transmitting 

  Wire.beginTransmission(0x48);
  Wire.send(0x90);
  Wire.send(0x91);

  Wire.endTransmission(); 

  Wire.requestFrom(0x48, 2);    // request 2 bytes from slave device #0 

  byte b1;
  while(Wire.available()){
    b1 = Wire.receive(); // receive a byte
    Serial.println(b1, HEX);         // print the character 
  } 

  delay(500);
  digitalWrite(ledPin, LOW); 
  delay(500); 
}

First of all, I don't know what you're trying to do with this code:

Wire.beginTransmission(0x48);
  Wire.send(0x90);
  Wire.send(0x91);

  Wire.endTransmission();

According to the data sheet you only need to send a single register address. Also, there doesn't appear to be a register with address 0x90. There is a register at decimal 90 (Raw R/C pulse counts). Maybe this is what you mean?

So if you were trying to read that register, you would want code like this:

Wire.beginTransmission(0x48);
Wire.send(0x5A);  // Decimal 90
Wire.endTransmission()

Wire.requestFrom(0x48, 2);    // request 2 bytes from slave device #0

byte b1;
int registerValue=0;
while(Wire.available()){
  b1 = Wire.receive(); // receive a byte
  Serial.println(b1, HEX);         // print the character
  registerValue=(registerValue << 8) + b1;
}

Also this code is strange:

  Wire.beginTransmission(0x48);
  Wire.send(0x90); //write
  Wire.send(0x24); //reg
  Wire.send(0x90); //write
  Wire.endTransmission();     // stop transmitting

Are you trying to write 0x9024 to register 0x90 (which doesn't appear to exist)? That's what the code is doing.

I might help to tell us what register you're trying to read or write (and the value).

Oops, a correction. I didn't realize the registers are in LSB then MSB order. In that case the code should be (the previous would work for MSB then LSB order):

byte b1;
int registerValue=0;
byte byteCount=0
while(Wire.available()){
  b1 = Wire.receive(); // receive a byte
  Serial.println(b1, HEX);         // print the character
 
  registerValue+=(b1 << (byteCount * 8));
  byteCount++;
}

Thanks for your help and patience!

I can explain (really! :wink: why I tried the stuff I was trying - first, the addresses, from the Gamoto docs I couldn't tell what the slave address should be:

I was confused if with 'beginTransmission' it should be the R or W or just some base address (like 0)

Then I was trying to follow a read register I2C PIC example from the manual where is looks like there is first a write then the register., then another write, then a read, then a write... very confusing.

All I could think was the purpose was to tell the Gamoto to write a register to some read buffer before a read was possible.

So from there it's just been a muddle and a lot of Googling for Arduino I2C/TWI examples. etc. The examples have either been too simple or too technical (or not relevant).

So...
--beginTransmission() should use the Write address
--the register sent
--then the Read address
--then receive

I'll tinker with this today to see if I can make sense of it.

--Roy

So...
--beginTransmission() should use the Write address
--the register sent
--then the Read address
--then receive

I'll tinker with this today to see if I can make sense of it.

No, not exactly. Don't worry about read vs. write address. The Wire library only gets supplied the slave address which is the 7 bit address (0x48 in this case) in all situations. The library takes care of setting the R/W bit appropriately while communicating with the device.

So to read register you:

  • Wire.beginTransmission(0x48);
  • Position the address pointer at the register you want: Wire.send(??);
  • Wire.endTransmission();
  • Wire.requestFrom(0x48,2);
  • Loop while Wire.available() doing Wire.receive()

To write a register:

  • Wire.beginTransmission(0x48);
  • Position the address pointer at the register you want: Wire.send(??);
  • Send the LSB: Wire.send(LSB);
  • Send the MSB: Wire.send(MSB);
  • Wire.endTransmission();

Also be wary of any delays that the device might need. For example, some devices specify a minimum delay after a write before the next command. Also some devices need a minimum amout of time between the request and when data will be available. If you try to read the data too quickly after the Wire.requestFrom you might not receive any data because the device couldn'e respond yet (and the Wire.available() will be zero causing the while-loop to exit). These timings depend on the device and should be specified in the datasheet.

Thanks again for your help - still no joy here though. With the code below reading from register 0x22, the example in the docs indicate that I should be receiving 0x1234 (4660). I'm getting 500.

Don't know why it should be this hard... :wink:

--Roy

void loop() { 
  digitalWrite(ledPin, HIGH); 
 
  Wire.beginTransmission(0x48);
  Wire.send(0x22); //reg
  Wire.endTransmission();     // stop transmitting 

  Wire.requestFrom(0x48, 2);    // request 2 bytes from slave device #0 

  delay(100);

  byte b1;
  long registerValue=0;
  byte byteCount=0;
  while(Wire.available()){
    b1 = Wire.receive(); // receive a byte
    registerValue+=(b1 << (byteCount * 8));
    byteCount++;
  } 
  Serial.println(registerValue);         // print the character

  delay(200);
  digitalWrite(ledPin, LOW); 
  delay(200); 
}

Everything looks right except for the code I gave you to convert the two bytes into the integer value (which was totally wrong!). That'll teach me for writing code late a night!

Some (hopefully) working code is:

  byte registerData[2];
  byte byteCount=0;

  while(Wire.available() && byteCount < 2){
    registerData[byteCount] = Wire.receive(); // receive a byte
    byteCount++;
  }
  
  uint16_t registerValue = (registerData[1] * 256) + registerData[0];
  Serial.println(registerValue, DEC);