Blynk ORP Sensor with NodeMCU & Ads1115 (water sensor)

Hi all, I was wondering if anyone can shed any light on this issue, I don’t think its too big maybe a few lines of code that perhaps need changing but not I’m too sure… I have looked through other topics on the forum as well as online but couldn’t work out how to fix it, I believe it could be a timer issue, I’ve been stuck on this one for a while…

The Project
Eventually, I am looking to make a water sensor that, will tell me the PH, ORP, temperature and turbidity of a water sample, hence the other lines of code, however at this moment in time I’m only testing the ORP section of the code.

The Issue
I have data posting to the mobile application, however, it is not responding/ updating, as it should be, i need it to be updated once every 5 seconds or 1 second if possible, but it just stays on a single value.

Im only looking for help or guidance, as im trying to learn too, thanks :slight_smile:

Setup

• Hardware model: NodeMCU/ Esp8266 board
• Smartphone OS: Android
• Server: Blynk server

#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <SimpleTimer.h> //Blynk
#include <Wire.h>
#include <Adafruit_ADS1015.h>

#define VOLTAGE 3.30    //system voltage   **CHANGED FROM 5 TO 3.3** ORP
#define OFFSET 1000        //zero drift voltage


double orpValue;

#define ArrayLenth  40    //times of collection
//#define orpPin 1          //orp meter output,connect to Arduino controller ADC pin

int orpArray[ArrayLenth];
int orpArrayIndex=0;


double avergearray(int* arr, int number){
  int i;
  int max,min;
  double avg;
  long amount=0;
  if(number<=0){
    printf("Error number for the array to avraging!/n");
    return 0;
  }
  if(number<5){   //less than 5, calculated directly statistics
    for(i=0;i<number;i++){
      amount+=arr[i];
    }
    avg = amount/number;
    return avg;
  }else{
    if(arr[0]<arr[1]){
      min = arr[0];max=arr[1];
    }
    else{
      min=arr[1];max=arr[0];
    }
    for(i=2;i<number;i++){
      if(arr[i]<min){
        amount+=min;        //arr<min
        min=arr[i];
      }else {
        if(arr[i]>max){
          amount+=max;    //arr>max
          max=arr[i];
        }else{
          amount+=arr[i]; //min<=arr<=max
        }
      }//if
    }//for
    avg = (double)amount/(number-2);
  }//if
  return avg;
}


char auth[] = "8f41b49eeebf4a19bd4e9012e812d18d";
char ssid[] = "TALKTALKA2FFE5";
char pass[] = "6K6Q66CV";

bool isFirstConnect = true;
SimpleTimer timer;


 Adafruit_ADS1115 ads;  /* Use this for the 16-bit version */
//Adafruit_ADS1015 ads;     /* Use thi for the 12-bit version */
float Voltage0 = 0.0;
float Voltage1 = 0.0;
float Voltage2 = 0.0;
float Voltage3 = 0.0;

void setup() 
{
  Serial.begin(115200);
  Blynk.begin(auth, ssid, pass);
  timer.setInterval(1000L, ReadANAlOGS);// changed from 350

    
  // The ADC input range (or gain) can be changed via the following
  // functions, but be careful never to exceed VDD +0.3V max, or to
  // exceed the upper and lower limits if you adjust the input range!
  // Setting these values incorrectly may destroy your ADC!
  //                                                                ADS1015  ADS1115
  //                                                                -------  -------
  // ads.setGain(GAIN_TWOTHIRDS);  // 2/3x gain +/- 6.144V  1 bit = 3mV      0.1875mV (default)
  ads.setGain(GAIN_ONE);           // 1x gain   +/- 4.096V  1 bit = 2mV      0.125mV
  // ads.setGain(GAIN_TWO);        // 2x gain   +/- 2.048V  1 bit = 1mV      0.0625mV
  // ads.setGain(GAIN_FOUR);       // 4x gain   +/- 1.024V  1 bit = 0.5mV    0.03125mV
  // ads.setGain(GAIN_EIGHT);      // 8x gain   +/- 0.512V  1 bit = 0.25mV   0.015625mV
  // ads.setGain(GAIN_SIXTEEN);    // 16x gain  +/- 0.256V  1 bit = 0.125mV  0.0078125mV
  
  ads.begin();
}

void ReadANAlOGS()
{

  int16_t adc0, adc1, adc2, adc3;

  adc0 = ads.readADC_SingleEnded(0);
  adc1 = ads.readADC_SingleEnded(1);
  adc2 = ads.readADC_SingleEnded(2);
  adc3 = ads.readADC_SingleEnded(3);
  
  Voltage0 = (adc0 * 0.125)/1000;
  Voltage1 = (adc1 * 0.125)/1000; 
  Voltage2 = (adc2 * 0.125)/1000;
  Voltage3 = (adc3 * 0.125)/1000;


 static unsigned long orpTimer=millis();   //analog sampling interval
  static unsigned long printTime=millis();
  if(millis() >= orpTimer)
  {
    orpTimer=millis()+20;
    orpArray[orpArrayIndex++]= Voltage0 ;    //read an analog value every 20ms
    if (orpArrayIndex==ArrayLenth) {
      orpArrayIndex=0;
    }   
    orpValue=((30*(double)VOLTAGE*1000)-(75*avergearray(orpArray, ArrayLenth)*VOLTAGE*1000/1024))/75-OFFSET;   //convert the analog value to orp according the circuit
  }
//if(millis() >= printTime)   //Every 800 milliseconds,

//printTime=millis()+800;

Serial.print("AIN0: "); Serial.println(orpValue);
 Serial.print("AIN1: "); Serial.println(Voltage1);
  Serial.print("AIN2: "); Serial.println(Voltage2);
  Serial.print("AIN3: "); Serial.println(Voltage3);
  Serial.println(" ");

  Serial.print(orpValue);

  Blynk.virtualWrite(V0, orpValue);
  Blynk.virtualWrite(V1, Voltage1);
  Blynk.virtualWrite(V2, Voltage2);
  Blynk.virtualWrite(V3, Voltage3); 


  Blynk.virtualWrite(V4, orpValue);
  Blynk.virtualWrite(V5, Voltage1);
  Blynk.virtualWrite(V6, Voltage2);
  Blynk.virtualWrite(V7, Voltage3);    
}

void loop()
{
    Blynk.run();
  timer.run();
}

I can’t easily troubleshoot others code… but I do suggest you have discrete timers and functions for each sensor… makes it easier to troubleshoot… and possible to even enable/disable individual tests.

You are calling ReadANAlOGS() once per second, right?
If so, then how is this supposed to work? I’m an amateur, but don’t get those timings… (20ms sampling? how?)

static unsigned long orpTimer=millis();   //analog sampling interval
  static unsigned long printTime=millis();
  if(millis() &gt;= orpTimer)
  {
    orpTimer=millis()+20;
    orpArray[orpArrayIndex++]= Voltage0 ;    //read an analog value every 20ms
    if (orpArrayIndex==ArrayLenth) {
      orpArrayIndex=0;
    }   
    orpValue=((30*(double)VOLTAGE*1000)-(75*avergearray(orpArray, ArrayLenth)*VOLTAGE*1000/1024))/75-OFFSET;   //convert the analog value to orp according the circuit
  }

Also, here:

  adc0 = ads.readADC_SingleEnded(0);
  adc1 = ads.readADC_SingleEnded(1);
  adc2 = ads.readADC_SingleEnded(2);
  adc3 = ads.readADC_SingleEnded(3);

I don’t know how library handles conversion time, but it is safe to wait a bit between subsequent readings from the same ADC