TCA9548A multiplexer with Arduino
This is the first time I have setup a MUX system. And I need your help to identify where I am going wrong! Bear with me.
A non-responsive system, I get as far as a serial output up to the first sensor initiation – which fails.
I have individually and successfully tested all sensory systems are working - separate from the MUX setup.
Attached is a GitHub package of the project scope including electrical schematics, Arduino code and pictures.
I have located the addresses of all the devices using the scanner code successfully. As you can see I have connected 3 peripheral devices – clock, compass and pressure sensor. Along with a SD card reader using SPI communications.
I am using 10k pull up resistors to 5v bus line for both the SDA and SCL channels, with Arduino uno.
I have added the code into one repo as there is 400 lines there.
this is a smaller test system of what is to come. I plan to incorporate many more I2c devices through one arduino MEGA.
your help is much appreciated!
// clock channel identify 0x68
// The I2C address of the DS3231 is 0x68. 0x57 is the I2C address of the AT24C32 EEPROM on your ZS-042 RTC module
// Following is for an I2C Multiplexor system.
// Arduino to LCA9548A
// 10k PULL UP RESISTORS
// Using 3 Peripheral I2C channels: 1,2,3
// NOTE: SD writing - working, BMP serial monitor displaying - working, magnetic compass function serial - working 
// INDIVIUDALLY TESTED AND WORKING PERIPHERALS
//
// MAGNETIC COMPASS
//
// magnetic compass x,y,z recordings serial print out + write to SD card
// SD_BMP180_Clock_QMC5583L
#include <SFE_BMP180.h>
#include <Wire.h>
#include <Regexp.h>
SFE_BMP180 pressure;
#define ALTITUDE 10 // Altitude of (Ajax, Ontario, Canada)
////////////////////
#include <Wire.h>
#include <RTC.h>
DS3231 RTC;
#include <SD.h>
#include <SPI.h>
File myFile;
int pinCS = 53; // chip select 53 mega >> 10 uno
int modeState = 1;
// to merge to main code below 
String liveDirectory;
String fileNameAllocation = "dive0.txt";
int logNum = 0;
String logDirectory = "/LOG#1";
int diveNumber = 0;
int logCount = 0;
String liveFullDirectory = "";
#include <QMC5883LCompass.h>
QMC5883LCompass compass;
//#define TotalSamples 100;
/////////////////////////////////////////////////////////////////////  FUNCTION CALLS
void BMP180_check();
void compassCheck();
void writeSD_compassData(int x,int y,int z,String t);
void writeSD_BMP(float temp,float absolutePressure,float computedAltitude);
void logProfileNameAllocation(); // can be created at the initiation of dive arming
void tcaSelect(uint8_t bus);
void instantiateLogNum();
void logProfileNameAllocation();
////////////////////////////////////////////////////////////////////
       
