Skip to content

Commit 7a4039a

Browse files
authored
Merge pull request #2 from bluesensor/adc-develop
Adc develop
2 parents 5eceffa + 1c97465 commit 7a4039a

File tree

2 files changed

+206
-100
lines changed

2 files changed

+206
-100
lines changed

src/BslibEnergyMeter.cpp

Lines changed: 162 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -4,128 +4,213 @@
44
* @brief Biblioteca medidor de energia, permite medir voltaje, y corriente con gran precisión.
55
* @version 2.2.1
66
* @date 2021-04-16
7-
*
7+
*
88
* @copyright DataAnalitic (c) {2021}
9-
*
9+
*
1010
*/
1111

1212
#include "BslibEnergyMeter.h"
1313

14+
int currentReference;
15+
int calibrationCurrent;
16+
17+
int currentADC;
18+
int currentRefADC;
19+
float currentDAC;
20+
float current;
21+
22+
int voltageADC;
23+
float voltageDAC;
24+
float voltage;
25+
1426
/**
1527
* @brief Configuracion de los pines del sensor de corriente
16-
*
28+
*
1729
* @param _inPinCurrent pin analógico Vout del sensor de voltaje
1830
* @param _inPinCurrentRef pin analógico Vref del sensor
1931
* @param _factorCurrent factor de sensiblidad del sensor
2032
*/
21-
void BslibEnergyMeter::SetSensorCurrent(unsigned int _inPinCurrent, unsigned int _inPinCurrentRef, float _factorCurrent)
22-
{
23-
inPinCurrent = _inPinCurrent;
24-
inPinCurrentRef = _inPinCurrentRef;
25-
factorCurrent = _factorCurrent;
33+
void BslibEnergyMeter::SetSensorCurrent(unsigned int _inPinCurrent, unsigned int _inPinCurrentRef, float _factorCurrent) {
34+
inPinCurrent = _inPinCurrent;
35+
inPinCurrentRef = _inPinCurrentRef;
36+
factorCurrent = _factorCurrent;
2637
}
2738

2839
/**
2940
* @brief Configuracion de los pines del sensor de voltaje
30-
*
41+
*
3142
* @param _inPinVoltage pin analógico de Vout de sensor de voltaje
3243
* @param _factorVoltage factor de sensiblidad del sensor
3344
* @param _offsetVoltage compensacion para obtener voltaje real
3445
*/
35-
void BslibEnergyMeter::SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage, float _offsetVoltage = 0)
36-
{
37-
inPinVoltage = _inPinVoltage;
38-
factorVoltage = _factorVoltage;
39-
offsetVoltage = _offsetVoltage;
46+
void BslibEnergyMeter::SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage, float _offsetVoltage = 0) {
47+
inPinVoltage = _inPinVoltage;
48+
factorVoltage = _factorVoltage;
49+
offsetVoltage = _offsetVoltage;
4050
}
4151

4252
/**
4353
* @brief Configuracion de los pines del sensor de voltaje
44-
*
54+
*
4555
* @param _inPinVoltage pin analógico de sensor de voltaje
4656
* @param _factorVoltage factor de sensiblidad del sensor
4757
*/
48-
void BslibEnergyMeter::SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage)
49-
{
50-
inPinVoltage = _inPinVoltage;
51-
factorVoltage = _factorVoltage;
58+
void BslibEnergyMeter::SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage) {
59+
inPinVoltage = _inPinVoltage;
60+
factorVoltage = _factorVoltage;
5261
}
5362

