7 Replies Latest reply on Sep 17, 2020 6:14 PM by MoTa_728816

    Testing I2C on a custom PSoC PCB

    JeSi_4326976

      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:

       

      Thanks a lot for your help!

        • 1. Re: Testing I2C on a custom PSoC PCB
          GaneshD_41

          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

          • 2. Re: Testing I2C on a custom PSoC PCB
            MoTa_728816

            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

            • 3. Re: Testing I2C on a custom PSoC PCB
              JeSi_4326976

              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

               

               

              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!

               

              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!

              • 4. Re: Testing I2C on a custom PSoC PCB
                MoTa_728816

                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

                1 of 1 people found this helpful
                • 5. Re: Testing I2C on a custom PSoC PCB
                  HiOm_1802421

                  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

                  2 of 2 people found this helpful
                  • 6. Re: Testing I2C on a custom PSoC PCB
                    JeSi_4326976

                    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);

                    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 so

                     

                    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.

                    • 7. Re: Testing I2C on a custom PSoC PCB
                      MoTa_728816

                      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