cancel
Showing results for 
Search instead for 
Did you mean: 

PSoC 4 MCU

auwi_3091191
New Contributor II

I'm having trouble using an I2C connection between my CYBLE-014008-00 and an AD5933 bio impedance chip. This is what I have for my master read and master write functions but I am not sure if they are correct. Any help with these functions would be greatly appreciated. 

bool writeByte(uint8 Reg, uint8 value) {
// Send byte to address
I2C_1_I2CMasterSendStart(AD5933_ADDR, I2C_1_I2C_WRITE_XFER_MODE, 1000);
I2C_1_I2CMasterWriteByte(Reg, 1000);
// Ensure transmission worked
if (I2C_1_I2CMasterStatus() != I2C_1_I2C_MSTAT_WR_CMPLT)
{
I2C_1_I2CMasterSendStop(1000);
return false;
}
I2C_1_I2CMasterWriteByte(value, 1000);
// Ensure transmission worked
if (I2C_1_I2CMasterStatus() != I2C_1_I2C_MSTAT_WR_CMPLT)
{
I2C_1_I2CMasterSendStop(1000);
return false;
}
I2C_1_I2CMasterSendStop(1000);
return true;
}

 

uint8 readByte(uint8 Reg, uint8 *value) {
// Request to read a byte using the address pointer register
I2C_1_I2CMasterSendStart(AD5933_ADDR, I2C_1_I2C_WRITE_XFER_MODE, 1000);
I2C_1_I2CMasterWriteByte(Reg, 1000);
// Ensure transmission worked
if (I2C_1_I2CMasterStatus() != I2C_1_I2C_MSTAT_WR_CMPLT)
{
I2C_1_I2CMasterSendStop(1000);
return false;
}
I2C_1_I2CMasterSendRestart(AD5933_ADDR,I2C_1_I2C_READ_XFER_MODE, 1000);
*value = I2C_1_I2CMasterReadByte(I2C_1_I2C_NAK_DATA, value, 1000);
I2C_1_I2CMasterSendStop(1000);
return true;
}

0 Likes
7 Replies
MotooTanaka
Esteemed Contributor

Hi,

I would also put a status check after SendStart() , as we often get an error here,

such as the slave device is busy , absent, or slave address is wrong, etc...

==========================

uint32 retStatus ;

retStatus = I2C_1_I2CMasterSendStart(AD5933_ADDR, I2C_1_I2C_WRITE_XFER_MODE, 1000);

if (retStatus != I2C_1_I2C_MSTR_NO_ERROR) {

I2C_1_I2CMasterSendStop(1000);
return false;

}
I2C_1_I2CMasterWriteByte(Reg, 1000);

==========================

Also I may want to add some delay after sending the register address before start reading the value

depending on the slave device.

 

moto

(Edited: Some English Spells)

0 Likes
auwi_3091191
New Contributor II

Thank you for your suggestion. The status check after SendStart() returns I2C_1_I2C_MSTR_NOT_READY. The documentation on this error suggests that either a master or slave operation is in progress but no other I2C functions are running before I try to communicate with the AD5933. Any thoughts on what may be causing this error? 

0 Likes
MotooTanaka
Esteemed Contributor

Hi,

When SendStart() fails, I would imagine the followings...

(1) I2C signals are not pulled up

Please make sure that both SCL and SDA are pulled up to VDD via 2K ~ 10K resistors.

(2) I2C component has not been initialized.

Please call function to initialize and start I2C_1 component.

In PSoC Creator, we do

I2C_1_Start()

(3) The sensor has not been powered up

(Probably this is not the case, though)

(4) The slave address is wrong

Please make sure that AD5933_ADDR is correct 7bit I2C address of you device's current configuration.
Note: Some device has selectable I2C address depending on the pin state at power up.

moto

0 Likes
auwi_3091191
New Contributor II

1) I currently am using 2.2K pull ups resistors but have tried as high as 5K resistors

2) I call I2C_1_Start(); in my initialization function where I start the other components being used

3) The senor is on the same power supply as the CYBLE chip

4) the AD5933 datasheet specifies and address of 0x0D which is the address I am using

AD 5933 Datasheet  I have included a link for the sensor's datasheet as I am still getting the same error on SendStart(). I will also include my initialization function at the end of this reply.

void Initialize(void)
{
    Opamp_1_Start();
    Opamp_2_Start();
    Opamp_1_Sleep();
    Opamp_2_Sleep();

    ADC_Start();
    ADC_Sleep();

    RTC_Start();
    RTC_SetPeriod(1, 256);

    Ctl.state = OPSTATE_SLEEP; // load variables before initializing the NEMO
    Ctl.samplesPerEntry = EEpromPointer[EE_IDX_samplesPerEntry];
    Ctl.wakeupThreshold = EEpromPointer[EE_IDX_wakeupThreshold]; // inactivity wakeup threshold (0 to 63.)
    Ctl.buzzer = EEpromPointer[EE_IDX_buzzer];

    SPI_Start();

    SPI_Sleep();

    I2C_1_Start();

    EventWriteIndex = FindFirstEmptyEvent();// now initialize event write index
    Ctl.events = GetEventCount(EventWriteIndex);

    CyDelay(200);
    CyGlobalIntEnable;

    CyBle_Start(GeneralEventHandler); // BLE on

    CySysWdtSetInterruptCallback(CY_SYS_WDT_COUNTER2, WatchdogTimerISR);
    CySysWdtEnableCounterIsr(CY_SYS_WDT_COUNTER2);

    #ifdef UART_DEBUG
        UART_Start();
    #endif
}

 

0 Likes
MotooTanaka
Esteemed Contributor

Hi,

I think that you have been doing everything OK.

There were a couple of minor points, I'd like to mention.

(they may not fix the problem though)

(1) In the datasheet you provided the URL,

pull-up resistor for SDA and SCL are specified as 10 kOhm in the Table 4.

001-DS-Table.JPG

(2) As I2C requires interrupt to operate,

I would call

I2C_1_Start() ;

after

CyGlobalIntEnable;

moto

Edited: On 14-Jan-2021 Table 4 picture was added.

 

0 Likes
auwi_3091191
New Contributor II

Thank you for your reply. I implemented the changes you suggested and now MasterSendStart() is returning an error of  I2C_1_I2C_MSTR_ERR_LB_NAK.

0 Likes
MotooTanaka
Esteemed Contributor

Hi,

The error seems to be "Last Byte Naked".

In my experience, this can happen if the slave device at the specified address is absent.

I would check

  1. If the connections of SDA, SCL, VDD, GND are correct.
    I have made this mistake not once.
  2. If the sensor is not broken.
    I wonder how we can test this, may be try another device?
  3. Monitor the signals of SDA and SCL using an oscilloscope.

moto

 

 

 

0 Likes