|
|
View previous topic :: View next topic |
Author |
Message |
ddevices
Joined: 15 Jun 2020 Posts: 13
|
I2C problem with sensor PAJ7620U2 [Solved] |
Posted: Mon Jun 15, 2020 1:45 pm |
|
|
I have an I2C problem and any help would be very much appreciated. My chip is the PIC18LF2550 and compiler is PCWHD V5.093c. The I2C chip that I’m attempting to connect to is the PAJ7620U2 on DFRobot SEN0315 Gesture Sensor board. Correct pull ups are on I2C lines. Most of the code to communicate to the sensor is from DFRobot Wiki page and github (https://github.com/DFRobot/DFRobot_PAJ7620U2). I have this sensor working with Arduino, I know the sensor works and code is fundamentally correct. I am transferring it to the PIC.
I have an oscilloscope and can see 99% of the code is working, just one register is failing and locking up board. To configure the sensor you have to write 219 registers with parameters, one register locks up. Register 0x72, the Enable/Disable (0=Disable, 1=Enable). Below are code snippets that show the core of the problem. Configuration of chip:
Code: | #define __USB_PIC_PERIF__ 1
#include <18LF2550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOMCLR
#use delay(clock=48000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
#use i2c(master, sda=PIN_B0, scl=PIN_B1) //have tried FORCE_HW OR SW, no difference
|
Configuration of PAJ is below, rewritten so it does not lock up:
Code: |
int8 paj7620Init(void) {
unsigned char i = 0;
int8 ack;
unsigned char data[2];
ack = paj7620ReadReg(0x00,1,data);
if(ack==1)
printf("Wake up Failure %d\r",ack);
else
printf("Wake Up Good! %d\r",ack);
delay_us(400);
ack = paj7620ReadReg(0x00,1,data);
if(ack==1)
printf("Wake up Failure %d\r",ack);
else
printf("Wake Up Good! %d\r",ack);
paj7620SelectBank(0);
paj7620SelectBank(0);
for (i = 0; i < 219; i++) { //INIT_REG_ARRAY_SIZE 219
data[0] = initRegisterArray[i][0];
data[1] = initRegisterArray[i][1];
//printf("%u %x %x\r",i,data[0],data[1]); //shows correct data
if(i != 210) ack = i2c_transfer_out(PAJ7620_write,data,2); //210 fails!
if(ack==1) printf("Init Failure %u\r",i);
}
paj7620SelectBank(1); //gesture flage reg in Bank1
// paj7620WriteReg(0x65, 0xB7); // far mode 120 fps
// paj7620WriteReg(0x65, 0x12); // near mode 240 fps
data[0]=0x65;
data[1]=0xB7;
ack = i2c_transfer_out(PAJ7620_write,data,2);
if(ack==1) printf("Set Mode Failure \r");
paj7620SelectBank(0); //gesture flag reg in Bank0
printf("Paj7620 initialize register finished.\r");
return 0;
}
|
Below is main, heavily rewritten for diagnostic purposes:
Code: | void main() {
int8 i, count;
unsigned char data[2];
setup_adc_ports ( NO_ANALOGS ) ;
setup_adc( ADC_OFF ) ;
set_tris_a( 0b11111111 ) ;
#use fast_io( A )
set_tris_b( 0b11111111 ) ;
#use fast_io( B )
set_tris_c( 0b10111110 ) ;
for(i=0; i<10; i++)
{
LED1_OFF() ;
delay_ms(100);
LED1_ON();
delay_ms(100);
}
SETUP_WDT( WDT_OFF ) ;
SETUP_TIMER_0( T0_OFF ) ;
SETUP_TIMER_1( T1_DISABLED ) ;
SETUP_TIMER_2( T2_DISABLED , 255 , 16 ) ;
SETUP_TIMER_3( T3_DISABLED ) ;
paj7620Init();
paj7620SelectBank(1); //0x72 is in bank 1
count = 200;
while ( TRUE ) { // main infinite while loop
MAINLOOP_WAIT() ; //10ms
if(count>0) count--;
if(count==1)
{
output_toggle(LED1);
i2c_start();
i2c_write(PAJ7620_write);
i2c_write(0x72);
i2c_write(0x01); //0x00 no lockup - 0x01 locks up (LED stops)
i2c_stop();
count=200; //2 secs
}
}//end main infinite while loop |
Normally writing to 0x72 is during the initialize of the chip but it would fail when reaching that register so I removed that one parameter and program would not lock up, verifying that was issue. The SelectBank sub provides confirmation to serial debug port, it is working with ACK received. Below shows the register configuration and is same as working Arduino code. This is very puzzling, any help appreciated.
Code: | ROM unsigned char initRegisterArray[219][2] = { // Initial Gesture
{0xEF, 0x00},
{0x32, 0x29},
{0x33, 0x01},
{0x34, 0x00},
{0x35, 0x01},
{0x36, 0x00},
{0x37, 0x07},
{0x38, 0x17},
{0x39, 0x06},
{0x3A, 0x12},
{0x3F, 0x00},
{0x40, 0x02},
{0x41, 0xFF},
{0x42, 0x01},
{0x46, 0x2D},
{0x47, 0x0F},
{0x48, 0x3C},
{0x49, 0x00},
{0x4A, 0x1E},
{0x4B, 0x00},
{0x4C, 0x20},
{0x4D, 0x00},
{0x4E, 0x1A},
{0x4F, 0x14},
{0x50, 0x00},
{0x51, 0x10},
{0x52, 0x00},
{0x5C, 0x02},
{0x5D, 0x00},
{0x5E, 0x10},
{0x5F, 0x3F},
{0x60, 0x27},
{0x61, 0x28},
{0x62, 0x00},
{0x63, 0x03},
{0x64, 0xF7},
{0x65, 0x03},
{0x66, 0xD9},
{0x67, 0x03},
{0x68, 0x01},
{0x69, 0xC8},
{0x6A, 0x40},
{0x6D, 0x04},
{0x6E, 0x00},
{0x6F, 0x00},
{0x70, 0x80},
{0x71, 0x00},
{0x72, 0x00},
{0x73, 0x00},
{0x74, 0xF0},
{0x75, 0x00},
{0x80, 0x42},
{0x81, 0x44},
{0x82, 0x04},
{0x83, 0x20},
{0x84, 0x20},
{0x85, 0x00},
{0x86, 0x10},
{0x87, 0x00},
{0x88, 0x05},
{0x89, 0x18},
{0x8A, 0x10},
{0x8B, 0x01},
{0x8C, 0x37},
{0x8D, 0x00},
{0x8E, 0xF0},
{0x8F, 0x81},
{0x90, 0x06},
{0x91, 0x06},
{0x92, 0x1E},
{0x93, 0x0D},
{0x94, 0x0A},
{0x95, 0x0A},
{0x96, 0x0C},
{0x97, 0x05},
{0x98, 0x0A},
{0x99, 0x41},
{0x9A, 0x14},
{0x9B, 0x0A},
{0x9C, 0x3F},
{0x9D, 0x33},
{0x9E, 0xAE},
{0x9F, 0xF9},
{0xA0, 0x48},
{0xA1, 0x13},
{0xA2, 0x10},
{0xA3, 0x08},
{0xA4, 0x30},
{0xA5, 0x19},
{0xA6, 0x10},
{0xA7, 0x08},
{0xA8, 0x24},
{0xA9, 0x04},
{0xAA, 0x1E},
{0xAB, 0x1E},
{0xCC, 0x19},
{0xCD, 0x0B},
{0xCE, 0x13},
{0xCF, 0x64},
{0xD0, 0x21},
{0xD1, 0x0F},
{0xD2, 0x88},
{0xE0, 0x01},
{0xE1, 0x04},
{0xE2, 0x41},
{0xE3, 0xD6},
{0xE4, 0x00},
{0xE5, 0x0C},
{0xE6, 0x0A},
{0xE7, 0x00},
{0xE8, 0x00},
{0xE9, 0x00},
{0xEE, 0x07},
{0xEF, 0x01},
{0x00, 0x1E},
{0x01, 0x1E},
{0x02, 0x0F},
{0x03, 0x10},
{0x04, 0x02},
{0x05, 0x00},
{0x06, 0xB0},
{0x07, 0x04},
{0x08, 0x0D},
{0x09, 0x0E},
{0x0A, 0x9C},
{0x0B, 0x04},
{0x0C, 0x05},
{0x0D, 0x0F},
{0x0E, 0x02},
{0x0F, 0x12},
{0x10, 0x02},
{0x11, 0x02},
{0x12, 0x00},
{0x13, 0x01},
{0x14, 0x05},
{0x15, 0x07},
{0x16, 0x05},
{0x17, 0x07},
{0x18, 0x01},
{0x19, 0x04},
{0x1A, 0x05},
{0x1B, 0x0C},
{0x1C, 0x2A},
{0x1D, 0x01},
{0x1E, 0x00},
{0x21, 0x00},
{0x22, 0x00},
{0x23, 0x00},
{0x25, 0x01},
{0x26, 0x00},
{0x27, 0x39},
{0x28, 0x7F},
{0x29, 0x08},
{0x30, 0x03},
{0x31, 0x00},
{0x32, 0x1A},
{0x33, 0x1A},
{0x34, 0x07},
{0x35, 0x07},
{0x36, 0x01},
{0x37, 0xFF},
{0x38, 0x36},
{0x39, 0x07},
{0x3A, 0x00},
{0x3E, 0xFF},
{0x3F, 0x00},
{0x40, 0x77},
{0x41, 0x40},
{0x42, 0x00},
{0x43, 0x30},
{0x44, 0xA0},
{0x45, 0x5C},
{0x46, 0x00},
{0x47, 0x00},
{0x48, 0x58},
{0x4A, 0x1E},
{0x4B, 0x1E},
{0x4C, 0x00},
{0x4D, 0x00},
{0x4E, 0xA0},
{0x4F, 0x80},
{0x50, 0x00},
{0x51, 0x00},
{0x52, 0x00},
{0x53, 0x00},
{0x54, 0x00},
{0x57, 0x80},
{0x59, 0x10},
{0x5A, 0x08},
{0x5B, 0x94},
{0x5C, 0xE8},
{0x5D, 0x08},
{0x5E, 0x3D},
{0x5F, 0x99},
{0x60, 0x45},
{0x61, 0x40},
{0x63, 0x2D},
{0x64, 0x02},
{0x65, 0x96},
{0x66, 0x00},
{0x67, 0x97},
{0x68, 0x01},
{0x69, 0xCD},
{0x6A, 0x01},
{0x6B, 0xB0},
{0x6C, 0x04},
{0x6D, 0x2C},
{0x6E, 0x01},
{0x6F, 0x32},
{0x71, 0x00},
{0x72, 0x01},
{0x73, 0x35},
{0x74, 0x00},
{0x75, 0x33},
{0x76, 0x31},
{0x77, 0x01},
{0x7C, 0x84},
{0x7D, 0x03},
{0x7E, 0x01}
}; |
Last edited by ddevices on Thu Jun 18, 2020 6:30 am; edited 1 time in total |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Mon Jun 15, 2020 2:50 pm |
|
|
hmm, can you write just to that one register( 0x72) ?
create a new, very small program to select the device and write... see what happens.
Jay |
|
|
ddevices
Joined: 15 Jun 2020 Posts: 13
|
|
Posted: Mon Jun 15, 2020 3:19 pm |
|
|
Thank you for the suggestion. In a way that's what I tried to do with the mainloop:
Code: | MAINLOOP_WAIT() ; //10ms
if(count>0) count--;
if(count==1)
{
output_toggle(LED1);
i2c_start();
i2c_write(PAJ7620_write);
i2c_write(0x72);
i2c_write(0x01); //if 0x00 it's okay , if 0x01 it locks up
i2c_stop();
count=200;
}
|
You can see in mainloop all I'm trying to do is write to that one register. It has no problem when parameter is 0 but switch it to 1 and PIC locks up. I assume it is waiting for ACK? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Mon Jun 15, 2020 3:54 pm |
|
|
Could you please post a link to the device datasheet that has all the registers ? I've downloaded 2 and can't see register 0x72 anywhere !
edit, OK 3rd datasheet has them listed BUT nothing about what they do.
also, are you running PIC at 3 volts ??
thanks
Jay |
|
|
ddevices
Joined: 15 Jun 2020 Posts: 13
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jun 15, 2020 4:32 pm |
|
|
Post the value of this.
Quote: | Correct pull ups are on I2C lines |
Tell us the value of the pull-ups. |
|
|
ddevices
Joined: 15 Jun 2020 Posts: 13
|
|
Posted: Mon Jun 15, 2020 4:41 pm |
|
|
// DEVICE ID
#define PAJ7620_ID 0x73
#define PAJ7620_write 0xE6
#define PAJ7620_read 0xE7
Pull ups are 2.2K. Also, please keep in mind the hundreds of other writes function correctly (as determined by the ACK), only to register 0x72 with parameter 0x01 fails.
Thank you for your help. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Jun 15, 2020 5:03 pm |
|
|
Quote: | I have this sensor working with Arduino |
Post the Arduino code that writes 01 to reg 0x72.
Also post a link to the full Arduino code.
We can analyze what the Arduino code is doing
and make equivalent CCS code. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Tue Jun 16, 2020 12:03 am |
|
|
Screaming thing is your setup is not legal....
The PAJ7620, is a 3.3v max device. The PIC you have, is legal to run at
3.3v, but at 18.7MHz max. You are showing a 48Mhz setup.
So either you have a clock speed that is illegal for the PIC, or you are
running the PIC at 5v....
If you are running the PIC at 5v, the I2C inputs require to go up to 4v.
Not possible with the PAJ7620.
Now I'd suspect you are at 5v, for a second reason. You have the USB
VREG enabled. This has a minimum input voltage of 4.1v. To run below
this, you have to supply the USB power.
However, if you are running the PIC at 5v (so clock setting is legal), and
the PAJ7620 at 3.3v, then you may be able to work by selecting the
'SMBUS' option on the I2C setup. This should switch the I2C inputs to
accepting SMBUS voltage levels.
Now expand here a little. On most PIC's, the data sheet lists the voltage
levels for SMBUS as 2.1v for ViH. However the xx50 datasheet does not
say this. However it does still refer to SMBUS mode on the input pins, so
should switch to this. The Arduino inputs are normal 'TTL' inputs, so have
a ViH of 2.4v, while the I2C pin inputs on the PIC have a ViH by default
of 0.8*Vdd. So with a 5v supply, 4v, which the chip is not going to give...
So what you post has problems. Describe what voltages are being used?.
What pull up resistors on the I2C, and to what voltage these go?.
How is the supply generated for the PAJ?.
This write is actually a main 'enable' for the chip. That earlier writes
seem to work, doesn't actually prove anything. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Tue Jun 16, 2020 3:53 am |
|
|
OK. See this:
Quote: |
I am running at 5 volts, the gesture board has voltage regulator and data line translators, board is rated for 3 to 5 volts.
|
Means you need the 'SMBUS' option in your #use i2c.
The point is that by default the PIC is setup to use 5v I2C inputs, which need
to go up to 4v to work. The Arduino, only needs 2.4v.
Adding this option should reprogram the PIC inputs down to a voltage
more like the Arduino....
Also, what is PAJ7620_write defined as?. Needs to be 0xE6. |
|
|
ddevices
Joined: 15 Jun 2020 Posts: 13
|
|
Posted: Tue Jun 16, 2020 6:52 am |
|
|
Ttelmah, good effort and I did try the SMBUS option that you suggested but same results. The board is fully compatible from 3.3V to 5V, it has voltage regulator and data line level shifters. Below is link to board:
https://wiki.dfrobot.com/Gravity%3A%20PAJ7620U2%20Gesture%20Sensor%20SKU%3A%20SEN0315
Link to schematic:
https://github.com/John-1997/schematiC
Using an oscilloscope I can see the PAJ7620U2 is pulling the SDA line low for valid ACK for all other registers (also with scope I can see full 5V SDA & SCL to PIC).
Below is link to code I have running on Arduino:
https://github.com/DFRobot/DFRobot_PAJ7620U2
Second set of code that is very similar:
https://github.com/Seeed-Studio/Gesture_PAJ7620
Most of the code does not have to be translated, my code is failing in the initialize of the registers which on Arduino is:
Code: | for (int i = 0; i < sizeof(initRegisterArray)/sizeof(initRegisterArray[0]); i++) {
writeReg(initRegisterArray[i][0], &initRegisterArray[i][1],1); |
My equivalent code you can see in first post, it stops at element 210 which is register 0x72. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9243 Location: Greensville,Ontario
|
|
Posted: Tue Jun 16, 2020 7:42 am |
|
|
I have to come back to doing the simple test..
cut code to access ONLY register 0x72 and see if you can read and write the data, which should be 0x00 or 0x01 according to the datasheet.
That eliminates 99.44% of all other code and focuses on the ONE register that's causes the problem.
it'd be nice to KNOW what that register actually does... 'disable' is vague... as in if it does 'disable' the device I can see it 'locking up' as no more I2C traffic would be possible.... |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Tue Jun 16, 2020 7:58 am |
|
|
I repeat the question. "what is PAJ7620_write defined as"?.
The code you link to has:
PAJ7620_IIC_ADDR = 0x73
You do understand this will have to be doubled for use on a PIC.
PIC's use the 8bit 'address byte', not the 7bit address format, that the Pi/Arduino uses. |
|
|
ddevices
Joined: 15 Jun 2020 Posts: 13
|
|
Posted: Tue Jun 16, 2020 8:16 am |
|
|
Sorry, in six posts above I had written PAJ7620_write is 0xE6.
I think you are on to something about the write to that register only. I changed the main code to:
Code: | void main() {
int8 scntr, i, count, status;
unsigned char data[2];
setup_adc_ports ( NO_ANALOGS ) ;
setup_adc( ADC_OFF ) ;
set_tris_a( 0b11111111 ) ;
#use fast_io( A )
set_tris_b( 0b11111111 ) ;
#use fast_io( B )
set_tris_c( 0b10111110 ) ;
SETUP_WDT( WDT_OFF ) ;
SETUP_TIMER_0( T0_OFF ) ;
SETUP_TIMER_1( T1_DISABLED ) ;
SETUP_TIMER_2( T2_DISABLED , 255 , 16 ) ;
SETUP_TIMER_3( T3_DISABLED ) ;
paj7620SelectBank(1);
count = 100; //one second timing
while ( TRUE ) { // main infinite while loop
MAINLOOP_WAIT() ; //10ms
if(count>0) count--;
i=0;
if(count==1)
{
output_toggle(LED1);
i2c_start();
i2c_write(PAJ7620_write);
i2c_write(0x72);
i2c_write(0x01);
i2c_stop();
count=100;
}
}//end main infinite while loop
} |
You can see I eliminated the initialization of the PAJ and every second write to 0x72, it now does not lock up with either 0 or 1 as parameter. I did have to set the bank to 1 as that is where 0x72 is located, but outside of that it is the only register I am writing and now I2C does not lock up. I would think this means problem is in one of the other 219 registers that I write parameters to. Finding it might be an issue. Also, the Arduino code is the same exact registers and parameters without problem.
Disable does not stop the I2C bus in PAJ, it continues to operate.
I will see if I can find the other offending register, it might take some time.
Thanks for help. |
|
|
ddevices
Joined: 15 Jun 2020 Posts: 13
|
|
Posted: Tue Jun 16, 2020 8:50 am |
|
|
Unfortunately I spoke too soon. In the 'short' code example I selected bank 1 only once but that at start is really only waking up the PAJ, you have to do it twice:
paj7620SelectBank(1);
paj7620SelectBank(1);
The first wakes the PAJ and the second correctly shifts it to bank 1. Once that is done then writing 0x72 with 0x01 locks up chip. It did not lock in my first test because I was still in bank 0. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|