[SOLVED] Inconsistent values returned by analogRead() on Photon

Getting really inconsistent values reading a light sensor connected to analogue pin.

Hardware:
Photon with an ALS-PT19 light sensor connected to the 3.3v and A0 (attached photo).

Software:
Photon with INO sketch (full code below).
Basically every second, sample the value of A0 twice and log it.
Every 5 seconds, alternate the light source on/off.

Problem:
Everything will work fine for many minutes, but then without me touching anything the values will start becoming inconsistent. Sometimes the values when the light is on are the same as when it is off, as if it completely stops working. Almost always the values sampled a/b are different, but mostly they are vastly different (see attached sample of data logged with the inconsistencies highlighted). I would expect small-medium variations between the 2 sampled values, but nothing as erratic as this. Have checked for loose cables etc and tried powering off 5v and 3.3v with same results. I’ve been reading around about how a fluctuating power source can cause issues with ADC/DAC and this is currently powered off a (good quality) powered USB hub so I can monitor the values in serial monitor. I’m pretty high up on the n00b scale TBH, but are my expectations also too high and this scale of variation is expected?

#include "HttpClient/HttpClient.h"

String codeVersion = "0.1.3";
String deviceName = "NoofnyPhoton2";
String lightIdToControl = "1"; 

uint32_t currentMillis;
uint32_t millisBetweenLoops = 1000;
uint32_t currentLoops = 0;
bool lightSourceIsOn;

int ledPin = D1;
int lightSensorPin = A0;


void setup()
{
  pinMode(ledPin, OUTPUT);

  delay(100);
  Serial.begin(115200);

  logString("*****************************************");
  logString("device_name:" + deviceName);
  logString("device_time:" + Time.timeStr());
  logString("code_version:" + codeVersion);
  logString("*****************************************");
}



void loop()
{

  // non-blocking loop delay
  if (delayLoop()){
    return;
  }


  // alternate the light source on/off every x seconds
  turnLightOnOrOff();


  // read the sensor
  readSensor();

}


bool delayLoop(){
  if (millis() - currentMillis < millisBetweenLoops) {
    return true;
  }
  currentMillis = millis();
  currentLoops++;
  return false;
}


void turnLedOnOrOff(){
  if (currentLoops % 5 == 0) {

    if (lightSourceIsOn) {
      lightSourceIsOn = false;
      digitalWrite(ledPin, LOW);
      logString("LED OFF");
    }
    else {
      lightSourceIsOn = true;
      digitalWrite(ledPin, HIGH);
      logString("LED ON");
    }
  }
}

// turning a light on/off via my Philips Hue hub API
void turnLightOnOrOff(){
  if (currentLoops % 5 == 0) {

    http_request_t request;
    http_response_t response;
    http_header_t headers[] = {
        { "Content-Type", "application/json" },
        { "Accept" , "*/*"},
        { NULL, NULL } // NOTE: Always terminate headers will NULL
    };
    HttpClient http;
    request.ip = { [my-ip-address] };
    request.port = 80;
    request.path = "/api/[my-api-key]/lights/" + lightIdToControl + "/state";

    if (lightSourceIsOn) {
      lightSourceIsOn = false;
      request.body = "{\"on\": false }";
      http.put(request, response, headers);
      logString("LIGHT OFF");
    }
    else {
      lightSourceIsOn = true;
      request.body = "{\"on\": true }";
      http.put(request, response, headers);
      logString("LIGHT ON");
    }
  }
}


void readSensor(){
  int value_a = analogRead(lightSensorPin);
  int value_b = analogRead(lightSensorPin);
  String logValue =  "a:" + String(value_a) + " b:" + String(value_b);
  logString(logValue);
}


void logString(String value) {
  value = String(currentMillis) + "ms > " + value;
  Serial.println(value);
  Particle.publish("photon/logString", value);
}

I unplugged it from USB and connected a 4-pack of AA batteries in series (brand new fully charged measured at ~5.9v) as the power source. Seemed to work perfectly for a minute, a/b values were even almost identical, but then started getting even more erratic values after that (see attached). It’s looking like a user code problem to me…

Further monitoring the pattern of behaviour goes like this;

  • Power device on

  • Values are as expected, even a/b values are very similar

  • After ~1minute the device goes offline/online (sorry to cross-post)

  • Values are erratic and unreliable entirely, device continues to go offline/online every minute.

You could try to read the light sensors less frequently than every 1 second.

You could also take a few samples and average them to get a more consistent reading. Like take 5 quick readings and then total all 5 readings and divide by 5 to get an average number which may help if all readings are mainly good

Your using cheap light sensors, I have tried those and more expensive versions and the more expensive versions do work better and provide more stable readings.

1 Like

I’m not seeing anything obvious in your code that would cause this. You might try commenting out all the http sending code to see if that makes a difference.

1 Like

Thanks guys. Well well well, with your help I am getting somewhere!

I changed the loop to run every 5 seconds instead of 1 second. Also too your averaging idea and now grab the average of 10 samples. Have been running it now for ~10 mins and not only are the values more stable, but the board is not going offline/online every minute.

Must be a case of too much happening too quickly (especially heavy lifting such as the http requests).

Really appreciate your time to help out :smile:

Would a better light sensor be considered something such as this?

The reason for your cloud disconnects might be due to running out of free sockets when HTTPClient doesn’t return unused sockets fast enough.

For your use case I’d only have one global HTTPClient object and reuse the same object over and over instead of repeatedly constructing/destroying new objects which will in turn acquire a new socket each time, eventually leaving no free ones for other tasks.

2 Likes

Glad it’s working better now.

This is a cheaper light sensor with i2c data communication which will probably eliminate the need to average our your readings as you have to with the Analog sensor.

1 Like