mBuino program that shows how to read VCC using the blink of a LED

Dependencies:   USBDevice mbed

mBuino PowerMeter

This program shows how to read the current voltage on the 3V3 (VCC) pin of mBuino using the blink of a LED.

Since mBuino uses the VCC voltage as reference for analog reads, all readings are relative. To get an absolute reading an external reference voltage is needed. An easy way to get an external reference is by using a zener-diode with proper characteristics.

Not having such a zener around made me look for alternatives. I found some on this page: http://www.talkingelectronics.com/projects/200TrCcts/200TrCcts.html#52

/media/uploads/maxint/reference_voltage_using_diode.jpg

Use a LED!

The most interesting method I found was to use the LEDs on mBuino! All needed to use this is an extra connection. I used a 100R resistor as connection between pin 14 and LED6. Pin 14 is the small dot right above the one of the version number. Alternatively you can also use an external LED or (zener)-diode. The picture below shows both the added resistor as well as an external LED/resistor circuit. /media/uploads/maxint/mbuino_powermeter.jpg

Serial USB

The picture above shows a USB cable connected to mBuino. When mBuino is powered via USB and nothing else is connected to VCC, power comes from the 3v3 regulator. The VCC reading will then be around its maximum. USB is used to display the readings on the USB serial console. Note that for this the USB serial driver and a terminal application such as Putty is required. When using the console the spacebar can be hit to switch between pin14+LED6 and pin15 with an external LED/resistor via pin4.

See the code comments for more information.

Committer:
maxint
Date:
Sat Aug 01 06:58:12 2015 +0000
Revision:
0:5ed29b03d6ce
Child:
1:0434198567a4
mBuino PowerMeter.; Measure VCC using flashing LED

Who changed what in which revision?

