Digital voltmeter on Arduino with connection to a PC via a serial port. Bluetooth voltmeter based on arduino

With some additions.

A little-known feature of Arduino and many other AVR chips is the ability to measure the internal 1.1 V reference voltage. This function can be used for increasing accuracy Arduino functions - analogRead using Standard reference voltage is 5 V (on 5 V platforms) or 3.3 V (on 3.3 V platforms).She may also be used to measure Vcc applied to the chip, providing means of control battery voltage without use precious analog pins.

Motivation

At least there is at least two reasons for measuring supply voltage our Arduino (Vcc). One of them is our battery powered project if we want to keep an eye on the battery voltage level. Also, when the battery power (Vcc) cannot be 5.0 volts (eg a 3 cell 1.5 V power supply) and we want to make analog measurements more accurate - we must use either an internal 1.1 V reference or external source reference voltage. Why?

The usual assumption when using analogRead() is that analog voltage The controller's power supply is 5.0 volts, when in reality this may not be the case at all (for example, power from 3 1.5 V elements). The official Arduino documentation may even lead us to this incorrect assumption. The fact is that the power is not necessarily 5.0 volts; regardless of the current level, this power is supplied to the Vcc of the chip. If our power supply is not stabilized or if we are running on battery power, this voltage may vary quite a bit. Here is a code example that illustrates this problem:

Double Vcc = 5.0; // not necessarily true int value = analogRead(0); / read the readings from A0 double volt = (value / 1023.0) * Vcc; // only true if Vcc = 5.0 volts In order to measure voltage accurately, an accurate reference voltage is needed. Most AVR chips provide three voltage references:

  • 1.1 in from internal source, in the documentation it passes as a bandgap reference (some of them are 2.56 V, for example ATMega 2560). The selection is made by the analogReference() function with the INTERNAL parameter: analogReference(INTERNAL) ;
  • external source of reference voltage, labeled AREF on the arduino. Select: analogReference(EXTERNAL);
  • Vcc is the power supply of the controller itself. Select: analogReference(DEFAULT).

In Arduino you can't just connect Vcc to the analog pin directly - by default AREF is connected to Vcc and you will always get a maximum value of 1023, no matter what voltage you are powered from. Connecting to AREF a voltage source with a previously known, stable voltage, but this - extra element in the diagram.

You can also connect Vcc to AREF via diode: The voltage drop across the diode is known in advance, so calculating Vcc is not difficult. However, with such a circuit through a diode current flows constantly, shortening the battery life, which is also not very good.

An external voltage reference is the most accurate, but requires additional hardware. Internal ION is stable but not accurate +/- 10% deviation. Vcc is completely unreliable in most cases. Selecting an internal voltage reference is inexpensive and stable, but most of the time, we would like to measure more voltage than 1.1V, so using Vcc is the most practical, but potentially the least accurate. In some cases it can be very unreliable!

How to do it

Many AVR chips including the ATmega and ATtiny series provide a means of measuring internal reference voltage. Why is this necessary? The reason is simple - by measuring the internal voltage, we can determine the value of Vcc. Here's how:

  1. Set default voltage reference: analogReference(DEFAULT); . We use Vcc as a source.
  2. Take ADC readings for the internal 1.1 V source.
  3. Calculate the Vcc value based on the 1.1 V measurement using the formula:

Vcc * (ADC reading) / 1023 = 1.1 V

What follows:

Vcc = 1.1 V * 1023 / (ADC reading)

Putting everything together and we get the code:

