[SOLVED] Can't read I2C registers

@gharmelech You’re welcome! Maybe you can share a github link to the working Arduino Nano TwoWire library version you are using … I think this would help @Heltec in making the library better.

Iv’e used their library and just made the 4 changes mentioned in the previous message.

Sorry I meant maybe @Heltec can use the working Arduino Nano library you used in your other I2C trace to figure out how to solve this properly in the CubeCell library (as you mentioned you probably messed up other stuff).

Oh, it’s the standard arduino wire library. nothing special there😅

from comparing between the two libraries, it seems as though the cube cell one is missing a flag for repeated start and a handler for that flag in the TWI driver, not a small undertaking…
The two libraries take rather different approaches from what I’ve seen.
My trivial change just assumes repeated start always.

1 Like

Hi gharmelech
What condition you have added before 2C_I2CMasterSendStop and I2C_1_I2CMasterSendStop ?

Thanks

Hey dfarre!
I most say in advance that my changes won’t work for all cases. since my sensor always requires start - register write- restart - read - stop, I made the changes such that readTransmission always sends a restart.
here’s my amended code:

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);
	    	}
	    }
            if (sendStop){
			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);
	    	}
	    }

	    if (sendStop){
			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;	  
}

i2c_err_t TwoWire::readTransmission(uint16_t address, uint8_t *buff, uint16_t size, bool sendStop, uint32_t *readCount)
{
	uint8_t Status=0;
	uint16_t i;
	flush();
	if(_i2c_num == I2C_NUM_0)
	{
		I2C_I2CMasterClearStatus();                                            //ַו³‎I2C׳´ּ¬ֺ‎¾
		Status =I2C_I2CMasterSendRestart(address, I2C_I2C_READ_XFER_MODE,I2CTIMEOUT);      //·¢ֻֽ¶ֱֺ‎¾ֳֱמ

		if(Status == I2C_I2C_MSTR_NO_ERROR)
		{    	
			for(i=0;i<size;i++)
			{
				I2C_I2CMasterReadByte(I2C_I2C_ACK_DATA,&buff[i],I2CTIMEOUT);
				(* readCount)++;
			}
		}
			I2C_I2CMasterSendStop(I2CTIMEOUT); 
	}
	else
	{
		I2C_1_I2CMasterClearStatus();                                            //ַו³‎I2C׳´ּ¬ֺ‎¾
		Status =I2C_1_I2CMasterSendRestart(address, I2C_1_I2C_READ_XFER_MODE,I2CTIMEOUT);      //·¢ֻֽ¶ֱֺ‎¾ֳֱמ

		if(Status == I2C_1_I2C_MSTR_NO_ERROR)
		{    	
			for(i=0;i<size;i++)
			{
				I2C_1_I2CMasterReadByte(I2C_1_I2C_ACK_DATA,&buff[i],I2CTIMEOUT);
				(* readCount)++;
			}
		}
			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;	  
}

as per my understanding, the proper way of implementing restart condition is to add a member flag to the class that gets updated when a commend with stopbit=false is called. then any function that normally calls I2C_MasterSendStart would check that flag. if it is set it will call MasterSendRestart and then reset the flag, otherwise It will call MasterSendStart.

Iv’e also noticed that changing the library directly(in arduino’s appData folder) bricked the arduino IDE, so you’ll need the make a copy of that library(with a unique name) in the user library.

1 Like

Hey gharmelech,

First of all, thanks a lot for your researches, it helps me a lot because I have a AB01 and tried to use a MMA8451.

I change The Wire library with your advices, and moved to my user library with a different name. I used the Adafruit MMA8451’s library without any good resultats. It doesn’t work :(.

Did you change something else ?

Thank a lot !
Have a nice day