Чтение из люкса висит при ярком свете

i2c

Я использую датчики VMEL6040, и иногда при ярком свете чтение может висеть, вместо того, чтобы использовать wdt для восстановления, я хотел бы задать некоторые вопросы о библиотеке.

что касается отладки датчиков, они работают стабли (несколько дней при считывании каждые 250 мс) в условиях низкой освещенности, но более 6k люкс они могут разбиться.

Я использую проволоку.к здесь

в заголовке

TwoWire *_i2cPort;

значение read вызывает функцию ReadRegister:

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);

}

есть ли причина, по которой они не проверяют возврат _i2cPort->endTransmission(false);>call? Мне интересно, должен ли я проверить это и не вызывать requestFrom, если это так, т. Е.:

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;
}

Или моя ошибка может быть от статического кастинга do int?

, 👍0

Обсуждение

Я думал, что "static_cast" - это просто приведение во время компиляции; Я не вижу, как приведение " 2 " к байту вызовет ошибку, если это то, что ожидает вызов (а это IIRC)., @Dave Newton

1) ' static_cast<uint8_t>(2) не является необходимым, если вы читаете [Wire](https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/Wire/src/Wire.cpp#L169-L186) источник, вы увидите несколько функций перегрузки для обработки приведения типа. 2) чтобы привести uint8_t1 к uint16_t, это (uint16_t) _i2cPort->read(), а не uint16_t(_i2cPort->>read() . 3) не должно ли uint16_t _regValue; быть объявлено на уровне вашего класса? теперь ваш код объявил его как локальную переменную, и вы возвращаете значение локальной переменной, которое может больше не существовать (вне области действия), когда программа возвращается из функции., @hcheung

@hcheung: Возврат _address_ локальной переменной будет ошибкой. Вернуть его _value_-это совершенно нормально., @Edgar Bonet

полную библиотеку, которую я использую, можно найти здесь: https://github.com/sparkfun/SparkFun_Ambient_Light_Sensor_Arduino_Library, @levi Clouser

Я думаю, что только что понял это _i2cPort->read(); возвращает -1 при ошибке duh, @levi Clouser


1 ответ


Лучший ответ:

1

итак, я думаю, что понял, проблема заключалась в том, что на fail wire.read() возвращает int -1 , когда он преобразуется в unint16-это большое число, а затем оно сдвигается влево и переполняется

решение было таково:

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 
}

Это содержит некоторую дополнительную обработку ошибок, которую я добавил, но оставит, например:

  1. время ожидания ответа
  2. проверка правильности закрытия шины в конечной передаче
  3. проверка ошибок при чтении

Я не занимался обработкой ошибок, так как мне нужно было бы переписать всю библиотеку, и для моего приложения достаточно повторить последнее чтение.

,