Search code examples
arduinoi2c

Read values from i2c sensors with the same address


I have 4 SingleTact capacitive sensors each with the i2c address of 0x04. I want to find the average value of the sensors, in order to make a joystick. However I am unsure how to assign each sensor it's own address since they all have the same address as they are the same sensor. I have an initial code however this only works with one single sensor as it only has one single i2c address byte. I have wired together all the SDA and SCL line together using tutorials online and have included pull-up resistors.

#include <Wire.h>
#define initializetime 4
byte serialToPCBuffer[77];
byte serialToPCBufferIndex = 0;

int data[4];
int databuffer[4][initializetime] = {0,0,0,0,0,0,0,0,0,0,0,0};
int base[4] = {0,0,0,0};
int ArduinoToPCBuffer[4] = {1000,2000,3000,4000};
byte outgoingI2CBuffer[32];
unsigned long timeStamp_;

void setup() {
  int i;
  Wire.begin();
  //TWBR = 12;
  Serial.begin(57600);
  Serial.flush();
  initializeSensors();

  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.println("PPS UK: SingleTact sensor value in PSI. \n(resembles PC executable display)");
  Serial.println("Refer manual for any other calculation.");
  Serial.println("----------------------------------------");  
}    

void loop(){
  byte i2cAddress = 0x04; // Slave address (SingleTact), default 0x04
  int data = readDataFromSensor(i2cAddress);
  Serial.print("I2C Sensor Data:");
  Serial.print(data);    
  Serial.print("\n");
  delay(100); // Change this if you are getting values too quickly 
}

int readDataFromSensor(int address)
{
  byte i = 0;
  byte i2cPacketLength = 6;
  byte outgoingI2CBuffer[3];
  byte incomingI2CBuffer[6];

  outgoingI2CBuffer[0] = 0x01;
  outgoingI2CBuffer[1] = 128;
  outgoingI2CBuffer[2] = i2cPacketLength;

  Wire.beginTransmission(address);
  Wire.write(outgoingI2CBuffer,3);
  byte error = Wire.endTransmission();
  if (error != 0) return -1;
  Wire.requestFrom(address,i2cPacketLength);

  int incomeCount =0;
  while(incomeCount < i2cPacketLength)
  {
    if(Wire.available())
    {
    incomingI2CBuffer[incomeCount] = Wire.read();
    incomeCount++;
    }
    else
    {
    delay(1);
    }
  }
  if(serialToPCBuffer[4] == 0x00 && serialToPCBuffer[5] == 0xFE)
  {
    serialToPCBuffer[5] = 0xFF;
  }

  int datafromi2c = serialToPCBuffer[4]*256+serialToPCBuffer[5]-base[address-5];

  if(datafromi2c<21)
    datafromi2c = 0;

  return datafromi2c;
}

void initializeSensors()
{
  for(int k = 0;k<4;k++)
  {
    databuffer[k][0] = readDataFromSensor(k+5);
    delay(10);
    databuffer[k][1] = readDataFromSensor(k+5);
    delay(10);
    databuffer[k][2] = readDataFromSensor(k+5);
    delay(10);
    databuffer[k][3] = readDataFromSensor(k+5);
    delay(10);
    base[k] = (databuffer[k][0] + databuffer[k][1] + databuffer[k][2] +     databuffer[k][3])/3;
  }
}

Thanks for any advice.


Solution

  • You should read the manual of this device, available here. It says, at the interface description, that

    Multiple sensor interfaces may be connected to a single I2C bus. The bus address of individual sensor interfaces can be configured by writing desired address value (4 to 127) via the I2C interface to register address 0 with an I2C Write Operation. Change of individual sensor I2C addresses is supported by the PC and Arduino Example.

    So you just have to

    1. plug the first sensor
    2. write an address (e.g. 0x41) to the register 0 of this device
    3. unplug the sensor
    4. repeat 1-2-3 for all the sensors using different addresses

    Then each sensor will reply to the address you set.

    Please note that

    As the interface board will always respond to address 0x04 then this address must be considered reserved for SingleTact. Where multiple SingleTact interfaces are to be connected to the same I2C bus then address 0x04 must be considered invalid

    So, even in this case, the RTFM advice is the most important one...