Analogread issue with client.stop() instruction

Hello,

I'm trying to read the value from LM35 sensor for temperature calculation and then post the value on a web server.

The temperature calculation on its own works fine, the web server post also. The issue is when I merge both. After debugging I came to this observation:

--> Analogread value becomes inconsistent as soon as a "client.stop()" instruction has been executed.

I'm using a simple Arduino UNO board Rev3 + a wifi shield.

Is it a know issue? Is there any trick?

Thanks,
Matthieu

The first trick is to post your code which you will have read in read this before posting a programming question

Sorry about that. Let me start again:

Issue
Analogread value becomes inconsistent as soon as a "client.stop()" instruction has been executed.

Schematic
LM35 component:

  • Pin 1 (+Vs) connected to 5V of the board
  • Pin 2 (GND) connected to GND of the board
  • Pin 3 (Vout) connected to Analog input A5 of the board
    No resistors or other components, only LM35 + wires.

Details
Arduino UNO Rev3 + Wifi shield R3;
Firmware version of wifi shield updated to 1.1.0;
IDE version: 1.6.5;
Arduino board powered-up with computer USB;

Code

#include <SPI.h>
#include <WiFi.h>

//Connection
char ssid[] = "XXX";
char pass[] = "YYY";
int status = WL_IDLE_STATUS;
unsigned long last_connection_time = 0;
const unsigned long POST_Interval = 10L * 1000L;
float temp;
IPAddress server(...,...,.,..); //local server
WiFiClient client;

void setup() 
{
  Serial.begin(9600);
  while (!Serial) //Wait for port COM3 to connect:
  {
    ;
  }
  if (WiFi.status() == WL_NO_SHIELD) // Check for the presence of the shield
  {
    Serial.println("WiFi shield not present");
    while (true); // don't continue
  }
  String fv = WiFi.firmwareVersion(); // Check firmware version
  if (fv != "1.1.0") 
  {
    Serial.println(fv);
    Serial.println("Please upgrade the firmware");
  }
  while (status != WL_CONNECTED) // WIFI connection
  {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);
    delay(10000); // Wait 10 seconds for connection
  }
  printWifiStatus();
}


void loop() 
{
  while (client.available()) // if there's incoming data from the net connection send it out the serial port (debugging purposes only)
  {
    char c = client.read();
    Serial.write(c);
  }
  if (millis() - last_connection_time > POST_Interval) // if ten seconds have passed since your last connection, then connect again and send data:
  {
    //Serial.print("ANALOGREAD BEFORE POST_DATA  ");
    //Serial.println(analogRead(5));
    temp = analogRead(5) * 0.48828125;
    //Serial.print("TEMP BEFORE POST_DATA  ");
    //Serial.println(temp);
    POST_DATA(temp);
  }
}


