Skip to content

Commit

Permalink
Merge pull request #2 from bluesensor/adc-develop
Browse files Browse the repository at this point in the history
Adc develop
  • Loading branch information
jhon-p16 authored Sep 1, 2022
2 parents 5eceffa + 1c97465 commit 7a4039a
Show file tree
Hide file tree
Showing 2 changed files with 206 additions and 100 deletions.
239 changes: 162 additions & 77 deletions src/BslibEnergyMeter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,128 +4,213 @@
* @brief Biblioteca medidor de energia, permite medir voltaje, y corriente con gran precisión.
* @version 2.2.1
* @date 2021-04-16
*
*
* @copyright DataAnalitic (c) {2021}
*
*
*/

#include "BslibEnergyMeter.h"

int currentReference;
int calibrationCurrent;

int currentADC;
int currentRefADC;
float currentDAC;
float current;

int voltageADC;
float voltageDAC;
float voltage;

/**
* @brief Configuracion de los pines del sensor de corriente
*
*
* @param _inPinCurrent pin analógico Vout del sensor de voltaje
* @param _inPinCurrentRef pin analógico Vref del sensor
* @param _factorCurrent factor de sensiblidad del sensor
*/
void BslibEnergyMeter::SetSensorCurrent(unsigned int _inPinCurrent, unsigned int _inPinCurrentRef, float _factorCurrent)
{
inPinCurrent = _inPinCurrent;
inPinCurrentRef = _inPinCurrentRef;
factorCurrent = _factorCurrent;
void BslibEnergyMeter::SetSensorCurrent(unsigned int _inPinCurrent, unsigned int _inPinCurrentRef, float _factorCurrent) {
inPinCurrent = _inPinCurrent;
inPinCurrentRef = _inPinCurrentRef;
factorCurrent = _factorCurrent;
}

/**
* @brief Configuracion de los pines del sensor de voltaje
*
*
* @param _inPinVoltage pin analógico de Vout de sensor de voltaje
* @param _factorVoltage factor de sensiblidad del sensor
* @param _offsetVoltage compensacion para obtener voltaje real
*/
void BslibEnergyMeter::SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage, float _offsetVoltage = 0)
{
inPinVoltage = _inPinVoltage;
factorVoltage = _factorVoltage;
offsetVoltage = _offsetVoltage;
void BslibEnergyMeter::SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage, float _offsetVoltage = 0) {
inPinVoltage = _inPinVoltage;
factorVoltage = _factorVoltage;
offsetVoltage = _offsetVoltage;
}

/**
* @brief Configuracion de los pines del sensor de voltaje
*
*
* @param _inPinVoltage pin analógico de sensor de voltaje
* @param _factorVoltage factor de sensiblidad del sensor
*/
void BslibEnergyMeter::SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage)
{
inPinVoltage = _inPinVoltage;
factorVoltage = _factorVoltage;
void BslibEnergyMeter::SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage) {
inPinVoltage = _inPinVoltage;
factorVoltage = _factorVoltage;
}

