[SOLVED] Can't read I2C registers

Hello, I am having trouble reading registers of an I2C accelerometer (MMA8452Q).
It’s connected to default I2C pins on the cubecell board and I2C scan sketch discovers it. However, when trying to read specific registers, I always get the same values (which seems to be some garbage data)

for example, I tried to read register 0x0D (WHO_AM_I) which should be factory hard coded to 0x02
but I get 0.

Here is the sketch:
> #include <Wire.h>
>
> void setup() {
> Serial.begin(9600);
> delay(500);
> Wire.begin();
> Wire.beginTransmission(0x1D);
> Wire.write(0x0D)
> Wire.endTransmission(false);
> Wire.requestFrom((uint16_t)0x1D, (byte)1);
> while (Wire.available())
> {
> Serial.print(“I AM: 0x”);
> Serial.println(Wire.read(), HEX);
> }
> }
> void loop() {
> }

Additional data:
no matter what device address or register number I try to read, I get the same 8 bits. If sensor is disconnected, I get nothing(as expected)…
The sensor works perfectly well with arduino nano every(using level shifting).

Hi will need to know what board / capsule you are using. Are you using vext to supply the sensor power? And controlling it correctly.you can see this in the example script.
Simon

I am using the cubecell dev board (htcc-ab01).
Iv’e tried Vext, tried the 3.3 header, tried a different power supply - all to no avail…
when running this same code with arduino nano I get the expected values.
Iv’e also noticed that the current draw of the sensor is different with each board: with cubecell it’s 1uA - way below spec(~160uA).

The code for nano may can’t working in CubeCell directly. Because CubeCell and Arduino nano use a different MCU.

BTW. what library did you use?

just the wire library

Did you refer to this example?

https://github.com/HelTecAutomation/ASR650x-Arduino/blob/master/libraries/Basics/examples/i2c_scan/i2c_scan.ino

Yes, I have.
As stated in the O.P, this example scan sketch did discover the sensor.
also, I have based my code on that example

The example can discover the sensor, it means the I2C bus is running well.

I think you need double check the sensor initial part.

I know Im not owed anything by you, but I get the feeling you never read the code. It is a vary simple code I wrote in order to debug after the sensor library(by Sparkfun) failed to work with this board.

As far as I know, giving an address and then reading it’s content is the most basic thing you can do with I2C.
this code uses only the Wire.h library, that suppose to work with this board.
I can’t find any syntax error.

guess I’ll have to wait for my scope to arrive in order to get to the bottom of this…

do you have to initialize the sensor or wake up from sleep before you can read data?
i dont have this sensor and dont know it.

What is done in the library you reference to init the sensor?

i ahve read that this sensor needs to be activated to send data.
A little googling gave me this interesting github repository:

this is sparkfun’s library.
-It didn’t work with cubecell dev board.
-It masks the use of Wire library, but don’t do anything complicated
-the “sensor initialization” that it contains does what Im trying to do: reads the “WHO AM I” register to make sure this is the said sensor. that’s the first thing it does. the library fails there, my code fails there.

edit: this is a predecessor to the sparkfun library. it does not compile, even when adding I2C.h library(which is about 9 years outdated).

I’ve finally got an oscilloscope.
It appears that SCL and SDL V_H is only ~2.7V, even though the 3V3 pin(which I use to power the sensor) is measured to be 3.31V. when not transmitting, the lines are at 3.3, pulled using 10k resistors.

Also, CubeCell’s SCL frequency was about 83kHz.

first pic is arduino nano every, srcond is cubecell board (ab01)

Any ideas?
Im still at a lost with this:(

Please save me!

Did you try different values for your pullup resistors?
Most often I see 2K2 on 3V3 I2C diagrams and 4K7 on 5V I2C diagrams.

There are 10K soldered on the sensor board, but I have tried adding different values in parallel. haven’t got as low as 2k2 equivalent though. Ill give it a try!

Looking at the I2C trace from your scope it seems that the bus is performing ok (levels maybe lower for CubeCell because of different pullup resistors but the MMA8452Q is responding to the requests as it should).

When comparing the I2C trace pictures you can see the CubeCell sends a I2C STOP condition and then I2C START condition after address and register selection., whereas the Arduino Nano sends only a I2C REPEATED START. This is the reason why the MMA8452Q is not sending the data as expected.

See the excerpt from the MMA8452Q specification below:
“A low to high transition on the SDA line while the SCL line is high is defined as a stop condition (stop). A data transfer is always terminated by a stop. A master may also issue a repeated start during a data transfer. The MMA8452Q expects repeated starts to be used to randomly read from specific registers.

Greetings,
Dario

It’s seems you are right.
Just looked at the wire library implementation in cubecell’s git. and it always generates a stop condition by calling I2C_1_I2CMasterSendStop, never calls I2C_1_I2CMasterSendRestart.

Blockquote
i2c_err_t TwoWire::writeTransmission(uint16_t address, uint8_t *buff, uint16_t size, bool sendStop)
{
uint8_t Status=0;
uint16_t i;
if(_i2c_num == I2C_NUM_0)
{
flush();
I2C_I2CMasterClearStatus(); //清除I2C状态数据
Status =I2C_I2CMasterSendStart(address, I2C_I2C_WRITE_XFER_MODE,I2CTIMEOUT); //发送读数据命令

    if(Status == I2C_I2C_MSTR_NO_ERROR)
    {    	
    	for(i=0;i<size;i++)
    	{
    		I2C_I2CMasterWriteByte(buff[i],I2CTIMEOUT);
    	}
    }
    I2C_I2CMasterSendStop(I2CTIMEOUT); 
}
else
{
	 flush();
	 I2C_1_I2CMasterClearStatus();                                            //清除I2C状态数据
     Status =I2C_1_I2CMasterSendStart(address, I2C_1_I2C_WRITE_XFER_MODE,I2CTIMEOUT);      //发送读数据命令
     
    if(Status == I2C_1_I2C_MSTR_NO_ERROR)
    {    	
    	for(i=0;i<size;i++)
    	{
    		I2C_1_I2CMasterWriteByte(buff[i],I2CTIMEOUT);
    	}
    }

    I2C_1_I2CMasterSendStop(I2CTIMEOUT); 
}
if(Status==I2C_I2C_MSTR_NO_ERROR)
{
	last_error=I2C_ERROR_OK;
}
else
{
	last_error=I2C_ERROR_TIMEOUT;
}
return last_error;	  

}

https://github.com/HelTecAutomation/ASR650x-Arduino/blob/master/cores/asr650x/Wire/Wire.cpp

I’ll try to fix it locally, but I think a library update is in order.

Thanks,
Gal

Update:
Iv’e manged to get it to work by changing 2 methods in CubeCell’s Wire library:
in: TwoWire::readTransmission Iv’e changed
Status =I2C_I2CMasterSendStart and Status =I2C_1_I2CMasterSendStart
to:
Status =I2C_I2CMasterSendRestart and Status =I2C_1_I2CMasterSendRestart
respectively

and in: TwoWire::writeTransmission Iv’e added a condition check for sendStop before
I2C_I2CMasterSendStop and I2C_1_I2CMasterSendStop

Probably massed up other stuff though.

@heltec, please do a formal update to the library in order to accommodate restart condition
@Dario, Thank you very much for figuring it out!

and thanks to everyone else who tried to help