Simple digital volt meter using internal reference(VREFINT)

Dependencies:   mbed

main.cpp

Committer:
kenjiArai
Date:
2016-11-16
Revision:
0:62a1e3699786
Child:
1:2fa5ba8b899f

File content as of revision 0:62a1e3699786:

/*
 * mbed Application program / Simple Digital Volt-meter
 *      on Nucleo-L152RE
 *
 * Copyright (c) 2016 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created:    Nobember  15th, 2016
 *      Revised:    Nobember  16th, 2016
 *
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#define VOLTMETER
//#define CALC_VDD
//#define READ_VREF_TEMP

#include "mbed.h"

#if defined(VOLTMETER)

/* Use R1 & R2 divider
                          | Nucleo-L152RE
    V_INPUT <-- R1 -.-----| A0(PA_0)
                    |     |
                    R2    |
                    |_____| GND
                          |
 */
#define     R1      (3332.4f)   // target 3.3K Ohm
#define     R2      (987.54f)   // target 1K Ohm

AnalogIn    v_input(A0);
AnalogIn    vref(ADC_VREF);
DigitalOut  myled(LED1);
Timer       tmr;

int main() {
    double      v_in, vdd;
    double      v_in_actual;

    while(true) {
        tmr.reset();
        tmr.start();
        vdd  = (1.224f) / vref.read();
        v_in = v_input.read();
        v_in_actual = v_in * vdd * ( R1 + R2) / R2;
        printf("V IN : %5.3f [V]\r\n", v_in_actual);
        wait_ms(500 - tmr.read_ms());      // 1sec interval    
    }
}
#endif

#if defined(CALC_VDD)

AnalogIn    vref(ADC_VREF);
DigitalOut  myled(LED1);
Timer       tmr;

/*
    Calculate Voltage data

    Vdd:        CPU Vdd line voltage
                (If VREF+ connected Vdd and VREF- connected GND)
    dt_adc:     ADC data (12bit)
    VREFINT:    Internal bandgap voltage
                1.202V(min), 1.224V(typ), 1.242V(max)
    VREFINT_CAL Raw data acquired at temperature of 30 °C,
                Vdd = 3 V Addr: 0x1FF80078-0x1FF80079

    VREFINT_CAL = 3000 * VREF(Factory) / 4096      [V]
    Vdd         = VREFINT_CAL / VREFINT(ADC float) [V]

    reference:
    en.CD00277537.pdf page 56/133 (April 2016 DocID17659 Rev 12)
    en.CD00240193.pdf page 287/908 (September 2016 DocID15965 Rev 14)
*/
int main() {
    double      vdd;
    double      vdd_calibed;
    double      vref_calibed;
    double      vref_f;
    uint16_t    vref_u16;
    uint16_t    vref_cal;

    vref_cal = *(__IO uint16_t *)((uint32_t)0x1ff800f8);
    while(true) {
        tmr.reset();
        tmr.start();
        myled = 1;
        wait(0.2f);   
        myled = 0;
        wait(0.6f);
        vref_f   = vref.read();
        vref_u16 = vref.read_u16();
        printf("Vref(f): %f, Vref : %u, Vref_CAL : %u,",
                     vref_f,  vref_u16,      vref_cal);
        vref_calibed = 3.0f * (double)vref_cal / 4096.0f;
        vdd_calibed  = vref_calibed / vref_f;
        vdd          = 1.224f / vref_f;
        printf(" Vref(Calibrated) : %f, VDD(Calibrated) : %f, VDD : %f,",
                         vref_calibed,           vdd_calibed,      vdd);
        printf(" VDD(measured my Nucleo) : 3.3163\r\n");
        wait_ms(1000 - tmr.read_ms());      // 1sec interval   
    }
}
#endif

#if defined(READ_VREF_TEMP)

AnalogIn   vrefint(ADC_VREF);
AnalogIn   tempint(ADC_TEMP);

int main() {
    while(true) {
        printf("Vref(f): %f, Vref : %u, Temperature : %u\r\n",
                 vrefint.read(), vrefint.read_u16(), tempint.read_u16());
        wait(1.0f);
    }
}
#endif