Last active
August 29, 2015 14:01
-
-
Save rlogiacco/c21f2015d1e797fb2202 to your computer and use it in GitHub Desktop.
VoltageReference
This file contains hidden or 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
#include <VoltageReference.h> | |
VoltageReference vRef; | |
void setup() { | |
Serial.begin(9600); | |
while (!Serial); | |
Serial.println("Calibrating voltage reference"); | |
vRef.begin(); | |
} | |
void loop() { | |
digitalWrite(13, HIGH); | |
delay(500); | |
digitalWrite(13, LOW); | |
delay(500); | |
int analog = analogRead(A0); | |
int vcc = vRef.readVcc(); | |
Serial.print("Input voltage is "); | |
Serial.print(vcc); | |
Serial.print("mV, analog pin voltage is "); | |
Serial.print(analog / 1024 * vcc); | |
Serial.print("mV"); | |
delay(50); | |
} |
This file contains hidden or 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
#include <EEPROM.h> | |
#include <VoltageReference.h> | |
// sets the storage area to the very end of the EEPROM | |
#define VREF_EEPROM_ADDR (E2END - 2) | |
int address = VREF_EEPROM_ADDR; | |
/** | |
* Loads the calibration value from EEPROM | |
*/ | |
uint32_t load(uint16_t address) { | |
uint32_t calibration = 0; | |
byte msb = EEPROM.read(address); | |
byte mid = EEPROM.read(address + 1); | |
byte lsb = EEPROM.read(address + 2); | |
calibration = (((long) msb) << 16) | ((mid << 8) | ((lsb & 0xFF) & 0xFFFF)); | |
if (calibration == 16777215L) { | |
Serial.println("No calibration value stored into EEPROM, using default"); | |
calibration = DEFAULT_REFERENCE_CALIBRATION; | |
} else { | |
Serial.print("Read from EEPROM address "); | |
Serial.print(address); | |
Serial.print(" calibration value "); | |
Serial.println(calibration); | |
} | |
return calibration; | |
} | |
/** | |
* Saves the calibration value into EEPROM | |
*/ | |
void save(uint16_t address, uint32_t calibration) { | |
EEPROM.write(address, calibration >> 16); | |
EEPROM.write(address + 1, calibration >> 8); | |
EEPROM.write(address + 2, calibration & 0xFF); | |
Serial.println("Saved calibration value into EEPROM"); | |
} | |
/** | |
* Clears the calibration value from EEPROM | |
*/ | |
void clear(uint16_t address) { | |
EEPROM.write(address, 0xFF); | |
EEPROM.write(address + 1, 0xFF); | |
EEPROM.write(address + 2, 0xFF); | |
Serial.println("Cleared calibration value from EEPROM"); | |
} | |
void menu() { | |
Serial.println("--- MENU ---"); | |
Serial.println("\tR to read Vcc"); | |
Serial.println("\tL to load calibration from EEPROM"); | |
Serial.println("\tS to store calibration into EEPROM"); | |
Serial.println("\tC to clear calibration from EEPROM"); | |
Serial.println("\tdddd (4 digits) to calibrate for mV"); | |
Serial.println("\tA to print EEPROM calibration start address (length 3)"); | |
Serial.println("\tAdddd (4 digits) to set EEPROM calibration start address (length 3)"); | |
Serial.println("\tH prints this help"); | |
} | |
VoltageReference vRef; | |
void setup() { | |
Serial.begin(9600); | |
while (!Serial); | |
vRef.begin(); | |
menu(); | |
} | |
void parse() { | |
char c = Serial.read(); | |
if (isalpha(c)) { | |
if (c == 's' || c == 'S') { | |
save(address, vRef.calibrate(vRef.readVcc())); | |
} else if (c == 'c' || c == 'C') { | |
clear(address); | |
} else if (c == 'l' || c == 'L') { | |
vRef.begin(load(address)); | |
} else if (c == 'r' || c == 'R') { | |
Serial.print("Calculated input voltage is "); | |
Serial.print(vRef.readVcc()); | |
Serial.println("mV"); | |
} else if (c == 'a' || c == 'A') { | |
if (Serial.available() > 0) { | |
c = Serial.read(); | |
char* buffer = new char[5]; | |
uint8_t i = 0; | |
while (isdigit(c)) { | |
buffer[i++] = c; | |
c = Serial.read(); | |
} | |
buffer[i++] = '\0'; | |
address = atol(buffer); | |
Serial.print("Setting EEPROM start address to "); | |
Serial.println(address); | |
} else { | |
Serial.print("EEPROM start address is "); | |
Serial.println(address); | |
} | |
} else if (c == 'h' || c == 'H') { | |
menu(); | |
} | |
} else { | |
char* buffer = new char[5]; | |
uint8_t i = 0; | |
while (isdigit(c)) { | |
buffer[i++] = c; | |
c = Serial.read(); | |
} | |
buffer[i++] = '\0'; | |
long voltage = atol(buffer); | |
Serial.print("Calibrating for Vcc "); | |
Serial.print(voltage); | |
Serial.println("mV"); | |
uint32_t calibration = vRef.calibrate(voltage); | |
Serial.print("Calibration value is "); | |
Serial.println(calibration); | |
vRef.begin(calibration); | |
} | |
} | |
void loop() { | |
digitalWrite(13, HIGH); | |
delay(1000); | |
digitalWrite(13, LOW); | |
delay(1000); | |
if (Serial.available() > 0) { | |
parse(); | |
} | |
} |
This file contains hidden or 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
/* | |
VoltageSource.cpp - VoltageSource library | |
Copyright (c) 2014 Roberto Lo Giacco. All right reserved. | |
This library is free software; you can redistribute it and/or | |
modify it under the terms of the GNU Lesser General Public | |
License as published by the Free Software Foundation; either | |
version 2.1 of the License, or (at your option) any later version. | |
This library is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
Lesser General Public License for more details. | |
You should have received a copy of the GNU Lesser General Public | |
License along with this library; if not, write to the Free Software | |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
*/ | |
/****************************************************************************** | |
* Includes | |
******************************************************************************/ | |
#include "Arduino.h" | |
#include "VoltageReference.h" | |
/****************************************************************************** | |
* User API | |
******************************************************************************/ | |
void VoltageReference::begin(uint32_t calibration) { | |
VoltageReference::calibration = calibration; | |
} | |
void VoltageReference::begin(uint8_t hi, uint8_t mid, uint8_t low) { | |
VoltageReference::calibration = mergeBytes(hi, mid, low); | |
} | |
uint16_t VoltageReference::readInternalRef() { | |
// Read 1.1V reference against AVcc | |
// Set the reference to Vcc and the measurement to the internal 1.1V reference | |
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega1284P__) | |
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); | |
#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); | |
#else | |
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1); | |
#endif | |
delay(2); // Wait for Vref to settle | |
ADCSRA |= _BV(ADSC); // Start conversion | |
while (bit_is_set(ADCSRA, ADSC)); // measuring | |
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH | |
uint8_t high = ADCH; // unlocks both | |
return (high << 8) | low; // raw bandgap value; | |
} | |
uint16_t VoltageReference::readVcc() { | |
return calibration / readInternalRef(); | |
} | |
uint32_t VoltageReference::calibrate(uint16_t milliVolts) { | |
return ((uint32_t)milliVolts * readInternalRef()); | |
} |
This file contains hidden or 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
/* | |
VoltageSource.cpp - VoltageSource library | |
Copyright (c) 2014 Roberto Lo Giacco. All right reserved. | |
This library is free software; you can redistribute it and/or | |
modify it under the terms of the GNU Lesser General Public | |
License as published by the Free Software Foundation; either | |
version 2.1 of the License, or (at your option) any later version. | |
This library is distributed in the hope that it will be useful, | |
but WITHOUT ANY WARRANTY; without even the implied warranty of | |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
Lesser General Public License for more details. | |
You should have received a copy of the GNU Lesser General Public | |
License along with this library; if not, write to the Free Software | |
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
*/ | |
#ifndef _VOLTAGE_REFERENCE_ | |
#define _VOLTAGE_REFERENCE_ | |
#include "Arduino.h" | |
#define SERIAL_DEBUG false | |
#include <SerialDebug.h> | |
#define DEFAULT_REFERENCE_CALIBRATION 1126400L | |
#define INVALID_REFERENCE_CALIBRATION 16777215L | |
#define getHiByte(calibration) (calibration >> 16) | |
#define getMidByte(calibration) (calibration >> 8) | |
#define getLowByte(calibration) (calibration & 0xFF) | |
#define mergeBytes(hi, mid, low) ((((long)hi) << 16) | ((mid << 8) | ((low & 0xFF) & 0xFFFF))) | |
class VoltageReference { | |
private: | |
uint32_t calibration; | |
/** | |
* Reads the internal voltage reference against Vcc | |
*/ | |
uint16_t readInternalRef(); | |
public: | |
/** | |
* Initializes the library by setting the calibration value for the 1.1V reference | |
* either to the provided value or to its default | |
*/ | |
void begin(uint32_t reference = DEFAULT_REFERENCE_CALIBRATION); | |
/** | |
* Initializes the library by setting the calibration value for the 1.1V reference | |
* from a three bytes representation | |
*/ | |
void begin(uint8_t hi, uint8_t mid, uint8_t low); | |
/** | |
* Reads the input voltage value applying any necessary calibration | |
*/ | |
uint16_t readVcc(); | |
/** | |
* Returns the calibration value to be used for the specified input voltage | |
*/ | |
uint32_t calibrate(uint16_t milliVolt); | |
}; | |
#endif // _VOLTAGE_REFERENCE_ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment