Testing I2C on a custom PSoC PCB

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
lock attach
Attachments are accessible only for community members.
jcsb1994
Level 4
Level 4
First solution authored 50 replies posted 50 sign-ins

Hi all,
I am working on a custom PSoC board and I am having trouble with I2C. I am pretty sure it is a software issue, as I have tested my pins with digital output pin components sending HIGH signals every 500ms and everythiing works fine.. The problem occurs when I try to use I2C on these pins. I do not read any voltage on the oscilloscope in that case.

I have tried a very simple project where I add a SCB block as I2C master, and I send it through the I2C on pins 0.0 and 0.1
I am using PSoC4100S (precisely chip CY8C4125AZI-S433) and I believe I just dont know how to use the API for the SCB blocks.

I am attaching my project file.

I think the problem might be that I am not starting the I2C correctly, or sending data. Here is what I am trying to do:

pastedImage_1.png

pastedImage_0.png

Thanks a lot for your help!

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

The first problem was my bad.

I included i2c_api_utils.h and modified i2c_api_utils.c in the previous project,

but somehow those files were missing from the archive.

Note: For this project I changed the following line in i2c_api_utils.c

> extern int i2c_dleay ;

< int i2c_delay = 50 ; /* delay in Us */

So I moved them from sources/i2c folder to project folder and made today's archive.

Hopefully it will work without modification (for i2c_delay)

For the second question, in the i2c_api_utils there already is i2c_readRegs() and i2c_writeRegs(),

which will take care of receiving/sending array of data.

I modified the sample as follows,

(And to make sure it is working, I changed the delta for r,g,b, from 10 to 20

and it is working on my desk with CY8CKIT-062-BLE)

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

    for(;;)

    {

    

//        i2c_writeReg(0, r) ;

//        i2c_writeReg(1, g) ;

//        i2c_writeReg(2, b) ;

        data[0] = r ;

        data[1] = g ;

        data[2] = b ;

     

        i2c_writeRegs(0, data, 3) ;

     

        r += 0x20 ;

        if (r >= 0x100) {

            r = 0 ;

            g += 0x20 ;

            if (g >= 0x100) {

                g = 0 ;

                b += 0x20 ;

                if (b >= 0x100) {

                    b = 0 ;

                }

            }

        }

     

        ledPin_Write(~ledPin_Read()) ;

        CyDelay(100);

    }

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

moto

P.S.

One more thing, as you tried, depending on the slave device, the delay in i2c_readReg() may need to be longer.

Although I use CyDelayUs(i2c_delay), which is delay of 50 us, you may need longer delay for a particular slave.

So using CyDelay(1), which is 1000us (1ms)  could be safer, make the application slower though.

IMG_4486.JPG

View solution in original post

7 Replies
lock attach
Attachments are accessible only for community members.
VenkataD_41
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi,

Please find the attached code example for SCB based code example. Check the pin assignments and test this example in your kit. You can find the same code example in PSoC Creator also.

Thanks

Ganesh

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

Maybe I missed something but usually I2C pins are open drain (driving Low).

So we need pull-up resistors for both SCL and SDA.

How about adding resistors of 2K ~10K between SCL and VDD and SDA and VDD?

moto

lock attach
Attachments are accessible only for community members.

I hadn't soldered the pullups on my custom PCB, but I just did this morning and I can see the output I2C pins work. I mean I see a clock signal and a SDA signal on the scope when when running this code

pastedImage_4.png

But now, I am trying to get the sent data on another psoc slave device. This slave is a PSoC6 dev kit (062-BLE) and I hooked up the I2C pins from my custom PCB to the dev kit. I need help in designing the software, because I see my buffer remains empty!

GaneshD_41​ I tried using the example projects but I cannot read my custom master project with them! I need to modify my slave code so it can populate the buffer and fprint it... I am sure it is very simple but I cannot find the error in my slave code!

pastedImage_5.png

I am attaching the 2 projects just in case. I just dont see why my buffer isnt filling up since I have set it and started the i2c in the slave main...

Thanks!

0 Likes
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

For me the good news was that your master program on PSoC 4 seemed to be working OK,

but the bad news was that I can not manage the PSoC 6 part working.

So I just borrowed the working CE of PSoC 6,  CE220541.

And for the PSoC 4 part, I cheated by using i2c utils from my sample code MCU Tester (TSoC version)

Re: MCU Tester, a Swiss Army Knife for PSoC (TSoC version)

So I replaced the EZI2C in the schematic to I2C

and since CY8C4146LQI-S433 was the closest device I have an evaluation board,

I changed the device to CY8C4146LQI-S433.

I tried to keep the pins, so hopefully if you change the device to CY8C4125AZI-S422, it will also work on your board.

001-master-schematic.JPG