UserRevisionLine numberNew contents of line
maxint 0:5ed29b03d6ce 1 #include "mbed.h"
maxint 0:5ed29b03d6ce 2 #include "USBSerial.h"
maxint 0:5ed29b03d6ce 3
maxint 0:5ed29b03d6ce 4 #define TIME_BETWEEN_SAMPLES_ms 300
maxint 0:5ed29b03d6ce 5
maxint 0:5ed29b03d6ce 6 // The USB virtual serial port is used for debugging. Note: driver required, see http://developer.mbed.org/handbook/USBSerial
maxint 0:5ed29b03d6ce 7 USBSerial serialUSB(0x1f00, 0x2012, 0x0001, false); // Virtual serial port over USB, set connect_blocking to false to allow starting without PC
maxint 0:5ed29b03d6ce 8 #define USBSERIAL_DEBUG 1
maxint 0:5ed29b03d6ce 9
maxint 0:5ed29b03d6ce 10 DigitalOut LED[] = {(LED1), (LED2), (LED3), (LED4), (LED5), (LED6), (LED7)};// declare 7 LEDs
maxint 0:5ed29b03d6ce 11
maxint 0:5ed29b03d6ce 12 void ledFlash(uint8_t nLed, float ftDelay=0.005)
maxint 0:5ed29b03d6ce 13 {
maxint 0:5ed29b03d6ce 14 if(nLed>6) nLed=6;
maxint 0:5ed29b03d6ce 15 LED[nLed]=!LED[nLed];
maxint 0:5ed29b03d6ce 16 wait(ftDelay);
maxint 0:5ed29b03d6ce 17 LED[nLed]=!LED[nLed];
maxint 0:5ed29b03d6ce 18 }
maxint 0:5ed29b03d6ce 19
maxint 0:5ed29b03d6ce 20
maxint 0:5ed29b03d6ce 21 float readVCC(PinName nAnalogIn=P0_14, PinName nLed=LED6, int nBlinkDelayMsec=0, float ftVrefInit=1.91)
maxint 0:5ed29b03d6ce 22 { // Unlike Arduino, mBuino v1.5 has no internal reference voltage for analog reads.
maxint 0:5ed29b03d6ce 23 // As all analog reads are relative to VCC, it would be nice to be able to tell the VCC
maxint 0:5ed29b03d6ce 24 // Additionally knowing the current VCC is critical for battery operated applications.
maxint 0:5ed29b03d6ce 25
maxint 0:5ed29b03d6ce 26 // Please note that the voltage on the 3v3 pin is always lower than 3.3V as diodes D10 and D11
maxint 0:5ed29b03d6ce 27 // are between the actual VCC of the 3.3V regulator and that of the CR2032 battery.
maxint 0:5ed29b03d6ce 28 // Measured voltages are 2.85V when powerd by USB or lower when powered by battery.
maxint 0:5ed29b03d6ce 29 // When mBuino has its LEDs on, or when an external device is using VCC, the voltage will be lower too.
maxint 0:5ed29b03d6ce 30
maxint 0:5ed29b03d6ce 31 // The current VCC voltage can be determined by using analogIn to read a known reference voltage.
maxint 0:5ed29b03d6ce 32 // One way to get a reference voltage is by connecting a led via a resistor between VCC and GND.
maxint 0:5ed29b03d6ce 33 // The voltage over the led is (more or less) constant (about 1.7V, depending on the kind of LED).
maxint 0:5ed29b03d6ce 34 // This constant voltage can be measured by using a multimeter.
maxint 0:5ed29b03d6ce 35 // Measured voltages are e.g. 1,77V for a yellow led, 1,66 for a red led and 1,73 for a green led.
maxint 0:5ed29b03d6ce 36 // See http://www.talkingelectronics.com/projects/200TrCcts/200TrCcts.html#52 for more methods.
maxint 0:5ed29b03d6ce 37 //
maxint 0:5ed29b03d6ce 38 // As mBuino already has LEDs we can use them as a reference by connecting P0_14 to the left leg of LED7 or LED6.
maxint 0:5ed29b03d6ce 39 // To avoid potential damage and to allow PWM on LED7 a 100R resistor can be used to make the connection.
maxint 0:5ed29b03d6ce 40 // Note: P0_14 is the tiny dot right above the 1 of the printed version number.
maxint 0:5ed29b03d6ce 41 // See https://developer.mbed.org/platforms/Outrageous-Circuits-mBuino/ for pin-outs and schematics
maxint 0:5ed29b03d6ce 42 //
maxint 0:5ed29b03d6ce 43 AnalogIn ana(nAnalogIn); // TODO: can be made static for better speed?
maxint 0:5ed29b03d6ce 44 DigitalOut ledBlink(nLed); // TODO: can be made static for better speed?
maxint 0:5ed29b03d6ce 45 float ftVoltage, ftVref;
maxint 0:5ed29b03d6ce 46 bool fLedStatus;
maxint 0:5ed29b03d6ce 47
maxint 0:5ed29b03d6ce 48 fLedStatus=ledBlink; // remember status of the led so we can set it back
maxint 0:5ed29b03d6ce 49 ledBlink=1; // put a high voltage on LED7 so we can measure it as a reference voltage and use that to calculate the VCC
maxint 0:5ed29b03d6ce 50 if(nBlinkDelayMsec!=0)
maxint 0:5ed29b03d6ce 51 wait_ms(nBlinkDelayMsec); // allow some time to reach full voltage level (when using no delay the reading can be a bit lower)
maxint 0:5ed29b03d6ce 52 ftVoltage=ana.read();
maxint 0:5ed29b03d6ce 53 ftVref=ftVrefInit; // assume reference voltage on ana14 to be 1.91V, e.g. by connecting is via a 100R resistor to the left leg of LED7
maxint 0:5ed29b03d6ce 54 #ifdef USBSERIAL_DEBUG
maxint 0:5ed29b03d6ce 55 serialUSB.printf("Vref %1.2f / Vread %1.2f%% ~~> ", ftVref, ftVoltage*100);
maxint 0:5ed29b03d6ce 56 #endif
maxint 0:5ed29b03d6ce 57
maxint 0:5ed29b03d6ce 58 // Some silly trial and error compensations. Note: this compensation is not very precise!
maxint 0:5ed29b03d6ce 59 // TODO: improve the compensation to get more accurate readings. Now final readings may differ up to 0.10V from
maxint 0:5ed29b03d6ce 60 // actual values, depending on the reference voltage, length of the blink, VCC-level and probably temperature.
maxint 0:5ed29b03d6ce 61 if(!fLedStatus && nBlinkDelayMsec<=10)
maxint 0:5ed29b03d6ce 62 ftVref+=(0.05-nBlinkDelayMsec/200.0); //compensate for lower voltage due to short delays.
maxint 0:5ed29b03d6ce 63 ftVref-=(0.04+(ftVoltage-0.66)/4); // compensation: Vref is slightly lower on low voltages.
maxint 0:5ed29b03d6ce 64
maxint 0:5ed29b03d6ce 65 // Calculate the VCC by dividing the Vref by the analog reading
maxint 0:5ed29b03d6ce 66 ftVoltage=ftVref/ftVoltage;
maxint 0:5ed29b03d6ce 67
maxint 0:5ed29b03d6ce 68 ledBlink=fLedStatus; // restore led7 to its original status
maxint 0:5ed29b03d6ce 69 return(ftVoltage);
maxint 0:5ed29b03d6ce 70 }
maxint 0:5ed29b03d6ce 71
maxint 0:5ed29b03d6ce 72 void SweepAllLeds(bool fLeftToRight=true, float flDelay=0.1)
maxint 0:5ed29b03d6ce 73 { // light all leds up from left to rigth or vise-versa and then switch them off from reverse direction
maxint 0:5ed29b03d6ce 74 // leds on, left to right
maxint 0:5ed29b03d6ce 75 for(int n=0; n<7; n++)
maxint 0:5ed29b03d6ce 76 {
maxint 0:5ed29b03d6ce 77 LED[fLeftToRight?n:6-n] = 1; // turn on
maxint 0:5ed29b03d6ce 78 wait(flDelay); // delay
maxint 0:5ed29b03d6ce 79 }
maxint 0:5ed29b03d6ce 80 // leds off, right to left
maxint 0:5ed29b03d6ce 81 for(int n=0; n<7; n++)
maxint 0:5ed29b03d6ce 82 {
maxint 0:5ed29b03d6ce 83 LED[!fLeftToRight?n:6-n] = 0; // turn off
maxint 0:5ed29b03d6ce 84 wait(flDelay); // delay
maxint 0:5ed29b03d6ce 85 }
maxint 0:5ed29b03d6ce 86 }
maxint 0:5ed29b03d6ce 87
maxint 0:5ed29b03d6ce 88
maxint 0:5ed29b03d6ce 89 main()
maxint 0:5ed29b03d6ce 90 {
maxint 0:5ed29b03d6ce 91 // Minimal voltage on 3v3 pin is about 1.8V. Below this mBuino may react weird or stop working.
maxint 0:5ed29b03d6ce 92 // Default reference for voltage on mBuino's LEDs is 1.91v, measurement pin is P0_14.
maxint 0:5ed29b03d6ce 93 // Press any key on USB-serial to switch to 1.85v and pin P0_15 for external (green) LED.
maxint 0:5ed29b03d6ce 94 float ftVmin=1.80, ftVled=1.91, ftVcc;
maxint 0:5ed29b03d6ce 95 PinName pinAnalog=P0_14, pinLed=LED6;
maxint 0:5ed29b03d6ce 96 Timer t;
maxint 0:5ed29b03d6ce 97
maxint 0:5ed29b03d6ce 98 // small initial delay to show all leds are working and to allow USB connection
maxint 0:5ed29b03d6ce 99 SweepAllLeds();
maxint 0:5ed29b03d6ce 100 SweepAllLeds(false,0.02);
maxint 0:5ed29b03d6ce 101 SweepAllLeds();
maxint 0:5ed29b03d6ce 102
maxint 0:5ed29b03d6ce 103 t.start();
maxint 0:5ed29b03d6ce 104 while(!serialUSB.readable() && (t.read_ms() <= 3000)) {
maxint 0:5ed29b03d6ce 105 serialUSB.printf(".");
maxint 0:5ed29b03d6ce 106 ledFlash(0);
maxint 0:5ed29b03d6ce 107 wait(0.1);
maxint 0:5ed29b03d6ce 108 }
maxint 0:5ed29b03d6ce 109
maxint 0:5ed29b03d6ce 110
maxint 0:5ed29b03d6ce 111 ledFlash(0);
maxint 0:5ed29b03d6ce 112 wait(0.5);
maxint 0:5ed29b03d6ce 113
maxint 0:5ed29b03d6ce 114 serialUSB.printf("\r\n === mBuino PowerMeter ==== \r\n");
maxint 0:5ed29b03d6ce 115 serialUSB.printf("Measuring LED pin %d [%1.2fV] using pin %d\r\n", pinLed, ftVled, pinAnalog);
maxint 0:5ed29b03d6ce 116 serialUSB.printf("Hit spacebar to change to LED pin 4 [1.85V] using pin 15.\r\n");
maxint 0:5ed29b03d6ce 117 while(true)
maxint 0:5ed29b03d6ce 118 {
maxint 0:5ed29b03d6ce 119 //ftVCC=readVCC(); // float readVCC(PinName nAnalogIn=P0_14, PinName nLed=LED6, int nBlinkDelayMsec=0, float ftVrefInit=1.91)
maxint 0:5ed29b03d6ce 120 ftVcc=readVCC(pinAnalog, pinLed, 0, ftVled);
maxint 0:5ed29b03d6ce 121 serialUSB.printf("VCC: %1.2fV\r\n", ftVcc);
maxint 0:5ed29b03d6ce 122
maxint 0:5ed29b03d6ce 123 if(ftVcc>ftVmin)
maxint 0:5ed29b03d6ce 124 {
maxint 0:5ed29b03d6ce 125 uint8_t uLed=0;
maxint 0:5ed29b03d6ce 126 if(ftVcc>=1.90) uLed=1;
maxint 0:5ed29b03d6ce 127 if(ftVcc>=2.00) uLed=2;
maxint 0:5ed29b03d6ce 128 if(ftVcc>=2.20) uLed=3;
maxint 0:5ed29b03d6ce 129 if(ftVcc>=2.40) uLed=4;
maxint 0:5ed29b03d6ce 130 if(ftVcc>=2.60) uLed=5;
maxint 0:5ed29b03d6ce 131 if(ftVcc>=2.75) uLed=6;
maxint 0:5ed29b03d6ce 132 ledFlash(uLed);
maxint 0:5ed29b03d6ce 133 wait(1);
maxint 0:5ed29b03d6ce 134 }
maxint 0:5ed29b03d6ce 135 else
maxint 0:5ed29b03d6ce 136 {
maxint 0:5ed29b03d6ce 137 ledFlash(0);
maxint 0:5ed29b03d6ce 138 wait(0.25);
maxint 0:5ed29b03d6ce 139 }
maxint 0:5ed29b03d6ce 140
maxint 0:5ed29b03d6ce 141 if(serialUSB.readable())
maxint 0:5ed29b03d6ce 142 { // switch pins when is spacebar is hit
maxint 0:5ed29b03d6ce 143 if(serialUSB._getc()==' ')
maxint 0:5ed29b03d6ce 144 {
maxint 0:5ed29b03d6ce 145 pinLed=(pinLed==P0_4?LED6:P0_4);
maxint 0:5ed29b03d6ce 146 //ftVled=(ftVled!=1.85?1.85f:1.91f);
maxint 0:5ed29b03d6ce 147 if(ftVled!=1.91f) ftVled=1.91f; else ftVled=1.85f;
maxint 0:5ed29b03d6ce 148 pinAnalog=(pinAnalog==P0_15?P0_14:P0_15);
maxint 0:5ed29b03d6ce 149 serialUSB.printf("Switched to measuring LED pin %d [%1.2fV] using pin %d\r\n", pinLed, ftVled, pinAnalog);
maxint 0:5ed29b03d6ce 150 }
maxint 0:5ed29b03d6ce 151 else
maxint 0:5ed29b03d6ce 152 {
maxint 0:5ed29b03d6ce 153 serialUSB.printf("Hit spacebar to switch between pins (4/15 or LED6/14).\r\n");
maxint 0:5ed29b03d6ce 154 }
maxint 0:5ed29b03d6ce 155 }
maxint 0:5ed29b03d6ce 156 }
maxint 0:5ed29b03d6ce 157 }