Reading sensors in a loop

Hi,
I want to ream my analog tds sensor every 20ms or some known inverval without using delay since other sections of code will get affected if I do so. I was thinking to use blink without delay concept but I’m failing here as this part involves sampling of data.

With the current version of code, while taking input like this, there are large differences in data acquired. I was thinking of taking input in some regular interval. How should I modify the input taking loop? Comments are given in the code for better understanding.

int readtds( void)
{
  float avg =0;
  int i;
  float x[50];
  unsigned long time1 = millis();
  unsigned long time2 = millis();
  
  for (int i=0;i<50; i++)                //this will take 50 inputs, we have to modify this loop somehow.
    {
      x[i]= analogRead(TdsSensorPin);
    }
  
  for(i=0;i<50;i++)          //this will sort the 50 inputs in ascending order
  {
    for (int j=i; j<50; j++)
    {
      if (x[i]>arr[j])
      {
        float temp = arr[i];
        x[i] = arr[j];
        x[j] = temp;
      }
    }
  }

  for(int i=10; i<40; i++)        //this will give average of mid 30 values 
      avg +=arr[i];
  avg /=30;

  float avg_reading = avg;          //calculation part, this is required only after above porcesses are completed.
  float voltage=(avg_reading)*5.0/1024.0;
  int tdsval=((133.42*voltage*voltage*voltage)-(255.86*voltage*voltage)+(857.39*voltage))*0.5;
  
return tdsval;
}

unsigned long qaz = millis();
int myMillisTIme = 20;
in loop()

if millis()-qaz > or equal to myMillisTime then do the thing
readtds;

I would go for a small finite statemachine as shown below

enum TDS_READSTATES
{
  READING,
  PROCESSING
};

/*
  take 50 samples at 20 ms interval
  Out:
    tdsval
  Returns:
    false if sampling in progress, true if process completed and tdsval is valid
 */
bool readtds(int &tdsval)
{
  static TDS_READSTATES readState = READING;
  static int count;
  static uint32_t lastReadTime;
  static float x[50];

  switch (readState)
  {
    case READING:
      if (count == 50)
      {
        readState = PROCESSING;
      }
      else
      {
        if (millis() - lastReadTime >= 20)
        {
          lastreadTime = millis();
          x[count++] = analogRead(TdsSensorPin);
        }
      }
      break;
    case PROCESSING:
      // sort the array
      ...
      ...
      // calculate average
      ...
      ...
      // clean up
      count = 0;
      readState = READING;
      // indicate that reading is complete and tdsval is valid
      break;
  }

  // indicate that reading is in progress
  return false;
}

Call it as often as you can. In loop(), you can test the return value; if it’s true, you can use tdsval.

Not compiled nor tested.

// Edit
All additional variables are decared static so they will be remembered.
Note that this costs you 50 floats extra as x needs to be static to be remembered.

// Edit2
Just realise that x does not need to be a float as analogRead() returns an int. So it only will cost you 50 integers extra.

1 Like

Thnxx, I worked out myself with similar concept if-else ladder. I haven't tried your solution but I'm pretty sure the concept is absolutely right. Thnxx again.

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