Problem with reading a serial sensor, while using RTC on a data logger shield

Hi all,

I am trying to read turbidity measurements from a serial sensor with inverted polarity (Seapoint Turbidity Sensor, STM-S) on an Arduino UNO with a data logger shield (Adafruit) attached. The data logger shield has a 1307 RTC and a micro SD reader. The sensor is connected to digital pin 3 and 4, and the code that I am using is as follows:

#include <RTClib.h>
#include <SoftwareSerial.h> // for the Turbidity (STM-S) sensor
#define TIME_ADJUSTMENT  0 // Adjusting the time on RTC
#define WAIT_TO_START    1 // Wait for serial input in setup()
char Turb = '0';

RTC_DS1307 RTC; // the Real Time Clock object

// Defining the pins for Turbidity sensor for inverted poarity serial reading
SoftwareSerial TurbiditySer(3, 4, true);

void setup()
{
  //initializing the Turbidity (STM-S) sensor
  Serial.begin(115200);
  TurbiditySer.begin(115200);
  delay(500);

#if WAIT_TO_START
  Serial.println("Type any character to start");
  while (!Serial.available());
#endif //WAIT_TO_START

  if (!RTC.begin()) {
    Serial.println("RTC failed");
  }
#if TIME_ADJUSTMENT
  // following line sets the RTC to the date & time this sketch was compiled
  Serial.println("Time adjusted!!");
  RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
#endif

  Serial.println("DateTime, Turbidity(NTU)");
}

void loggingTime() {
  DateTime now = RTC.now();
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(' ');
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.print(",");
  delay(2000);
}

void loop()
{
  loggingTime();
  if (TurbiditySer.available()) {
    Turb = TurbiditySer.read();
    Serial.println(Turb);
  }
}

Here is a sample of the output that I am getting:

Type any character to start
DateTime, Turbidity(NTU)
2003/19/1 1:21:48,3
2019/1/15 21:48:2,5
2019/1/15 21:48:4,.
2019/1/15 21:48:6,7
2019/1/15 21:48:8,9
2019/1/15 21:48:10,6
2019/1/15 21:48:12,,
2019/1/15 21:48:14,8
2019/1/15 21:48:16,8
2019/1/15 21:48:18,6
2019/1/15 21:48:20,7
2019/1/15 21:48:22,

However, with the same assembly without any changes, if I upload the following code I can get correct pair of reading from the sensor:

#include <SoftwareSerial.h>

SoftwareSerial mySer(3, 4, true);

char inData = '0';

void setup(){
     Serial.begin(115200); 
      mySer.begin(115200);
      delay(500);
}

void loop(){
    if(mySer.available()){
     inData = mySer.read(); 
     Serial.print(inData);
  }
}

which looks like:

35.958,8866.4
35.909,8865.2
35.992,8867.1
35.852,8868.5
35.927,8864.5
35.920,8865.4

Could you please help me figuring out why I can't get correct readings from the sensor?

The problem is that you only read and print a single character of the turbidity reading on each loop. That worked fine in first program since you weren't printing anything else but not in the second program. You need to read and print the entire turbidity reading before calling loggingTime(). There will be a newline character ('\n') at the end of the data received from the turbidity sensor so you can simply wait until you read that character before calling loggingTime().

Thank you very much! That pretty much solved the issue, but now I am running into another problem. The sensor is just responding every few times, and rest of the time I cannot read from the sensor. I should mention that the sensor can work in two different mode, the default mode (That I am using here) is autostreaming which is set to 0.1 sec intervals. Here is my modified version of my code:

#include <RTClib.h>
#include <SoftwareSerial.h> // for the Turbidity (STM-S) sensor
#define TIME_ADJUSTMENT  0 // Adjusting the time on RTC
#define WAIT_TO_START    1 // Wait for serial input in setup()
const byte numChars = 32;
char Turb [numChars];
boolean newData = false;

RTC_DS1307 RTC; // the Real Time Clock object

// Defining the pins for Turbidity sensor for inverted poarity serial reading
SoftwareSerial TurbiditySer(3, 4, true);

void setup()
{
  //initializing the Turbidity (STM-S) sensor
  Serial.begin(115200);
  TurbiditySer.begin(115200);
  delay(500);

#if WAIT_TO_START
  Serial.println("Type any character to start");
  while (!Serial.available());
#endif //WAIT_TO_START

  if (!RTC.begin()) {
    Serial.println("RTC failed");
  }
#if TIME_ADJUSTMENT
  // following line sets the RTC to the date & time this sketch was compiled
  Serial.println("Time adjusted!!");
  RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
#endif

  Serial.println("DateTime, Turbidity(NTU)");
}

void loggingTime() {
  DateTime now = RTC.now();
  Serial.print(now.year(), DEC);
  Serial.print('/');
  Serial.print(now.month(), DEC);
  Serial.print('/');
  Serial.print(now.day(), DEC);
  Serial.print(' ');
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.print(",");
}

