BITX Voltage Monitor
by Don Cantrell, ND6T
With eight pins available
for reading analog signals, the little Nano® has some enticing capabilities.
More useful than an “S” meter reading, a measurement of the supply voltage is
another display item that you can easily include. This will allow you to keep
track of your battery status if you are portable. It could also be adapted to
check on any other voltage (or voltages) that you might be concerned with. Like
your PA supply if you are going to feed it with a separate higher voltage.
Looking at the wiring
diagram of my VFO build you will notice a couple of resistors that are in
series and placed between the +12 Volt input and ground. There is a 1.8 Kohm
from ground and a 5.6 Kohm on the power feed side. Power rating is unimportant
since they are going to dissipate only about 25 milliwatts. I chose these
values so that it could measure up to 20 Volts without subjecting the Nano® to
more than 5 volts. A safe Nano® is a happy Nano®.
Whenever measuring any
voltage with the Nano®, endeavor to keep the maximum voltage to the analog pin
below 5 Volts but compromise to retain the best dynamic range. The measurement
involves converting the range into 1024 steps and then dividing the result by
whatever number will display a reading that will be closest to what the
measured voltage actually is. If you have too much range then those steps will
be larger and more inaccurate.
Software implementation is
wonderfully simple. Here's how to read the voltage on pin A2:
// Read supply voltage
int supply = analogRead(A1);
The first line is just a
comment, reminding you what the next code is about. This line is optional. The
second line establishes a local variable (that I named “supply”) and specifies
it to be an integer type, saving a little storage space and keeping handling
simple. The “=” sign assigns the result of the “analogRead” function on port
A1. If the voltage applied to that pin was 2.5 Volts, for instance, the
“supply” variable is now worth 512. That's because 2.5 volts is half the
maximum 5 volts and, therefore, half of the maximum 1024. Make sense?
To display that as a voltage
on our LCD screen we would use this line:
lcd.print(supply/47.7);
Why divide the supply
variable by 47.7? Because that would make it correspond to the voltage that we
were feeding the resistive scaling divider with. Find it by experiment. In this
case you would see 10.73 on the display. Apply 10.73 volts to the top of the
divider and you will see 2.5 volts on the tap where you have pin A1 attached
and you will read 10.73 (or so) on the display.
Easy. Two resistors, two
lines of code. You can use similar schemes to monitor any voltage or current.
Rectify the voltage from a winding on a toroid that you run the antenna lead
through and read output power (antenna current). Set up a VSWR bridge. Ahhh!
The possibilities!
de ND6T
I use a similar method for measuring voltages greater than the maximum ADC voltage. I have a simple set of definitions and code I paste into my sketch as needed. I just define ADC values for the board I am using , and voltage divider values
ReplyDelete// define info about ADC and voltage divider values
#define ADC_ref 500 // ADC reference voltage X 100 ( 500 for nano ,uno , 5 volt pro mini ( 330 for 3.3v pro mini ,teensy, stm32)
#define ADC_res 1023 // ADC resolution ( 1023 for nano uno pro mini ) (4095 for teensy stm32 )
#define R1 10 // from GND to Vin_bat, express in 100R (10 = 1000 Ohm)
#define R2 47 // from + power supply to Vin_bat, express in 100R (47 = 4700 Ohm)
#define V_multi (R1+R2)/R1 // compute multiplier based on voltage divider values
// ADC pin to read battery vltage
#define VIN_bat A6
//battery voltage x 100 divide by 100 in display routine
int bat_voltage;
// measure and scale voltage
bat_voltage = analogRead(VIN_bat);
// compute battery voltage using ADC & divider values
bat_voltage = map(bat_voltage , 0, ADC_res, 0, (ADC_ref * V_multi);
This comment has been removed by the author.
ReplyDeleteMy own 'scheme' is to use Custom LCD characters:
ReplyDelete13.0 V down to the recommended 11.9 V Gel Battery discharge, I can show one of 7 battery icons.
But anything above 13.0 V, I'll show a 'plugged in' icon, just like a laptop (since a gel battery is nearly always below 13V).
Custom Chars can be used in a single LCD spot (if you don't want to display it all out in digits: '12.9' takes 4 LCD spots).
I have a little tool which you can use to setup the character bytes:
https://mikeyancey.com/projects/lcd-characters
Here's my set of Custom LCD Icons, starting with 'Power Supply', followed by full battery...empty battery (11.9V for Gel Batteries) -
int batterySense[8] = {647,632,622,612,602,597,592,587}; // Values based upon 560k/180k resistor divider
byte battery[][8] = {
{ B01010, B01010, B11111, B10001, B10001, B10001, B01110, B00100 } // Plugged In > 13.0
,{ B01110, B11111, B11111, B11111, B11111, B11111, B11111, B11111 } // Full Battery > 12.7
,{ B01110, B11011, B11111, B11111, B11111, B11111, B11111, B11111 } // > 12.5
,{ B01110, B11011, B10001, B11111, B11111, B11111, B11111, B11111 } // > 12.3
,{ B01110, B11011, B10001, B10001, B11111, B11111, B11111, B11111 } // > 12.1
,{ B01110, B11011, B10001, B10001, B10001, B11111, B11111, B11111 } // > 12.0
,{ B01110, B11011, B10001, B10001, B10001, B10001, B11111, B11111 } // > 11.9
,{ B01110, B11011, B10001, B10001, B10001, B10001, B10001, B11111 } // > 11.8
};
#define BatteryCheckSeconds 5 * 1000L // Check the battery every 'n' Seconds.
unsigned long lastBatteryCheck = 0L;
Hi!
ReplyDeleteYou got a small bug on your code\explanation :)
Software implementation is wonderfully simple. Here's how to read the voltage on pin => A2 <=:
// Read supply voltage
int supply = analogRead(=> A1 <=);
Vildor: Yes, indeed! Nothing better than the "send" key to find those errors! If only I could learn to read:-)
ReplyDelete-Don, ND6T
hi where you set the position on the display?? i want to implement this on ubitx source code. Thanks in advance
ReplyDeleteLucky Club Casino Site - Free Bonus Code - LuckyClub.live
ReplyDelete› › Lucky Club Casino Site Lucky Club offers a great experience on the luckyclub.live gambling floor. We offer a wide variety of casino games including Slots, Roulette and Blackjack.