My project is to connect 48 TLV493D magnetic field sensors through a TCA9548A MUX. I'm using the 3.3V version of the ProMini, as the sensors require 3.3V. The TLV sensors have 8 possible addresses, and there are 8 channels on the MUX, so I actually could use as many as 64 sensors.
As a first step, I set the MUX to address 0x70 and used just channel 5 to control only 8 sensors. I'm not reading any data yet. That worked great - a scan of the I2C bus recognizes the MUX and the 8 sensors.
Final setup for Sensor 5 =========
I2C scanner. Scanning ...
Found address: 11 (0xB)
Found address: 15 (0xF)
Found address: 27 (0x1B)
Found address: 31 (0x1F)
Found address: 74 (0x4A)
Found address: 78 (0x4E)
Found address: 90 (0x5A)
Found address: 94 (0x5E)
Found address: 112 (0x70)
Done. Found 9 device(s).
Here is the code:
#include <Wire.h>
#define baud 115200
#define TCA_add0 0x70
// TLV493 registers
byte byte0 = 0; // Bx value MSB's
byte byte1 = 0; // By value MSB's
byte byte2 = 0; // Bz value MSB's
byte byte3 = 0; // Selected channel, frame counter, temp MSB's
byte byte4 = 0; // By, Bx LSB's
byte byte5 = 0; // Bz LSB's, PD flag
byte byte6 = 0; // Temp LSB's
byte byte7 = 0; // Factory settings
byte byte8 = 0; // Factory settings
byte byte9 = 0; // Factory settings
byte MOD1;
byte b8;
byte MOD2;
//set addresses
const int def_addr_lo = 31; // boot-up address with SDA low
const int def_addr_hi = 94; // boot-up address with SDA high
byte addr;
byte add1 = 11;
byte add2 = 74;
byte add3 = 78;
byte add4 = 90;
byte add5 = 94;
byte add6 = 15;
byte add7 = 27;
byte add8 = 31;
const int config_reg = 0x00; // initialization value
const byte sens1Pwr = 2; // sensor 1 power
const byte sens2Pwr = 3; // sensor 2 power
const byte sens3Pwr = 4; // sensor 3 power
const byte sens4Pwr = 5; // sensor 4 power
const byte sens5Pwr = 6; // sensor 5 power
const byte sens6Pwr = 7; // sensor 6 power
const byte sens7Pwr = 8; // sensor 7 power
const byte sens8Pwr = 9; // sensor 8 power
byte sensor; // sensor # on current channel (1-8)
int sensor_pin; // pin # of sensor (sensor # + 1)
const byte addrPin = 10; // used to hold SDA/ADDR to 0 on power up to use lower I2C addresses
const byte del = 100;
unsigned int i = 0;
// ###########
// Functions
// ###########
void I2Cscan() // scans for I2C device addresses
{
Serial.println ();
Serial.println ("I2C scanner. Scanning ...");
byte count = 0;
Wire.begin();
for (byte j = 1; j < 127; j++)
{
Wire.beginTransmission (j);
if (Wire.endTransmission (j) == 0)
{
Serial.print ("Found address: ");
Serial.print (j, DEC);
Serial.print (" (0x");
Serial.print (j, HEX);
Serial.println (")");
count++;
}
}
Serial.print ("Done. Found ");
Serial.print (count, DEC);
Serial.println (" device(s).");
}
// =======
void tcaselect(byte TCA_addr, int chan) //set MUX address and channel
{
if (chan > 7) return;
Wire.beginTransmission(TCA_addr);
Wire.write(1 << chan);
Wire.endTransmission();
}
// =======
void init_sensor_lo(uint8_t sensor, byte mod1_val) // Routine to initialize sensors to addresses 11, 15, 27, or 31
{
sensor_pin=sensor+1;
Serial.print("Setup sensor ");
Serial.println(sensor);
Serial.print("............\n");
pinMode(sensor_pin, OUTPUT); //
digitalWrite(sensor_pin, LOW); // turn sensor off
pinMode(addrPin, OUTPUT); // )
digitalWrite(addrPin, LOW); // turn SDA/ADDR off
delay(del);
digitalWrite(sensor_pin, HIGH); // turn sensor on while SDA is low
delay(del);
pinMode(addrPin, INPUT);
delay(del);
I2Cscan();
Wire.beginTransmission(def_addr_lo);
Wire.write(0);
Wire.endTransmission();
delay(del);
readReadRegs(def_addr_lo, true); // read all 10 registers
MOD1 = (byte7 & B00011000) | mod1_val; // set appropriate bits
b8 = byte8;
MOD2 = (byte9 & B00011111) | B11000000; // set appropriate bits
configTLV(def_addr_lo, MOD1, b8, MOD2);
readReadRegs(add1, true); // read register settings
I2Cscan();
Serial.print("Setup Complete for Sensor ");
Serial.println(sensor);
Serial.print("............\n");
}
// =======
void init_sensor_hi(uint8_t sensor, byte mod1_val) // Routine to initialize sensors to addresses 74, 78, 90, and 94
{
sensor_pin=sensor+1;
Serial.print("Setup sensor ");
Serial.println(sensor);
Serial.print("............\n");
pinMode(sensor_pin, OUTPUT);
digitalWrite(sensor_pin, LOW); // turn sensor off
pinMode(addrPin, OUTPUT);
digitalWrite(addrPin, HIGH); // set SDA/ADDR High
delay(del);
digitalWrite(sensor_pin, HIGH); // turn sensor on while SDA is high
delay(del);
pinMode(addrPin, INPUT);
delay(del);
I2Cscan();
Wire.beginTransmission(def_addr_hi);
Wire.write(0); // Sensor initialization
Wire.endTransmission();
delay(del);
readReadRegs(def_addr_hi, true); // read all 10 registers
MOD1 = (byte7 & B00011000) | mod1_val; // set appropriate bits
b8 = byte8;
MOD2 = (byte9 & B00011111) | B11000000;
configTLV(def_addr_hi, MOD1, b8, MOD2);
readReadRegs(add2, true); // read register settings
Serial.print("Setup Complete for Sensor ");
Serial.println(sensor);
Serial.print("............\n");
}
// =======
void readReadRegs(byte addr, bool ten) // read register settings, if argument = true, get all 10 else 7
{
byte noOfBytes;
ten ? noOfBytes = 10 : noOfBytes = 7; //if (ten == true) read 10 bytes else 7
Wire.requestFrom(addr, noOfBytes); // read correct number of bytes
if (noOfBytes <= Wire.available()) // if all bytes were received
{
byte0 = Wire.read(); // Bx value MSBs
byte1 = Wire.read(); // By value MSBs
byte2 = Wire.read(); // Bz value MSBs
byte3 = Wire.read(); // TEMP MSbits 7:4; FRM 3:2; CH 1:0
byte4 = Wire.read(); // Bx LSbits 7:4; By LSBits 3:0
byte5 = Wire.read(); // RSV 7; TestMode 6; PFF 5; PowerDown 4; Bz LSbits 3:0
byte6 = Wire.read(); // Temp LSB
if (ten == true)
{
byte7 = Wire.read(); // Factory settings
byte8 = Wire.read(); // Factory settings
byte9 = Wire.read(); // Factory settings
}
}
}
// =======
void configTLV(byte addr, byte MOD1, byte b8, byte MOD2)
{
Wire.beginTransmission(addr);
Wire.write(byte(0x00)); // config byte 0
Wire.write(byte(MOD1)); // config byte 1
Wire.write(byte(b8)); // config byte 2
Wire.write(byte(MOD2)); // config byte 3
Wire.endTransmission();
delay(500);
}
// ###########
// Setup
// ###########
void setup()
{
Wire.begin();
Serial.begin(baud);
while (!Serial) {}
tcaselect(TCA_add0,5);
Serial.print("\n Initialize all sensors on Channel 5 =========\n");
I2Cscan();
init_sensor_lo(1,B01100111); // sensor 1 = address 11
init_sensor_hi(2,B01100111); // sensor 2 = address 74
init_sensor_hi(3,B01000111); // sensor 3 = address 78
init_sensor_hi(4,B00100111); // sensor 4 = address 90
init_sensor_hi(5,B00000111); // sensor 5 = address 94
init_sensor_lo(6,B01000111); // sensor 6 = address 15
init_sensor_lo(7,B00100111); // sensor 7 = address 27
init_sensor_lo(8,B00000111); // sensor 8 = address 31
Serial.print("\n Final setup for Sensor 5 =========\n");
I2Cscan();
[b]
// tcaselect(TCA_add0,7);
// Serial.print("\n Initialize all sensors on Channel 7 =========\n");
// I2Cscan();
// init_sensor_lo(1,B01100111);
// init_sensor_hi(2,B01100111);
// init_sensor_hi(3,B01000111);
// init_sensor_hi(4,B00100111);
// init_sensor_hi(5,B00000111);
// init_sensor_lo(6,B01000111);
// init_sensor_lo(7,B00100111);
// init_sensor_lo(8,B00000111);
// Serial.print("\n Final setup for Sensor 7 =========\n");
// I2Cscan();
[/b]
Serial.print("\n\n Re-check all sensors on Channel 5 =========\n");
tcaselect(TCA_add0,5);
I2Cscan();
Serial.print("\n =========\n");
}
// ###########
// Main Loop
// ###########
void loop()
{}
The problem comes when I try to connect an additional channel of the MUX. If you uncomment the 13 bolded lines in the Setup section of the code, it will initialize and confirm the settings for channel 5, then do the same for Channel 7. However, it then re-checks the settings for Channel 5, and shows that its settings have been lost. Can anyone see what I'm doing wrong? Thanks.
Re-check all sensors on Channel 5 =========
I2C scanner. Scanning ...
Found address: 94 (0x5E)
Found address: 112 (0x70)
Done. Found 2 device(s).
Register Map.pdf (886 KB)
tca9548a-1-to-8-i2c-multiplexer.pdf (629 KB)