1

I need to read the registers of a message gotten from onReceive(). I read here that

There's nothing "magic" about the register pointer: it's simply the first data byte in the packet. So just write your I2C slave code so it examines the first received byte and treats it as an "opcode" for deciding how to interpret the rest of the packet.

So I thought that since hosts set registers by calling write() twice, I could just make my onReceive() handler function twice, like this

byte CURRENT_REGISTER = 0x00;

void onMessage(int numBytes){
  if(CURRENT_REGISTER == 0x00 && numBytes == 1){
    CURRENT_REGISTER = Wire.read();
    return;
  }

  char msg[numBytes];
  for(int i = 0; i < numBytes; i++){
    msg[i] = Wire.read();
  }
  
  //logic function goes here

  CURRENT_REGISTER = 0x00;
}

But then i noticed here that

This first byte written here 'r' moves the register pointer to the register with address 'r'. You can think of the pointer as a read/write head.
Now that the pointer is 'pointing' at the specific register you wanted, this command will replace the byte stored in that register with the value 'v'.

which made me think after endTransmission(), it only sent one message, which would ruin this idea. Is this the case, and if so how can I obtain the registers as a slave?

8
  • You reallly should provide more context. What are you trying to achieve? About was registers are you talking?
    – chrisl
    Feb 5 at 21:10
  • @chrisl i was trying to provide a minimal example, since the context is alot. But if you want to know, im trying to replace a wiimotion+ IMU with a BNO055, and i need to communicate to the wimmote over an I2C connection in a specific format to be understood. There are specific registers a wiimote expects that when it writes to it receives a specific response back, and im trying to emulate these responses with an arduino nano. I need to know the register in order to know how to respond. If you need more context, look at this link wiibrew.org/wiki/Wiimote/Extension_Controllers#Wii_Motion_Plus Feb 5 at 21:37
  • The forum threats, that you linked to, are totally unrelated to the wiimote. The only common thing is, that - like many other devices too - the wiimote seems to read its peripherals by first sending a "register address" in the peripheral device (the address of the sensor internal memory), that it then wants to read or write. From what you linked in the comments, for the wiimote, that "register address" doesn't really correspond to a register. It is more like a command, that is send by the master.
    – chrisl
    Feb 5 at 23:28
  • So you need to first actually understand the communication protocol, that the wiimote uses. Then you can start implementing it. From your link it seems, that there is first an initialization process. Also something about possible encryption. The site isn't easy to understand.
    – chrisl
    Feb 5 at 23:33
  • @chrisl okay so, the wiimote communicates over i2c. these registers in fact do matter, and wiimotion plus is unencrypted, but even if it was, im initializing it in a way which encryption does not matter. Not only is this incorrect, but this has even been done before the opposite way around, with the arduino nano as the master and wiimotion+ as the slave. Feb 5 at 23:48
0

I just realized, what your actual question might be, so I'm prepending this to my answer:

With I2C and the typical register communication protocol, you have 3 communication patters:

  • Master wants to write:
    • Master does transmission with first byte being the address of the register and following bytes being the data, that should be written to the addressed register (and following registers)
  • Master wants to read:
    • Master does a 1 byte transmission with the address of the register, that is wants to read
    • Master starts a request for 1 or more bytes and the slave will send the previously requested register (and following registers, until no more bytes are available or requested)
  • Some devices have sequential reads. For these devices the register address is not reset, when an operation is done. Thus the master could do more requests and read more data from the registers. Here the current register address is incremented on each read.

This means, that a master write cycle has only 1 transmission (only 1 endTransmission() in the master code), since every first byte in a master send transmission is handled as a register address. Your code snippet does not allow that. To solve that, just remove the check of numBytes and the return statement.


As mentioned in the comments, your question is really unclear. It seems you are asking things, that doesn't really make sense in the context of general I2C communication. So I will go over the basics and then point you in a good direction to solve your problem interfacing the Wiimote as peripheral.

The I2C protocol: This is the general communication protocol, that the Wiimote uses for its peripherals. It uses 2 lines and a master-slave structure. That means, that any communication is controlled by the master (the Wiimote in this case) and the slave (the peripheral, like a Motion+, a Nunchuk or your Arduino) cannot do anything by itself. The I2C protocol has markers for the start and end of a message and can address each slave on the bus with its specific address (which is send before the data). The protocol does NOT include any rules about the content of each message. So when writing code with the Wire library (the Arduinos library for interfacing the I2C hardware), you only get a buffer full of data bytes. It is up to you to interpret these bytes as needed for your application.

Data structure protocol: This protocol is imposed onto the data, that is end via I2C, so this is a higher level of abstraction and does not really have much to do with the I2C interface (you could use this data structure protocol with any binary communication interface, that has the concept of separated data packages). The data structure protocol defines the logic of the communication.

Here the registers come in. I2C is often used to interface simple sensor chips. These chips work by reading and writing to their internal memory. So the I2C interface exposes this internal memory to the master, who can now configure the sensor by writing data to the internal memory of the sensor, or read data from it.

An example: Lets imagine a simple distance sensor. It has 2 bytes/registers of internal memory. The first byte/register is for configuration of the sensor; the second byte/register represents the measured distance. The common communication protocol for such a chip can be:

Master sends the address of the register, that it wants to access
if Master wants to write to the register
    Master sends bytes to the slave
    Slave saves bytes into previously chosen register (and following registers)
if masters wants to read form the register
    Master requests X bytes from the slave
    Slave sends X bytes with the content of the previously chosen register (and following registers)

The I2C master now wants to configure the sensor (for example setting the measurement frequency), thus writing a corresponding byte to the first byte/register. It will first send the address of the configuration register to the slave, which is 0 (first byte/register). Then it will send another byte, which is the new value of the configuration register.

Then our I2C master wants to read the distance measurement the sensor. For this it first sends the address of the register, that holds the distance measurement (1 aka second byte/register). Then it will request 1 byte from the slave. The slave will then send the content of the previously chosen register (register 1 aka distance measurement register).

So for the slave, the first byte of a Master send transmission is to be handled as a register address. More complex slave classes might have a 16bit (2byte) register address or even more.


Now to your problem mimicking a Wii Motion+. The description on the site, that you linked to is rather difficult. Unfortunately I cannot help much with that. But you can try to use an already existing library, that mimics a Wiimote peripheral: Arduino-Wiimote

I cannot guarantee, that is will work, but it is definitely a good start. If you don't want to use a library, but implement this yourself, you can still learn from how the library does it.

With more searching (for term combinations like "github wiimote arduino") you might find more libraries for this. I have only invested a limited amount of time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.