/* * \brief Get light intensity value (Lux & FootCandles) from Light dependent Resistor (implementation) * * \author Quentin Comte-Gaz * \date 30 January 2023 * \license MIT License (contact me if too restrictive) * \copyright Copyright (c) 2023 Quentin Comte-Gaz * \version 1.4 */ #include "LightDependentResistor.h" LightDependentResistor::LightDependentResistor(int pin, unsigned long other_resistor, ePhotoCellKind kind, unsigned int adc_resolution_bits, unsigned int smoothing_history_size) : _pin (pin), _other_resistor (other_resistor), _mult_value(32017200), _pow_value(1.5832), _photocell_on_ground (true), _adc_resolution_bits(adc_resolution_bits), _smoothing_sum(0.0f), _smoothing_history_size(smoothing_history_size), _smoothing_history_next(0), _smoothing_history_values(new float[smoothing_history_size]) { switch (kind) { case GL5516: _mult_value = 29634400; _pow_value = 1.6689; break; case GL5537_1: _mult_value = 32435800; _pow_value = 1.4899; break; case GL5537_2: _mult_value = 2801820; _pow_value = 1.1772; break; case GL5539: _mult_value = 208510000; _pow_value = 1.4850; break; case GL5549: _mult_value = 44682100; _pow_value = 1.2750; break; case GL5528: default: _mult_value = 32017200; _pow_value = 1.5832; } for (unsigned int i = 0 ; i < _smoothing_history_size ; i++) { // We initialize the values as impossible value (lux can't be negative) _smoothing_history_values[i] = -1.0f; } } LightDependentResistor::LightDependentResistor(int pin, unsigned long other_resistor, float mult_value, float pow_value, unsigned int adc_resolution_bits, unsigned int smoothing_history_size) : _pin (pin), _other_resistor (other_resistor), _mult_value (mult_value), _pow_value (pow_value), _photocell_on_ground (true), _adc_resolution_bits(adc_resolution_bits), _smoothing_sum(0.0f), _smoothing_history_size(smoothing_history_size), _smoothing_history_next(0), _smoothing_history_values(new float[smoothing_history_size]) { for (unsigned int i = 0 ; i < _smoothing_history_size ; i++) { // We initialize the values as impossible value (lux can't be negative) _smoothing_history_values[i] = -1.0f; } } LightDependentResistor::~LightDependentResistor() { // De-allocate the table at the end of the use of the class delete[] _smoothing_history_values; } void LightDependentResistor::updatePhotocellParameters(float mult_value, float pow_value) { _mult_value = mult_value; _pow_value = pow_value; } float LightDependentResistor::luxToFootCandles(float intensity_in_lux) { return intensity_in_lux/10.764; } float LightDependentResistor::footCandlesToLux(float intensity_in_footcandles) { return 10.764*intensity_in_footcandles; } void LightDependentResistor::setPhotocellPositionOnGround(bool on_ground) { _photocell_on_ground = on_ground; } int LightDependentResistor::getCurrentRawAnalogValue() const { // Analog resolution setter is not handled on all boards (not compatible boards: MEGA, ESP8266, Uno) #if !defined(__AVR_ATmega1280__) && !defined(__AVR_ATmega2560__) && !defined(ESP8266) && !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) analogReadResolution(_adc_resolution_bits); #endif return analogRead(_pin); } float LightDependentResistor::rawAnalogValueToLux(int raw_analog_value) const { unsigned long photocell_resistor; if (pow(2, _adc_resolution_bits) == raw_analog_value) { raw_analog_value--; } float ratio = ((float)pow(2, _adc_resolution_bits) / (float)raw_analog_value) - 1; if (_photocell_on_ground) { photocell_resistor = _other_resistor / ratio; } else { photocell_resistor = _other_resistor * ratio; } return _mult_value / (float)pow(photocell_resistor, _pow_value); } float LightDependentResistor::getCurrentLux() const { return rawAnalogValueToLux(getCurrentRawAnalogValue()); } float LightDependentResistor::getCurrentFootCandles() const { return luxToFootCandles(getCurrentLux()); } float LightDependentResistor::getSmoothedLux() { float sumResult = 0; if (_smoothing_history_size == 0) { // Smoothing disabled, return current value. sumResult = getCurrentLux(); } else { if (_smoothing_history_values[_smoothing_history_next] < -0.1f) { // Smoothing enabled but not all values are filled yet // (Let's fill one more) _smoothing_history_values[_smoothing_history_next] = getCurrentLux(); _smoothing_sum += _smoothing_history_values[_smoothing_history_next]; if (_smoothing_history_next < _smoothing_history_size - 1) { // Still not all buffers filled _smoothing_history_next++; sumResult = _smoothing_sum / _smoothing_history_next; } else { // All buffers filled now, start regular operation _smoothing_history_next = 0; sumResult = _smoothing_sum / _smoothing_history_size; } } else { // Smoothing enabled and buffer filled previously. // => Regular operation from now on: // Replace previous value by the new one (from buffer and sum) _smoothing_sum -= _smoothing_history_values[_smoothing_history_next]; _smoothing_history_values[_smoothing_history_next] = getCurrentLux(); _smoothing_sum += _smoothing_history_values[_smoothing_history_next]; // Update next value tu acquire _smoothing_history_next = (_smoothing_history_next < _smoothing_history_size - 1) ? _smoothing_history_next + 1 : 0; sumResult = _smoothing_sum / _smoothing_history_size; } } return sumResult; } float LightDependentResistor::getSmoothedFootCandles() { return luxToFootCandles(getSmoothedLux()); }