I2C communication with "C" language

Hi
I want to do my own cnc level controller using the mpu-6050 with "C'' language, I tried most i2c device communicate 'c' program but not work. does have anybody Test code i2c "C" language for P8x32A?
somebody help me?
is there some library?

Comments

  • Peter JakackiPeter Jakacki Posts: 8,282
    edited 2018-08-23 - 06:34:30
    Bear in mind that your i2c driver must allow for slave busy signalling where the mp6050 pulls the scl line low until it is ready. Most i2c devices do not do this so most i2c drivers do not worry about it and blindly read the data (which isn't ready).

    Tachyon Forth - compact, fast, forthwright and interactive
    useforthlogo-s.png
    --->CLICK THE LOGO for more links<---
    P2 +++++ TAQOZ INTRO & LINKS +++++ P2 SHORTFORM DATASHEET
    P1 +++++ Latest binary V5.4 includes EASYFILE +++++ Tachyon Forth News Blog
    Brisbane, Australia
  • Thank you mr.peter ,
    mpu6050 i add the wait while busy ampu6050 i add the wait while busy and it never jumps out of the loop since i isue the fitst commandnd it never jumps out of the loop since i isue the fitst comm[img][/img]and(Attached file)

    this my programs,
    #include "simpletools.h" // Include simpletools header
    // MPU6050 Slave Device Address
    const uint8_t MPU6050SlaveAddress = 0x68;

    // sensitivity scale factor respective to full scale setting provided in datasheet
    const uint16_t AccelScaleFactor = 16384;
    const uint16_t GyroScaleFactor = 131;

    // MPU6050 few configuration register addresses
    const uint8_t MPU6050_REGISTER_SMPLRT_DIV = 0x19;
    const uint8_t MPU6050_REGISTER_USER_CTRL = 0x6A;
    const uint8_t MPU6050_REGISTER_PWR_MGMT_1 = 0x6B;
    const uint8_t MPU6050_REGISTER_PWR_MGMT_2 = 0x6C;
    const uint8_t MPU6050_REGISTER_CONFIG = 0x1A;
    const uint8_t MPU6050_REGISTER_GYRO_CONFIG = 0x1B;
    const uint8_t MPU6050_REGISTER_ACCEL_CONFIG = 0x1C;
    const uint8_t MPU6050_REGISTER_FIFO_EN = 0x23;
    const uint8_t MPU6050_REGISTER_INT_ENABLE = 0x38;
    const uint8_t MPU6050_REGISTER_ACCEL_XOUT_H = 0x3B;
    const uint8_t MPU6050_REGISTER_SIGNAL_PATH_RESET = 0x68;

    void MPU6050_Init();
    void Read_RawValue(uint8_t deviceAddress,uint8_t regAddress);
    void I2C_Write(uint8_t deviceAddress,uint8_t regAddress,char *data);

    i2c *eeBus; // I2C bus ID
    char testStr[] = {0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0};
    int16_t AccelX, AccelY, AccelZ, Temperature, GyroX, GyroY, GyroZ;
    double Ax, Ay, Az, T, Gx, Gy, Gz;

    int main() // Main function
    {
    eeBus = i2c_newbus(16,15, 1); // Set up I2C bus, get bus ID;
    //I2C_Write(0x68,0x6b,0);
    //print("done");
    MPU6050_Init();
    while (1){
    Read_RawValue(MPU6050SlaveAddress, MPU6050_REGISTER_ACCEL_XOUT_H);
    //print("testStr = %s \n", testStr); // Display result
    print("Ax: %f",Ax);
    print(" Ay: %f",Ay);
    print(" Az: %f",Az);
    print(" T: %f",T);
    print(" Gx: %f",Gx);
    print(" Gy: %f",Gy);
    print(" Gz: %f",Gz);
    print(" \n ");
    pause(1000);
    }

    }

    void I2C_Write(uint8_t deviceAddress,uint8_t regAddress,char *data){
    i2c_out(eeBus, deviceAddress,regAddress, 1, data, 1);
    while(i2c_busy(eeBus,deviceAddress));
    }

    void Read_RawValue(uint8_t deviceAddress,uint8_t regAddress){
    i2c_in(eeBus, deviceAddress,regAddress, 1, testStr, 14);

    AccelX = (((int16_t)testStr[1]<<8) | testStr[2]);
    AccelY = (((int16_t)testStr[3]<<8) | testStr[4]);
    AccelZ = (((int16_t)testStr[5]<<8) | testStr[6]);
    Temperature = (((int16_t)testStr[7]<<8) | testStr[8]);
    GyroX = (((int16_t)testStr[9]<<8) | testStr[10]);
    GyroY = (((int16_t)testStr[11]<<8) | testStr[12]);
    GyroZ = (((int16_t)testStr[13]<<8) | testStr[14]);

    //divide each with their sensitivity scale factor
    Ax = (double)AccelX/AccelScaleFactor;
    Ay = (double)AccelY/AccelScaleFactor;
    Az = (double)AccelZ/AccelScaleFactor;
    T = (double)Temperature/340+36.53; //temperature formula
    Gx = (double)GyroX/GyroScaleFactor;
    Gy = (double)GyroY/GyroScaleFactor;
    Gz = (double)GyroZ/GyroScaleFactor;

    }

    void MPU6050_Init(){
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_SMPLRT_DIV,(char*) 7);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_PWR_MGMT_1,(char*) 1);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_PWR_MGMT_2,(char*) 0);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_CONFIG,(char*) 0);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_GYRO_CONFIG,(char*) 0);//set +/-250 degree/second full scale
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_ACCEL_CONFIG,(char*) 0);// set +/- 2g full scale
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_FIFO_EN,(char*) 0);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_INT_ENABLE,(char*) 1);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_SIGNAL_PATH_RESET,(char*) 0);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_USER_CTRL,(char*) 0);

    }

  • eny one have suggestions for clear that?
  • Peter JakackiPeter Jakacki Posts: 8,282
    edited 2018-08-23 - 12:01:34
    I don't think that the busy function is the same thing because when a device does not ack its device address it is because it's busy but when it does respond but you then address an internal register that it still needs time to acquire the sensor data for, then the only way it can arbitrate is to hold the clock from the master low until it is ready. This low level arbitration is transparent to the upper layers so you can't wait for something you can't detect, it just stretches out the time it takes to respond. Therefore you must use a driver that supports arbitration which usually is not required and usually not implemented, or write or modify it yourself.

    BTW, if you post code make sure you apply the code tags (edit icons - B I U S C etc ) so you don't lose any formatting or whitespace to it like this:
    #include "simpletools.h" // Include simpletools header
    // MPU6050 Slave Device Address
    const uint8_t MPU6050SlaveAddress = 0x68;
    
    // sensitivity scale factor respective to full scale setting provided in datasheet
    const uint16_t AccelScaleFactor = 16384;
    const uint16_t GyroScaleFactor = 131;
    
    // MPU6050 few configuration register addresses
    const uint8_t MPU6050_REGISTER_SMPLRT_DIV = 0x19;
    const uint8_t MPU6050_REGISTER_USER_CTRL = 0x6A;
    const uint8_t MPU6050_REGISTER_PWR_MGMT_1 = 0x6B;
    const uint8_t MPU6050_REGISTER_PWR_MGMT_2 = 0x6C;
    const uint8_t MPU6050_REGISTER_CONFIG = 0x1A;
    const uint8_t MPU6050_REGISTER_GYRO_CONFIG = 0x1B;
    const uint8_t MPU6050_REGISTER_ACCEL_CONFIG = 0x1C;
    const uint8_t MPU6050_REGISTER_FIFO_EN = 0x23;
    const uint8_t MPU6050_REGISTER_INT_ENABLE = 0x38;
    const uint8_t MPU6050_REGISTER_ACCEL_XOUT_H = 0x3B;
    const uint8_t MPU6050_REGISTER_SIGNAL_PATH_RESET = 0x68;
    
    void MPU6050_Init();
    void Read_RawValue(uint8_t deviceAddress,uint8_t regAddress);
    void I2C_Write(uint8_t deviceAddress,uint8_t regAddress,char *data);
    
    i2c *eeBus; // I2C bus ID
    char testStr[] = {0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0,0,0};
    int16_t AccelX, AccelY, AccelZ, Temperature, GyroX, GyroY, GyroZ;
    double Ax, Ay, Az, T, Gx, Gy, Gz;
    
    int main() // Main function
    {
    eeBus = i2c_newbus(16,15, 1); // Set up I2C bus, get bus ID;
    //I2C_Write(0x68,0x6b,0);
    //print("done");
    MPU6050_Init();
    while (1){
    Read_RawValue(MPU6050SlaveAddress, MPU6050_REGISTER_ACCEL_XOUT_H);
    //print("testStr = %s \n", testStr); // Display result
    print("Ax: %f",Ax);
    print(" Ay: %f",Ay);
    print(" Az: %f",Az);
    print(" T: %f",T);
    print(" Gx: %f",Gx);
    print(" Gy: %f",Gy);
    print(" Gz: %f",Gz);
    print(" \n ");
    pause(1000);
    }
    
    }
    
    void I2C_Write(uint8_t deviceAddress,uint8_t regAddress,char *data){
    i2c_out(eeBus, deviceAddress,regAddress, 1, data, 1);
    while(i2c_busy(eeBus,deviceAddress));
    }
    
    void Read_RawValue(uint8_t deviceAddress,uint8_t regAddress){
    i2c_in(eeBus, deviceAddress,regAddress, 1, testStr, 14);
    
    AccelX = (((int16_t)testStr[1]<<8) | testStr[2]);
    AccelY = (((int16_t)testStr[3]<<8) | testStr[4]);
    AccelZ = (((int16_t)testStr[5]<<8) | testStr[6]);
    Temperature = (((int16_t)testStr[7]<<8) | testStr[8]);
    GyroX = (((int16_t)testStr[9]<<8) | testStr[10]);
    GyroY = (((int16_t)testStr[11]<<8) | testStr[12]);
    GyroZ = (((int16_t)testStr[13]<<8) | testStr[14]);
    
    //divide each with their sensitivity scale factor
    Ax = (double)AccelX/AccelScaleFactor;
    Ay = (double)AccelY/AccelScaleFactor;
    Az = (double)AccelZ/AccelScaleFactor;
    T = (double)Temperature/340+36.53; //temperature formula
    Gx = (double)GyroX/GyroScaleFactor;
    Gy = (double)GyroY/GyroScaleFactor;
    Gz = (double)GyroZ/GyroScaleFactor;
    
    }
    
    void MPU6050_Init(){
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_SMPLRT_DIV,(char*) 7);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_PWR_MGMT_1,(char*) 1);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_PWR_MGMT_2,(char*) 0);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_CONFIG,(char*) 0);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_GYRO_CONFIG,(char*) 0);//set +/-250 degree/second full scale
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_ACCEL_CONFIG,(char*) 0);// set +/- 2g full scale
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_FIFO_EN,(char*) 0);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_INT_ENABLE,(char*) 1);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_SIGNAL_PATH_RESET,(char*) 0);
    I2C_Write(MPU6050SlaveAddress, MPU6050_REGISTER_USER_CTRL,(char*) 0);
    
    }
    

    Tachyon Forth - compact, fast, forthwright and interactive
    useforthlogo-s.png
    --->CLICK THE LOGO for more links<---
    P2 +++++ TAQOZ INTRO & LINKS +++++ P2 SHORTFORM DATASHEET
    P1 +++++ Latest binary V5.4 includes EASYFILE +++++ Tachyon Forth News Blog
    Brisbane, Australia
Sign In or Register to comment.