Introduction: Arduino Volt Meter (0-100V DC) - Version 2 (better)
In this instructable, I've built a voltmeter to measure high voltages DC (0-100v) with relative precision and accuracy using an Arduino Nano and an ADS 1115 ADC.
This is a second version of the voltmeter used my previous instructable here: https://www.instructables.com/id/Arduino-Precise-A...
The test measurements I took were accurate , mostly within 0.1v of the actual voltage measured with a standard voltmeter (I used an Astro AI DM6000AR).
This is much better, and easier in my opinion than using an external voltage reference on the Arduino.
Supplies
1 x Arduino Nano - Link
1 x Oled Display (SSD 1306) - Link
1 x ADS 1115 - 16 bit ADC - Link
1 x 1/4W (I suggest using 1W resistors though) 1% Resistors - 220k ohm - Link
1 x 1/4W (I suggest using 1W resistors though) 1% Resistors - 10k ohm - Link
Breadboard and wires - Link
Astro AI DM6000AR - Link
USB Power Bank - Link
9V Batteries - Link
CanadianWinters is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn fees by linking to Amazon.com and affiliated sites. By using these links, as an Amazon Associate I earn from qualifying purchases, even if you buy something else--and it won't cost you anything.
Step 1: The Schematics
I connected all the parts as per the schematics above.
I tied the ADDR pin of the ADC1115 to ground. This sets the address of the ADC to 0x48.
Step 2: The Code and Resistor Calculations
As in the previous instructable, the idea of the circuit is that the DC voltage to be measured goes through a voltage divider. The scaled voltage and then gets into the analog pin of the ADC converter to be read, then passed to the Arduino via I2C and then re-scaled and displayed on the OLed display.
I did not use any averaging or smoothing in the code in this case, as the readings seem quite accurate a precise. To reduce the noise, you might want to add a small capacitor between A0 (on the ADC) and ground. It was not required for my test though.
One thing I noticed, was a bit of noise when there was no battery attached (0 volts). I used the serial monitor of the Arduino to display the ADC value and correct/adjust it via code.
As in the previous instructable, I made a spreadsheet that automates the calculations in case you want to use different resistor values in the voltage divider: Link to Google Sheet
Here is the code I used for this project:
#include <Arduino.h> #include <U8g2lib.h> #include <Adafruit_ADS1015.h> #include <Wire.h> Adafruit_ADS1115 ads(0x48); //Adress of the ADC U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0);// (rotation, [reset]) int calib = 7; // Value of calibration of ADS1115 to reduce error float voltage = 0; // used to store voltage value float Radjust = 0.043421905; // Voltage divider factor ( R2 / R1+R2 ) float vbat = 0; //final voltage after calcs- voltage of the battery //variables for refreshing the screen without using delay unsigned long previousMillis = 0; // will store last time the screen was refreshed // constants won't change: const long interval = 250; // interval at which to refresh the screen (milliseconds) void setup(void) { Serial.begin(9600); u8g2.begin(); ads.begin(); } void loop(void) { int16_t adc0; // 16 bits ADC read of input A0 adc0 = ads.readADC_SingleEnded(0); voltage = ((adc0 + calib) * 0.1875)/1000; unsigned long currentMillis = millis(); vbat = voltage/Radjust; //Prevent displaying negative voltage when battery is disconnected if (vbat < 0.1) { vbat = 0.01; } // Setting the delay for the screen refresh using Millis if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; u8g2.clearBuffer(); // clear the internal menory //Pack Voltage display - Fonts at this page: https://github.com/olikraus/u8g2/wiki/fntlistall //u8g2.setFont(u8g2_font_fub20_tr); // 20px font u8g2.setFont(u8g2_font_fub35_tr); // 35px font u8g2.setCursor (1, 42); u8g2.print(vbat,2); u8g2.setFont(u8g2_font_8x13B_mr); // 10 px font u8g2.setCursor (1, 60); u8g2.print("Volts"); } u8g2.sendBuffer(); // transfer internal memory to the display delay(1); }
Step 3: Let's Test It Out!
To test this voltmeter I used 10x 9v batteries that I got at a local store. This time I could measure up to 97 volts! I am planning to use this voltmeter to measure the voltage on my electric bicycles battery packs (they have voltages ranging from 24-60v with the occasional 72v ones).
Once the electronics are packaged into a pcb and a little box, this will make a nice and portable battery pack meter. The graphics and fonts on the OLED could be customized to fit your needs (eg. bigger font for easy reading). My goal was to have a voltage reading on the Oled/Arduino meter not too far from my Digital Multi Meter. I was aiming for +/-0,3v max delta.
As you can see from the video at the beginning of the Instructable, I was able to archive this! Most readings were spot on!
I hope you enjoyed this Instructable and let me know your thoughts!
13 Comments
Question 10 days ago
I have a 48v 120Ah battery pack. Can i use this project for that application?
Please reply.
5 months ago
Serial.println("Failed to initialize ADS.");
while(1);
}
Receive Failed to initialize ADS.please advice
2 years ago
Hello!
I've also purchased an ADS1115 and I am using it for a project. The max values that will be used are 100DCV and 20A. Will it break the sensor if I let it read the 5Ω resistor when the voltage is 100DCV? The best option is that it's reading the JFET that I will be using, is it possible to do so? Is it possible that the library you're using doesn't exist anymore? if not where can I find them?
Question 3 years ago
Hey, I have made your project! Unfortunately I am getting the following error:
Volt_Meter:52:1: error: expected primary-expression before '<' token
</a>
^
Volt_Meter:52:2: error: expected primary-expression before '/' token
</a>
^
Volt_Meter:52:3: error: 'a' was not declared in this scope
</a>
^
C:\Users\josht\OneDrive\Documents\Arduino\Volt_Meter\Volt_Meter.ino: At global scope:
Volt_Meter:66:2: error: expected unqualified-id before '<' token
}<br>
^
Using library U8g2 at version 2.27.6 in folder: C:\Users\josht\OneDrive\Documents\Arduino\libraries\U8g2
Using library Adafruit_SH1106-master in folder: C:\Users\josht\OneDrive\Documents\Arduino\libraries\Adafruit_SH1106-master (legacy)
Using library SPI at version 1.0 in folder: C:\Users\josht\Downloads\arduino-nightly-windows\arduino-nightly\hardware\arduino\avr\libraries\SPI
Using library Adafruit_GFX_Library at version 1.10.1 in folder: C:\Users\josht\OneDrive\Documents\Arduino\libraries\Adafruit_GFX_Library
Using library Wire at version 1.0 in folder: C:\Users\josht\Downloads\arduino-nightly-windows\arduino-nightly\hardware\arduino\avr\libraries\Wire
Using library Adafruit_ADS1X15 at version 1.1.1 in folder: C:\Users\josht\OneDrive\Documents\Arduino\libraries\Adafruit_ADS1X15
Using library Adafruit_BusIO-master at version 1.5.0 in folder: C:\Users\josht\OneDrive\Documents\Arduino\libraries\Adafruit_BusIO-master
exit status 1
expected primary-expression before '<' token
It is at this point in the code:
//Pack Voltage display - Fonts at this page: https://github.com/olikraus/u8g2/wiki/fntlistall
//u8g2.setFont(u8g2_font_fub20_tr); // 20px font
u8g2.setFont(u8g2_font_fub35_tr); // 35px font
u8g2.setCursor (1, 42);
u8g2.print(vbat,2);
Thank You!
Reply 3 years ago
Hi!
Can you please post your code? I normally get those errors when I forget a semicolon or a bracket.
Reply 3 years ago
It's the exact code you have on here. I didn't edit anything. The only difference is I'm using the SH1106 OLED. All the other hardware is the same as you have listed.
Thanks!
Reply 3 years ago
It seems the editor on instructables added some html formatting to the code. I have edited the code. I tested it and it compiles without errors now.
Reply 2 years ago
can you please share thee code again?
Reply 3 years ago
Awesome! thank you so much!
2 years ago
from this method we can measure 300-500dc voltages too right?
Reply 2 years ago
It should be possible by choosing the appropriate resistors, however, I do not suggest it as working with such high voltages is dangerous.
2 years ago
can you explain this code please,,
voltage = ((adc0 + calib) * 0.1875)/1000;
where is value 0.1875 from,, ?
Reply 2 years ago
Hi there!
The values comes from the ADC input range/gain. More info here: https://github.com/adafruit/Adafruit_ADS1X15/blob/master/examples/singleended/singleended.ino