-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
308 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,151 @@ | ||
/* | ||
MCMVoltSense.cpp - Library for Grove AC Voltage Sensor | ||
Author: Christopher Mendez, November 3 2022 | ||
*/ | ||
|
||
#include "MCMVoltSense.h" | ||
|
||
#if defined(ARDUINO) && ARDUINO >= 100 | ||
#include "Arduino.h" | ||
#else | ||
#include "WProgram.h" | ||
#endif | ||
|
||
//---------------------------------------------------------------------------------- | ||
// Sets the analog pin, calibration factors for the voltage and phase to be used | ||
//---------------------------------------------------------------------------------- | ||
void MCMmeter::VoltageStp(unsigned int _analogVin, double _VoltCal, double _PhaseCal) | ||
{ | ||
offsetV = ADC_COUNTS >> 1; | ||
PhaseCal = _PhaseCal; | ||
VoltCal = _VoltCal; | ||
analogVin = _analogVin; | ||
} | ||
|
||
//------------------------------------------------------------------------------------------------- | ||
// Voltage calculation from a window sample of the analog input from the Grove AC Voltage Sensor | ||
//------------------------------------------------------------------------------------------------- | ||
void MCMmeter::analogVoltage(unsigned int cycles, unsigned int timeout) | ||
{ | ||
|
||
cycles = cycles/2; // Converting cycles to zero crossings | ||
|
||
int SupplyVoltage = boardVcc(); | ||
|
||
unsigned int crossCount = 0; // Used to measure number of times threshold is crossed. | ||
unsigned int numberOfSamples = 0; // This is now incremented | ||
|
||
//------------------------------------------------------------------------------------------------------------------------- | ||
// 1) Waits for the waveform to be close to 'zero' (mid-scale adc) part in sin curve. | ||
//------------------------------------------------------------------------------------------------------------------------- | ||
unsigned long start = millis(); // timer for the timeout. | ||
|
||
while (1) // wait for the sine signal to zero cross, break if timeout | ||
{ | ||
startV = analogRead(analogVin); // using the voltage waveform | ||
if ((startV < (ADC_COUNTS * 0.51)) && (startV > (ADC_COUNTS * 0.49))) | ||
break; // check its within range to start from here | ||
if ((millis() - start) > timeout) | ||
break; | ||
} | ||
|
||
//------------------------------------------------------------------------------------------------------------------------- | ||
// 2) Voltage measurement loop | ||
//------------------------------------------------------------------------------------------------------------------------- | ||
start = millis(); | ||
|
||
while ((crossCount < cycles) && ((millis() - start) < timeout)) | ||
{ | ||
numberOfSamples++; // Count number of times looped. | ||
lastFilteredV = filteredV; // Used for delay/phase compensation | ||
|
||
//----------------------------------------------------------------------------- | ||
// A) Read in raw voltage and current samples | ||
//----------------------------------------------------------------------------- | ||
sampleV = analogRead(analogVin); // Read in raw voltage signal | ||
|
||
//----------------------------------------------------------------------------- | ||
// B) Apply digital low pass filters to extract the 2.5 V or 1.65 V dc offset, | ||
// then subtract this - signal is now centred on 0 counts. | ||
//----------------------------------------------------------------------------- | ||
offsetV = offsetV + ((sampleV - offsetV) / ADC_COUNTS); | ||
filteredV = sampleV - offsetV; | ||
|
||
//----------------------------------------------------------------------------- | ||
// C) Root-mean-square method voltage | ||
//----------------------------------------------------------------------------- | ||
sqV = filteredV * filteredV; // 1) square voltage values | ||
sumV += sqV; // 2) sum | ||
|
||
//----------------------------------------------------------------------------- | ||
// E) Phase calibration | ||
//----------------------------------------------------------------------------- | ||
phaseShiftedV = lastFilteredV + PhaseCal * (filteredV - lastFilteredV); | ||
|
||
//----------------------------------------------------------------------------- | ||
// G) Find the number of times the voltage has crossed the initial voltage | ||
// - every 2 crosses we will have sampled 1 wavelength | ||
// - so this method allows us to sample an integer number of half wavelengths which increases accuracy | ||
//----------------------------------------------------------------------------- | ||
lastVCross = checkVCross; | ||
if (sampleV > startV) | ||
checkVCross = true; | ||
else | ||
checkVCross = false; | ||
if (numberOfSamples == 1) | ||
lastVCross = checkVCross; | ||
|
||
if (lastVCross != checkVCross) | ||
crossCount++; | ||
} | ||
|
||
//------------------------------------------------------------------------------------------------------------------------- | ||
// 3) Post loop calculations | ||
//------------------------------------------------------------------------------------------------------------------------- | ||
// Calculation of the root of the mean of the voltage and current squared (rms) | ||
// Calibration coefficients applied. | ||
|
||
double V_RATIO = VoltCal * ((SupplyVoltage / 1000.0) / (ADC_COUNTS)); | ||
Vrms = V_RATIO * sqrt(sumV / numberOfSamples); | ||
|
||
// Reset accumulators | ||
sumV = 0; | ||
//-------------------------------------------------------------------------------------- | ||
} | ||
|
||
//------------------------------------------------------------------------------------------------------------------------- | ||
// Function that measures the supply voltage of the boards. | ||
//------------------------------------------------------------------------------------------------------------------------- | ||
long MCMmeter::boardVcc() | ||
{ | ||
|
||
long result; | ||
|
||
#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 | ||
#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 | ||
|
||
#if defined(__AVR__) | ||
delay(2); // Wait for the reference voltage to stabilize | ||
ADCSRA |= _BV(ADSC); // Convert | ||
while (bit_is_set(ADCSRA, ADSC)) | ||
; | ||
result = ADCL; | ||
result |= ADCH << 8; | ||
result = READVCC_CALIBRATION_CONST / result; // 1100mV*1024 ADC steps | ||
return result; | ||
#elif defined(__arm__) | ||
return (3300); // Arduino Due | ||
#else | ||
return (3300); // Assuming other architectures works with 3.3V! | ||
#endif | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/* | ||
MCMVoltSense.cpp - Library for Grove AC Voltage Sensor | ||
Author: Christopher Mendez, November 3 2022 | ||
*/ | ||
|
||
#ifndef MCMVoltSense_h | ||
#define MCMVoltSense_h | ||
|
||
#if defined(ARDUINO) && ARDUINO >= 100 | ||
|
||
#include "Arduino.h" | ||
|
||
#else | ||
|
||
#include "WProgram.h" | ||
|
||
#endif | ||
|
||
// define theoretical vref calibration constant for use in boardVcc() | ||
// 1100mV*1024 ADC steps | ||
// override in your code with value for your specific AVR chip | ||
|
||
#ifndef READVCC_CALIBRATION_CONST | ||
#define READVCC_CALIBRATION_CONST 1126400L | ||
#endif | ||
|
||
// to enable 12-bit ADC resolution on Arduino Due, | ||
// include the following line in main sketch inside setup() function: | ||
// analogReadResolution(ADC_BITS); | ||
// otherwise will default to 10 bits, as in regular Arduino-based boards. | ||
|
||
#if defined(__arm__) | ||
#define ADC_BITS 12 | ||
#else | ||
#define ADC_BITS 10 | ||
#endif | ||
|
||
#define ADC_COUNTS (1<<ADC_BITS) | ||
|
||
|
||
class MCMmeter | ||
{ | ||
public: | ||
|
||
void VoltageStp(unsigned int _analogVin, double _VoltCal, double _PhaseCal); | ||
|
||
void analogVoltage(unsigned int cycles, unsigned int timeout); | ||
|
||
long boardVcc(); | ||
//Useful value variables | ||
double Vrms; | ||
|
||
private: | ||
|
||
//Set Voltage and current input pins | ||
unsigned int analogVin; | ||
|
||
//Calibration coefficients | ||
//These need to be set in order to obtain accurate results | ||
double VoltCal; | ||
double PhaseCal; | ||
|
||
//-------------------------------------------------------------------------------------- | ||
// Variable declaration | ||
//-------------------------------------------------------------------------------------- | ||
int sampleV; //sample holds the raw analog read value | ||
|
||
double lastFilteredV,filteredV; //Filtered is the raw analog value minus the DC offset | ||
double offsetV; //Low-pass filter output | ||
|
||
|
||
double phaseShiftedV; //Holds the calibrated phase shifted voltage. | ||
|
||
double sqV,sumV; //sq = squared, sum = Sum | ||
|
||
int startV; //Instantaneous voltage at start of sample window. | ||
|
||
boolean lastVCross, checkVCross; //Used to measure number of times threshold is crossed. | ||
|
||
|
||
}; | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
|
||
#include "MCMVoltSense.h" // Include MCM Volt Sense Library | ||
|
||
MCMmeter meter; // Create an instance | ||
|
||
void setup() { | ||
|
||
Serial.begin(115200); | ||
|
||
meter.VoltageStp(A1, 523.56, 1.7); // Voltage: input pin, calibration, phase_shift | ||
|
||
} | ||
|
||
void loop() { | ||
|
||
meter.analogVoltage(40,2000); // Measure the AC voltage. Arguments = (# of AC cycles, timeout) | ||
|
||
float Vrms = meter.Vrms; // Save the RMS Voltage into a variable. | ||
|
||
Serial.print("Voltage: "); | ||
Serial.print(Vrms,2); | ||
Serial.println(" V"); | ||
|
||
delay(2000); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
####################################### | ||
# Syntax Coloring Map | ||
####################################### | ||
|
||
####################################### | ||
# Datatypes (KEYWORD1) | ||
####################################### | ||
|
||
MCMmeter KEYWORD1 | ||
|
||
####################################### | ||
# Methods and Functions (KEYWORD2) | ||
####################################### | ||
|
||
VoltageStp KEYWORD2 | ||
analogVoltage KEYWORD2 | ||
boardVcc KEYWORD2 | ||
|
||
###################################### | ||
# Constants (LITERAL1) | ||
####################################### | ||
Vrms LITERAL1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "MCMVoltSense", | ||
"keywords": "voltage, measurement, energy", | ||
"description": "AC Voltage Measurement Library", | ||
"version": "0.0.1", | ||
"repository": | ||
{ | ||
"type": "git", | ||
"url": "https://github.com/mcmchris/mcm-grove-voltage-sensor.git" | ||
}, | ||
"frameworks": "arduino", | ||
"platforms": | ||
[ | ||
"atmelavr", | ||
"atmelsam" | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
name=MCMVoltSense | ||
version=0.0.1 | ||
author=mcmchris | ||
maintainer=mcmchris | ||
sentence=Voltage Measurement Library | ||
paragraph=Voltage Measurement Library | ||
category=Sensors | ||
url=https://github.com/mcmchris/mcm-grove-voltage-sensor.git | ||
architectures=* |