Voltage on analog pin always 5V

I'm measuring voltage from voltage divider on analog pin A3. Voltage divider consists of 2.2k and 1k resistors and is connected to the 12V battery that also powers the whole system (using buck booster to lower the voltage to 5V). When I connected the battery which had 12.64V, the arduino measures 16V what would be 5V from voltage divider and is incorrect. When I measured voltage between A3 pin and ground it showed correct voltage from voltage divider (3.92V) what should be with the code then converted to 12.64V.
Can anyone explain me why is this happening and if possible provide a solution?
If you need more information just ask.

This is the code that does the voltage calculation:

int vm = analogRead(A3);
float vmvoltage = vm * (5.0 / 1023.0);
supplyvoltage = vmvoltage * 3.22;  //supplyvoltage is defined eariler in the code

does it read 5V when not connected?

do you have A3 pulled up in some other bit of code?

You should be using more like 22k and 10k. In your scheme if the 1k goes open circuit your
12V supply will push about 7V/2k2 = 3mA through the analog pin's protection diode, which is probably
more than it can take. Once that diode fails you fry that input or the whole chip. With 22k everything
is a lot safer.

Have you tried removing the divider and connecting the 3.3V supply to the analog pin and checking
it reads that correctly?

It reads 5V when connected and 0V when not. I don't have this analog pin pulled up in any other part of the code. It might be divider fault, because the other 2 analog pins reads correctly.

Use this to figure out voltage divider for the Arduino: http://www.ohmslawcalculator.com/voltage-divider-calculator

Also use that to see why your current voltage divider is …

I start with a R1 of 100K.

I changed resistors of voltage divider to 100k and 220k and its still same. A3 pin still reads a little less than 5V, but there is only 3.86V on it.

Could you post a full sketch?

A full sketch is basically transmitting side of weather station. With that voltage divider I measure the voltage on the battery of outdoor weather station and with all other data transmit it to indoor station on which data is displayed. I already posted the sketch that is responsible for voltage calculation from divider and that is only part of the code where A3 pin is mentioned.

I ment minimal compilable sketch.

alesam:
I ment minimal compilable sketch.

.... that still illustrates the problem :wink:

Sometimes in the process of stripping huge code down to that, the problem goes away so it becomes evident what the actual problem is.

Here is the full code… A lot of things is in Slovenian, sorry about that. Translated version of the part with A3 pin is in my first post, if you need anything else translated just tell me.

#include <SPI.h>
#include <SoftwareSerial.h>
#include <stdint.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include "Wire.h"
#define RAINSENSOR 7
#define LIGHT 5
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME680 bme;

unsigned long period = 86400000;
unsigned long time_now = 0;

const char tempS[]  = "Temperatura: ";
const char pressureS[]  = "Pritisk: ";
const char rhS[]  =  "Vlaga: ";
const char hitrostvS[]  = "Hitrost vetra:";
const char maxhitrostvS[]  = "Max hitrost vetra:    ";
const char smervS[]  = "Smer vetra:";
const char rainS[]  = "";
const char lightS[]  = "";
const char napajanjeS[]  = "";
const char* const string_table[]  = {
  tempS, pressureS, rhS, hitrostvS, maxhitrostvS, smervS, rainS, lightS, napajanjeS
};

const char tempUnit[] = " \xB0""C";
const char pressureUnit[] = " hPa";
const char RHUnit[] = " %";
const char hitrostvUnit[] = " m/s";
const char maxhitrostvUnit[] = " m/s";
const char smervUnit[] = "";
const char rainUnit[] = "";
const char lightUnit[] = "";
const char napajanjeUnit[]  = " V";
char dataString[300] = {};

int count = 0;

const char* const unit_table[]  = {
  tempUnit, pressureUnit, RHUnit, hitrostvUnit, maxhitrostvUnit, smervUnit, rainUnit, lightUnit, napajanjeUnit
};

int light = -300;
int rain = -300;
double hitrostvetra = 0;
double maxhitrostvetra = 0;
char smervetra[12];
double napajalnanapetost;
float rh = -300.0;
float sensor = -300.0;
char buff[12] = {};
boolean newData = false;
SoftwareSerial mySerial(10, 11); //TX, RX

void setup()
{
  Serial.begin(115200);
  pinMode(LIGHT, INPUT);
  pinMode(RAINSENSOR, INPUT);
  bme.begin();
  bme.setTemperatureOversampling(BME680_OS_8X);
  bme.setHumidityOversampling(BME680_OS_2X);
  bme.setPressureOversampling(BME680_OS_4X);
  bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
  Serial.println("started");
  delay(1000);
  mySerial.begin(2400);
  time_now = millis();

}

void loop()
{
  bme.performReading();
  int senzorhitrostivetra = analogRead(A0);
  float napetost1 = senzorhitrostivetra * (5.0 / 1023.0);
  hitrostvetra = napetost1 / 0.16667;

  if (millis() - time_now > period) {
    time_now = millis();
  }
  if(maxhitrostvetra < hitrostvetra)
  {
    maxhitrostvetra = hitrostvetra;
  }

  int senzorsmerivetra = analogRead(A1);
  float napetost2 = senzorsmerivetra * (5.0 / 1023.0);
  if (napetost2 > 4.69 && napetost2 < 5.00 || napetost2 > 0.00 && napetost2 < 0.31) {
    strcpy(smervetra, "Sever");
  }
  else if (napetost2 > 0.31 && napetost2 < 0.94) {
    strcpy(smervetra, "Severovzhod");
  }
  else if (napetost2 > 0.94 && napetost2 < 1.56) {
    strcpy(smervetra, "Vzhod");
  }
  else if (napetost2 > 1.56 && napetost2 < 2.19) {
    strcpy(smervetra, "Jugovzhod");
  }
  else if (napetost2 > 2.19 && napetost2 < 2.81) {
    strcpy(smervetra, "Jug");
  }
  else if (napetost2 > 2.81 && napetost2 < 3.44) {
    strcpy(smervetra, "Jugozahod");
  }
  else if (napetost2 > 3.44 && napetost2 < 4.06) {
    strcpy(smervetra, "Zahod");
  }
  else if (napetost2 > 4.06 && napetost2 < 4.69) {
    strcpy(smervetra, "Severozahod");
  }

  int vm = analogRead(A3);
  float napetostvm = vm * (5.0 / 1023.0);
  napajalnanapetost = napetostvm * 3.22;

  acquireForSending();
  Serial.println();
  Serial.print("Data to send :");
  Serial.println(dataString);

  Serial.print("DS length : ");
  Serial.println(strlen(dataString));

  if (newData && (strlen(dataString)) > 0)
  {
    Serial.println("Sending");
    mySerial.write(dataString);
    newData = false;
  }

  count += 1;

  memset(dataString, 0, 300);

  delay(5000);

}

void acquireForSending()
{
  int arrC;
  dataString[0]  = 0;
  if (!newData)
  {

    int tempo = 0;
    int dsPos = 0;
    arrC = 0;

    tempo = strlen((char*)(&(string_table[arrC])));
    strcpy(dataString, (char*)"<");
    dsPos += 1;

    //initialize output string
    while (arrC < 9)
    {
      switch (arrC) {
        case 0:
          dtostrf(sensor = bme.temperature, 2, 2, buff);
          formartReading(arrC, false);
          break;
        case 1:
          dtostrf(sensor = bme.pressure / 100.0, 6, 2, buff);
          formartReading(arrC, false);
          break;
        case 2:
          dtostrf(sensor = bme.humidity, 2, 2, buff);
          formartReading(arrC, false);
          break;
        case 3:
          dtostrf(hitrostvetra, 2, 2, buff);
          formartReading(arrC, false);
          break;
        case 4:
          dtostrf(maxhitrostvetra, 2, 2, buff);
          formartReading(arrC, false);
          break;
        case 5:
          strcpy(buff, smervetra);
          formartReading(arrC, false);
          break;
        case 6:
          strcpy(buff, (char*)digitalRead(RAINSENSOR) ? "Ne" : "Ja");
          formartReading(arrC, false);
          break;
        case 7:
          strcpy(buff, (char*)digitalRead(LIGHT) ? "Ne" : "Ja");
          formartReading(arrC, false);
          break;
        case 8:
          dtostrf(napajalnanapetost, 2, 2, buff);
          formartReading(arrC, true);
          break;
        default:
          break;
      }
      arrC += 1;
    }

  }
  newData = true;
}
char *formartReading(int arrC, boolean last)
{
  strcat(dataString, (char*)(string_table[arrC]));
  strcat(dataString, buff);
  strcat(dataString, (char*)(unit_table[arrC]));
  if (!last)
  {
    strcat(dataString, (char*)",");
  }
  else
  {
    strcat(dataString, (char*)">");
  }
  return dataString;
}

int senzorhitrostivetra = analogRead(A0); <<<<---- what do you get if you ground A0? What do you get if you do a 1K/1K resistor divider, with the top of one resistor going to 5V and the bottom of the other going to ground, and put the divided voltage into A0?

I could try that, but I already got everything soldered and whole weather station completely assembled. So it would be a bummer trying this out.

I need someone to confirm me that this isn't software(sketch), but is hardware issue.

It is physically impossible for you to ohm out every wire connection to make sure each and every wire goes to where it is supposed to go and does not go to where its not supposed to go?

After I solder the entire project together, I ohm out each connection to make sure it goes to where it is supposed to go and to make sure the connection is not shorted to ground or V+.

If no matter what you do the A0 reads 5V then the A0 is connected to V+ or the bottom of the resistor divider is not connected to ground. That is until you've proven it otherwise.

No, only if voltage divider is connected to analog pin A3 it shows 5V, no matter which voltage comes from voltage divider it always shows 5V. If I remove the wire from analog pin A3 it shows 0V. And I tried connecting voltage divider to other analog pins and it is same story. While on the other hand analog pins A0 and A1 measure voltage from wind direction and wind speed sensor perfectly fine. This is just mind blowing.