//  TCA9548 module I2C address:  0x70 >> MULTIPLEXOR
//  I2C device found at address 0x0D  ! QMC5883L >> COMPASS
//  I2C device found at address 0x68  ! DS3231 RTC >> CLOCK LINE 
//  I2C device found at address 0x77  ! BMP180 >> PRESSURE BAROMETER
#define addr1   0x68       // CLOCK device 3 (I2C bus 2)
#define addr2   0x0D       // QMC device 1 (I2C bus 1)
#define addr3   0x77       // BMP device 4 (I2C bus 2)
#define TCA_Address 0x70   // address of I2C switch module
#define bus1    1          // CLOCK
#define bus2    2          // COMPASS
#define bus3    3          // BMP
void setup() {
////////////////////////////////////////////////////////////////////////// CLOCK ACTIVATE
  
  
  pinMode (pinCS,OUTPUT); // cs pin needs to be in a low setting for SPI communication to work correctly
  digitalWrite(pinCS, HIGH);
  
  Serial.begin(38400); // serial boot
  delay(200);
  Wire.begin(); // initialize i2c comms
  delay(500);
  Serial.println("PROGRAM LIVE");
  Serial.println("***************************************");
  Serial.println();
  
  tcaSelect(bus1);               // enable I2C channel 1
  
  delay(100);
  
  if (RTC.begin()){
    Serial.println("RTC init success");
  }
  else
  {
    // Oops, something went wrong, this is usually a connection problem,
    // see the comments at the top of this sketch for the proper connections.
    Serial.println("RTC init fail\n\n");
    while(1); // Pause forever.
  }
 
//////////////////////////////////////////////////////////////////////////// COMPASS ACTIVATE
tcaSelect(bus2);               // enable I2C channel 2
    
compass.init();
Serial.println("Compass init success");
//  }
//  else
//  {
//    // Oops, something went wrong, this is usually a connection problem,
//    // see the comments at the top of this sketch for the proper connections.
//
//    Serial.println("Compass init fail\n\n");
//    while(1); // Pause forever.
//  }
  
  compass.setCalibration(-428, 656, -2357, 0, 0, 980);
  Serial.println("Compass Calibration Set");
 
//////////////////////////////////////////////////////////////////////////// BMP180 ACTIVATE - TEMP/PRESSURE
  tcaSelect(bus3);               // enable I2C channel 3
  
  if (pressure.begin()){
    Serial.println("BMP180 init success");
  }
  else
  {
    // Oops, something went wrong, this is usually a connection problem,
    // see the comments at the top of this sketch for the proper connections.
    Serial.println("BMP180 init fail\n\n");
    while(1); // Pause forever.
  }
 
  
//////////////////////////////////////////////////////////////////////////// SPI COMMS, SD INITIALIZE, CS
  
  // pinMode(pinCS, OUTPUT);
  
  // SD Card Initialization
  if (SD.begin())
  {
    Serial.println("SD card is ready to use.");
  } else
  {
    Serial.println("SD card initialization failed");
    return;
  }
////////////////////////////////////////////////// BOOT UP FUNCTIONS - SINGULAR
instantiateLogNum();
logProfileNameAllocation(); // call to scan card if file exists otherwise break and write file as the default setting dive0
} // END OF SETUP ***************************************************************************************************************************************************************
          void loop() {                          
                         
                          compassCheck();
                        
                          BMP180_check();
                        
                          delay(2000); 
          
          }
