1 2 Previous Next 19 Replies Latest reply on Nov 9, 2016 12:48 AM by pmartinez_1655886

    Psoc and I2C with PCA9685

    pmartinez_1655886

      I am trying to port the library provided by Adafruit (https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library)  to use it in my project. 

         

      This library is intended to be used with PCA9685 chip, which provides 16 pwm outputs by the use of the I2C protocol. 

         

      I already have a board from adafruit and tested with an arduino and their library, it works fine. I tried to do the same with psoc but I guess I don't ported it well because it is not working (nothing happens when I try to make a servo to work.

         

      I attach you the project so you can check my code and give me some ideas. I am using the first address (6 different modules can be added. The first one is 0x60, it is wrong in my project but result is the same fixing it).

        • 1. Re: Psoc and I2C with PCA9685
          user_1377889

          At first: set your I2C component to Byte mode or your target gets bad data.

             

          You are omitting the MasterSendStop() API.

             

          Byte I2C interface is quite simple: After setting up the component (no Enable() needed) and starting it you use

             

              I2C_MasterSendStart(DeviceAddress,I2C_WRITE_XFER_MODE);    // Initialize a transaction for writing
              I2C_MasterWriteByte(Register);                // Indicate which register you want to write to
              I2C_MasterWriteByte(Value);                // Write to register
              I2C_MasterSendStop();                    // End of transaction

             

          When you want to read from a device you use (example for reading two bytes

             

              I2C_MasterSendStart(DeviceAddress,I2C_WRITE_XFER_MODE);    // Initialize a transaction for writing
              I2C_MasterWrite(Register);                // Indicate which register you want to write to
              I2C_MasterSendRestart(DeviceAddress,I2C_READ_XFER_MODE);
              I2C_MasterReadByte(I2C_ACK_DATA);            // Read from register
              I2C_MasterReadByte(I2C_NAK_DATA);            // Read from register, last byte is NAKed
              I2C_MasterSendStop();                    // End of transaction

             

          Not too difficult. Keep in mind that most of the APIs (except those for reading a byte) return a status byte which, when non-zero indicate an error condition, do not continue when an error occured. Use that status information at least while testing your connection.

             

           

             

          Bob

          • 2. Re: Psoc and I2C with PCA9685
            pmartinez_1655886

            Thank you, Bob. I will try and post what I find

            • 3. Re: Psoc and I2C with PCA9685
              pmartinez_1655886

              I have made some changes, define the words you use for write/read operations and tested a bit but it seems to hang as soon as the program go into:

                 

              PWM_begin()>PWM_reset()>PWM_write8()>MOTOR_I2CMasterWriteByte(d)(HERE PROGRAM STOPS):

                 

               

                 

              void PWM_write8(uint8_t reg, uint8_t d) {
                MOTOR_I2CMasterSendStart(_addr, I2C_WRITE_XFER_MODE);
                MOTOR_I2CMasterWriteByte(reg);
                MOTOR_I2CMasterWriteByte(d);   <------ HERE STOPS
                MOTOR_I2CMasterSendStop();
              }

                 

               

                 

              I don't know if I should activate something else. I also changed to byte mode I2C block.

              • 4. Re: Psoc and I2C with PCA9685
                user_1377889

                Change your PWM_write8() to

                   

                uint8_t PWM_write8(uint8_t reg, uint8_t d)
                {uint8_t Result;
                    
                    if((Result = MOTOR_I2CMasterSendStart(_addr, I2C_WRITE_XFER_MODE))) return Result;
                    if((Result = MOTOR_I2CMasterWriteByte(reg))) return Result;
                    if((Result = MOTOR_I2CMasterWriteByte(d))) return Result;
                    if((Result = MOTOR_I2CMasterSendStop())) return Result;
                    return Result;
                }

                   


                and check the returned result for != 0. There are descriptions in the associated .h file for error reasons.

                   

                 

                   

                Bob

                • 5. Re: Psoc and I2C with PCA9685
                  pmartinez_1655886

                  Ok, I tested. It returns at first if. I2CMasterSendStart with 0x02 response code. If I remove Pullup resistors, I get a 0x04 code. I guess: MOTOR_I2C_MSTR_ERR_LB_NAK and MOTOR_I2C_MSTAT_ERR_ARB_LOST

                  • 6. Re: Psoc and I2C with PCA9685
                    user_1377889

                    Removing of the pullups will not work at all. Try reducing I2C speed to 100kbps. use 2.2k pullups.

                       

                    First start address NAKed could mean wrong address. Do you set _addr??? Do you call  PWM_ServoDriver() ???

                       

                     

                       

                    Bob

                    • 7. Re: Psoc and I2C with PCA9685
                      pmartinez_1655886

                      Yes, I call PWM_ServoDriver. First thing in my code. I could replicate the 0x02 error. I have just got 0x04 since I post my previous message. 

                         

                      I modified data rate to 100 and set slew rate to "Slow". I found those parameters in the datasheet. But this IC also supports 400 and fast rate. 

                         

                       

                         

                      I double checked datasheet to see if the address was ok. I think it is. I have all address entries to 0, so it should be 0x40.

                      • 8. Re: Psoc and I2C with PCA9685
                        user_1377889

                        I call PWM_ServoDriver. First thing in my code.   Quite sure? main() reads

                           

                            CyGlobalIntEnable; /* Enable global interrupts. */
                            PWM_begin();
                            PWM_ServoDriver();

                           

                        And in PWM_begin() you get the device out of sleep mode but using a wrong I2C address.

                           

                         

                           

                        Bob

                        • 9. Re: Psoc and I2C with PCA9685
                          pmartinez_1655886

                          Yes, I fixed it. I saw it also when you pointed about the address. I have been reworking the library a bit basing on libraries for python I found on the internet and now I get a first error of 0x02 (NACK?) and then 0x04 always.

                             

                          I don't have time today to check something else. Tomorrow I will try to test something else and I will post my updates. I willt ry also setting up another pioneer psoc as slave with address 0x40 and see what happens. 

                          • 10. Re: Psoc and I2C with PCA9685
                            user_1377889

                            Are you using a -042 BLE Pioneer board?

                               

                            Use P0_4 and P0_5 for I2C and provide your own 2k2 pullup resistors. The ohter pins are connected to FRam with an address 0x42 which will collide with your chip or with an internal UART-USB bridge which will destroy your sda-line data.

                               

                             

                               

                            Bob

                            • 11. Re: Psoc and I2C with PCA9685
                              pmartinez_1655886

                              Thank you bob. I got it working!. The board I was using (adafruit original) has 2 pullup resistors (10K) and that seems to be a bit too much for pionneer psoc board. I replaced them by 2.2k as you suggested and it started to work. As I said I tested with 4.7k jumping the 10k resistors but this value seems to be still too high.

                                 

                              I have to include the library in my project so I will change the code a bit to make it more readable (variable and function names) and also including some comments. After that I will update this topic with a copy of the project with a small example of use. Maybe it is useful for anyone who wants to test this IC.

                              • 12. Re: Psoc and I2C with PCA9685
                                user_1377889

                                Congratulations!

                                   

                                 

                                   

                                Bob

                                • 13. Re: Psoc and I2C with PCA9685
                                  pmartinez_1655886

                                  Sorry for rescuing such an old post. I am still working on this, My company has had other priorities all this time. I am trying to finish it right now. 

                                     

                                   

                                     

                                  We already have our final pcb board designed and prototyped. I am able to communicate to the first PCA9685 device (2 I2C slaves) with 0x40 address. 

                                     

                                  It works while I don't try to communicate to the second one. As soon as I try this communication, neither the first one nor the second one works.

                                     

                                   

                                     

                                  We are using the same core as my pioneer kit. CY8C4247LQI-BL483 56-QFN and pins we use from it are SCL P0[5] 25, and SDA P0[4] 24. 2.2K resistors for pull up.

                                     

                                   

                                     

                                  Using 0x41 for the second device in I2C (The address we configured by its input pins) I get a fail in writeByte function. 0x02 MOTOR_I2C_MSTR_ERR_LB_NACK. If I set, for example, 0x42-0x45, I get a fail in SendStart function. also a 0x02. Can you give me any clue with this information? Or what should I check? 

                                     

                                  Is there something related to close connection to one slave device before talking to another in I2C?

                                     

                                   

                                     

                                  EDIT: I tried removing the call to the first I2C device. So the only one initialized and use is the seond one. I also get the 0x02 error in writeByte function.

                                  • 14. Re: Psoc and I2C with PCA9685
                                    user_1377889

                                    Is the call to MasterSendStart() returning an error? Or the (required to close a connection) the MasterSendStop?

                                       

                                    What is the length of the signal cable to the second PCA9685?

                                       

                                     

                                       

                                    Bob

                                    1 2 Previous Next