Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

PIC16F18877: Trying to read Accelerometer data from LSM9DS0 on I2C

Status
Not open for further replies.

sr2w

Junior Member level 1
Junior Member level 1
Joined
Jul 12, 2017
Messages
18
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
156
I am receiving same value as the output even when I change the orientation of the sensor.
What could be the reason ?

1) I send slave address (with write bit).
2) I send sub address.
3) I send slave address (with read bit).


Code:
void main(void)
{
    
    TRISC = 0x18; // Set RC3(SCL) and RC4(SDA) as inputs.
    ANSELC = 0;   // In debug mode I can see RC3 and RC4 high after stepping into
                  // this line of code, so I know SDA and SCL are properly pulled
                  // high.
    TRISB = 0;    // Saving received I2C data in PORTB.
    ANSELB = 0;   // After this step the PORTB is filled with the last  
                  // SSPBUF data (0X3C), I find this weird 
 
 RC3PPS = 0X14;   // 
 RC4PPS = 0X15;   // Setting RC3 and RC4 as SCL and SDA pins
 SSP1CON1 = 0X28; // SSPEN - 1, SSPM - 1000
 SSP1ADD = 0X03; // clock frequency 31.25 kHz
 SSP1STAT = 0X80; // SMP - 1
 
 // First write with slave address
 SSP1CON2bits.SEN = 1;  // Start I2C
 
 while (SSP1CON2bits.SEN == 1); // Wait for "START" to finish
 PIR3bits.SSP1IF = 0;           
 SSP1BUF = 0X3C;                // LSM9DS0 Accelerometer address(with write bit)
                                // Page 33 in LSM9DS0 data sheet
 while((PIR3bits.SSP1IF == 0) && (SSP1STATbits.BF == 1) && (SSP1STATbits.R_nW == 1));
 PIR3bits.SSP1IF = 0;           // Wait for transmission to complete 
 
 // Slave sub Address
 SSP1BUF = 0X2C;                // sub-address of Z-axis acceleration data 
                                // register, first 8 bits
 while((PIR3bits.SSP1IF == 0) && (SSP1STATbits.BF == 1) && (SSP1STATbits.R_nW == 1));
 PIR3bits.SSP1IF = 0;           // Wait for transmission to complete
 
 // Repeated Start
 SSP1CON2bits.RSEN = 1;        // Repeated Start so that I can start reading the  
                               // above Z axis data
 while (SSP1CON2bits.RSEN == 1);/* Wait if Transmit in progress */
 PIR3bits.SSP1IF = 0;
 SSP1BUF = 0X3D;               // LSM9DS0 Accelerometer address(with read bit)
                                // Page 33 in LSM9DS0 data sheet
 while((PIR3bits.SSP1IF == 0) && (SSP1STATbits.BF == 1) && (SSP1STATbits.R_nW == 1));
 PIR3bits.SSP1IF = 0;          // Wait for transmission to complete
 
 SSP1CON2bits.RCEN = 1;        // Enable receive in I2C
 //while ( SSP1CON2bits.RCEN == 1);
 while(SSP1STATbits.BF == 0);
 PIR3bits.SSP1IF = 0;
 PORTB = SSP1BUF;              
 
 SSP1CON2bits.ACKDT = 1;
 SSP1CON2bits.ACKEN = 1;
 while( SSP1CON2bits.ACKEN == 1);
 PIR3bits.SSP1IF = 0;
 
 SSP1CON2bits.PEN = 1;
 while(1);
 
 
}
 

Put the I2C device reading code in main loop. Use a 100 ms delay before main loop.

I2C clock freuency is 32.78 KHz or 100 KHz ? What is th evalue of I2C bus pullup resistors ?

PIC16F18877 has LATx registers to output data. Use LATB instead of PORTB.
 
Last edited:
  • Like
Reactions: sr2w

    sr2w

    Points: 2
    Helpful Answer Positive Rating
All of my code is in main function. Do you want me to separate the reading code to make it more readable ?

I2C clock frequency is 31.25 KHz (SSP1ADD = 0X03). Should it necessarily be 32.78 KHz or 100 KHz ?

10 Kilo Ohms - Pull up registers. The SDA and SCL pins are pulled high since I have verified this in debug mode.

Sure I'll try LATB instead of PORTB.
 

Have you checked I2C application note. Does i tmention that for 32.78 KHZ I2C Clock the I2C bus pullups need to be 10k ?

You are reading I2C device only at the beginning and before while(1) loop and so you will not get continuous accelerometer readings. If both PIC and LSM9DS0 is powered from the same source then LSM9DS0 might need some 100 ms delay before it can stabilize and provide readings when power is applied. There is no initialization delay in your code. If you put your LSM90DS0 reading code in while(1) loop and move the sensor then you might seeing different readings on PORTB.