5463
/**
55-
* @brief Filtro suave (promedio) de lecturas ADC
56-
*
57-
* @param pinADC pin analógico al cual leer
58-
* @param samples número de muestras para el promedio
59-
* @return int
64+
* @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.
65+
*
66+
* @param _currentReference
6067
*/
61-
unsigned int BslibEnergyMeter::FilterValueADC(unsigned int pinADC, unsigned int samples)
62-
{
63-
unsigned long valueADC = 0;
64-
unsigned int filteredValueADC = 0;
65-
for (unsigned int i = 0; i < samples; i++)
66-
{
67-
valueADC += analogRead(pinADC);
68-
}
69-
filteredValueADC = valueADC / samples;
70-
return filteredValueADC;
68+
void BslibEnergyMeter::SetCurrentReference(int _currentReference) {
69+
currentReference = _currentReference;
7170
}
7271

7372
/**
74-
* @brief Calibrar automaticamente el sensor de corriente con Vref. Usar esta función cuando la corriente sea cero.
75-
*
76-
* @param _numberOfSamples número de muestras a tomar en cada lenctura
77-
* @return int
73+
* @brief Configura el valor de referencia analógica para el MCU
74+
*
75+
* @param _analogReference
7876
*/
79-
unsigned int BslibEnergyMeter::AutoCalibrationCurrent(unsigned int _numberOfSamples)
80-
{
81-
calibrationCurrent = FilterValueADC(inPinCurrentRef, _numberOfSamples);
82-
// algunos sensores tienen un offset (compensacion) cuando Vref<Vout
83-
float offset = FilterValueADC(inPinCurrent, _numberOfSamples) - calibrationCurrent;
84-
calibrationCurrent += offset;
85-
return calibrationCurrent;
77+
void BslibEnergyMeter::SetAnalogReference(float _analogReference) {
78+
analogReference = _analogReference;
79+
}
80+
81+
void BslibEnergyMeter::SetFilterSamples(unsigned int _numberOfSamples) {
82+
numberOfSamples = _numberOfSamples;
8683
}
8784

8885
/**
89-
* @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.
90-
*
91-
* @param _currentReference
86+
* @brief Filtro suave (promedio) de lecturas ADC
87+
*
88+
* @param pinADC pin analógico al cual leer
89+
* @return int
9290
*/
93-
void BslibEnergyMeter::SetCurrentReference(unsigned int _currentReference)
94-
{
95-
currentReference = _currentReference;
91+
int BslibEnergyMeter::FilterValueADC(unsigned int pinADC) {
92+
unsigned long valueADC = 0;
93+
int filteredValueADC = 0;
94+
for (int i = 0; i < numberOfSamples; i++) {
95+
valueADC += analogRead(pinADC);
96+
}
97+
filteredValueADC = valueADC / numberOfSamples;
98+
return filteredValueADC;
9699
}
97100

98101
/**
99-
* @brief Obtiene la corriente del sensor motor
100-
*
101-
* @param _numberOfSamples número de muestras a tomar en cada lenctura
102-
* @return float
102+
* @brief Calcula el valor en voltaje de la lectura ADC del MCU
103+
*
104+
* @param digitalValue
105+
* @return float
103106
*/
104-
float BslibEnergyMeter::GetCurrent(unsigned int _numberOfSamples)
105-
{
106-
int filteredCurrent = FilterValueADC(inPinCurrent, _numberOfSamples) - currentReference;
107-
108-
if (filteredCurrent < 0)
109-
{
110-
filteredCurrent = 0;
111-
}
112-
113-
float convertValueADC = float(filteredCurrent) / ADC_SCALE * VOLT_INPUT_DRIVER;
114-
float current = convertValueADC / factorCurrent;
115-
return current;
107+
float BslibEnergyMeter::SoftwareDAC(int digitalValue) {
108+
float convertValueDCA = float(digitalValue) / ADC_SCALE * analogReference;
109+
return convertValueDCA;
116110
}
117111

118112
/**
119-
* @brief Obtiene el voltaje de la bateria
120-
*
121-
* @param _numberOfSamples número de muestras a tomar en cada lenctura
122-
* @return float
113+
* @brief Calibrar automaticamente el sensor de corriente con Vref. Usar esta función cuando la corriente sea cero.
114+
*
115+
* @return int
123116
*/
124-
float BslibEnergyMeter::GetVoltage(unsigned int _numberOfSamples)
125-
{
126-
int filteredVoltage = FilterValueADC(inPinVoltage, _numberOfSamples);
127-
float convertValueADC = float(filteredVoltage) / ADC_SCALE * VOLT_INPUT_MAIN;
128-
float voltage = (convertValueADC * factorVoltage) + offsetVoltage;
117+
int BslibEnergyMeter::AutoCalibrationCurrent(int lastVRef) {
118+
119+
float vRef = FilterValueADC(inPinCurrentRef);
120+
float vOut = FilterValueADC(inPinCurrent);
121+
122+
if (lastVRef == vRef) {
123+
calibrationCurrent = vRef;
124+
} else {
125+
calibrationCurrent = vRef;
126+
}
127+
// algunos sensores tienen un offset (compensacion) cuando Vref<Vout
128+
// float offset = vOut - vRef;
129+
// calibrationCurrent += offset;
130+
return calibrationCurrent;
131+
}
132+
133+
void BslibEnergyMeter::CalCurrent() {
134+
currentRefADC = FilterValueADC(inPinCurrentRef);
135+
currentADC = FilterValueADC(inPinCurrent);
136+
137+
int offsetCurrent = currentADC - currentRefADC;
138+
139+
if (offsetCurrent < 0) {
140+
offsetCurrent = 0;
141+
}
142+
143+
currentDAC = SoftwareDAC(offsetCurrent);
144+
current = currentDAC / factorCurrent;
145+
}
146+
147+
int BslibEnergyMeter::GetCurrentRefADC() {
148+
return currentRefADC;
149+
}
150+
151+
int BslibEnergyMeter::GetCurrentADC() {
152+
return currentADC;
153+
}
154+
155+
float BslibEnergyMeter::GetCurrentDAC() {
156+
return currentDAC;
157+
}
158+
float BslibEnergyMeter::GetCurrent() {
159+
CalCurrent();
160+
return current;
161+
}
162+
163+
// -----------------------------------------------------------
164+
165+
void BslibEnergyMeter::CalVoltage() {
166+
voltageADC = FilterValueADC(inPinVoltage);
167+
voltageDAC = SoftwareDAC(voltageADC);
168+
voltage = (voltageDAC * factorVoltage) + offsetVoltage;
169+
}
170+
171+
int BslibEnergyMeter::GetVoltageADC() {
172+
return voltageADC;
173+
}
174+
175+
float BslibEnergyMeter::GetVoltageDAC() {
176+
return voltageDAC;
177+
}
178+
179+
float BslibEnergyMeter::GetVoltage() {
180+
CalVoltage();
181+
182+
return voltage;
183+
}
184+
185+
float BslibEnergyMeter::ReadVcc() {
186+
long vccADC;
187+
188+
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
189+
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
190+
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__)
191+
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
192+
#elif defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_AT90USB1286__)
193+
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
194+
ADCSRB &= ~_BV(MUX5); // Without this the function always returns -1 on the ATmega2560 http://openenergymonitor.org/emon/node/2253#comment-11432
195+
#elif defined(__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
196+
ADMUX = _BV(MUX5) | _BV(MUX0);
197+
#elif defined(__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
198+
ADMUX = _BV(MUX3) | _BV(MUX2);
199+
200+
#endif
129201

130-
return voltage;
202+
#if defined(__AVR__)
203+
delay(2); // Wait for Vref to settle
204+
ADCSRA |= _BV(ADSC); // Convert
205+
while (bit_is_set(ADCSRA, ADSC))
206+
;
207+
vccADC = ADCL;
208+
vccADC |= ADCH << 8;
209+
vccADC = READVCC_CALIBRATION_CONST / vccADC; // 1100mV*1024 ADC steps
210+
return vccADC / 1000.0;
211+
#elif defined(__arm__)
212+
return (3300); // Arduino Due
213+
#else
214+
return (3300); // Guess that other un-supported architectures will be running a 3.3V!
215+
#endif
131216
}

src/BslibEnergyMeter.h

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,44 +4,65 @@
44
* @brief Biblioteca medidor de energia, permite medir voltaje, y corriente con gran precisión.
55
* @version 2.2.1
66
* @date 2021-04-16
7-
*
7+
*
88
* @copyright DataAnalitic (c) {2021}
9-
*
9+
*
1010
*/
1111

1212
#ifndef BslibEnergyMeter_h
1313
#define BslibEnergyMeter_h
1414
#include "Arduino.h"
1515

1616
#define ADC_SCALE 1023.0
17-
#define VOLT_INPUT_MAIN 5.0
18-
#define VOLT_INPUT_DRIVER 3.3
1917

20-
class BslibEnergyMeter
21-
{
18+
// define theoretical vref calibration constant for use in readvcc()
19+
// 1100mV*1024 ADC steps
20+
#ifndef READVCC_CALIBRATION_CONST
21+
#define READVCC_CALIBRATION_CONST 1126400L
22+
#endif
23+
24+
class BslibEnergyMeter {
2225
public:
23-
void SetSensorCurrent(unsigned int _inPinCurrent, unsigned int _inPinCurrentRef, float _factorCurrent);
24-
void SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage, float _offsetVoltage);
25-
void SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage);
26+
void SetSensorCurrent(unsigned int _inPinCurrent, unsigned int _inPinCurrentRef, float _factorCurrent);
27+
void SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage, float _offsetVoltage);
28+
void SetSensorVoltage(unsigned int _inPinVoltage, float _factorVoltage);
2629

27-
unsigned int FilterValueADC(unsigned int pinADC, unsigned int samples);
28-
unsigned int AutoCalibrationCurrent(unsigned int _numberOfSamples);
29-
void SetCurrentReference(unsigned int _currentReference);
30+
void SetCurrentReference(int _currentReference);
31+
void SetAnalogReference(float _analogReference);
32+
void SetFilterSamples(unsigned int _numberOfSamples);
3033

31-
float GetCurrent(unsigned int _numberOfSamples);
32-
float GetVoltage(unsigned int _numberOfSamples);
34+
int FilterValueADC(unsigned int pinADC);
35+
float SoftwareDAC(int digitalValue);
3336

34-
private:
35-
unsigned int currentReference;
36-
unsigned int calibrationCurrent;
37+
int AutoCalibrationCurrent(int lastVRef);
38+
39+
void CalCurrent();
40+
int GetCurrentRefADC();
41+
int GetCurrentADC();
42+
float GetCurrentDAC();
43+
float GetCurrent();
3744

38-
unsigned int inPinCurrent;
39-
unsigned int inPinCurrentRef;
40-
unsigned int inPinVoltage;
45+
void CalVoltage();
46+
int GetVoltageADC();
47+
float GetVoltageDAC();
48+
float GetVoltage();
49+
50+
// int GetDistanceADC();
51+
// float GetDistanceDAC();
52+
// float GetDistance();
53+
54+
float ReadVcc();
55+
56+
private:
57+
unsigned int inPinCurrent;
58+
unsigned int inPinCurrentRef;
59+
unsigned int inPinVoltage;
4160

42-
float factorCurrent;
43-
float factorVoltage;
44-
float offsetVoltage;
61+
unsigned int numberOfSamples;
62+
float analogReference;
63+
float factorCurrent;
64+
float factorVoltage;
65+
float offsetVoltage;
4566
};
4667

4768
#endif

0 commit comments

Comments
 (0)