void loop()
{

  static byte ndx = 0;
  char endMarker = '\n';
  char rc;

  while (TurbiditySer.available() > 0 && newData == false) {
    rc = TurbiditySer.read();

    if (rc != endMarker) {
      Turb[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      Turb[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }

  }
  if (newData == true) {
    loggingTime();
    Serial.println(Turb);
    newData = false;
  }
  delay(1000);
}

and here is a sample of the output that I am getting:

Type any character to start
DateTime, Turbidity(NTU)
2019/1/16 11:50:22,25.219,4741.9

2019/1/16 11:50:24,
2019/1/16 11:50:26,
2019/1/16 11:50:28,
2019/1/16 11:50:30,23.953,4310.0

2019/1/16 11:50:32,24.012,4309.1

2019/1/16 11:50:34,
2019/1/16 11:50:36,
2019/1/16 11:50:38,
2019/1/16 11:50:40,23.950,4307.5

2019/1/16 11:50:42,23.949,4309.9

2019/1/16 11:50:44,
2019/1/16 11:50:46,
2019/1/16 11:50:48,
2019/1/16 11:50:50,23.932,4310.6

2019/1/16 11:50:52,24.009,4307.5

2019/1/16 11:50:54,
2019/1/16 11:50:56,

Instead of getting an automatic stream of data, I can also ask sensor to report a single pair of measurement with sending 'r' to the sensor over serial. I can do this when I am connecting the sensor directly to a PC, using a FTDI USB-RS232 cable, but I don't know how can I implement it in my code on Arduino. Here is my best shot though:

#include <SoftwareSerial.h>

SoftwareSerial TurbiditySer(3, 4, true);

const byte numChars = 32;
char Turb [numChars];
boolean newData = false;

void setup(){
     Serial.begin(115200); 
      TurbiditySer.begin(115200);
      delay(500);
}

void loop(){

static byte ndx = 0;
  char endMarker = '\n';
  char rc;
   TurbiditySer.println('r');
  while (TurbiditySer.available() > 0 && newData == false) {
    rc = TurbiditySer.read();

    if (rc != endMarker) {
      Turb[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
      Turb[ndx] = '\0'; // terminate the string
      ndx = 0;
      newData = true;
    }

  }
  if (newData == true) {
    Serial.println(Turb);
    newData = false;
  }
  
  delay(500);
}

but I am getting almost the same result:

24.307,4497.9




25.111,4719.3

24.336,4495.8




24.275,4490.6

24.278,4491.6




24.394,4489.9

24.289,4484.4




24.302,4483.0

24.344,4485.7

Any idea on how to fix either of these? For me there is no preference in the way that sensor is talking, the only point is that I want to decide when to capture a reading on Arduino.

Raincast:
Here is my modified version of my code:

Nice work!

Raincast:
and here is a sample of the output that I am getting:

These timestamps without turbidity readings are strange. I guess the sensor is outputting some extra newlines. It's easy enough to add some additional logic to your code to suppress these.

Raincast:
don't know how can I implement it in my code on Arduino. Here is my best shot though:

My concern with that code is that there is such a short interval between you sending the 'r' and checking whether data is available from the sensor, that the sensor may not have had the chance to send any data yet. This means you will have to wait out the 500 ms delay before checking for data again, but the sensor may not require that long of a delay.

I'm hampered by not having any familiarity with the sensor you're using. I did look at the information on the Seapoint website, but those sensors only have an analog output so it seems your unit has an extra serial interface.

Thanks for you help!

Whatever I did, I couldn't get rid of those empty lines. I tried checking the first character before printing, or checking the length of it, or even existence of certain character ( ',' ) in it, but none of them could completely solve the issue. They just reduced the number of the false readings.

Before checking whether a combination of these logic could help me, I realized that I cannot ignore any readings from the sensor and I am going to need correct measurements at a certain interval. What surprises me is that with the first simple code (the one without RTC) I can easily read all the measurements, but as soon as I try to add things to the program I am getting false readings.

I am wondering if the time of serial read from the sensor should be synced with its inherent measurement intervals?

I am really confused! Any thought is much appreciated!

pert:
I'm hampered by not having any familiarity with the sensor you're using. I did look at the information on the Seapoint website, but those sensors only have an analog output so it seems your unit has an extra serial interface.

By the way, the datasheet of this specific sensor is attached.

STM-S data sheet v3.pdf (195 KB)

When dealing with strange serial data like this, it can be helpful to print some debug output with the ASCII values of the incoming data, rather than the character equivalent (which may be non-printing). Serial.print() and Serial.println() automatically display the char data type as characters. If you want to see the ASCII code for the incoming data, you can cast to the byte type

Serial.println((byte)rc);

You can then refer to an ASCII table (the above code gives you decimal values):

The ASCII code for newline is 10.