0

I am using VMEL6040 sensors and occasionally under bright light the read can hang, rather than using a wdt to recover I would like to ask some questions about the library.

as for debugging the sensors run stabley (several days at reads every 250 ms) in low light, but over 6k lux they can crash.

I am using wire.h here

in the header

TwoWire *_i2cPort;

the read value calls the ReadRegister function:

uint16_t SparkFun_Ambient_Light::_readRegister(uint8_t _reg)
{

  uint16_t _regValue; 

  _i2cPort->beginTransmission(_address); 
  _i2cPort->write(_reg); // Moves pointer to register.
  _i2cPort->endTransmission(false); // 'False' here sends a restart message so that bus is not released
  _i2cPort->requestFrom(_address, static_cast<uint8_t>(2)); // Two reads for 16 bit registers
  _regValue = _i2cPort->read(); // LSB
  _regValue |= uint16_t(_i2cPort->read()) << 8; //MSB
  return(_regValue);

}

is there a reason they are not checking the return of the _i2cPort->endTransmission(false);call? I am wondering if I should check that and not call the requestFrom if it does, i.e.:

uint16_t SparkFun_Ambient_Light::_readRegister(uint8_t _reg)
{

  uint16_t _regValue; 

  _i2cPort->beginTransmission(_address); 
  _i2cPort->write(_reg); // Moves pointer to register.
  if (_i2cPort->endTransmission(false) == 0) { // 'False' here sends a restart message so that bus is not released
      _i2cPort->requestFrom(_address, static_cast<uint8_t>(2)); // Two reads for 16 bit registers
      _regValue = _i2cPort->read(); // LSB
      _regValue |= uint16_t(_i2cPort->read()) << 8; //MSB
      return(_regValue);
  }
  else
      return 0;
}

Or could my error be from the static casting do int?

5
  • 1
    I thought a static_cast was just a compile time cast; I don’t see how casting 2 to a byte would cause an error if that’s what the call expects (which IIRC it is). May 26, 2021 at 23:58
  • 1
    1) static_cast<uint8_t>(2) is not necessary, if you read Wire source, you will see multiple overload functions to handle the type casting. 2) to cast a uint8_t1 to a uint16_t, it is (uint16_t) _i2cPort->read(), not uint16_t(_i2cPort->read() . 3) shouldn't uint16_t _regValue; ` be declared at your Class level? your code now declared it as a local variable, and you are returning a local variable's value, which may no longer exist (out of scope) when the program return from the function.
    – hcheung
    May 27, 2021 at 0:37
  • 1
    @hcheung: Returning a local variable's address would be an error. Returning it's value is perfectly fine. May 27, 2021 at 7:03
  • the full library im using can be found here: github.com/sparkfun/… May 27, 2021 at 10:10
  • I think i just figured it out _i2cPort->read(); returns a -1 on error duh May 28, 2021 at 1:47

1 Answer 1

1

so I think I got it, the problem was that on a fail wire.read() returns an int -1 when that gets converted to a unint16 its a big number then it gets left shifted and overflows

the solution was:

uint16_t SparkFun_Ambient_Light::_readRegisterLight(uint8_t _reg)
{
    int lsb;
    int msb;

    _i2cPort->beginTransmission(_address);
    _i2cPort->write(_reg); // Moves pointer to register.
    if (_i2cPort->endTransmission(false) == 0) { // 'False' here sends a restart message so that bus is not released

        unsigned long tstamp = millis();
        while ((_i2cPort->available() < 2) && ((millis() - tstamp) < 10));

        if ((_i2cPort->available() < 2)) {
            _i2cPort->requestFrom(_address, 2); // Two reads for 16 bit registers
            lsb = _i2cPort->read(); // LSB
            msb = _i2cPort->read(); //MSB

            if ((lsb >= 0) && (lsb <= 256) && (msb >= 0) && (msb <= 256)) {                    
                _regValue = lsb + msb * 256;
            }
        }


        return(_regValue);
    }
    else
        return _regValue;//last read 
}

This contains some extra error handling I added, but will leave in such as:

  1. timeout on waiting for a response
  2. checking on properly closing the bus in end transmission
  3. checking for errors from the read

I didn't do error handling as I would need to rewrite the whole library, and for my application repeating the last reading is sufficient.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.