pins

Note: I tried not to change the pins, but please double check them to match with your board.

002-pins.JPG

main.c

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

#include <project.h>

#include "i2c_api_utils.h"

/* LED constants for turning the RGB LED on and off */

#define LED_ON              (0xFFu)

#define LED_OFF             (0x00u)

void init_hardware(void)

{

    CyGlobalIntEnable;

   

    I2C_Start() ;

    i2c_set_slave_address(0x08) ;

}

int main()

{

    int i = 0 ;

    int r = 0 ;

    int g = 0 ;

    int b = 0 ;

   

    init_hardware() ;

   

    ledPin_Write(1);

    ledPin2_Write(1);

    CyDelay(500);

    ledPin_Write(0);

    ledPin2_Write(0);

   

    for(;;)

    {

              

        i2c_writeReg(0, r) ;

        i2c_writeReg(1, g) ;

        i2c_writeReg(2, b) ;

       

        r += 0x10 ;

        if (r >= 0x100) {

            r = 0 ;

            g += 0x10 ;

            if (g >= 0x100) {

                g = 0 ;

                b += 0x10 ;

                if (b >= 0x100) {

                    b = 0 ;

                }

            }

        }

       

        ledPin_Write(~ledPin_Read()) ;

        CyDelay(100);

    }

}

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

moto

HiOm_1802421
Level 5
Level 5
Distributor - Marubun (Japan)
50 replies posted 50 questions asked 25 replies posted

Hi,

The write access code of your I2C master is 1-byte transfer.

However, write access to EZ-I2C slave requires at least 2-bytes (subaddress and data).

Your buffer remains empty because you are only writing the subaddress.

Motoo's slave sample project is not EZ-I2C, so it works fine with 1-byte write access.

See page 17 of the EZ-I2C component datasheet for more detail.

https://www.cypress.com/documentation/component-datasheets/ezi2c-slave

Thanks

Omoi

Thank you so much,  I managed to make it work with the projects you shared. I really like your i2c utils, it makes it easy to understand. There was an error when building at first, there is an external reference to a i2c_delay variable in your library, and I needed to replace CyDelay(i2c_delay); with CyDelay(1);

pastedImage_0.png

1. I was wondering why a delay is necessary after all, it seems to work with a delay of 1ms but what was the intended value of i2c_delay? and could I just remove the delay while still having a robust communication?

2. I have problems trying to send multiple byte variables with your library. Ultimately I want to send capsense data to the psoc 6 through I2C. And capsense sensor values are stored in uint32_t. Do you have an example of how you would send this with your library? I could also just parse the uint32 into an array of uint8 and send them individually with  your writeReg function like sopastedImage_1.png

but it doesnt seem very efficient, especially if I have to send uint32 variables for each of my 49 sensors in my 7x7 capsense trackpad.. I was thinking writeRegs might be the way you would do it?

Thanks again!!

HiOm_1802421​ I replaced the ezi2c for an i2c scb as motoo did. Thanks for this clarification.

0 Likes
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

The first problem was my bad.

I included i2c_api_utils.h and modified i2c_api_utils.c in the previous project,

but somehow those files were missing from the archive.

Note: For this project I changed the following line in i2c_api_utils.c

> extern int i2c_dleay ;

< int i2c_delay = 50 ; /* delay in Us */

So I moved them from sources/i2c folder to project folder and made today's archive.

Hopefully it will work without modification (for i2c_delay)

For the second question, in the i2c_api_utils there already is i2c_readRegs() and i2c_writeRegs(),

which will take care of receiving/sending array of data.

I modified the sample as follows,

(And to make sure it is working, I changed the delta for r,g,b, from 10 to 20

and it is working on my desk with CY8CKIT-062-BLE)

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

    for(;;)

    {

    

//        i2c_writeReg(0, r) ;

//        i2c_writeReg(1, g) ;

//        i2c_writeReg(2, b) ;

        data[0] = r ;

        data[1] = g ;

        data[2] = b ;

     

        i2c_writeRegs(0, data, 3) ;

     

        r += 0x20 ;

        if (r >= 0x100) {

            r = 0 ;

            g += 0x20 ;

            if (g >= 0x100) {

                g = 0 ;

                b += 0x20 ;

                if (b >= 0x100) {

                    b = 0 ;

                }

            }

        }

     

        ledPin_Write(~ledPin_Read()) ;

        CyDelay(100);

    }

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

moto

P.S.

One more thing, as you tried, depending on the slave device, the delay in i2c_readReg() may need to be longer.

Although I use CyDelayUs(i2c_delay), which is delay of 50 us, you may need longer delay for a particular slave.

So using CyDelay(1), which is 1000us (1ms)  could be safer, make the application slower though.

IMG_4486.JPG