/**
* @brief Filtro suave (promedio) de lecturas ADC
*
* @param pinADC pin analógico al cual leer
* @param samples número de muestras para el promedio
* @return int
* @brief Se usar después de la función AutoCalibrationCurrent para configurar el valor de referencia de corriente debido a que no siempre la corriente es cero.
*
* @param _currentReference
*/
unsigned int BslibEnergyMeter::FilterValueADC(unsigned int pinADC, unsigned int samples)
{
unsigned long valueADC = 0;
unsigned int filteredValueADC = 0;
for (unsigned int i = 0; i < samples; i++)
{
valueADC += analogRead(pinADC);
}
filteredValueADC = valueADC / samples;
return filteredValueADC;
void BslibEnergyMeter::SetCurrentReference(int _currentReference) {
currentReference = _currentReference;
}

/**
* @brief Calibrar automaticamente el sensor de corriente con Vref. Usar esta función cuando la corriente sea cero.
*
* @param _numberOfSamples número de muestras a tomar en cada lenctura
* @return int
* @brief Configura el valor de referencia analógica para el MCU
*
* @param _analogReference
*/
unsigned int BslibEnergyMeter::AutoCalibrationCurrent(unsigned int _numberOfSamples)
{
calibrationCurrent = FilterValueADC(inPinCurrentRef, _numberOfSamples);
// algunos sensores tienen un offset (compensacion) cuando Vref<Vout
float offset = FilterValueADC(inPinCurrent, _numberOfSamples) - calibrationCurrent;
calibrationCurrent += offset;
return calibrationCurrent;
void BslibEnergyMeter::SetAnalogReference(float _analogReference) {
analogReference = _analogReference;
}

void BslibEnergyMeter::SetFilterSamples(unsigned int _numberOfSamples) {
numberOfSamples = _numberOfSamples;
}

/**
* @brief Se usar después de la función AutoCalibrationCurrent para configurar el valor de referencia de corriente debido a que no siempre la corriente es cero.
*
* @param _currentReference
* @brief Filtro suave (promedio) de lecturas ADC
*
* @param pinADC pin analógico al cual leer
* @return int
*/
void BslibEnergyMeter::SetCurrentReference(unsigned int _currentReference)
{
currentReference = _currentReference;
int BslibEnergyMeter::FilterValueADC(unsigned int pinADC) {
unsigned long valueADC = 0;
int filteredValueADC = 0;
for (int i = 0; i < numberOfSamples; i++) {
valueADC += analogRead(pinADC);
}
filteredValueADC = valueADC / numberOfSamples;
return filteredValueADC;
}

/**
* @brief Obtiene la corriente del sensor motor
*
* @param _numberOfSamples número de muestras a tomar en cada lenctura
* @return float
* @brief Calcula el valor en voltaje de la lectura ADC del MCU
*
* @param digitalValue
* @return float
*/
float BslibEnergyMeter::GetCurrent(unsigned int _numberOfSamples)
{
int filteredCurrent = FilterValueADC(inPinCurrent, _numberOfSamples) - currentReference;

if (filteredCurrent < 0)
{
filteredCurrent = 0;
}

float convertValueADC = float(filteredCurrent) / ADC_SCALE * VOLT_INPUT_DRIVER;
float current = convertValueADC / factorCurrent;
return current;
float BslibEnergyMeter::SoftwareDAC(int digitalValue) {
float convertValueDCA = float(digitalValue) / ADC_SCALE * analogReference;
return convertValueDCA;
}

/**
* @brief Obtiene el voltaje de la bateria
*
* @param _numberOfSamples número de muestras a tomar en cada lenctura
* @return float
* @brief Calibrar automaticamente el sensor de corriente con Vref. Usar esta función cuando la corriente sea cero.
*
* @return int
*/
float BslibEnergyMeter::GetVoltage(unsigned int _numberOfSamples)
{
int filteredVoltage = FilterValueADC(inPinVoltage, _numberOfSamples);
float convertValueADC = float(filteredVoltage) / ADC_SCALE * VOLT_INPUT_MAIN;
float voltage = (convertValueADC * factorVoltage) + offsetVoltage;
int BslibEnergyMeter::AutoCalibrationCurrent(int lastVRef) {

float vRef = FilterValueADC(inPinCurrentRef);
float vOut = FilterValueADC(inPinCurrent);

if (lastVRef == vRef) {
calibrationCurrent = vRef;
} else {
calibrationCurrent = vRef;
}
// algunos sensores tienen un offset (compensacion) cuando Vref<Vout
// float offset = vOut - vRef;
// calibrationCurrent += offset;
return calibrationCurrent;
}

void BslibEnergyMeter::CalCurrent() {
currentRefADC = FilterValueADC(inPinCurrentRef);
currentADC = FilterValueADC(inPinCurrent);

int offsetCurrent = currentADC - currentRefADC;

if (offsetCurrent < 0) {
offsetCurrent = 0;
}

currentDAC = SoftwareDAC(offsetCurrent);
current = currentDAC / factorCurrent;
}

int BslibEnergyMeter::GetCurrentRefADC() {
return currentRefADC;
}

int BslibEnergyMeter::GetCurrentADC() {
return currentADC;
}

float BslibEnergyMeter::GetCurrentDAC() {
return currentDAC;
}
float BslibEnergyMeter::GetCurrent() {
CalCurrent();
return current;
}

// -----------------------------------------------------------

void BslibEnergyMeter::CalVoltage() {
voltageADC = FilterValueADC(inPinVoltage);
voltageDAC = SoftwareDAC(voltageADC);
voltage = (voltageDAC * factorVoltage) + offsetVoltage;
}

int BslibEnergyMeter::GetVoltageADC() {
return voltageADC;
}

float BslibEnergyMeter::GetVoltageDAC() {
return voltageDAC;
}

float BslibEnergyMeter::GetVoltage() {
CalVoltage();

return voltage;
}

float BslibEnergyMeter::ReadVcc() {
long vccADC;

#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB1286__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
ADCSRB &= ~_BV(MUX5); // Without this the function always returns -1 on the ATmega2560 http://openenergymonitor.org/emon/node/2253#comment-11432
#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);

#endif

return voltage;
#if defined(__AVR__)
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA, ADSC))
;
vccADC = ADCL;
vccADC |= ADCH << 8;
vccADC = READVCC_CALIBRATION_CONST / vccADC; // 1100mV*1024 ADC steps
return vccADC / 1000.0;
#elif defined(__arm__)
return (3300); // Arduino Due
#else
return (3300); // Guess that other un-supported architectures will be running a 3.3V!
#endif
}
67 changes: 44 additions & 23 deletions src/BslibEnergyMeter.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,65 @@
* @brief Biblioteca medidor de energia, permite medir voltaje, y corriente con gran precisión.
* @version 2.2.1
* @date 2021-04-16
*
*
* @copyright DataAnalitic (c) {2021}
*
*
*/

#ifndef BslibEnergyMeter_h
#define BslibEnergyMeter_h
#include "Arduino.h"

#define ADC_SCALE 1023.0
#define VOLT_INPUT_MAIN 5.0
#define VOLT_INPUT_DRIVER 3.3

class BslibEnergyMeter
{
// define theoretical vref calibration constant for use in readvcc()
// 1100mV*1024 ADC steps
#ifndef READVCC_CALIBRATION_CONST
#define READVCC_CALIBRATION_CONST 1126400L
#endif

class BslibEnergyMeter {
public:
void SetSensorCurrent(unsigned int _inPinCurrent, unsigned int _inPinCurrentRef, float _factorCurrent);
void SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage, float _offsetVoltage);
void SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage);
void SetSensorCurrent(unsigned int _inPinCurrent, unsigned int _inPinCurrentRef, float _factorCurrent);
void SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage, float _offsetVoltage);
void SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage);

unsigned int FilterValueADC(unsigned int pinADC, unsigned int samples);
unsigned int AutoCalibrationCurrent(unsigned int _numberOfSamples);
void SetCurrentReference(unsigned int _currentReference);
void SetCurrentReference(int _currentReference);
void SetAnalogReference(float _analogReference);
void SetFilterSamples(unsigned int _numberOfSamples);

float GetCurrent(unsigned int _numberOfSamples);
float GetVoltage(unsigned int _numberOfSamples);
int FilterValueADC(unsigned int pinADC);
float SoftwareDAC(int digitalValue);

private:
unsigned int currentReference;
unsigned int calibrationCurrent;
int AutoCalibrationCurrent(int lastVRef);

void CalCurrent();
int GetCurrentRefADC();
int GetCurrentADC();
float GetCurrentDAC();
float GetCurrent();

unsigned int inPinCurrent;
unsigned int inPinCurrentRef;
unsigned int inPinVoltage;
void CalVoltage();
int GetVoltageADC();
float GetVoltageDAC();
float GetVoltage();

// int GetDistanceADC();
// float GetDistanceDAC();
// float GetDistance();

float ReadVcc();

private:
unsigned int inPinCurrent;
unsigned int inPinCurrentRef;
unsigned int inPinVoltage;

float factorCurrent;
float factorVoltage;
float offsetVoltage;
unsigned int numberOfSamples;
float analogReference;
float factorCurrent;
float factorVoltage;
float offsetVoltage;
};

#endif

0 comments on commit 7a4039a

Please sign in to comment.