IF Statement manipulates variable without writing to it

I hope the Arduino Experts can help me with my Problem.

The Problem is an IF - ELSE IF Statement.

I have a Gesture, Color, Proximity and Light Sensor (All in One) connected to an Arduino UNO. I am trying to change the Gain of Gesture Sensing depending on the Proximity Value. Everything works perfectly fine if i don't use the if statement which checks and compare the current proximity value stored in a variable. The If Statement is never supposed to write or anyhow change the prox variable as it ONLY reads from it but exactly that seems to happen here.

This is the complete Code:

#include <I2C.h>

uint8_t prox;
uint8_t gain;

void setup() {
  Serial.begin(9600);
  I2c.begin();
  I2c.setSpeed(1);
  I2c.pullup(1);
  tmginit();
}

void tmginit() {
  prox = 0;
  gain = 1;
  I2c.write(57, 128, 69);  //0x80 Gesture, Proximity and Power enabled
  I2c.write(57, 171, 3);   //0xAB Hardware interrupt and gmode enabled
  I2c.write(57, 142, 224); //0x8E PPLEN 32µs
  I2c.write(57, 143, 0);   //0x8F LDRIVE 100% Mode
  I2c.write(57, 144, 16);  //0x90 LEDBOOST 300% and 2x prox gain
  I2c.write(57, 160, 0);   //0xA0 Gesture Proximity Entry Threshold set to 0
  I2c.write(57, 161, 255); //0xA1 Gesture Exit Threshold set to maximum
  I2c.write(57, 163, 0);   //0xA3 Gain set to 4x
  I2c.write(57, 164, 2);   //0xA4 Gesture North Offset
  I2c.write(57, 165, 1);   //0xA5 Gesture South Offset
  I2c.write(57, 166, 224); //0xA6 Gesture PWM Length set to 32µs
  I2c.write(57, 167, 1);   //0xA7 Gesture West Offset
  I2c.write(57, 169, 2);   //0xA9 Gesture East Offset
}

void loop() {

  prox = 0;
  Serial.println();
  I2c.read(57, 156, 1); // Proximity Value
  prox = I2c.receive();
  Serial.println("PROX:");
  Serial.println(prox);

 if ((prox >= 225) && (gain != 1))
  {

    I2c.write(57, 163, 0);
    gain = 1;

  }

  else if ((prox >= 100) && (prox < 225) && (gain != 2))
  {

    I2c.write(57, 163, 32);
    gain = 2;

  }

  else if ((prox >= 30) && (prox < 100) && (gain != 4))
  {

    I2c.write(57, 163, 64);
    gain = 4;

  }

  else if ((prox >= 0) && (prox < 30) && (gain != 8))
  {

    I2c.write(57, 163, 96);
    gain = 8;

  }

  Serial.println();
  Serial.println("GAIN:");
  Serial.println(gain);
  Serial.println();


  I2c.read(57, 252, 1); //FIFO N

  Serial.println(I2c.receive(), DEC);
  I2c.read(57, 253, 1); //FIFO S

  Serial.println(I2c.receive(), DEC);
  I2c.read(57, 254, 1); //FIFO W

  Serial.println(I2c.receive(), DEC);
  I2c.read(57, 255, 1); //FIFO E

  Serial.println(I2c.receive(), DEC);

  delay(500);


}

The Proximity Value outputs really strange values if i have the if and else if block actively running. But when I comment the complete if and else if Block out, everything runs perfectly. The Proximity Value changes when i come near the sensor or when i go away from the sensor.

Example:

I am very close to the Sensor. The Proximity Value is somewhere between 200 and 255 (255 is max). This is the correct behaviour.

Now i activate the if and else if block and do the same thing again

I am very close to the Sensor. The Proximity Value is somewhere between 5 and 10 (255 is max). This is the Problem that only occurs when the if else if statements are active...

Only the very first read WITH if and else is correct. From then on all this weird stuff starts to happen.

The I2C Write in the if else if statements doesn't affect the Proximity Value. It only adjusts the Gain of Gesture Sensing. So the whole thing is supposed to be something like Automatic Gain Control.

There is a programming bug in my code but i can't figure it put. Please help!

Thank You.

Can you explain what this line is doing?

  I2c.read(57, 156, 1); // Proximity Value

When I say "explain" please describe what each of those numbers: 57, 156, and 1, represent.

Because I found this function on the Internets, since you didn't provide a link to anything:

uint8_t I2C::read(uint8_t address, uint8_t numberBytes, uint8_t *dataBuffer)

Ooops Sorry!

I am using an external Library for I2C. I downloaded it from here.

Direct Download Link for the Library.

I2c.read(57, 156, 1); // Proximity Value

57 --- I2C Slave Address
156 --- Register Address
1 --- Number of Bytes to read out from the register.

This Code Line works perfectly without the if else statements. I tested it. The whole thing just goes crazy if i use the following if else if statement.

if ((prox >= 225) && (gain != 1))
  {

    I2c.write(57, 163, 0);
    gain = 1;

  }

  else if ((prox >= 100) && (prox < 225) && (gain != 2))
  {

    I2c.write(57, 163, 32);
    gain = 2;

  }

  else if ((prox >= 30) && (prox < 100) && (gain != 4))
  {

    I2c.write(57, 163, 64);
    gain = 4;

  }

  else if ((prox >= 0) && (prox < 30) && (gain != 8))
  {

    I2c.write(57, 163, 96);
    gain = 8;

  }

Can you please explain the 3 parameters in
I2c.write(57, 163, 0);I would guess slave address and register but what about the third parameter ?

I2c.write(57, 163, 0);

write 0 into register 163.

57 is the slave address.

this line also works if i don't use the if else if statement.

You are calling I2C.receive() everytime round loop(), which is returning the next byte in
I2C library's internal buffer, or zero if you've already drained it.

I think you should be calling I2C.available ()

I appreciate your answer MarkT.

If i comment the if else if block out, it still runs in a round loop and works perfectly without any issues.

Putting a /* before the first if and */ after the last else if is the only modification i do and the whole thing works flawlessly. i don't call I2C.available() in that case and still no issues. The If else If is causing some kind of strange problem.

57 --- I2C Slave Address
156 --- Register Address
1 --- Number of Bytes to read out from the register.

Yes, but where do those bytes go? And your explanation doesn't match the prototype:

uint8_t I2C::read(uint8_t address, uint8_t numberBytes, uint8_t *dataBuffer)
uint8_t I2C::read(int address, int registerAddress, int numberBytes)
{
  return(read((uint8_t) address, (uint8_t) registerAddress, (uint8_t) numberBytes));
}

This is code i copied out of the .cpp file of I2C. So according to this it does match the prototype.

Yes, but where do those bytes go?

  1. I2C.read();
  2. I2C.receive();

First you read out the data from the register using the read function. The data is then saved into a buffer.

Using I2C.receive() i fetch the data from the buffer and put into a variable such as Prox.

and it does work. Pretty easy to tell if you test the whole thing with a proximity sensor. the value increases as i come closer to the sensor.

it's just the if else if statement that somehow doesn't work.

Hmm. Well, "if" statements work, or else the entire world of C programming would fail. So you have to look elsewhere.

For one thing, your "if" statements include a test on "gain".

The Proximity Value outputs really strange values if i have the if and else if block actively running.

You have debugging displays. How about posting what you see, and what we cannot see?