Sunday, April 14, 2013

Arduino - Voltmeter - Redux

This article is an evolution of a volt meter that I discussed earlier.   This iteration adds an LCD Display and the code is done entirely in Arduino instead of using my interface library.  The LCD display that I am using was borrowed from the 'Bot where I have it in use for status messaging.

The circuit diagram follows.   This diagram was done with a neat piece of software called Fritzing.  Part of the reason for this article existing was so I would have an excuse to use this software to create a diagram!
 
Here is a picture of the hardware.   As you can see from the diagram the voltage that I am reading is coming from the Arduino so will be no higher than 5v.   I am using a variable resistor as part of a voltage divider circuit to provide something to read.  The display shows that voltage on the first line and a bar graph with a range of zero to five on the second line.
Finally, the code for the demo.   The following code illustrates the reading of a voltage with the Arduino, adjusting it using the code from the Secret Arduino Voltmeter article by Scott Daniels, and presenting it on the LCD display:
/*
    Voltage Measure with LCD Display

    Created 4 March 2013 - 1

    Copyright (C) 2012 Will Kostelecky <will.kostelecky@gmail.com>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program 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 General Public License for more details.
*/

const int TRUE=1, FALSE=0;

// Include and initialize the library for the LCD
#include <LiquidCrystal.h>
LiquidCrystal lcd(0, 1, 2, 3, 4, 5);
String lcdMessage = "";
int lastMinute = 0;

int voltagePin = 5;
long voltageIn = 0;
float refVoltage = 0;
float voltage = 0;
float adjustToRef = 0;
String stars = "*******************";
char tmp[10];

/* ************************************************************************
Initialization
************************************************************************ */
void setup() {
    pinMode(voltagePin, INPUT);

    // Set the size of the lcd
    lcd.begin(16,2);
  
    // Get the reference voltage
    refVoltage = float(readVcc()) / 1000;
}

/* ************************************************************************
Process Loop
************************************************************************ */
void loop()
{
    // *****
    // Update the status on our LCD display
    // *****
    voltageIn = analogRead(voltagePin);
    adjustToRef = 1 + (refVoltage - 5) / refVoltage;
    lastMinute = millis();

    lcd.setCursor(0, 0);
    lcdMessage = "                ";
    lcd.print(lcdMessage);
    lcd.setCursor(0, 0);
    lcdMessage = "Voltage=";
    voltage = (float(voltageIn) / 204.8) * adjustToRef;
    dtostrf(voltage, 1, 2, tmp);
    lcdMessage += tmp;
    lcd.print(lcdMessage);

    lcd.setCursor(0, 1);
    lcdMessage = "                ";
    lcd.print(lcdMessage);
    lcd.setCursor(0, 1);
    voltage = voltage * 16 / 5;
    lcd.print(stars.substring(0, int(voltage)));

    delay(333);
}

// ****************************************************************
// Read 1.1V reference against AVcc - Courtesty of Scott Daniels - July 9, 2012
// http://provideyourown.com/2012/secret-arduino-voltmeter-measure-battery-voltage/
// ****************************************************************
long readVcc() {
    // Set the reference to Vcc and the measurement to the internal 1.1V reference
    #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
        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(20);                          // Wait for Vref to settle
    ADCSRA |= _BV(ADSC);                // Start conversion
    while (bit_is_set(ADCSRA,ADSC));    // measuring

    delay(20);
    uint8_t low  = ADCL;                // Read ADCL first - it then locks ADCH
    delay(20);
    uint8_t high = ADCH;                // Unlocks both

    long result = (high<<8) | low;

    // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 - (Uno 1098073L, Mega 1066957L)
    result = 1111145L / result;
   
    return result;                      // Vcc in millivolts
}
 



2 comments:

  1. Hi, im kinda interested with this project. can you provide me the schematic diagram of this project

    ReplyDelete
    Replies
    1. Sorry, I never did a schematic and I can not find the Fritzing file that I did do! If I find it I will post it but in the meantime you can glean what you need from the image of the breadboard...

      Delete