Need arduino I2C Bitbang for mpu6050 for W806 - Solved

Koepel ,

Tried your Lowire code :

https://wokwi.com/projects/355936784151680001

Modified to Code below o compile under W806 on arduino IDE :

  • but this version does not work - just spits back lines of 0x00 ....
/*

 : W806_I2C_BitBang_arduino_mpu6050_hmc5883.ino :

 - compiles on Arduino IDS for W806 chips.

 - This is the master controller for the Mpu6050 & Hmc5883 chips. 

 - This uses the I2S protocol
    using raw bit bang low-level code. 

*/

//

#include <Arduino.h>

#include <stdio.h>
#include <stdlib.h>

//

 // #define USE_ARDUINO_E  1 
#ifdef  USE_ARDUINO_E7 
  #define  SDA  A4
  #define  SCL  A5
#else
  #define  SDA  4
  #define  SCL  1
#endif

//

/// Enable I2C DEVICES : ///
 //// #define  DS1307_E   1
 #define  MPU6050_E   1
 #define  HMC5883_E   1


/// I2C DEVICE ADDRESSES : ///

//#define  DS1307_ADDR_R  = 0xD1 ;  // the DS1307 7-bit address 1101000 with READ  bit (1) = 11010001 = D1
//#define  DS1307_ADDR_W  = 0xD0 ;  // DS1307   : xD0 = b 1101 0000 == (MPU6050  : x68 = b 0110 1000 <<1) 
#define    DS1307_ADDR      0xD0    // DS1307   : xD0 = b 1101 0000 

//#define  MPU6050_ADDR_R = 0x69 ;  // MPU6050 
//#define  MPU6050_ADDR_W = 0x68 ;  // MPU6050  : x68 = b 0110 1000
// #define  MPU6050_ADDR_W = (0x68 <<1) ;  // MPU6050  : 0xD0 = b 1101 0000  // - ??? 
#define    MPU6050_ADDR     (0x68)    // MPU6050 
#define    MPU6050_ADDR_2   (0x69)    // MPU6050 

//#define  HMC5883_ADDR_R = 0x1F ;  // HMC5883L 
//#define  HMC5883_ADDR_W = 0x1E ;  // HMC5883L : x1E = b 0001 1110
// #define  HMC5883_ADDR_W = (0x1E <<1) ;  // HMC5883L  : x3C = b 0011 1100  // - ??? 
#define    HMC5883_ADDR     (0x1E)    // HMC5883L  


/// Set Current Device ADDRESS Function : ///
#define  DeviceSet(D)  (CHIP_ADDR=(D << 1)) 

//

 uint8_t  CHIP_ADDR = 0              ;
 // uint8_t  CHIP_ADDR = DS1307_ADDR_W  ;
// uint8_t  CHIP_ADDR = MPU6050_ADDR_W ;
// uint8_t  CHIP_ADDR = HMC5883_ADDR_W ;

//

int32_t  AcX, AcY, AcZ,  Tmp,  GcX, GcY, GcZ ;

int cX,cY,cZ; //triple axis data
// int xmin,xmax,ymin,ymax,zmin,zmax;

int  Id ;

//


#define  MSBFIRST  81 
#define  LSBFIRST  18 
//// shiftOut(SDA, SCL, MSBFIRST, value); : ////
void shiftOut(int datpin, int clkpin, int dir, int val) 
{
  // pinMode(datpin, OUTPUT);

  if( dir == MSBFIRST )
  {
    // MSBFIRST : send out the 8 bits 
    for (int i=7; i>=0; i--) 
    {
      digitalWrite(clkpin, LOW);
       digitalWrite(datpin, bitRead(val,i));
/*
       if(bitRead(val,i))
         pinMode(datpin,INPUT_PULLUP)
       else
       {
         pinMode(datpin,OUTPUT);
         digitalWrite(datpin, HIGH);
       }
*/
      digitalWrite(clkpin, HIGH);
    }
  }
  else  
  {
    // LSBFIRST : send out the 8 bits 
    for (int i=0; i<=7; i++) 
    {
      digitalWrite(clkpin, LOW);
       digitalWrite(datpin, bitRead(val,i));
/*
       if(bitRead(val,i))
         pinMode(datpin,INPUT_PULLUP)
       else
       {
         pinMode(datpin,OUTPUT);
         digitalWrite(datpin, LOW);
       }
*/
      digitalWrite(clkpin, HIGH);
    }
  }
  
  digitalWrite(clkpin, LOW); // must have this last LOW
}


void sendStart(byte addr) 
{
  pinMode(SDA, OUTPUT);
  digitalWrite(SDA, HIGH);
  digitalWrite(SCL, HIGH);
  digitalWrite(SDA, LOW);  

  // send out the 8 bits
  for(int i=7; i>=0; i-- ) 
  {
    digitalWrite(SCL, LOW);
    digitalWrite(SDA, bitRead(addr,i) );
/*
       if(bitRead(val,i))
         pinMode(SDA,INPUT_PULLUP)
       else
       {
         pinMode(SDA,OUTPUT);
         digitalWrite(SDA, LOW);
       }
*/
    digitalWrite(SCL, HIGH);
  }
  
  digitalWrite(SCL, LOW); // must have this last LOW
}


void sendStart_BitStream(byte addr) 
{
  pinMode(SDA, OUTPUT);
  digitalWrite(SDA, HIGH);
  digitalWrite(SCL, HIGH);
  digitalWrite(SDA, LOW);  


  // send out the 8 bits :
  digitalWrite(SCL, LOW);
  digitalWrite(SDA, bitRead(addr,7));
  digitalWrite(SCL, HIGH);

  digitalWrite(SCL, LOW);
  digitalWrite(SDA, bitRead(addr,6));
  digitalWrite(SCL, HIGH);

  digitalWrite(SCL, LOW);
  digitalWrite(SDA, bitRead(addr,5));
  digitalWrite(SCL, HIGH);

  digitalWrite(SCL, LOW);
  digitalWrite(SDA, bitRead(addr,4));
  digitalWrite(SCL, HIGH);

  digitalWrite(SCL, LOW);
  digitalWrite(SDA, bitRead(addr,3));
  digitalWrite(SCL, HIGH);

  digitalWrite(SCL, LOW);
  digitalWrite(SDA, bitRead(addr,2));
  digitalWrite(SCL, HIGH);

  digitalWrite(SCL, LOW);
  digitalWrite(SDA, bitRead(addr,1));
  digitalWrite(SCL, HIGH);

  digitalWrite(SCL, LOW);
  digitalWrite(SDA, bitRead(addr,0));
  digitalWrite(SCL, HIGH);

  digitalWrite(SCL, LOW); // must have this last LOW
}


// this also works using the shiftOut command
void sendStart_works(byte addr) 
{
   pinMode(SDA, OUTPUT);
   
   digitalWrite(SDA, HIGH);
  digitalWrite(SCL, HIGH);
   digitalWrite(SDA, LOW);
  digitalWrite(SCL, LOW);

  shiftOut(SDA, SCL, MSBFIRST, addr);   // send out the 8 bits
}


void sendStop() 
{
   pinMode(SDA, OUTPUT);
   
   digitalWrite(SDA, LOW);
  digitalWrite(SCL, HIGH);
   digitalWrite(SDA, HIGH);
   
   pinMode(SDA, INPUT);
}


void sendNack() 
{
   pinMode(SDA, OUTPUT);
  digitalWrite(SCL, LOW);
   digitalWrite(SDA, HIGH);
  digitalWrite(SCL, HIGH);
  digitalWrite(SCL, LOW);
   pinMode(SDA, INPUT);
}


void sendAck() 
{
   pinMode(SDA, OUTPUT);
  digitalWrite(SCL, LOW);
   digitalWrite(SDA, LOW);
  digitalWrite(SCL, HIGH);
  digitalWrite(SCL, LOW);
   pinMode(SDA, INPUT);
}


byte waitForAck()   // - getAck() ??? 
{
   pinMode(SDA, INPUT);
  digitalWrite(SCL, HIGH);

byte ack = digitalRead(SDA);  //ACK bit should be LOW

  digitalWrite(SCL, LOW);
return ack;
}


byte readByte() 
{
  pinMode(SDA, INPUT);
byte value = 0;
byte currentBit = 0;

  for (int i = 0; i < 8; ++i) 
  {
    digitalWrite(SCL, HIGH);

    currentBit = digitalRead(SDA);
    value |= (currentBit << 7-i);

    delayMicroseconds(1);

    digitalWrite(SCL, LOW);
  }
return value;
}


void writeByte(byte value) 
{
  pinMode(SDA, OUTPUT);

  // send out the 8 bits
  for (int i=7; i>=0; i--) 
  {
    digitalWrite(SCL, LOW);
     digitalWrite(SDA, bitRead(value,i));
    digitalWrite(SCL, HIGH);
  }
  
  digitalWrite(SCL, LOW); // must have this last LOW
}


// this also works using the shiftOut command
void writeByte_2(byte value) 
{
  pinMode(SDA, OUTPUT);
  shiftOut(SDA, SCL, MSBFIRST, value);
}


byte readRegister(byte reg) 
{
byte readValue=0;

  sendStart( CHIP_ADDR ); // set write mode
  waitForAck();

  writeByte(reg);           // send register address to read from
  waitForAck();

  sendStop();
  sendStart( CHIP_ADDR | 0x01 ); // change to read mode
  waitForAck();

  readValue = readByte();   // read data from register
  sendNack();
  sendStop();

return readValue;
}


void writeRegister(byte reg, byte value) 
{
  sendStart( CHIP_ADDR );
  waitForAck();

  writeByte(reg);   // send register address
  waitForAck();

  writeByte(value); // send data to store in register
  waitForAck();

  sendStop();
}

byte decToBcd(byte val) 
{
  return ((val/10*16) + (val%10));
}
byte bcdToDec(byte val) 
{
  return ((val/16*10) + (val%16));
}


//

void setup() 
{
#ifdef  USE_ARDUINO_E 
 Serial.begin(9600);
#endif

  pinMode(SCL, OUTPUT);
  //pinMode(SDA, OUTPUT); // set in the low-level functions

  //

#ifdef  DS1307_E   
 Serial.println("DS1307");
//   CHIP_ADDR = DS1307_ADDR_W ;
  DeviceSet( DS1307_ADDR );

  writeRegister(0x00,0x00); // set the seconds register
                            // note: reset bit 7 of register 0 to 0 to enable the clock
  writeRegister(0x01,decToBcd(15)); // set the minutes register
  writeRegister(0x02,decToBcd(8)); // set the hours register
  writeRegister(0x07,0x10); // set control register to enable SQW to 1Hz output
 Serial.println(freadRegister(0x07));
#endif

  //

#ifdef  MPU6050_E   
 printf(": MP6050 :\r\n");
//   CHIP_ADDR = MPU6050_ADDR_W ;
 // CHIP_ADDR = DS1307_ADDR_W ;  // -??? 
  DeviceSet( MPU6050_ADDR );
  
  writeRegister(0x6B,0x00); // PWR_MGMT_1 register , set to zero (wakes up the MPU-6050) 
 printf( "%02X \n" , readRegister(0x75) );
#endif

  //

#ifdef  HMC5883_E   
 printf(": HMC5883 :\r\n");
//   CHIP_ADDR = HMC5883_ADDR_W ;
  DeviceSet( HMC5883_ADDR );

  writeRegister(0x02,0x00); //select mode register - continuous measurement mode
#endif

  //

 // #define SNOOP_E  1 
#ifdef  SNOOP_E
 printf(": I2C Snoop : \r\n");
  for(int i=0x00; i<=0xFF; i+=1)
  {
    CHIP_ADDR = ( i ) ;
   printf( "* dvc%02X: r%02X = %02X  ,"   , i , 0    , readRegister(0)    );
   printf( "  dvc%02X: r%02X = %02X \r\n" , i , 0x75 , readRegister(0x75) );
   
    if( readRegister(0) != 0xFF )
    {
      for(int j=0x00; j<=0xFF; j+=1)
      {
        CHIP_ADDR = ( i ) ;
       printf( " %02X ," , readRegister(j)    );
      }
      printf("\r\n");
    }
  }
#endif

  //

 printf( "\r\n" );
}