long readVcc() ( // Read 1.1V reference against AVcc // 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(MUX3) | _BV(MUX1); #elif defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) (MUX0); #elif defined (__AVR_ATtiny45__) || defined(__AVR_ATtiny85__) ADMUX = _BV(MUX2); #else ADMUX = _BV(MUX3) | MUX2) | _BV(MUX1); #endif delay(75); Wait for Vref to settle ADCSRA |= _BV(ADSC); // Start conversion while (bit_is_set(ADCSRA,ADSC)); // measuring uint8_t low = ADCL; // must read ADCL first - it then locks ADCH uint8_t high = ADCH; // unlocks both long result = (high<<8) | low; result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000 return result; // Vcc in millivolts }

Usage

Checking Vcc or Battery Voltage

You can call this function readVcc() if you want to monitor Vcc. An example would be checking the battery charge level. You can also use it to determine whether you are connected to a power source or running on battery power.

Vcc measurement for reference voltage

You can also use it to get the correct Vcc value for use with analogRead() when you are using the reference voltage (Vcc). Unless you use a regulated power supply, you cannot be sure that Vcc = 5.0 volts. This function allows you to get the correct value. There is one caveat though...

In one of the articles I made a statement that this function could be used to improve the accuracy of analog measurements in cases where Vcc was not quite 5.0 volts. Unfortunately, this procedure will not give an accurate result. Why? This depends on the accuracy of the internal voltage reference. The specification gives a nominal voltage of 1.1 volts, but says it can vary by up to 10%. Such measurements may be less accurate than our Arduino power supply!

Increasing accuracy

While the large tolerances of the internal 1.1V power supply significantly limit measurement accuracy when used in mass production, we can achieve greater accuracy for custom projects. This is easy to do by simply measuring Vcc using a voltmeter and our readVcc() function. Next, replace the constant 1125300L with a new variable:

scale_constant = internal1.1Ref * 1023 * 1000

internal1.1Ref = 1.1 * Vcc1 (voltmeter_readings) / Vcc2 (readVcc_function_readings)

This calibrated value will be a good indicator for AVR chip measurements, but may be affected by temperature changes. Feel free to experiment with your own measurements.

Conclusion

There's a lot you can do with this little feature. You can use a stable reference voltage close to 5.0V without actually having 5.0V on Vcc. You can measure your battery voltage or even see whether you are running on battery power or stationary power.

Finally, the code will support all Arduinos, including the new Leonardo, as well as the ATtinyX4 and ATtinyX5 series chips.

Hello, Habr! Today I want to continue the topic of “crossing” arduino and android. IN previous publication I talked about a bluetooth machine, and today we will talk about a DIY bluetooth voltmeter. Another such device can be called a smart voltmeter, a “smart” voltmeter, or just a smart voltmeter, without quotes. The last name is incorrect from the point of view of Russian grammar, however, it is often found in the media. There will be a vote on this topic at the end of the article, but I suggest starting with a demonstration of the device’s operation in order to understand what the article will be about.


Disclaimer: the article is intended for the average arduino enthusiast who is usually not familiar with programming for Android, therefore, as in the previous article, we will create an application for a smartphone using a visual development environment android applications App Inventor 2.
To make a DIY bluetooth voltmeter, we need to write two relatively independent programs: a sketch for Arduino and an application for Android. Let's start with a sketch.
First, you should know that there are three main options for measuring voltage using Arduino, regardless of where you need to output the information: to the com port, to a screen connected to the Arduino, or to a smartphone.
First case: voltage measurements up to 5 volts. Here, one or two lines of code are enough, and the voltage is supplied directly to pin A0:
int value = analogRead(0); // read readings from A0
voltage = (value / 1023.0) * 5; // true only if Vcc = 5.0 volts
Second case: to measure voltages greater than 5 volts, a voltage divider is used. The circuit is very simple, and so is the code.

Sketch

int analogInput = A0;
float val = 0.0;
float voltage = 0.0;
float R1 = 100000.0; //Battery Vin-> 100K -> A0
float R2 = 10000.0; //Battery Gnd -> Arduino Gnd and Arduino Gnd -> 10K -> A0
int value = 0;

Void setup() (
Serial.begin(9600);
pinMode(analogInput, INPUT);
}

Void loop() (
value = analogRead(analogInput);
val = (value * 4.7) / 1024.0;
voltage = val / (R2/(R1+R2));
Serial.println(voltage);
delay(500);
}


Arduino Uno
Bluetooth module
Third case. When you need to get more accurate information about the voltage, you should use as a reference voltage not the supply voltage, which can vary slightly when powered by a battery, for example, but the voltage of the internal Arduino stabilizer of 1.1 volts. The circuit is the same here, but the code is a little longer. I will not analyze this option in detail, since it is already well described in thematic articles, but the second method is quite enough for me, since my power supply is stable, from the USB port of the laptop.
So we’ve sorted out the voltage measurement, now let’s move on to the second half of the project: creating an Android application. We will create the application directly from the browser in the visual development environment for Android applications App Inventor 2. Go to the website appinventor.mit.edu/explore, log in using your Google account, click the create button, new project, and by simple drag and drop elements we create something like this design:

I kept the graphics very simple if anyone wants more interesting graphics, let me remind you that for this you need to use .png files with a transparent background instead of .jpeg files.
Now go to the Blocks tab and create the application logic there something like this:


If everything works out, you can click the Build button and save .apk to my computer, and then download and install the application on your smartphone, although there are other ways to upload the application. here it’s more convenient for anyone. As a result, I ended up with this application:


I understand that few people use the App Inventor 2 visual development environment for Android applications in their projects, so many questions may arise about working in it. To remove some of these questions, I did detailed video, about how to make such an application “from scratch” (to view it you need to go to YouTube):

P.S. A collection of more than 100 educational materials on Arduino for beginners and professionals

Described how to assemble a homemade double voltmeter based on the platform Arduino UNO using the 1602A LCD display. In some cases, it is necessary to measure two constant voltages simultaneously and compare them. This may be required, for example, when repairing or adjusting a stabilizer DC voltage to measure the voltage at its input and output, or in other cases.

Schematic diagram

Using a universal microcontroller ARDUINO module UNO and a two-line LCD display type 1602A (based on the HD44780 controller) can easily make such a device. In one line it will show the voltage U1, in the other - the voltage U2.

Rice. 1. Schematic diagram dual voltmeter with display 1602A on Arduino UNO.

But, first of all, I want to remind you that ARDUINO UNO is a relatively inexpensive ready-made module - a small printed circuit board, on which the ATMEGA328 microcontroller is located, as well as all its “harness” necessary for its operation, including a USB programmer and power supply.

For those who are unfamiliar with ARDUINO UNO, I advise you to first read articles L.1 and L.2. The circuit of a double voltmeter is shown in Fig. 1. It is designed to measure two voltages from 0 to 100V (practically up to 90V).

As can be seen from the diagram, to digital ports D2-D7 ARDUINO boards UNO is connected to the liquid crystal display module H1 type 1602A. The LCD indicator is powered by a 5V voltage stabilizer located on the 5V voltage stabilizer board.

The measured voltages are supplied to two analog inputs A1 and A2. There are six analog inputs in total, A0-A5, you could select any two of them. IN in this case, A1 and A2 are selected. The voltage on analog ports can only be positive and only in the range from zero to the microcontroller supply voltage, that is, nominally, up to 5V.

The output of the analog port is converted into digital form by the microcontroller's ADC. To get the result in units of volts, you need to multiply it by 5 (by the reference voltage, that is, by the supply voltage of the microcontroller) and divide by 1024.

In order to be able to measure voltages greater than 5V, or rather, greater than the supply voltage of the microcontroller, because the actual voltage at the output of the 5-volt stabilizer on the ARDUINO UNO board may differ from 5V, and usually a little lower, you need to use conventional resistive dividers at the input. Here these are voltage dividers across resistors R1, R3 and R2, R4.

At the same time, to bring the instrument readings to real value input voltage, you need to set in the program the division of the measurement result by the division coefficient of the resistive divider. And the division coefficient, let’s denote it “K,” can be calculated using the following formula:

K = R3 / (R1+R3) or K = R4 / (R2+R4),

respectively for different entrances double voltmeter.

It is very interesting that the resistors in the dividers do not necessarily have to be high-precision. You can take ordinary resistors, then measure their actual resistance with an accurate ohmmeter, and substitute these measured values ​​into the formula. You will get the value “K” for a specific divisor, which will need to be substituted into the formula.

Voltmeter program

The C++ program is shown in Figure 2.

Rice. 2. Source programs.

To control the LCD indicator, it was decided to use ports D2 to D7 of the ARDUINO UNO board. In principle, other ports are possible, but this is how I decided to use these.

In order for the indicator to interact with ARDUINO UNO, you need to load a subroutine into the program to control it. Such routines are called "libraries", and there are many different "libraries" in the ARDUINO UNO software suite. To work with an LCD indicator based on the HD44780, you need the LiquidCrystal library. Therefore, the program (Table 1) begins by loading this library:

This line gives the command to load into ARDUINO UNO this library. Then you need to assign ARDUINO ports UNO, which will work with the LCD indicator. I chose ports D2 through D7. You can choose others. These ports are assigned by the line:

LiquidCrystal led(2, 3, 4, 5, 6, 7);

After which, the program proceeds to the actual operation of the voltmeter. To measure voltage, it was decided to use analog inputs A1 and A2. These inputs are given on the lines:

int analogInput=1;

int analogInput1=2;

To read data from analog ports, use the analogRead function. Reading data from analog ports occurs in the lines:

vout=analogRead(analogInput);

voutl=analogRead(analoglnput1);

Then, the actual voltage is calculated taking into account the division ratio of the input voltage divider:

volt=vout*5.0/1024.0/0.048 ;

volt1=vout1*5.0/1024.0/0.048;

In these lines, the number 5.0 is the voltage at the output of the stabilizer of the ARDUINO UNO board. Ideally it should be 5V, but for precise work Using a voltmeter, this voltage must first be measured. Connect the power source and measure the +5V voltage at the POWER connector of the board with a fairly accurate voltmeter. What happens, then enter in these lines instead of 5.0, for example, if there is 4.85V, the lines will look like this:

volt=vout*4.85/1024.0/0.048;

volt1=vout1*4.85/1024.0/0.048;

At the next stage, you will need to measure the actual resistances of resistors R1-R4 and determine the K coefficients (indicated as 0.048) for these lines using the formulas:

K1 = R3 / (R1+R3) and K2 = R4 / (R2+R4)

Let's say K1 = 0.046, and K2 = 0.051, so we write:

volt=vout*4.85/1024.0/0.046 ;

volt1=vout1*4.85/1024.0/0.051;

Thus, changes must be made to the program text according to the actual voltage at the output of the 5-volt stabilizer of the ARDUINO UNO board and according to the actual division coefficients of the resistive dividers. After this, the device will work accurately and will not require any adjustment or calibration.

By changing the division coefficients of the resistive dividers (and, accordingly, the “K” coefficients), you can make other measurement limits, and not necessarily the same for both inputs.

Karavkin V. RK-2017-01.

Literature:

  1. Karavkin V. - Christmas tree flasher on ARDUINO as a remedy for the fear of microcontrollers. RK-11-2016.
  2. Karavkin V. - Frequency meter on ARDUINO. RK-12-2016.

This article shows how to interface Arduino and PC and transfer data from the ADC to the PC. The program for Windows is written using Visual C++ 2008 Express. The voltmeter program is very simple and has a lot of room for improvement. Its main purpose was to show how to work with a COM port and exchange data between a computer and Arduino.

Communication between Arduino and PC:

  • Taking readings from the ADC begins when the computer sends the Arduino commands 0xAC and 0x1y. at– ADC channel number (0-2);
  • Taking readings stops after receiving Arduino commands 0xAC and 0×00;
  • When taking readings, Arduino sends the commands 0xAB 0xaa 0xbb to the computer every 50 ms, where aa and bb are the maximum and minimum measurement results.

Program for Arduino

You can read more about serial communication at arduino.cc. The program is quite simple, most of it is spent working with parallel port. After finishing reading data from the ADC, we receive a 10-bit voltage value (0x0000 – 0x0400) in the form of 16-bit variables (INT). The serial port (RS-232) allows data to be transmitted in 8-bit packets. It is necessary to divide 16-bit variables into 2 parts of 8 bits.

Serial.print(voltage>>8,BYTE);

Serial.print(voltage%256,BYTE);

We shift the bytes of the variable 8 bits to the right and then divide by 256 and send the result to the computer.

You can download the full source code for Arduino software

Visual C++

I assume that you already have basic knowledge of C++ programming for Windows, if not, then use Google. The Internet is full of tutorials for beginners.

The first thing to do is add serial port from the toolbar to the lower form. This will change some important parameters serial port: port name, baud rate, bit depth. This is useful for adding controls to an application window, changing these settings at any time, without recompiling the program. I only used the port selection option.

After searching for available serial ports, the first port is selected by default. How it's done:

array< String ^>^ serialPorts = nullptr;

serialPorts = serialPort1->GetPortNames();

this->comboBox1->Items->AddRange(serialPorts);

this->comboBox1->SelectedIndex=0;

The serial port on a PC can only be used by one application at a time, so the port must be open before use and not closed. Simple commands for this:

serialPort1->Open();

serialPort1->Close();

To correctly read data from a serial port, you must use events (in our case, an interrupt). Select event type:

Drop-down list when double click"DataReceived".

The event code is generated automatically:

If the first byte arrived on serial port 0xAB if this means the remaining bytes carry voltage data.

private: System::Void serialPort1_DataReceived(System::Object^ sender, System::IO::Ports::SerialDataReceivedEventArgs^ e) (

unsigned char data0, data1;

if (serialPort1->ReadByte()==0xAB) (

data0=serialPort1->ReadByte();

data1=serialPort1->ReadByte();

voltage=Math::Round((float(data0*256+data1)/1024*5.00),2);

data_count++;

serialPort1->ReadByte();

Write and read serial port data

A small problem for me was sending hex RAW data through the serial port. The Write() command was used; but with three arguments: array, start byte number, number of bytes to write.

private: System::Void button2_Click_1(System::Object^ sender, System::EventArgs^ e) (

unsigned char channel=0;

channel=this->listBox1->SelectedIndex;

array^start =(0xAC,(0x10+channel));

array^stop =(0xAC,0x00);

serialPort1->Write(start,0,2);

this->button2->Text="Stop";

) else (

serialPort1->Write(stop,0,2);

this->button2->Text="Start";

That's all!

Original article on English language(translation: Alexander Kasyanov for the site cxem.net)

Hello, Habr! Today I want to continue the topic of “crossing” arduino and android. In the previous publication I talked about, and today we will talk about a DIY bluetooth voltmeter. Another such device can be called a smart voltmeter, a “smart” voltmeter, or just a smart voltmeter, without quotes. The last name is incorrect from the point of view of Russian grammar, however, it is often found in the media. There will be a vote on this topic at the end of the article, but I suggest starting with a demonstration of the device’s operation in order to understand what the article will be about.


Disclaimer: the article is intended for the average arduino enthusiast who is usually not familiar with Android programming, therefore, as in the previous article, we will create an application for a smartphone using the App Inventor 2 visual development environment for Android applications.
To make a DIY bluetooth voltmeter, we need to write two relatively independent programs: a sketch for Arduino and an application for Android. Let's start with a sketch.
First, you should know that there are three main options for measuring voltage using Arduino, regardless of where you need to output the information: to the com port, to a screen connected to the Arduino, or to a smartphone.
First case: voltage measurements up to 5 volts. Here, one or two lines of code are enough, and the voltage is supplied directly to pin A0:
int value = analogRead(0); // read readings from A0
voltage = (value / 1023.0) * 5; // true only if Vcc = 5.0 volts
Second case: to measure voltages greater than 5 volts, a voltage divider is used. The circuit is very simple, and so is the code.

Sketch

int analogInput = A0;
float val = 0.0;
float voltage = 0.0;
float R1 = 100000.0; //Battery Vin-> 100K -> A0
float R2 = 10000.0; //Battery Gnd -> Arduino Gnd and Arduino Gnd -> 10K -> A0
int value = 0;

Void setup() (
Serial.begin(9600);
pinMode(analogInput, INPUT);
}

Void loop() (
value = analogRead(analogInput);
val = (value * 4.7) / 1024.0;
voltage = val / (R2/(R1+R2));
Serial.println(voltage);
delay(500);
}


Arduino Uno
Bluetooth module
Third case. When you need to get more accurate information about the voltage, you should use as a reference voltage not the supply voltage, which can vary slightly when powered by a battery, for example, but the voltage of the internal Arduino stabilizer of 1.1 volts. The circuit is the same here, but the code is a little longer. I will not analyze this option in detail, since it is already well described in thematic articles, but the second method is quite enough for me, since my power supply is stable, from the USB port of the laptop.
So we’ve sorted out the voltage measurement, now let’s move on to the second half of the project: creating an Android application. We will create the application directly from the browser in the visual development environment for Android applications App Inventor 2. Go to the website appinventor.mit.edu/explore, log in using your Google account, click the create, new project button, and by simply dragging and dropping elements we will create something like this design:

I made the graphics very simple, if anyone wants more interesting graphics, let me remind you that for this you need to use .png files with a transparent background instead of .jpeg files.
Now go to the Blocks tab and create the application logic there something like this:


If everything works out, you can click the Build button and save .apk to my computer, and then download and install the application on your smartphone, although there are other ways to upload the application. here it’s more convenient for anyone. As a result, I ended up with this application:


I understand that few people use the App Inventor 2 visual development environment for Android applications in their projects, so many questions may arise about working in it. To address some of these questions, I made a detailed video on how to make such an application “from scratch” (to view it you need to go to YouTube):

P.S. A collection of more than 100 educational materials on Arduino for beginners and professionals