https://www.ti.com/lit/an/slva689/slva689.pdf

Are you sure that in your PIC the I2C pins are directly available for communication ? My Compilers tells that the I2C pins needs to be remapped.

Edit:

I see that you have remapped the pins.

Try

Code:
SLRCONC = 0x00;

What is your Fosc ? Are you using any PLL ?

- - - Updated - - -

PPS needs to be unloacked and then I2C pins needs to be remapped and PPS have to be locked.

Show your config words configurations. In config words how the PPS unlocking and locking bit is configured ?


8 MHz Fosc. Can you test this .hex file. Tell me what PORTB displays.
 

Attachments

  • Reading_LSM9DS0.rar
    1.2 KB · Views: 174
Last edited:
  • Like
Reactions: sr2w

    sr2w

    Points: 2
    Helpful Answer Positive Rating
These are my config settings, You can see - CONFIG 2, one PPS setting is present.

// PIC16F18877 Configuration Bit Settings

// 'C' source line config statements

Code:
// CONFIG1
#pragma config FEXTOSC = LP     // External Oscillator mode selection bits (LP (crystal oscillator) optimized for 32.768kHz; PFM set to low power)
#pragma config RSTOSC = HFINT32 // Power-up default value for COSC bits (HFINTOSC with OSCFRQ= 32 MHz and CDIV = 1:1)
#pragma config CLKOUTEN = OFF   // Clock Out Enable bit (CLKOUT function is disabled; i/o or oscillator function on OSC2)
#pragma config CSWEN = OFF      // Clock Switch Enable bit (The NOSC and NDIV bits cannot be changed by user software)
#pragma config FCMEN = OFF      // Fail-Safe Clock Monitor Enable bit (FSCM timer disabled)

// CONFIG2
#pragma config MCLRE = OFF      // Master Clear Enable bit (MCLR pin function is port defined function)
#pragma config PWRTE = OFF      // Power-up Timer Enable bit (PWRT disabled)
#pragma config LPBOREN = OFF    // Low-Power BOR enable bit (ULPBOR disabled)
#pragma config BOREN = OFF      // Brown-out reset enable bits (Brown-out reset disabled)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (VBOR) set to 1.9V on LF, and 2.45V on F Devices)
#pragma config ZCD = OFF        // Zero-cross detect disable (Zero-cross detect circuit is disabled at POR.)
#pragma config PPS1WAY = OFF    // Peripheral Pin Select one-way control (The PPSLOCK bit can be set and cleared repeatedly by software)
#pragma config STVREN = OFF     // Stack Overflow/Underflow Reset Enable bit (Stack Overflow or Underflow will not cause a reset)

// CONFIG3
#pragma config WDTCPS = WDTCPS_31// WDT Period Select bits (Divider ratio 1:65536; software control of WDTPS)
#pragma config WDTE = OFF       // WDT operating mode (WDT Disabled, SWDTEN is ignored)
#pragma config WDTCWS = WDTCWS_7// WDT Window Select bits (window always open (100%); software control; keyed access not required)
#pragma config WDTCCS = HFINTOSC// WDT input clock selector (WDT reference clock is the 31.25 kHz HFINTOSC)

// CONFIG4
#pragma config WRT = OFF        // UserNVM self-write protection bits (Write protection off)
#pragma config SCANE = available// Scanner Enable bit (Scanner module is available for use)
#pragma config LVP = OFF        // Low Voltage Programming Enable bit (High Voltage on MCLR/Vpp must be used for programming)

// CONFIG5
#pragma config CP = OFF         // UserNVM Program memory code protection bit (Program Memory code protection disabled)
#pragma config CPD = OFF        // DataNVM code protection bit (Data EEPROM code protection disabled)
 
Last edited by a moderator:

My Compiler tells that for Fosc = 32 MHz, I2C Clock 31.25 KHz is out of range and it doesn't compile.

Here is Fosc = 32 MHz and I2C Clock - 100 KHz .hex file for testing. Test and reply.
 

Attachments

  • Reading_LSM9DS0_1.1.rar
    1.2 KB · Views: 171

Can you please send me the .c file instead of HEX file so that I can do Step-by-Step debugging ?

I haven't found any specific instruction about using 10k resistors I am just using them. During debugging I can see that SDA and SCL pins go high hence I am concluding that 10k resistors should do fine.

I am trying to read the sensor only once, hence the while(1) in the end.

Fosc = 32 MHz. I am not using any PLL.

Thank You for the efforts you are taking for my solving my problem baileychic!
 
Last edited:

My Compiler is mikroC PRO PIC. I didn't write code in MPLAB X XC8. Here is my mikroC PRO PIC project. Also view the .asm file which is my Compiler generated .asm code for my C code.