void POST_DATA(float data_to_post) 
{
  client.stop(); // close any connection before send a new request, this will free the socket on the WiFi shield
  delay(1000);

  if (client.connect(server, 8080)) 
  {
    Serial.println("connecting...");
    //Serial.println(client.status());
    
    client.println("POST /Api/AddParking/3 HTTP/1.1");
    client.println("Host: 192.168.1.63");
    client.println("User-Agent: Arduino/1.0");
    client.print("Content-Type: Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(sizeof(data_to_post));
    client.println(data_to_post);
    client.println();
    
    last_connection_time = millis(); // Note the time that the connection was made
  } 
  else
  {
    Serial.println("connection failed");
    Serial.println(client.status());
  }
}


void printWifiStatus() 
{
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}

Thanks,
Matthieu

The code to read the temperature seems quite separate from the code that causes the client to stop so I doubt if it is a problem with your code.

You have not told us the range of error that you mean by "inconsistent" and my wild guess is that the WiFi connection is affecting the voltage used by the LM35 .

Make a pencil drawing showing how everything is connected and how everything is powered and post a photo of the drawing. Note that a photo of your hardware will not clearly show the wiring connections.

...R

    client.println(sizeof(data_to_post));
    client.println(data_to_post);

A float is 4 bytes, so sizeof() will always return 4. The string that a float becomes is not necessarily 4 characters. That is NOT the correct way to define the amount of data.

Is there any trick?

To understanding what "Analogread value becomes inconsistent as soon as a "client.stop()" instruction has been executed." means? No. Someone needs to explain that. Guess who that someone is.

Thank you both for your answers and sorry for not being clear enough about my issue.

The wire schematic is this one:

  • USB connection between my computer and the UNO board.

By "Analogread value becomes inconsistent as soon as a "client.stop()" instruction has been executed" I mean that the value returned by Analogread(5); becomes "inconsistent" as soon as a client.stop(); instruction has been executed anywhere in the code. By inconsistent I mean it goes indefinitely between approximately 222 and 229.

  • If I don't execute POST_DATA(); at all the Analogread value is OK.
  • If I execute POST_DATA(); but remove the client.stop(); the Analogread value is OK.
  • If I don't execute POST_DATA(); but insert a dummy client.stop(); into the loop(); after the Analogread then only the first value of Analogread is OK.
  • If I don't execute POST_DATA(); but insert a dummy client.stop(); into the loop(); before the Analogread then all the Analogread values are NOK.

It really seems to be the client.stop(); instruction that triggers the issue.

Below is the code I used for testing:

#include <SPI.h>
#include <WiFi.h>

//Connection
char ssid[] = "XXX";
char pass[] = "YYY";
int status = WL_IDLE_STATUS;
unsigned long Last_Connection_Time = 0;
const unsigned long POST_Interval = 10L * 1000L;
float temp;
IPAddress server(...,...,.,..); //local server
WiFiClient client;

void setup() 
{
  Serial.begin(9600);
  while (!Serial) //Wait for port COM3 to connect:
  {
    ;
  }
  if (WiFi.status() == WL_NO_SHIELD) // Check for the presence of the shield
  {
    Serial.println("WiFi shield not present");
    while (true); // don't continue
  }
  String fv = WiFi.firmwareVersion(); // Check firmware version
  if (fv != "1.1.0") 
  {
    Serial.println(fv);
    Serial.println("Please upgrade the firmware");
  }
  while (status != WL_CONNECTED) // WIFI connection
  {
    Serial.print("Attempting to connect to SSID: ");
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);
    delay(10000); // Wait 10 seconds for connection
  }
  //printWifiStatus();
}


void loop() 
{
  while (client.available()) // if there's incoming data from the net connection send it out the serial port (debugging purposes only)
  {
    char c = client.read();
    Serial.write(c);
  }
  if (millis() - Last_Connection_Time > POST_Interval) // if ten seconds have passed since your last connection, then connect again and send data:
  {
    //client.stop();
    temp = analogRead(5) * 0.48828125;
    Serial.println(analogRead(5));
    //client.stop();
    POST_DATA(temp);
  }
}