void loop() 
{

  //

#ifdef  DS1307_E   
 printf("%d ",bcdToDec(readRegister(2)));
 printf(":");
 printf("%d ",bcdToDec(readRegister(1)));
 printf(":");
 printf("%d \n",bcdToDec(readRegister(0)));
#endif

  //

#ifdef  MPU6050_E   
//   CHIP_ADDR = MPU6050_ADDR_W ;
  DeviceSet( MPU6050_ADDR );
  
  writeRegister(0x6B,0x00); // PWR_MGMT_1 register , set to zero (wakes up the MPU-6050) 

  Id = readRegister(0x75);
 printf( " Id=%0X "   , Id );

 // #define PRT_REGS_1  1 
#ifdef  PRT_REGS_1 
 printf( "%02X" ,  readRegister(0x3B) );
 printf( "%02X " ,  readRegister(0x3C) );
 printf( "%02X" ,  readRegister(0x3D) );
 printf( "%02X " ,  readRegister(0x3E) );
 printf( "%02X" ,  readRegister(0x3F) );
 printf( "%02X " ,  readRegister(0x40) );
 printf( "%02X" ,  readRegister(0x41) );
 printf( "%02X " ,  readRegister(0x42) );
 printf( "%02X" ,  readRegister(0x43) );
 printf( "%02X " ,  readRegister(0x44) );
 printf( "%02X" ,  readRegister(0x45) );
 printf( "%02X " ,  readRegister(0x46) );
 printf( "%02X" ,  readRegister(0x47) );
 printf( "%02X \r\n" ,  readRegister(0x48) );
#endif

  AcX = readRegister(0x3B)<<8 | readRegister(0x3C) ;  // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)    
  AcY = readRegister(0x3D)<<8 | readRegister(0x3E) ;  // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
  AcZ = readRegister(0x3F)<<8 | readRegister(0x40) ;  // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
  Tmp = readRegister(0x41)<<8 | readRegister(0x42) ;  // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
  GcX = readRegister(0x43)<<8 | readRegister(0x44) ;  // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
  GcY = readRegister(0x45)<<8 | readRegister(0x46) ;  // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
  GcZ = readRegister(0x47)<<8 | readRegister(0x48) ;  // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

  AcX = ( (AcX >= 0x8000) ? (AcX = AcX - 0x10000) : (AcX = AcX) );
  AcY = ( (AcY >= 0x8000) ? (AcY = AcY - 0x10000) : (AcY = AcY) );
  AcZ = ( (AcZ >= 0x8000) ? (AcZ = AcZ - 0x10000) : (AcZ = AcZ) );
  Tmp = Tmp ;
  GcX = ( (GcX >= 0x8000) ? (GcX = GcX - 0x10000) : (GcX = GcX) );
  GcY = ( (GcY >= 0x8000) ? (GcY = GcY - 0x10000) : (GcY = GcY) );
  GcZ = ( (GcZ >= 0x8000) ? (GcZ = GcZ - 0x10000) : (GcZ = GcZ) );

 // #define PRT_REGS_2  1 
#ifdef  PRT_REGS_2 
 printf( "aX=%04X  "   , AcX & 0xFFFF );
 printf( "aY=%04X  "   , AcY & 0xFFFF );
 printf( "aZ=%04X    " , AcZ & 0xFFFF );
 printf( "(T=%fC"       , (Tmp / 340.00) + 36.53 );
 printf( "=%fF)    "    , ((Tmp / 340.00 + 36.53) * (9.0/5.0) + 32.0) );
 printf( "gX=%04X  "   , GyX & 0xFFFF );
 printf( "gY=%04X  "   , GyY & 0xFFFF );
 printf( "gZ=%04X  "   , GyZ & 0xFFFF );
 printf( "\r\n" );
#endif

 printf( "aX=%d  "     , AcX );
 printf( "aY=%d  "     , AcY );
 printf( "aZ=%d    "   , AcZ );
 printf( "T=%fC"       , (Tmp / 340.00) + 36.53 );
 printf( "=%fF    "    , ((Tmp / 340.00 + 36.53) * (9.0/5.0) + 32.0) );
 printf( "gX=%d  "   ,   GcX );
 printf( "gY=%d  "   ,   GcY );
 printf( "gZ=%d  "   ,   GcZ );
 printf( "\r\n" );
#endif

  //

#ifdef  HMC5883_E   

//   CHIP_ADDR = HMC5883_ADDR_W ;
  DeviceSet( HMC5883_ADDR );

 // #define SNOOP_DVC_E  1 
#ifdef  SNOOP_DVC_E 
 printf(": I2C Snoop : \r\n");
  for(int i=0x01; i<=0xFF; i+=2)
  {
    CHIP_ADDR = ( HMC5883_ADDR ) ;
   printf( "* %02X  ," , readRegister(i)    );
  }
 printf("\r\n");
#endif

  
 // CHIP_ADDR = HMC5883_ADDR_W ;
  DeviceSet( HMC5883_ADDR );

  Id = readRegister(0x75);
 printf( " Id=%0X "   , Id );

  writeRegister(0x02,0x00); //select mode register - continuous measurement mode

 // #define PRT_REGS_3  1 
#ifdef  PRT_REGS_3 
 printf( "%02X" ,  readRegister(0x03) );
 printf( "%02X " ,  readRegister(0x04) );
 printf( "%02X" ,  readRegister(0x05) );
 printf( "%02X " ,  readRegister(0x06) );
 printf( "%02X" ,  readRegister(0x07) );
 printf( "%02X " ,  readRegister(0x08) );
#endif

  cX = readRegister(0x03)<<8 | readRegister(0x04) ; 
  cZ = readRegister(0x05)<<8 | readRegister(0x06) ; 
  cY = readRegister(0x07)<<8 | readRegister(0x08) ; 

  cX = ( (cX >= 0x8000) ? (cX = cX - 0x10000) : (cX = cX) );
  cY = ( (cY >= 0x8000) ? (cY = cY - 0x10000) : (cY = cY) );
  cZ = ( (cZ >= 0x8000) ? (cZ = cZ - 0x10000) : (cZ = cZ) );

 // #define PRT_REGS_4  1 
#ifdef  PRT_REGS_4 
 printf( "  cX=%04X  " , cX & 0xFFFF );
 printf( "cY=%04X  "   , cY & 0xFFFF );
 printf( "cZ=%04X  "   , cZ & 0xFFFF );
// printf( "\r\n" );
#endif

 printf( "  cX=%d  " , cX  );
 printf( "cY=%d  "   , cY  );
 printf( "cZ=%d  "   , cZ  );
 printf( "\r\n" );
#endif

  //


  /// PCA965 : ///

 // #define  PCA9685_E  1 
#ifdef  PCA9685_E 
/*
  x00  Mode1
  x01  Mode2
  x02  SubAdr1
  x03  SubAdr2
  x04  SubAdr3
  x05  AllCallAdr
  x06  Led0_ON_L    // 0 to 4095
  x07  Led0_ON_H    // ...
  x08  Led0_OFF_H   // 0 to 4095
  x09  Led0_OFF_H   // ...
  ...  
  x42  Led15_ON_L
  x43  Led15_ON_H
  x44  Led15_OFF_L
  x45  Led15_OFF_H
  ...  
  xFA  ALL_Led_ON_L
  xFB  ALL_Led_ON_H
  xFC  ALL_Led_OFF_L
  xFD  ALL_Led_OFF_H
  xFE  PreScale    // - prescale_value = round( clock_rate/(4096 * update_rate ) – 1
  xFF  TestMode
*/

    ////i2c_init(i2c_freq);                 //Initializing I2C communication at 100KHz

    i2c_start();                        //Start signal
    i2c_write(pca_addr=0x40);           //Specifying slave address in write mode
    i2c_write(0x00);                    //Control register set to address 00h
    i2c_write(0x21);                    //Mode 1 configured to with AI=1 and ALLCALL=1
    i2c_stop();                         //Stop signal

    /// PRE_SCALE register 
    ///  is hardware limited to have a minimum value of 3 (03h) and a maximum value of 255 (FFh). 
    ///  Thus using the 25MHz internal oscillator, 
    ///   the maximum value of update_rate is 1526 Hz (prescale_value=0x03h) 
    ///   and the minimum value of update_rate is 24 Hz (prescale_value=0xFFh).
    ///  By default, the PRE_SCALE register is loaded with the value 30 (0x1Eh) 
    ///   giving us an update_rate of 200 Hz with the 25MHz internal oscillator.

    /// Delay = 10% of 4096 = 409.6 ~ 410.
    ///  Count starts from 0 to 4095 (must be subtracted by 1), so ON count = 409 = 0x199h.
    ///  Thus, LED0_ON_H = 0x01h and LED_ON_L = 0x99h
    on_count  = 0x0199 ;
    /// Duty cycle = 30% of 4096 = 1228.8 ~ 1229
    ///  So OFF count = Delay + Duty cycle = 409 + 1229 = 1638 = 0x666h
    ///  Thus, LED0_OFF_H = 0x06h and LED_OFF_L = 0x66h
    off_count = 0x0666h ;
    i2c_start();                        //Start signal
    i2c_write(pca_addr=0x40);           //Specifying slave address in write mode
    i2c_write(((ledn=0x00)*4)+6);       //Control register set to address LEDn_ON_L
    i2c_write(on_count&0xFF);           //Writing 8 LSB bits of ON count
    i2c_write((on_count&0xF00)>>8);     //Writing 4 MSB bits of ON count
    i2c_write(off_count&0xFF);          //Writing 8 LSB bits of OFF count
    i2c_write((off_count&0xF00)>>8);    //Writing 4 MSB bits of ON count    
    i2c_stop();                         //Stop signal

  //

  #define  I2CAdd 0x40
  /// ... 
  #define  I2CAdd 0x7F
  HCPCA9685 HCPCA9685(I2CAdd);

  HCPCA9685.Init(SERVO_MODE);
  HCPCA9685.Sleep(false);  // Wakeup 
  
  Adafruit_PWMServoDriver pwm1 = Adafruit_PWMServoDriver(0x40);

  pwm.setPWMFreq(1000)

  pulselength = map(degrees, 0, 180, SERVOMIN, SERVOMAX);
  pwm.setPWM(15, 1024, 3072)


  pwm.setPWM(pin, 4096, 0);  // PON 

  pwm.setPWM(pin, 0, 4096);  // POFF 


  HCPCA9685.Servo(1, Pos);


#endif

  //

 printf( "\r\n" );

  HAL_Delay(500);
}

///

This code does not work (I compiled and flashed it repeatedly)

  • it just spits back lines of 0x00 ....
    When (I reverted back to my Bitbang earlier - it worked again)