Change I2C pullups to 4.7k and test my 100 KHz I2C clock code which I posted in this post. Just burn my .hex file to PIC and see if you get any readings.

Data sheet page 494;

FClock = Fosc/(4 * SSPxADD+1) = 32 MHz / (4 * 256) = 31250. SSPxADD = 256 - 1 = 255 but for 100 KHz I2C clock

Fclock = Fosc/(4 * 80) = 100 KHz, SSPxADD = 79 (80 - 1) but my Compiler is generating 80 for SSPxADD. I found value in .asm code generated by mikroC PRO PIC Compiler. So, mikroC PRO PIC uses SSPxADD+1 as SSPxADD value. So, for 31.25 KHz it is 256 and doesn't fit in SSPxADD register and hence mikroC PRO PIC Compiler is generating error while compiling but I have used mikroC PRO PIC Compiler for many I2C projects and it works fine.
 

Attachments

  • Reading LSM9DS0.rar
    50 KB · Views: 162
Last edited:
  • Like
Reactions: sr2w

    sr2w

    Points: 2
    Helpful Answer Positive Rating
I don't have 4.7k resistors now. I'll have to go to college for that (day-after-tomorrow).

I'll read the output on PORTB using LEDs that should be fine right ?
 

For SSPxADD = 255 and Fosc = 32 MHz you will get 31.25 KHz I2C Clock. Use that value. So, in your original code SSP1ADD value was wrong.

Don't configure SSP1STAT. Configure only SSP1ADD and SSP1CON.

Yes, outputting read I2C data on PORTB Leds will be fine.
 

My debugger gets stuck at the green highlighted line when I set SSP1ADD as 255 (0xFF), when it is 0x03, it doesn't give me such problems.
Capture.JPG
 

How did you calculate 0x03 for SSP1ADD ?

First test the attached project and see if you get any readings on PORTB Leds. I have used 16 MHz HFINTOSC and 31.25 KHz I2C Clock. Just burn my .hex file and test.
 

Attachments

  • Reading LSM9DS0 - 16 MHz HFINTOSC - I2C CLK 31.25 KHz.rar
    50 KB · Views: 169
Last edited:

0x03 has stuck along with me since my last code which I wrote for PIC16F1508 proteus simulation. I used to get 31.25 KHz clock set in simulation log(attached picture) if I used SSPADD = 0x03. Using this value for other PIC controller(now 16F18877) is something wrong which I am doing. This lets me easily debug through step-by-step my code.

I am ready to forget 0x03. 0xFF should be the right answer as we get it from the formula. But then it is creating problems while debugging.
Capture.JPG
 

I am getting zero volts on all port B pins. I have burnt the code using MPLAB. This shouldn't be a problem right ? A hex file should be a hex file right ?
 

I tried using a logic analyzer, but the output doesn't change when I try to read the sensor register with different orientations.
image.png

Did some variations in code,

Code:
 void wait()
{
    while(PIR3bits.SSP1IF == 0);
PIR3bits.SSP1IF = 0;
}
void main()
{
    
    TRISC = 0x18;
    ANSELC = 0;
    TRISB = 0;
    ANSELB = 0;
 
 RC3PPS = 0X14;
 RC4PPS = 0X15;
 SSP1CON1 = 0X28; // SSPEN - 1, SSPM - 1000
 SSP1ADD = 0X4F; // clock frequency 31.25 kHz
 SSP1STAT = 0X80; // SMP - 1
 
 
 while(1)
 {
 SSP1CON2bits.SEN = 1;
 
 while (SSP1CON2bits.SEN == 1);
 PIR3bits.SSP1IF = 0;
 SSP1BUF = 0X3C; // Slave Add + Write
 wait();
SSP1BUF = 0X2C; // Slave sub Add
wait();
SSP1CON2bits.RSEN = 1;
 while (SSP1CON2bits.RSEN == 1);
 PIR3bits.SSP1IF = 0;
 
 SSP1BUF = 0X3D; // Slave Add + Read
 wait();
 
 
SSP1CON2bits.RCEN = 1;
while (SSP1CON2bits.RCEN == 1);
wait();
 PORTB = SSP1BUF;
 
 SSP1CON2bits.ACKDT = 0;
 SSP1CON2bits.ACKEN = 1;
while (SSP1CON2bits.ACKEN == 1);
wait();

 
 SSP1CON2bits.PEN = 1;
 __delay_ms(1000);
 
 }
 
}
 
Last edited:

Your Oscillator settings might be wrong if yoiu ar egetting 31.25 KhZ I2C clock for SSPADD value 0x03. Are you doing oscillator switching in the code ? Somewhere maybe in another forum thread of yours I saw that you are switching oscillator. Is this right ?
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top