void POST_DATA(float data_to_post) 
{
  client.stop(); // close any connection before send a new request, this will free the socket on the WiFi shield
  delay(1000);

  if (client.connect(server, 8080)) 
  {
    Serial.println("connecting...");
    //Serial.println(client.status());
    
    client.println("POST /Api/AddParking/3 HTTP/1.1");
    client.println("Host: 192.168.1.63");
    client.println("User-Agent: Arduino/1.0");
    client.print("Content-Type: Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(6);
    client.println();
    client.println(data_to_post);
    client.println();
    
    Last_Connection_Time = millis(); // Note the time that the connection was made
  } 
  else
  {
    Serial.println("connection failed");
    Serial.println(client.status());
  }
}

/*
void printWifiStatus() 
{
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());
  IPAddress ip = WiFi.localIP();
  Serial.print("IP Address: ");
  Serial.println(ip);
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}
*/

Thank you in advance for your answers and your time,
Matthieu

Lazy41:
By inconsistent I mean it goes indefinitely between approximately 222 and 229.

That is only a variation of 3%. Would it be sufficient to average the readings ?

...R

Thanks for your answer. No the variation is not the issue, the value is.

  • If I don't execute POST_DATA(); at all the Analogread value is OK.
  • If I execute POST_DATA(); but remove the client.stop(); the Analogread value is OK.
  • If I don't execute POST_DATA(); but insert a dummy client.stop(); into the loop(); after the Analogread then only the first value of Analogread is OK.
  • If I don't execute POST_DATA(); but insert a dummy client.stop(); into the loop(); before the Analogread then all the Analogread values are NOK.

Value is OK means Analogread ~= 49 (at 23°C).
Value is NOK means Analogread ~=222-229.

This is looking more and more like a hardware issue. Like the WIFI board is pulling too much power or something and when you stop it is letting the voltage come back up and that is affecting your analog reference.

I don't see any capacitors in the circuit. You should have several. On the arduino power rail, on the WIFI power rail, on the sensor power rail, and maybe a small one (0.01) on the analog input pin.

"Analogread value becomes inconsistent as soon as a "client.stop()" instruction has been executed.". Is this just for a couple milliseconds, or does it continue for ever. If it is just for a couple milliseconds, then you can delay taking any readings for that period of time.

You need proper decoupling on the sensor itself too, as you are next to a relatively
powerful RF signal from the WiFi board. Suggest 100nF ceramic directly across the sensor's
supply/ground right at the chip, and at least 1nF on A5 to ground right at the Arduino.

What happens with no RF protection like this is that flying leads pick up RF and this gets rectified by
any semiconductors pretty much, pushing a DC offset onto sensitive analog signals.

You'll likely find your circuit is sensitive to a nearby active mobile phone for the same reason.

Lazy41:
Thanks for your answer. No the variation is not the issue, the value is.

Value is OK means Analogread ~= 49 (at 23°C).
Value is NOK means Analogread ~=222-229.

I had a suspicion that that was the problem - but you had not told us.

If you want useful suggestions you need to give us all the information.

...R

Ok thank you all for your answers!

I will try the decoupling and let you know.

Hello,

MarkT I tried decoupling with your values, and I also tried this one from LM35 datasheet:

Decoupling schematic

Analogread results are approximately the same with or without the decoupling capacitors/resistors. Small differences but the problem remains:

When value is OK (no client.stop() instruction) Analogread ~= 49/50 (at 23°C).
When value is NOK (client.stop() instruction somewhere) Analogread ~=220-230 (at 23°C still).

When searching on the net I found one similar issue (posted on this forum on another section): WiFi Shield + Potentiometer problem - Networking, Protocols, and Devices - Arduino Forum

I don't really know what to do next :slight_smile:

This is looking more and more like a hardware issue. Like the WIFI board is pulling too much power or something and when you stop it is letting the voltage come back up and that is affecting your analog reference.

I'm starting to doubt about the Wifi board pulling too much because the problem remains even with the code below, where I don't start any connection using the wifi shield:

#include <SPI.h>
#include <WiFi.h>

float temp=0;
WiFiClient client;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  client.stop();
  temp = analogRead(5) * 0.48828125;
  Serial.println(temp);
  Serial.println();
  delay(2000);
}

What do you think?

Thanks,
Matthieu

Have you read the voltages on the rails. Do they change, or remain consistent?
If the Wifi board is pulling to much power from the arduino power rail, then you may need to provide an external power supply just for the Wifi board.

For some inexplicable reason, calling client.stop() from the WiFi library changes the reference voltage of the UNO's ATmega microcontroller.

A work-around is adding the line analogReference(DEFAULT); after each call to client.stop(). analogRead() results will then be as expected.

I wonder if your work-around is just allowing time for the reference voltage to stabilize after being disturbed?

...R