Skip to content

Instantly share code, notes, and snippets.

@OrganicIrradiation
Created March 23, 2015 10:27
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save OrganicIrradiation/9e51a0a6c3bcc8ff3871 to your computer and use it in GitHub Desktop.
Save OrganicIrradiation/9e51a0a6c3bcc8ff3871 to your computer and use it in GitHub Desktop.
Arduino FIO Internal Voltmeter and Thermometer
long readTemp() {
long result;
// Read temperature sensor against 1.1V reference
ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX3);
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = (result - 125) * 1075;
return result;
}
// See: http://code.google.com/p/tinkerit/wiki/SecretThermometer
float readTemp() {
signed long resultTemp;
float resultTempFloat;
// Read temperature sensor against 1.1V reference
ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX3);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
resultTemp = ADCL;
resultTemp |= ADCH<<8;
resultTempFloat = (float) resultTemp * 0.9338 - 282.7; // Apply calibration correction
resultTempFloat = resultTempFloat * 1.8 + 32.0; // Convert to F
return resultTempFloat;
}
long readVcc() {
long result;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
result = ADCL;
result |= ADCH<<8;
result = 1126400L / result; // Back-calculate AVcc in mV
return result;
}
// See: http://code.google.com/p/tinkerit/wiki/SecretVoltmeter
float readVcc() {
signed long resultVcc;
float resultVccFloat;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
resultVcc = ADCL;
resultVcc |= ADCH<<8;
resultVcc = 1126400L / resultVcc; // Back-calculate AVcc in mV
resultVccFloat = (float) resultVcc / 1000.0; // Convert to Float
return resultVccFloat;
}
/*
* SuperSleepyTempAndVolts SuperSleepyTempAndVolts.ino
* Steven A Cholewiak - www.semifluid.com
*
* This sketch takes advantage of the XBee's hibernation mode as
* well as the Ardunio Fio's Power Save Mode to grossly reduce power
* consumption. Also uses some *supersecret* code to access the Arduino
* Fio's own voltage rail (http://code.google.com/p/tinkerit/wiki/SecretVoltmeter)
* and internal thermometer (http://code.google.com/p/tinkerit/wiki/SecretThermometer).
*
*/
#include <avr/wdt.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
const int ledPin = 13;
const int XBeeSleep = 2; // Connect to XBee DTR for hibernation mode
const int waitPeriod = 8; // Number of 8 second cycles before waking
// up XBee and sending data (8*8 = 64 seconds)
// See: http://code.google.com/p/tinkerit/wiki/SecretVoltmeter
float readVcc() {
signed long resultVcc;
float resultVccFloat;
// Read 1.1V reference against AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
resultVcc = ADCL;
resultVcc |= ADCH<<8;
resultVcc = 1126400L / resultVcc; // Back-calculate AVcc in mV
resultVccFloat = (float) resultVcc / 1000.0; // Convert to Float
return resultVccFloat;
}
// See: http://code.google.com/p/tinkerit/wiki/SecretThermometer
float readTemp() {
signed long resultTemp;
float resultTempFloat;
// Read temperature sensor against 1.1V reference
ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX3);
delay(10); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Convert
while (bit_is_set(ADCSRA,ADSC));
resultTemp = ADCL;
resultTemp |= ADCH<<8;
resultTempFloat = (float) resultTemp * 0.9338 - 282.7; // Apply calibration correction
resultTempFloat = resultTempFloat * 1.8 + 32.0; // Convert to F
return resultTempFloat;
}
void sleepNow()
{
/* Now is the time to set the sleep mode. In the Atmega8 datasheet
* http://www.atmel.com/dyn/resources/prod_documents/doc2486.pdf on page 35
* there is a list of sleep modes which explains which clocks and
* wake up sources are available in which sleep modus.
*
* In the avr/sleep.h file, the call names of these sleep modus are to be found:
*
* The 5 different modes are:
* SLEEP_MODE_IDLE -the least power savings
* SLEEP_MODE_ADC
* SLEEP_MODE_PWR_SAVE
* SLEEP_MODE_STANDBY
* SLEEP_MODE_PWR_DOWN -the most power savings
*
* the power reduction management <avr/power.h> is described in
* http://www.nongnu.org/avr-libc/user-manual/group__avr__power.html
*/
set_sleep_mode(SLEEP_MODE_PWR_SAVE); // Sleep mode is set here
sleep_enable(); // Enables the sleep bit in the mcucr register
// so sleep is possible. just a safety pin
sleep_mode(); // Here the device is actually put to sleep!!
// THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
sleep_disable(); // Dirst thing after waking from sleep:
// disable sleep...
}
ISR (WDT_vect) { // WDT Wakeup
cli();
wdt_disable();
sei();
}
// Variable Definition
volatile int MeasurementID = 1;
volatile int timeKeeper = 0;
volatile float averageVcc = 0.0;
volatile float averageTemp = 0.0;
void setup() {
Serial.begin(57600);
pinMode(XBeeSleep, OUTPUT);
digitalWrite(XBeeSleep, 0); // Enable XBee
digitalWrite(ledPin, 1); // Turn on Notification LED
delay(4000); // 4 second LED blink, good for wireless programming
digitalWrite(ledPin, 0); // Turn off Notification LED
Serial.write( 170 ); // Sync Byte
Serial.print( '\t' ); // Tab
Serial.print( '0' ); // Reading # (0)
Serial.print( '\t' ); // Tab
Serial.print( '0' ); // Voltage (unmeasured, so 0)
Serial.print( '\t' ); // Tab
Serial.println( '0' ); // Temperature (unmeasured, so 0)
digitalWrite(XBeeSleep, 1); // Disable XBee
}
void loop() {
//
averageVcc = averageVcc + (float) readVcc();
averageTemp = averageTemp + (float) readTemp();
if (timeKeeper == (waitPeriod-1)) { // Transmit every 8*8 (64) seconds
digitalWrite(XBeeSleep, 0); // Enable XBee
delay(50); // Wait for XBee Wakeup
Serial.write( 170 ); // Sync Byte
Serial.print( '\t' );
Serial.print( MeasurementID, DEC );
Serial.print( '\t' );
Serial.print( (float) (averageVcc/waitPeriod) , 3);
Serial.print( '\t' );
Serial.println( (float) (averageTemp/waitPeriod) , 2);
MeasurementID++;
digitalWrite(ledPin, 1); // Turn on Notification LED
delay(50); // Blink LED
digitalWrite(ledPin, 0); // Turn off Notification LED
digitalWrite(XBeeSleep, 1); // Disable XBee
averageVcc = 0; // Reset voltage for new measurements
averageTemp = 0; // Reset temperature for new measurements
timeKeeper = 0;
} else { // Add a reading to the average
digitalWrite(ledPin, 1); // Turn on Notification LED
delay(1); // Blink LED very quickly
digitalWrite(ledPin, 0); // Turn off Notification LED
timeKeeper++;
}
wdt_reset(); // Get ready to go to sleep...
watchdogEnable(); // Turn on the watchdog timer
sleepNow(); // Go to sleep, watchdog timer will wake later
}
void watchdogEnable() { // Turn on watchdog timer; interrupt mode every 8.0s
cli();
MCUSR = 0;
WDTCSR |= B00011000;
//WDTCSR = B01000111; // 2 Second Timeout
//WDTCSR = B01100000; // 4 Second Timeout
WDTCSR = B01100001; // 8 Second Timeout
sei();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment