analogRead values way way off ...has me stumped. SOLVED, but cause unknown

I am revamping my Arduino Nano based voltmeter project by using a Arduino Nano 33 IOT.

I am aware the 33 IOT takes max 3.3 volts on the analog and digital inputs. However, I'm stranded right at the start of the project, because i can't get the A4 pin reading anywhere near zero volts, unless i short it to ground. I can't make it produce any meaningfull measures above 0V either.

Schematics:

  • Arduino Nano 33 IOT powered via USB from pc
  • A4 connected to the middle of a voltage divider: 12K to GND, 56K to the to be measured load.
  • nothing else connected!

In this schematic, voltage at A4 is already 2.11 volts (analogRead giving me numbers around 650, i.e. already half past the 0 - 3.3 V range the pin can take. The only way i can lower this number is by using a smaller resistor to ground, but 1K still gives me readings of around 150. And, a voltage divider should always be constructed of relative high resistors.

If i apply voltage to the voltage divider, the excess voltage above this 'rest' voltage isn't measured properly either. A4 (and A0 and A1 i tried) don't behave anywhere near i am expecting. Does anyone have a clue?

my full code (work in progress)

#include <OneWire.h>
#include <string.h>
#include <DallasTemperature.h>
//#include <SoftwareSerial.h>
#include <SPI.h>
//#include <MemoryFree.h>
#include <ArduinoHttpClient.h>
#include <WiFiNINA.h>
#define ONE_WIRE_BUS 5
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

#define DEBUG 1
#if DEBUG == 1
#define debug(x) Serial.print(x)
#define debugln(x) Serial.println(x)
#else
#define debug(x)
#define debugln(x)
#endif

char ssid[] = "PP1";                // your network SSID (name)
char pass[] = "******";                // your network password (use for WPA, or use as key for WEP)
int status = WL_IDLE_STATUS;             // the Wi-Fi radio's status
int ledState = LOW;                       //ledState used to set the LED
unsigned long previousMillisInfo = 0;     //will store last time Wi-Fi information was updated
unsigned long previousMillisLED = 0;      // will store the last time LED was updated
const int intervalInfo = 5000;            // interval at which to update the board information

// Name of the server we want to connect to
const char kHostname[] = "*********";
int kPort = 8195;
const char kPath[] = "/json.htm?type=command&param=getversion";
String serverName = "http://**********";

// Number of milliseconds to wait without receiving any data before we give up
const int kNetworkTimeout = 30 * 1000;
// Number of milliseconds to wait if no data is available before trying again
const int kNetworkDelay = 1000;

WiFiClient c;
HttpClient http(c, kHostname, kPort);

/****************************************************
  Declare pins & variables
 ****************************************************/

int batMonPin = A4;           // input pin for the voltage divider

int ampMonPin = A3;           // input pin for the amperemeter
//int refMonPin = A6;           // input pin for ref voltage 4.2 volt
float batteryVoltage = 0.00;
float ampoffset = 0.00;
float voltoffset = 0.1;
float accucapaciteit = 100;
float accuniveau = 100;
float amps = 0.00;
float batteryValues = 1;
float ampValues = 0;
//float refValues = 0;
float tempC1 = 20.0;
float tempC1min = 100.0;
float tempC1max = -100.0;
float tempC2 = 0.0;
float tempC2min = 100.0;
float tempC2max = -100.0;
float mem = 0;
float uptime = 0;

unsigned long Time1 = millis();
unsigned long Time2 = millis();




/****************************************************
  Function reset
 ****************************************************/
void(* resetFunc) (void) = 0;

/****************************************************/



/********************************************************************************************************************************************************
  Setup    put your setup code here, to run once:
 *******************************************************************************************************************************************************/
void setup() {
  Serial.begin(9600);  // for serial monitor
  
  while (!Serial);
  debugln("Powermonitor starting");
  // Start up the DallasLibrary:
  sensors.begin();

  // attempt to connect to Wi-Fi network:
  while (status != WL_CONNECTED) {
    debug("Attempting to connect to network: ");
    debugln(ssid);
    // Connect to WPA/WPA2 network:
    status = WiFi.begin(ssid, pass);

    // wait 10 seconds for connection:
    delay(10000);
  }

  // you're connected now, so print out the data:
  debugln("You're connected to the network");
  debugln("---------------------------------------");

  debugln(F("Einde setup"));
} // end setup


/********************************************************************************************************************************************************
  Loop     put your main code here, to run repeatedly:
 *******************************************************************************************************************************************************/
void loop() {


  /*** Section 1. Get the Values***********************************************************************************************************************************/
  sensors.requestTemperatures();
  tempC1 = sensors.getTempCByIndex(0) + 0.2; // the index 0 refers to the first device
  tempC2 = sensors.getTempCByIndex(1); // the index 1 refers to the second device


  // read analog power values
  batteryValues = 1;
  ampValues = 0;
  //  refValues = 0;
  for (int x = 0; x < 20; x++)                 // run through loop 20 times
  {
    ampValues += analogRead(ampMonPin); //       // add samples together
    delay(10);
    batteryValues += analogRead(batMonPin);        // add samples together
    delay (10);                                    // let ADC settle before next sample
    //    refValues += analogRead(refMonPin);           //refMionPin voltage is measured at 4.42V
    //    delay(10);
  } //end 20 loop

  // convert to milli amps. Sensor puts out 32mV per Ampere. Voltage at sensor at  rest is around 2475 mV
  batteryValues = batteryValues / 20;
  //  refValues = refValues / 20;
  ampValues = ampValues / 20 - 570;
  amps = ampoffset + ampValues * 0.067;  //via afdrukken avgampvalue vastgesteld dat elke 0.066288 A een stap is.
  batteryVoltage = voltoffset + batteryValues * 3.3 / 1024 * 5.643;
  Time2 = millis();
  if (Time2 > Time1) accuniveau = accuniveau + ((amps * (Time2 - Time1)) / 3600000 *  (100 / accucapaciteit) ) ;
  Time1 = Time2;
  if (accuniveau > 100) accuniveau = 100;
  if (accuniveau <= 0) accuniveau = 0;

  uptime = (Time2 / 3600000);
  // mem = freeMemory();

  debug("batteryValues:");
  debugln(batteryValues);
  debug("batteryVoltage:");
  debugln(batteryVoltage);
  debug("ampValues:");
  debugln(ampValues);
  debug("amps:");
  debugln(amps);
  debug("accuniveau:");
  debugln(accuniveau);
  //  debug("Free memory");
  //  debugln(mem);
  debug("Uptime");
  debugln(uptime);

  //  if (mem < 250) {
  //    debugln("Calling resetFunc");
  //    delay(1000);
  //   resetFunc();
  //  }


  debugln("Board Information:");
  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  debug("IP Address: ");
  debugln(ip);

  // print your network's SSID:
  debugln();
  debugln("Network Information:");
  debug("SSID: ");
  debugln(WiFi.SSID());

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  debug("signal strength (RSSI):");
  debugln(rssi);
  debugln("---------------------------------------");


  int err = 0;
  const char kPath[] = "/json.htm?type=command&param=updateuservariable&vname=Powermonitor&vtype=2&vvalue=";
  char kPath_string[100];
  char semicolon[2] =";";
  strcpy(kPath_string,kPath);
 char buffer[15];
int ret = snprintf(buffer, sizeof buffer, "%.2f", batteryVoltage);
strcat(kPath_string, buffer);


  strcat(kPath_string,semicolon);
 
Serial.println(kPath_string);
  err = http.get(kPath_string);
  if (err == 0)
  {
    Serial.println("startedRequest ok");

    err = http.responseStatusCode();
    if (err >= 0)
    {
      Serial.print("Got status code: ");
      Serial.println(err);

      // Usually you'd check that the response code is 200 or a
      // similar "success" code (200-299) before carrying on,
      // but we'll print out whatever response we get

      // If you are interesting in the response headers, you
      // can read them here:
      //while(http.headerAvailable())
      //{
      //  String headerName = http.readHeaderName();
      //  String headerValue = http.readHeaderValue();
      //}

      int bodyLen = http.contentLength();
      Serial.print("Content length is: ");
      Serial.println(bodyLen);
      Serial.println();
      Serial.println("Body returned follows:");

      // Now we've got to the body, so we can print it out
      unsigned long timeoutStart = millis();
      char c;
      // Whilst we haven't timed out & haven't reached the end of the body
      while ( (http.connected() || http.available()) &&
              (!http.endOfBodyReached()) &&
              ((millis() - timeoutStart) < kNetworkTimeout) )
      {
        if (http.available())
        {
          c = http.read();
          // Print out this character
          Serial.print(c);

          // We read something, reset the timeout counter
          timeoutStart = millis();
        }
        else
        {
          // We haven't got any data, so let's pause to allow some to
          // arrive
          delay(kNetworkDelay);
        }
      }
    }
    else
    {
      Serial.print("Getting response failed: ");
      Serial.println(err);
    }
  }
  else
  {
    Serial.print("Connect failed: ");
    Serial.println(err);
  }



  delay(5000);

} // end main loop

How about your code?
Do you have a pinMode call in the setup that defines A4 as some mode?
If so remove it as it sounds like you have enabled the internal pull up resistor by mistake.

Edit
So you posted your code while I was composing my answer. There is a whole lot of code in there that suggests that your hardware was not as described. But might have been at some stage wired up differently.

You talk, in your comments, of a potential divider on pin A4. Does that mean you at one time fitted one. It is possible if you got that wrong that you burned out that pin.

Write a simple code that just tests what you say you have connected.

Absolute not, you have that wrong. It depends on what you are driving the voltage divider into. As a rough rule of thumb there should always be ten time the amount of current down a voltage divider chain as you tap off from the lower leg.

The reason my exisiting code contains way more than needed for a voltage meter is because i'm converting my project from a regular arduino nano to a 3.3IOT.

But, i found this post Strange AnalogRead Behaviour - #2 by DrDiettrich , and rewired my voltage divider to A0, and A0 is behaving as expected (analogRead values of 0-2 when nothing connected, rising to levels as expected, resulting in voltagereadings by applying the formula analogReads/1024 *3.3 *5.643 which only need minor tuning. So happy for now, indeed maybe i fried A4

Edit: A3 used in my code showed the same odd behaviour, switching that to A1 and grounding that pin with a large resistor (56K) to GND solved that too. If anyone has an explanation why A0 and A1 behave expectedly, and A3 and A4 not, i'd be glad to hear.

You fried A3 and A4 in your previous experiments?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.