SD data logging for RGB sensors not working with multiplexer

Hi. I've been trying to get 8 Adafruit RGB Sensors (TCS34725) to simultaneously log data to an SD card using an Adafruit multiplexer (TCA9548A) and an Arduino mini pearl data logger. When one sensor is directly connected to the data logger, I can get data written to the SD card a couple times a second. However, when I try to use a multiplexer and multiple sensors, with code modified to try and allow this, no data is written at all. When directly connected to a computer and sensor outputs are printed to serial monitor, the data is displayed with no issues. It's just when writing to the SD card that the issue occurs.

The wiring for the mini pearl data logger is exactly as in this schematic; the VCC, GND, SDA, and SCL pins for the real time clock are connected to the multiplexer. The 8 RGB sensors' 3V3 and GND pins are also connected to the VCC and GND pins of the multiplexer, and the sensors' SDA and SCL pins are wired to the corresponding pins on the multiplexer.

I am a relative novice to Arduino programming and so I modified the example code that is provided for the mini pearl data logger to try to function with the multiplexer. I believe this is where the error is coming from. This modified code is pasted below.

#include <SPI.h>
#include <Wire.h>
#include <SdFat.h>                           // https://github.com/greiman/SdFat/
#include <RTClib.h>                          // https://github.com/adafruit/RTClib/     
#include "Adafruit_TCS34725.h"
RTC_DS3231 RTC;                              // RTC will be the RTC_DS3231 object
#define DS3231_I2C_ADDRESS 0x68              // RTC address
#define donePin  A3                          // This pin signals to the TPL51100 to cut power
#define TCAADDR 0x70                         //multiplexer

Adafruit_TCS34725 tcs1 = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_614MS, TCS34725_GAIN_1X);
Adafruit_TCS34725 tcs2 = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_614MS, TCS34725_GAIN_1X);
Adafruit_TCS34725 tcs3 = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_614MS, TCS34725_GAIN_1X);
Adafruit_TCS34725 tcs4 = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_614MS, TCS34725_GAIN_1X);
Adafruit_TCS34725 tcs5 = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_614MS, TCS34725_GAIN_1X);
Adafruit_TCS34725 tcs6 = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_614MS, TCS34725_GAIN_1X);
Adafruit_TCS34725 tcs7 = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_614MS, TCS34725_GAIN_1X);
Adafruit_TCS34725 tcs8 = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_614MS, TCS34725_GAIN_1X);

SdFat SD;                                    // SD will be the SdFat object
#define MOSIpin 11                           // for SD card
#define MISOpin 12                           // for SD card
char TmeStrng[] = "0000/00/00,00:00:00";     // string template for RTC time stamp
                                             // variables for the RTC:
float rtcTemp;   
float rtcTempC;      
byte tMSB = 0;
byte tLSB = 0; 

// Helper function for changing TCA output channel
void tcaselect(uint8_t channel) {
  if (channel > 7) return;
  Wire.beginTransmission(TCAADDR);
  Wire.write(1 << channel);
  Wire.endTransmission();  
}

void setup() { 
  pinMode(donePin, OUTPUT);                // This pin sends output to the TPL5110 timer to cut power
  digitalWrite(donePin, LOW);              // LOW until its time to cut power
  Serial.begin(9600);                      // Open serial communications
  Wire.begin();                            // initialize the I2C interface
  RTC.begin();                             // initialize the RTC  

  if (!SD.begin(10)) {                     // initialize the SD card
    Serial.println("No SD card");
    return;
    }
    else
    {
    Serial.println("SD OK");
    }
       /*     
       Set the RTC time to the time this sketch was last compiled. Uncomment the following line. 
       Load the sketch onto the logger (using the Arduino IDE which compiles the sketch).
       Must then immediately comment out the line and reload or the RTC time will be wrong:
       */
  //RTC.adjust(DateTime((__DATE__), (__TIME__)));
  
  //initialize sensor 1 
  tcaselect(0);      // TCA channel for bme1
  if (tcs1.begin(0x29))   // address = 0x29 
  {
    Serial.println("Found sensor 1");
  } 
  else 
  {
    Serial.println("No TCS34725 1 found ... check your connections");
    while (1);
  }     

  //initialize sensor 2 ... and so on
  tcaselect(1);      // TCA channel for bme2
  if (tcs2.begin(0x29))   // address = 0x29 
  {
    Serial.println("Found sensor 2");
  } 
  else 
  {
    Serial.println("No TCS34725 2 found ... check your connections");
    while (1);
  }     
  
  tcaselect(2);
  if (tcs3.begin(0x29))   // address = 0x29 
  {
    Serial.println("Found sensor 3");
  } 
  else 
  {
    Serial.println("No TCS34725 3 found ... check your connections");
    while (1);
  }     
  
  tcaselect(3);
  if (tcs4.begin(0x29))   // address = 0x29 
  {
    Serial.println("Found sensor 4");
  } 
  else 
  {
    Serial.println("No TCS34725 4 found ... check your connections");
    while (1);
  }     
  
  tcaselect(4);
  if (tcs5.begin(0x29))   // address = 0x29 
  {
    Serial.println("Found sensor 5");
  } 
  else 
  {
    Serial.println("No TCS34725 5 found ... check your connections");
    while (1);
  }   
    
  tcaselect(5);
  if (tcs6.begin(0x29))   // address = 0x29 
  {
    Serial.println("Found sensor 6");
  } 
  else 
  {
    Serial.println("No TCS34725 6 found ... check your connections");
    while (1);
  } 
      
  tcaselect(6);
  if (tcs7.begin(0x29))   // address = 0x29 
  {
    Serial.println("Found sensor 7");
  } 
  else 
  {
    Serial.println("No TCS34725 7 found ... check your connections");
    while (1);
  }   
    
  tcaselect(7);
  if (tcs8.begin(0x29))   // address = 0x29 
  {
    Serial.println("Found sensor 8");
  } 
  else 
  {
    Serial.println("No TCS34725 8 found ... check your connections");
    while (1);
  }     
  delay(50);                           // 
}                                        // end of setup

void loop() {    

  uint16_t r1, g1, b1, c1, r2, g2, b2, c2, r3, g3, b3, c3, r4, g4, b4, c4, r5, g5, b5, c5, r6, g6, b6, c6, r7, g7, b7, c7, r8, g8, b8, c8;                                                               
  DateTime now = RTC.now();            // read the time from the RTC, then construct a data string:
  sprintf(TmeStrng, "%04d/%02d/%02d,%02d:%02d:%02d", now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second()); 

                                     // write the data to the SD card:
  File dataFile = SD.open("datalogTPL.txt", FILE_WRITE);  
  dataFile.print(TmeStrng);dataFile.print(",");
  tcaselect(0);
  tcs1.getRawData(&r1, &g1, &b1, &c1);
  dataFile.print(r1);dataFile.print(","); //sensor 1
  dataFile.print(g1);dataFile.print(",");
  dataFile.print(b1);dataFile.print(",");   
  dataFile.print(c1);dataFile.print(",");
  tcaselect(1);
  tcs2.getRawData(&r2, &g2, &b2, &c2);
  dataFile.print(r2);dataFile.print(","); //sensor 2
  dataFile.print(g2);dataFile.print(",");
  dataFile.print(b2);dataFile.print(",");   
  dataFile.print(c2);dataFile.print(",");     
  tcaselect(2);
  tcs3.getRawData(&r3, &g3, &b3, &c3);
  dataFile.print(r3);dataFile.print(","); //sensor 3
  dataFile.print(g3);dataFile.print(",");
  dataFile.print(b3);dataFile.print(",");   
  dataFile.print(c3);dataFile.print(",");     
  tcaselect(3);
  tcs4.getRawData(&r4, &g4, &b4, &c4);
  dataFile.print(r4);dataFile.print(","); //sensor 4
  dataFile.print(g4);dataFile.print(",");
  dataFile.print(b4);dataFile.print(",");   
  dataFile.print(c4);dataFile.print(","); 
  tcaselect(4);    
  tcs5.getRawData(&r5, &g5, &b5, &c5);
  dataFile.print(r5);dataFile.print(","); //sensor 5
  dataFile.print(g5);dataFile.print(",");
  dataFile.print(b5);dataFile.print(",");   
  dataFile.print(c5);dataFile.print(",");   
  tcaselect(5);  
  tcs6.getRawData(&r6, &g6, &b6, &c6);
  dataFile.print(r6);dataFile.print(","); //sensor 6
  dataFile.print(g6);dataFile.print(",");
  dataFile.print(b6);dataFile.print(",");   
  dataFile.print(c6);dataFile.print(","); 
  tcaselect(6);    
  tcs7.getRawData(&r7, &g7, &b7, &c7);
  dataFile.print(r7);dataFile.print(","); //sensor 7
  dataFile.print(g7);dataFile.print(",");
  dataFile.print(b7);dataFile.print(",");   
  dataFile.print(c7);dataFile.print(",");  
  tcaselect(7);   
  tcs8.getRawData(&r8, &g8, &b8, &c8);
  dataFile.print(r8);dataFile.print(","); //sensor 8
  dataFile.print(g8);dataFile.print(",");
  dataFile.print(b8);dataFile.print(",");   
  dataFile.print(c8);dataFile.print(",");          
  dataFile.println();
  dataFile.flush();                                        // wait for serial data to complete transmission
  dataFile.close();
  delay(1);

  while (1)                          // The toggling does not seem to be required, but...
  {                                  // toggle donePin so TPL5110 will cut power and turn off logger
    digitalWrite(donePin, HIGH);
    delay(1);
    digitalWrite(donePin, LOW);
    delay(1);
  }
}                                    // end of the MAIN LOOP

