|
|
View previous topic :: View next topic |
Author |
Message |
rfjhh
Joined: 31 Mar 2011 Posts: 51 Location: Mexico
|
Interfacing MPU-6050 with i2c |
Posted: Tue Feb 12, 2019 12:32 pm |
|
|
I'm new in using MPU-650 accelerometer/gyroscope with a i2c so I have a lot of doubts. I've wrote a program but It doesn't work. I've read a lot of information, some in this forum.
The program is as follows:
Code: |
#include <16F887.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay(clock=4M)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#include<LCD.c>
void giro_ini()
{
i2c_start(); // Secuencia de inicio
i2c_write(0xD0); // Envío la dirección del esclavo
i2c_write(0x1A); // Dirección del registro CONFIG
i2c_write(0x00); // EXT_SYNC_SET = deshabilitado;
// Ancho de banda acelerómetro = 260Hz
// Ancho de banda giroscopio = 256Hz
// Fs giroscopio = 8KHz
i2c_stop(); // Secuencia de paro
i2c_start(); // Secuencia de inicio
i2c_write(0xD0); // Envío la dirección del esclavo
i2c_write(0x19); // Dirección del registro Sample Rate Divider
i2c_write(0x07); // Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)
// Sample Rate = 8 KHz/(1 + 7)= 1 KHz
i2c_stop(); // Secuencia de paro
i2c_start(); // Secuencia de inicio
i2c_write(0xD0); // Envío la dirección del esclavo
i2c_write(0x6B); // Dirección del registro Power Management 1
i2c_write(0x01); // Frecuencia de referencia del eje X del giroscopio
// Se elige según 7.15 Internal Clock Generation *
i2c_stop(); // Secuencia de paro
i2c_start(); // Secuencia de inicio
i2c_write(0xD0); // Envío la dirección del esclavo
i2c_write(0x1B); // Dirección del registro GYRO_CONFIG
i2c_write(0x18); // Escala completa +/- 2000°
//
i2c_stop(); //
i2c_start(); // Secuencia de inicio
i2c_write(0xD0); // Envío la dirección del esclavo
i2c_write(0x38); // Dirección del registro INT_ENABLE
i2c_write(0x01); // DATA_RDY_EN = 1
//
i2c_stop(); //
}
void acel_ini()
{
i2c_start(); // Secuencia de inicio
i2c_write(0xD0); // Envío la dirección del esclavo
i2c_write(0x1C); // Dirección del registro ACCEL_CONFIG
i2c_write(0x00); // Escala completa +/- 2g
//
i2c_stop(); //
}
void main()
{
float ax, ay, az, gx, gy, gz;
int8 acxB = 0, acxA = 0;
int8 dato = 0, status;
giro_ini();
lcd_init();
lcd_gotoxy(1,1);
printf(lcd_putc, "Lectura Acelera");
for(;;)
{
i2c_start(); // Secuencia de inicio
i2c_write(0x3B); // Dirección de ACCEL_XOUT[15:8]
i2c_write(0xD1); // Envío la dirección del esclavo lectura
acxA = i2c_read(0); // Byte más significativo
i2c_stop();
i2c_start();
i2c_write(0x3C); // Dirección de ACCEL_XOUT[7:0]
i2c_write(0xD1); // Envío la dirección del esclavo lectura
acxB = i2c_read(0);
i2c_stop();
lcd_gotoxy(1,2);
printf(lcd_putc, "AA: %u %u", acxA, acxB);
delay_ms(200);
}
} |
All I see in the LCD is AA: 255 255
Can somebody tell me what I'm doing wrong please????
Regards |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Tue Feb 12, 2019 12:53 pm |
|
|
Give the proper chip number. MPU6000, MPU6500?. MPU650 doesn't exist...
However big 'glaring' thing. These chips are generally 3.3v devices. As
such you really need a level translator to use with a 5v PIC. Though you
may be able to work with a PIC that supports SMBUS, by selecting
this in the settings, and 3.3v pull-ups. Honestly much better to use a
3.3v PIC. |
|
|
rfjhh
Joined: 31 Mar 2011 Posts: 51 Location: Mexico
|
|
Posted: Tue Feb 12, 2019 1:08 pm |
|
|
MPU 6050
I'm using a small board that works at 5V. There is a 3,3V regulator on board. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Tue Feb 12, 2019 1:16 pm |
|
|
The MPU6050 is a 3 volt device so the onboard regulator converts VDD to 3. As Mr T points out, the 3 volts FROM the MPU6050 is NOT 'high' enough to properly communicate with the 5 volt PIC.
As he says a 3 volt PIC is the easy solution. Another option, You could ADD a 5 to 3 level translation module.
Jay |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Feb 12, 2019 1:24 pm |
|
|
To put Ttelmah's comments into code and pictures, do this:
Code: | #use i2c(Master, I2C1, SMBUS) |
Code: | +3.3v
|
<
> 3.3K
<
To PIC | To MPU6050
pin C4 ------------------ SDA pin
(SDA)
+3.3v
|
<
> 3.3K
<
To PIC | To MPU6050
pin C3 ------------------ SCL pin
(SCL) |
|
|
|
rfjhh
Joined: 31 Mar 2011 Posts: 51 Location: Mexico
|
|
Posted: Tue Feb 12, 2019 1:41 pm |
|
|
As I told you, I'm using a small board (GY-521) with a MPU 6050, 3,3 V regulator and pull up resistors included in the same configuration you proposed.
It has been designed to work with Arduino (I don't like it at all), so, talking about hardware, all you have to do is connect the SDA and SCL pins to the uC. |
|
|
dluu13
Joined: 28 Sep 2018 Posts: 395 Location: Toronto, ON
|
|
Posted: Tue Feb 12, 2019 2:15 pm |
|
|
Based on what I can see from the GY521, the I2C bus will pull up to 3v3
when high. On your MCU datasheet for the I2C bus which uses a Schmitt
Trigger buffer, the MCU flips high when the voltage on the bus reaches
0.8*Vdd, which is 4 V. So, 3v3 is too low to flip the pin.
At least that's what I'm reading off the datasheet, in the electrical
characteristics chapter.
We are talking about level translator like this:
https://www.sparkfun.com/products/12009
It translates the voltage level of your signal bus, not power. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1909
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Tue Feb 12, 2019 3:59 pm |
|
|
The Arduino uC uses a totally different architecture in the die (the chip ( the 'computer')) compared to the PIC series.
That's why you must read and understand the different hardware configurations of the PIC for I2C.
Yes the voltage reg of the module reduces 5v to 3v to power the device BUT as others have said a '1' from the device will NOT be seen as a '1' by the PIC.
At the very least you need a dual, bidirectional logic level converter. Easier to just use a 3 volt PIC. a 16LF887 would work, note the 'L' ,which means Low voltage ( good for 3 v operation).
OK.. I just downloaded the 16F887 datasheet...and it WILL run at 4MHz with a VDD of 3 volts. so NO need to power the PIC from 5 volts ! So it will interface without additional parts IF run at 3 volts.
I suggest copying/compile and run PCM P 'I2C scanner' program in the code library. It will confirm IF the PIC can 'see' the peripheral. If it does, then there's a problem with your program. If it doesn't see it,and the wiring is correct, then perhaps the device is dead. |
|
|
rfjhh
Joined: 31 Mar 2011 Posts: 51 Location: Mexico
|
|
Posted: Tue Feb 12, 2019 7:35 pm |
|
|
I've use this program to look for the address of the slave, MPU 6050 in this case and it runs well, so I don't know what is wrong with the other program.
The hardware conditions are the same.....
Code: |
#include <16F887.h>
#fuses INTRC_IO,NOWDT,NOPROTECT,PUT,NOLVP,NOBROWNOUT
#use delay(clock=4M)
#use i2c(Master, sda=PIN_C4, scl=PIN_C3)
#include<LCD.c>
int8 estado_ack(int8 direccion)
{
int8 status;
i2c_start();
status = i2c_write(direccion); // Status = 0 si se obtuvo un ACK
i2c_stop();
if(status == 0)
return(TRUE);
else
return(FALSE);
}
//=================================
void main()
{
unsigned int8 i;
unsigned int8 status;
unsigned int8 count = 0;
lcd_init();
lcd_gotoxy(1,1);
printf(lcd_putc, "Inicia: ");
delay_ms(1000);
for(i=0x10; i < 0xF0; i+=2)
{
status = estado_ack(i);
if(status == TRUE)
{
lcd_gotoxy(1,1);
printf(lcd_putc, "Dir ACK: %u", i);
count++;
delay_ms(2000);
}
}
if(count == 0)
{lcd_gotoxy(1,2);
printf(lcd_putc, "Nada encontrado.");}
else
{lcd_gotoxy(1,2);
printf(lcd_putc, "Num de chips %u", count);}
while(1);
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Tue Feb 12, 2019 8:11 pm |
|
|
What is the address of the peripheral ?
'255' usually means bus is high.
Are you running the PIC with 3 volts or 5 ?
OK... I did a search here... found this..
https://www.ccsinfo.com/forum/viewtopic.php?t=52866&postdays=0&postorder=asc&start=15
2nd page appears to have working code.. something about 'sleep' mode, it needs to be told to wakeup !!
I don't know if it's the same device but does seem similar....
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Wed Feb 13, 2019 2:35 am |
|
|
Key point to understand, is that Arduino inputs accept a signal of 2.4v as
'high'. The PIC, in I2C mode (using the I2C hardware), requires the signal to
go up to 0.8*Vdd to be seen as a 'high'. So a 5v PIC will require the signals
to reach 4v.
This won't happen.
However you can use the PIC in 'software' I2C mode, on different pins
(look in the data sheet for ones supporting TTL input levels), or you can
switch to SMBUS mode (which changes the input thresholds).
#use i2c(Master, sda=PIN_C4, scl=PIN_C3, SMBUS)
One or the other of these is needed before you have any hope of working.
It'll be seeing a bus error, because the line will be sampled as low:
Quote: |
Note: If, at the beginning of START condition, the
SDA and SCL pins are already sampled
low, or if during the START condition the
SCL line is sampled low before the SDA
line is driven low, a bus collision occurs,
the Bus Collision Interrupt Flag (BCLIF) is
set, the START condition is aborted, and
the I2C module is reset into its IDLE state.
|
so values returned will be meaningless. This is why it returns 255. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9241 Location: Greensville,Ontario
|
|
Posted: Wed Feb 13, 2019 6:22 am |
|
|
what is odd is that he says his test program works....
I'd still like to know the PICs VDD. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
Re: Interfacing MPU-6050 with i2c |
Posted: Wed Feb 13, 2019 6:42 am |
|
|
rfjhh wrote: |
for(;;)
{
i2c_start(); // Secuencia de inicio
i2c_write(0x3B); // Dirección de ACCEL_XOUT[15:8]
i2c_write(0xD1); // Envío la dirección del esclavo lectura
acxA = i2c_read(0); // Byte más significativo
i2c_stop();
i2c_start();
i2c_write(0x3C); // Dirección de ACCEL_XOUT[7:0]
i2c_write(0xD1); // Envío la dirección del esclavo lectura
acxB = i2c_read(0);
i2c_stop();
lcd_gotoxy(1,2);
printf(lcd_putc, "AA: %u %u", acxA, acxB);
delay_ms(200);
}
}[/code]
All I see in the LCD is AA: 255 255
Can somebody tell me what I'm doing wrong please????
Regards |
That's not the correct way to read ACCEL_XOUT_H and ACCEL_XOUT_L.
You have the device address and the register address out of order, and
it's still not the correct way to read two bytes. Look at this link:
http://www.ccsinfo.com/forum/viewtopic.php?t=52866&start=29
From that link, here is the correct way to read a 16-bit register:
Code: | int16 MPU6050_read_word(int8 reg_addr)
{
int8 lsb, msb;
int16 retval;
i2c_start();
i2c_write(MPU6050_SLAVE_WRT); // 0xD0
i2c_write(reg_addr);
i2c_start();
i2c_write(MPU6050_SLAVE_RD); // 0xD1
msb = i2c_read(); // Read MSB byte first.
lsb = i2c_read(0); // Do a NACK on the last read
i2c_stop();
retval = make16(msb, lsb);
return(retval);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19537
|
|
Posted: Wed Feb 13, 2019 8:08 am |
|
|
Yes, he's addressing a device at address 0x3B or 0x3C, which doesn't exist, so
will get 255 as a 'nothing there' answer...
Well spotted.
I actually don't see 'how' he can be successfully accessing the device unless
he is either running on 3.3v, or the board has got level translation. The
pictures of the boards with this number don't show any.
His chip actually has the 'high' for standard I2C mode, at 0.7*Vdd = 3.5v,
so if his 5v supply just happened to be a little low, and the 3.3v on the
board just a little high, it might 'just' work. Not a reliable way to run it
though.... |
|
|
|
|
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
|