void instantiateLogNum(){
                        // created only at bootup, as root directory.
                        // traverse log folder directory until the latest can be appended
                       
                        while(SD.exists(logDirectory)) // check if folder structure/ directory exists log
                        {
                                                   
                         logCount++;
                         String logCountCastToString = String(logCount);
                         String logPrefix = "/LOG#";
                         logDirectory = logPrefix + logCountCastToString;
                         Serial.print(logDirectory);
                         
                        }                     
                        
                        SD.mkdir(logDirectory);
                        Serial.println("New Folder Log made: ");
                        Serial.print(logDirectory);
                        Serial.println();
  
}
// running program should save data to live set profile, LOG#1/dive1/dive0.txt >> dive1.txt >> dive2.txt
void logProfileNameAllocation(){ // using SPI comms - command should be called as the dive is armed moments before break-away.
                          
                       // see if the directory exists, create it if not. construct from the live dive profile denotation
                        String mScast = String(modeState); // convert into string
                        
                        liveDirectory = logDirectory + "/diveProfile" + mScast; // >> /LOG#1/diveProfile1
                                                  
                        if(!SD.exists(liveDirectory)) // check if folder structure/ directory exists
                        {
                          if(SD.mkdir(liveDirectory)){
                            Serial.print("Directory Created: ");
                            Serial.print(liveDirectory);                      
                          }
                        }
                        else {
                                      ("path already exists, directory not created");
                                  }                        
                                 liveFullDirectory = liveDirectory  + "/" + fileNameAllocation; // >> /LOG#1/diveProfile1/dive0.txt
                                 
                                 while(SD.exists(liveFullDirectory))  {
                                        diveNumber ++;        
                                        String diveNumberString = String(diveNumber);
                                        fileNameAllocation = "dive" + diveNumberString + ".txt"; // concatanate an iteration one up from the existing global scoped variable/existing file
                                        liveFullDirectory = liveDirectory + "/" + fileNameAllocation;
                                        
                                        }                   
                                                                              
                                                                                                                   
                                                          myFile = SD.open(liveFullDirectory, FILE_WRITE);
                                                                              if (myFile) { 
                                                                                myFile.print("\n\n"); 
                                                                                myFile.print("New File: ");
                                                                                myFile.print(fileNameAllocation);    
                                                                                Serial.println();
                                                                                Serial.println("***************************************");
                                                                                Serial.println("Success >> New Log text printed");                                    
                                                                                myFile.close(); // close the file
                                                                                
                                                                                                              }       
                                                                                                              else {
                                                                                                                            Serial.println("error opening SD file");
                                                                                                                          }
                                                                                                                                   
}
// **********************************************************************************************************************************************************************
void tcaSelect(uint8_t bus) {
  
              if (bus > 7) return;
              Wire.beginTransmission(TCA_Address);
              Wire.write(1 << bus);
              Wire.endTransmission();
              Serial.print("bus live: ");
              Serial.print(bus);
              Serial.println();
  
}
void compassCheck(){
           tcaSelect(bus1);               // enable I2C channel 1, busline switch to clockline function call
                                                                                        
                                                          String absoluteTime = ""; 
                                                         
                                                          absoluteTime = absoluteTime + RTC.getHours() + ":" +  RTC.getMinutes()+ ":" + RTC.getSeconds();
                                                          Serial.println();
                                                          Serial.print("Time: ");
                                                          Serial.println(absoluteTime);
            tcaSelect(bus2);               // enable I2C channel 2
                    
            int compass_x, compass_y, compass_z, a, b;
            char myArray[3];
          
            compass.read();
            Serial.println();
            compass_x = compass.getX();
            compass_y = compass.getY();
            compass_z = compass.getZ();
            Serial.print("X: ");
            Serial.print(",");
            Serial.print(compass_x);
            Serial.print(",");
            Serial.print(" Y: ");
            Serial.print(compass_y);
            Serial.print(",");
            Serial.print(" Z: ");
            Serial.print(compass_z);
            
            a = compass.getAzimuth();
            b = compass.getBearing(a);
            compass.getDirection(myArray, a);
            
                                                Serial.println();
                                                Serial.print("Azimuth: ");
                                                Serial.print(a);
                                                Serial.println();
                                                Serial.print("Bearing: ");
                                                Serial.print(b);
                                                Serial.println();
                                                Serial.print("Direction: ");
                                                Serial.print(myArray[0]);
                                                Serial.print(myArray[1]);
                                                Serial.print(myArray[2]);                                              
                                                Serial.println();
                                                /////////////////////////////////////////
                                                writeSD_compassData(compass_x,compass_y,compass_z,absoluteTime);
                                                                                        
}
  
  
void writeSD_compassData(int x,int y,int z,String t){
                                    Serial.print("write to directory: ");
                                    Serial.print(liveFullDirectory);
                                    Serial.println();
                                    myFile = SD.open(fileNameAllocation, FILE_WRITE);
                                    if (myFile) {  
                                      
                                                    myFile.println();
                                                    myFile.print("X: ");
                                                    myFile.print(",");
                                                    myFile.print(x);
                                                    myFile.print(",");
                                                    myFile.print(" Y: ");
                                                    myFile.print(",");
                                                    myFile.print(y);
                                                    myFile.print(" Z: ");
                                                    myFile.print(",");
                                                    myFile.print(z);
                                                    myFile.println();
                                                    myFile.print("Time: ");
                                                    myFile.print(t);
                                                    Serial.println();
                                                    
                                                    Serial.println("Success >> Compass data write to card");
                                                    
                                    myFile.close(); // close the file
                                                    }
                                                                                                              // if the file didn't open, print an error:
                                                                            else {
                                                                              Serial.println("error opening SD file");
                                                                            }
}
void BMP180_check(){
  tcaSelect(bus3);               // enable I2C channel 3
 
  char status;
  double T,P,p0,J;
  // Loop here getting pressure readings every 10 seconds.
  // If you want sea-level-compensated pressure, as used in weather reports,
  // you will need to know the altitude at which your measurements are taken.
  // We're using a constant called ALTITUDE in this sketch:
  
  Serial.println();
  Serial.print("provided altitude: ");
  Serial.print(ALTITUDE,0);
  Serial.print(" meters, ");
  Serial.print(ALTITUDE*3.28084,0);
  Serial.println(" feet");
  
  // If you want to measure altitude, and not pressure, you will instead need
  // to provide a known baseline pressure. This is shown at the end of the sketch.
  // You must first get a temperature measurement to perform a pressure reading.
  
  // Start a temperature measurement:
  // If request is successful, the number of ms to wait is returned.
  // If request is unsuccessful, 0 is returned.
  status = pressure.startTemperature();
  if (status != 0)
  {
    // Wait for the measurement to complete:
    delay(status);
    // Retrieve the completed temperature measurement:
    // Note that the measurement is stored in the variable T.
    // Function returns 1 if successful, 0 if failure.
    status = pressure.getTemperature(T);
    if (status != 0)
    {
      // Print out the measurement:
      Serial.print("temperature: ");
      Serial.print(T,2);
      Serial.print(" deg C, ");
      Serial.print((9.0/5.0)*T+32.0,2);
      Serial.println(" deg F");
      
      // Start a pressure measurement:
      // The parameter is the oversampling setting, from 0 to 3 (highest res, longest wait).
      // If request is successful, the number of ms to wait is returned.
      // If request is unsuccessful, 0 is returned.
      status = pressure.startPressure(3);
      if (status != 0)
      {
        // Wait for the measurement to complete:
        delay(status);
        // Retrieve the completed pressure measurement:
        // Note that the measurement is stored in the variable P.
        // Note also that the function requires the previous temperature measurement (T).
        // (If temperature is stable, you can do one temperature measurement for a number of pressure measurements.)
        // Function returns 1 if successful, 0 if failure.
        status = pressure.getPressure(P,T);
        if (status != 0)
        {
          // Print out the measurement:
          Serial.print("absolute pressure: ");
          Serial.print(P,2);
          Serial.print(" mb, ");
          Serial.print(P*0.0295333727,2);
          Serial.println(" inHg");
          // The pressure sensor returns abolute pressure, which varies with altitude.
          // To remove the effects of altitude, use the sealevel function and your current altitude.
          // This number is commonly used in weather reports.
          
          // Parameters: P = absolute pressure in mb, ALTITUDE = current altitude in m.
          // Result: p0 = sea-level compensated pressure in mb
          p0 = pressure.sealevel(P,ALTITUDE); // we're at 90 meters (Boulder, CO)
          Serial.print("relative (sea-level) pressure: ");
          Serial.print(p0,2);
          Serial.print(" mb, ");
          Serial.print(p0*0.0295333727,2);
          Serial.println(" inHg");
          // On the other hand, if you want to determine your altitude from the pressure reading,
          // use the altitude function along with a baseline pressure (sea-level or other).
          
          // Parameters: P = absolute pressure in mb, p0 = baseline pressure in mb.
          // Result: a = altitude in m.
          J = pressure.altitude(P,p0);
          Serial.print("computed altitude: ");
          Serial.print(J,0);
          Serial.print(" meters, ");
          Serial.print(J*3.28084,0);
          Serial.println(" feet");
        }
        else Serial.println("error retrieving pressure measurement\n");
      }
      else Serial.println("error starting pressure measurement\n");
    }
    else Serial.println("error retrieving temperature measurement\n");
  }
  else Serial.println("error starting temperature measurement\n");
writeSD_BMP(T,P,J);
}
void writeSD_BMP(float temp,float absolutePressure,float computedAltitude){
                                    myFile = SD.open(fileNameAllocation, FILE_WRITE);
                                    if (myFile) {  
                                      
                                                    myFile.println();
                                                    myFile.print("Temperature: ");
                                                    myFile.print(temp);
                                                    myFile.print(",");
                                                    myFile.print(" Absolute Pressure: ");
                                                    myFile.print(absolutePressure);
                                                    myFile.print(",");
                                                    myFile.print(" Computed Altitude: ");
                                                    myFile.print(computedAltitude);
                                                    Serial.println();
                                                    
                                                    Serial.println("Success >> BMP data write to card");
                                                    
                                    myFile.close(); // close the file
                                                    }
                                                                                                              // if the file didn't open, print an error:
                                                                            else {
                                                                              Serial.println("error opening SD file");
                                                                            }
  
}
Sketch uses 26640 bytes (10%) of program storage space. Maximum is 253952 bytes.
Global variables use 2292 bytes (27%) of dynamic memory, leaving 5900 bytes for local variables. Maximum is 8192 bytes.