Welcome to the forum.

The official Arduino boards and modules are good quality. Adafruit makes good quality products, and so do Sparkfun and Pololu. There are however a lot a nasty cheap modules that might ruin your day.
I think I spot a few of those bad modules in the photos here: https://publiclab.org/wiki/mini-pearl-logger.
Is that a 3.3V 8MHz Pro Mini ?

Can you get a normal Arduino Uno ? or a 3.3V Arduino board or Arduino-compatible board ? That is easier. However, some modules might not be compatible with the 5V Arduino Uno.

Do you see the data of 8 different sensor in the Serial Monitor ? That is good.
Did you try to write the data of a single sensor to a file ? Or even just some text while the sensor data is shown to the Serial Monitor.

Things to look into:

  • I have a few older 8GB microSD memory cards, and I'm sure that they work with Arduino. Do you have a compatible microSD card ? I'm using a tool to format it. Read about the tool: https://forum.arduino.cc/t/dont-format-sd-cards-with-os-utilities/222016
  • I'm seriously worried about the quality of your circuit. Can you show a photo of your project ? Can you give links to every module ? Please provide a drawing or schematic of the circuit.
  • Is the 3.3V output strong enough to power everything ? Those leds of the 8 modules require some current. I think that the 3.3V pin of the Pro Mini is not that strong. Do you have a multimeter ?
  • Your sketch will be easier when you put everything into arrays. Checking a few code lines is easier than checking 8 times a few code lines.

Could your sketch be running out of RAM memory? The SD card library uses a lot of memory, and 8 sensors each also needing some memory, perhaps you are running out, which does not give any error messages, but will make the sketch "misbehave".

You say that 8 sensors outputting to the serial monitor works ok, and I assume this means not using the SD card library? Also you said that reading 1 sensor and writing that to SD card works ok. It might be worth testing 2 sensors writing to SD card, then 3, 4... until it stops working.

An easy tip for reducing the RAM used is to use the F() macro like this:

Serial.println(F("Found sensor 2"));

Reviewing the code in Adafruit_TCS34725.h, I think you can re-use the same Adafruit_TCS34725 object for all 8 sensors, instead of declaring a separate object for each. I think this because they all use the same i²c address, integration time and gain settings.

However, another point I noticed when reviewing the library was that each Adafruit_TCS34725 should not consume much RAM memory, so I'm not sure why there would not be sufficient RAM memory for 8 of them.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.